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:
Jan-Niclas Loosen
2026-11-06 12:03:30 +01:00
co-authored by Claude Opus 5.5
parent 9beb55e228
commit b511ef6348
92 changed files with 1185 additions and 636 deletions
+93
View File
@@ -0,0 +1,93 @@
<?php
declare(strict_types=1);
namespace LIT\MCP\Compatibility;
defined('ABSPATH') || exit;
/**
* The external dependencies of one adapter (spec §4.1) – the single source for the compatibility checks, the release
* 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
{
/** @var list<ConstantRequirement> */
public readonly array $constants;
/**
* @param string $area Area label for reports (the Divi integration: DiviAreas).
* @param list<Call> $calls Functions and static methods the adapter calls.
* @param list<string|ConstantRequirement> $constants Constants it reads; a plain name stands for a
* ConstantRequirement without features of its own.
* @param list<string> $postTypes Post types it needs registered.
* @param list<string> $taxonomies Taxonomies it needs registered.
* @param list<string> $blockTypes Block types it needs (registered or known
* to the ManifestCheck knowsBlock closure).
* @param list<string> $keys Other names it uses as strings: meta keys, options,
* internal post types that need no registration check,
* query arguments.
* @param list<Mirror> $mirrors Functions whose storage logic it repeats.
* @param list<Capability> $features The features of every call, mirror and constant that names
* none itself (featuresOf()).
* @param list<GlobalRequirement> $globals Global variables it reads (isset check).
*/
public function __construct(
public readonly string $area,
public readonly array $calls = [],
array $constants = [],
public readonly array $postTypes = [],
public readonly array $taxonomies = [],
public readonly array $blockTypes = [],
public readonly array $keys = [],
public readonly array $mirrors = [],
public readonly array $features = [],
public readonly array $globals = []
) {
$this->constants = array_map(
static fn (string|ConstantRequirement $constant): ConstantRequirement => is_string($constant)
? new ConstantRequirement($constant)
: $constant,
array_values($constants)
);
}
/** @return list<Requirement> Calls, constants, mirrors and globals – everything the release gate checks as code. */
public function requirements(): array
{
return [...$this->calls, ...$this->constants, ...$this->mirrors, ...$this->globals];
}
/** @return list<Capability> The features $requirement names itself, else this manifest's default. */
public function featuresOf(Requirement $requirement): array
{
$own = $requirement->features();
return $own !== [] ? $own : $this->features;
}
/**
* @return list<string> Every external name the adapter's code may contain (DiviBoundaryTest): called functions and
* classes, constants, globals, post types, taxonomies, keys and the names of mirrored functions.
*/
public function names(): array
{
$names = [];
foreach ($this->calls as $call) {
$names[] = $call->className() ?? $call->member();
}
$constants = array_map(static fn (ConstantRequirement $constant): string => $constant->name, $this->constants);
$mirrored = array_map(static fn (Mirror $mirror): string => $mirror->function, $this->mirrors);
return array_values(array_unique(array_merge(
$names,
$constants,
array_map(static fn (GlobalRequirement $global): string => $global->name, $this->globals),
$this->postTypes,
$this->taxonomies,
$this->keys,
$mirrored
)));
}
}