requirement ("Nachbau " before a mirror's label) => features (sorted values). */ private const EXPECTED = [ DiviPages::class => [ 'ET_Core_PageResource::remove_static_resources()' => ['page-write', 'tb-write'], 'et_builder_get_public_post_types()' => ['page-write'], 'Nachbau SyncToServerController::update()' => ['page-write'], ], DiviLibraryStore::class => [ 'GlobalLayout::is_global_layout_template()' => ['library-read', 'library-write'], 'Nachbau et_pb_submit_layout()' => ['library-write'], ], DiviRoles::class => [ 'et_pb_is_allowed()' => ['roles'], ], DiviThemeBuilder::class => [ 'et_theme_builder_get_theme_builder_post_id()' => ['tb-read', 'tb-write'], 'et_theme_builder_get_theme_builder_template_ids()' => ['tb-read'], 'et_theme_builder_get_template()' => ['tb-read'], 'et_theme_builder_insert_layout()' => ['tb-write'], 'et_theme_builder_store_template()' => ['tb-write'], 'et_theme_builder_get_flat_template_settings_options()' => ['tb-read'], 'et_theme_builder_clear_wp_cache()' => ['page-write', 'tb-write'], 'et_()' => ['tb-write'], 'ET_Core_PageResource::remove_static_resources()' => ['page-write', 'tb-write'], 'Nachbau et_theme_builder_api_save()' => ['tb-write'], 'Nachbau et_theme_builder_store_template()' => ['tb-write'], 'Nachbau et_theme_builder_load_template_setting_options()' => ['tb-read', 'tb-write'], ], DesignSystemReader::class => [ 'GlobalData::get_global_colors()' => ['design-read', 'page-read'], 'GlobalData::get_global_variables()' => ['design-read', 'page-read'], 'GlobalPreset::get_data()' => ['design-read', 'page-read'], ], DesignSystemWriter::class => [ 'GlobalPreset::get_data()' => ['design-read', 'preset-write'], 'GlobalPreset::prepare_data()' => ['preset-write'], 'GlobalPreset::validate_preset_count()' => ['preset-write'], 'GlobalPreset::get_deleted_preset_ids()' => ['preset-write'], 'GlobalPreset::remove_preset_from_legacy_option()' => ['preset-write'], 'GlobalPreset::save_data()' => ['preset-write'], 'Conversion::get_preset_attrs_mapping()' => ['preset-write'], 'Conversion::get_preset_attrs()' => ['preset-write'], 'GlobalPreset::get_group_preset_default_attr()' => ['catalog', 'preset-write'], 'ModuleRegistration::get_module_settings()' => ['catalog', 'preset-write'], 'UserRole::can_current_user_use_visual_builder()' => ['preset-write'], 'Nachbau GlobalPresetController::sync()' => ['preset-write'], ], GlobalColorsAdapter::class => [ 'GlobalData::get_global_colors()' => ['color-write'], 'GlobalData::sanitize_global_colors_data()' => ['color-write'], 'GlobalData::set_global_colors()' => ['color-write'], ], GlobalVariablesAdapter::class => [ 'GlobalData::get_global_variables()' => ['variable-write'], 'GlobalData::set_global_variables()' => ['variable-write'], 'et_pb_is_allowed()' => ['variable-write'], ], ThemeOptionsAdapter::class => [ 'et_sanitize_font_choices()' => ['theme-option-write'], 'et_sanitize_global_font_weight()' => ['theme-option-write'], 'et_sanitize_float_number()' => ['theme-option-write'], 'et_sanitize_int_number()' => ['theme-option-write'], 'et_divi_global_font_style()' => ['theme-option-write'], 'et_update_option()' => ['theme-option-write'], 'et_delete_option()' => ['theme-option-write'], 'ET_Core_PageResource::remove_static_resources()' => ['theme-option-write'], 'et_pb_force_regenerate_templates()' => ['theme-option-write'], 'et_pb_is_allowed()' => ['theme-option-write'], 'Nachbau et_divi_customizer_theme_settings()' => ['theme-option-read', 'theme-option-write'], ], FontCatalog::class => [ 'et_builder_get_fonts()' => ['font-upload', 'theme-option-write', 'variable-write'], 'et_builder_get_custom_fonts()' => ['font-upload', 'theme-option-write', 'variable-write'], 'et_builder_get_google_fonts()' => ['font-upload', 'theme-option-write', 'variable-write'], 'et_builder_get_websafe_fonts()' => ['font-upload', 'theme-option-write', 'variable-write'], 'et_pb_is_allowed()' => ['font-upload'], ], FontInstaller::class => [ 'FontsUtility::mime_types_font()' => ['font-upload'], 'HooksRegistration::check_filetype_and_ext_font()' => ['font-upload'], 'FontsUtility::font_add()' => ['font-upload'], 'FontsUtility::font_remove()' => ['font-upload'], 'Konstante ET\\Builder\\VisualBuilder\\Fonts\\FontsUtility::FONT_NAME_MAX_LENGTH' => ['font-upload'], 'Nachbau AiAgentImageUtility::install_to_custom_fonts()' => ['font-upload'], ], DiviModules::class => [ 'ModuleRegistration::get_all_core_modules_metadata()' => ['catalog'], 'ModuleRegistration::get_default_attrs()' => ['catalog'], 'et_builder_enabled_for_post_type()' => ['catalog'], 'Konstante ET_BUILDER_PRODUCT_VERSION' => ['catalog'], ], DynamicContentMap::class => [ 'DynamicContentOptions::get_options()' => ['dynamic-sources'], ], ]; public function testEveryRequirementOfEveryAdapterServesAtLeastOneFeature(): void { $bare = []; foreach (DiviAdapters::manifests() as $class => $manifest) { foreach ($manifest->requirements() as $requirement) { $features = $manifest->featuresOf($requirement); if ($features === [] || array_unique($features, SORT_REGULAR) !== $features) { $bare[] = $class . ': ' . $requirement->label(); } } } self::assertSame([], $bare, "Anforderungen ohne (eindeutige) Fähigkeit:\n" . implode("\n", $bare)); } public function testEveryFeatureIsServedByAtLeastOneRequirement(): void { $served = []; foreach (DiviAdapters::manifests() as $manifest) { foreach ($manifest->requirements() as $requirement) { foreach ($manifest->featuresOf($requirement) as $feature) { $served[$feature->value] = true; } } } $missing = array_values(array_diff( array_map(static fn (DiviFeature $feature): string => $feature->value, DiviFeature::cases()), array_keys($served) )); self::assertSame([], $missing, 'Fähigkeiten ohne Anforderung in einem Manifest'); } public function testTheAssignmentIsThePinnedTable(): void { $actual = []; foreach (DiviAdapters::manifests() as $class => $manifest) { foreach ($manifest->requirements() as $requirement) { $values = array_map( static fn (DiviFeature $feature): string => $feature->value, $manifest->featuresOf($requirement) ); sort($values); $name = ($requirement instanceof Mirror ? 'Nachbau ' : '') . $requirement->label(); $actual[$class][$name] = $values; } } self::assertSame(self::EXPECTED, $actual); self::assertSame(array_keys(self::EXPECTED), DiviAdapters::CLASSES, 'all thirteen adapters, in report order'); } public function testReadingAdaptersCarryNoWriteFeature(): void { $readingOnly = [DesignSystemReader::class, DiviRoles::class, DiviModules::class, DynamicContentMap::class]; foreach ($readingOnly as $class) { $manifest = DiviAdapters::manifests()[$class]; foreach ($manifest->requirements() as $requirement) { foreach ($manifest->featuresOf($requirement) as $feature) { self::assertFalse($feature->isWrite(), $class . ': ' . $requirement->label()); } } } } public function testEveryMirrorServesAWriteFeature(): void { foreach (DiviAdapters::manifests() as $class => $manifest) { foreach ($manifest->mirrors as $mirror) { $writes = array_filter( $manifest->featuresOf($mirror), static fn (DiviFeature $feature): bool => $feature->isWrite() ); self::assertNotSame([], $writes, $class . ': Nachbau ' . $mirror->id . ' dient keinem Schreib-Feature'); } } } }