Files
WP-LIT-MCP/src/Integrations/Divi/Release/FeatureSets.php
T
Jan-Niclas LoosenandClaude Opus 5.5 c85131603b feat(compat): Profile, Gates und Pods über den Kompatibilitätskern
Neu: Tier, Profile, Compatibility, CapabilityLocked, CapabilityGate, CompatibilityComponent, ProvidesCompatibility, DiviProfile sowie PodsFeature, PodsCompatibility und PodsIntegration. Das CapabilityGate sperrt gesperrte und unbekannte Fähigkeits-IDs (übernimmt die Sperre unbekannter IDs vom DiviFeatureGate) und delegiert nur Divi ausdrücklich. Pods-Schema, -Lesen, -Schreiben und -Feldrechte laufen über usable(PodsFeature::…); Schreiben verlangt FieldRead und FieldWrite, damit ein Rollback keine Werte verliert. lit-site-status meldet Pods über die CompatibilityComponent.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-06 12:26:54 +01:00

101 lines
3.4 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<?php
declare(strict_types=1);
namespace LIT\MCP\Integrations\Divi\Release;
use LIT\MCP\Abilities\Ability;
use LIT\MCP\Abilities\DeclaresRequirements;
use LIT\MCP\Integrations\Divi\Library\DiviLibraryStore;
use LIT\MCP\Integrations\Divi\ThemeBuilder\DiviThemeBuilder;
use LIT\MCP\Integrations\WordPress\PostGuard;
defined('ABSPATH') || exit;
/** Helpers of RequiresDiviFeatures::diviFeatures(): joining lists and the capabilities an entry adds. */
final class FeatureSets
{
/**
* The capabilities $ability declares for $input: its own diviFeatures() (the Divi tools) or the IDs a core tool
* names through DeclaresRequirements (lit/content-create with divi). Anything else declares none; an ID that is no
* DiviFeature is ignored (CapabilityGate checks the IDs of other integrations and locks unknown ones).
*
* @param array<string, mixed> $input
* @return list<DiviFeature>
*/
public static function declaredBy(Ability $ability, array $input): array
{
if ($ability instanceof RequiresDiviFeatures) {
return self::merge($ability->diviFeatures($input));
}
if (! $ability instanceof DeclaresRequirements) {
return [];
}
$features = [];
foreach ($ability->requirements($input) as $id) {
$feature = DiviFeature::tryFrom($id);
if ($feature !== null) {
$features[] = $feature;
}
}
return self::merge($features);
}
/**
* @param list<DiviFeature> ...$lists
* @return list<DiviFeature> Every capability once, in the order of first appearance.
*/
public static function merge(array ...$lists): array
{
$merged = [];
foreach ($lists as $list) {
foreach ($list as $feature) {
$merged[$feature->value] ??= $feature;
}
}
return array_values($merged);
}
/**
* What the entry $postId adds to a tool that loads it. A page or post adds nothing; a library entry needs the
* Divi roles (LibraryAccess), written also the library check of global entries and the library save scope
* (DiviSaver, D5); a Theme Builder layout needs the roles, written also the template lookup of
* ThemeBuilderEdits and the Theme Builder save scope. An ID that names no entry, or one the caller may not edit,
* adds nothing – the tool answers "not found" or "forbidden" itself, and a lock never tells which kind of entry
* an ID is (ruling P12).
*
* @return list<DiviFeature>
*/
public static function ofEntry(mixed $postId, bool $write): array
{
$id = PostGuard::id($postId);
$type = $id === null ? false : get_post_type($id);
if ($id === null || ! is_string($type)) {
return [];
}
$isLibrary = $type === DiviLibraryStore::POST_TYPE;
if (! $isLibrary && DiviThemeBuilder::areaOf($type) === null) {
return [];
}
if (! current_user_can('edit_post', $id)) {
return [];
}
if ($isLibrary) {
return $write
? [DiviFeature::Roles, DiviFeature::LibraryRead, DiviFeature::LibraryWrite]
: [DiviFeature::Roles];
}
return $write
? [DiviFeature::Roles, DiviFeature::ThemeBuilderRead, DiviFeature::ThemeBuilderWrite]
: [DiviFeature::Roles];
}
}