Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
32 KiB
Etappe 4d – Divi 5.15.1: Theme-Optionen und Schriften (Code-Recherche)
Stand: 2026-10-19. Grundlage der Rulings W1–W14 (siehe 2026-09-28-etappe-4-entscheidungen-entwurf.md, Abschnitt „Etappe 4d“). Die Befunde in Abschnitt 0 sind in den Formate-Nachtrag „Etappe 4d“ übernommen.
Quelle: installiertes Divi 5.15.1 (style.css:4), WordPress 7.1.3. Alle Pfade relativ zu wp-content/themes/Divi, sofern nicht anders angegeben. Nur aus Code abgeleitet; die Zeilen der Formate-Notiz §4 (5.2.1) sind durchweg um ca. +80 verschoben.
0. Überraschungen gegenüber Spec §8 (Kurzfassung)
FontsUtility::font_add()ist in-process aufrufbar.wp_handle_upload()nimmt$overrides['action']als Action (wp-admin/includes/file.php:1110); nur bei Action'wp_handle_upload'prüft_wp_handle_uploadis_uploaded_file()/move_uploaded_file()(file.php:936,:1019-1027), sonstis_readable()+copy()/unlink(). Divi übergibt selbst['action' => 'wp_handle_upload_rest'](CustomFontController.php:68-75) und installiert so serverseitige Temp-Dateien:AiAgentImageUtility::install_to_custom_fonts()(includes/builder-5/server/VisualBuilder/AiAgent/AiAgentImageUtility.php:860-1009,wp_tempnam→copy→font_add([...'tmp_name'=>$temp...], …, ['action'=>'wp_handle_upload_rest'])). → Kein eigener Sideload und kein Nachbau deset_uploaded_fonts-Eintrags nötig; Spec §8.2 („nur echte Browser-Uploads“, „Nachbau mit Fingerabdruck“) ist überholt. Mirror höchstens für die Aufrufkonvention (install_to_custom_fonts).- Divi-Rolle für Schriften ist
custom_fonts_management, nichtuse_visual_builder(CustomFontController.php:141-152,:214-225; Rollen-Editorincludes/builder/functions.php:9595). Plusupload_files. Spec §10 nachziehen. - Standard-Formate nur
ttf,otf:et_pb_get_supported_font_formats()(includes/builder/core.php:5090, Filteret_pb_supported_font_formats). Der REST-Store nimmt nur diese Felder an;font_addselbst akzeptiert alles ausmime_types_font()(otf, ttf, woff, woff2, eot), das Frontend (et_builder_enqueue_user_fonts,includes/builder/functions.php:3813ff) gibt alle fünf aus. woff/woff2 sind also technisch möglich, aber über Divis UI nicht vorgesehen → Entscheidung nötig. - „Standard-Schrift“ wird im Customizer als
falsegespeichert, nicht als'none'.et_sanitize_font_choices('none')→false('none'steht nicht inet_builder_get_fonts()), WP speichertfalse(nurnull/WP_Errorwerden verworfen,wp-includes/class-wp-customize-manager.php:1848-1851). Leser: Divi-4-CSS/Google-URLet_pb_get_specific_default_font()behandeltfalse/''/'none'gleich (functions.php:1287-1290, losein_array); Divi 5Fonts::enqueue()undGlobalData::get_customizer_fonts()nehmen bei fehlendem Schlüssel'Open Sans', beifalseebenfalls'Open Sans'(FrontEnd/Module/Fonts.php:100-129), bei'none'aberself::add('none')(:138-144). → „Standard“ = Schlüssel entfernen (et_delete_option), nie'none'schreiben. - Divis Sanitizer prüfen keine Bereiche.
absint,intval,floatvalklemmen nicht auf min/max der Controls;et_sanitize_*_choicesliefern bei Unbekanntemfalse(kein Fehler). Plugin muss Bereiche aus den Control-input_attrsselbst prüfen undfalseals Ablehnung werten. body_header_styleist im Control mehrfach wählbar (italic|uppercase, Checkbox-Liste mit|,functions.php:5457-5481), der Sanitizeret_divi_global_font_styleakzeptiert aber nur genau einen Schlüssel → jede Kombination und auch''(alles abgewählt) wird zufalse. Divi-Bug; Tool sollte nur einen Wert (oder „unset“) zulassen.et_builder_get_google_fonts()kann einen HTTP-Request auslösen (et_builder_google_fonts_sync(),includes/builder/core.php:4868-4905: einmal je 24 h per Transientfonts_cache_status, nur wenn Google-API-Key gesetzt). Sonst Optionet_google_fonts_cachebzw. 1,3-MB-JSON (core/json-data/google-fonts.json, 1945 Familien), statisch gecacht.et_sanitize_font_choicesruft das bei jedem Aufruf (ksort über ~1950 Einträge) → Liste je Request einmal holen.- Namens-Eindeutigkeit in
font_addprüft nur Google-Fonts undet_uploaded_fonts, nicht Web-Safe-Fonts (FontsUtility.php:125-131) – „Arial“ wäre hochladbar. Plugin-Regel strenger halten. font_addmeldet Teilerfolg als Erfolg: schlägt eine von mehreren Dateien fehl, wird die Schrift mit den übrigen gespeichert, die Fehler gehen verloren (FontsUtility.php:157-190). Plugin: vorab jede Datei mitHooksRegistration::check_filetype_and_ext_font()prüfen (wie Divis AI-Pfad) und Ergebnisfont_file-Schlüssel gegen Eingabe vergleichen.ET_Core_PageResource::remove_static_resourceshat jetzt 7 Parameter (+ $skip_external_cache,core/components/PageResource.php:1398); Signatur-Fingerabdruck prüfen.GlobalData::get_customizer_fonts()cached perstaticohne Reset (GlobalData.php:446-451) → Zurücklesen nach dem Schreiben im selben Request überget_option('et_divi')/et_get_option, nicht darüber.et_update_optionschreibt das ganzeet_divi-Array aus dem Request-Global$et_theme_options(epanel/custom_functions.php:297-310); wurde das Global früher im Request geladen und die Option inzwischen von einem anderen Prozess geändert, werden dessen Änderungen überschrieben (Lost Update). Fürdesign_rev-Vergleich und Snapshotget_option('et_divi')lesen; Restrisiko dokumentieren.
A. Theme-Optionen
Allgemein für alle 20 Settings (Registrierung in et_divi_customizer_theme_settings(), functions.php:1371ff, Hook customize_register → et_divi_customize_register functions.php:1306/:1363):
type => 'option', IDet_divi[<key>]→ Speicherget_option('et_divi')[<key>](Divi:$shortname = 'divi',$et_store_options_in_one_row = true,functions.php:16-17).capability => 'edit_theme_options',transport => 'postMessage'.- Sanitizer sind globale Funktionen, immer geladen:
includes/functions/sanitization.phpundchoices.phpwerden inet_setup_theme()(after_setup_theme,functions.php:50-52,:150) ohne Bedingung eingebunden; Builder-Listen inincludes/builder/core.php(immer geladen). WP ruft sie als Filtercustomize_sanitize_{id}mit($value, $setting)(class-wp-customize-setting.php:581); alle Divi-Sanitizer nehmen nur$value, also direkt mit 1 Argument aufrufbar. Kein Customizer-Kontext nötig. - Rückgabe
falsebei ungültiger Auswahl (et_sanitize_key_based_option($choosen, $options, $default = false),sanitization.php:45-52;isset($options[$choosen]), also case-sensitiv, numerische String-Schlüssel ≙ int). - Gespeicherte Typen:
absint→ int,et_sanitize_float_number→ float,et_sanitize_int_number→ int, Auswahl-Sanitizer → der übergebene Wert (String) oderfalse.
| Schlüssel | Setting (file:line) | Standard (Setting) | sanitize_callback (Definition) | Control / Choices / min–max–step | Zusammenspiel / Leser |
|---|---|---|---|---|---|
heading_font |
functions.php:2563-2572, Control :2574-2586 |
'none' |
et_sanitize_font_choices($choosen) sanitization.php:59-66 (Google+Websafe via et_builder_get_fonts() + et_builder_get_custom_fonts()) |
ET_Divi_Select_Option, type select, Choices $font_choices (functions.php:1407-1440: 'none' + alle Fonts, im UI nach Locale-Zeichensatz gefiltert, Sanitizer filtert nicht nach Locale) |
'none' → false gespeichert (§0.4). Builder/D5-Sicht 'Open Sans' (GlobalData::$customizer_fonts GlobalData.php:108-119, Fonts.php:100). Speist --et_global_heading_font (Fonts.php:148-175), D4-Font-URL functions.php:432, :7216, et_builder_get_font_family('--et_global_heading_font') includes/builder/core.php:4683-4686. Alias Source Sans Pro→Source Sans 3 nur im D5-Enqueue (Fonts.php:113-127). |
body_font |
functions.php:2636-2645, Control :2647-2659 |
'none' |
et_sanitize_font_choices |
wie oben | wie oben, --et_global_body_font; zusätzlich functions.php:334, :474, includes/builder/functions.php:4254, Fonts.php:134-136 ('none'/'' = „Theme lädt Open Sans selbst“). |
primary_nav_font |
functions.php:3477-3486, Control :3488-3500 |
'none' |
et_sanitize_font_choices |
Select, $font_choices (Section et_divi_header_primary) |
nur D4-Header/Google-URL (functions.php:435); kein D5-Global. |
secondary_nav_font |
functions.php:3601-3610, Control :3612-3624 |
'none' |
et_sanitize_font_choices |
Select, $font_choices (Section et_divi_header_secondary) |
functions.php:436; kein D5-Global. |
heading_font_weight |
functions.php:2588-2597, Control :2599-2611 |
'500' |
et_sanitize_global_font_weight($choosen) sanitization.php:345-347 |
ET_Divi_Custom_Select_Option, Choices et_builder_get_font_weight_list() (includes/builder/core.php:4792-4807: '100'…'900', Filter et_builder_all_font_weights) |
--et_global_heading_font_weight (Fonts.php:151, leer → '500'), D4-CSS functions.php:5827, :6943ff (nur wenn ≠ 500). |
body_font_weight |
functions.php:2661-2670, Control :2672-2684 |
'500' |
et_sanitize_global_font_weight |
wie oben | --et_global_body_font_weight, functions.php:5828, :5992ff. |
body_font_size |
functions.php:2287-2296, Control :2298-2313 |
'14' |
absint (WP) |
ET_Divi_Range_Option, range 10–32, step 1 |
--et_global_body_font_size (Fonts.php:104-107, '' → 14), D4 functions.php:5819, VB-Settings SettingsDataCallbacks.php:2379. |
tablet_body_font_size |
functions.php:2371-2380, Control :2382-2397 |
et_get_option('body_font_size','14') (dynamisch) |
absint |
Range 10–32, step 1 (Section et_divi_mobile_tablet) |
Leser nehmen fest '14' (functions.php:5841, Fonts.php:108), CSS nur wenn ≠14 && ≠ body (functions.php:7019) → unset ≙ erbt Desktop. |
phone_body_font_size |
functions.php:2343-2352, Control :2354-2369 |
et_get_option('tablet_body_font_size','14') |
absint |
Range 10–32, step 1 (et_divi_mobile_phone) |
Leser: Standard = Tablet-Wert (functions.php:5846, Fonts.php:109); CSS nur wenn ≠14 && ≠ tablet (:7112). |
body_header_size |
functions.php:2399-2408, Control :2410-2425 |
'30' |
absint |
Range 22–72, step 1 | functions.php:5821, VB SettingsDataCallbacks.php:2391. |
tablet_header_font_size |
functions.php:2535-2544, Control :2546-2561 |
et_get_option('body_header_size','30') |
absint |
Range 22–72, step 1 | Leser fest '30' (functions.php:5840), CSS nur wenn ≠30 && ≠ body_header_size (:7039). |
phone_header_font_size |
functions.php:2507-2516, Control :2518-2533 |
et_get_option('tablet_header_font_size','30') |
absint |
Range 22–72, step 1 | Standard = Tablet (functions.php:5845), CSS :7132. |
body_font_height |
functions.php:2315-2324, Control :2326-2341 |
'1.7' |
et_sanitize_float_number($number) sanitization.php:7-9 (floatval) |
Range 0.8–3, step 0.1 | --et_global_body_font_height (Fonts.php:105-107, Einheit em), D4 functions.php:5820, VB :2378. |
body_header_height |
functions.php:2455-2464, Control :2466-2481 |
'1' |
et_sanitize_float_number |
Range 0.8–3, step 0.1 | D4 functions.php:5824, :6604. |
body_header_spacing |
functions.php:2427-2436, Control :2438-2453 |
'0' |
et_sanitize_int_number($number) sanitization.php:16-18 (intval) |
Range −2–10, step 1 | D4 functions.php:5823, :6604. Negativ erlaubt. |
body_header_style |
functions.php:2483-2492, Control :2494-2505 |
'' |
et_divi_global_font_style($choosen) sanitization.php:358-360 |
ET_Divi_Font_Style_Option (functions.php:5457, Checkboxen, Wert `a |
b), Choices et_divi_global_font_style_choices() (includes/functions/choices.php:23-33: italic, uppercase, underline; Filter et_divi_global_font_style_choices) – **kein bold** (das gibt es nur bei et_divi_font_style_choices/et_sanitize_font_style`) |
content_width |
functions.php:1903-1912, Control :1914-1929 |
'1080' |
absint |
Range 960–1920, step 1 (et_divi_general_layout) |
D4 functions.php:5833, :6133; VB SettingsDataCallbacks.php:2387. |
gutter_width |
functions.php:1931-1940, Control :1942-1957 |
'3' |
absint |
Range 1–4, step 1 | Standard für Section/Row-gutter_width (D4 includes/builder/main-structure-elements.php:239, :1953), Body-Klasse functions.php:8581. In D5-Servercode kein Leser gefunden. |
section_padding |
functions.php:2006-2015, Control :2017-2032 |
'4' |
absint |
Range 0–10, step 1 | D4 functions.php:5837. |
row_padding |
functions.php:2090-2099, Control :2101-2116 |
'2' |
absint |
Range 0–10, step 1 | D4 functions.php:5838. |
Abhängige Standards: tablet_* / phone_* werden im Customizer beim Registrieren aus dem aktuellen Größeren berechnet; die CSS-Leser nutzen feste 14/30 und „gleich dem Größeren = keine Regel“. Für das Tool: Standard von tablet_body_font_size = effektiver body_font_size, phone_* = effektiver tablet_*; „unset“ heißt „erbt“.
A.1 Builder-Globals (--et_global_*)
GlobalData::$customizer_fonts(includes/builder-5/server/Packages/GlobalData/GlobalData.php:108-119):--et_global_heading_font→heading_font,--et_global_body_font→body_font, beide Standard'Open Sans'.get_customizer_fonts()(:446-470) liefert{id,label,value,status:'active',order},staticgecacht.- Frontend-Variablen (
FrontEnd/Module/Fonts.php:99-191,Fonts::enqueue()):--et_global_heading_font,--et_global_body_font,--et_global_heading_font_weight,--et_global_body_font_weight,--et_global_body_font_size(+ responsive austablet_/phone_body_font_size),--et_global_body_font_height– also speisen heading_font, body_font, heading_font_weight, body_font_weight, body_font_size, tablet_body_font_size, phone_body_font_size, body_font_height Divi-5-Globals; inline ausgegeben (<style class="et-vb-global-data et-vb-global-fonts">), nicht im Static-CSS gecacht. - REST
POST /global-data/global-fonts(includes/builder-5/server/VisualBuilder/REST/RESTRegistration.php:1677) →GlobalDataController::update_global_fonts()(GlobalDataController.php:166-191):et_update_option('heading_font', …),et_update_option('body_font', …)(Argsrequired, nursanitize_text_field,:215-227, keine Font-Prüfung), dannET_Core_PageResource::remove_static_resources('all','all',true). Rechte nuredit_posts(:243-249) + Routen-Nonce. Weitere Schreiber derselben Schlüssel: AJAXet_update_customizer_fonts(includes/builder/functions.php:13583-13603,edit_theme_options), ImportPortabilityPost.php:4130-4136.
A.2 Was ein Customizer-Speichern zusätzlich tut
- WP schreibt das Setting direkt per
update_option('et_divi', …)(multidimensional), nicht überet_update_option. customize_save_after-Hooks in Divi (vollständig per grep):ET_Core_PageResource::customize_save_after_cb→remove_static_resources('all','all')(core/components/PageResource.php:953,:1252-1254) undet_pb_force_regenerate_templates(includes/builder/core.php:3811-3817,:3825:et_update_option('et_pb_clear_templates_cache', true)+et_fb_delete_builder_assets()core.php:6592ff, löscht VB-Helper-JS/.data/Bild-Caches).- Keine Hooks auf
update_option_et_divi/pre_update_option_et_diviin Divi. remove_static_resources(PageResource.php:1398-1417): wirkungslos beiDOING_AUTOSAVE, ohnewp_doing_cron()bzw.et_core_security_check_passed('edit_posts'), oder ohne Schreibrecht im Dateisystem;$forcelöscht nur zusätzlich die Optionet_core_page_resource_remove_all(:1596-1598);$skip_external_cache=falseruftet_core_clear_wp_cache()(Fremd-Page-Caches). Die Customizer-CSS liegt im Static-Resourceet-divi-customizer-global-*(functions.php:5790,:7331) und wird damit invalidiert.et_update_option(epanel/custom_functions.php:276-315): lädt$et_theme_optionsnur, wenn das Global fehlt oderis_customize_preview(); setzt Schlüssel,update_option('et_divi', $et_theme_options); aktualisiert damit auch das Global (spätereet_get_optionim Request sehen den neuen Wert). Keine weiteren Seiteneffekte.
A.3 Minimale korrekte In-Process-Schreibfolge (≙ Customizer-Speichern)
- Rechte:
current_user_can('edit_theme_options')undet_pb_is_allowed('theme_customizer')(Customizer:functions.php:1357,wp_die; Rollen-Editorincludes/builder/functions.php:9523).et_pb_is_allowed(includes/builder/core.php:1136-1170) ist ohne Eintrag im Rollen-Editortrue(nicht „dangerous“); nur eine Fähigkeit je Aufruf übergeben (bei Arrays entscheidet die erste gespeicherte). - Je Schlüssel: Divi-Sanitizer aufrufen;
false→ Validierungsfehler (statt wie Divifalsezu speichern); Bereich aus Tabelle selbst prüfen; Ergebnis vergleichen (z. B.absint('15.7')= 15 → als Änderung melden oder ablehnen). - Schreiben:
et_update_option($key, $sanitized)je Schlüssel; „unset“:et_delete_option($key). - Caches:
ET_Core_PageResource::remove_static_resources('all', 'all')(Customizer) – oder('all','all',true)wieglobal-fonts; pluset_pb_force_regenerate_templates(). Benutzer muss angemeldet sein (edit_posts). - Zurücklesen:
get_option('et_divi')(WP-Cache wird vonupdate_optionaktualisiert), nichtGlobalData::get_customizer_fonts().
B. Schriften
B.1 Listen
| Funktion | Ort | Signatur | Rückgabe / Kosten |
|---|---|---|---|
et_builder_get_google_fonts() |
includes/builder/core.php:4911-4929 |
() |
[] wenn Google Fonts aus (et_core_use_google_fonts(), core/functions.php:223-228, Option et_google_api_settings['use_google_fonts'], Standard 'on'). Sonst ruft et_builder_google_fonts_sync() (:4868-4905, ggf. wp_remote_get an Google, 1×/24 h, nur mit API-Key) und liefert Option et_google_fonts_cache (Array oder JSON-String, dann jedes Mal geparst) bzw. et_core_get_saved_google_fonts() (core/functions.php:1970-1985, 1,3 MB JSON, 1945 Familien, static). Filter et_builder_google_fonts. Form: `Family => {styles:'100,100italic,…', character_set:'latin,…', type:'sans-serif |
et_builder_get_websafe_fonts() |
core.php:4783-4785 |
() |
→ et_core_get_websafe_fonts() (core/functions.php:1993-2030): Arial, Georgia, Times New Roman, Trebuchet, Verdana mit styles, character_set, type, ggf. add_ms_version; Filter et_websafe_fonts. |
et_builder_get_fonts( $settings = array() ) |
core.php:4730-4751 |
0–1 Arg (prepend_standard_fonts) |
Websafe + Google, ksort; bei abgeschalteten Google Fonts nur Websafe. Ohne hochgeladene Schriften. |
et_builder_get_custom_fonts() |
core.php:4822-4831 |
() |
get_option('et_uploaded_fonts', []), nicht-Array → [], Filter et_builder_custom_fonts. |
et_builder_get_font_family( $font_name, $use_important = false ) |
core.php:4683-4723 |
1–2 | CSS-String font-family: '…', <stack>; – kein Listen-Lieferant. Löst --et_global_*_font auf. |
et_builder_old_fonts_mapping() |
core.php:4839ff |
() |
Alt-Namen (Raleway Light, Open Sans Light …) → parent_font + Gewicht. |
et_builder_get_font_weight_list() |
core.php:4792-4807 |
() |
'100'…'900' → Label. |
Gesamtliste wie der Customizer-Sanitizer: array_merge(et_builder_get_custom_fonts(), et_builder_get_fonts()) (sanitization.php:59-66). Gültiger Wert = exakter Familienname als Schlüssel (case-sensitiv), keine :/|-Qualifizierer; 'none' ist kein Schlüssel. Gewichte/Stile sind eigene Settings.
B.2 Hochgeladene Schriften
Option et_uploaded_fonts (autoload Standard), geschrieben von FontsUtility::font_add():
'<Name>' => [
'font_file' => [ '<ext>' => esc_url('<absoluter Dateipfad>') , … ], // Pfad durch esc_url
'font_url' => [ '<ext>' => esc_url('<URL>'), … ],
'styles' => '100,200,…,900' | '<eingegebene Liste>', // nur wenn $font_settings nicht leer
'type' => '<generic_family>' | 'serif', // nur wenn $font_settings nicht leer
]
(Divi-4-Altformat von et_pb_add_font, includes/builder/core.php:5183-5270, ist gleich; font_file/font_url können dort auch Strings sein – et_builder_enqueue_user_fonts behandelt beides, functions.php:3818, :3869.)
FontsUtility::font_add( array $font_files, string $font_name, array $font_settings, array $overrides = [] ) (includes/builder-5/server/VisualBuilder/Fonts/FontsUtility.php:102-213, Namespace ET\Builder\VisualBuilder\Fonts):
$font_files:['<ext>' => <$_FILES-Element {name,type,tmp_name,error,size}>](nicht Pfade, trotz Docblock). Leer →WP_Error file_empty.- Name:
preg_replace('/[^A-Za-z0-9\s\_-]/', '', $name)(stilles Entfernen, kein Fehler) → leer:font_name_empty; >FONT_NAME_MAX_LENGTH(100,:39) Zeichen nachStringUtility::strlen_utf8:font_name_too_long; bereits inget_option('et_uploaded_fonts')(ungefiltert) oderet_builder_get_google_fonts()(exakt, case-sensitiv):font_name_exists. Websafe nicht geprüft. Der tatsächlich gespeicherte Name steht inuploaded_fontder Rückgabe. - Ablage:
add_filter('upload_dir', [HooksRegistration::class, 'upload_dir_font'])→<uploads basedir>/et-fonts, URL<baseurl>/et-fonts,subdir '/et-fonts'(keine Jahr/Monat-Ordner;HooksRegistration.php:318-332);add_filter('wp_check_filetype_and_ext', [HooksRegistration::class, 'check_filetype_and_ext_font'], 999, 3); beide nach der Schleife entfernt (:174-178). - Je Datei
wp_handle_upload($file, wp_parse_args(['test_size'=>true,'test_type'=>true,'test_form'=>false], $overrides))→ die drei Tests sind fest,action(und andere Overrides wieunique_filename_callback,mimes) kommen durch. Dateinamewp_unique_filename→ keine Überschreibung. - Typprüfung
check_filetype_and_ext_font(HooksRegistration.php:77-127): mitfileinfo: Endung (lowercase) muss inmime_types_font()stehen undfinfo(Magic) einen der MIME-Typen liefern: otffont/otf|application/x-font-opentype|application/x-font-ttf|application/vnd.ms-opentype, ttffont/ttf|font/sfnt|application/font-sfnt|application/x-font-ttf, wofffont/woff|application/font-woff, woff2font/woff2|application/font-woff2, eotapplication/vnd.ms-fontobject(FontsUtility.php:290-316);proper_filename = sanitize_file_name(). Ohnefileinfo: Fallback auf WPs Ergebnis. Achtung:_wp_handle_uploadlässt beicurrent_user_can('unfiltered_upload')auch fehlgeschlagene Typprüfung durch (wp-admin/includes/file.php:971) → eigene Magic-Byte-Prüfung vorab ist Pflicht (Spec hat sie schon). - Gewichte:
font_weightsfehlt oder'all'→'100,200,300,400,500,600,700,800,900', sonst ungeprüft übernommen;generic_familyungeprüft, Standard'serif'. Kein Größenlimit außertest_size(>0). - Ergebnis: mind. eine Datei ok →
update_option('et_uploaded_fonts', …),do_action('divi_visual_builder_fonts_custom_font_added')(→et_fb_delete_builder_assets,HooksRegistration.php:345), Rückgabe['uploaded_font' => $name, 'updated_fonts' => $all]. Keine Datei ok →WP_Error(gesammelte Upload-Fehler, ggf.fileinfo_extension_not_loaded, sonstupload_error_unknown). - Keine Rechte-/Nonce-Prüfung in
font_add/font_remove; die liegt im REST-Controller:CustomFontController::store_permission()/destroy_permission()(includes/builder-5/server/VisualBuilder/REST/CustomFont/CustomFontController.php:141-152,:214-225):upload_files+et_pb_is_allowed('custom_fonts_management'); RoutenPOST /custom-font/add,/custom-font/remove(RESTRegistration.php:1168-1183) mit Divi-Routen-Nonce. Store nimmt nuret_pb_font_file_<fmt>füret_pb_get_supported_font_formats()(Standard ttf, otf).
In-process mit Nicht-HTTP-Dateien: möglich. wp_handle_upload() setzt $action = $overrides['action'] ?? 'wp_handle_upload' (wp-admin/includes/file.php:1110); _wp_handle_upload prüft is_uploaded_file() und nutzt move_uploaded_file() nur bei 'wp_handle_upload' === $action, sonst is_readable(), filesize(), copy() + unlink(tmp); zusätzlich laufen {$action}_prefilter/{$action}_overrides-Filter (also wp_handle_upload_rest_prefilter, nicht wp_handle_upload_prefilter). Divi macht genau das in AiAgentImageUtility::install_to_custom_fonts() (AiAgentImageUtility.php:860-1009): check_filetype_and_ext_font() vorab, wp_tempnam($filename), copy, font_add([$ext => ['name'=>$filename,'type'=>$mime,'tmp_name'=>$temp,'error'=>0,'size'=>filesize($temp)]], $name, ['font_weights'=>'all','generic_family'=>'sans-serif'], ['action'=>'wp_handle_upload_rest']), danach Temp löschen. → Plugin: wp_safe_remote_get → Temp (wp_tempnam, Name mit korrekter Endung) → Magic-Bytes + check_filetype_and_ext_font → font_add(..., ['action' => 'wp_handle_upload_rest']). Kein Sideload-Nachbau, kein Nachbau des Options-Formats. wp_handle_sideload wäre gleichwertig, aber unnötig.
FontsUtility::font_remove( string $font_name ) (:242-276): '' → file_name_empty; fehlt Schlüssel oder font_file → font_not_exist; jede Datei et_pb_safe_unlink_font_file() (includes/builder/core.php:5336-5381: nur echte Pfade unter uploads/et-fonts, Font-Endung), unset, update_option, do_action('divi_visual_builder_fonts_custom_font_removed'). Für Rollback nach fehlgeschlagenem Zurücklesen nutzbar.
Zu rufende Divi-Symbole für den Upload: FontsUtility::font_add (4), HooksRegistration::check_filetype_and_ext_font (3, Vorprüfung je Datei), FontsUtility::mime_types_font (0, erlaubte Endungen), FontsUtility::FONT_NAME_MAX_LENGTH (Konstante), et_pb_get_supported_font_formats (0, falls Divi-UI-Formate gelten sollen), et_builder_get_google_fonts (0) / et_builder_get_websafe_fonts (0) / et_builder_get_custom_fonts (0) für Namensprüfung, et_pb_is_allowed (1, custom_fonts_management), optional FontsUtility::font_remove (1) für Rollback. HooksRegistration::upload_dir_font muss nicht gerufen werden (setzt font_add selbst).
Mirror-Kandidaten (statt Speicher-Nachbau):
new Mirror('font-install', 'includes/builder-5/server/VisualBuilder/AiAgent/AiAgentImageUtility.php', 'install_to_custom_fonts', 'AiAgentImageUtility', 'Aufrufkonvention von font_add mit Temp-Datei (check_filetype_and_ext_font, wp_tempnam, action wp_handle_upload_rest)')– fängt, wenn Divi den In-Process-Weg ändert.- Optional
new Mirror('font-add', 'includes/builder-5/server/VisualBuilder/Fonts/FontsUtility.php', 'font_add', 'FontsUtility', 'Namensregeln und Eintragsformat von et_uploaded_fonts (Plugin-Vorprüfung, Rückgabe-Vergleich)')– nur nötig, wenn das Plugin Namensregeln (Regex, 100 Zeichen, Kollision) vorab nachbildet, um im Probelauf ohne Upload zu melden. new Mirror('customizer-font-sanitize', 'includes/functions/sanitization.php', 'et_sanitize_font_choices', null, …)nur, wenn die Font-Validierung nicht über den Sanitizer, sondern über die gemergte Liste nachgebaut wird.
C. Snapshot / Restore „theme_options“
- Inhalt: genau die 20 Whitelist-Schlüssel aus
get_option('et_divi'), je Schlüssel vorhanden + Rohwert (mit Typ: int/float/string/false) oder nicht vorhanden. Darstellung z. B.{"set": {key: value, …}, "unset": [key, …]}oder Wert-Objekt{present: bool, value}– wichtig ist die Unterscheidung „fehlt“ vs.falsevs.'', weilet_get_optionbei vorhandenem Schlüssel (auchfalse) den Wert, sonst den Standard liefert (custom_functions.php:238,:246-248; Bedingung! empty($default_value)). Farben (accent_color…) nicht hier (Snapshotcolors). - Restore: für „vorhanden“
et_update_option($key, $raw)(Rohwert ohne Sanitizer zurückschreiben – er stammt aus Divi), für „fehlt“et_delete_option($key); danach Caches wie A.3.et_update_optionallein reicht nicht, weil es Schlüssel nicht entfernen kann. et_delete_option( $option_name )(epanel/custom_functions.php:320-333, 1 Arg, untypisiert): lädt das Global nur, wenn nicht gesetzt (ignoriertis_customize_preview),unset,update_option('et_divi', …). Entfernt den Schlüssel also wirklich. Sonderfall: istet_divigar nicht vorhanden (false), schreibt esfalsezurück (unkritisch).- „Unset“ im Tool-Input: eigener Wert (z. B.
null= „auf Divi-Standard zurück“) →et_delete_option. Nicht'none', nichtfalseschreiben. getliefert Divi-Standard je Feld aus der Tabelle (Settings-default; fürtablet_*/phone_*den effektiven Wert des Größeren; für Schriften Customizer-Standardnone= „Theme-Standard“, Builder-AnzeigeOpen Sans).
D. Divi-Symbole für das Manifest
Arg-Anzahl = was das Plugin übergibt; „untyp.“ = Parameter ohne Typ-Deklaration (Signatur-Fingerabdruck weniger aussagekräftig).
Optionen lesen
et_get_option– 2 (von 8), untyp. (epanel/custom_functions.php:215) – optional; für Rohsicht direktget_option('et_divi')(Keyet_divi).ET\Builder\Packages\GlobalData\GlobalData::get_customizer_fonts– 0, typisiert(): array(GlobalData.php:446) – nur Builder-Sicht, gecacht.- Keys:
et_divi,et_uploaded_fonts,et_google_fonts_cache,et_google_api_settings, Statische EigenschaftGlobalData::$customizer_fonts.
Standards / Choices
et_builder_get_font_weight_list– 0 (includes/builder/core.php:4792).et_divi_global_font_style_choices– 0 (includes/functions/choices.php:23).- Standardwerte und min/max/step selbst sind nur in
et_divi_customizer_theme_settings()(functions.php:1371) als Literale → nicht aufrufbar (brauchtWP_Customize_Manager) → Mirrornew Mirror('customizer-typography', 'functions.php', 'et_divi_customizer_theme_settings', null, 'Standards, Sanitize-Callbacks und Bereiche der 20 Whitelist-Settings')(große Funktion; Fingerabdruck schlägt bei jeder Customizer-Änderung an – akzeptabel oder engere Referenz wählen).
Sanitize
absint(WP-Core, nicht ins Manifest).et_sanitize_float_number– 1, untyp. (includes/functions/sanitization.php:7).et_sanitize_int_number– 1, untyp. (:16).et_sanitize_font_choices– 1, untyp. (:59).et_sanitize_global_font_weight– 1, untyp. (:345).et_divi_global_font_style– 1, untyp. (:358).- (indirekt
et_sanitize_key_based_option– 3, untyp.,:45.)
Schreiben
et_update_option– 2 (von 6), untyp. (epanel/custom_functions.php:276).et_delete_option– 1, untyp. (:320).
Rechte
et_pb_is_allowed– 1, untyp. (includes/builder/core.php:1136) mittheme_customizerbzw.custom_fonts_management.
Caches
ET_Core_PageResource::remove_static_resources– 2 oder 3 (von 7), untyp. (core/components/PageResource.php:1398).et_pb_force_regenerate_templates– 0 (includes/builder/core.php:3811).
Schriftlisten
et_builder_get_fonts– 0, untyp. (core.php:4730).et_builder_get_google_fonts– 0 (core.php:4911; Seiteneffekt HTTP, §0.7).et_builder_get_websafe_fonts– 0 (core.php:4783).et_builder_get_custom_fonts– 0 (core.php:4822).- optional
et_core_use_google_fonts– 0 (core/functions.php:223),et_builder_old_fonts_mapping– 0 (core.php:4839).
Font-Upload
ET\Builder\VisualBuilder\Fonts\FontsUtility::font_add– 4, typisiert(array, string, array, array = []), Rückgabe untyp. (FontsUtility.php:102).ET\Builder\VisualBuilder\Fonts\FontsUtility::font_remove– 1,(string), Rückgabe untyp. (:242).ET\Builder\VisualBuilder\Fonts\FontsUtility::mime_types_font– 0,(): array(:290).- Konstante
FontsUtility::FONT_NAME_MAX_LENGTH(:39). ET\Builder\VisualBuilder\Hooks\HooksRegistration::check_filetype_and_ext_font– 3,(array, string, string): array(HooksRegistration.php:77).et_pb_get_supported_font_formats– 0 (includes/builder/core.php:5090).- Hooks (nur Namen, Keys):
divi_visual_builder_fonts_custom_font_added,upload_dir/wp_check_filetype_and_ext(von Divi gesetzt).