'object', 'properties' => [ 'keys' => [ 'type' => 'array', 'items' => ['type' => 'string', 'enum' => ThemeOptionSpec::KEYS], 'description' => 'Nur diese Theme-Optionen liefern (Standard: alle).', ], ], 'additionalProperties' => false, ]; } public function outputSchema(): ?array { return [ 'type' => 'object', 'properties' => [ 'options' => [ 'type' => 'array', 'items' => [ 'type' => 'object', 'properties' => [ 'key' => ['type' => 'string'], 'label' => ['type' => 'string'], 'type' => ['type' => 'string'], 'is_default' => ['type' => 'boolean'], ], 'required' => ['key', 'label', 'type', 'value', 'effective', 'default', 'is_default'], ], ], 'design_rev' => ['type' => 'string'], 'notes' => ['type' => 'array', 'items' => ['type' => 'string']], ], 'required' => ['options', 'design_rev', 'notes'], ]; } public function annotations(): array { return Annotations::read(); } public function isDirect(): bool { return false; } /** Reads et_divi and the Customizer table (ThemeOptionsAdapter, ThemeOptionSpec mirror). */ public function diviFeatures(array $input): array { return [DiviFeature::ThemeOptionRead]; } public function permission(array $input): bool|WP_Error { return self::rights() ?? true; } public function execute(array $input): mixed { $refusal = self::rights(); if ($refusal !== null) { return $refusal; } $keys = self::keys($input); if ($keys instanceof WP_Error) { return $keys; } $stored = ThemeOptionBook::fromDivi($this->options->read()); $book = $stored->withoutFalse(); $rows = []; foreach ($keys as $key) { $definition = ThemeOptionSpec::definition($key); $rows[] = [ 'key' => $key, 'label' => $definition['label'], 'type' => $definition['type'], 'value' => $book->get($key), 'effective' => ThemeOptionSpec::effective($key, $book->data()), 'default' => ThemeOptionSpec::effective($key, $book->without($key)->data()), 'is_default' => ! $book->has($key), ] + array_intersect_key($definition, array_flip(self::RULES)); } return ['options' => $rows, 'design_rev' => $stored->rev(), 'notes' => self::NOTES]; } /** Like lit/divi-design-system: whoever edits content may read the design. */ private static function rights(): ?WP_Error { return current_user_can('edit_posts') ? null : Errors::forbidden('Keine Berechtigung, Inhalte zu bearbeiten.'); } /** * @param array $input * @return list|WP_Error The requested keys in ThemeOptionSpec::KEYS order (all without "keys"). */ private static function keys(array $input): array|WP_Error { $keys = $input['keys'] ?? ThemeOptionSpec::KEYS; if (! is_array($keys) || ! array_is_list($keys)) { return Errors::invalidInput('keys muss eine Liste sein.', ['keys' => 'Liste von Theme-Optionen']); } $errors = []; foreach ($keys as $index => $key) { if (! is_string($key) || ! ThemeOptionSpec::isKey($key)) { $errors[sprintf('keys[%d]', $index)] = 'unbekannte Theme-Option; erlaubt sind die Schlüssel aus ' . 'lit/divi-theme-options-get ohne keys'; } } if ($errors !== []) { return Errors::invalidInput('Unbekannte Theme-Optionen.', $errors); } return array_values(array_intersect(ThemeOptionSpec::KEYS, $keys)); } }