| 1 |
<?php |
| 2 |
/** |
| 3 |
* OpenStation — Desktop-theme enqueue + body class + shell config. |
| 4 |
* |
| 5 |
* **Zero cost when no theme is active.** Every entry point here |
| 6 |
* early-returns on an empty selection before it reads an option, |
| 7 |
* touches the filesystem, or registers a handle. A site whose users |
| 8 |
* all sit on "System default" pays one user-meta read that the OS |
| 9 |
* settings layer was doing anyway. |
| 10 |
* |
| 11 |
* @package OpenStation |
| 12 |
*/ |
| 13 |
|
| 14 |
defined( 'ABSPATH' ) || exit; |
| 15 |
|
| 16 |
/** Style handle for the compiled desktop-theme stylesheet. */ |
| 17 |
const OPENSTATION_DESKTOP_THEME_STYLE_HANDLE = 'os-desktop-theme'; |
| 18 |
|
| 19 |
/** |
| 20 |
* Resolve the desktop theme a user has selected, if it still exists. |
| 21 |
* |
| 22 |
* Orphans degrade silently: a user whose selected theme was deleted |
| 23 |
* (or whose registering plugin was deactivated) gets `''` here and |
| 24 |
* sees the system default, with no user-meta rewrite and no error. |
| 25 |
* |
| 26 |
* @param int $user_id User id. Defaults to the current user. |
| 27 |
* @return string Slug, or `''` for the system default. |
| 28 |
*/ |
| 29 |
function openstation_active_desktop_theme_slug( $user_id = 0 ) { |
| 30 |
$user_id = (int) $user_id; |
| 31 |
if ( $user_id <= 0 ) { |
| 32 |
$user_id = get_current_user_id(); |
| 33 |
} |
| 34 |
if ( $user_id <= 0 ) { |
| 35 |
return ''; |
| 36 |
} |
| 37 |
|
| 38 |
$settings = openstation_get_os_settings( $user_id ); |
| 39 |
$slug = isset( $settings['desktopTheme'] ) ? sanitize_key( (string) $settings['desktopTheme'] ) : ''; |
| 40 |
if ( '' === $slug ) { |
| 41 |
return ''; |
| 42 |
} |
| 43 |
|
| 44 |
// Existence check across both sources. This is the safety net |
| 45 |
// that lets the os-settings sanitizer stay a cheap pattern check |
| 46 |
// instead of loading the themes option on every settings write. |
| 47 |
if ( null !== openstation_desktop_theme_get( $slug ) ) { |
| 48 |
return $slug; |
| 49 |
} |
| 50 |
if ( null !== openstation_desktop_theme_registry( $slug ) ) { |
| 51 |
return $slug; |
| 52 |
} |
| 53 |
return ''; |
| 54 |
} |
| 55 |
|
| 56 |
/** |
| 57 |
* Whether this request should carry desktop-theme assets at all. |
| 58 |
* |
| 59 |
* @internal |
| 60 |
* |
| 61 |
* @return bool |
| 62 |
*/ |
| 63 |
function openstation_desktop_theme_request_is_themable() { |
| 64 |
return openstation_is_enabled() |
| 65 |
&& ! openstation_is_chromeless_request() |
| 66 |
&& ! openstation_is_classic_request(); |
| 67 |
} |
| 68 |
|
| 69 |
/** |
| 70 |
* Enqueue the active theme's compiled stylesheet. |
| 71 |
* |
| 72 |
* The `os-variables` dependency is load-bearing, not |
| 73 |
* decoration: the compiled selectors weigh the same as the |
| 74 |
* per-admin-color-scheme blocks in `variables.css`, and a |
| 75 |
* specificity tie is settled by source order. Drop the dependency |
| 76 |
* and a themed token silently loses to the color scheme. |
| 77 |
*/ |
| 78 |
function openstation_enqueue_desktop_theme_style() { |
| 79 |
if ( ! openstation_desktop_theme_request_is_themable() ) { |
| 80 |
return; |
| 81 |
} |
| 82 |
$slug = openstation_active_desktop_theme_slug(); |
| 83 |
if ( '' === $slug ) { |
| 84 |
// The whole point: nothing registered, nothing enqueued, no |
| 85 |
// extra request, no extra bytes. |
| 86 |
return; |
| 87 |
} |
| 88 |
|
| 89 |
$uploaded = openstation_desktop_theme_get( $slug ); |
| 90 |
if ( is_array( $uploaded ) ) { |
| 91 |
$version = isset( $uploaded['installedAt'] ) ? (string) (int) $uploaded['installedAt'] : OPENSTATION_VERSION; |
| 92 |
wp_enqueue_style( |
| 93 |
OPENSTATION_DESKTOP_THEME_STYLE_HANDLE, |
| 94 |
openstation_desktop_themes_url( $slug ) . '/theme.css', |
| 95 |
array( 'os-variables' ), |
| 96 |
$version |
| 97 |
); |
| 98 |
return; |
| 99 |
} |
| 100 |
|
| 101 |
$code = openstation_desktop_theme_registry( $slug ); |
| 102 |
if ( is_array( $code ) && ! empty( $code['cssText'] ) ) { |
| 103 |
// Code themes have no file to link. Register a src-less stub |
| 104 |
// so `wp_add_inline_style()` has a handle to hang off, and |
| 105 |
// keep the same dependency so print order is identical. |
| 106 |
wp_register_style( |
| 107 |
OPENSTATION_DESKTOP_THEME_STYLE_HANDLE, |
| 108 |
false, |
| 109 |
array( 'os-variables' ), |
| 110 |
OPENSTATION_VERSION |
| 111 |
); |
| 112 |
wp_enqueue_style( OPENSTATION_DESKTOP_THEME_STYLE_HANDLE ); |
| 113 |
wp_add_inline_style( OPENSTATION_DESKTOP_THEME_STYLE_HANDLE, (string) $code['cssText'] ); |
| 114 |
} |
| 115 |
} |
| 116 |
add_action( 'admin_enqueue_scripts', 'openstation_enqueue_desktop_theme_style', 20 ); |
| 117 |
|
| 118 |
/** |
| 119 |
* Add `os-desktop-theme-<slug>` to the admin body classes. |
| 120 |
* |
| 121 |
* The compiled stylesheet scopes to this class as well as to the |
| 122 |
* shell root, because toasts / dialogs / tooltips / context menus |
| 123 |
* mount on `document.body`, outside `#os-shell`. |
| 124 |
* |
| 125 |
* `admin_body_class` is a STRING filter — concatenate, never |
| 126 |
* array-push. |
| 127 |
* |
| 128 |
* @param string $classes Space-separated class list. |
| 129 |
* @return string |
| 130 |
*/ |
| 131 |
function openstation_desktop_theme_body_class( $classes ) { |
| 132 |
if ( ! openstation_desktop_theme_request_is_themable() ) { |
| 133 |
return $classes; |
| 134 |
} |
| 135 |
$slug = openstation_active_desktop_theme_slug(); |
| 136 |
if ( '' === $slug ) { |
| 137 |
return $classes; |
| 138 |
} |
| 139 |
return trim( $classes . ' os-desktop-theme-' . $slug ); |
| 140 |
} |
| 141 |
add_filter( 'admin_body_class', 'openstation_desktop_theme_body_class', 20 ); |
| 142 |
|
| 143 |
/** |
| 144 |
* Inject the desktop-theme bits of the shell config. |
| 145 |
* |
| 146 |
* Uses the public `openstation_shell_config` filter rather than |
| 147 |
* editing the config literal in `includes/render/assets.php`, the |
| 148 |
* same way the stored-files module contributes `desktopStorage`. |
| 149 |
* |
| 150 |
* @param array $config Shell config. |
| 151 |
* @return array |
| 152 |
*/ |
| 153 |
function openstation_desktop_theme_inject_shell_config( $config ) { |
| 154 |
$config['canManageDesktopThemes'] = current_user_can( openstation_desktop_theme_upload_capability() ); |
| 155 |
$config['desktopThemesUrl'] = esc_url_raw( rest_url( 'desktop-mode/v1/desktop-themes' ) ); |
| 156 |
return $config; |
| 157 |
} |
| 158 |
add_filter( 'openstation_shell_config', 'openstation_desktop_theme_inject_shell_config', 20 ); |
| 159 |
|