feat: Divi-Adapter sperren je Fähigkeit – ReleaseGate::feature/assertFeature(s), DiviLocked und Ablehnung nennen die betroffenen Fähigkeiten (D6), DiviSaver prüft Seiten schreiben und die Fähigkeit des Speicherbereichs (D5), DesignArea::feature; Test-Standard alle Fähigkeiten freigegeben

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Jan-Niclas Loosen
2026-10-18 22:10:41 +02:00
co-authored by Claude Opus 5.5
parent c4efeb3ba4
commit e387d8d29e
20 changed files with 525 additions and 65 deletions
+39 -7
View File
@@ -11,9 +11,9 @@ use Throwable;
defined('ABSPATH') || exit;
/**
* The release status of this request and the lock every writing Divi path asks (spec §5.5). whileProbing() lets the
* admin check write its throwaway page whatever the status – only that post, only during the call, and only from
* code (there is no parameter or option for it).
* The release status of this request and the lock every writing Divi path asks for the feature it needs (spec §5.5,
* E1). whileProbing() lets the admin check write its throwaway page whatever the status – only that post, only
* during the call, and only from code (there is no parameter or option for it).
*/
final class ReleaseGate
{
@@ -57,17 +57,49 @@ final class ReleaseGate
self::$status = null;
}
/** @throws DiviLocked */
public static function assertWritable(?int $postId = null): void
public static function feature(DiviFeature $feature): FeatureStatus
{
return self::status()->matrix->of($feature);
}
/** @throws DiviLocked When $feature is not usable – before anything is written. */
public static function assertFeature(DiviFeature $feature, ?int $postId = null): void
{
self::assertFeatures([$feature], $postId);
}
/**
* Every one of $features usable, else DiviLocked with the locked ones. The probe post passes whatever the status.
*
* @param list<DiviFeature> $features
* @throws DiviLocked
*/
public static function assertFeatures(array $features, ?int $postId = null): void
{
if (self::$probe !== null && $postId === self::$probe) {
return;
}
$status = self::status();
if (! $status->writable()) {
throw new DiviLocked($status);
$locked = [];
foreach ($features as $feature) {
if (! $status->matrix->of($feature)->usable()) {
$locked[$feature->value] = $feature;
}
}
if ($locked !== []) {
throw new DiviLocked($status, array_values($locked));
}
}
/**
* Every writing feature (CompatibilityMatrix::writeFeatures()) – for callers that know no feature.
*
* @throws DiviLocked
*/
public static function assertWritable(?int $postId = null): void
{
self::assertFeatures(CompatibilityMatrix::writeFeatures(), $postId);
}
public static function whileProbing(int $postId, callable $write): mixed