| @@ -1,7 +1,7 @@ | ||
| 1 | 1 | <?php |
| 2 | 2 | /** |
| 3 | - * Desktop Mode — Desktop-theme manifest sanitizer. | |
| 3 | + * OpenStation — Desktop-theme manifest sanitizer. | |
| 4 | 4 | * |
| 5 | 5 | * Pure functions: no filesystem writes, no option reads. The one |
| 6 | 6 | * dependency on the outside world is an injected `$asset_resolver` |
| 7 | 7 | * callable, so the same sanitizer serves both intake paths: |
| @@ -7,9 +7,9 @@ | ||
| 7 | 7 | * callable, so the same sanitizer serves both intake paths: |
| 8 | 8 | * |
| 9 | 9 | * - ZIP uploads pass a resolver that validates a path INSIDE the |
| 10 | 10 | * staging directory and hands back the theme-relative path. |
| 11 | - * - Code registrations (`desktop_mode_register_desktop_theme()`) | |
| 11 | + * - Code registrations (`openstation_register_desktop_theme()`) | |
| 12 | 12 | * pass a resolver that validates an absolute http(s) URL. |
| 13 | 13 | * |
| 14 | 14 | * Both resolvers take the same two arguments — |
| 15 | 15 | * `fn( string $path, string $kind ): string|false` — where `$kind` |
| @@ -26,9 +26,9 @@ | ||
| 26 | 26 | * removed and the rest of the theme installs. That IS the |
| 27 | 27 | * fallback contract: whatever the manifest doesn't say, the |
| 28 | 28 | * system default keeps saying. |
| 29 | 29 | * |
| 30 | - * @package WPDesktopMode | |
| 30 | + * @package OpenStation | |
| 31 | 31 | */ |
| 32 | 32 | |
| 33 | 33 | defined( 'ABSPATH' ) || exit; |
| 34 | 34 | |
| @@ -72,9 +72,9 @@ | ||
| 72 | 72 | * |
| 73 | 73 | * @param mixed $value Candidate value. |
| 74 | 74 | * @return bool |
| 75 | 75 | */ |
| 76 | -function desktop_mode_desktop_theme_is_safe_css_value( $value ) { | |
| 76 | +function openstation_desktop_theme_is_safe_css_value( $value ) { | |
| 77 | 77 | if ( ! is_string( $value ) ) { |
| 78 | 78 | return false; |
| 79 | 79 | } |
| 80 | 80 | $value = trim( $value ); |
| @@ -118,9 +118,9 @@ | ||
| 118 | 118 | * |
| 119 | 119 | * @param mixed $raw Raw `tokens` value. |
| 120 | 120 | * @return array<string,string> |
| 121 | 121 | */ |
| 122 | -function desktop_mode_sanitize_desktop_theme_tokens( $raw ) { | |
| 122 | +function openstation_sanitize_desktop_theme_tokens( $raw ) { | |
| 123 | 123 | if ( ! is_array( $raw ) ) { |
| 124 | 124 | return array(); |
| 125 | 125 | } |
| 126 | 126 | $out = array(); |
| @@ -125,9 +125,17 @@ | ||
| 125 | 125 | } |
| 126 | 126 | $out = array(); |
| 127 | 127 | $count = 0; |
| 128 | 128 | foreach ( $raw as $key => $value ) { |
| 129 | - if ( $count >= 512 ) { | |
| 129 | + /* | |
| 130 | + * A size guard, not a design budget, and it needs headroom: | |
| 131 | + * Legacy answers every literal the palette declares, so it | |
| 132 | + * grows with the palette, and crossing this line is silent | |
| 133 | + * (a dropped entry falls back to the built-in value). What | |
| 134 | + * keeps a manifest safe is the namespace filter and the value | |
| 135 | + * grammar below, both per entry. | |
| 136 | + */ | |
| 137 | + if ( $count >= 2048 ) { | |
| 130 | 138 | break; |
| 131 | 139 | } |
| 132 | 140 | if ( ! is_string( $key ) ) { |
| 133 | 141 | continue; |
| @@ -134,31 +142,31 @@ | ||
| 134 | 142 | } |
| 135 | 143 | $key = strtolower( trim( $key ) ); |
| 136 | 144 | // Three namespaces are themable: |
| 137 | 145 | // |
| 138 | - // --desktop-mode-* the shell's own tokens (chrome, dock, | |
| 139 | - // desktop, window frame). | |
| 140 | - // --wpd-* the `<wpd-*>` component kit. Window | |
| 141 | - // BODIES are built from those components, | |
| 142 | - // and `--wpd-*` is the kit's documented | |
| 143 | - // theming contract (see | |
| 144 | - // `src/ui/core/tokens.ts`). Without this a | |
| 145 | - // theme could restyle the chrome around a | |
| 146 | - // window but not a single thing inside it. | |
| 147 | - // --wp-admin-theme-color | |
| 148 | - // the one Core property the shell already | |
| 149 | - // writes at runtime (the admin accent). | |
| 146 | + // --os-* the shell's own tokens (chrome, dock, | |
| 147 | + // desktop, window frame). | |
| 148 | + // --os-ui-* the `<os-*>` component kit. Window | |
| 149 | + // BODIES are built from those components, | |
| 150 | + // and `--os-ui-*` is the kit's documented | |
| 151 | + // theming contract (see | |
| 152 | + // `src/ui/core/tokens.ts`). Without this a | |
| 153 | + // theme could restyle the chrome around a | |
| 154 | + // window but not a single thing inside it. | |
| 155 | + // --wp-admin-theme-color | |
| 156 | + // the one Core property the shell already | |
| 157 | + // writes at runtime (the admin accent). | |
| 150 | 158 | // |
| 151 | 159 | // Everything else is dropped: a theme must not be able to |
| 152 | 160 | // reach properties the shell never meant to expose. |
| 153 | 161 | if ( |
| 154 | 162 | '--wp-admin-theme-color' !== $key |
| 155 | - && ! preg_match( '/^--desktop-mode-[a-z0-9-]+$/', $key ) | |
| 156 | - && ! preg_match( '/^--wpd-[a-z0-9-]+$/', $key ) | |
| 163 | + && ! preg_match( '/^--os-[a-z0-9-]+$/', $key ) | |
| 164 | + && ! preg_match( '/^--os-ui-[a-z0-9-]+$/', $key ) | |
| 157 | 165 | ) { |
| 158 | 166 | continue; |
| 159 | 167 | } |
| 160 | - if ( ! desktop_mode_desktop_theme_is_safe_css_value( $value ) ) { | |
| 168 | + if ( ! openstation_desktop_theme_is_safe_css_value( $value ) ) { | |
| 161 | 169 | continue; |
| 162 | 170 | } |
| 163 | 171 | $out[ $key ] = trim( (string) $value ); |
| 164 | 172 | ++$count; |
| @@ -181,9 +189,9 @@ | ||
| 181 | 189 | * |
| 182 | 190 | * @param mixed $value Candidate. |
| 183 | 191 | * @return bool |
| 184 | 192 | */ |
| 185 | -function desktop_mode_desktop_theme_is_color_value( $value ) { | |
| 193 | +function openstation_desktop_theme_is_color_value( $value ) { | |
| 186 | 194 | if ( ! is_string( $value ) ) { |
| 187 | 195 | return false; |
| 188 | 196 | } |
| 189 | 197 | $value = trim( preg_replace( '/\s+/', ' ', $value ) ); |
| @@ -191,9 +199,9 @@ | ||
| 191 | 199 | return false; |
| 192 | 200 | } |
| 193 | 201 | // The general grammar is still the floor — it is what bans `;`, |
| 194 | 202 | // `{`, `@`, quotes, comments and `var()`. |
| 195 | - if ( ! desktop_mode_desktop_theme_is_safe_css_value( $value ) ) { | |
| 203 | + if ( ! openstation_desktop_theme_is_safe_css_value( $value ) ) { | |
| 196 | 204 | return false; |
| 197 | 205 | } |
| 198 | 206 | if ( 0 === strcasecmp( 'currentcolor', $value ) ) { |
| 199 | 207 | // Normalized to the spelling CSS authors expect to read back. |
| @@ -238,13 +246,13 @@ | ||
| 238 | 246 | * to any icon that doesn't set its |
| 239 | 247 | * own. `''` for none. |
| 240 | 248 | * @return array<string,array> |
| 241 | 249 | */ |
| 242 | -function desktop_mode_sanitize_desktop_theme_icons( $raw, $asset_resolver, $default_color = '' ) { | |
| 250 | +function openstation_sanitize_desktop_theme_icons( $raw, $asset_resolver, $default_color = '' ) { | |
| 243 | 251 | if ( ! is_array( $raw ) ) { |
| 244 | 252 | return array(); |
| 245 | 253 | } |
| 246 | - $allowed = array_flip( array_map( 'strval', desktop_mode_desktop_theme_icon_slots() ) ); | |
| 254 | + $allowed = array_flip( array_map( 'strval', openstation_desktop_theme_icon_slots() ) ); | |
| 247 | 255 | $out = array(); |
| 248 | 256 | $count = 0; |
| 249 | 257 | foreach ( $raw as $slot => $descriptor ) { |
| 250 | 258 | if ( $count >= 256 ) { |
| @@ -280,10 +288,10 @@ | ||
| 280 | 288 | if ( isset( $descriptor['color'] ) && is_string( $descriptor['color'] ) ) { |
| 281 | 289 | $candidate = trim( $descriptor['color'] ); |
| 282 | 290 | if ( 0 === strcasecmp( 'none', $candidate ) ) { |
| 283 | 291 | $color = 'none'; |
| 284 | - } elseif ( desktop_mode_desktop_theme_is_color_value( $candidate ) ) { | |
| 285 | - $color = desktop_mode_desktop_theme_normalize_color( $candidate ); | |
| 292 | + } elseif ( openstation_desktop_theme_is_color_value( $candidate ) ) { | |
| 293 | + $color = openstation_desktop_theme_normalize_color( $candidate ); | |
| 286 | 294 | } |
| 287 | 295 | } |
| 288 | 296 | if ( '' === $color ) { |
| 289 | 297 | $color = $default_color; |
| @@ -340,9 +348,9 @@ | ||
| 340 | 348 | * |
| 341 | 349 | * @param string $value Validated colour. |
| 342 | 350 | * @return string |
| 343 | 351 | */ |
| 344 | -function desktop_mode_desktop_theme_normalize_color( $value ) { | |
| 352 | +function openstation_desktop_theme_normalize_color( $value ) { | |
| 345 | 353 | $value = trim( preg_replace( '/\s+/', ' ', (string) $value ) ); |
| 346 | 354 | return 0 === strcasecmp( 'currentcolor', $value ) ? 'currentColor' : $value; |
| 347 | 355 | } |
| 348 | 356 | |
| @@ -356,9 +364,9 @@ | ||
| 356 | 364 | * |
| 357 | 365 | * @param string $value Candidate. |
| 358 | 366 | * @return bool |
| 359 | 367 | */ |
| 360 | -function desktop_mode_desktop_theme_is_size_value( $value ) { | |
| 368 | +function openstation_desktop_theme_is_size_value( $value ) { | |
| 361 | 369 | $value = strtolower( trim( (string) $value ) ); |
| 362 | 370 | if ( in_array( $value, array( 'auto', 'cover', 'contain' ), true ) ) { |
| 363 | 371 | return true; |
| 364 | 372 | } |
| @@ -394,9 +402,9 @@ | ||
| 394 | 402 | * |
| 395 | 403 | * @param string $value Candidate. |
| 396 | 404 | * @return bool |
| 397 | 405 | */ |
| 398 | -function desktop_mode_desktop_theme_is_position_value( $value ) { | |
| 406 | +function openstation_desktop_theme_is_position_value( $value ) { | |
| 399 | 407 | $value = strtolower( trim( (string) $value ) ); |
| 400 | 408 | if ( '' === $value || strlen( $value ) > 64 ) { |
| 401 | 409 | return false; |
| 402 | 410 | } |
| @@ -431,13 +439,13 @@ | ||
| 431 | 439 | * @param mixed $raw Raw `textures` value. |
| 432 | 440 | * @param callable $asset_resolver `fn( string $path ): string|false`. |
| 433 | 441 | * @return array<string,array> |
| 434 | 442 | */ |
| 435 | -function desktop_mode_sanitize_desktop_theme_textures( $raw, $asset_resolver ) { | |
| 443 | +function openstation_sanitize_desktop_theme_textures( $raw, $asset_resolver ) { | |
| 436 | 444 | if ( ! is_array( $raw ) ) { |
| 437 | 445 | return array(); |
| 438 | 446 | } |
| 439 | - $slots = desktop_mode_desktop_theme_texture_slots(); | |
| 447 | + $slots = openstation_desktop_theme_texture_slots(); | |
| 440 | 448 | $out = array(); |
| 441 | 449 | $repeat = array( 'repeat', 'repeat-x', 'repeat-y', 'no-repeat', 'space', 'round' ); |
| 442 | 450 | |
| 443 | 451 | foreach ( $raw as $slot => $descriptor ) { |
| @@ -513,15 +521,15 @@ | ||
| 513 | 521 | } |
| 514 | 522 | } |
| 515 | 523 | if ( isset( $descriptor['size'] ) && is_string( $descriptor['size'] ) ) { |
| 516 | 524 | $value = strtolower( trim( preg_replace( '/\s+/', ' ', $descriptor['size'] ) ) ); |
| 517 | - if ( desktop_mode_desktop_theme_is_size_value( $value ) ) { | |
| 525 | + if ( openstation_desktop_theme_is_size_value( $value ) ) { | |
| 518 | 526 | $entry['size'] = $value; |
| 519 | 527 | } |
| 520 | 528 | } |
| 521 | 529 | if ( isset( $descriptor['position'] ) && is_string( $descriptor['position'] ) ) { |
| 522 | 530 | $value = strtolower( trim( preg_replace( '/\s+/', ' ', $descriptor['position'] ) ) ); |
| 523 | - if ( desktop_mode_desktop_theme_is_position_value( $value ) ) { | |
| 531 | + if ( openstation_desktop_theme_is_position_value( $value ) ) { | |
| 524 | 532 | $entry['position'] = $value; |
| 525 | 533 | } |
| 526 | 534 | } |
| 527 | 535 | } |
| @@ -543,9 +551,9 @@ | ||
| 543 | 551 | * |
| 544 | 552 | * @param string $ref Resolved reference. |
| 545 | 553 | * @return string Format keyword, or `''` when unrecognised. |
| 546 | 554 | */ |
| 547 | -function desktop_mode_desktop_theme_font_format( $ref ) { | |
| 555 | +function openstation_desktop_theme_font_format( $ref ) { | |
| 548 | 556 | $ref = (string) $ref; |
| 549 | 557 | $path = $ref; |
| 550 | 558 | if ( preg_match( '~^https?://~i', $ref ) ) { |
| 551 | 559 | $path = (string) wp_parse_url( $ref, PHP_URL_PATH ); |
| @@ -555,9 +563,9 @@ | ||
| 555 | 563 | 'woff' => 'woff', |
| 556 | 564 | 'ttf' => 'truetype', |
| 557 | 565 | 'otf' => 'opentype', |
| 558 | 566 | ); |
| 559 | - $ext = strtolower( (string) pathinfo( $path, PATHINFO_EXTENSION ) ); | |
| 567 | + $ext = strtolower( (string) pathinfo( $path, PATHINFO_EXTENSION ) ); | |
| 560 | 568 | return isset( $formats[ $ext ] ) ? $formats[ $ext ] : ''; |
| 561 | 569 | } |
| 562 | 570 | |
| 563 | 571 | /** |
| @@ -589,13 +597,13 @@ | ||
| 589 | 597 | * @param mixed $raw Raw `fonts` value. |
| 590 | 598 | * @param callable $asset_resolver `fn( string $path, string $kind ): string|false`. |
| 591 | 599 | * @return array<int,array> |
| 592 | 600 | */ |
| 593 | -function desktop_mode_sanitize_desktop_theme_fonts( $raw, $asset_resolver ) { | |
| 601 | +function openstation_sanitize_desktop_theme_fonts( $raw, $asset_resolver ) { | |
| 594 | 602 | if ( ! is_array( $raw ) ) { |
| 595 | 603 | return array(); |
| 596 | 604 | } |
| 597 | - $caps = desktop_mode_desktop_theme_font_caps(); | |
| 605 | + $caps = openstation_desktop_theme_font_caps(); | |
| 598 | 606 | $out = array(); |
| 599 | 607 | |
| 600 | 608 | foreach ( $raw as $face ) { |
| 601 | 609 | if ( count( $out ) >= $caps['max_faces'] ) { |
| @@ -638,9 +646,9 @@ | ||
| 638 | 646 | $ref = call_user_func( $asset_resolver, $candidate, 'font' ); |
| 639 | 647 | if ( ! is_string( $ref ) || '' === $ref ) { |
| 640 | 648 | continue; |
| 641 | 649 | } |
| 642 | - $format = desktop_mode_desktop_theme_font_format( $ref ); | |
| 650 | + $format = openstation_desktop_theme_font_format( $ref ); | |
| 643 | 651 | if ( '' === $format ) { |
| 644 | 652 | continue; |
| 645 | 653 | } |
| 646 | 654 | $sources[] = array( |
| @@ -770,9 +778,9 @@ | ||
| 770 | 778 | * @param mixed $raw Raw `wallpaper` / `wallpapers` value. |
| 771 | 779 | * @param callable $asset_resolver `fn( string $path, string $kind ): string|false`. |
| 772 | 780 | * @return array[] List of sanitized descriptors. |
| 773 | 781 | */ |
| 774 | -function desktop_mode_sanitize_desktop_theme_wallpapers( $raw, $asset_resolver ) { | |
| 782 | +function openstation_sanitize_desktop_theme_wallpapers( $raw, $asset_resolver ) { | |
| 775 | 783 | if ( is_string( $raw ) ) { |
| 776 | 784 | $raw = array( array( 'path' => $raw ) ); |
| 777 | 785 | } elseif ( is_array( $raw ) && isset( $raw['path'] ) ) { |
| 778 | 786 | // A single descriptor, not a collection. |
| @@ -786,9 +794,9 @@ | ||
| 786 | 794 | * Filters how many wallpapers one desktop theme may contribute. |
| 787 | 795 | * |
| 788 | 796 | * @param int $max Default 12. |
| 789 | 797 | */ |
| 790 | - $max = max( 1, (int) apply_filters( 'desktop_mode_desktop_theme_max_wallpapers', 12 ) ); | |
| 798 | + $max = max( 1, (int) apply_filters( 'openstation_desktop_theme_max_wallpapers', 12 ) ); | |
| 791 | 799 | $out = array(); |
| 792 | 800 | $seen = array(); |
| 793 | 801 | |
| 794 | 802 | foreach ( $raw as $key => $entry ) { |
| @@ -845,15 +853,15 @@ | ||
| 845 | 853 | } |
| 846 | 854 | } |
| 847 | 855 | if ( isset( $entry['size'] ) && is_string( $entry['size'] ) ) { |
| 848 | 856 | $value = strtolower( trim( preg_replace( '/\s+/', ' ', $entry['size'] ) ) ); |
| 849 | - if ( desktop_mode_desktop_theme_is_size_value( $value ) ) { | |
| 857 | + if ( openstation_desktop_theme_is_size_value( $value ) ) { | |
| 850 | 858 | $item['size'] = $value; |
| 851 | 859 | } |
| 852 | 860 | } |
| 853 | 861 | if ( isset( $entry['position'] ) && is_string( $entry['position'] ) ) { |
| 854 | 862 | $value = strtolower( trim( preg_replace( '/\s+/', ' ', $entry['position'] ) ) ); |
| 855 | - if ( desktop_mode_desktop_theme_is_position_value( $value ) ) { | |
| 863 | + if ( openstation_desktop_theme_is_position_value( $value ) ) { | |
| 856 | 864 | $item['position'] = $value; |
| 857 | 865 | } |
| 858 | 866 | } |
| 859 | 867 | if ( isset( $entry['description'] ) && is_string( $entry['description'] ) ) { |
| @@ -873,8 +881,9 @@ | ||
| 873 | 881 | * ```json |
| 874 | 882 | * "recommendedOsSettings": { |
| 875 | 883 | * "dockSize": "large", |
| 876 | 884 | * "desktopLayout": "unified", |
| 885 | + * "dockPlacement": "left", | |
| 877 | 886 | * "windowRadius": "default", |
| 878 | 887 | * "adminBarMode": "dynamic", |
| 879 | 888 | * "dockRailRenderer": "default" |
| 880 | 889 | * } |
| @@ -886,9 +895,9 @@ | ||
| 886 | 895 | * keeps their choice for good. See docs/desktop-themes.md § |
| 887 | 896 | * "Recommended OS settings" for the full contract. |
| 888 | 897 | * |
| 889 | 898 | * Every key is checked against |
| 890 | - * {@see desktop_mode_desktop_theme_recommended_os_settings_schema()}, | |
| 899 | + * {@see openstation_desktop_theme_recommended_os_settings_schema()}, | |
| 891 | 900 | * and the same drop-and-continue posture as the rest of the manifest |
| 892 | 901 | * applies: an unknown key or an out-of-enum value disappears and the |
| 893 | 902 | * remaining recommendations survive. |
| 894 | 903 | * |
| @@ -896,13 +905,13 @@ | ||
| 896 | 905 | * |
| 897 | 906 | * @param mixed $raw Raw `recommendedOsSettings` value. |
| 898 | 907 | * @return array<string,string|int> |
| 899 | 908 | */ |
| 900 | -function desktop_mode_sanitize_desktop_theme_recommended_os_settings( $raw ) { | |
| 909 | +function openstation_sanitize_desktop_theme_recommended_os_settings( $raw ) { | |
| 901 | 910 | if ( ! is_array( $raw ) ) { |
| 902 | 911 | return array(); |
| 903 | 912 | } |
| 904 | - $schema = desktop_mode_desktop_theme_recommended_os_settings_schema(); | |
| 913 | + $schema = openstation_desktop_theme_recommended_os_settings_schema(); | |
| 905 | 914 | $out = array(); |
| 906 | 915 | foreach ( $schema as $key => $rule ) { |
| 907 | 916 | if ( ! isset( $raw[ $key ] ) ) { |
| 908 | 917 | continue; |
| @@ -957,12 +966,12 @@ | ||
| 957 | 966 | * allowlist. |
| 958 | 967 | * @return array|WP_Error Sanitized manifest, or `WP_Error` when a |
| 959 | 968 | * structural field is missing/invalid. |
| 960 | 969 | */ |
| 961 | -function desktop_mode_sanitize_desktop_theme_manifest( $raw, $asset_resolver ) { | |
| 970 | +function openstation_sanitize_desktop_theme_manifest( $raw, $asset_resolver ) { | |
| 962 | 971 | if ( ! is_array( $raw ) ) { |
| 963 | 972 | return new WP_Error( |
| 964 | - 'desktop_mode_desktop_theme_invalid_manifest', | |
| 973 | + 'openstation_desktop_theme_invalid_manifest', | |
| 965 | 974 | __( 'The theme manifest is not a JSON object.', 'desktop-mode' ), |
| 966 | 975 | array( 'status' => 400 ) |
| 967 | 976 | ); |
| 968 | 977 | } |
| @@ -967,9 +976,9 @@ | ||
| 967 | 976 | ); |
| 968 | 977 | } |
| 969 | 978 | if ( ! is_callable( $asset_resolver ) ) { |
| 970 | 979 | return new WP_Error( |
| 971 | - 'desktop_mode_desktop_theme_invalid_resolver', | |
| 980 | + 'openstation_desktop_theme_invalid_resolver', | |
| 972 | 981 | __( 'No asset resolver was provided for this manifest.', 'desktop-mode' ), |
| 973 | 982 | array( 'status' => 500 ) |
| 974 | 983 | ); |
| 975 | 984 | } |
| @@ -987,9 +996,9 @@ | ||
| 987 | 996 | $version_field = isset( $raw['manifestVersion'] ) ? $raw['manifestVersion'] : null; |
| 988 | 997 | $version = is_numeric( $version_field ) ? (int) $version_field : 0; |
| 989 | 998 | if ( ! in_array( $version, array( 1, 2 ), true ) ) { |
| 990 | 999 | return new WP_Error( |
| 991 | - 'desktop_mode_desktop_theme_bad_version', | |
| 1000 | + 'openstation_desktop_theme_bad_version', | |
| 992 | 1001 | __( 'Unsupported theme manifest version. Expected "manifestVersion": 1 or 2.', 'desktop-mode' ), |
| 993 | 1002 | array( 'status' => 400 ) |
| 994 | 1003 | ); |
| 995 | 1004 | } |
| @@ -996,17 +1005,17 @@ | ||
| 996 | 1005 | |
| 997 | 1006 | $id = isset( $raw['id'] ) && is_string( $raw['id'] ) ? trim( $raw['id'] ) : ''; |
| 998 | 1007 | if ( '' === $id || strlen( $id ) > 64 || ! preg_match( '~^[a-z0-9_-]+(/[a-z0-9_-]+)?$~', $id ) ) { |
| 999 | 1008 | return new WP_Error( |
| 1000 | - 'desktop_mode_desktop_theme_bad_id', | |
| 1009 | + 'openstation_desktop_theme_bad_id', | |
| 1001 | 1010 | __( 'The theme id must look like "neon-glass" or "vendor/neon-glass" (lowercase, max 64 characters).', 'desktop-mode' ), |
| 1002 | 1011 | array( 'status' => 400 ) |
| 1003 | 1012 | ); |
| 1004 | 1013 | } |
| 1005 | - $slug = desktop_mode_desktop_theme_slug_from_id( $id ); | |
| 1014 | + $slug = openstation_desktop_theme_slug_from_id( $id ); | |
| 1006 | 1015 | if ( '' === $slug ) { |
| 1007 | 1016 | return new WP_Error( |
| 1008 | - 'desktop_mode_desktop_theme_bad_id', | |
| 1017 | + 'openstation_desktop_theme_bad_id', | |
| 1009 | 1018 | __( 'The theme id does not reduce to a usable slug.', 'desktop-mode' ), |
| 1010 | 1019 | array( 'status' => 400 ) |
| 1011 | 1020 | ); |
| 1012 | 1021 | } |
| @@ -1013,9 +1022,9 @@ | ||
| 1013 | 1022 | |
| 1014 | 1023 | $name = isset( $raw['name'] ) && is_string( $raw['name'] ) ? sanitize_text_field( $raw['name'] ) : ''; |
| 1015 | 1024 | if ( '' === $name ) { |
| 1016 | 1025 | return new WP_Error( |
| 1017 | - 'desktop_mode_desktop_theme_missing_name', | |
| 1026 | + 'openstation_desktop_theme_missing_name', | |
| 1018 | 1027 | __( 'The theme manifest requires a non-empty "name".', 'desktop-mode' ), |
| 1019 | 1028 | array( 'status' => 400 ) |
| 1020 | 1029 | ); |
| 1021 | 1030 | } |
| @@ -1033,10 +1042,10 @@ | ||
| 1033 | 1042 | // Manifest-wide icon tint. Applied to every icon that doesn't set |
| 1034 | 1043 | // its own `color`, so a monochrome iconset is one line rather than |
| 1035 | 1044 | // twenty-odd repetitions. |
| 1036 | 1045 | $icon_color = ''; |
| 1037 | - if ( isset( $raw['iconColor'] ) && desktop_mode_desktop_theme_is_color_value( $raw['iconColor'] ) ) { | |
| 1038 | - $icon_color = desktop_mode_desktop_theme_normalize_color( $raw['iconColor'] ); | |
| 1046 | + if ( isset( $raw['iconColor'] ) && openstation_desktop_theme_is_color_value( $raw['iconColor'] ) ) { | |
| 1047 | + $icon_color = openstation_desktop_theme_normalize_color( $raw['iconColor'] ); | |
| 1039 | 1048 | } |
| 1040 | 1049 | |
| 1041 | 1050 | $manifest = array( |
| 1042 | 1051 | 'manifestVersion' => $version, |
| @@ -1052,28 +1061,28 @@ | ||
| 1052 | 1061 | 'description' => isset( $raw['description'] ) && is_string( $raw['description'] ) |
| 1053 | 1062 | ? mb_substr( sanitize_textarea_field( $raw['description'] ), 0, 500 ) |
| 1054 | 1063 | : '', |
| 1055 | 1064 | 'preview' => $preview, |
| 1056 | - 'tokens' => desktop_mode_sanitize_desktop_theme_tokens( | |
| 1065 | + 'tokens' => openstation_sanitize_desktop_theme_tokens( | |
| 1057 | 1066 | isset( $raw['tokens'] ) ? $raw['tokens'] : null |
| 1058 | 1067 | ), |
| 1059 | 1068 | 'iconColor' => $icon_color, |
| 1060 | - 'icons' => desktop_mode_sanitize_desktop_theme_icons( | |
| 1069 | + 'icons' => openstation_sanitize_desktop_theme_icons( | |
| 1061 | 1070 | isset( $raw['icons'] ) ? $raw['icons'] : null, |
| 1062 | 1071 | $asset_resolver, |
| 1063 | 1072 | $icon_color |
| 1064 | 1073 | ), |
| 1065 | - 'textures' => desktop_mode_sanitize_desktop_theme_textures( | |
| 1074 | + 'textures' => openstation_sanitize_desktop_theme_textures( | |
| 1066 | 1075 | isset( $raw['textures'] ) ? $raw['textures'] : null, |
| 1067 | 1076 | $asset_resolver |
| 1068 | 1077 | ), |
| 1069 | - 'fonts' => desktop_mode_sanitize_desktop_theme_fonts( | |
| 1078 | + 'fonts' => openstation_sanitize_desktop_theme_fonts( | |
| 1070 | 1079 | isset( $raw['fonts'] ) ? $raw['fonts'] : null, |
| 1071 | 1080 | $asset_resolver |
| 1072 | 1081 | ), |
| 1073 | 1082 | // `wallpaper` and `wallpapers` are both accepted — authors |
| 1074 | 1083 | // guess either — and merge into one list. |
| 1075 | - 'wallpapers' => desktop_mode_sanitize_desktop_theme_wallpapers( | |
| 1084 | + 'wallpapers' => openstation_sanitize_desktop_theme_wallpapers( | |
| 1076 | 1085 | isset( $raw['wallpapers'] ) ? $raw['wallpapers'] : ( |
| 1077 | 1086 | isset( $raw['wallpaper'] ) ? $raw['wallpaper'] : null |
| 1078 | 1087 | ), |
| 1079 | 1088 | $asset_resolver |
| @@ -1079,9 +1088,9 @@ | ||
| 1079 | 1088 | $asset_resolver |
| 1080 | 1089 | ), |
| 1081 | 1090 | // Presentation preferences the theme would like the user to |
| 1082 | 1091 | // wear. Applied once, on first activation — never on load. |
| 1083 | - 'recommendedOsSettings' => desktop_mode_sanitize_desktop_theme_recommended_os_settings( | |
| 1092 | + 'recommendedOsSettings' => openstation_sanitize_desktop_theme_recommended_os_settings( | |
| 1084 | 1093 | isset( $raw['recommendedOsSettings'] ) ? $raw['recommendedOsSettings'] : null |
| 1085 | 1094 | ), |
| 1086 | 1095 | ); |
| 1087 | 1096 | |
| @@ -1096,9 +1105,9 @@ | ||
| 1096 | 1105 | * @param array $manifest Sanitized manifest. |
| 1097 | 1106 | * @param array $raw The manifest as the author wrote it. |
| 1098 | 1107 | * @param string $slug Storage slug derived from `id`. |
| 1099 | 1108 | */ |
| 1100 | - $manifest = (array) apply_filters( 'desktop_mode_desktop_theme_manifest', $manifest, $raw, $slug ); | |
| 1109 | + $manifest = (array) apply_filters( 'openstation_desktop_theme_manifest', $manifest, $raw, $slug ); | |
| 1101 | 1110 | |
| 1102 | 1111 | return $manifest; |
| 1103 | 1112 | } |
| 1104 | 1113 | |
| @@ -1113,9 +1122,9 @@ | ||
| 1113 | 1122 | * |
| 1114 | 1123 | * @param string $staging_dir Absolute path of the extracted ZIP. |
| 1115 | 1124 | * @return callable `fn( string $path, string $kind = 'image' ): string|false` |
| 1116 | 1125 | */ |
| 1117 | -function desktop_mode_desktop_theme_staging_asset_resolver( $staging_dir ) { | |
| 1126 | +function openstation_desktop_theme_staging_asset_resolver( $staging_dir ) { | |
| 1118 | 1127 | $base = realpath( $staging_dir ); |
| 1119 | 1128 | return static function ( $path, $kind = 'image' ) use ( $base ) { |
| 1120 | 1129 | if ( false === $base || ! is_string( $path ) ) { |
| 1121 | 1130 | return false; |
| @@ -1135,9 +1144,9 @@ | ||
| 1135 | 1144 | return false; |
| 1136 | 1145 | } |
| 1137 | 1146 | } |
| 1138 | 1147 | $ext = strtolower( (string) pathinfo( $path, PATHINFO_EXTENSION ) ); |
| 1139 | - if ( ! in_array( $ext, desktop_mode_desktop_theme_asset_extensions( $kind ), true ) ) { | |
| 1148 | + if ( ! in_array( $ext, openstation_desktop_theme_asset_extensions( $kind ), true ) ) { | |
| 1140 | 1149 | return false; |
| 1141 | 1150 | } |
| 1142 | 1151 | $full = realpath( $base . '/' . $path ); |
| 1143 | 1152 | if ( false === $full || ! is_file( $full ) ) { |
| @@ -1155,9 +1164,9 @@ | ||
| 1155 | 1164 | * are already-published http(s) URLs rather than files in a ZIP. |
| 1156 | 1165 | * |
| 1157 | 1166 | * @return callable `fn( string $url, string $kind = 'image' ): string|false` |
| 1158 | 1167 | */ |
| 1159 | -function desktop_mode_desktop_theme_url_asset_resolver() { | |
| 1168 | +function openstation_desktop_theme_url_asset_resolver() { | |
| 1160 | 1169 | return static function ( $url, $kind = 'image' ) { |
| 1161 | 1170 | if ( ! is_string( $url ) ) { |
| 1162 | 1171 | return false; |
| 1163 | 1172 | } |
| @@ -1177,9 +1186,9 @@ | ||
| 1177 | 1186 | return false; |
| 1178 | 1187 | } |
| 1179 | 1188 | $path = (string) wp_parse_url( $url, PHP_URL_PATH ); |
| 1180 | 1189 | $ext = strtolower( (string) pathinfo( $path, PATHINFO_EXTENSION ) ); |
| 1181 | - if ( ! in_array( $ext, desktop_mode_desktop_theme_asset_extensions( $kind ), true ) ) { | |
| 1190 | + if ( ! in_array( $ext, openstation_desktop_theme_asset_extensions( $kind ), true ) ) { | |
| 1182 | 1191 | return false; |
| 1183 | 1192 | } |
| 1184 | 1193 | return $url; |
| 1185 | 1194 | }; |