|null */ private ?array $names = null; public static function manifest(): Manifest { return new Manifest( DiviAreas::DESIGN, calls: [ new Call('et_builder_get_fonts', 0), new Call('et_builder_get_custom_fonts', 0), new Call('et_builder_get_google_fonts', 0), new Call('et_builder_get_websafe_fonts', 0), new Call('et_pb_is_allowed', 1, [DiviFeature::FontUpload]), ], // The options behind Divi's lists; read only through the functions above. keys: ['et_uploaded_fonts', 'et_google_fonts_cache', 'et_google_api_settings'], // Plan 4d W1: font variables are checked against the same list, so a break locks all three on purpose. features: [DiviFeature::ThemeOptionWrite, DiviFeature::FontUpload, DiviFeature::VariableWrite] ); } /** @return list Exact family names Divi's sanitizer accepts: uploaded, then web-safe and Google. */ public function names(): array { return $this->names ??= self::namesOf(et_builder_get_custom_fonts(), et_builder_get_fonts()); } /** @return list */ public function uploaded(): array { return self::namesOf(et_builder_get_custom_fonts()); } /** @return list Google, web-safe and uploaded names – an upload must not reuse one (W9). */ public function reserved(): array { return self::namesOf( et_builder_get_google_fonts(), et_builder_get_websafe_fonts(), et_builder_get_custom_fonts() ); } public function has(string $name): bool { return in_array($name, $this->names(), true); } /** Divi's role right "Eigene Schriften verwalten" (custom_fonts_management); fail closed without Divi. */ public function canManage(): bool { return function_exists('et_pb_is_allowed') && (bool) et_pb_is_allowed('custom_fonts_management'); } /** * @param mixed ...$lists Divi's lists (family => settings); anything else (a broken filter) is skipped. * @return list */ private static function namesOf(mixed ...$lists): array { $names = []; foreach ($lists as $list) { if (! is_array($list)) { continue; } foreach (array_keys($list) as $name) { $names[] = (string) $name; } } return array_values(array_unique($names)); } }