refactor(compat): Prüfbausteine nach src/Compatibility, Matrix und ManifestCheck generisch
Requirement, Call, ConstantRequirement, Mirror, Problem, FeatureStatus, CompatibilityMatrix, Manifest, ManifestCheck sowie Fingerprints und LineDiff liegen jetzt im divi-freien Kern. Neu: GlobalRequirement, CompatibilityMatrix::fromProblems(), ManifestCheck-Option signatures, DiviManifestCheck::create() und DiviAreas. Divi-Verhalten unverändert. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5.5
parent
9beb55e228
commit
b511ef6348
@@ -0,0 +1,81 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace LIT\MCP\Compatibility;
|
||||||
|
|
||||||
|
use ReflectionFunction;
|
||||||
|
use ReflectionMethod;
|
||||||
|
|
||||||
|
defined('ABSPATH') || exit;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* One function or static method of a third-party plugin or theme that an adapter calls (spec §4.1), with the number
|
||||||
|
* of arguments the plugin passes. $args null: only its existence matters (a function the third-party code itself
|
||||||
|
* needs, e.g. et_() inside store_template in the Divi integration).
|
||||||
|
*/
|
||||||
|
final class Call implements Requirement
|
||||||
|
{
|
||||||
|
/** Key prefix of the signature fingerprints in the reference; no mirror ID starts with it. */
|
||||||
|
public const SIGNATURE_PREFIX = 'sig:';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $symbol "function_name" or "Fully\Qualified\Class::method".
|
||||||
|
* @param list<Capability> $features [] = the default of the manifest.
|
||||||
|
*/
|
||||||
|
public function __construct(
|
||||||
|
public readonly string $symbol,
|
||||||
|
public readonly ?int $args = null,
|
||||||
|
private readonly array $features = []
|
||||||
|
) {
|
||||||
|
}
|
||||||
|
|
||||||
|
public function className(): ?string
|
||||||
|
{
|
||||||
|
return str_contains($this->symbol, '::') ? ltrim(explode('::', $this->symbol, 2)[0], '\\') : null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** The key of this call's signature fingerprint in the reference: "sig:" and the symbol without a leading backslash. */
|
||||||
|
public function signatureKey(): string
|
||||||
|
{
|
||||||
|
return self::SIGNATURE_PREFIX . ltrim($this->symbol, '\\');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function member(): string
|
||||||
|
{
|
||||||
|
return str_contains($this->symbol, '::') ? explode('::', $this->symbol, 2)[1] : $this->symbol;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** The function or method exists and takes the number of arguments the adapter passes. */
|
||||||
|
public function accepts(): bool
|
||||||
|
{
|
||||||
|
$class = $this->className();
|
||||||
|
if ($class === null) {
|
||||||
|
if (! function_exists($this->member())) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
$reflection = new ReflectionFunction($this->member());
|
||||||
|
} else {
|
||||||
|
if (! method_exists($class, $this->member())) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
$reflection = new ReflectionMethod($class, $this->member());
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->args === null
|
||||||
|
|| ($reflection->getNumberOfRequiredParameters() <= $this->args
|
||||||
|
&& ($reflection->isVariadic() || $reflection->getNumberOfParameters() >= $this->args));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function features(): array
|
||||||
|
{
|
||||||
|
return $this->features;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function label(): string
|
||||||
|
{
|
||||||
|
$class = $this->className();
|
||||||
|
|
||||||
|
return ($class === null ? '' : SourceFingerprint::shortName($class) . '::') . $this->member() . '()';
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,230 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace LIT\MCP\Compatibility;
|
||||||
|
|
||||||
|
defined('ABSPATH') || exit;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The release state of every capability of one integration (E1). A capability the constructor did not get a status
|
||||||
|
* for is incompatible (fail closed), so of() always answers. The overall state of the matrix is its worst state.
|
||||||
|
*/
|
||||||
|
final class CompatibilityMatrix
|
||||||
|
{
|
||||||
|
public const MISSING = 'Für diese Fähigkeit liegt kein Prüfergebnis vor.';
|
||||||
|
|
||||||
|
/** Where a release comes from: the plugin's list of tested versions, the site's database, the automatic check. */
|
||||||
|
public const SOURCE_CODE = 'code';
|
||||||
|
public const SOURCE_DATABASE = 'database';
|
||||||
|
public const SOURCE_AUTO = 'auto';
|
||||||
|
|
||||||
|
/** @var array<string, FeatureStatus> keyed by capability ID, in the order of the capabilities */
|
||||||
|
private array $features = [];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param list<Capability> $capabilities
|
||||||
|
* @param array<string, FeatureStatus> $statuses keyed by capability ID
|
||||||
|
*/
|
||||||
|
public function __construct(array $capabilities, array $statuses)
|
||||||
|
{
|
||||||
|
foreach ($capabilities as $capability) {
|
||||||
|
$status = $statuses[$capability->id()] ?? null;
|
||||||
|
$this->features[$capability->id()] = $status instanceof FeatureStatus && $status->feature === $capability
|
||||||
|
? $status
|
||||||
|
: self::missing($capability);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static function missing(Capability $capability): FeatureStatus
|
||||||
|
{
|
||||||
|
return new FeatureStatus($capability, ReleaseState::Incompatible, [self::MISSING]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @param list<Capability> $capabilities */
|
||||||
|
public static function allReleased(array $capabilities, string $source = self::SOURCE_CODE): self
|
||||||
|
{
|
||||||
|
return self::uniform($capabilities, ReleaseState::Released, [], $source);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @param list<Capability> $capabilities */
|
||||||
|
public static function allIncompatible(array $capabilities, string $problem): self
|
||||||
|
{
|
||||||
|
return self::uniform($capabilities, ReleaseState::Incompatible, [$problem]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Every capability in $state – the matrix of a status built without one (ReleaseStatus' constructor).
|
||||||
|
*
|
||||||
|
* @param list<Capability> $capabilities
|
||||||
|
* @param list<string> $problems
|
||||||
|
*/
|
||||||
|
public static function uniform(
|
||||||
|
array $capabilities,
|
||||||
|
ReleaseState $state,
|
||||||
|
array $problems = [],
|
||||||
|
?string $source = null
|
||||||
|
): self {
|
||||||
|
$released = $state === ReleaseState::Released;
|
||||||
|
$statuses = [];
|
||||||
|
foreach ($capabilities as $capability) {
|
||||||
|
$statuses[$capability->id()] = new FeatureStatus(
|
||||||
|
$capability,
|
||||||
|
$state,
|
||||||
|
$released ? [] : $problems,
|
||||||
|
$released ? ($source ?? self::SOURCE_CODE) : null
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return new self($capabilities, $statuses);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The matrix the problems of a check add up to (spec §5.2–§5.4): per capability a hard problem (call, mirror,
|
||||||
|
* constant) makes it incompatible, released version or not; a released version releases every other one; without
|
||||||
|
* release the automatic release decides (changed signature: incompatible, missing reference: untested, no
|
||||||
|
* problem: released from SOURCE_AUTO), else it is untested.
|
||||||
|
*
|
||||||
|
* @param list<Capability> $capabilities
|
||||||
|
* @param list<Problem> $problems
|
||||||
|
* @param string|null $source SOURCE_CODE or SOURCE_DATABASE for a released version, else null.
|
||||||
|
* @param bool $automatic The automatic release applies (no release, known version, filter on).
|
||||||
|
*/
|
||||||
|
public static function fromProblems(array $capabilities, array $problems, ?string $source, bool $automatic): self
|
||||||
|
{
|
||||||
|
$statuses = [];
|
||||||
|
foreach ($capabilities as $capability) {
|
||||||
|
$concerning = array_values(array_filter(
|
||||||
|
$problems,
|
||||||
|
static fn (Problem $problem): bool => $problem->concerns($capability)
|
||||||
|
));
|
||||||
|
$statuses[$capability->id()] = self::statusOf($capability, $concerning, $source, $automatic);
|
||||||
|
}
|
||||||
|
|
||||||
|
return new self($capabilities, $statuses);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @param list<Problem> $problems The problems concerning $capability. */
|
||||||
|
private static function statusOf(
|
||||||
|
Capability $capability,
|
||||||
|
array $problems,
|
||||||
|
?string $source,
|
||||||
|
bool $automatic
|
||||||
|
): FeatureStatus {
|
||||||
|
$hard = array_filter($problems, static fn (Problem $problem): bool => $problem->isHard());
|
||||||
|
if ($hard !== []) {
|
||||||
|
return new FeatureStatus($capability, ReleaseState::Incompatible, self::labels($hard));
|
||||||
|
}
|
||||||
|
if ($source !== null) {
|
||||||
|
return new FeatureStatus($capability, ReleaseState::Released, [], $source);
|
||||||
|
}
|
||||||
|
if (! $automatic) {
|
||||||
|
return new FeatureStatus($capability, ReleaseState::Untested, self::labels($problems));
|
||||||
|
}
|
||||||
|
|
||||||
|
$changed = array_filter($problems, static fn (Problem $problem): bool => $problem->kind === Problem::SIGNATURE);
|
||||||
|
if ($changed !== []) {
|
||||||
|
return new FeatureStatus($capability, ReleaseState::Incompatible, self::labels($changed));
|
||||||
|
}
|
||||||
|
|
||||||
|
return $problems === []
|
||||||
|
? new FeatureStatus($capability, ReleaseState::Released, [], self::SOURCE_AUTO)
|
||||||
|
: new FeatureStatus($capability, ReleaseState::Untested, self::labels($problems));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param array<int, Problem> $problems
|
||||||
|
* @return list<string>
|
||||||
|
*/
|
||||||
|
private static function labels(array $problems): array
|
||||||
|
{
|
||||||
|
return array_values(array_map(static fn (Problem $problem): string => $problem->label, $problems));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function of(Capability $feature): FeatureStatus
|
||||||
|
{
|
||||||
|
return $this->features[$feature->id()] ?? self::missing($feature);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @param list<Capability> $features */
|
||||||
|
public function usable(array $features): bool
|
||||||
|
{
|
||||||
|
foreach ($features as $feature) {
|
||||||
|
if (! $this->of($feature)->usable()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The statuses of those of $features that are not usable – each once, in the order of $features. The one answer
|
||||||
|
* to "what locks this call" for the gates, the adapters and the
|
||||||
|
* refusals.
|
||||||
|
*
|
||||||
|
* @param list<Capability> $features
|
||||||
|
* @return list<FeatureStatus>
|
||||||
|
*/
|
||||||
|
public function locked(array $features): array
|
||||||
|
{
|
||||||
|
$locked = [];
|
||||||
|
foreach ($features as $feature) {
|
||||||
|
$status = $this->of($feature);
|
||||||
|
if (! $status->usable()) {
|
||||||
|
$locked[$feature->id()] = $status;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return array_values($locked);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @return list<FeatureStatus> */
|
||||||
|
public function unusable(): array
|
||||||
|
{
|
||||||
|
return array_values(array_filter(
|
||||||
|
$this->features,
|
||||||
|
static fn (FeatureStatus $status): bool => ! $status->usable()
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Incompatible before untested before released. */
|
||||||
|
public function state(): ReleaseState
|
||||||
|
{
|
||||||
|
$states = array_map(static fn (FeatureStatus $status): ReleaseState => $status->state, $this->features);
|
||||||
|
|
||||||
|
return match (true) {
|
||||||
|
in_array(ReleaseState::Incompatible, $states, true) => ReleaseState::Incompatible,
|
||||||
|
in_array(ReleaseState::Untested, $states, true) => ReleaseState::Untested,
|
||||||
|
default => ReleaseState::Released,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/** The common source of a fully released matrix; null when not all released or the sources differ. */
|
||||||
|
public function source(): ?string
|
||||||
|
{
|
||||||
|
$sources = array_unique(array_map(
|
||||||
|
static fn (FeatureStatus $status): string => (string) $status->source,
|
||||||
|
$this->features
|
||||||
|
));
|
||||||
|
|
||||||
|
return $this->state() === ReleaseState::Released && count($sources) === 1 ? (string) reset($sources) : null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @return list<string> Every problem label once, in feature order. */
|
||||||
|
public function problems(): array
|
||||||
|
{
|
||||||
|
$problems = [];
|
||||||
|
foreach ($this->features as $status) {
|
||||||
|
$problems = array_merge($problems, $status->problems);
|
||||||
|
}
|
||||||
|
|
||||||
|
return array_values(array_unique($problems));
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @return list<array{id: string, label: string, state: string, problems: list<string>, source: ?string}> */
|
||||||
|
public function toArray(): array
|
||||||
|
{
|
||||||
|
return array_values(array_map(static fn (FeatureStatus $status): array => $status->toArray(), $this->features));
|
||||||
|
}
|
||||||
|
}
|
||||||
+3
-3
@@ -2,14 +2,14 @@
|
|||||||
|
|
||||||
declare(strict_types=1);
|
declare(strict_types=1);
|
||||||
|
|
||||||
namespace LIT\MCP\Integrations\Divi\Release;
|
namespace LIT\MCP\Compatibility;
|
||||||
|
|
||||||
defined('ABSPATH') || exit;
|
defined('ABSPATH') || exit;
|
||||||
|
|
||||||
/** A Divi constant an adapter reads (spec §4.1); it must be defined. */
|
/** A constant of a third-party plugin or theme that an adapter reads (spec §4.1); it must be defined. */
|
||||||
final class ConstantRequirement implements Requirement
|
final class ConstantRequirement implements Requirement
|
||||||
{
|
{
|
||||||
/** @param list<DiviFeature> $features [] = the default of the manifest. */
|
/** @param list<Capability> $features [] = the default of the manifest. */
|
||||||
public function __construct(public readonly string $name, private readonly array $features = [])
|
public function __construct(public readonly string $name, private readonly array $features = [])
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
+5
-5
@@ -2,20 +2,20 @@
|
|||||||
|
|
||||||
declare(strict_types=1);
|
declare(strict_types=1);
|
||||||
|
|
||||||
namespace LIT\MCP\Integrations\Divi\Release;
|
namespace LIT\MCP\Compatibility;
|
||||||
|
|
||||||
defined('ABSPATH') || exit;
|
defined('ABSPATH') || exit;
|
||||||
|
|
||||||
/** The release state of one Divi feature (E1): released (with its source), untested or incompatible. */
|
/** The release state of one capability (E1): released (with its source), untested or incompatible. */
|
||||||
final class FeatureStatus
|
final class FeatureStatus
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* @param list<string> $problems Labels of the problems behind the state (Problem::$label).
|
* @param list<string> $problems Labels of the problems behind the state (Problem::$label).
|
||||||
* @param string|null $source For a released feature: ReleaseStatus::SOURCE_CODE, SOURCE_DATABASE or
|
* @param string|null $source For a released feature: CompatibilityMatrix::SOURCE_CODE, SOURCE_DATABASE or
|
||||||
* SOURCE_AUTO; null otherwise.
|
* SOURCE_AUTO; null otherwise.
|
||||||
*/
|
*/
|
||||||
public function __construct(
|
public function __construct(
|
||||||
public readonly DiviFeature $feature,
|
public readonly Capability $feature,
|
||||||
public readonly ReleaseState $state,
|
public readonly ReleaseState $state,
|
||||||
public readonly array $problems = [],
|
public readonly array $problems = [],
|
||||||
public readonly ?string $source = null
|
public readonly ?string $source = null
|
||||||
@@ -31,7 +31,7 @@ final class FeatureStatus
|
|||||||
public function summary(): array
|
public function summary(): array
|
||||||
{
|
{
|
||||||
return [
|
return [
|
||||||
'id' => $this->feature->value,
|
'id' => $this->feature->id(),
|
||||||
'label' => $this->feature->label(),
|
'label' => $this->feature->label(),
|
||||||
'state' => $this->state->value,
|
'state' => $this->state->value,
|
||||||
'problems' => $this->problems,
|
'problems' => $this->problems,
|
||||||
@@ -0,0 +1,32 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace LIT\MCP\Compatibility;
|
||||||
|
|
||||||
|
defined('ABSPATH') || exit;
|
||||||
|
|
||||||
|
/** A global variable an adapter reads (e.g. a function-pointer or settings global of a plugin); it must be set. */
|
||||||
|
final class GlobalRequirement implements Requirement
|
||||||
|
{
|
||||||
|
/** @param list<Capability> $features [] = the default of the manifest. */
|
||||||
|
public function __construct(public readonly string $name, private readonly array $features = [])
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public function label(): string
|
||||||
|
{
|
||||||
|
return 'Globale Variable ' . $this->name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function features(): array
|
||||||
|
{
|
||||||
|
return $this->features;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** isset, not array_key_exists: a global that is null cannot be used by the adapter either. */
|
||||||
|
public function isSet(): bool
|
||||||
|
{
|
||||||
|
return isset($GLOBALS[$this->name]);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
declare(strict_types=1);
|
declare(strict_types=1);
|
||||||
|
|
||||||
namespace LIT\MCP\Integrations\Divi\Release;
|
namespace LIT\MCP\Compatibility;
|
||||||
|
|
||||||
defined('ABSPATH') || exit;
|
defined('ABSPATH') || exit;
|
||||||
|
|
||||||
@@ -2,40 +2,36 @@
|
|||||||
|
|
||||||
declare(strict_types=1);
|
declare(strict_types=1);
|
||||||
|
|
||||||
namespace LIT\MCP\Integrations\Divi\Release;
|
namespace LIT\MCP\Compatibility;
|
||||||
|
|
||||||
defined('ABSPATH') || exit;
|
defined('ABSPATH') || exit;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The Divi dependencies of one adapter (spec §4.1) – the single source for DiviCompatibility, the release gate,
|
* The external dependencies of one adapter (spec §4.1) – the single source for the compatibility checks, the release
|
||||||
* the admin check and DiviBoundaryTest. Pure data, no WordPress calls.
|
* gate, the admin check and DiviBoundaryTest. Pure data, no WordPress calls. Only area and calls are needed; the
|
||||||
|
* other fields are optional (the Divi integration uses all of them).
|
||||||
*/
|
*/
|
||||||
final class Manifest
|
final class Manifest
|
||||||
{
|
{
|
||||||
public const PAGES = 'Seiten';
|
|
||||||
public const LIBRARY = 'Bibliothek';
|
|
||||||
public const THEME_BUILDER = 'Theme Builder';
|
|
||||||
public const DESIGN = 'Designsystem';
|
|
||||||
public const CATALOG = 'Katalog';
|
|
||||||
|
|
||||||
/** @var list<ConstantRequirement> */
|
/** @var list<ConstantRequirement> */
|
||||||
public readonly array $constants;
|
public readonly array $constants;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param string $area One of the constants above (the five areas of spec §3).
|
* @param string $area Area label for reports (the Divi integration: DiviAreas).
|
||||||
* @param list<Call> $calls Divi functions and static methods the adapter calls.
|
* @param list<Call> $calls Functions and static methods the adapter calls.
|
||||||
* @param list<string|ConstantRequirement> $constants Divi constants it reads; a plain name stands for a
|
* @param list<string|ConstantRequirement> $constants Constants it reads; a plain name stands for a
|
||||||
* ConstantRequirement without features of its own.
|
* ConstantRequirement without features of its own.
|
||||||
* @param list<string> $postTypes Divi post types it needs registered.
|
* @param list<string> $postTypes Post types it needs registered.
|
||||||
* @param list<string> $taxonomies Divi taxonomies it needs registered.
|
* @param list<string> $taxonomies Taxonomies it needs registered.
|
||||||
* @param list<string> $blockTypes Divi block types it needs (registered or in Divi's
|
* @param list<string> $blockTypes Block types it needs (registered or known
|
||||||
* module metadata).
|
* to the ManifestCheck knowsBlock closure).
|
||||||
* @param list<string> $keys Other Divi names it uses as strings: meta keys, options,
|
* @param list<string> $keys Other names it uses as strings: meta keys, options,
|
||||||
* internal post types that need no registration check,
|
* internal post types that need no registration check,
|
||||||
* query arguments.
|
* query arguments.
|
||||||
* @param list<Mirror> $mirrors Divi functions whose storage logic it repeats.
|
* @param list<Mirror> $mirrors Functions whose storage logic it repeats.
|
||||||
* @param list<DiviFeature> $features The features of every call, mirror and constant that names
|
* @param list<Capability> $features The features of every call, mirror and constant that names
|
||||||
* none itself (featuresOf()).
|
* none itself (featuresOf()).
|
||||||
|
* @param list<GlobalRequirement> $globals Global variables it reads (isset check).
|
||||||
*/
|
*/
|
||||||
public function __construct(
|
public function __construct(
|
||||||
public readonly string $area,
|
public readonly string $area,
|
||||||
@@ -46,7 +42,8 @@ final class Manifest
|
|||||||
public readonly array $blockTypes = [],
|
public readonly array $blockTypes = [],
|
||||||
public readonly array $keys = [],
|
public readonly array $keys = [],
|
||||||
public readonly array $mirrors = [],
|
public readonly array $mirrors = [],
|
||||||
public readonly array $features = []
|
public readonly array $features = [],
|
||||||
|
public readonly array $globals = []
|
||||||
) {
|
) {
|
||||||
$this->constants = array_map(
|
$this->constants = array_map(
|
||||||
static fn (string|ConstantRequirement $constant): ConstantRequirement => is_string($constant)
|
static fn (string|ConstantRequirement $constant): ConstantRequirement => is_string($constant)
|
||||||
@@ -56,13 +53,13 @@ final class Manifest
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @return list<Requirement> Calls, constants and mirrors – everything the release gate checks as code. */
|
/** @return list<Requirement> Calls, constants, mirrors and globals – everything the release gate checks as code. */
|
||||||
public function requirements(): array
|
public function requirements(): array
|
||||||
{
|
{
|
||||||
return [...$this->calls, ...$this->constants, ...$this->mirrors];
|
return [...$this->calls, ...$this->constants, ...$this->mirrors, ...$this->globals];
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @return list<DiviFeature> The features $requirement names itself, else this manifest's default. */
|
/** @return list<Capability> The features $requirement names itself, else this manifest's default. */
|
||||||
public function featuresOf(Requirement $requirement): array
|
public function featuresOf(Requirement $requirement): array
|
||||||
{
|
{
|
||||||
$own = $requirement->features();
|
$own = $requirement->features();
|
||||||
@@ -71,8 +68,8 @@ final class Manifest
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return list<string> Every Divi name the adapter's code may contain (DiviBoundaryTest): called functions and
|
* @return list<string> Every external name the adapter's code may contain (DiviBoundaryTest): called functions and
|
||||||
* classes, constants, post types, taxonomies, keys and the names of mirrored functions.
|
* classes, constants, globals, post types, taxonomies, keys and the names of mirrored functions.
|
||||||
*/
|
*/
|
||||||
public function names(): array
|
public function names(): array
|
||||||
{
|
{
|
||||||
@@ -86,6 +83,7 @@ final class Manifest
|
|||||||
return array_values(array_unique(array_merge(
|
return array_values(array_unique(array_merge(
|
||||||
$names,
|
$names,
|
||||||
$constants,
|
$constants,
|
||||||
|
array_map(static fn (GlobalRequirement $global): string => $global->name, $this->globals),
|
||||||
$this->postTypes,
|
$this->postTypes,
|
||||||
$this->taxonomies,
|
$this->taxonomies,
|
||||||
$this->keys,
|
$this->keys,
|
||||||
+46
-64
@@ -2,18 +2,16 @@
|
|||||||
|
|
||||||
declare(strict_types=1);
|
declare(strict_types=1);
|
||||||
|
|
||||||
namespace LIT\MCP\Integrations\Divi\Release;
|
namespace LIT\MCP\Compatibility;
|
||||||
|
|
||||||
use Closure;
|
use Closure;
|
||||||
use LIT\MCP\Integrations\Divi\Schema\DiviModules;
|
use LogicException;
|
||||||
use ReflectionFunction;
|
|
||||||
use ReflectionMethod;
|
|
||||||
use Throwable;
|
use Throwable;
|
||||||
|
|
||||||
defined('ABSPATH') || exit;
|
defined('ABSPATH') || exit;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The checks of all adapter manifests (spec §4.3), as label => check for reports, and as problems with their Divi
|
* The checks of all adapter manifests (spec §4.3), as label => check for reports, and as problems with their
|
||||||
* features for the release matrix (problems(), E1). Code checks (calls with the argument count the adapter passes
|
* features for the release matrix (problems(), E1). Code checks (calls with the argument count the adapter passes
|
||||||
* and their signature, constants) and mirror checks decide the release gate; registration checks (post types,
|
* and their signature, constants) and mirror checks decide the release gate; registration checks (post types,
|
||||||
* taxonomies, block types) depend on the request context (stage3 finding 6) and only show in reports.
|
* taxonomies, block types) depend on the request context (stage3 finding 6) and only show in reports.
|
||||||
@@ -22,32 +20,30 @@ defined('ABSPATH') || exit;
|
|||||||
*/
|
*/
|
||||||
class ManifestCheck
|
class ManifestCheck
|
||||||
{
|
{
|
||||||
/** @var array<string, Manifest> */
|
|
||||||
private array $manifests;
|
|
||||||
|
|
||||||
/** @var Closure(Mirror): ?string */
|
|
||||||
private Closure $current;
|
|
||||||
|
|
||||||
/** @var Closure(string): bool */
|
|
||||||
private Closure $knowsBlock;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param array<string, Manifest>|null $manifests null = DiviAdapters::manifests().
|
* @param array<string, Manifest> $manifests Area key => manifest.
|
||||||
* @param array<string, string>|null $expected Mirror ID or "sig:<symbol>" => sha256;
|
* @param array<string, string>|null $expected Mirror ID or "sig:<symbol>" => sha256; null = none known.
|
||||||
* null = DiviReference::expected().
|
|
||||||
* @param (Closure(Mirror): ?string)|null $current Hash of the installed mirror, null = unreadable;
|
* @param (Closure(Mirror): ?string)|null $current Hash of the installed mirror, null = unreadable;
|
||||||
* null = SourceFingerprint in the Divi theme directory.
|
* no closure = every mirror is unreadable (a problem).
|
||||||
* @param (Closure(string): bool)|null $knowsBlock null = DiviModules::knowsBlock().
|
* @param (Closure(string): bool)|null $knowsBlock Whether a block type is known; required when a manifest
|
||||||
|
* has block types, which would otherwise pass unchecked.
|
||||||
|
* @param bool $signatures false = no signature checks: neither reference-missing
|
||||||
|
* nor signature problems (calls are still checked for
|
||||||
|
* existence and argument count).
|
||||||
|
* @throws LogicException When a manifest has block types but $knowsBlock is null.
|
||||||
*/
|
*/
|
||||||
public function __construct(
|
public function __construct(
|
||||||
?array $manifests = null,
|
private array $manifests,
|
||||||
private ?array $expected = null,
|
private ?array $expected = null,
|
||||||
?Closure $current = null,
|
private ?Closure $current = null,
|
||||||
?Closure $knowsBlock = null
|
private ?Closure $knowsBlock = null,
|
||||||
|
private bool $signatures = true
|
||||||
) {
|
) {
|
||||||
$this->manifests = $manifests ?? DiviAdapters::manifests();
|
foreach ($manifests as $manifest) {
|
||||||
$this->current = $current ?? self::installed(...);
|
if ($manifest->blockTypes !== [] && $knowsBlock === null) {
|
||||||
$this->knowsBlock = $knowsBlock ?? DiviModules::knowsBlock(...);
|
throw new LogicException('block types need a knowsBlock closure, else they pass unchecked');
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @return array<string, Closure(): bool> */
|
/** @return array<string, Closure(): bool> */
|
||||||
@@ -62,6 +58,9 @@ class ManifestCheck
|
|||||||
$checks[$manifest->area . ': ' . $constant->label()] =
|
$checks[$manifest->area . ': ' . $constant->label()] =
|
||||||
static fn (): bool => defined($constant->name);
|
static fn (): bool => defined($constant->name);
|
||||||
}
|
}
|
||||||
|
foreach ($manifest->globals as $global) {
|
||||||
|
$checks[$manifest->area . ': ' . $global->label()] = static fn (): bool => $global->isSet();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return $checks;
|
return $checks;
|
||||||
@@ -92,7 +91,7 @@ class ManifestCheck
|
|||||||
$checks[$manifest->area . ': Taxonomie ' . $taxonomy] =
|
$checks[$manifest->area . ': Taxonomie ' . $taxonomy] =
|
||||||
static fn (): bool => taxonomy_exists($taxonomy);
|
static fn (): bool => taxonomy_exists($taxonomy);
|
||||||
}
|
}
|
||||||
foreach ($manifest->blockTypes as $block) {
|
foreach ($this->knowsBlock === null ? [] : $manifest->blockTypes as $block) {
|
||||||
$checks[$manifest->area . ': Block-Typ ' . $block] = fn (): bool => ($this->knowsBlock)($block);
|
$checks[$manifest->area . ': Block-Typ ' . $block] = fn (): bool => ($this->knowsBlock)($block);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -123,8 +122,8 @@ class ManifestCheck
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Calls (missing or other argument count: call; no reference: reference-missing; other signature: signature)
|
* Calls (missing or other argument count: call; no reference: reference-missing; other signature: signature;
|
||||||
* and constants. Reflection only – cheap enough for every request.
|
* the last two only with signatures), constants and globals. Reflection only – cheap enough for every request.
|
||||||
*
|
*
|
||||||
* @return list<Problem>
|
* @return list<Problem>
|
||||||
*/
|
*/
|
||||||
@@ -147,6 +146,15 @@ class ManifestCheck
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
foreach ($manifest->globals as $global) {
|
||||||
|
if (! $global->isSet()) {
|
||||||
|
$problems[] = new Problem(
|
||||||
|
$manifest->area . ': ' . $global->label(),
|
||||||
|
$manifest->featuresOf($global),
|
||||||
|
Problem::GLOBAL
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return $problems;
|
return $problems;
|
||||||
@@ -154,8 +162,8 @@ class ManifestCheck
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Mirrors that differ from their reference, cannot be read or have no reference – kind mirror in every case:
|
* Mirrors that differ from their reference, cannot be read or have no reference – kind mirror in every case:
|
||||||
* a mirror repeats how Divi writes, so it never runs unverified, whatever the release. Reads Divi files; the
|
* a mirror repeats how the third-party code writes, so it never runs unverified, whatever the release. Reads
|
||||||
* resolver caches the result.
|
* files; the resolver caches the result.
|
||||||
*
|
*
|
||||||
* @return list<Problem>
|
* @return list<Problem>
|
||||||
*/
|
*/
|
||||||
@@ -180,22 +188,7 @@ class ManifestCheck
|
|||||||
/** The function or method exists and takes the number of arguments the adapter passes. */
|
/** The function or method exists and takes the number of arguments the adapter passes. */
|
||||||
public static function accepts(Call $call): bool
|
public static function accepts(Call $call): bool
|
||||||
{
|
{
|
||||||
$class = $call->className();
|
return $call->accepts();
|
||||||
if ($class === null) {
|
|
||||||
if (! function_exists($call->member())) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
$reflection = new ReflectionFunction($call->member());
|
|
||||||
} else {
|
|
||||||
if (! method_exists($class, $call->member())) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
$reflection = new ReflectionMethod($class, $call->member());
|
|
||||||
}
|
|
||||||
|
|
||||||
return $call->args === null
|
|
||||||
|| ($reflection->getNumberOfRequiredParameters() <= $call->args
|
|
||||||
&& ($reflection->isVariadic() || $reflection->getNumberOfParameters() >= $call->args));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private function callProblem(Manifest $manifest, Call $call): ?Problem
|
private function callProblem(Manifest $manifest, Call $call): ?Problem
|
||||||
@@ -206,7 +199,11 @@ class ManifestCheck
|
|||||||
return new Problem($label, $features, Problem::CALL);
|
return new Problem($label, $features, Problem::CALL);
|
||||||
}
|
}
|
||||||
|
|
||||||
$expected = $this->expected()[DiviReference::signatureKey($call)] ?? null;
|
if (! $this->signatures) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
$expected = ($this->expected ?? [])[$call->signatureKey()] ?? null;
|
||||||
if ($expected === null) {
|
if ($expected === null) {
|
||||||
return new Problem($label . ' – Referenz der Signatur fehlt', $features, Problem::REFERENCE_MISSING);
|
return new Problem($label . ' – Referenz der Signatur fehlt', $features, Problem::REFERENCE_MISSING);
|
||||||
}
|
}
|
||||||
@@ -219,15 +216,9 @@ class ManifestCheck
|
|||||||
/** The mirror's reference exists and the installed source has the same fingerprint. */
|
/** The mirror's reference exists and the installed source has the same fingerprint. */
|
||||||
private function matches(Mirror $mirror): bool
|
private function matches(Mirror $mirror): bool
|
||||||
{
|
{
|
||||||
$expected = $this->expected()[$mirror->id] ?? null;
|
$expected = ($this->expected ?? [])[$mirror->id] ?? null;
|
||||||
|
|
||||||
return $expected !== null && ($this->current)($mirror) === $expected;
|
return $expected !== null && $this->current !== null && ($this->current)($mirror) === $expected;
|
||||||
}
|
|
||||||
|
|
||||||
/** @return array<string, string> */
|
|
||||||
private function expected(): array
|
|
||||||
{
|
|
||||||
return $this->expected ??= DiviReference::expected();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static function mirrorLabel(Manifest $manifest, Mirror $mirror): string
|
private static function mirrorLabel(Manifest $manifest, Mirror $mirror): string
|
||||||
@@ -244,13 +235,4 @@ class ManifestCheck
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static function installed(Mirror $mirror): ?string
|
|
||||||
{
|
|
||||||
$dir = DiviEnvironment::themeDir();
|
|
||||||
|
|
||||||
return $dir === null
|
|
||||||
? null
|
|
||||||
: SourceFingerprint::of($dir . '/' . $mirror->file, $mirror->function, $mirror->class)->hash;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,48 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace LIT\MCP\Compatibility;
|
||||||
|
|
||||||
|
defined('ABSPATH') || exit;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A function of a third-party plugin or theme whose logic an adapter repeats instead of calling it (spec §4.1
|
||||||
|
* "mirrors"). Its fingerprint (SourceFingerprint) must match the one in fingerprints.json, else the third-party code
|
||||||
|
* changed what we copy.
|
||||||
|
*/
|
||||||
|
final class Mirror implements Requirement
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @param string $id Key in fingerprints.json and name of its reference source (the Divi integration
|
||||||
|
* keeps them in tests/Fixtures/divi/reference/<id>.txt – an example, not a rule).
|
||||||
|
* @param string $file File of the third-party code, relative to its plugin or theme directory.
|
||||||
|
* @param string $function Function or method name.
|
||||||
|
* @param string|null $class Class of a method – the short name is enough (the file fixes where it
|
||||||
|
* lives, and a short name is no external name for DiviBoundaryTest); null for a
|
||||||
|
* function.
|
||||||
|
* @param string $what What the plugin repeats (German, for reports).
|
||||||
|
* @param list<Capability> $features [] = the default of the manifest.
|
||||||
|
*/
|
||||||
|
public function __construct(
|
||||||
|
public readonly string $id,
|
||||||
|
public readonly string $file,
|
||||||
|
public readonly string $function,
|
||||||
|
public readonly ?string $class,
|
||||||
|
public readonly string $what,
|
||||||
|
private readonly array $features = []
|
||||||
|
) {
|
||||||
|
}
|
||||||
|
|
||||||
|
public function features(): array
|
||||||
|
{
|
||||||
|
return $this->features;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function label(): string
|
||||||
|
{
|
||||||
|
$class = $this->class === null ? '' : SourceFingerprint::shortName($this->class) . '::';
|
||||||
|
|
||||||
|
return $class . $this->function . '()';
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -2,15 +2,17 @@
|
|||||||
|
|
||||||
declare(strict_types=1);
|
declare(strict_types=1);
|
||||||
|
|
||||||
namespace LIT\MCP\Integrations\Divi\Release;
|
namespace LIT\MCP\Compatibility;
|
||||||
|
|
||||||
|
use Closure;
|
||||||
|
|
||||||
defined('ABSPATH') || exit;
|
defined('ABSPATH') || exit;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* One failed manifest check and the Divi features it concerns (Manifest::featuresOf()). The kind decides how the
|
* One failed manifest check and the capabilities it concerns (Manifest::featuresOf()). The kind decides how the
|
||||||
* resolver weighs it (E1): call, mirror and constant lock their features for every Divi version, released or not;
|
* resolver weighs it (E1): call, mirror, constant and global lock their features for every version, released
|
||||||
* signature and reference-missing only matter for a version without release (automatic release). A problem without
|
* or not; signature and reference-missing only matter for a version without release (automatic release). A problem
|
||||||
* features concerns every feature (fail closed).
|
* without features concerns every feature (fail closed).
|
||||||
*/
|
*/
|
||||||
final class Problem
|
final class Problem
|
||||||
{
|
{
|
||||||
@@ -18,6 +20,7 @@ final class Problem
|
|||||||
public const SIGNATURE = 'signature';
|
public const SIGNATURE = 'signature';
|
||||||
public const MIRROR = 'mirror';
|
public const MIRROR = 'mirror';
|
||||||
public const CONSTANT = 'constant';
|
public const CONSTANT = 'constant';
|
||||||
|
public const GLOBAL = 'global';
|
||||||
public const REFERENCE_MISSING = 'reference-missing';
|
public const REFERENCE_MISSING = 'reference-missing';
|
||||||
public const RESOLVER = 'resolver';
|
public const RESOLVER = 'resolver';
|
||||||
|
|
||||||
@@ -26,14 +29,15 @@ final class Problem
|
|||||||
self::SIGNATURE,
|
self::SIGNATURE,
|
||||||
self::MIRROR,
|
self::MIRROR,
|
||||||
self::CONSTANT,
|
self::CONSTANT,
|
||||||
|
self::GLOBAL,
|
||||||
self::REFERENCE_MISSING,
|
self::REFERENCE_MISSING,
|
||||||
self::RESOLVER,
|
self::RESOLVER,
|
||||||
];
|
];
|
||||||
private const HARD = [self::CALL, self::MIRROR, self::CONSTANT, self::RESOLVER];
|
private const HARD = [self::CALL, self::MIRROR, self::CONSTANT, self::GLOBAL, self::RESOLVER];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param string $label German, e.g. "Seiten: et_x()" (the labels of ManifestCheck).
|
* @param string $label German, e.g. "Seiten: et_x()" (the labels of ManifestCheck).
|
||||||
* @param list<DiviFeature> $features
|
* @param list<Capability> $features
|
||||||
* @param string $kind One of the constants above.
|
* @param string $kind One of the constants above.
|
||||||
*/
|
*/
|
||||||
public function __construct(
|
public function __construct(
|
||||||
@@ -43,13 +47,13 @@ final class Problem
|
|||||||
) {
|
) {
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Locks its features whatever the release (the code no longer fits Divi or a mirror differs). */
|
/** Locks its features whatever the release (the third-party code no longer fits or a mirror differs). */
|
||||||
public function isHard(): bool
|
public function isHard(): bool
|
||||||
{
|
{
|
||||||
return in_array($this->kind, self::HARD, true);
|
return in_array($this->kind, self::HARD, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function concerns(DiviFeature $feature): bool
|
public function concerns(Capability $feature): bool
|
||||||
{
|
{
|
||||||
return $this->features === [] || in_array($feature, $this->features, true);
|
return $this->features === [] || in_array($feature, $this->features, true);
|
||||||
}
|
}
|
||||||
@@ -60,12 +64,16 @@ final class Problem
|
|||||||
return [
|
return [
|
||||||
'label' => $this->label,
|
'label' => $this->label,
|
||||||
'kind' => $this->kind,
|
'kind' => $this->kind,
|
||||||
'features' => array_map(static fn (DiviFeature $feature): string => $feature->value, $this->features),
|
'features' => array_map(static fn (Capability $feature): string => $feature->id(), $this->features),
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
/** The problem of toArray(), or null for anything else (an unknown kind or feature included). */
|
/**
|
||||||
public static function fromArray(mixed $row): ?self
|
* The problem of toArray(), or null for anything else (an unknown kind or feature included).
|
||||||
|
*
|
||||||
|
* @param Closure(string): ?Capability $capability Finds a capability by its ID, null for an unknown one.
|
||||||
|
*/
|
||||||
|
public static function fromArray(mixed $row, Closure $capability): ?self
|
||||||
{
|
{
|
||||||
if (
|
if (
|
||||||
! is_array($row)
|
! is_array($row)
|
||||||
@@ -78,7 +86,7 @@ final class Problem
|
|||||||
|
|
||||||
$features = [];
|
$features = [];
|
||||||
foreach ($row['features'] as $value) {
|
foreach ($row['features'] as $value) {
|
||||||
$feature = is_string($value) ? DiviFeature::tryFrom($value) : null;
|
$feature = is_string($value) ? $capability($value) : null;
|
||||||
if ($feature === null) {
|
if ($feature === null) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
declare(strict_types=1);
|
declare(strict_types=1);
|
||||||
|
|
||||||
namespace LIT\MCP\Integrations\Divi\Release;
|
namespace LIT\MCP\Compatibility;
|
||||||
|
|
||||||
defined('ABSPATH') || exit;
|
defined('ABSPATH') || exit;
|
||||||
|
|
||||||
@@ -2,11 +2,14 @@
|
|||||||
|
|
||||||
declare(strict_types=1);
|
declare(strict_types=1);
|
||||||
|
|
||||||
namespace LIT\MCP\Integrations\Divi\Release;
|
namespace LIT\MCP\Compatibility;
|
||||||
|
|
||||||
defined('ABSPATH') || exit;
|
defined('ABSPATH') || exit;
|
||||||
|
|
||||||
/** One thing an adapter needs from Divi (a call, a mirrored function or a constant) and the features it serves. */
|
/**
|
||||||
|
* One thing an adapter needs from a third-party plugin or theme (a call, a mirrored function or a constant) and the
|
||||||
|
* features it serves.
|
||||||
|
*/
|
||||||
interface Requirement
|
interface Requirement
|
||||||
{
|
{
|
||||||
/** Name for reports, e.g. "GlobalPreset::get_data()" (without the manifest area). */
|
/** Name for reports, e.g. "GlobalPreset::get_data()" (without the manifest area). */
|
||||||
@@ -16,7 +19,7 @@ interface Requirement
|
|||||||
* The features this requirement serves itself; [] = the default of the manifest that lists it
|
* The features this requirement serves itself; [] = the default of the manifest that lists it
|
||||||
* (Manifest::featuresOf() resolves that).
|
* (Manifest::featuresOf() resolves that).
|
||||||
*
|
*
|
||||||
* @return list<DiviFeature>
|
* @return list<Capability>
|
||||||
*/
|
*/
|
||||||
public function features(): array;
|
public function features(): array;
|
||||||
}
|
}
|
||||||
+6
-5
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
declare(strict_types=1);
|
declare(strict_types=1);
|
||||||
|
|
||||||
namespace LIT\MCP\Integrations\Divi\Release;
|
namespace LIT\MCP\Compatibility;
|
||||||
|
|
||||||
use ReflectionException;
|
use ReflectionException;
|
||||||
use ReflectionFunction;
|
use ReflectionFunction;
|
||||||
@@ -14,14 +14,15 @@ use ReflectionType;
|
|||||||
defined('ABSPATH') || exit;
|
defined('ABSPATH') || exit;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Fingerprint of the signature of one Divi function or static method (spec §4.2, E1 of the plan "Divi-Fähigkeiten"),
|
* Fingerprint of the signature of one function or static method of a third-party plugin or theme (spec §4.2, E1 of
|
||||||
* read with Reflection from the running PHP process – so it needs the symbol to be loaded (in WordPress Divi is) and
|
* the plan "Divi-Fähigkeiten"), read with Reflection from the running PHP process – so it needs the symbol to be
|
||||||
* never includes a file. The class of a method is autoloaded the way ManifestCheck::accepts() already does it.
|
* loaded (in WordPress the plugin or theme is, once active) and never includes a file. The class of a method is
|
||||||
|
* autoloaded the way ManifestCheck::accepts() already does it.
|
||||||
*
|
*
|
||||||
* What the hash covers: function or method; for a method its visibility and whether it is static; per parameter the
|
* What the hash covers: function or method; for a method its visibility and whether it is static; per parameter the
|
||||||
* type (nullable and union included; no type reads as "mixed"), by reference, variadic and whether it is optional
|
* type (nullable and union included; no type reads as "mixed"), by reference, variadic and whether it is optional
|
||||||
* (has a default); the return type (none reads as "mixed"). What it leaves out:
|
* (has a default); the return type (none reads as "mixed"). What it leaves out:
|
||||||
* - Parameter names: the plugin passes every argument to Divi positionally (PHP 8 named arguments are never used),
|
* - Parameter names: the plugin passes every argument positionally (PHP 8 named arguments are never used),
|
||||||
* so a rename cannot break a call, and a harmless rename must not lock a feature.
|
* so a rename cannot break a call, and a harmless rename must not lock a feature.
|
||||||
* - Default values: they are expressions (constants, arrays) that Reflection may be unable to evaluate in some
|
* - Default values: they are expressions (constants, arrays) that Reflection may be unable to evaluate in some
|
||||||
* requests and that change spelling without changing meaning; only "has a default" matters for the number of
|
* requests and that change spelling without changing meaning; only "has a default" matters for the number of
|
||||||
+6
-6
@@ -2,18 +2,18 @@
|
|||||||
|
|
||||||
declare(strict_types=1);
|
declare(strict_types=1);
|
||||||
|
|
||||||
namespace LIT\MCP\Integrations\Divi\Release;
|
namespace LIT\MCP\Compatibility;
|
||||||
|
|
||||||
use RuntimeException;
|
use RuntimeException;
|
||||||
|
|
||||||
defined('ABSPATH') || exit;
|
defined('ABSPATH') || exit;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Fingerprint of one Divi function or method (spec §4.2), read with token_get_all(): the file is never included,
|
* Fingerprint of one function or method of a third-party plugin or theme (spec §4.2), read with token_get_all(): the
|
||||||
* so functions Divi loads only in some requests (theme-builder/api.php, admin-ajax only) are readable in every
|
* file is never included, so functions loaded only in some requests (e.g. Divi's theme-builder/api.php, admin-ajax
|
||||||
* request. The hash covers the tokens from "function" to the closing brace without comments and whitespace –
|
* only) are readable in every request. The hash covers the tokens from "function" to the closing brace without
|
||||||
* new comments or reformatting keep it, any code change changes it. $source is the verbatim text of those
|
* comments and whitespace – new comments or reformatting keep it, any code change changes it. $source is the verbatim
|
||||||
* tokens for the human diff (wp lit-mcp divi-check --diff).
|
* text of those tokens for the human diff (wp lit-mcp divi-check --diff).
|
||||||
*/
|
*/
|
||||||
final class SourceFingerprint
|
final class SourceFingerprint
|
||||||
{
|
{
|
||||||
@@ -9,15 +9,15 @@ use LIT\MCP\Admin\AdminPostAction;
|
|||||||
use LIT\MCP\Admin\AdminTab;
|
use LIT\MCP\Admin\AdminTab;
|
||||||
use LIT\MCP\Admin\SettingsPage;
|
use LIT\MCP\Admin\SettingsPage;
|
||||||
use LIT\MCP\ChangeLog\ChangeLog;
|
use LIT\MCP\ChangeLog\ChangeLog;
|
||||||
|
use LIT\MCP\Compatibility\ReleaseState;
|
||||||
use LIT\MCP\Integrations\Divi\Release\CheckReport;
|
use LIT\MCP\Integrations\Divi\Release\CheckReport;
|
||||||
use LIT\MCP\Integrations\Divi\Release\CheckReportStore;
|
use LIT\MCP\Integrations\Divi\Release\CheckReportStore;
|
||||||
use LIT\MCP\Integrations\Divi\Release\DiviCheckRoute;
|
use LIT\MCP\Integrations\Divi\Release\DiviCheckRoute;
|
||||||
use LIT\MCP\Integrations\Divi\Release\DiviEnvironment;
|
use LIT\MCP\Integrations\Divi\Release\DiviEnvironment;
|
||||||
use LIT\MCP\Integrations\Divi\Release\FeatureOverview;
|
use LIT\MCP\Integrations\Divi\Release\FeatureOverview;
|
||||||
use LIT\MCP\Integrations\Divi\Release\FeatureStatus;
|
use LIT\MCP\Compatibility\FeatureStatus;
|
||||||
use LIT\MCP\Integrations\Divi\Release\ReleaseGate;
|
use LIT\MCP\Integrations\Divi\Release\ReleaseGate;
|
||||||
use LIT\MCP\Integrations\Divi\Release\ReleaseResolver;
|
use LIT\MCP\Integrations\Divi\Release\ReleaseResolver;
|
||||||
use LIT\MCP\Integrations\Divi\Release\ReleaseState;
|
|
||||||
use LIT\MCP\Integrations\Divi\Release\ReleaseStatus;
|
use LIT\MCP\Integrations\Divi\Release\ReleaseStatus;
|
||||||
use LIT\MCP\Integrations\Divi\Release\ReleaseStore;
|
use LIT\MCP\Integrations\Divi\Release\ReleaseStore;
|
||||||
use LIT\MCP\Integrations\Divi\Release\WriteProbe;
|
use LIT\MCP\Integrations\Divi\Release\WriteProbe;
|
||||||
|
|||||||
@@ -5,17 +5,17 @@ declare(strict_types=1);
|
|||||||
namespace LIT\MCP\Integrations\Divi\Cli;
|
namespace LIT\MCP\Integrations\Divi\Cli;
|
||||||
|
|
||||||
use Closure;
|
use Closure;
|
||||||
|
use LIT\MCP\Compatibility\LineDiff;
|
||||||
|
use LIT\MCP\Compatibility\SourceFingerprint;
|
||||||
use LIT\MCP\Integrations\Divi\Release\CheckReport;
|
use LIT\MCP\Integrations\Divi\Release\CheckReport;
|
||||||
use LIT\MCP\Integrations\Divi\Release\CheckReportStore;
|
use LIT\MCP\Integrations\Divi\Release\CheckReportStore;
|
||||||
use LIT\MCP\Integrations\Divi\Release\CheckStep;
|
use LIT\MCP\Integrations\Divi\Release\CheckStep;
|
||||||
use LIT\MCP\Integrations\Divi\Release\CompatibilityCheck;
|
use LIT\MCP\Integrations\Divi\Release\CompatibilityCheck;
|
||||||
use LIT\MCP\Integrations\Divi\Release\CompatibilityMatrix;
|
use LIT\MCP\Compatibility\CompatibilityMatrix;
|
||||||
use LIT\MCP\Integrations\Divi\Release\DiviAdapters;
|
use LIT\MCP\Integrations\Divi\Release\DiviAdapters;
|
||||||
use LIT\MCP\Integrations\Divi\Release\DiviEnvironment;
|
use LIT\MCP\Integrations\Divi\Release\DiviEnvironment;
|
||||||
use LIT\MCP\Integrations\Divi\Release\DiviReference;
|
use LIT\MCP\Integrations\Divi\Release\DiviReference;
|
||||||
use LIT\MCP\Integrations\Divi\Release\LineDiff;
|
|
||||||
use LIT\MCP\Integrations\Divi\Release\ReleaseGate;
|
use LIT\MCP\Integrations\Divi\Release\ReleaseGate;
|
||||||
use LIT\MCP\Integrations\Divi\Release\SourceFingerprint;
|
|
||||||
use RuntimeException;
|
use RuntimeException;
|
||||||
|
|
||||||
defined('ABSPATH') || exit;
|
defined('ABSPATH') || exit;
|
||||||
|
|||||||
@@ -6,10 +6,11 @@ namespace LIT\MCP\Integrations\Divi\Design;
|
|||||||
|
|
||||||
use ET\Builder\Packages\GlobalData\GlobalData;
|
use ET\Builder\Packages\GlobalData\GlobalData;
|
||||||
use ET\Builder\Packages\GlobalData\GlobalPreset;
|
use ET\Builder\Packages\GlobalData\GlobalPreset;
|
||||||
use LIT\MCP\Integrations\Divi\Release\Call;
|
use LIT\MCP\Compatibility\Call;
|
||||||
use LIT\MCP\Integrations\Divi\Release\DiviAdapter;
|
use LIT\MCP\Integrations\Divi\Release\DiviAdapter;
|
||||||
|
use LIT\MCP\Integrations\Divi\Release\DiviAreas;
|
||||||
use LIT\MCP\Integrations\Divi\Release\DiviFeature;
|
use LIT\MCP\Integrations\Divi\Release\DiviFeature;
|
||||||
use LIT\MCP\Integrations\Divi\Release\Manifest;
|
use LIT\MCP\Compatibility\Manifest;
|
||||||
|
|
||||||
defined('ABSPATH') || exit;
|
defined('ABSPATH') || exit;
|
||||||
|
|
||||||
@@ -29,7 +30,7 @@ class DesignSystemReader implements DiviAdapter
|
|||||||
public static function manifest(): Manifest
|
public static function manifest(): Manifest
|
||||||
{
|
{
|
||||||
return new Manifest(
|
return new Manifest(
|
||||||
Manifest::DESIGN,
|
DiviAreas::DESIGN,
|
||||||
calls: [
|
calls: [
|
||||||
new Call(GlobalData::class . '::get_global_colors', 0),
|
new Call(GlobalData::class . '::get_global_colors', 0),
|
||||||
new Call(GlobalData::class . '::get_global_variables', 0),
|
new Call(GlobalData::class . '::get_global_variables', 0),
|
||||||
|
|||||||
@@ -8,12 +8,13 @@ use ET\Builder\Framework\UserRole\UserRole;
|
|||||||
use ET\Builder\Packages\Conversion\Conversion;
|
use ET\Builder\Packages\Conversion\Conversion;
|
||||||
use ET\Builder\Packages\GlobalData\GlobalPreset;
|
use ET\Builder\Packages\GlobalData\GlobalPreset;
|
||||||
use ET\Builder\Packages\ModuleLibrary\ModuleRegistration;
|
use ET\Builder\Packages\ModuleLibrary\ModuleRegistration;
|
||||||
use LIT\MCP\Integrations\Divi\Release\Call;
|
use LIT\MCP\Compatibility\Call;
|
||||||
use LIT\MCP\Integrations\Divi\Release\DiviAdapter;
|
use LIT\MCP\Integrations\Divi\Release\DiviAdapter;
|
||||||
|
use LIT\MCP\Integrations\Divi\Release\DiviAreas;
|
||||||
use LIT\MCP\Integrations\Divi\Release\DiviFeature;
|
use LIT\MCP\Integrations\Divi\Release\DiviFeature;
|
||||||
use LIT\MCP\Integrations\Divi\Release\DiviLocked;
|
use LIT\MCP\Integrations\Divi\Release\DiviLocked;
|
||||||
use LIT\MCP\Integrations\Divi\Release\Manifest;
|
use LIT\MCP\Compatibility\Manifest;
|
||||||
use LIT\MCP\Integrations\Divi\Release\Mirror;
|
use LIT\MCP\Compatibility\Mirror;
|
||||||
use LIT\MCP\Integrations\Divi\Release\ReleaseGate;
|
use LIT\MCP\Integrations\Divi\Release\ReleaseGate;
|
||||||
use RuntimeException;
|
use RuntimeException;
|
||||||
use WP_Error;
|
use WP_Error;
|
||||||
@@ -43,7 +44,7 @@ class DesignSystemWriter implements DiviAdapter
|
|||||||
public static function manifest(): Manifest
|
public static function manifest(): Manifest
|
||||||
{
|
{
|
||||||
return new Manifest(
|
return new Manifest(
|
||||||
Manifest::DESIGN,
|
DiviAreas::DESIGN,
|
||||||
calls: [
|
calls: [
|
||||||
// Read by the preset tools as well as by the design system tool.
|
// Read by the preset tools as well as by the design system tool.
|
||||||
new Call(GlobalPreset::class . '::get_data', 0, [DiviFeature::DesignRead, DiviFeature::PresetWrite]),
|
new Call(GlobalPreset::class . '::get_data', 0, [DiviFeature::DesignRead, DiviFeature::PresetWrite]),
|
||||||
|
|||||||
@@ -4,10 +4,11 @@ declare(strict_types=1);
|
|||||||
|
|
||||||
namespace LIT\MCP\Integrations\Divi\Design;
|
namespace LIT\MCP\Integrations\Divi\Design;
|
||||||
|
|
||||||
use LIT\MCP\Integrations\Divi\Release\Call;
|
use LIT\MCP\Compatibility\Call;
|
||||||
use LIT\MCP\Integrations\Divi\Release\DiviAdapter;
|
use LIT\MCP\Integrations\Divi\Release\DiviAdapter;
|
||||||
|
use LIT\MCP\Integrations\Divi\Release\DiviAreas;
|
||||||
use LIT\MCP\Integrations\Divi\Release\DiviFeature;
|
use LIT\MCP\Integrations\Divi\Release\DiviFeature;
|
||||||
use LIT\MCP\Integrations\Divi\Release\Manifest;
|
use LIT\MCP\Compatibility\Manifest;
|
||||||
|
|
||||||
defined('ABSPATH') || exit;
|
defined('ABSPATH') || exit;
|
||||||
|
|
||||||
@@ -26,7 +27,7 @@ class FontCatalog implements DiviAdapter
|
|||||||
public static function manifest(): Manifest
|
public static function manifest(): Manifest
|
||||||
{
|
{
|
||||||
return new Manifest(
|
return new Manifest(
|
||||||
Manifest::DESIGN,
|
DiviAreas::DESIGN,
|
||||||
calls: [
|
calls: [
|
||||||
new Call('et_builder_get_fonts', 0),
|
new Call('et_builder_get_fonts', 0),
|
||||||
new Call('et_builder_get_custom_fonts', 0),
|
new Call('et_builder_get_custom_fonts', 0),
|
||||||
|
|||||||
@@ -6,12 +6,13 @@ namespace LIT\MCP\Integrations\Divi\Design;
|
|||||||
|
|
||||||
use ET\Builder\VisualBuilder\Fonts\FontsUtility;
|
use ET\Builder\VisualBuilder\Fonts\FontsUtility;
|
||||||
use ET\Builder\VisualBuilder\Hooks\HooksRegistration;
|
use ET\Builder\VisualBuilder\Hooks\HooksRegistration;
|
||||||
use LIT\MCP\Integrations\Divi\Release\Call;
|
use LIT\MCP\Compatibility\Call;
|
||||||
use LIT\MCP\Integrations\Divi\Release\DiviAdapter;
|
use LIT\MCP\Integrations\Divi\Release\DiviAdapter;
|
||||||
|
use LIT\MCP\Integrations\Divi\Release\DiviAreas;
|
||||||
use LIT\MCP\Integrations\Divi\Release\DiviFeature;
|
use LIT\MCP\Integrations\Divi\Release\DiviFeature;
|
||||||
use LIT\MCP\Integrations\Divi\Release\DiviLocked;
|
use LIT\MCP\Integrations\Divi\Release\DiviLocked;
|
||||||
use LIT\MCP\Integrations\Divi\Release\Manifest;
|
use LIT\MCP\Compatibility\Manifest;
|
||||||
use LIT\MCP\Integrations\Divi\Release\Mirror;
|
use LIT\MCP\Compatibility\Mirror;
|
||||||
use LIT\MCP\Integrations\Divi\Release\ReleaseGate;
|
use LIT\MCP\Integrations\Divi\Release\ReleaseGate;
|
||||||
use RuntimeException;
|
use RuntimeException;
|
||||||
|
|
||||||
@@ -35,7 +36,7 @@ class FontInstaller implements DiviAdapter
|
|||||||
public static function manifest(): Manifest
|
public static function manifest(): Manifest
|
||||||
{
|
{
|
||||||
return new Manifest(
|
return new Manifest(
|
||||||
Manifest::DESIGN,
|
DiviAreas::DESIGN,
|
||||||
calls: [
|
calls: [
|
||||||
new Call(FontsUtility::class . '::mime_types_font', 0),
|
new Call(FontsUtility::class . '::mime_types_font', 0),
|
||||||
new Call(HooksRegistration::class . '::check_filetype_and_ext_font', 3),
|
new Call(HooksRegistration::class . '::check_filetype_and_ext_font', 3),
|
||||||
|
|||||||
@@ -5,11 +5,12 @@ declare(strict_types=1);
|
|||||||
namespace LIT\MCP\Integrations\Divi\Design;
|
namespace LIT\MCP\Integrations\Divi\Design;
|
||||||
|
|
||||||
use ET\Builder\Packages\GlobalData\GlobalData;
|
use ET\Builder\Packages\GlobalData\GlobalData;
|
||||||
use LIT\MCP\Integrations\Divi\Release\Call;
|
use LIT\MCP\Compatibility\Call;
|
||||||
use LIT\MCP\Integrations\Divi\Release\DiviAdapter;
|
use LIT\MCP\Integrations\Divi\Release\DiviAdapter;
|
||||||
|
use LIT\MCP\Integrations\Divi\Release\DiviAreas;
|
||||||
use LIT\MCP\Integrations\Divi\Release\DiviFeature;
|
use LIT\MCP\Integrations\Divi\Release\DiviFeature;
|
||||||
use LIT\MCP\Integrations\Divi\Release\DiviLocked;
|
use LIT\MCP\Integrations\Divi\Release\DiviLocked;
|
||||||
use LIT\MCP\Integrations\Divi\Release\Manifest;
|
use LIT\MCP\Compatibility\Manifest;
|
||||||
use LIT\MCP\Integrations\Divi\Release\ReleaseGate;
|
use LIT\MCP\Integrations\Divi\Release\ReleaseGate;
|
||||||
use RuntimeException;
|
use RuntimeException;
|
||||||
|
|
||||||
@@ -39,7 +40,7 @@ class GlobalColorsAdapter implements DiviAdapter
|
|||||||
public static function manifest(): Manifest
|
public static function manifest(): Manifest
|
||||||
{
|
{
|
||||||
return new Manifest(
|
return new Manifest(
|
||||||
Manifest::DESIGN,
|
DiviAreas::DESIGN,
|
||||||
calls: [
|
calls: [
|
||||||
new Call(GlobalData::class . '::get_global_colors', 0),
|
new Call(GlobalData::class . '::get_global_colors', 0),
|
||||||
new Call(GlobalData::class . '::sanitize_global_colors_data', 1),
|
new Call(GlobalData::class . '::sanitize_global_colors_data', 1),
|
||||||
|
|||||||
@@ -5,11 +5,12 @@ declare(strict_types=1);
|
|||||||
namespace LIT\MCP\Integrations\Divi\Design;
|
namespace LIT\MCP\Integrations\Divi\Design;
|
||||||
|
|
||||||
use ET\Builder\Packages\GlobalData\GlobalData;
|
use ET\Builder\Packages\GlobalData\GlobalData;
|
||||||
use LIT\MCP\Integrations\Divi\Release\Call;
|
use LIT\MCP\Compatibility\Call;
|
||||||
use LIT\MCP\Integrations\Divi\Release\DiviAdapter;
|
use LIT\MCP\Integrations\Divi\Release\DiviAdapter;
|
||||||
|
use LIT\MCP\Integrations\Divi\Release\DiviAreas;
|
||||||
use LIT\MCP\Integrations\Divi\Release\DiviFeature;
|
use LIT\MCP\Integrations\Divi\Release\DiviFeature;
|
||||||
use LIT\MCP\Integrations\Divi\Release\DiviLocked;
|
use LIT\MCP\Integrations\Divi\Release\DiviLocked;
|
||||||
use LIT\MCP\Integrations\Divi\Release\Manifest;
|
use LIT\MCP\Compatibility\Manifest;
|
||||||
use LIT\MCP\Integrations\Divi\Release\ReleaseGate;
|
use LIT\MCP\Integrations\Divi\Release\ReleaseGate;
|
||||||
use RuntimeException;
|
use RuntimeException;
|
||||||
use WP_Error;
|
use WP_Error;
|
||||||
@@ -28,7 +29,7 @@ class GlobalVariablesAdapter implements DiviAdapter
|
|||||||
public static function manifest(): Manifest
|
public static function manifest(): Manifest
|
||||||
{
|
{
|
||||||
return new Manifest(
|
return new Manifest(
|
||||||
Manifest::DESIGN,
|
DiviAreas::DESIGN,
|
||||||
calls: [
|
calls: [
|
||||||
new Call(GlobalData::class . '::get_global_variables', 0),
|
new Call(GlobalData::class . '::get_global_variables', 0),
|
||||||
new Call(GlobalData::class . '::set_global_variables', 2),
|
new Call(GlobalData::class . '::set_global_variables', 2),
|
||||||
|
|||||||
@@ -5,12 +5,13 @@ declare(strict_types=1);
|
|||||||
namespace LIT\MCP\Integrations\Divi\Design;
|
namespace LIT\MCP\Integrations\Divi\Design;
|
||||||
|
|
||||||
use InvalidArgumentException;
|
use InvalidArgumentException;
|
||||||
use LIT\MCP\Integrations\Divi\Release\Call;
|
use LIT\MCP\Compatibility\Call;
|
||||||
use LIT\MCP\Integrations\Divi\Release\DiviAdapter;
|
use LIT\MCP\Integrations\Divi\Release\DiviAdapter;
|
||||||
|
use LIT\MCP\Integrations\Divi\Release\DiviAreas;
|
||||||
use LIT\MCP\Integrations\Divi\Release\DiviFeature;
|
use LIT\MCP\Integrations\Divi\Release\DiviFeature;
|
||||||
use LIT\MCP\Integrations\Divi\Release\DiviLocked;
|
use LIT\MCP\Integrations\Divi\Release\DiviLocked;
|
||||||
use LIT\MCP\Integrations\Divi\Release\Manifest;
|
use LIT\MCP\Compatibility\Manifest;
|
||||||
use LIT\MCP\Integrations\Divi\Release\Mirror;
|
use LIT\MCP\Compatibility\Mirror;
|
||||||
use LIT\MCP\Integrations\Divi\Release\ReleaseGate;
|
use LIT\MCP\Integrations\Divi\Release\ReleaseGate;
|
||||||
use RuntimeException;
|
use RuntimeException;
|
||||||
|
|
||||||
@@ -61,7 +62,7 @@ class ThemeOptionsAdapter implements DiviAdapter
|
|||||||
public static function manifest(): Manifest
|
public static function manifest(): Manifest
|
||||||
{
|
{
|
||||||
return new Manifest(
|
return new Manifest(
|
||||||
Manifest::DESIGN,
|
DiviAreas::DESIGN,
|
||||||
calls: [
|
calls: [
|
||||||
new Call('et_sanitize_font_choices', 1),
|
new Call('et_sanitize_font_choices', 1),
|
||||||
new Call('et_sanitize_global_font_weight', 1),
|
new Call('et_sanitize_global_font_weight', 1),
|
||||||
|
|||||||
@@ -4,7 +4,8 @@ declare(strict_types=1);
|
|||||||
|
|
||||||
namespace LIT\MCP\Integrations\Divi;
|
namespace LIT\MCP\Integrations\Divi;
|
||||||
|
|
||||||
use LIT\MCP\Integrations\Divi\Release\ManifestCheck;
|
use LIT\MCP\Compatibility\ManifestCheck;
|
||||||
|
use LIT\MCP\Integrations\Divi\Release\DiviManifestCheck;
|
||||||
|
|
||||||
defined('ABSPATH') || exit;
|
defined('ABSPATH') || exit;
|
||||||
|
|
||||||
@@ -29,7 +30,7 @@ final class DiviCompatibility
|
|||||||
/** @return array<string, callable(): bool> */
|
/** @return array<string, callable(): bool> */
|
||||||
public static function defaults(?ManifestCheck $check = null): array
|
public static function defaults(?ManifestCheck $check = null): array
|
||||||
{
|
{
|
||||||
$check ??= new ManifestCheck();
|
$check ??= DiviManifestCheck::create();
|
||||||
|
|
||||||
return array_merge($check->codeChecks(), $check->registrationChecks(), $check->mirrorChecks());
|
return array_merge($check->codeChecks(), $check->registrationChecks(), $check->mirrorChecks());
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,12 +5,13 @@ declare(strict_types=1);
|
|||||||
namespace LIT\MCP\Integrations\Divi\Library;
|
namespace LIT\MCP\Integrations\Divi\Library;
|
||||||
|
|
||||||
use LIT\MCP\Abilities\WriteFailed;
|
use LIT\MCP\Abilities\WriteFailed;
|
||||||
use LIT\MCP\Integrations\Divi\Release\Call;
|
use LIT\MCP\Compatibility\Call;
|
||||||
use LIT\MCP\Integrations\Divi\Release\DiviAdapter;
|
use LIT\MCP\Integrations\Divi\Release\DiviAdapter;
|
||||||
|
use LIT\MCP\Integrations\Divi\Release\DiviAreas;
|
||||||
use LIT\MCP\Integrations\Divi\Release\DiviFeature;
|
use LIT\MCP\Integrations\Divi\Release\DiviFeature;
|
||||||
use LIT\MCP\Integrations\Divi\Release\DiviLocked;
|
use LIT\MCP\Integrations\Divi\Release\DiviLocked;
|
||||||
use LIT\MCP\Integrations\Divi\Release\Manifest;
|
use LIT\MCP\Compatibility\Manifest;
|
||||||
use LIT\MCP\Integrations\Divi\Release\Mirror;
|
use LIT\MCP\Compatibility\Mirror;
|
||||||
use LIT\MCP\Integrations\Divi\Release\ReleaseGate;
|
use LIT\MCP\Integrations\Divi\Release\ReleaseGate;
|
||||||
use LIT\MCP\Integrations\WordPress\Content\NewDraft;
|
use LIT\MCP\Integrations\WordPress\Content\NewDraft;
|
||||||
use RuntimeException;
|
use RuntimeException;
|
||||||
@@ -55,7 +56,7 @@ class DiviLibraryStore implements DiviAdapter
|
|||||||
public static function manifest(): Manifest
|
public static function manifest(): Manifest
|
||||||
{
|
{
|
||||||
return new Manifest(
|
return new Manifest(
|
||||||
Manifest::LIBRARY,
|
DiviAreas::LIBRARY,
|
||||||
calls: [
|
calls: [
|
||||||
// isGlobal() serves listing and describing as well as the global edits.
|
// isGlobal() serves listing and describing as well as the global edits.
|
||||||
new Call(
|
new Call(
|
||||||
|
|||||||
@@ -6,10 +6,11 @@ namespace LIT\MCP\Integrations\Divi\Library;
|
|||||||
|
|
||||||
use Closure;
|
use Closure;
|
||||||
use LIT\MCP\Abilities\Errors;
|
use LIT\MCP\Abilities\Errors;
|
||||||
use LIT\MCP\Integrations\Divi\Release\Call;
|
use LIT\MCP\Compatibility\Call;
|
||||||
use LIT\MCP\Integrations\Divi\Release\DiviAdapter;
|
use LIT\MCP\Integrations\Divi\Release\DiviAdapter;
|
||||||
|
use LIT\MCP\Integrations\Divi\Release\DiviAreas;
|
||||||
use LIT\MCP\Integrations\Divi\Release\DiviFeature;
|
use LIT\MCP\Integrations\Divi\Release\DiviFeature;
|
||||||
use LIT\MCP\Integrations\Divi\Release\Manifest;
|
use LIT\MCP\Compatibility\Manifest;
|
||||||
use WP_Error;
|
use WP_Error;
|
||||||
|
|
||||||
defined('ABSPATH') || exit;
|
defined('ABSPATH') || exit;
|
||||||
@@ -35,7 +36,7 @@ class DiviRoles implements DiviAdapter
|
|||||||
public static function manifest(): Manifest
|
public static function manifest(): Manifest
|
||||||
{
|
{
|
||||||
return new Manifest(
|
return new Manifest(
|
||||||
Manifest::LIBRARY,
|
DiviAreas::LIBRARY,
|
||||||
calls: [new Call('et_pb_is_allowed', 1)],
|
calls: [new Call('et_pb_is_allowed', 1)],
|
||||||
features: [DiviFeature::Roles]
|
features: [DiviFeature::Roles]
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -4,12 +4,13 @@ declare(strict_types=1);
|
|||||||
|
|
||||||
namespace LIT\MCP\Integrations\Divi\Pages;
|
namespace LIT\MCP\Integrations\Divi\Pages;
|
||||||
|
|
||||||
use LIT\MCP\Integrations\Divi\Release\Call;
|
use LIT\MCP\Compatibility\Call;
|
||||||
use LIT\MCP\Integrations\Divi\Release\DiviAdapter;
|
use LIT\MCP\Integrations\Divi\Release\DiviAdapter;
|
||||||
|
use LIT\MCP\Integrations\Divi\Release\DiviAreas;
|
||||||
use LIT\MCP\Integrations\Divi\Release\DiviFeature;
|
use LIT\MCP\Integrations\Divi\Release\DiviFeature;
|
||||||
use LIT\MCP\Integrations\Divi\Release\DiviLocked;
|
use LIT\MCP\Integrations\Divi\Release\DiviLocked;
|
||||||
use LIT\MCP\Integrations\Divi\Release\Manifest;
|
use LIT\MCP\Compatibility\Manifest;
|
||||||
use LIT\MCP\Integrations\Divi\Release\Mirror;
|
use LIT\MCP\Compatibility\Mirror;
|
||||||
use LIT\MCP\Integrations\Divi\Release\ReleaseGate;
|
use LIT\MCP\Integrations\Divi\Release\ReleaseGate;
|
||||||
use RuntimeException;
|
use RuntimeException;
|
||||||
use WP_Post;
|
use WP_Post;
|
||||||
@@ -35,7 +36,7 @@ final class DiviPages implements DiviAdapter
|
|||||||
public static function manifest(): Manifest
|
public static function manifest(): Manifest
|
||||||
{
|
{
|
||||||
return new Manifest(
|
return new Manifest(
|
||||||
Manifest::PAGES,
|
DiviAreas::PAGES,
|
||||||
calls: [
|
calls: [
|
||||||
// Also called by DiviThemeBuilder::clearSiteCaches() – a break locks both features.
|
// Also called by DiviThemeBuilder::clearSiteCaches() – a break locks both features.
|
||||||
new Call(
|
new Call(
|
||||||
|
|||||||
@@ -8,10 +8,11 @@ use Closure;
|
|||||||
use LIT\MCP\Integrations\Divi\Compose\Placeholders;
|
use LIT\MCP\Integrations\Divi\Compose\Placeholders;
|
||||||
use LIT\MCP\Integrations\Divi\Compose\DynamicContentRules;
|
use LIT\MCP\Integrations\Divi\Compose\DynamicContentRules;
|
||||||
use LIT\MCP\Integrations\Divi\Compose\LoopScope;
|
use LIT\MCP\Integrations\Divi\Compose\LoopScope;
|
||||||
use LIT\MCP\Integrations\Divi\Release\Call;
|
use LIT\MCP\Compatibility\Call;
|
||||||
use LIT\MCP\Integrations\Divi\Release\DiviAdapter;
|
use LIT\MCP\Integrations\Divi\Release\DiviAdapter;
|
||||||
|
use LIT\MCP\Integrations\Divi\Release\DiviAreas;
|
||||||
use LIT\MCP\Integrations\Divi\Release\DiviFeature;
|
use LIT\MCP\Integrations\Divi\Release\DiviFeature;
|
||||||
use LIT\MCP\Integrations\Divi\Release\Manifest;
|
use LIT\MCP\Compatibility\Manifest;
|
||||||
use LIT\MCP\Log;
|
use LIT\MCP\Log;
|
||||||
use Throwable;
|
use Throwable;
|
||||||
|
|
||||||
@@ -56,7 +57,7 @@ class DynamicContentMap implements DiviAdapter
|
|||||||
public static function manifest(): Manifest
|
public static function manifest(): Manifest
|
||||||
{
|
{
|
||||||
return new Manifest(
|
return new Manifest(
|
||||||
Manifest::CATALOG,
|
DiviAreas::CATALOG,
|
||||||
calls: [new Call(self::REGISTRY . '::get_options', 2)],
|
calls: [new Call(self::REGISTRY . '::get_options', 2)],
|
||||||
features: [DiviFeature::DynamicSources]
|
features: [DiviFeature::DynamicSources]
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -1,47 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
declare(strict_types=1);
|
|
||||||
|
|
||||||
namespace LIT\MCP\Integrations\Divi\Release;
|
|
||||||
|
|
||||||
defined('ABSPATH') || exit;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* One Divi function or static method an adapter calls (spec §4.1), with the number of arguments the plugin passes.
|
|
||||||
* $args null: only its existence matters (a function Divi itself needs, e.g. et_() inside store_template).
|
|
||||||
*/
|
|
||||||
final class Call implements Requirement
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* @param string $symbol "function_name" or "Fully\Qualified\Class::method".
|
|
||||||
* @param list<DiviFeature> $features [] = the default of the manifest.
|
|
||||||
*/
|
|
||||||
public function __construct(
|
|
||||||
public readonly string $symbol,
|
|
||||||
public readonly ?int $args = null,
|
|
||||||
private readonly array $features = []
|
|
||||||
) {
|
|
||||||
}
|
|
||||||
|
|
||||||
public function className(): ?string
|
|
||||||
{
|
|
||||||
return str_contains($this->symbol, '::') ? ltrim(explode('::', $this->symbol, 2)[0], '\\') : null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function member(): string
|
|
||||||
{
|
|
||||||
return str_contains($this->symbol, '::') ? explode('::', $this->symbol, 2)[1] : $this->symbol;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function features(): array
|
|
||||||
{
|
|
||||||
return $this->features;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function label(): string
|
|
||||||
{
|
|
||||||
$class = $this->className();
|
|
||||||
|
|
||||||
return ($class === null ? '' : SourceFingerprint::shortName($class) . '::') . $this->member() . '()';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -5,6 +5,7 @@ declare(strict_types=1);
|
|||||||
namespace LIT\MCP\Integrations\Divi\Release;
|
namespace LIT\MCP\Integrations\Divi\Release;
|
||||||
|
|
||||||
use Closure;
|
use Closure;
|
||||||
|
use LIT\MCP\Compatibility\ManifestCheck;
|
||||||
use LIT\MCP\Integrations\Divi\Schema\DiviModules;
|
use LIT\MCP\Integrations\Divi\Schema\DiviModules;
|
||||||
use LIT\MCP\Integrations\Divi\Schema\ShortformCheck;
|
use LIT\MCP\Integrations\Divi\Schema\ShortformCheck;
|
||||||
use LIT\MCP\Integrations\WordPress\Content\ContentComposer;
|
use LIT\MCP\Integrations\WordPress\Content\ContentComposer;
|
||||||
@@ -40,7 +41,7 @@ class CompatibilityCheck
|
|||||||
public static function create(ContentComposer $composer): self
|
public static function create(ContentComposer $composer): self
|
||||||
{
|
{
|
||||||
return new self(
|
return new self(
|
||||||
new ManifestCheck(),
|
DiviManifestCheck::create(),
|
||||||
static fn (): array => DiviModules::isAvailable()
|
static fn (): array => DiviModules::isAvailable()
|
||||||
? ShortformCheck::problems((new DiviModules())->catalog())
|
? ShortformCheck::problems((new DiviModules())->catalog())
|
||||||
: ['Divi 5 ist in dieser Anfrage nicht geladen.'],
|
: ['Divi 5 ist in dieser Anfrage nicht geladen.'],
|
||||||
|
|||||||
@@ -1,148 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
declare(strict_types=1);
|
|
||||||
|
|
||||||
namespace LIT\MCP\Integrations\Divi\Release;
|
|
||||||
|
|
||||||
defined('ABSPATH') || exit;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The release state of every Divi feature (E1). A feature the constructor did not get is incompatible (fail
|
|
||||||
* closed), so of() always answers. The overall state of the matrix is its worst feature state.
|
|
||||||
*/
|
|
||||||
final class CompatibilityMatrix
|
|
||||||
{
|
|
||||||
public const MISSING = 'Für diese Fähigkeit liegt kein Prüfergebnis vor.';
|
|
||||||
|
|
||||||
/** @var array<string, FeatureStatus> keyed by DiviFeature value, in DiviFeature::cases() order */
|
|
||||||
private array $features = [];
|
|
||||||
|
|
||||||
/** @param array<string, FeatureStatus> $features keyed by DiviFeature value */
|
|
||||||
public function __construct(array $features)
|
|
||||||
{
|
|
||||||
foreach (DiviFeature::cases() as $feature) {
|
|
||||||
$status = $features[$feature->value] ?? null;
|
|
||||||
$this->features[$feature->value] = $status instanceof FeatureStatus && $status->feature === $feature
|
|
||||||
? $status
|
|
||||||
: new FeatureStatus($feature, ReleaseState::Incompatible, [self::MISSING]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static function allReleased(string $source = ReleaseStatus::SOURCE_CODE): self
|
|
||||||
{
|
|
||||||
return self::uniform(ReleaseState::Released, [], $source);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static function allIncompatible(string $problem): self
|
|
||||||
{
|
|
||||||
return self::uniform(ReleaseState::Incompatible, [$problem]);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Every feature in $state – the matrix of a status built without one (ReleaseStatus' constructor).
|
|
||||||
*
|
|
||||||
* @param list<string> $problems
|
|
||||||
*/
|
|
||||||
public static function uniform(ReleaseState $state, array $problems = [], ?string $source = null): self
|
|
||||||
{
|
|
||||||
$released = $state === ReleaseState::Released;
|
|
||||||
$features = [];
|
|
||||||
foreach (DiviFeature::cases() as $feature) {
|
|
||||||
$features[$feature->value] = new FeatureStatus(
|
|
||||||
$feature,
|
|
||||||
$state,
|
|
||||||
$released ? [] : $problems,
|
|
||||||
$released ? ($source ?? ReleaseStatus::SOURCE_CODE) : null
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
return new self($features);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function of(DiviFeature $feature): FeatureStatus
|
|
||||||
{
|
|
||||||
return $this->features[$feature->value];
|
|
||||||
}
|
|
||||||
|
|
||||||
/** @param list<DiviFeature> $features */
|
|
||||||
public function usable(array $features): bool
|
|
||||||
{
|
|
||||||
foreach ($features as $feature) {
|
|
||||||
if (! $this->of($feature)->usable()) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The statuses of those of $features that are not usable – each once, in the order of $features. The one answer
|
|
||||||
* to "what locks this call" for the gate (DiviFeatureGate), the adapters (ReleaseGate::assertFeatures()) and the
|
|
||||||
* refusal (ReleaseStatus::refusalFor()).
|
|
||||||
*
|
|
||||||
* @param list<DiviFeature> $features
|
|
||||||
* @return list<FeatureStatus>
|
|
||||||
*/
|
|
||||||
public function locked(array $features): array
|
|
||||||
{
|
|
||||||
$locked = [];
|
|
||||||
foreach ($features as $feature) {
|
|
||||||
$status = $this->of($feature);
|
|
||||||
if (! $status->usable()) {
|
|
||||||
$locked[$feature->value] = $status;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return array_values($locked);
|
|
||||||
}
|
|
||||||
|
|
||||||
/** @return list<FeatureStatus> */
|
|
||||||
public function unusable(): array
|
|
||||||
{
|
|
||||||
return array_values(array_filter(
|
|
||||||
$this->features,
|
|
||||||
static fn (FeatureStatus $status): bool => ! $status->usable()
|
|
||||||
));
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Incompatible before untested before released. */
|
|
||||||
public function state(): ReleaseState
|
|
||||||
{
|
|
||||||
$states = array_map(static fn (FeatureStatus $status): ReleaseState => $status->state, $this->features);
|
|
||||||
|
|
||||||
return match (true) {
|
|
||||||
in_array(ReleaseState::Incompatible, $states, true) => ReleaseState::Incompatible,
|
|
||||||
in_array(ReleaseState::Untested, $states, true) => ReleaseState::Untested,
|
|
||||||
default => ReleaseState::Released,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
/** The common source of a fully released matrix; null when not all released or the sources differ. */
|
|
||||||
public function source(): ?string
|
|
||||||
{
|
|
||||||
$sources = array_unique(array_map(
|
|
||||||
static fn (FeatureStatus $status): string => (string) $status->source,
|
|
||||||
$this->features
|
|
||||||
));
|
|
||||||
|
|
||||||
return $this->state() === ReleaseState::Released && count($sources) === 1 ? (string) reset($sources) : null;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** @return list<string> Every problem label once, in feature order. */
|
|
||||||
public function problems(): array
|
|
||||||
{
|
|
||||||
$problems = [];
|
|
||||||
foreach ($this->features as $status) {
|
|
||||||
$problems = array_merge($problems, $status->problems);
|
|
||||||
}
|
|
||||||
|
|
||||||
return array_values(array_unique($problems));
|
|
||||||
}
|
|
||||||
|
|
||||||
/** @return list<array{id: string, label: string, state: string, problems: list<string>, source: ?string}> */
|
|
||||||
public function toArray(): array
|
|
||||||
{
|
|
||||||
return array_values(array_map(static fn (FeatureStatus $status): array => $status->toArray(), $this->features));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -4,6 +4,8 @@ declare(strict_types=1);
|
|||||||
|
|
||||||
namespace LIT\MCP\Integrations\Divi\Release;
|
namespace LIT\MCP\Integrations\Divi\Release;
|
||||||
|
|
||||||
|
use LIT\MCP\Compatibility\Manifest;
|
||||||
|
|
||||||
defined('ABSPATH') || exit;
|
defined('ABSPATH') || exit;
|
||||||
|
|
||||||
/** A class that may touch Divi (spec §3); it lists every Divi dependency in its manifest. */
|
/** A class that may touch Divi (spec §3); it lists every Divi dependency in its manifest. */
|
||||||
|
|||||||
@@ -4,6 +4,9 @@ declare(strict_types=1);
|
|||||||
|
|
||||||
namespace LIT\MCP\Integrations\Divi\Release;
|
namespace LIT\MCP\Integrations\Divi\Release;
|
||||||
|
|
||||||
|
use LIT\MCP\Compatibility\Call;
|
||||||
|
use LIT\MCP\Compatibility\Manifest;
|
||||||
|
use LIT\MCP\Compatibility\Mirror;
|
||||||
use LIT\MCP\Integrations\Divi\Design\DesignSystemReader;
|
use LIT\MCP\Integrations\Divi\Design\DesignSystemReader;
|
||||||
use LIT\MCP\Integrations\Divi\Design\DesignSystemWriter;
|
use LIT\MCP\Integrations\Divi\Design\DesignSystemWriter;
|
||||||
use LIT\MCP\Integrations\Divi\Design\FontCatalog;
|
use LIT\MCP\Integrations\Divi\Design\FontCatalog;
|
||||||
|
|||||||
@@ -0,0 +1,17 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace LIT\MCP\Integrations\Divi\Release;
|
||||||
|
|
||||||
|
defined('ABSPATH') || exit;
|
||||||
|
|
||||||
|
/** The five Divi areas of spec §3. Each value is the prefix of the labels in the admin check. */
|
||||||
|
final class DiviAreas
|
||||||
|
{
|
||||||
|
public const PAGES = 'Seiten';
|
||||||
|
public const LIBRARY = 'Bibliothek';
|
||||||
|
public const THEME_BUILDER = 'Theme Builder';
|
||||||
|
public const DESIGN = 'Designsystem';
|
||||||
|
public const CATALOG = 'Katalog';
|
||||||
|
}
|
||||||
@@ -8,6 +8,7 @@ use LIT\MCP\Abilities\Ability;
|
|||||||
use LIT\MCP\Abilities\AbilityGuard;
|
use LIT\MCP\Abilities\AbilityGuard;
|
||||||
use LIT\MCP\Abilities\Errors;
|
use LIT\MCP\Abilities\Errors;
|
||||||
use LIT\MCP\ChangeLog\ChangeLog;
|
use LIT\MCP\ChangeLog\ChangeLog;
|
||||||
|
use LIT\MCP\Compatibility\ReleaseState;
|
||||||
use WP_Error;
|
use WP_Error;
|
||||||
|
|
||||||
defined('ABSPATH') || exit;
|
defined('ABSPATH') || exit;
|
||||||
|
|||||||
@@ -0,0 +1,35 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace LIT\MCP\Integrations\Divi\Release;
|
||||||
|
|
||||||
|
use LIT\MCP\Compatibility\ManifestCheck;
|
||||||
|
use LIT\MCP\Compatibility\Mirror;
|
||||||
|
use LIT\MCP\Compatibility\SourceFingerprint;
|
||||||
|
use LIT\MCP\Integrations\Divi\Schema\DiviModules;
|
||||||
|
|
||||||
|
defined('ABSPATH') || exit;
|
||||||
|
|
||||||
|
/** The ManifestCheck of Divi: its adapter manifests, signature references, theme sources and block registry. */
|
||||||
|
final class DiviManifestCheck
|
||||||
|
{
|
||||||
|
public static function create(): ManifestCheck
|
||||||
|
{
|
||||||
|
return new ManifestCheck(
|
||||||
|
DiviAdapters::manifests(),
|
||||||
|
DiviReference::expected(),
|
||||||
|
self::installed(...),
|
||||||
|
DiviModules::knowsBlock(...)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static function installed(Mirror $mirror): ?string
|
||||||
|
{
|
||||||
|
$dir = DiviEnvironment::themeDir();
|
||||||
|
|
||||||
|
return $dir === null
|
||||||
|
? null
|
||||||
|
: SourceFingerprint::of($dir . '/' . $mirror->file, $mirror->function, $mirror->class)->hash;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -4,6 +4,9 @@ declare(strict_types=1);
|
|||||||
|
|
||||||
namespace LIT\MCP\Integrations\Divi\Release;
|
namespace LIT\MCP\Integrations\Divi\Release;
|
||||||
|
|
||||||
|
use LIT\MCP\Compatibility\Call;
|
||||||
|
use LIT\MCP\Compatibility\SignatureFingerprint;
|
||||||
|
use LIT\MCP\Compatibility\SourceFingerprint;
|
||||||
use RuntimeException;
|
use RuntimeException;
|
||||||
|
|
||||||
defined('ABSPATH') || exit;
|
defined('ABSPATH') || exit;
|
||||||
@@ -18,8 +21,7 @@ final class DiviReference
|
|||||||
{
|
{
|
||||||
public const FILE = __DIR__ . '/fingerprints.json';
|
public const FILE = __DIR__ . '/fingerprints.json';
|
||||||
|
|
||||||
/** Key prefix of the signature fingerprints; no mirror ID starts with it. */
|
public const SIGNATURE_PREFIX = Call::SIGNATURE_PREFIX;
|
||||||
public const SIGNATURE_PREFIX = 'sig:';
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return array<string, string> Mirror ID or "sig:<symbol>" => sha256, sorted by key; [] when the file is
|
* @return array<string, string> Mirror ID or "sig:<symbol>" => sha256, sorted by key; [] when the file is
|
||||||
@@ -61,12 +63,6 @@ final class DiviReference
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** The key of $call's signature fingerprint: "sig:" and the symbol without a leading backslash. */
|
|
||||||
public static function signatureKey(Call $call): string
|
|
||||||
{
|
|
||||||
return self::SIGNATURE_PREFIX . ltrim($call->symbol, '\\');
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Signature fingerprints of the calls in the running PHP process (Divi loaded).
|
* Signature fingerprints of the calls in the running PHP process (Divi loaded).
|
||||||
*
|
*
|
||||||
@@ -82,7 +78,7 @@ final class DiviReference
|
|||||||
if ($hash === null) {
|
if ($hash === null) {
|
||||||
throw new RuntimeException(sprintf('signature of %s: symbol is not loaded', $call->label()));
|
throw new RuntimeException(sprintf('signature of %s: symbol is not loaded', $call->label()));
|
||||||
}
|
}
|
||||||
$signatures[self::signatureKey($call)] = $hash;
|
$signatures[$call->signatureKey()] = $hash;
|
||||||
}
|
}
|
||||||
ksort($signatures);
|
ksort($signatures);
|
||||||
|
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ namespace LIT\MCP\Integrations\Divi\Release;
|
|||||||
|
|
||||||
use Closure;
|
use Closure;
|
||||||
use LIT\MCP\Abilities\Ability;
|
use LIT\MCP\Abilities\Ability;
|
||||||
|
use LIT\MCP\Compatibility\CompatibilityMatrix;
|
||||||
|
|
||||||
defined('ABSPATH') || exit;
|
defined('ABSPATH') || exit;
|
||||||
|
|
||||||
|
|||||||
@@ -1,46 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
declare(strict_types=1);
|
|
||||||
|
|
||||||
namespace LIT\MCP\Integrations\Divi\Release;
|
|
||||||
|
|
||||||
defined('ABSPATH') || exit;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A Divi function whose storage logic an adapter repeats instead of calling it (spec §4.1 "mirrors"). Its
|
|
||||||
* fingerprint (SourceFingerprint) must match the one in fingerprints.json, else Divi changed what we copy.
|
|
||||||
*/
|
|
||||||
final class Mirror implements Requirement
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* @param string $id Key in fingerprints.json and name of tests/Fixtures/divi/reference/<id>.txt.
|
|
||||||
* @param string $file Divi file, relative to the Divi theme directory.
|
|
||||||
* @param string $function Function or method name.
|
|
||||||
* @param string|null $class Class of a method – the short name is enough (the file fixes where it
|
|
||||||
* lives, and a short name is no Divi name for DiviBoundaryTest); null for a
|
|
||||||
* function.
|
|
||||||
* @param string $what What the plugin repeats (German, for reports).
|
|
||||||
* @param list<DiviFeature> $features [] = the default of the manifest.
|
|
||||||
*/
|
|
||||||
public function __construct(
|
|
||||||
public readonly string $id,
|
|
||||||
public readonly string $file,
|
|
||||||
public readonly string $function,
|
|
||||||
public readonly ?string $class,
|
|
||||||
public readonly string $what,
|
|
||||||
private readonly array $features = []
|
|
||||||
) {
|
|
||||||
}
|
|
||||||
|
|
||||||
public function features(): array
|
|
||||||
{
|
|
||||||
return $this->features;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function label(): string
|
|
||||||
{
|
|
||||||
$class = $this->class === null ? '' : SourceFingerprint::shortName($this->class) . '::';
|
|
||||||
|
|
||||||
return $class . $this->function . '()';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -5,6 +5,9 @@ declare(strict_types=1);
|
|||||||
namespace LIT\MCP\Integrations\Divi\Release;
|
namespace LIT\MCP\Integrations\Divi\Release;
|
||||||
|
|
||||||
use Closure;
|
use Closure;
|
||||||
|
use LIT\MCP\Compatibility\Capability;
|
||||||
|
use LIT\MCP\Compatibility\CompatibilityMatrix;
|
||||||
|
use LIT\MCP\Compatibility\FeatureStatus;
|
||||||
use LIT\MCP\Log;
|
use LIT\MCP\Log;
|
||||||
use Throwable;
|
use Throwable;
|
||||||
|
|
||||||
@@ -37,7 +40,10 @@ final class ReleaseGate
|
|||||||
self::$status = (self::$resolver ?? static fn (): ReleaseStatus => (new ReleaseResolver())->resolve())();
|
self::$status = (self::$resolver ?? static fn (): ReleaseStatus => (new ReleaseResolver())->resolve())();
|
||||||
} catch (Throwable $e) {
|
} catch (Throwable $e) {
|
||||||
Log::failure('divi release status', $e);
|
Log::failure('divi release status', $e);
|
||||||
self::$status = ReleaseStatus::of('', CompatibilityMatrix::allIncompatible(self::UNRESOLVED));
|
self::$status = ReleaseStatus::of(
|
||||||
|
'',
|
||||||
|
CompatibilityMatrix::allIncompatible(DiviFeature::cases(), self::UNRESOLVED)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
return self::$status;
|
return self::$status;
|
||||||
@@ -107,11 +113,17 @@ final class ReleaseGate
|
|||||||
{
|
{
|
||||||
$status = self::status();
|
$status = self::status();
|
||||||
$locked = $status->matrix->locked($features);
|
$locked = $status->matrix->locked($features);
|
||||||
|
if ($locked === []) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
return $locked === [] ? null : new DiviLocked(
|
$named = array_values(array_filter(
|
||||||
$status,
|
array_map(static fn (FeatureStatus $feature): Capability => $feature->feature, $locked),
|
||||||
array_map(static fn (FeatureStatus $feature): DiviFeature => $feature->feature, $locked)
|
static fn (Capability $capability): bool => $capability instanceof DiviFeature
|
||||||
);
|
));
|
||||||
|
|
||||||
|
// Fail closed: the lock stays; without a DiviFeature among its capabilities it names the features asked for.
|
||||||
|
return new DiviLocked($status, $named === [] ? $features : $named);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function whileProbing(int $postId, callable $write): mixed
|
public static function whileProbing(int $postId, callable $write): mixed
|
||||||
|
|||||||
@@ -5,6 +5,9 @@ declare(strict_types=1);
|
|||||||
namespace LIT\MCP\Integrations\Divi\Release;
|
namespace LIT\MCP\Integrations\Divi\Release;
|
||||||
|
|
||||||
use Closure;
|
use Closure;
|
||||||
|
use LIT\MCP\Compatibility\CompatibilityMatrix;
|
||||||
|
use LIT\MCP\Compatibility\ManifestCheck;
|
||||||
|
use LIT\MCP\Compatibility\Problem;
|
||||||
use LIT\MCP\Plugin;
|
use LIT\MCP\Plugin;
|
||||||
|
|
||||||
defined('ABSPATH') || exit;
|
defined('ABSPATH') || exit;
|
||||||
@@ -44,15 +47,19 @@ final class ReleaseResolver
|
|||||||
public function resolve(): ReleaseStatus
|
public function resolve(): ReleaseStatus
|
||||||
{
|
{
|
||||||
$version = ($this->version ?? DiviEnvironment::version(...))() ?? '';
|
$version = ($this->version ?? DiviEnvironment::version(...))() ?? '';
|
||||||
$check = $this->check ?? new ManifestCheck();
|
$check = $this->check ?? DiviManifestCheck::create();
|
||||||
$problems = array_merge($check->codeProblems(), $this->mirrorProblems($check, $version));
|
$problems = array_merge($check->codeProblems(), $this->mirrorProblems($check, $version));
|
||||||
|
|
||||||
if (in_array($version, DiviReleases::TESTED, true)) {
|
if (in_array($version, DiviReleases::TESTED, true)) {
|
||||||
return ReleaseStatus::of($version, self::matrix($problems, ReleaseStatus::SOURCE_CODE, false));
|
return ReleaseStatus::of($version, self::matrix($problems, CompatibilityMatrix::SOURCE_CODE, false));
|
||||||
}
|
}
|
||||||
$entry = $version === '' ? null : ($this->store ?? new ReleaseStore())->find($version, Plugin::VERSION);
|
$entry = $version === '' ? null : ($this->store ?? new ReleaseStore())->find($version, Plugin::VERSION);
|
||||||
if ($entry !== null) {
|
if ($entry !== null) {
|
||||||
return ReleaseStatus::of($version, self::matrix($problems, ReleaseStatus::SOURCE_DATABASE, false), $entry);
|
return ReleaseStatus::of(
|
||||||
|
$version,
|
||||||
|
self::matrix($problems, CompatibilityMatrix::SOURCE_DATABASE, false),
|
||||||
|
$entry
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
return ReleaseStatus::of($version, self::matrix($problems, null, $version !== '' && self::automatic()));
|
return ReleaseStatus::of($version, self::matrix($problems, null, $version !== '' && self::automatic()));
|
||||||
@@ -81,60 +88,10 @@ final class ReleaseResolver
|
|||||||
return apply_filters(self::AUTO_RELEASE_FILTER, true) === true;
|
return apply_filters(self::AUTO_RELEASE_FILTER, true) === true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/** @param list<Problem> $problems */
|
||||||
* @param list<Problem> $problems
|
|
||||||
* @param string|null $source SOURCE_CODE or SOURCE_DATABASE for a released version, else null.
|
|
||||||
* @param bool $automatic The automatic release applies (no release, known version, filter on).
|
|
||||||
*/
|
|
||||||
private static function matrix(array $problems, ?string $source, bool $automatic): CompatibilityMatrix
|
private static function matrix(array $problems, ?string $source, bool $automatic): CompatibilityMatrix
|
||||||
{
|
{
|
||||||
$features = [];
|
return CompatibilityMatrix::fromProblems(DiviFeature::cases(), $problems, $source, $automatic);
|
||||||
foreach (DiviFeature::cases() as $feature) {
|
|
||||||
$concerning = array_values(array_filter(
|
|
||||||
$problems,
|
|
||||||
static fn (Problem $problem): bool => $problem->concerns($feature)
|
|
||||||
));
|
|
||||||
$features[$feature->value] = self::feature($feature, $concerning, $source, $automatic);
|
|
||||||
}
|
|
||||||
|
|
||||||
return new CompatibilityMatrix($features);
|
|
||||||
}
|
|
||||||
|
|
||||||
/** @param list<Problem> $problems The problems concerning $feature. */
|
|
||||||
private static function feature(
|
|
||||||
DiviFeature $feature,
|
|
||||||
array $problems,
|
|
||||||
?string $source,
|
|
||||||
bool $automatic
|
|
||||||
): FeatureStatus {
|
|
||||||
$hard = array_filter($problems, static fn (Problem $problem): bool => $problem->isHard());
|
|
||||||
if ($hard !== []) {
|
|
||||||
return new FeatureStatus($feature, ReleaseState::Incompatible, self::labels($hard));
|
|
||||||
}
|
|
||||||
if ($source !== null) {
|
|
||||||
return new FeatureStatus($feature, ReleaseState::Released, [], $source);
|
|
||||||
}
|
|
||||||
if (! $automatic) {
|
|
||||||
return new FeatureStatus($feature, ReleaseState::Untested, self::labels($problems));
|
|
||||||
}
|
|
||||||
|
|
||||||
$changed = array_filter($problems, static fn (Problem $problem): bool => $problem->kind === Problem::SIGNATURE);
|
|
||||||
if ($changed !== []) {
|
|
||||||
return new FeatureStatus($feature, ReleaseState::Incompatible, self::labels($changed));
|
|
||||||
}
|
|
||||||
|
|
||||||
return $problems === []
|
|
||||||
? new FeatureStatus($feature, ReleaseState::Released, [], ReleaseStatus::SOURCE_AUTO)
|
|
||||||
: new FeatureStatus($feature, ReleaseState::Untested, self::labels($problems));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param array<int, Problem> $problems
|
|
||||||
* @return list<string>
|
|
||||||
*/
|
|
||||||
private static function labels(array $problems): array
|
|
||||||
{
|
|
||||||
return array_values(array_map(static fn (Problem $problem): string => $problem->label, $problems));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @return list<Problem> */
|
/** @return list<Problem> */
|
||||||
@@ -174,7 +131,7 @@ final class ReleaseResolver
|
|||||||
|
|
||||||
$problems = [];
|
$problems = [];
|
||||||
foreach ($entry['problems'] as $row) {
|
foreach ($entry['problems'] as $row) {
|
||||||
$problem = Problem::fromArray($row);
|
$problem = Problem::fromArray($row, DiviFeature::tryFrom(...));
|
||||||
if ($problem === null) {
|
if ($problem === null) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,6 +5,9 @@ declare(strict_types=1);
|
|||||||
namespace LIT\MCP\Integrations\Divi\Release;
|
namespace LIT\MCP\Integrations\Divi\Release;
|
||||||
|
|
||||||
use LIT\MCP\Abilities\Errors;
|
use LIT\MCP\Abilities\Errors;
|
||||||
|
use LIT\MCP\Compatibility\CompatibilityMatrix;
|
||||||
|
use LIT\MCP\Compatibility\FeatureStatus;
|
||||||
|
use LIT\MCP\Compatibility\ReleaseState;
|
||||||
use LogicException;
|
use LogicException;
|
||||||
use WP_Error;
|
use WP_Error;
|
||||||
|
|
||||||
@@ -16,9 +19,9 @@ defined('ABSPATH') || exit;
|
|||||||
*/
|
*/
|
||||||
final class ReleaseStatus
|
final class ReleaseStatus
|
||||||
{
|
{
|
||||||
public const SOURCE_CODE = 'code';
|
public const SOURCE_CODE = CompatibilityMatrix::SOURCE_CODE;
|
||||||
public const SOURCE_DATABASE = 'database';
|
public const SOURCE_DATABASE = CompatibilityMatrix::SOURCE_DATABASE;
|
||||||
public const SOURCE_AUTO = 'auto';
|
public const SOURCE_AUTO = CompatibilityMatrix::SOURCE_AUTO;
|
||||||
|
|
||||||
private const FEATURE_UNTESTED = 'Achtung: %1$s ist auf dieser Website für %2$s noch nicht für LIT MCP '
|
private const FEATURE_UNTESTED = 'Achtung: %1$s ist auf dieser Website für %2$s noch nicht für LIT MCP '
|
||||||
. 'freigegeben. Das ist gesperrt, bis ein Administrator unter Einstellungen → LIT MCP → Divi die Prüfung '
|
. 'freigegeben. Das ist gesperrt, bis ein Administrator unter Einstellungen → LIT MCP → Divi die Prüfung '
|
||||||
@@ -52,7 +55,7 @@ final class ReleaseStatus
|
|||||||
if ($matrix !== null && $matrix->state() !== $state) {
|
if ($matrix !== null && $matrix->state() !== $state) {
|
||||||
throw new LogicException('the matrix is ' . $matrix->state()->value . ', not ' . $state->value);
|
throw new LogicException('the matrix is ' . $matrix->state()->value . ', not ' . $state->value);
|
||||||
}
|
}
|
||||||
$this->matrix = $matrix ?? CompatibilityMatrix::uniform($state, $problems, $source);
|
$this->matrix = $matrix ?? CompatibilityMatrix::uniform(DiviFeature::cases(), $state, $problems, $source);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @param array<string, mixed>|null $release The database entry of a SOURCE_DATABASE release. */
|
/** @param array<string, mixed>|null $release The database entry of a SOURCE_DATABASE release. */
|
||||||
|
|||||||
@@ -7,10 +7,11 @@ namespace LIT\MCP\Integrations\Divi\Schema;
|
|||||||
use ET\Builder\Packages\ModuleLibrary\ModuleRegistration;
|
use ET\Builder\Packages\ModuleLibrary\ModuleRegistration;
|
||||||
use LIT\MCP\Integrations\Divi\BlockTree\GlobalInstance;
|
use LIT\MCP\Integrations\Divi\BlockTree\GlobalInstance;
|
||||||
use LIT\MCP\Integrations\Divi\Library\DiviLibraryStore;
|
use LIT\MCP\Integrations\Divi\Library\DiviLibraryStore;
|
||||||
use LIT\MCP\Integrations\Divi\Release\Call;
|
use LIT\MCP\Compatibility\Call;
|
||||||
use LIT\MCP\Integrations\Divi\Release\DiviAdapter;
|
use LIT\MCP\Integrations\Divi\Release\DiviAdapter;
|
||||||
|
use LIT\MCP\Integrations\Divi\Release\DiviAreas;
|
||||||
use LIT\MCP\Integrations\Divi\Release\DiviFeature;
|
use LIT\MCP\Integrations\Divi\Release\DiviFeature;
|
||||||
use LIT\MCP\Integrations\Divi\Release\Manifest;
|
use LIT\MCP\Compatibility\Manifest;
|
||||||
use LIT\MCP\Integrations\Divi\ThemeBuilder\DiviThemeBuilder;
|
use LIT\MCP\Integrations\Divi\ThemeBuilder\DiviThemeBuilder;
|
||||||
|
|
||||||
defined('ABSPATH') || exit;
|
defined('ABSPATH') || exit;
|
||||||
@@ -39,7 +40,7 @@ class DiviModules implements DiviAdapter
|
|||||||
public static function manifest(): Manifest
|
public static function manifest(): Manifest
|
||||||
{
|
{
|
||||||
return new Manifest(
|
return new Manifest(
|
||||||
Manifest::CATALOG,
|
DiviAreas::CATALOG,
|
||||||
calls: [
|
calls: [
|
||||||
new Call(ModuleRegistration::class . '::get_all_core_modules_metadata', 0),
|
new Call(ModuleRegistration::class . '::get_all_core_modules_metadata', 0),
|
||||||
new Call(ModuleRegistration::class . '::get_default_attrs', 2),
|
new Call(ModuleRegistration::class . '::get_default_attrs', 2),
|
||||||
|
|||||||
@@ -4,12 +4,13 @@ declare(strict_types=1);
|
|||||||
|
|
||||||
namespace LIT\MCP\Integrations\Divi\ThemeBuilder;
|
namespace LIT\MCP\Integrations\Divi\ThemeBuilder;
|
||||||
|
|
||||||
use LIT\MCP\Integrations\Divi\Release\Call;
|
use LIT\MCP\Compatibility\Call;
|
||||||
use LIT\MCP\Integrations\Divi\Release\DiviAdapter;
|
use LIT\MCP\Integrations\Divi\Release\DiviAdapter;
|
||||||
|
use LIT\MCP\Integrations\Divi\Release\DiviAreas;
|
||||||
use LIT\MCP\Integrations\Divi\Release\DiviFeature;
|
use LIT\MCP\Integrations\Divi\Release\DiviFeature;
|
||||||
use LIT\MCP\Integrations\Divi\Release\DiviLocked;
|
use LIT\MCP\Integrations\Divi\Release\DiviLocked;
|
||||||
use LIT\MCP\Integrations\Divi\Release\Manifest;
|
use LIT\MCP\Compatibility\Manifest;
|
||||||
use LIT\MCP\Integrations\Divi\Release\Mirror;
|
use LIT\MCP\Compatibility\Mirror;
|
||||||
use LIT\MCP\Integrations\Divi\Release\ReleaseGate;
|
use LIT\MCP\Integrations\Divi\Release\ReleaseGate;
|
||||||
use RuntimeException;
|
use RuntimeException;
|
||||||
use Throwable;
|
use Throwable;
|
||||||
@@ -83,7 +84,7 @@ class DiviThemeBuilder implements DiviAdapter
|
|||||||
$dir = 'includes/builder/frontend-builder/theme-builder/';
|
$dir = 'includes/builder/frontend-builder/theme-builder/';
|
||||||
|
|
||||||
return new Manifest(
|
return new Manifest(
|
||||||
Manifest::THEME_BUILDER,
|
DiviAreas::THEME_BUILDER,
|
||||||
calls: [
|
calls: [
|
||||||
// liveId(): reads the live post, or creates it like Divi's first save.
|
// liveId(): reads the live post, or creates it like Divi's first save.
|
||||||
new Call(
|
new Call(
|
||||||
|
|||||||
@@ -4,11 +4,11 @@ declare(strict_types=1);
|
|||||||
|
|
||||||
namespace LIT\MCP\Tests\Support;
|
namespace LIT\MCP\Tests\Support;
|
||||||
|
|
||||||
use LIT\MCP\Integrations\Divi\Release\CompatibilityMatrix;
|
use LIT\MCP\Compatibility\ReleaseState;
|
||||||
|
use LIT\MCP\Compatibility\CompatibilityMatrix;
|
||||||
use LIT\MCP\Integrations\Divi\Release\DiviFeature;
|
use LIT\MCP\Integrations\Divi\Release\DiviFeature;
|
||||||
use LIT\MCP\Integrations\Divi\Release\FeatureStatus;
|
use LIT\MCP\Compatibility\FeatureStatus;
|
||||||
use LIT\MCP\Integrations\Divi\Release\ReleaseGate;
|
use LIT\MCP\Integrations\Divi\Release\ReleaseGate;
|
||||||
use LIT\MCP\Integrations\Divi\Release\ReleaseState;
|
|
||||||
use LIT\MCP\Integrations\Divi\Release\ReleaseStatus;
|
use LIT\MCP\Integrations\Divi\Release\ReleaseStatus;
|
||||||
|
|
||||||
/** A release status in which single Divi capabilities are locked – for guard and tool tests. */
|
/** A release status in which single Divi capabilities are locked – for guard and tool tests. */
|
||||||
@@ -37,7 +37,7 @@ final class DiviFeatureFixtures
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$status = new ReleaseStatus($overall, $version, null, [], null, matrix: new CompatibilityMatrix($features));
|
$status = new ReleaseStatus($overall, $version, null, [], null, matrix: new CompatibilityMatrix(DiviFeature::cases(), $features));
|
||||||
ReleaseGate::useResolver(static fn (): ReleaseStatus => $status);
|
ReleaseGate::useResolver(static fn (): ReleaseStatus => $status);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -4,10 +4,10 @@ declare(strict_types=1);
|
|||||||
|
|
||||||
namespace LIT\MCP\Tests\Support;
|
namespace LIT\MCP\Tests\Support;
|
||||||
|
|
||||||
use LIT\MCP\Integrations\Divi\Release\CompatibilityMatrix;
|
use LIT\MCP\Compatibility\ReleaseState;
|
||||||
|
use LIT\MCP\Compatibility\CompatibilityMatrix;
|
||||||
use LIT\MCP\Integrations\Divi\Release\DiviFeature;
|
use LIT\MCP\Integrations\Divi\Release\DiviFeature;
|
||||||
use LIT\MCP\Integrations\Divi\Release\FeatureStatus;
|
use LIT\MCP\Compatibility\FeatureStatus;
|
||||||
use LIT\MCP\Integrations\Divi\Release\ReleaseState;
|
|
||||||
|
|
||||||
/** Compatibility matrices for tests: every feature released, with single features replaced. */
|
/** Compatibility matrices for tests: every feature released, with single features replaced. */
|
||||||
final class MatrixFixtures
|
final class MatrixFixtures
|
||||||
@@ -22,10 +22,10 @@ final class MatrixFixtures
|
|||||||
$features[$feature->value] = new FeatureStatus($feature, ReleaseState::Released, [], $source);
|
$features[$feature->value] = new FeatureStatus($feature, ReleaseState::Released, [], $source);
|
||||||
}
|
}
|
||||||
foreach ($replace as $status) {
|
foreach ($replace as $status) {
|
||||||
$features[$status->feature->value] = $status;
|
$features[$status->feature->id()] = $status;
|
||||||
}
|
}
|
||||||
|
|
||||||
return new CompatibilityMatrix($features);
|
return new CompatibilityMatrix(DiviFeature::cases(), $features);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @param string ...$problems */
|
/** @param string ...$problems */
|
||||||
|
|||||||
@@ -4,10 +4,10 @@ declare(strict_types=1);
|
|||||||
|
|
||||||
namespace LIT\MCP\Tests\Support;
|
namespace LIT\MCP\Tests\Support;
|
||||||
|
|
||||||
use LIT\MCP\Integrations\Divi\Release\CompatibilityMatrix;
|
use LIT\MCP\Compatibility\ReleaseState;
|
||||||
|
use LIT\MCP\Compatibility\CompatibilityMatrix;
|
||||||
use LIT\MCP\Integrations\Divi\Release\DiviFeature;
|
use LIT\MCP\Integrations\Divi\Release\DiviFeature;
|
||||||
use LIT\MCP\Integrations\Divi\Release\FeatureStatus;
|
use LIT\MCP\Compatibility\FeatureStatus;
|
||||||
use LIT\MCP\Integrations\Divi\Release\ReleaseState;
|
|
||||||
use LIT\MCP\Integrations\Divi\Release\ReleaseStatus;
|
use LIT\MCP\Integrations\Divi\Release\ReleaseStatus;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -30,7 +30,7 @@ final class ReleaseMatrices
|
|||||||
: new FeatureStatus($feature, ReleaseState::Released, [], ReleaseStatus::SOURCE_CODE);
|
: new FeatureStatus($feature, ReleaseState::Released, [], ReleaseStatus::SOURCE_CODE);
|
||||||
}
|
}
|
||||||
|
|
||||||
return new CompatibilityMatrix($features);
|
return new CompatibilityMatrix(DiviFeature::cases(), $features);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @param list<DiviFeature> $locked */
|
/** @param list<DiviFeature> $locked */
|
||||||
@@ -52,7 +52,7 @@ final class ReleaseMatrices
|
|||||||
string $source = ReleaseStatus::SOURCE_CODE,
|
string $source = ReleaseStatus::SOURCE_CODE,
|
||||||
?array $release = null
|
?array $release = null
|
||||||
): ReleaseStatus {
|
): ReleaseStatus {
|
||||||
return ReleaseStatus::of($version, CompatibilityMatrix::allReleased($source), $release);
|
return ReleaseStatus::of($version, CompatibilityMatrix::allReleased(DiviFeature::cases(), $source), $release);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -62,6 +62,6 @@ final class ReleaseMatrices
|
|||||||
*/
|
*/
|
||||||
public static function uniform(ReleaseState $state, string $version = '5.3.0', array $problems = []): ReleaseStatus
|
public static function uniform(ReleaseState $state, string $version = '5.3.0', array $problems = []): ReleaseStatus
|
||||||
{
|
{
|
||||||
return ReleaseStatus::of($version, CompatibilityMatrix::uniform($state, $problems));
|
return ReleaseStatus::of($version, CompatibilityMatrix::uniform(DiviFeature::cases(), $state, $problems));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,11 +12,11 @@ use LIT\MCP\Abilities\Errors;
|
|||||||
use LIT\MCP\Abilities\ExposurePolicy;
|
use LIT\MCP\Abilities\ExposurePolicy;
|
||||||
use LIT\MCP\Abilities\ToolRefusal;
|
use LIT\MCP\Abilities\ToolRefusal;
|
||||||
use LIT\MCP\Abilities\WriteFailed;
|
use LIT\MCP\Abilities\WriteFailed;
|
||||||
|
use LIT\MCP\Compatibility\ReleaseState;
|
||||||
use LIT\MCP\Integrations\Divi\Release\DiviFeature;
|
use LIT\MCP\Integrations\Divi\Release\DiviFeature;
|
||||||
use LIT\MCP\Integrations\Divi\Release\DiviFeatureGate;
|
use LIT\MCP\Integrations\Divi\Release\DiviFeatureGate;
|
||||||
use LIT\MCP\Integrations\Divi\Release\DiviLocked;
|
use LIT\MCP\Integrations\Divi\Release\DiviLocked;
|
||||||
use LIT\MCP\Integrations\Divi\Release\ReleaseGate;
|
use LIT\MCP\Integrations\Divi\Release\ReleaseGate;
|
||||||
use LIT\MCP\Integrations\Divi\Release\ReleaseState;
|
|
||||||
use LIT\MCP\Integrations\Divi\Release\RequiresDiviFeatures;
|
use LIT\MCP\Integrations\Divi\Release\RequiresDiviFeatures;
|
||||||
use LIT\MCP\Integrations\Integration;
|
use LIT\MCP\Integrations\Integration;
|
||||||
use LIT\MCP\Integrations\IntegrationRegistry;
|
use LIT\MCP\Integrations\IntegrationRegistry;
|
||||||
|
|||||||
@@ -24,6 +24,7 @@ final class CoreIndependenceTest extends TestCase
|
|||||||
'Admin',
|
'Admin',
|
||||||
'ChangeLog',
|
'ChangeLog',
|
||||||
'Cli',
|
'Cli',
|
||||||
|
'Compatibility',
|
||||||
'Guides',
|
'Guides',
|
||||||
'Integrations/Core',
|
'Integrations/Core',
|
||||||
'Integrations/Media',
|
'Integrations/Media',
|
||||||
|
|||||||
@@ -0,0 +1,52 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace LIT\MCP\Tests\Unit\Compatibility;
|
||||||
|
|
||||||
|
use LIT\MCP\Compatibility\Call;
|
||||||
|
use PHPUnit\Framework\TestCase;
|
||||||
|
|
||||||
|
final class CallTest extends TestCase
|
||||||
|
{
|
||||||
|
public static function sample(int $a, int $b = 0): void
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
private static function method(): string
|
||||||
|
{
|
||||||
|
return self::class . '::sample';
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testAcceptsAnExistingFunctionWithAMatchingArgumentCount(): void
|
||||||
|
{
|
||||||
|
self::assertTrue((new Call('strlen', 1))->accepts());
|
||||||
|
self::assertTrue((new Call('sprintf', 5))->accepts(), 'variadic');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testRejectsAnArgumentCountThePlatformFunctionDoesNotTake(): void
|
||||||
|
{
|
||||||
|
self::assertFalse((new Call('strlen', 2))->accepts(), 'strlen takes one argument');
|
||||||
|
self::assertFalse((new Call('str_replace', 2))->accepts(), 'str_replace needs three');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testNullArgumentCountOnlyChecksExistence(): void
|
||||||
|
{
|
||||||
|
self::assertTrue((new Call('str_replace'))->accepts());
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testMissingFunctionOrMethodIsRejected(): void
|
||||||
|
{
|
||||||
|
self::assertFalse((new Call('lit_mcp_missing_function'))->accepts());
|
||||||
|
self::assertFalse((new Call(self::class . '::missing'))->accepts());
|
||||||
|
self::assertFalse((new Call('Lit\Missing\Klass::method'))->accepts());
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testChecksTheArgumentCountOfAMethod(): void
|
||||||
|
{
|
||||||
|
self::assertTrue((new Call(self::method(), 1))->accepts());
|
||||||
|
self::assertTrue((new Call(self::method(), 2))->accepts());
|
||||||
|
self::assertFalse((new Call(self::method(), 0))->accepts(), 'one required');
|
||||||
|
self::assertFalse((new Call(self::method(), 3))->accepts(), 'at most two');
|
||||||
|
}
|
||||||
|
}
|
||||||
+101
-10
@@ -2,12 +2,14 @@
|
|||||||
|
|
||||||
declare(strict_types=1);
|
declare(strict_types=1);
|
||||||
|
|
||||||
namespace LIT\MCP\Tests\Unit\Integrations\Divi\Release;
|
namespace LIT\MCP\Tests\Unit\Compatibility;
|
||||||
|
|
||||||
use LIT\MCP\Integrations\Divi\Release\CompatibilityMatrix;
|
use LIT\MCP\Compatibility\Capability;
|
||||||
|
use LIT\MCP\Compatibility\CompatibilityMatrix;
|
||||||
|
use LIT\MCP\Compatibility\FeatureStatus;
|
||||||
|
use LIT\MCP\Compatibility\Problem;
|
||||||
|
use LIT\MCP\Compatibility\ReleaseState;
|
||||||
use LIT\MCP\Integrations\Divi\Release\DiviFeature;
|
use LIT\MCP\Integrations\Divi\Release\DiviFeature;
|
||||||
use LIT\MCP\Integrations\Divi\Release\FeatureStatus;
|
|
||||||
use LIT\MCP\Integrations\Divi\Release\ReleaseState;
|
|
||||||
use LIT\MCP\Tests\Support\ReleaseMatrices;
|
use LIT\MCP\Tests\Support\ReleaseMatrices;
|
||||||
use PHPUnit\Framework\TestCase;
|
use PHPUnit\Framework\TestCase;
|
||||||
|
|
||||||
@@ -15,7 +17,7 @@ final class CompatibilityMatrixTest extends TestCase
|
|||||||
{
|
{
|
||||||
public function testAFeatureWithoutResultIsIncompatible(): void
|
public function testAFeatureWithoutResultIsIncompatible(): void
|
||||||
{
|
{
|
||||||
$matrix = new CompatibilityMatrix([
|
$matrix = new CompatibilityMatrix(DiviFeature::cases(), [
|
||||||
'page-read' => new FeatureStatus(DiviFeature::PageRead, ReleaseState::Released, [], 'code'),
|
'page-read' => new FeatureStatus(DiviFeature::PageRead, ReleaseState::Released, [], 'code'),
|
||||||
// Under the wrong key: does not count for page-write.
|
// Under the wrong key: does not count for page-write.
|
||||||
'page-write' => new FeatureStatus(DiviFeature::PageRead, ReleaseState::Released, [], 'code'),
|
'page-write' => new FeatureStatus(DiviFeature::PageRead, ReleaseState::Released, [], 'code'),
|
||||||
@@ -32,8 +34,8 @@ final class CompatibilityMatrixTest extends TestCase
|
|||||||
|
|
||||||
public function testAllReleasedAndAllIncompatible(): void
|
public function testAllReleasedAndAllIncompatible(): void
|
||||||
{
|
{
|
||||||
$released = CompatibilityMatrix::allReleased('database');
|
$released = CompatibilityMatrix::allReleased(DiviFeature::cases(), 'database');
|
||||||
$broken = CompatibilityMatrix::allIncompatible('kaputt');
|
$broken = CompatibilityMatrix::allIncompatible(DiviFeature::cases(), 'kaputt');
|
||||||
|
|
||||||
foreach (DiviFeature::cases() as $feature) {
|
foreach (DiviFeature::cases() as $feature) {
|
||||||
self::assertTrue($released->of($feature)->usable());
|
self::assertTrue($released->of($feature)->usable());
|
||||||
@@ -43,7 +45,7 @@ final class CompatibilityMatrixTest extends TestCase
|
|||||||
self::assertNull($broken->of($feature)->source);
|
self::assertNull($broken->of($feature)->source);
|
||||||
}
|
}
|
||||||
self::assertSame([], $released->unusable());
|
self::assertSame([], $released->unusable());
|
||||||
self::assertSame('code', CompatibilityMatrix::allReleased()->source());
|
self::assertSame('code', CompatibilityMatrix::allReleased(DiviFeature::cases())->source());
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testTheStateIsTheWorstFeatureAndEveryProblemIsListedOnce(): void
|
public function testTheStateIsTheWorstFeatureAndEveryProblemIsListedOnce(): void
|
||||||
@@ -64,7 +66,7 @@ final class CompatibilityMatrixTest extends TestCase
|
|||||||
{
|
{
|
||||||
self::assertSame('auto', self::matrix([])->source());
|
self::assertSame('auto', self::matrix([])->source());
|
||||||
|
|
||||||
$mixed = new CompatibilityMatrix(array_merge(
|
$mixed = new CompatibilityMatrix(DiviFeature::cases(), array_merge(
|
||||||
self::features([]),
|
self::features([]),
|
||||||
['roles' => new FeatureStatus(DiviFeature::Roles, ReleaseState::Released, [], 'code')]
|
['roles' => new FeatureStatus(DiviFeature::Roles, ReleaseState::Released, [], 'code')]
|
||||||
));
|
));
|
||||||
@@ -146,6 +148,95 @@ final class CompatibilityMatrixTest extends TestCase
|
|||||||
/** @param array<string, array{ReleaseState, list<string>}> $locked */
|
/** @param array<string, array{ReleaseState, list<string>}> $locked */
|
||||||
private static function matrix(array $locked): CompatibilityMatrix
|
private static function matrix(array $locked): CompatibilityMatrix
|
||||||
{
|
{
|
||||||
return new CompatibilityMatrix(self::features($locked));
|
return new CompatibilityMatrix(DiviFeature::cases(), self::features($locked));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static function fakeCapability(string $id, bool $write = false): Capability
|
||||||
|
{
|
||||||
|
return new class ($id, $write) implements Capability {
|
||||||
|
public function __construct(private readonly string $id, private readonly bool $write)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public function id(): string
|
||||||
|
{
|
||||||
|
return $this->id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function label(): string
|
||||||
|
{
|
||||||
|
return 'Fake ' . $this->id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function isWrite(): bool
|
||||||
|
{
|
||||||
|
return $this->write;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testWorksForCapabilitiesOfAnotherIntegration(): void
|
||||||
|
{
|
||||||
|
$read = self::fakeCapability('pods-x');
|
||||||
|
$write = self::fakeCapability('pods-y', true);
|
||||||
|
$stranger = self::fakeCapability('pods-z');
|
||||||
|
|
||||||
|
$matrix = CompatibilityMatrix::uniform([$read, $write], ReleaseState::Untested, ['offen']);
|
||||||
|
|
||||||
|
self::assertSame(ReleaseState::Untested, $matrix->of($read)->state);
|
||||||
|
self::assertSame(['pods-x', 'pods-y'], array_column($matrix->toArray(), 'id'));
|
||||||
|
self::assertFalse($matrix->usable([$read, $write]));
|
||||||
|
self::assertSame(
|
||||||
|
[CompatibilityMatrix::MISSING],
|
||||||
|
$matrix->of($stranger)->problems,
|
||||||
|
'a capability the matrix does not know is incompatible (fail closed)'
|
||||||
|
);
|
||||||
|
self::assertSame(ReleaseState::Released, CompatibilityMatrix::allReleased([$read])->state());
|
||||||
|
self::assertSame(
|
||||||
|
ReleaseState::Incompatible,
|
||||||
|
CompatibilityMatrix::allIncompatible([$read], 'kaputt')->of($read)->state
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testTheSourceConstantsLiveOnTheMatrix(): void
|
||||||
|
{
|
||||||
|
self::assertSame('code', CompatibilityMatrix::SOURCE_CODE);
|
||||||
|
self::assertSame('database', CompatibilityMatrix::SOURCE_DATABASE);
|
||||||
|
self::assertSame('auto', CompatibilityMatrix::SOURCE_AUTO);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testFromProblemsWeighsHardAndSoftProblemsPerCapability(): void
|
||||||
|
{
|
||||||
|
$a = self::fakeCapability('pods-a');
|
||||||
|
$b = self::fakeCapability('pods-b');
|
||||||
|
$c = self::fakeCapability('pods-c');
|
||||||
|
$problems = [
|
||||||
|
new Problem('hart', [$a], Problem::CALL),
|
||||||
|
new Problem('Signatur', [$b], Problem::SIGNATURE),
|
||||||
|
new Problem('Referenz', [$c], Problem::REFERENCE_MISSING),
|
||||||
|
];
|
||||||
|
|
||||||
|
$released = CompatibilityMatrix::fromProblems([$a, $b, $c], $problems, CompatibilityMatrix::SOURCE_CODE, false);
|
||||||
|
self::assertSame(ReleaseState::Incompatible, $released->of($a)->state, 'hard locks even a released version');
|
||||||
|
self::assertSame(['hart'], $released->of($a)->problems);
|
||||||
|
self::assertSame(CompatibilityMatrix::SOURCE_CODE, $released->of($b)->source);
|
||||||
|
|
||||||
|
$manual = CompatibilityMatrix::fromProblems([$a, $b, $c], $problems, null, false);
|
||||||
|
self::assertSame(ReleaseState::Untested, $manual->of($b)->state);
|
||||||
|
self::assertSame(['Signatur'], $manual->of($b)->problems);
|
||||||
|
|
||||||
|
$auto = CompatibilityMatrix::fromProblems([$a, $b, $c], $problems, null, true);
|
||||||
|
self::assertSame(ReleaseState::Incompatible, $auto->of($b)->state, 'changed signature');
|
||||||
|
self::assertSame(ReleaseState::Untested, $auto->of($c)->state, 'reference missing');
|
||||||
|
|
||||||
|
$clean = CompatibilityMatrix::fromProblems([$a], [new Problem('b', [$b], Problem::CALL)], null, true);
|
||||||
|
self::assertSame(ReleaseState::Released, $clean->of($a)->state);
|
||||||
|
self::assertSame(CompatibilityMatrix::SOURCE_AUTO, $clean->of($a)->source);
|
||||||
|
|
||||||
|
$everyone = CompatibilityMatrix::fromProblems([$a, $b], [new Problem('alle', [], Problem::CALL)], null, true);
|
||||||
|
self::assertSame([ReleaseState::Incompatible, ReleaseState::Incompatible], [
|
||||||
|
$everyone->of($a)->state,
|
||||||
|
$everyone->of($b)->state,
|
||||||
|
], 'a problem without capabilities concerns every one');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
+3
-3
@@ -2,11 +2,11 @@
|
|||||||
|
|
||||||
declare(strict_types=1);
|
declare(strict_types=1);
|
||||||
|
|
||||||
namespace LIT\MCP\Tests\Unit\Integrations\Divi\Release;
|
namespace LIT\MCP\Tests\Unit\Compatibility;
|
||||||
|
|
||||||
|
use LIT\MCP\Compatibility\FeatureStatus;
|
||||||
|
use LIT\MCP\Compatibility\ReleaseState;
|
||||||
use LIT\MCP\Integrations\Divi\Release\DiviFeature;
|
use LIT\MCP\Integrations\Divi\Release\DiviFeature;
|
||||||
use LIT\MCP\Integrations\Divi\Release\FeatureStatus;
|
|
||||||
use LIT\MCP\Integrations\Divi\Release\ReleaseState;
|
|
||||||
use PHPUnit\Framework\TestCase;
|
use PHPUnit\Framework\TestCase;
|
||||||
|
|
||||||
final class FeatureStatusTest extends TestCase
|
final class FeatureStatusTest extends TestCase
|
||||||
+2
-2
@@ -2,9 +2,9 @@
|
|||||||
|
|
||||||
declare(strict_types=1);
|
declare(strict_types=1);
|
||||||
|
|
||||||
namespace LIT\MCP\Tests\Unit\Integrations\Divi\Release;
|
namespace LIT\MCP\Tests\Unit\Compatibility;
|
||||||
|
|
||||||
use LIT\MCP\Integrations\Divi\Release\LineDiff;
|
use LIT\MCP\Compatibility\LineDiff;
|
||||||
use PHPUnit\Framework\TestCase;
|
use PHPUnit\Framework\TestCase;
|
||||||
|
|
||||||
final class LineDiffTest extends TestCase
|
final class LineDiffTest extends TestCase
|
||||||
+97
-10
@@ -2,19 +2,22 @@
|
|||||||
|
|
||||||
declare(strict_types=1);
|
declare(strict_types=1);
|
||||||
|
|
||||||
namespace LIT\MCP\Tests\Unit\Integrations\Divi\Release;
|
namespace LIT\MCP\Tests\Unit\Compatibility;
|
||||||
|
|
||||||
use ArrayObject;
|
use ArrayObject;
|
||||||
use Brain\Monkey\Functions;
|
use Brain\Monkey\Functions;
|
||||||
use LIT\MCP\Integrations\Divi\Release\Call;
|
use LIT\MCP\Compatibility\Call;
|
||||||
use LIT\MCP\Integrations\Divi\Release\ConstantRequirement;
|
use LIT\MCP\Compatibility\ConstantRequirement;
|
||||||
|
use LIT\MCP\Compatibility\GlobalRequirement;
|
||||||
|
use LIT\MCP\Compatibility\Manifest;
|
||||||
|
use LIT\MCP\Compatibility\ManifestCheck;
|
||||||
|
use LIT\MCP\Compatibility\Mirror;
|
||||||
|
use LIT\MCP\Compatibility\Problem;
|
||||||
|
use LIT\MCP\Compatibility\SignatureFingerprint;
|
||||||
|
use LIT\MCP\Integrations\Divi\Release\DiviAreas;
|
||||||
use LIT\MCP\Integrations\Divi\Release\DiviFeature;
|
use LIT\MCP\Integrations\Divi\Release\DiviFeature;
|
||||||
use LIT\MCP\Integrations\Divi\Release\Manifest;
|
|
||||||
use LIT\MCP\Integrations\Divi\Release\ManifestCheck;
|
|
||||||
use LIT\MCP\Integrations\Divi\Release\Mirror;
|
|
||||||
use LIT\MCP\Integrations\Divi\Release\Problem;
|
|
||||||
use LIT\MCP\Integrations\Divi\Release\SignatureFingerprint;
|
|
||||||
use LIT\MCP\Tests\Unit\TestCase;
|
use LIT\MCP\Tests\Unit\TestCase;
|
||||||
|
use LogicException;
|
||||||
use RuntimeException;
|
use RuntimeException;
|
||||||
|
|
||||||
final class ManifestCheckTest extends TestCase
|
final class ManifestCheckTest extends TestCase
|
||||||
@@ -23,7 +26,7 @@ final class ManifestCheckTest extends TestCase
|
|||||||
{
|
{
|
||||||
$manifests = [
|
$manifests = [
|
||||||
'A' => new Manifest(
|
'A' => new Manifest(
|
||||||
Manifest::PAGES,
|
DiviAreas::PAGES,
|
||||||
calls: [
|
calls: [
|
||||||
new Call('strlen', 1),
|
new Call('strlen', 1),
|
||||||
new Call('lit_mcp_missing_function', 0),
|
new Call('lit_mcp_missing_function', 0),
|
||||||
@@ -140,7 +143,7 @@ final class ManifestCheckTest extends TestCase
|
|||||||
private function featureCheck(?\Closure $current = null): ManifestCheck
|
private function featureCheck(?\Closure $current = null): ManifestCheck
|
||||||
{
|
{
|
||||||
$manifest = new Manifest(
|
$manifest = new Manifest(
|
||||||
Manifest::PAGES,
|
DiviAreas::PAGES,
|
||||||
calls: [
|
calls: [
|
||||||
new Call('strlen', 1),
|
new Call('strlen', 1),
|
||||||
new Call('str_replace', 3, [DiviFeature::PageWrite]),
|
new Call('str_replace', 3, [DiviFeature::PageWrite]),
|
||||||
@@ -232,4 +235,88 @@ final class ManifestCheckTest extends TestCase
|
|||||||
array_column(self::rows($check->problems()), 'label')
|
array_column(self::rows($check->problems()), 'label')
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function testWithoutSignaturesACallWithoutReferenceIsNoProblem(): void
|
||||||
|
{
|
||||||
|
$check = new ManifestCheck(
|
||||||
|
['A' => new Manifest(DiviAreas::PAGES, calls: [new Call('strlen', 1), new Call('trim', 1)])],
|
||||||
|
[],
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
false
|
||||||
|
);
|
||||||
|
|
||||||
|
self::assertSame([], $check->codeProblems());
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testWithoutSignaturesAMissingCallStillFails(): void
|
||||||
|
{
|
||||||
|
$check = new ManifestCheck(
|
||||||
|
['A' => new Manifest(DiviAreas::PAGES, calls: [new Call('strlen', 2)])],
|
||||||
|
signatures: false
|
||||||
|
);
|
||||||
|
|
||||||
|
self::assertSame(['call'], array_column(self::rows($check->codeProblems()), 'kind'));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testAMissingGlobalIsAHardProblemWithItsFeatures(): void
|
||||||
|
{
|
||||||
|
$GLOBALS['lit_mcp_present_global'] = 1;
|
||||||
|
$GLOBALS['lit_mcp_null_global'] = null;
|
||||||
|
$check = new ManifestCheck(['A' => new Manifest(
|
||||||
|
DiviAreas::PAGES,
|
||||||
|
globals: [
|
||||||
|
new GlobalRequirement('lit_mcp_present_global'),
|
||||||
|
new GlobalRequirement('lit_mcp_null_global'),
|
||||||
|
new GlobalRequirement('lit_mcp_missing_global', [DiviFeature::Catalog]),
|
||||||
|
],
|
||||||
|
features: [DiviFeature::PageRead]
|
||||||
|
)], signatures: false);
|
||||||
|
|
||||||
|
try {
|
||||||
|
$problems = $check->problems();
|
||||||
|
$failed = ManifestCheck::failed($check->codeChecks());
|
||||||
|
} finally {
|
||||||
|
unset($GLOBALS['lit_mcp_present_global'], $GLOBALS['lit_mcp_null_global']);
|
||||||
|
}
|
||||||
|
|
||||||
|
self::assertSame(
|
||||||
|
[
|
||||||
|
['label' => 'Seiten: Globale Variable lit_mcp_null_global', 'kind' => 'global',
|
||||||
|
'features' => ['page-read']],
|
||||||
|
['label' => 'Seiten: Globale Variable lit_mcp_missing_global', 'kind' => 'global',
|
||||||
|
'features' => ['catalog']],
|
||||||
|
],
|
||||||
|
self::rows($problems)
|
||||||
|
);
|
||||||
|
self::assertTrue($problems[0]->isHard());
|
||||||
|
self::assertSame(
|
||||||
|
['Seiten: Globale Variable lit_mcp_null_global', 'Seiten: Globale Variable lit_mcp_missing_global'],
|
||||||
|
$failed
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testWithoutCurrentClosureEveryMirrorIsUnreadable(): void
|
||||||
|
{
|
||||||
|
$check = new ManifestCheck(['A' => new Manifest(
|
||||||
|
DiviAreas::PAGES,
|
||||||
|
mirrors: [new Mirror('same', 'a.php', 'a', null, 'gleich')]
|
||||||
|
)], ['same' => 'h1']);
|
||||||
|
|
||||||
|
self::assertSame(['mirror'], array_column(self::rows($check->mirrorProblems()), 'kind'));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testBlockTypesWithoutKnowsBlockClosureRefuseToBuildTheCheck(): void
|
||||||
|
{
|
||||||
|
$this->expectException(LogicException::class);
|
||||||
|
|
||||||
|
new ManifestCheck(['A' => new Manifest(DiviAreas::PAGES, blockTypes: ['divi/x'])]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testWithoutBlockTypesNoKnowsBlockClosureIsNeeded(): void
|
||||||
|
{
|
||||||
|
$check = new ManifestCheck(['A' => new Manifest(DiviAreas::PAGES, calls: [new Call('strlen', 1)])]);
|
||||||
|
|
||||||
|
self::assertSame([], $check->registrationChecks());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
+20
-10
@@ -2,13 +2,15 @@
|
|||||||
|
|
||||||
declare(strict_types=1);
|
declare(strict_types=1);
|
||||||
|
|
||||||
namespace LIT\MCP\Tests\Unit\Integrations\Divi\Release;
|
namespace LIT\MCP\Tests\Unit\Compatibility;
|
||||||
|
|
||||||
use LIT\MCP\Integrations\Divi\Release\Call;
|
use LIT\MCP\Compatibility\Call;
|
||||||
use LIT\MCP\Integrations\Divi\Release\ConstantRequirement;
|
use LIT\MCP\Compatibility\ConstantRequirement;
|
||||||
|
use LIT\MCP\Compatibility\GlobalRequirement;
|
||||||
|
use LIT\MCP\Compatibility\Manifest;
|
||||||
|
use LIT\MCP\Compatibility\Mirror;
|
||||||
|
use LIT\MCP\Integrations\Divi\Release\DiviAreas;
|
||||||
use LIT\MCP\Integrations\Divi\Release\DiviFeature;
|
use LIT\MCP\Integrations\Divi\Release\DiviFeature;
|
||||||
use LIT\MCP\Integrations\Divi\Release\Manifest;
|
|
||||||
use LIT\MCP\Integrations\Divi\Release\Mirror;
|
|
||||||
use PHPUnit\Framework\TestCase;
|
use PHPUnit\Framework\TestCase;
|
||||||
|
|
||||||
final class ManifestTest extends TestCase
|
final class ManifestTest extends TestCase
|
||||||
@@ -39,7 +41,7 @@ final class ManifestTest extends TestCase
|
|||||||
public function testNamesListEveryDeclaredDiviName(): void
|
public function testNamesListEveryDeclaredDiviName(): void
|
||||||
{
|
{
|
||||||
$manifest = new Manifest(
|
$manifest = new Manifest(
|
||||||
Manifest::LIBRARY,
|
DiviAreas::LIBRARY,
|
||||||
calls: [new Call('et_pb_is_allowed', 1), new Call('ET\Builder\GlobalLayout::is_global_layout_template', 1)],
|
calls: [new Call('et_pb_is_allowed', 1), new Call('ET\Builder\GlobalLayout::is_global_layout_template', 1)],
|
||||||
constants: ['ET_BUILDER_PRODUCT_VERSION'],
|
constants: ['ET_BUILDER_PRODUCT_VERSION'],
|
||||||
postTypes: ['et_pb_layout'],
|
postTypes: ['et_pb_layout'],
|
||||||
@@ -59,7 +61,7 @@ final class ManifestTest extends TestCase
|
|||||||
public function testPlainConstantNamesBecomeRequirementsWithALabel(): void
|
public function testPlainConstantNamesBecomeRequirementsWithALabel(): void
|
||||||
{
|
{
|
||||||
$manifest = new Manifest(
|
$manifest = new Manifest(
|
||||||
Manifest::CATALOG,
|
DiviAreas::CATALOG,
|
||||||
constants: ['ET_BUILDER_PRODUCT_VERSION', new ConstantRequirement('ET_OTHER', [DiviFeature::Roles])]
|
constants: ['ET_BUILDER_PRODUCT_VERSION', new ConstantRequirement('ET_OTHER', [DiviFeature::Roles])]
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -77,7 +79,7 @@ final class ManifestTest extends TestCase
|
|||||||
{
|
{
|
||||||
$call = new Call('et_pb_is_allowed', 1);
|
$call = new Call('et_pb_is_allowed', 1);
|
||||||
$mirror = new Mirror('m', 'a.php', 'a', null, 'Terme');
|
$mirror = new Mirror('m', 'a.php', 'a', null, 'Terme');
|
||||||
$manifest = new Manifest(Manifest::LIBRARY, calls: [$call], constants: ['ET_X'], mirrors: [$mirror]);
|
$manifest = new Manifest(DiviAreas::LIBRARY, calls: [$call], constants: ['ET_X'], mirrors: [$mirror]);
|
||||||
|
|
||||||
$requirements = $manifest->requirements();
|
$requirements = $manifest->requirements();
|
||||||
|
|
||||||
@@ -93,7 +95,7 @@ final class ManifestTest extends TestCase
|
|||||||
$inherited = new Call('et_b');
|
$inherited = new Call('et_b');
|
||||||
$mirror = new Mirror('m', 'a.php', 'a', null, 'x', [DiviFeature::LibraryWrite]);
|
$mirror = new Mirror('m', 'a.php', 'a', null, 'x', [DiviFeature::LibraryWrite]);
|
||||||
$manifest = new Manifest(
|
$manifest = new Manifest(
|
||||||
Manifest::PAGES,
|
DiviAreas::PAGES,
|
||||||
calls: [$own, $inherited],
|
calls: [$own, $inherited],
|
||||||
constants: ['ET_X'],
|
constants: ['ET_X'],
|
||||||
mirrors: [$mirror],
|
mirrors: [$mirror],
|
||||||
@@ -110,6 +112,14 @@ final class ManifestTest extends TestCase
|
|||||||
{
|
{
|
||||||
$call = new Call('et_a');
|
$call = new Call('et_a');
|
||||||
|
|
||||||
self::assertSame([], (new Manifest(Manifest::PAGES, calls: [$call]))->featuresOf($call));
|
self::assertSame([], (new Manifest(DiviAreas::PAGES, calls: [$call]))->featuresOf($call));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testGlobalsAreRequirementsAndNames(): void
|
||||||
|
{
|
||||||
|
$manifest = new Manifest(DiviAreas::PAGES, globals: [new GlobalRequirement('wp_cache_clear_cache')]);
|
||||||
|
|
||||||
|
self::assertSame('wp_cache_clear_cache', $manifest->names()[0]);
|
||||||
|
self::assertSame('Globale Variable wp_cache_clear_cache', $manifest->requirements()[0]->label());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
+36
-4
@@ -2,10 +2,11 @@
|
|||||||
|
|
||||||
declare(strict_types=1);
|
declare(strict_types=1);
|
||||||
|
|
||||||
namespace LIT\MCP\Tests\Unit\Integrations\Divi\Release;
|
namespace LIT\MCP\Tests\Unit\Compatibility;
|
||||||
|
|
||||||
|
use LIT\MCP\Compatibility\Capability;
|
||||||
|
use LIT\MCP\Compatibility\Problem;
|
||||||
use LIT\MCP\Integrations\Divi\Release\DiviFeature;
|
use LIT\MCP\Integrations\Divi\Release\DiviFeature;
|
||||||
use LIT\MCP\Integrations\Divi\Release\Problem;
|
|
||||||
use PHPUnit\Framework\TestCase;
|
use PHPUnit\Framework\TestCase;
|
||||||
|
|
||||||
final class ProblemTest extends TestCase
|
final class ProblemTest extends TestCase
|
||||||
@@ -44,7 +45,7 @@ final class ProblemTest extends TestCase
|
|||||||
['label' => 'Seiten: Nachbau von a() – x', 'kind' => 'mirror', 'features' => ['page-write']],
|
['label' => 'Seiten: Nachbau von a() – x', 'kind' => 'mirror', 'features' => ['page-write']],
|
||||||
$problem->toArray()
|
$problem->toArray()
|
||||||
);
|
);
|
||||||
self::assertEquals($problem, Problem::fromArray($problem->toArray()));
|
self::assertEquals($problem, Problem::fromArray($problem->toArray(), DiviFeature::tryFrom(...)));
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testFromArrayRefusesAnythingElse(): void
|
public function testFromArrayRefusesAnythingElse(): void
|
||||||
@@ -56,7 +57,38 @@ final class ProblemTest extends TestCase
|
|||||||
'unknown feature' => ['label' => 'x', 'kind' => 'call', 'features' => ['page-delete']],
|
'unknown feature' => ['label' => 'x', 'kind' => 'call', 'features' => ['page-delete']],
|
||||||
'features no list' => ['label' => 'x', 'kind' => 'call', 'features' => 'page-write'],
|
'features no list' => ['label' => 'x', 'kind' => 'call', 'features' => 'page-write'],
|
||||||
] as $case => $row) {
|
] as $case => $row) {
|
||||||
self::assertNull(Problem::fromArray($row), $case);
|
self::assertNull(Problem::fromArray($row, DiviFeature::tryFrom(...)), $case);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function testFromArrayResolvesFeaturesThroughTheLookupClosure(): void
|
||||||
|
{
|
||||||
|
$pods = new class implements Capability {
|
||||||
|
public function id(): string
|
||||||
|
{
|
||||||
|
return 'pods-x';
|
||||||
|
}
|
||||||
|
|
||||||
|
public function label(): string
|
||||||
|
{
|
||||||
|
return 'Pods X';
|
||||||
|
}
|
||||||
|
|
||||||
|
public function isWrite(): bool
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
$lookup = static fn (string $id): ?Capability => $id === 'pods-x' ? $pods : null;
|
||||||
|
|
||||||
|
$problem = Problem::fromArray(['label' => 'x', 'kind' => 'call', 'features' => ['pods-x']], $lookup);
|
||||||
|
self::assertNotNull($problem);
|
||||||
|
self::assertSame([$pods], $problem->features);
|
||||||
|
self::assertTrue($problem->concerns($pods));
|
||||||
|
|
||||||
|
self::assertNull(
|
||||||
|
Problem::fromArray(['label' => 'x', 'kind' => 'call', 'features' => ['pods-x', 'page-read']], $lookup),
|
||||||
|
'one unknown ID discards the problem'
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
+4
-4
@@ -2,11 +2,11 @@
|
|||||||
|
|
||||||
declare(strict_types=1);
|
declare(strict_types=1);
|
||||||
|
|
||||||
namespace LIT\MCP\Tests\Unit\Integrations\Divi\Release;
|
namespace LIT\MCP\Tests\Unit\Compatibility;
|
||||||
|
|
||||||
use ArrayObject;
|
use ArrayObject;
|
||||||
use LIT\MCP\Integrations\Divi\Release\Call;
|
use LIT\MCP\Compatibility\Call;
|
||||||
use LIT\MCP\Integrations\Divi\Release\SignatureFingerprint;
|
use LIT\MCP\Compatibility\SignatureFingerprint;
|
||||||
use PHPUnit\Framework\TestCase;
|
use PHPUnit\Framework\TestCase;
|
||||||
|
|
||||||
/** Stand-in for a Divi class: one baseline method and one variant per property the fingerprint covers. */
|
/** Stand-in for a Divi class: one baseline method and one variant per property the fingerprint covers. */
|
||||||
@@ -191,7 +191,7 @@ final class SignatureFingerprintTest extends TestCase
|
|||||||
public function testTheClassNeverIncludesAFile(): void
|
public function testTheClassNeverIncludesAFile(): void
|
||||||
{
|
{
|
||||||
$source = (string) file_get_contents(
|
$source = (string) file_get_contents(
|
||||||
dirname(__DIR__, 5) . '/src/Integrations/Divi/Release/SignatureFingerprint.php'
|
dirname(__DIR__, 3) . '/src/Compatibility/SignatureFingerprint.php'
|
||||||
);
|
);
|
||||||
$forbidden = [T_INCLUDE, T_INCLUDE_ONCE, T_REQUIRE, T_REQUIRE_ONCE, T_EVAL];
|
$forbidden = [T_INCLUDE, T_INCLUDE_ONCE, T_REQUIRE, T_REQUIRE_ONCE, T_EVAL];
|
||||||
|
|
||||||
+2
-2
@@ -2,9 +2,9 @@
|
|||||||
|
|
||||||
declare(strict_types=1);
|
declare(strict_types=1);
|
||||||
|
|
||||||
namespace LIT\MCP\Tests\Unit\Integrations\Divi\Release;
|
namespace LIT\MCP\Tests\Unit\Compatibility;
|
||||||
|
|
||||||
use LIT\MCP\Integrations\Divi\Release\SourceFingerprint;
|
use LIT\MCP\Compatibility\SourceFingerprint;
|
||||||
use PHPUnit\Framework\TestCase;
|
use PHPUnit\Framework\TestCase;
|
||||||
use RuntimeException;
|
use RuntimeException;
|
||||||
|
|
||||||
@@ -7,15 +7,15 @@ namespace LIT\MCP\Tests\Unit\Integrations\Divi\Admin;
|
|||||||
use Brain\Monkey\Actions;
|
use Brain\Monkey\Actions;
|
||||||
use Brain\Monkey\Functions;
|
use Brain\Monkey\Functions;
|
||||||
use LIT\MCP\Admin\AdminPostAction;
|
use LIT\MCP\Admin\AdminPostAction;
|
||||||
|
use LIT\MCP\Compatibility\ReleaseState;
|
||||||
use LIT\MCP\Integrations\Divi\Admin\DiviTab;
|
use LIT\MCP\Integrations\Divi\Admin\DiviTab;
|
||||||
use LIT\MCP\Integrations\Divi\Release\CheckReport;
|
use LIT\MCP\Integrations\Divi\Release\CheckReport;
|
||||||
use LIT\MCP\Integrations\Divi\Release\CheckReportStore;
|
use LIT\MCP\Integrations\Divi\Release\CheckReportStore;
|
||||||
use LIT\MCP\Integrations\Divi\Release\CheckStep;
|
use LIT\MCP\Integrations\Divi\Release\CheckStep;
|
||||||
use LIT\MCP\Integrations\Divi\Release\DiviFeature;
|
use LIT\MCP\Integrations\Divi\Release\DiviFeature;
|
||||||
use LIT\MCP\Integrations\Divi\Release\FeatureOverview;
|
use LIT\MCP\Integrations\Divi\Release\FeatureOverview;
|
||||||
use LIT\MCP\Integrations\Divi\Release\FeatureStatus;
|
use LIT\MCP\Compatibility\FeatureStatus;
|
||||||
use LIT\MCP\Integrations\Divi\Release\ReleaseGate;
|
use LIT\MCP\Integrations\Divi\Release\ReleaseGate;
|
||||||
use LIT\MCP\Integrations\Divi\Release\ReleaseState;
|
|
||||||
use LIT\MCP\Integrations\Divi\Release\ReleaseStatus;
|
use LIT\MCP\Integrations\Divi\Release\ReleaseStatus;
|
||||||
use LIT\MCP\Integrations\Divi\Release\ReleaseStore;
|
use LIT\MCP\Integrations\Divi\Release\ReleaseStore;
|
||||||
use LIT\MCP\Integrations\Divi\Release\WriteProbe;
|
use LIT\MCP\Integrations\Divi\Release\WriteProbe;
|
||||||
|
|||||||
@@ -5,17 +5,17 @@ declare(strict_types=1);
|
|||||||
namespace LIT\MCP\Tests\Unit\Integrations\Divi\Cli;
|
namespace LIT\MCP\Tests\Unit\Integrations\Divi\Cli;
|
||||||
|
|
||||||
use Brain\Monkey\Functions;
|
use Brain\Monkey\Functions;
|
||||||
|
use LIT\MCP\Compatibility\ReleaseState;
|
||||||
use LIT\MCP\Integrations\Divi\Cli\DiviCheckCommand;
|
use LIT\MCP\Integrations\Divi\Cli\DiviCheckCommand;
|
||||||
use LIT\MCP\Integrations\Divi\Release\CheckReport;
|
use LIT\MCP\Integrations\Divi\Release\CheckReport;
|
||||||
use LIT\MCP\Integrations\Divi\Release\CheckReportStore;
|
use LIT\MCP\Integrations\Divi\Release\CheckReportStore;
|
||||||
use LIT\MCP\Integrations\Divi\Release\CheckStep;
|
use LIT\MCP\Integrations\Divi\Release\CheckStep;
|
||||||
use LIT\MCP\Integrations\Divi\Release\CompatibilityCheck;
|
use LIT\MCP\Integrations\Divi\Release\CompatibilityCheck;
|
||||||
use LIT\MCP\Integrations\Divi\Release\CompatibilityMatrix;
|
use LIT\MCP\Compatibility\CompatibilityMatrix;
|
||||||
use LIT\MCP\Integrations\Divi\Release\DiviFeature;
|
use LIT\MCP\Integrations\Divi\Release\DiviFeature;
|
||||||
use LIT\MCP\Integrations\Divi\Release\DiviReference;
|
use LIT\MCP\Integrations\Divi\Release\DiviReference;
|
||||||
use LIT\MCP\Integrations\Divi\Release\ReleaseGate;
|
use LIT\MCP\Integrations\Divi\Release\ReleaseGate;
|
||||||
use LIT\MCP\Integrations\Divi\Release\ReleaseResolver;
|
use LIT\MCP\Integrations\Divi\Release\ReleaseResolver;
|
||||||
use LIT\MCP\Integrations\Divi\Release\ReleaseState;
|
|
||||||
use LIT\MCP\Integrations\Divi\Release\ReleaseStatus;
|
use LIT\MCP\Integrations\Divi\Release\ReleaseStatus;
|
||||||
use LIT\MCP\Tests\Support\MatrixFixtures;
|
use LIT\MCP\Tests\Support\MatrixFixtures;
|
||||||
use LIT\MCP\Tests\Support\ReleaseMatrices;
|
use LIT\MCP\Tests\Support\ReleaseMatrices;
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ use LIT\MCP\Integrations\Divi\Library\UsageReport;
|
|||||||
use LIT\MCP\Integrations\Divi\Release\DiviFeature;
|
use LIT\MCP\Integrations\Divi\Release\DiviFeature;
|
||||||
use LIT\MCP\Integrations\Divi\Release\DiviLocked;
|
use LIT\MCP\Integrations\Divi\Release\DiviLocked;
|
||||||
use LIT\MCP\Integrations\Divi\Release\ReleaseGate;
|
use LIT\MCP\Integrations\Divi\Release\ReleaseGate;
|
||||||
use LIT\MCP\Integrations\Divi\Release\ReleaseState;
|
use LIT\MCP\Compatibility\ReleaseState;
|
||||||
use LIT\MCP\Integrations\Divi\Release\ReleaseStatus;
|
use LIT\MCP\Integrations\Divi\Release\ReleaseStatus;
|
||||||
use LIT\MCP\Abilities\WriteFailed;
|
use LIT\MCP\Abilities\WriteFailed;
|
||||||
use LIT\MCP\Tests\Support\FakeChangeLog;
|
use LIT\MCP\Tests\Support\FakeChangeLog;
|
||||||
|
|||||||
@@ -6,9 +6,9 @@ namespace LIT\MCP\Tests\Unit\Integrations\Divi\Design;
|
|||||||
|
|
||||||
use Brain\Monkey\Functions;
|
use Brain\Monkey\Functions;
|
||||||
use LIT\MCP\Integrations\Divi\Design\DesignSystemReader;
|
use LIT\MCP\Integrations\Divi\Design\DesignSystemReader;
|
||||||
use LIT\MCP\Integrations\Divi\Release\Call;
|
use LIT\MCP\Compatibility\Call;
|
||||||
use LIT\MCP\Integrations\Divi\Release\DiviAdapters;
|
use LIT\MCP\Integrations\Divi\Release\DiviAdapters;
|
||||||
use LIT\MCP\Integrations\Divi\Release\Manifest;
|
use LIT\MCP\Integrations\Divi\Release\DiviAreas;
|
||||||
use LIT\MCP\Tests\Unit\TestCase;
|
use LIT\MCP\Tests\Unit\TestCase;
|
||||||
|
|
||||||
final class DesignSystemReaderTest extends TestCase
|
final class DesignSystemReaderTest extends TestCase
|
||||||
@@ -18,7 +18,7 @@ final class DesignSystemReaderTest extends TestCase
|
|||||||
$manifest = DesignSystemReader::manifest();
|
$manifest = DesignSystemReader::manifest();
|
||||||
|
|
||||||
self::assertContains(DesignSystemReader::class, DiviAdapters::CLASSES);
|
self::assertContains(DesignSystemReader::class, DiviAdapters::CLASSES);
|
||||||
self::assertSame(Manifest::DESIGN, $manifest->area);
|
self::assertSame(DiviAreas::DESIGN, $manifest->area);
|
||||||
self::assertSame(
|
self::assertSame(
|
||||||
['GlobalData::get_global_colors()', 'GlobalData::get_global_variables()',
|
['GlobalData::get_global_colors()', 'GlobalData::get_global_variables()',
|
||||||
'GlobalPreset::get_data()'],
|
'GlobalPreset::get_data()'],
|
||||||
|
|||||||
@@ -4,13 +4,13 @@ declare(strict_types=1);
|
|||||||
|
|
||||||
namespace LIT\MCP\Tests\Unit\Integrations\Divi\Design;
|
namespace LIT\MCP\Tests\Unit\Integrations\Divi\Design;
|
||||||
|
|
||||||
|
use LIT\MCP\Compatibility\ReleaseState;
|
||||||
use LIT\MCP\Integrations\Divi\Design\DesignSystemWriter;
|
use LIT\MCP\Integrations\Divi\Design\DesignSystemWriter;
|
||||||
use LIT\MCP\Integrations\Divi\Release\Call;
|
use LIT\MCP\Compatibility\Call;
|
||||||
use LIT\MCP\Integrations\Divi\Release\DiviAdapters;
|
use LIT\MCP\Integrations\Divi\Release\DiviAdapters;
|
||||||
|
use LIT\MCP\Integrations\Divi\Release\DiviAreas;
|
||||||
use LIT\MCP\Integrations\Divi\Release\DiviLocked;
|
use LIT\MCP\Integrations\Divi\Release\DiviLocked;
|
||||||
use LIT\MCP\Integrations\Divi\Release\Manifest;
|
|
||||||
use LIT\MCP\Integrations\Divi\Release\ReleaseGate;
|
use LIT\MCP\Integrations\Divi\Release\ReleaseGate;
|
||||||
use LIT\MCP\Integrations\Divi\Release\ReleaseState;
|
|
||||||
use LIT\MCP\Integrations\Divi\Release\ReleaseStatus;
|
use LIT\MCP\Integrations\Divi\Release\ReleaseStatus;
|
||||||
use LIT\MCP\Tests\Support\ReleaseMatrices;
|
use LIT\MCP\Tests\Support\ReleaseMatrices;
|
||||||
use LIT\MCP\Tests\Unit\TestCase;
|
use LIT\MCP\Tests\Unit\TestCase;
|
||||||
@@ -22,7 +22,7 @@ final class DesignSystemWriterTest extends TestCase
|
|||||||
$manifest = DesignSystemWriter::manifest();
|
$manifest = DesignSystemWriter::manifest();
|
||||||
|
|
||||||
self::assertContains(DesignSystemWriter::class, DiviAdapters::CLASSES);
|
self::assertContains(DesignSystemWriter::class, DiviAdapters::CLASSES);
|
||||||
self::assertSame(Manifest::DESIGN, $manifest->area);
|
self::assertSame(DiviAreas::DESIGN, $manifest->area);
|
||||||
self::assertSame(
|
self::assertSame(
|
||||||
[
|
[
|
||||||
'GlobalPreset::get_data()', 'GlobalPreset::prepare_data()', 'GlobalPreset::validate_preset_count()',
|
'GlobalPreset::get_data()', 'GlobalPreset::prepare_data()', 'GlobalPreset::validate_preset_count()',
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ use Brain\Monkey\Functions;
|
|||||||
use Closure;
|
use Closure;
|
||||||
use LIT\MCP\Abilities\Errors;
|
use LIT\MCP\Abilities\Errors;
|
||||||
use LIT\MCP\Abilities\WriteFailed;
|
use LIT\MCP\Abilities\WriteFailed;
|
||||||
|
use LIT\MCP\Compatibility\ReleaseState;
|
||||||
use LIT\MCP\Integrations\Divi\BlockTree\Block;
|
use LIT\MCP\Integrations\Divi\BlockTree\Block;
|
||||||
use LIT\MCP\Integrations\Divi\Design\DesignChange;
|
use LIT\MCP\Integrations\Divi\Design\DesignChange;
|
||||||
use LIT\MCP\Integrations\Divi\Design\DesignSystemWriter;
|
use LIT\MCP\Integrations\Divi\Design\DesignSystemWriter;
|
||||||
@@ -24,7 +25,6 @@ use LIT\MCP\Integrations\Divi\Library\GlobalUsages;
|
|||||||
use LIT\MCP\Integrations\Divi\Library\UsageReport;
|
use LIT\MCP\Integrations\Divi\Library\UsageReport;
|
||||||
use LIT\MCP\Integrations\Divi\Release\DiviFeature;
|
use LIT\MCP\Integrations\Divi\Release\DiviFeature;
|
||||||
use LIT\MCP\Integrations\Divi\Release\DiviLocked;
|
use LIT\MCP\Integrations\Divi\Release\DiviLocked;
|
||||||
use LIT\MCP\Integrations\Divi\Release\ReleaseState;
|
|
||||||
use LIT\MCP\Tests\Support\FakeChangeLog;
|
use LIT\MCP\Tests\Support\FakeChangeLog;
|
||||||
use LIT\MCP\Tests\Support\LockTable;
|
use LIT\MCP\Tests\Support\LockTable;
|
||||||
use LIT\MCP\Tests\Support\ReleaseMatrices;
|
use LIT\MCP\Tests\Support\ReleaseMatrices;
|
||||||
|
|||||||
@@ -7,12 +7,12 @@ namespace LIT\MCP\Tests\Unit\Integrations\Divi\Design;
|
|||||||
use Brain\Monkey\Functions;
|
use Brain\Monkey\Functions;
|
||||||
use LIT\MCP\Abilities\Errors;
|
use LIT\MCP\Abilities\Errors;
|
||||||
use LIT\MCP\Abilities\WriteFailed;
|
use LIT\MCP\Abilities\WriteFailed;
|
||||||
|
use LIT\MCP\Compatibility\ReleaseState;
|
||||||
use LIT\MCP\Integrations\Divi\Design\DiviFontsUploadAbility;
|
use LIT\MCP\Integrations\Divi\Design\DiviFontsUploadAbility;
|
||||||
use LIT\MCP\Integrations\Divi\Design\FontCatalog;
|
use LIT\MCP\Integrations\Divi\Design\FontCatalog;
|
||||||
use LIT\MCP\Integrations\Divi\Design\FontInstaller;
|
use LIT\MCP\Integrations\Divi\Design\FontInstaller;
|
||||||
use LIT\MCP\Integrations\Divi\Release\DiviFeature;
|
use LIT\MCP\Integrations\Divi\Release\DiviFeature;
|
||||||
use LIT\MCP\Integrations\Divi\Release\DiviLocked;
|
use LIT\MCP\Integrations\Divi\Release\DiviLocked;
|
||||||
use LIT\MCP\Integrations\Divi\Release\ReleaseState;
|
|
||||||
use LIT\MCP\Integrations\Media\RemoteFileFetcher;
|
use LIT\MCP\Integrations\Media\RemoteFileFetcher;
|
||||||
use LIT\MCP\Limits;
|
use LIT\MCP\Limits;
|
||||||
use LIT\MCP\Tests\Support\FakeChangeLog;
|
use LIT\MCP\Tests\Support\FakeChangeLog;
|
||||||
|
|||||||
@@ -6,10 +6,10 @@ namespace LIT\MCP\Tests\Unit\Integrations\Divi\Design;
|
|||||||
|
|
||||||
use Brain\Monkey\Functions;
|
use Brain\Monkey\Functions;
|
||||||
use LIT\MCP\Integrations\Divi\Design\FontCatalog;
|
use LIT\MCP\Integrations\Divi\Design\FontCatalog;
|
||||||
use LIT\MCP\Integrations\Divi\Release\Call;
|
use LIT\MCP\Compatibility\Call;
|
||||||
use LIT\MCP\Integrations\Divi\Release\DiviAdapters;
|
use LIT\MCP\Integrations\Divi\Release\DiviAdapters;
|
||||||
|
use LIT\MCP\Integrations\Divi\Release\DiviAreas;
|
||||||
use LIT\MCP\Integrations\Divi\Release\DiviFeature;
|
use LIT\MCP\Integrations\Divi\Release\DiviFeature;
|
||||||
use LIT\MCP\Integrations\Divi\Release\Manifest;
|
|
||||||
use LIT\MCP\Tests\Unit\TestCase;
|
use LIT\MCP\Tests\Unit\TestCase;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -24,7 +24,7 @@ final class FontCatalogTest extends TestCase
|
|||||||
$manifest = FontCatalog::manifest();
|
$manifest = FontCatalog::manifest();
|
||||||
|
|
||||||
self::assertContains(FontCatalog::class, DiviAdapters::CLASSES);
|
self::assertContains(FontCatalog::class, DiviAdapters::CLASSES);
|
||||||
self::assertSame(Manifest::DESIGN, $manifest->area);
|
self::assertSame(DiviAreas::DESIGN, $manifest->area);
|
||||||
self::assertSame(
|
self::assertSame(
|
||||||
[
|
[
|
||||||
'et_builder_get_fonts()', 'et_builder_get_custom_fonts()', 'et_builder_get_google_fonts()',
|
'et_builder_get_fonts()', 'et_builder_get_custom_fonts()', 'et_builder_get_google_fonts()',
|
||||||
|
|||||||
@@ -5,15 +5,15 @@ declare(strict_types=1);
|
|||||||
namespace LIT\MCP\Tests\Unit\Integrations\Divi\Design;
|
namespace LIT\MCP\Tests\Unit\Integrations\Divi\Design;
|
||||||
|
|
||||||
use Brain\Monkey\Functions;
|
use Brain\Monkey\Functions;
|
||||||
|
use LIT\MCP\Compatibility\ReleaseState;
|
||||||
use LIT\MCP\Integrations\Divi\Design\FontInstaller;
|
use LIT\MCP\Integrations\Divi\Design\FontInstaller;
|
||||||
use LIT\MCP\Integrations\Divi\Release\Call;
|
use LIT\MCP\Compatibility\Call;
|
||||||
use LIT\MCP\Integrations\Divi\Release\ConstantRequirement;
|
use LIT\MCP\Compatibility\ConstantRequirement;
|
||||||
use LIT\MCP\Integrations\Divi\Release\DiviAdapters;
|
use LIT\MCP\Integrations\Divi\Release\DiviAdapters;
|
||||||
|
use LIT\MCP\Integrations\Divi\Release\DiviAreas;
|
||||||
use LIT\MCP\Integrations\Divi\Release\DiviFeature;
|
use LIT\MCP\Integrations\Divi\Release\DiviFeature;
|
||||||
use LIT\MCP\Integrations\Divi\Release\DiviLocked;
|
use LIT\MCP\Integrations\Divi\Release\DiviLocked;
|
||||||
use LIT\MCP\Integrations\Divi\Release\Manifest;
|
|
||||||
use LIT\MCP\Integrations\Divi\Release\ReleaseGate;
|
use LIT\MCP\Integrations\Divi\Release\ReleaseGate;
|
||||||
use LIT\MCP\Integrations\Divi\Release\ReleaseState;
|
|
||||||
use LIT\MCP\Integrations\Divi\Release\ReleaseStatus;
|
use LIT\MCP\Integrations\Divi\Release\ReleaseStatus;
|
||||||
use LIT\MCP\Tests\Support\ReleaseMatrices;
|
use LIT\MCP\Tests\Support\ReleaseMatrices;
|
||||||
use LIT\MCP\Tests\Unit\TestCase;
|
use LIT\MCP\Tests\Unit\TestCase;
|
||||||
@@ -65,7 +65,7 @@ final class FontInstallerTest extends TestCase
|
|||||||
$manifest = FontInstaller::manifest();
|
$manifest = FontInstaller::manifest();
|
||||||
|
|
||||||
self::assertContains(FontInstaller::class, DiviAdapters::CLASSES);
|
self::assertContains(FontInstaller::class, DiviAdapters::CLASSES);
|
||||||
self::assertSame(Manifest::DESIGN, $manifest->area);
|
self::assertSame(DiviAreas::DESIGN, $manifest->area);
|
||||||
self::assertSame(
|
self::assertSame(
|
||||||
['FontsUtility::mime_types_font()', 'HooksRegistration::check_filetype_and_ext_font()',
|
['FontsUtility::mime_types_font()', 'HooksRegistration::check_filetype_and_ext_font()',
|
||||||
'FontsUtility::font_add()', 'FontsUtility::font_remove()'],
|
'FontsUtility::font_add()', 'FontsUtility::font_remove()'],
|
||||||
|
|||||||
@@ -5,14 +5,14 @@ declare(strict_types=1);
|
|||||||
namespace LIT\MCP\Tests\Unit\Integrations\Divi\Design;
|
namespace LIT\MCP\Tests\Unit\Integrations\Divi\Design;
|
||||||
|
|
||||||
use Brain\Monkey\Functions;
|
use Brain\Monkey\Functions;
|
||||||
|
use LIT\MCP\Compatibility\ReleaseState;
|
||||||
use LIT\MCP\Integrations\Divi\Design\GlobalColorsAdapter;
|
use LIT\MCP\Integrations\Divi\Design\GlobalColorsAdapter;
|
||||||
use LIT\MCP\Integrations\Divi\Release\Call;
|
use LIT\MCP\Compatibility\Call;
|
||||||
use LIT\MCP\Integrations\Divi\Release\DiviAdapters;
|
use LIT\MCP\Integrations\Divi\Release\DiviAdapters;
|
||||||
|
use LIT\MCP\Integrations\Divi\Release\DiviAreas;
|
||||||
use LIT\MCP\Integrations\Divi\Release\DiviFeature;
|
use LIT\MCP\Integrations\Divi\Release\DiviFeature;
|
||||||
use LIT\MCP\Integrations\Divi\Release\DiviLocked;
|
use LIT\MCP\Integrations\Divi\Release\DiviLocked;
|
||||||
use LIT\MCP\Integrations\Divi\Release\Manifest;
|
|
||||||
use LIT\MCP\Integrations\Divi\Release\ReleaseGate;
|
use LIT\MCP\Integrations\Divi\Release\ReleaseGate;
|
||||||
use LIT\MCP\Integrations\Divi\Release\ReleaseState;
|
|
||||||
use LIT\MCP\Integrations\Divi\Release\ReleaseStatus;
|
use LIT\MCP\Integrations\Divi\Release\ReleaseStatus;
|
||||||
use LIT\MCP\Tests\Support\ReleaseMatrices;
|
use LIT\MCP\Tests\Support\ReleaseMatrices;
|
||||||
use LIT\MCP\Tests\Unit\TestCase;
|
use LIT\MCP\Tests\Unit\TestCase;
|
||||||
@@ -32,7 +32,7 @@ final class GlobalColorsAdapterTest extends TestCase
|
|||||||
$manifest = GlobalColorsAdapter::manifest();
|
$manifest = GlobalColorsAdapter::manifest();
|
||||||
|
|
||||||
self::assertContains(GlobalColorsAdapter::class, DiviAdapters::CLASSES);
|
self::assertContains(GlobalColorsAdapter::class, DiviAdapters::CLASSES);
|
||||||
self::assertSame(Manifest::DESIGN, $manifest->area);
|
self::assertSame(DiviAreas::DESIGN, $manifest->area);
|
||||||
self::assertSame(
|
self::assertSame(
|
||||||
['GlobalData::get_global_colors()', 'GlobalData::sanitize_global_colors_data()',
|
['GlobalData::get_global_colors()', 'GlobalData::sanitize_global_colors_data()',
|
||||||
'GlobalData::set_global_colors()'],
|
'GlobalData::set_global_colors()'],
|
||||||
|
|||||||
@@ -5,14 +5,14 @@ declare(strict_types=1);
|
|||||||
namespace LIT\MCP\Tests\Unit\Integrations\Divi\Design;
|
namespace LIT\MCP\Tests\Unit\Integrations\Divi\Design;
|
||||||
|
|
||||||
use Brain\Monkey\Functions;
|
use Brain\Monkey\Functions;
|
||||||
|
use LIT\MCP\Compatibility\ReleaseState;
|
||||||
use LIT\MCP\Integrations\Divi\Design\GlobalVariablesAdapter;
|
use LIT\MCP\Integrations\Divi\Design\GlobalVariablesAdapter;
|
||||||
use LIT\MCP\Integrations\Divi\Release\Call;
|
use LIT\MCP\Compatibility\Call;
|
||||||
use LIT\MCP\Integrations\Divi\Release\DiviAdapters;
|
use LIT\MCP\Integrations\Divi\Release\DiviAdapters;
|
||||||
|
use LIT\MCP\Integrations\Divi\Release\DiviAreas;
|
||||||
use LIT\MCP\Integrations\Divi\Release\DiviFeature;
|
use LIT\MCP\Integrations\Divi\Release\DiviFeature;
|
||||||
use LIT\MCP\Integrations\Divi\Release\DiviLocked;
|
use LIT\MCP\Integrations\Divi\Release\DiviLocked;
|
||||||
use LIT\MCP\Integrations\Divi\Release\Manifest;
|
|
||||||
use LIT\MCP\Integrations\Divi\Release\ReleaseGate;
|
use LIT\MCP\Integrations\Divi\Release\ReleaseGate;
|
||||||
use LIT\MCP\Integrations\Divi\Release\ReleaseState;
|
|
||||||
use LIT\MCP\Integrations\Divi\Release\ReleaseStatus;
|
use LIT\MCP\Integrations\Divi\Release\ReleaseStatus;
|
||||||
use LIT\MCP\Tests\Support\ReleaseMatrices;
|
use LIT\MCP\Tests\Support\ReleaseMatrices;
|
||||||
use LIT\MCP\Tests\Unit\TestCase;
|
use LIT\MCP\Tests\Unit\TestCase;
|
||||||
@@ -33,7 +33,7 @@ final class GlobalVariablesAdapterTest extends TestCase
|
|||||||
$manifest = GlobalVariablesAdapter::manifest();
|
$manifest = GlobalVariablesAdapter::manifest();
|
||||||
|
|
||||||
self::assertContains(GlobalVariablesAdapter::class, DiviAdapters::CLASSES);
|
self::assertContains(GlobalVariablesAdapter::class, DiviAdapters::CLASSES);
|
||||||
self::assertSame(Manifest::DESIGN, $manifest->area);
|
self::assertSame(DiviAreas::DESIGN, $manifest->area);
|
||||||
self::assertSame(
|
self::assertSame(
|
||||||
['GlobalData::get_global_variables()', 'GlobalData::set_global_variables()', 'et_pb_is_allowed()'],
|
['GlobalData::get_global_variables()', 'GlobalData::set_global_variables()', 'et_pb_is_allowed()'],
|
||||||
array_map(static fn (Call $call): string => $call->label(), $manifest->calls)
|
array_map(static fn (Call $call): string => $call->label(), $manifest->calls)
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ use LIT\MCP\Integrations\Divi\Pages\DiviSaver;
|
|||||||
use LIT\MCP\Integrations\Divi\Pages\SaveScope;
|
use LIT\MCP\Integrations\Divi\Pages\SaveScope;
|
||||||
use LIT\MCP\Integrations\Divi\Release\DiviFeature;
|
use LIT\MCP\Integrations\Divi\Release\DiviFeature;
|
||||||
use LIT\MCP\Integrations\Divi\Release\DiviLocked;
|
use LIT\MCP\Integrations\Divi\Release\DiviLocked;
|
||||||
use LIT\MCP\Integrations\Divi\Release\ReleaseState;
|
use LIT\MCP\Compatibility\ReleaseState;
|
||||||
use LIT\MCP\Tests\Support\FakeChangeLog;
|
use LIT\MCP\Tests\Support\FakeChangeLog;
|
||||||
use LIT\MCP\Tests\Support\LibraryFixtures;
|
use LIT\MCP\Tests\Support\LibraryFixtures;
|
||||||
use LIT\MCP\Tests\Support\ReleaseMatrices;
|
use LIT\MCP\Tests\Support\ReleaseMatrices;
|
||||||
|
|||||||
@@ -6,14 +6,14 @@ namespace LIT\MCP\Tests\Unit\Integrations\Divi\Design;
|
|||||||
|
|
||||||
use Brain\Monkey\Functions;
|
use Brain\Monkey\Functions;
|
||||||
use InvalidArgumentException;
|
use InvalidArgumentException;
|
||||||
|
use LIT\MCP\Compatibility\ReleaseState;
|
||||||
use LIT\MCP\Integrations\Divi\Design\ThemeOptionsAdapter;
|
use LIT\MCP\Integrations\Divi\Design\ThemeOptionsAdapter;
|
||||||
use LIT\MCP\Integrations\Divi\Release\Call;
|
use LIT\MCP\Compatibility\Call;
|
||||||
use LIT\MCP\Integrations\Divi\Release\DiviAdapters;
|
use LIT\MCP\Integrations\Divi\Release\DiviAdapters;
|
||||||
|
use LIT\MCP\Integrations\Divi\Release\DiviAreas;
|
||||||
use LIT\MCP\Integrations\Divi\Release\DiviFeature;
|
use LIT\MCP\Integrations\Divi\Release\DiviFeature;
|
||||||
use LIT\MCP\Integrations\Divi\Release\DiviLocked;
|
use LIT\MCP\Integrations\Divi\Release\DiviLocked;
|
||||||
use LIT\MCP\Integrations\Divi\Release\Manifest;
|
|
||||||
use LIT\MCP\Integrations\Divi\Release\ReleaseGate;
|
use LIT\MCP\Integrations\Divi\Release\ReleaseGate;
|
||||||
use LIT\MCP\Integrations\Divi\Release\ReleaseState;
|
|
||||||
use LIT\MCP\Integrations\Divi\Release\ReleaseStatus;
|
use LIT\MCP\Integrations\Divi\Release\ReleaseStatus;
|
||||||
use LIT\MCP\Tests\Support\ReleaseMatrices;
|
use LIT\MCP\Tests\Support\ReleaseMatrices;
|
||||||
use LIT\MCP\Tests\Unit\TestCase;
|
use LIT\MCP\Tests\Unit\TestCase;
|
||||||
@@ -40,7 +40,7 @@ final class ThemeOptionsAdapterTest extends TestCase
|
|||||||
$manifest = ThemeOptionsAdapter::manifest();
|
$manifest = ThemeOptionsAdapter::manifest();
|
||||||
|
|
||||||
self::assertContains(ThemeOptionsAdapter::class, DiviAdapters::CLASSES);
|
self::assertContains(ThemeOptionsAdapter::class, DiviAdapters::CLASSES);
|
||||||
self::assertSame(Manifest::DESIGN, $manifest->area);
|
self::assertSame(DiviAreas::DESIGN, $manifest->area);
|
||||||
self::assertSame(
|
self::assertSame(
|
||||||
[
|
[
|
||||||
'et_sanitize_font_choices()', 'et_sanitize_global_font_weight()', 'et_sanitize_float_number()',
|
'et_sanitize_font_choices()', 'et_sanitize_global_font_weight()', 'et_sanitize_float_number()',
|
||||||
|
|||||||
@@ -5,10 +5,11 @@ declare(strict_types=1);
|
|||||||
namespace LIT\MCP\Tests\Unit\Integrations\Divi;
|
namespace LIT\MCP\Tests\Unit\Integrations\Divi;
|
||||||
|
|
||||||
use LIT\MCP\Integrations\Divi\DiviCompatibility;
|
use LIT\MCP\Integrations\Divi\DiviCompatibility;
|
||||||
use LIT\MCP\Integrations\Divi\Release\Call;
|
use LIT\MCP\Compatibility\Call;
|
||||||
use LIT\MCP\Integrations\Divi\Release\Manifest;
|
use LIT\MCP\Integrations\Divi\Release\DiviAreas;
|
||||||
use LIT\MCP\Integrations\Divi\Release\ManifestCheck;
|
use LIT\MCP\Compatibility\Manifest;
|
||||||
use LIT\MCP\Integrations\Divi\Release\Mirror;
|
use LIT\MCP\Compatibility\ManifestCheck;
|
||||||
|
use LIT\MCP\Compatibility\Mirror;
|
||||||
use PHPUnit\Framework\TestCase;
|
use PHPUnit\Framework\TestCase;
|
||||||
use RuntimeException;
|
use RuntimeException;
|
||||||
|
|
||||||
@@ -31,7 +32,7 @@ final class DiviCompatibilityTest extends TestCase
|
|||||||
{
|
{
|
||||||
$check = new ManifestCheck(
|
$check = new ManifestCheck(
|
||||||
['X' => new Manifest(
|
['X' => new Manifest(
|
||||||
Manifest::LIBRARY,
|
DiviAreas::LIBRARY,
|
||||||
calls: [new Call('strlen', 1)],
|
calls: [new Call('strlen', 1)],
|
||||||
postTypes: ['et_pb_layout'],
|
postTypes: ['et_pb_layout'],
|
||||||
mirrors: [new Mirror('m', 'a.php', 'a', null, 'Terme')]
|
mirrors: [new Mirror('m', 'a.php', 'a', null, 'Terme')]
|
||||||
@@ -51,7 +52,7 @@ final class DiviCompatibilityTest extends TestCase
|
|||||||
{
|
{
|
||||||
$labels = implode("\n", array_keys(DiviCompatibility::defaults()));
|
$labels = implode("\n", array_keys(DiviCompatibility::defaults()));
|
||||||
|
|
||||||
$areas = [Manifest::PAGES, Manifest::LIBRARY, Manifest::THEME_BUILDER, Manifest::DESIGN, Manifest::CATALOG];
|
$areas = [DiviAreas::PAGES, DiviAreas::LIBRARY, DiviAreas::THEME_BUILDER, DiviAreas::DESIGN, DiviAreas::CATALOG];
|
||||||
foreach ($areas as $area) {
|
foreach ($areas as $area) {
|
||||||
self::assertStringContainsString($area . ': ', $labels);
|
self::assertStringContainsString($area . ': ', $labels);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,13 +5,13 @@ declare(strict_types=1);
|
|||||||
namespace LIT\MCP\Tests\Unit\Integrations\Divi;
|
namespace LIT\MCP\Tests\Unit\Integrations\Divi;
|
||||||
|
|
||||||
use Brain\Monkey\Functions;
|
use Brain\Monkey\Functions;
|
||||||
|
use LIT\MCP\Compatibility\ReleaseState;
|
||||||
use LIT\MCP\Integrations\Core\EnvironmentComponent;
|
use LIT\MCP\Integrations\Core\EnvironmentComponent;
|
||||||
use LIT\MCP\Integrations\Divi\DiviCompatibility;
|
use LIT\MCP\Integrations\Divi\DiviCompatibility;
|
||||||
use LIT\MCP\Integrations\Divi\DiviEnvironmentComponent;
|
use LIT\MCP\Integrations\Divi\DiviEnvironmentComponent;
|
||||||
use LIT\MCP\Integrations\Divi\Release\DiviFeature;
|
use LIT\MCP\Integrations\Divi\Release\DiviFeature;
|
||||||
use LIT\MCP\Integrations\Divi\Release\FeatureOverview;
|
use LIT\MCP\Integrations\Divi\Release\FeatureOverview;
|
||||||
use LIT\MCP\Integrations\Divi\Release\ReleaseGate;
|
use LIT\MCP\Integrations\Divi\Release\ReleaseGate;
|
||||||
use LIT\MCP\Integrations\Divi\Release\ReleaseState;
|
|
||||||
use LIT\MCP\Integrations\Divi\Release\ReleaseStatus;
|
use LIT\MCP\Integrations\Divi\Release\ReleaseStatus;
|
||||||
use LIT\MCP\Tests\Support\FeatureFakeTool;
|
use LIT\MCP\Tests\Support\FeatureFakeTool;
|
||||||
use LIT\MCP\Tests\Support\MatrixFixtures;
|
use LIT\MCP\Tests\Support\MatrixFixtures;
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ use LIT\MCP\Abilities\WriteFailed;
|
|||||||
use LIT\MCP\Integrations\Divi\Library\DiviLibraryStore;
|
use LIT\MCP\Integrations\Divi\Library\DiviLibraryStore;
|
||||||
use LIT\MCP\Integrations\Divi\Library\LibraryItemSpec;
|
use LIT\MCP\Integrations\Divi\Library\LibraryItemSpec;
|
||||||
use LIT\MCP\Integrations\Divi\Release\DiviAdapters;
|
use LIT\MCP\Integrations\Divi\Release\DiviAdapters;
|
||||||
use LIT\MCP\Integrations\Divi\Release\Manifest;
|
use LIT\MCP\Integrations\Divi\Release\DiviAreas;
|
||||||
use LIT\MCP\Integrations\WordPress\Content\NewDraft;
|
use LIT\MCP\Integrations\WordPress\Content\NewDraft;
|
||||||
use LIT\MCP\Tests\Support\FakeChangeLog;
|
use LIT\MCP\Tests\Support\FakeChangeLog;
|
||||||
use LIT\MCP\Tests\Unit\TestCase;
|
use LIT\MCP\Tests\Unit\TestCase;
|
||||||
@@ -121,7 +121,7 @@ final class DiviLibraryStoreTest extends TestCase
|
|||||||
$manifest = DiviLibraryStore::manifest();
|
$manifest = DiviLibraryStore::manifest();
|
||||||
|
|
||||||
self::assertContains(DiviLibraryStore::class, DiviAdapters::CLASSES);
|
self::assertContains(DiviLibraryStore::class, DiviAdapters::CLASSES);
|
||||||
self::assertSame(Manifest::LIBRARY, $manifest->area);
|
self::assertSame(DiviAreas::LIBRARY, $manifest->area);
|
||||||
self::assertSame(['et_pb_layout'], $manifest->postTypes);
|
self::assertSame(['et_pb_layout'], $manifest->postTypes);
|
||||||
self::assertSame(
|
self::assertSame(
|
||||||
['scope', 'layout_type', 'module_width', 'layout_category', 'layout_tag'],
|
['scope', 'layout_type', 'module_width', 'layout_category', 'layout_tag'],
|
||||||
|
|||||||
@@ -4,13 +4,13 @@ declare(strict_types=1);
|
|||||||
|
|
||||||
namespace LIT\MCP\Tests\Unit\Integrations\Divi\Pages;
|
namespace LIT\MCP\Tests\Unit\Integrations\Divi\Pages;
|
||||||
|
|
||||||
|
use LIT\MCP\Compatibility\ReleaseState;
|
||||||
use LIT\MCP\Integrations\Divi\BlockTree\Parser;
|
use LIT\MCP\Integrations\Divi\BlockTree\Parser;
|
||||||
use LIT\MCP\Integrations\Divi\Compose\VariableRef;
|
use LIT\MCP\Integrations\Divi\Compose\VariableRef;
|
||||||
use LIT\MCP\Integrations\Divi\Pages\DiviContentComposer;
|
use LIT\MCP\Integrations\Divi\Pages\DiviContentComposer;
|
||||||
use LIT\MCP\Integrations\Divi\Pages\DiviSaver;
|
use LIT\MCP\Integrations\Divi\Pages\DiviSaver;
|
||||||
use LIT\MCP\Integrations\Divi\Pages\DynamicContentMap;
|
use LIT\MCP\Integrations\Divi\Pages\DynamicContentMap;
|
||||||
use LIT\MCP\Integrations\Divi\Release\DiviFeature;
|
use LIT\MCP\Integrations\Divi\Release\DiviFeature;
|
||||||
use LIT\MCP\Integrations\Divi\Release\ReleaseState;
|
|
||||||
use LIT\MCP\Tests\Support\DiviFeatureFixtures;
|
use LIT\MCP\Tests\Support\DiviFeatureFixtures;
|
||||||
use LIT\MCP\Tests\Support\DiviFixtures;
|
use LIT\MCP\Tests\Support\DiviFixtures;
|
||||||
use LIT\MCP\Tests\Support\DiviWriterFixture;
|
use LIT\MCP\Tests\Support\DiviWriterFixture;
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ namespace LIT\MCP\Tests\Unit\Integrations\Divi\Pages;
|
|||||||
use Brain\Monkey\Functions;
|
use Brain\Monkey\Functions;
|
||||||
use LIT\MCP\Integrations\Divi\Pages\DiviPages;
|
use LIT\MCP\Integrations\Divi\Pages\DiviPages;
|
||||||
use LIT\MCP\Integrations\Divi\Release\DiviAdapters;
|
use LIT\MCP\Integrations\Divi\Release\DiviAdapters;
|
||||||
use LIT\MCP\Integrations\Divi\Release\Manifest;
|
use LIT\MCP\Integrations\Divi\Release\DiviAreas;
|
||||||
use LIT\MCP\Tests\Unit\TestCase;
|
use LIT\MCP\Tests\Unit\TestCase;
|
||||||
use RuntimeException;
|
use RuntimeException;
|
||||||
use WP_Post;
|
use WP_Post;
|
||||||
@@ -63,7 +63,7 @@ final class DiviPagesTest extends TestCase
|
|||||||
$manifest = DiviPages::manifest();
|
$manifest = DiviPages::manifest();
|
||||||
|
|
||||||
self::assertContains(DiviPages::class, DiviAdapters::CLASSES);
|
self::assertContains(DiviPages::class, DiviAdapters::CLASSES);
|
||||||
self::assertSame(Manifest::PAGES, $manifest->area);
|
self::assertSame(DiviAreas::PAGES, $manifest->area);
|
||||||
self::assertSame(['vb-sync-flags'], array_map(static fn ($mirror): string => $mirror->id, $manifest->mirrors));
|
self::assertSame(['vb-sync-flags'], array_map(static fn ($mirror): string => $mirror->id, $manifest->mirrors));
|
||||||
self::assertSame('SyncToServerController::update()', $manifest->mirrors[0]->label());
|
self::assertSame('SyncToServerController::update()', $manifest->mirrors[0]->label());
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ use Brain\Monkey\Functions;
|
|||||||
use LIT\MCP\Integrations\Divi\Release\CheckStep;
|
use LIT\MCP\Integrations\Divi\Release\CheckStep;
|
||||||
use LIT\MCP\Integrations\Divi\Release\CompatibilityCheck;
|
use LIT\MCP\Integrations\Divi\Release\CompatibilityCheck;
|
||||||
use LIT\MCP\Integrations\Divi\Release\FormatCheck;
|
use LIT\MCP\Integrations\Divi\Release\FormatCheck;
|
||||||
use LIT\MCP\Integrations\Divi\Release\ManifestCheck;
|
use LIT\MCP\Compatibility\ManifestCheck;
|
||||||
use LIT\MCP\Integrations\Divi\Release\WriteProbe;
|
use LIT\MCP\Integrations\Divi\Release\WriteProbe;
|
||||||
use LIT\MCP\Plugin;
|
use LIT\MCP\Plugin;
|
||||||
use LIT\MCP\Tests\Unit\TestCase;
|
use LIT\MCP\Tests\Unit\TestCase;
|
||||||
|
|||||||
@@ -0,0 +1,20 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace LIT\MCP\Tests\Unit\Integrations\Divi\Release;
|
||||||
|
|
||||||
|
use LIT\MCP\Integrations\Divi\Release\DiviAreas;
|
||||||
|
use PHPUnit\Framework\TestCase;
|
||||||
|
|
||||||
|
final class DiviAreasTest extends TestCase
|
||||||
|
{
|
||||||
|
public function testTheFiveAreasAreNamedAsInSpecSection3(): void
|
||||||
|
{
|
||||||
|
self::assertSame('Seiten', DiviAreas::PAGES);
|
||||||
|
self::assertSame('Bibliothek', DiviAreas::LIBRARY);
|
||||||
|
self::assertSame('Theme Builder', DiviAreas::THEME_BUILDER);
|
||||||
|
self::assertSame('Designsystem', DiviAreas::DESIGN);
|
||||||
|
self::assertSame('Katalog', DiviAreas::CATALOG);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -17,7 +17,7 @@ use LIT\MCP\Integrations\Divi\Pages\DiviPages;
|
|||||||
use LIT\MCP\Integrations\Divi\Pages\DynamicContentMap;
|
use LIT\MCP\Integrations\Divi\Pages\DynamicContentMap;
|
||||||
use LIT\MCP\Integrations\Divi\Release\DiviAdapters;
|
use LIT\MCP\Integrations\Divi\Release\DiviAdapters;
|
||||||
use LIT\MCP\Integrations\Divi\Release\DiviFeature;
|
use LIT\MCP\Integrations\Divi\Release\DiviFeature;
|
||||||
use LIT\MCP\Integrations\Divi\Release\Mirror;
|
use LIT\MCP\Compatibility\Mirror;
|
||||||
use LIT\MCP\Integrations\Divi\Schema\DiviModules;
|
use LIT\MCP\Integrations\Divi\Schema\DiviModules;
|
||||||
use LIT\MCP\Integrations\Divi\ThemeBuilder\DiviThemeBuilder;
|
use LIT\MCP\Integrations\Divi\ThemeBuilder\DiviThemeBuilder;
|
||||||
use PHPUnit\Framework\TestCase;
|
use PHPUnit\Framework\TestCase;
|
||||||
|
|||||||
@@ -7,11 +7,11 @@ namespace LIT\MCP\Tests\Unit\Integrations\Divi\Release;
|
|||||||
use Brain\Monkey\Functions;
|
use Brain\Monkey\Functions;
|
||||||
use LIT\MCP\Abilities\Ability;
|
use LIT\MCP\Abilities\Ability;
|
||||||
use LIT\MCP\Abilities\DeclaresRequirements;
|
use LIT\MCP\Abilities\DeclaresRequirements;
|
||||||
|
use LIT\MCP\Compatibility\ReleaseState;
|
||||||
use LIT\MCP\Integrations\Divi\DiviIntegration;
|
use LIT\MCP\Integrations\Divi\DiviIntegration;
|
||||||
use LIT\MCP\Integrations\Divi\Release\DiviFeature;
|
use LIT\MCP\Integrations\Divi\Release\DiviFeature;
|
||||||
use LIT\MCP\Integrations\Divi\Release\DiviFeatureGate;
|
use LIT\MCP\Integrations\Divi\Release\DiviFeatureGate;
|
||||||
use LIT\MCP\Integrations\Divi\Release\FeatureSets;
|
use LIT\MCP\Integrations\Divi\Release\FeatureSets;
|
||||||
use LIT\MCP\Integrations\Divi\Release\ReleaseState;
|
|
||||||
use LIT\MCP\Integrations\Divi\Release\RequiresDiviFeatures;
|
use LIT\MCP\Integrations\Divi\Release\RequiresDiviFeatures;
|
||||||
use LIT\MCP\Integrations\WordPress\Content\ContentComposer;
|
use LIT\MCP\Integrations\WordPress\Content\ContentComposer;
|
||||||
use LIT\MCP\Integrations\WordPress\Content\ContentCreateAbility;
|
use LIT\MCP\Integrations\WordPress\Content\ContentCreateAbility;
|
||||||
|
|||||||
@@ -5,9 +5,9 @@ declare(strict_types=1);
|
|||||||
namespace LIT\MCP\Tests\Unit\Integrations\Divi\Release;
|
namespace LIT\MCP\Tests\Unit\Integrations\Divi\Release;
|
||||||
|
|
||||||
use LIT\MCP\Abilities\ToolRefusal;
|
use LIT\MCP\Abilities\ToolRefusal;
|
||||||
|
use LIT\MCP\Compatibility\ReleaseState;
|
||||||
use LIT\MCP\Integrations\Divi\Release\DiviFeature;
|
use LIT\MCP\Integrations\Divi\Release\DiviFeature;
|
||||||
use LIT\MCP\Integrations\Divi\Release\DiviLocked;
|
use LIT\MCP\Integrations\Divi\Release\DiviLocked;
|
||||||
use LIT\MCP\Integrations\Divi\Release\ReleaseState;
|
|
||||||
use LIT\MCP\Tests\Support\ReleaseMatrices;
|
use LIT\MCP\Tests\Support\ReleaseMatrices;
|
||||||
use LIT\MCP\Tests\Unit\TestCase;
|
use LIT\MCP\Tests\Unit\TestCase;
|
||||||
use LogicException;
|
use LogicException;
|
||||||
|
|||||||
@@ -0,0 +1,37 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace LIT\MCP\Tests\Unit\Integrations\Divi\Release;
|
||||||
|
|
||||||
|
use LIT\MCP\Integrations\Divi\Release\DiviAdapters;
|
||||||
|
use LIT\MCP\Integrations\Divi\Release\DiviManifestCheck;
|
||||||
|
use LIT\MCP\Tests\Unit\TestCase;
|
||||||
|
|
||||||
|
final class DiviManifestCheckTest extends TestCase
|
||||||
|
{
|
||||||
|
public function testCreateChecksEveryDiviManifest(): void
|
||||||
|
{
|
||||||
|
$code = [];
|
||||||
|
$mirrors = [];
|
||||||
|
foreach (DiviAdapters::manifests() as $manifest) {
|
||||||
|
foreach ([...$manifest->calls, ...$manifest->constants] as $requirement) {
|
||||||
|
$code[] = $manifest->area . ': ' . $requirement->label();
|
||||||
|
}
|
||||||
|
$mirrors = [...$mirrors, ...array_map(static fn ($mirror): string => $mirror->id, $manifest->mirrors)];
|
||||||
|
}
|
||||||
|
$check = DiviManifestCheck::create();
|
||||||
|
|
||||||
|
self::assertNotSame([], $code);
|
||||||
|
self::assertSame(array_values(array_unique($code)), array_keys($check->codeChecks()));
|
||||||
|
self::assertCount(count(array_unique($mirrors)), $check->mirrorChecks());
|
||||||
|
self::assertNotSame([], $check->registrationChecks(), 'DiviModules::knowsBlock is wired for block types');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testCreateLoadsTheSignatureReferences(): void
|
||||||
|
{
|
||||||
|
$kinds = array_map(static fn ($problem): string => $problem->kind, DiviManifestCheck::create()->codeProblems());
|
||||||
|
|
||||||
|
self::assertNotContains('reference-missing', $kinds);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -4,10 +4,10 @@ declare(strict_types=1);
|
|||||||
|
|
||||||
namespace LIT\MCP\Tests\Unit\Integrations\Divi\Release;
|
namespace LIT\MCP\Tests\Unit\Integrations\Divi\Release;
|
||||||
|
|
||||||
use LIT\MCP\Integrations\Divi\Release\Call;
|
use LIT\MCP\Compatibility\Call;
|
||||||
|
use LIT\MCP\Compatibility\SignatureFingerprint;
|
||||||
use LIT\MCP\Integrations\Divi\Release\DiviAdapters;
|
use LIT\MCP\Integrations\Divi\Release\DiviAdapters;
|
||||||
use LIT\MCP\Integrations\Divi\Release\DiviReference;
|
use LIT\MCP\Integrations\Divi\Release\DiviReference;
|
||||||
use LIT\MCP\Integrations\Divi\Release\SignatureFingerprint;
|
|
||||||
use PHPUnit\Framework\TestCase;
|
use PHPUnit\Framework\TestCase;
|
||||||
use RuntimeException;
|
use RuntimeException;
|
||||||
|
|
||||||
@@ -19,7 +19,7 @@ final class DiviReferenceTest extends TestCase
|
|||||||
$signatureKeys = [];
|
$signatureKeys = [];
|
||||||
foreach (DiviAdapters::manifests() as $manifest) {
|
foreach (DiviAdapters::manifests() as $manifest) {
|
||||||
foreach ($manifest->calls as $call) {
|
foreach ($manifest->calls as $call) {
|
||||||
$signatureKeys[] = 'sig:' . ltrim($call->symbol, '\\');
|
$signatureKeys[] = $call->signatureKey();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
$keys = array_values(array_unique(array_merge($mirrorIds, $signatureKeys)));
|
$keys = array_values(array_unique(array_merge($mirrorIds, $signatureKeys)));
|
||||||
@@ -40,10 +40,10 @@ final class DiviReferenceTest extends TestCase
|
|||||||
foreach (DiviAdapters::mirrors() as $mirror) {
|
foreach (DiviAdapters::mirrors() as $mirror) {
|
||||||
self::assertStringStartsNotWith(DiviReference::SIGNATURE_PREFIX, $mirror->id);
|
self::assertStringStartsNotWith(DiviReference::SIGNATURE_PREFIX, $mirror->id);
|
||||||
}
|
}
|
||||||
self::assertSame('sig:et_pb_is_allowed', DiviReference::signatureKey(new Call('et_pb_is_allowed', 1)));
|
self::assertSame('sig:et_pb_is_allowed', (new Call('et_pb_is_allowed', 1))->signatureKey());
|
||||||
self::assertSame(
|
self::assertSame(
|
||||||
'sig:ET_Core_PageResource::remove_static_resources',
|
'sig:ET_Core_PageResource::remove_static_resources',
|
||||||
DiviReference::signatureKey(new Call('\\ET_Core_PageResource::remove_static_resources', 3))
|
(new Call('\\ET_Core_PageResource::remove_static_resources', 3))->signatureKey()
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -4,9 +4,9 @@ declare(strict_types=1);
|
|||||||
|
|
||||||
namespace LIT\MCP\Tests\Unit\Integrations\Divi\Release;
|
namespace LIT\MCP\Tests\Unit\Integrations\Divi\Release;
|
||||||
|
|
||||||
|
use LIT\MCP\Compatibility\ReleaseState;
|
||||||
use LIT\MCP\Integrations\Divi\Release\DiviFeature;
|
use LIT\MCP\Integrations\Divi\Release\DiviFeature;
|
||||||
use LIT\MCP\Integrations\Divi\Release\FeatureOverview;
|
use LIT\MCP\Integrations\Divi\Release\FeatureOverview;
|
||||||
use LIT\MCP\Integrations\Divi\Release\ReleaseState;
|
|
||||||
use LIT\MCP\Tests\Support\FeatureFakeTool;
|
use LIT\MCP\Tests\Support\FeatureFakeTool;
|
||||||
use LIT\MCP\Tests\Support\MatrixFixtures;
|
use LIT\MCP\Tests\Support\MatrixFixtures;
|
||||||
use PHPUnit\Framework\TestCase;
|
use PHPUnit\Framework\TestCase;
|
||||||
|
|||||||
@@ -6,11 +6,13 @@ namespace LIT\MCP\Tests\Unit\Integrations\Divi\Release;
|
|||||||
|
|
||||||
use Brain\Monkey\Functions;
|
use Brain\Monkey\Functions;
|
||||||
use LIT\MCP\Abilities\WriteFailed;
|
use LIT\MCP\Abilities\WriteFailed;
|
||||||
|
use LIT\MCP\Compatibility\Capability;
|
||||||
|
use LIT\MCP\Compatibility\CompatibilityMatrix;
|
||||||
|
use LIT\MCP\Compatibility\ReleaseState;
|
||||||
use LIT\MCP\Integrations\Divi\Release\DiviFeature;
|
use LIT\MCP\Integrations\Divi\Release\DiviFeature;
|
||||||
use LIT\MCP\Integrations\Divi\Release\DiviLocked;
|
use LIT\MCP\Integrations\Divi\Release\DiviLocked;
|
||||||
use LIT\MCP\Integrations\Divi\Release\ReleaseGate;
|
use LIT\MCP\Integrations\Divi\Release\ReleaseGate;
|
||||||
use LIT\MCP\Integrations\Divi\Release\ReleaseResolver;
|
use LIT\MCP\Integrations\Divi\Release\ReleaseResolver;
|
||||||
use LIT\MCP\Integrations\Divi\Release\ReleaseState;
|
|
||||||
use LIT\MCP\Integrations\Divi\Release\ReleaseStatus;
|
use LIT\MCP\Integrations\Divi\Release\ReleaseStatus;
|
||||||
use LIT\MCP\Tests\Support\DiviFeatureFixtures;
|
use LIT\MCP\Tests\Support\DiviFeatureFixtures;
|
||||||
use LIT\MCP\Tests\Support\ReleaseMatrices;
|
use LIT\MCP\Tests\Support\ReleaseMatrices;
|
||||||
@@ -43,6 +45,37 @@ final class ReleaseGateTest extends TestCase
|
|||||||
self::assertSame('5.3.0', $lock->status->version);
|
self::assertSame('5.3.0', $lock->status->version);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function testALockWhoseLockedCapabilityIsNoDiviFeatureStillRefusesTheFeatureAsked(): void
|
||||||
|
{
|
||||||
|
$foreign = new class () implements Capability {
|
||||||
|
public function id(): string
|
||||||
|
{
|
||||||
|
return DiviFeature::PageWrite->id();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function label(): string
|
||||||
|
{
|
||||||
|
return 'fremde Fähigkeit';
|
||||||
|
}
|
||||||
|
|
||||||
|
public function isWrite(): bool
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
ReleaseGate::useResolver(static fn (): ReleaseStatus => ReleaseStatus::of(
|
||||||
|
'5.3.0',
|
||||||
|
CompatibilityMatrix::uniform([$foreign], ReleaseState::Incompatible, ['fremde Fähigkeit'])
|
||||||
|
));
|
||||||
|
|
||||||
|
try {
|
||||||
|
ReleaseGate::assertFeature(DiviFeature::PageWrite);
|
||||||
|
self::fail('a locked feature must refuse');
|
||||||
|
} catch (DiviLocked $locked) {
|
||||||
|
self::assertSame([DiviFeature::PageWrite], $locked->features);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public function testAssertFeatureRefusesOnlyALockedFeature(): void
|
public function testAssertFeatureRefusesOnlyALockedFeature(): void
|
||||||
{
|
{
|
||||||
ReleaseGate::useResolver(static fn (): ReleaseStatus => ReleaseMatrices::status(
|
ReleaseGate::useResolver(static fn (): ReleaseStatus => ReleaseMatrices::status(
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ declare(strict_types=1);
|
|||||||
namespace LIT\MCP\Tests\Unit\Integrations\Divi\Release;
|
namespace LIT\MCP\Tests\Unit\Integrations\Divi\Release;
|
||||||
|
|
||||||
use Brain\Monkey\Functions;
|
use Brain\Monkey\Functions;
|
||||||
|
use LIT\MCP\Compatibility\ReleaseState;
|
||||||
use LIT\MCP\Integrations\Divi\Design\DesignSystemWriter;
|
use LIT\MCP\Integrations\Divi\Design\DesignSystemWriter;
|
||||||
use LIT\MCP\Integrations\Divi\Library\DiviLibraryStore;
|
use LIT\MCP\Integrations\Divi\Library\DiviLibraryStore;
|
||||||
use LIT\MCP\Integrations\Divi\Library\LibraryItemSpec;
|
use LIT\MCP\Integrations\Divi\Library\LibraryItemSpec;
|
||||||
@@ -14,7 +15,6 @@ use LIT\MCP\Integrations\Divi\Pages\SaveScope;
|
|||||||
use LIT\MCP\Integrations\Divi\Release\DiviFeature;
|
use LIT\MCP\Integrations\Divi\Release\DiviFeature;
|
||||||
use LIT\MCP\Integrations\Divi\Release\DiviLocked;
|
use LIT\MCP\Integrations\Divi\Release\DiviLocked;
|
||||||
use LIT\MCP\Integrations\Divi\Release\ReleaseGate;
|
use LIT\MCP\Integrations\Divi\Release\ReleaseGate;
|
||||||
use LIT\MCP\Integrations\Divi\Release\ReleaseState;
|
|
||||||
use LIT\MCP\Integrations\Divi\Release\ReleaseStatus;
|
use LIT\MCP\Integrations\Divi\Release\ReleaseStatus;
|
||||||
use LIT\MCP\Integrations\Divi\ThemeBuilder\DiviThemeBuilder;
|
use LIT\MCP\Integrations\Divi\ThemeBuilder\DiviThemeBuilder;
|
||||||
use LIT\MCP\Integrations\WordPress\Content\NewDraft;
|
use LIT\MCP\Integrations\WordPress\Content\NewDraft;
|
||||||
|
|||||||
@@ -6,11 +6,11 @@ namespace LIT\MCP\Tests\Unit\Integrations\Divi\Release;
|
|||||||
|
|
||||||
use Brain\Monkey\Filters;
|
use Brain\Monkey\Filters;
|
||||||
use Brain\Monkey\Functions;
|
use Brain\Monkey\Functions;
|
||||||
|
use LIT\MCP\Compatibility\ReleaseState;
|
||||||
use LIT\MCP\Integrations\Divi\Release\DiviFeature;
|
use LIT\MCP\Integrations\Divi\Release\DiviFeature;
|
||||||
use LIT\MCP\Integrations\Divi\Release\ManifestCheck;
|
use LIT\MCP\Compatibility\ManifestCheck;
|
||||||
use LIT\MCP\Integrations\Divi\Release\Problem;
|
use LIT\MCP\Compatibility\Problem;
|
||||||
use LIT\MCP\Integrations\Divi\Release\ReleaseResolver;
|
use LIT\MCP\Integrations\Divi\Release\ReleaseResolver;
|
||||||
use LIT\MCP\Integrations\Divi\Release\ReleaseState;
|
|
||||||
use LIT\MCP\Integrations\Divi\Release\ReleaseStatus;
|
use LIT\MCP\Integrations\Divi\Release\ReleaseStatus;
|
||||||
use LIT\MCP\Integrations\Divi\Release\ReleaseStore;
|
use LIT\MCP\Integrations\Divi\Release\ReleaseStore;
|
||||||
use LIT\MCP\Plugin;
|
use LIT\MCP\Plugin;
|
||||||
|
|||||||
@@ -4,10 +4,10 @@ declare(strict_types=1);
|
|||||||
|
|
||||||
namespace LIT\MCP\Tests\Unit\Integrations\Divi\Release;
|
namespace LIT\MCP\Tests\Unit\Integrations\Divi\Release;
|
||||||
|
|
||||||
use LIT\MCP\Integrations\Divi\Release\CompatibilityMatrix;
|
use LIT\MCP\Compatibility\ReleaseState;
|
||||||
|
use LIT\MCP\Compatibility\CompatibilityMatrix;
|
||||||
use LIT\MCP\Integrations\Divi\Release\DiviFeature;
|
use LIT\MCP\Integrations\Divi\Release\DiviFeature;
|
||||||
use LIT\MCP\Integrations\Divi\Release\FeatureStatus;
|
use LIT\MCP\Compatibility\FeatureStatus;
|
||||||
use LIT\MCP\Integrations\Divi\Release\ReleaseState;
|
|
||||||
use LIT\MCP\Integrations\Divi\Release\ReleaseStatus;
|
use LIT\MCP\Integrations\Divi\Release\ReleaseStatus;
|
||||||
use LIT\MCP\Tests\Support\ReleaseMatrices;
|
use LIT\MCP\Tests\Support\ReleaseMatrices;
|
||||||
use LIT\MCP\Tests\Unit\TestCase;
|
use LIT\MCP\Tests\Unit\TestCase;
|
||||||
@@ -57,14 +57,14 @@ final class ReleaseStatusTest extends TestCase
|
|||||||
self::assertNull($status->source);
|
self::assertNull($status->source);
|
||||||
self::assertSame(['Seiten: et_x() – Signatur geändert'], $status->problems);
|
self::assertSame(['Seiten: et_x() – Signatur geändert'], $status->problems);
|
||||||
self::assertSame(['user_id' => 1], $status->release);
|
self::assertSame(['user_id' => 1], $status->release);
|
||||||
self::assertSame('auto', ReleaseStatus::of('5.99.0', CompatibilityMatrix::allReleased('auto'))->source);
|
self::assertSame('auto', ReleaseStatus::of('5.99.0', CompatibilityMatrix::allReleased(DiviFeature::cases(), 'auto'))->source);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testAMatrixInAnotherStateThanTheStatusIsRefused(): void
|
public function testAMatrixInAnotherStateThanTheStatusIsRefused(): void
|
||||||
{
|
{
|
||||||
$this->expectException(LogicException::class);
|
$this->expectException(LogicException::class);
|
||||||
|
|
||||||
new ReleaseStatus(ReleaseState::Released, '5.2.1', 'code', [], null, CompatibilityMatrix::allIncompatible('x'));
|
new ReleaseStatus(ReleaseState::Released, '5.2.1', 'code', [], null, CompatibilityMatrix::allIncompatible(DiviFeature::cases(), 'x'));
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testRefusalForAnUntestedFeatureNamesItAndKeepsTheOthersWorking(): void
|
public function testRefusalForAnUntestedFeatureNamesItAndKeepsTheOthersWorking(): void
|
||||||
@@ -101,7 +101,7 @@ final class ReleaseStatusTest extends TestCase
|
|||||||
$features[$feature->value] = $matrix->of($feature);
|
$features[$feature->value] = $matrix->of($feature);
|
||||||
}
|
}
|
||||||
$features['library-write'] = new FeatureStatus(DiviFeature::LibraryWrite, ReleaseState::Untested);
|
$features['library-write'] = new FeatureStatus(DiviFeature::LibraryWrite, ReleaseState::Untested);
|
||||||
$status = ReleaseStatus::of('5.99.0', new CompatibilityMatrix($features));
|
$status = ReleaseStatus::of('5.99.0', new CompatibilityMatrix(DiviFeature::cases(), $features));
|
||||||
|
|
||||||
$payload = self::assertToolError(
|
$payload = self::assertToolError(
|
||||||
$status->refusalFor([DiviFeature::PageWrite, DiviFeature::LibraryWrite, DiviFeature::ThemeBuilderWrite]),
|
$status->refusalFor([DiviFeature::PageWrite, DiviFeature::LibraryWrite, DiviFeature::ThemeBuilderWrite]),
|
||||||
|
|||||||
@@ -5,9 +5,9 @@ declare(strict_types=1);
|
|||||||
namespace LIT\MCP\Tests\Unit\Integrations\Divi\Release;
|
namespace LIT\MCP\Tests\Unit\Integrations\Divi\Release;
|
||||||
|
|
||||||
use Brain\Monkey\Functions;
|
use Brain\Monkey\Functions;
|
||||||
|
use LIT\MCP\Compatibility\ReleaseState;
|
||||||
use LIT\MCP\Integrations\Divi\Release\DiviFeature;
|
use LIT\MCP\Integrations\Divi\Release\DiviFeature;
|
||||||
use LIT\MCP\Integrations\Divi\Release\ReleaseGate;
|
use LIT\MCP\Integrations\Divi\Release\ReleaseGate;
|
||||||
use LIT\MCP\Integrations\Divi\Release\ReleaseState;
|
|
||||||
use LIT\MCP\Integrations\Divi\Release\ReleaseStatus;
|
use LIT\MCP\Integrations\Divi\Release\ReleaseStatus;
|
||||||
use LIT\MCP\Integrations\Divi\Release\WriteProbe;
|
use LIT\MCP\Integrations\Divi\Release\WriteProbe;
|
||||||
use LIT\MCP\Integrations\WordPress\Content\ContentComposer;
|
use LIT\MCP\Integrations\WordPress\Content\ContentComposer;
|
||||||
|
|||||||
@@ -6,10 +6,10 @@ namespace LIT\MCP\Tests\Unit\Integrations\Divi\Schema;
|
|||||||
|
|
||||||
use Brain\Monkey\Functions;
|
use Brain\Monkey\Functions;
|
||||||
use LIT\MCP\Integrations\Divi\Pages\DynamicContentMap;
|
use LIT\MCP\Integrations\Divi\Pages\DynamicContentMap;
|
||||||
use LIT\MCP\Integrations\Divi\Release\Call;
|
use LIT\MCP\Compatibility\Call;
|
||||||
use LIT\MCP\Integrations\Divi\Release\ConstantRequirement;
|
use LIT\MCP\Compatibility\ConstantRequirement;
|
||||||
use LIT\MCP\Integrations\Divi\Release\DiviAdapters;
|
use LIT\MCP\Integrations\Divi\Release\DiviAdapters;
|
||||||
use LIT\MCP\Integrations\Divi\Release\Manifest;
|
use LIT\MCP\Integrations\Divi\Release\DiviAreas;
|
||||||
use LIT\MCP\Integrations\Divi\Schema\DiviModules;
|
use LIT\MCP\Integrations\Divi\Schema\DiviModules;
|
||||||
use LIT\MCP\Tests\Unit\TestCase;
|
use LIT\MCP\Tests\Unit\TestCase;
|
||||||
|
|
||||||
@@ -19,8 +19,8 @@ final class DiviModulesTest extends TestCase
|
|||||||
{
|
{
|
||||||
self::assertContains(DiviModules::class, DiviAdapters::CLASSES);
|
self::assertContains(DiviModules::class, DiviAdapters::CLASSES);
|
||||||
self::assertContains(DynamicContentMap::class, DiviAdapters::CLASSES);
|
self::assertContains(DynamicContentMap::class, DiviAdapters::CLASSES);
|
||||||
self::assertSame(Manifest::CATALOG, DiviModules::manifest()->area);
|
self::assertSame(DiviAreas::CATALOG, DiviModules::manifest()->area);
|
||||||
self::assertSame(Manifest::CATALOG, DynamicContentMap::manifest()->area);
|
self::assertSame(DiviAreas::CATALOG, DynamicContentMap::manifest()->area);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testManifestListsModuleRegistrationAndTheBuilderSwitch(): void
|
public function testManifestListsModuleRegistrationAndTheBuilderSwitch(): void
|
||||||
|
|||||||
@@ -7,9 +7,9 @@ namespace LIT\MCP\Tests\Unit\Integrations\Divi\ThemeBuilder;
|
|||||||
use Brain\Monkey\Actions;
|
use Brain\Monkey\Actions;
|
||||||
use Brain\Monkey\Filters;
|
use Brain\Monkey\Filters;
|
||||||
use Brain\Monkey\Functions;
|
use Brain\Monkey\Functions;
|
||||||
use LIT\MCP\Integrations\Divi\Release\Call;
|
use LIT\MCP\Compatibility\Call;
|
||||||
use LIT\MCP\Integrations\Divi\Release\DiviAdapters;
|
use LIT\MCP\Integrations\Divi\Release\DiviAdapters;
|
||||||
use LIT\MCP\Integrations\Divi\Release\Manifest;
|
use LIT\MCP\Integrations\Divi\Release\DiviAreas;
|
||||||
use LIT\MCP\Integrations\Divi\ThemeBuilder\DiviThemeBuilder;
|
use LIT\MCP\Integrations\Divi\ThemeBuilder\DiviThemeBuilder;
|
||||||
use LIT\MCP\Integrations\Divi\ThemeBuilder\InsertedBeforeFailure;
|
use LIT\MCP\Integrations\Divi\ThemeBuilder\InsertedBeforeFailure;
|
||||||
use LIT\MCP\Tests\Unit\TestCase;
|
use LIT\MCP\Tests\Unit\TestCase;
|
||||||
@@ -25,7 +25,7 @@ final class DiviThemeBuilderTest extends TestCase
|
|||||||
$manifest = DiviThemeBuilder::manifest();
|
$manifest = DiviThemeBuilder::manifest();
|
||||||
|
|
||||||
self::assertContains(DiviThemeBuilder::class, DiviAdapters::CLASSES);
|
self::assertContains(DiviThemeBuilder::class, DiviAdapters::CLASSES);
|
||||||
self::assertSame(Manifest::THEME_BUILDER, $manifest->area);
|
self::assertSame(DiviAreas::THEME_BUILDER, $manifest->area);
|
||||||
self::assertSame(DiviThemeBuilder::postTypes(), $manifest->postTypes);
|
self::assertSame(DiviThemeBuilder::postTypes(), $manifest->postTypes);
|
||||||
self::assertSame(
|
self::assertSame(
|
||||||
['tb-api-save', 'tb-store-template', 'tb-load-setting-options'],
|
['tb-api-save', 'tb-store-template', 'tb-load-setting-options'],
|
||||||
|
|||||||
@@ -6,7 +6,8 @@ namespace LIT\MCP\Tests\Unit;
|
|||||||
|
|
||||||
use Brain\Monkey;
|
use Brain\Monkey;
|
||||||
use Brain\Monkey\Functions;
|
use Brain\Monkey\Functions;
|
||||||
use LIT\MCP\Integrations\Divi\Release\CompatibilityMatrix;
|
use LIT\MCP\Compatibility\CompatibilityMatrix;
|
||||||
|
use LIT\MCP\Integrations\Divi\Release\DiviFeature;
|
||||||
use LIT\MCP\Integrations\Divi\Release\ReleaseGate;
|
use LIT\MCP\Integrations\Divi\Release\ReleaseGate;
|
||||||
use LIT\MCP\Integrations\Divi\Release\ReleaseStatus;
|
use LIT\MCP\Integrations\Divi\Release\ReleaseStatus;
|
||||||
use LIT\MCP\Tests\Support\AssertsToolErrors;
|
use LIT\MCP\Tests\Support\AssertsToolErrors;
|
||||||
@@ -41,7 +42,7 @@ abstract class TestCase extends BaseTestCase
|
|||||||
|
|
||||||
// Every Divi feature is released unless a test says otherwise (the gate would ask WordPress and Divi).
|
// Every Divi feature is released unless a test says otherwise (the gate would ask WordPress and Divi).
|
||||||
ReleaseGate::useResolver(
|
ReleaseGate::useResolver(
|
||||||
static fn (): ReleaseStatus => ReleaseStatus::of('5.2.1', CompatibilityMatrix::allReleased())
|
static fn (): ReleaseStatus => ReleaseStatus::of('5.2.1', CompatibilityMatrix::allReleased(DiviFeature::cases()))
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user