| 1 |
<?php |
| 2 |
/** |
| 3 |
* OpenStation — Desktop-theme wallpapers. |
| 4 |
* |
| 5 |
* A theme may declare any number of wallpapers in its manifest. Each |
| 6 |
* is published into the ordinary wallpaper registry as a pickable |
| 7 |
* entry labelled `<name> - (theme)`, alongside the built-in gradients |
| 8 |
* and canvas wallpapers. A theme shipping several names them, and the |
| 9 |
* label becomes `<name>: <label> - (theme)`. |
| 10 |
* |
| 11 |
* ## Why it is a pick and not an act |
| 12 |
* |
| 13 |
* Every other desktop OS swaps the wallpaper when you apply a theme. |
| 14 |
* We deliberately do not, because a wallpaper here is a **stored user |
| 15 |
* preference** (`wallpaper` in `desktop_mode_os_settings`), and |
| 16 |
* activating a theme would have to either overwrite that silently or |
| 17 |
* grow a shadow "what did they have before" record to undo it later. |
| 18 |
* Both are worse than simply offering the theme's artwork in the |
| 19 |
* place the user already goes to change wallpapers. |
| 20 |
* |
| 21 |
* The practical consequence is a nice one: a theme's wallpaper is |
| 22 |
* usable WITHOUT wearing the theme, and wearing the theme never |
| 23 |
* costs you the wallpaper you chose. |
| 24 |
* |
| 25 |
* Note this is separate from the `DESKTOP` texture slot. That slot |
| 26 |
* layers over whatever wallpaper is active and follows the theme; |
| 27 |
* this is a wallpaper in its own right that the user selects. |
| 28 |
* |
| 29 |
* @package OpenStation |
| 30 |
*/ |
| 31 |
|
| 32 |
defined( 'ABSPATH' ) || exit; |
| 33 |
|
| 34 |
/** |
| 35 |
* Prefix for wallpaper ids minted from desktop themes. |
| 36 |
* |
| 37 |
* Namespaced so a theme's wallpaper can never collide with a |
| 38 |
* built-in or with a plugin's own registration. |
| 39 |
*/ |
| 40 |
const OPENSTATION_DESKTOP_THEME_WALLPAPER_PREFIX = 'desktop-theme/'; |
| 41 |
|
| 42 |
/** |
| 43 |
* Build the CSS `background` value for a theme's wallpaper. |
| 44 |
* |
| 45 |
* PHP writes the `url()` itself from the resolved, `rawurlencode`d |
| 46 |
* path — the same rule the compiler follows, and the reason a |
| 47 |
* manifest may not contain a `url()` of its own. |
| 48 |
* |
| 49 |
* @internal |
| 50 |
* |
| 51 |
* @param array $wallpaper Sanitized `wallpaper` block. |
| 52 |
* @param string $base_url Theme base URL (empty for code themes, |
| 53 |
* whose paths are absolute already). |
| 54 |
* @param string $version Cache-buster for relative paths. |
| 55 |
* @return string CSS value, or `''` when unusable. |
| 56 |
*/ |
| 57 |
function openstation_desktop_theme_wallpaper_css( $wallpaper, $base_url = '', $version = '' ) { |
| 58 |
if ( ! is_array( $wallpaper ) || empty( $wallpaper['path'] ) ) { |
| 59 |
return ''; |
| 60 |
} |
| 61 |
$url = openstation_desktop_theme_asset_url( $wallpaper['path'], $base_url, $version ); |
| 62 |
if ( '' === $url ) { |
| 63 |
return ''; |
| 64 |
} |
| 65 |
|
| 66 |
// `<image> <position> / <size> <repeat>` — a background shorthand, |
| 67 |
// which is what `--os-bg` is assigned to. Defaults cover |
| 68 |
// the overwhelmingly common case (a photo filling the desk); the |
| 69 |
// manifest can override each part through the same grammar the |
| 70 |
// texture slots use. |
| 71 |
$position = ! empty( $wallpaper['position'] ) ? (string) $wallpaper['position'] : 'center center'; |
| 72 |
$size = ! empty( $wallpaper['size'] ) ? (string) $wallpaper['size'] : 'cover'; |
| 73 |
$repeat = ! empty( $wallpaper['repeat'] ) ? (string) $wallpaper['repeat'] : 'no-repeat'; |
| 74 |
|
| 75 |
return openstation_desktop_theme_css_url( $url ) . ' ' . $position . ' / ' . $size . ' ' . $repeat; |
| 76 |
} |
| 77 |
|
| 78 |
/** |
| 79 |
* Picker label for a theme's wallpaper. |
| 80 |
* |
| 81 |
* The theme `name` reaching this function has already been through |
| 82 |
* `sanitize_text_field()` in the manifest sanitizer, and |
| 83 |
* `openstation_register_wallpaper()` sanitizes the finished label |
| 84 |
* again on the way into the registry. Both are belt-and-braces: the |
| 85 |
* shell paints wallpaper labels through the `html` tagged template, |
| 86 |
* whose text slots are built with `createTextNode()`, so a label is |
| 87 |
* never parsed as markup. |
| 88 |
* |
| 89 |
* @param string $name Theme display name. |
| 90 |
* @param string $slug Theme slug. |
| 91 |
* @param string $own_label The wallpaper's own label, or `''`. |
| 92 |
* @return string |
| 93 |
*/ |
| 94 |
function openstation_desktop_theme_wallpaper_label( $name, $slug, $own_label = '' ) { |
| 95 |
$own_label = (string) $own_label; |
| 96 |
if ( '' === $own_label ) { |
| 97 |
$label = sprintf( |
| 98 |
/* translators: %s: desktop theme name. Marks a wallpaper that came from a theme. */ |
| 99 |
__( '%s - (theme)', 'desktop-mode' ), |
| 100 |
$name |
| 101 |
); |
| 102 |
} else { |
| 103 |
$label = sprintf( |
| 104 |
/* translators: 1: desktop theme name, 2: the wallpaper's own name. */ |
| 105 |
__( '%1$s: %2$s - (theme)', 'desktop-mode' ), |
| 106 |
$name, |
| 107 |
$own_label |
| 108 |
); |
| 109 |
} |
| 110 |
/** |
| 111 |
* Filters the picker label for a wallpaper contributed by a |
| 112 |
* desktop theme. |
| 113 |
* |
| 114 |
* @param string $label Default `<name> - (theme)`, or |
| 115 |
* `<name>: <own label> - (theme)`. |
| 116 |
* @param string $name Theme display name. |
| 117 |
* @param string $slug Theme slug. |
| 118 |
* @param string $own_label The wallpaper's own label, or `''`. |
| 119 |
*/ |
| 120 |
return (string) apply_filters( |
| 121 |
'openstation_desktop_theme_wallpaper_label', |
| 122 |
$label, |
| 123 |
$name, |
| 124 |
$slug, |
| 125 |
$own_label |
| 126 |
); |
| 127 |
} |
| 128 |
|
| 129 |
/** |
| 130 |
* Register one wallpaper per installed/registered theme that declares |
| 131 |
* one. |
| 132 |
* |
| 133 |
* Runs on `init` at 20 — after the built-ins (5) and after |
| 134 |
* code-registered themes, which the documented recipe hooks at the |
| 135 |
* default 10. |
| 136 |
* |
| 137 |
* Every theme in the library contributes, not just the active one: |
| 138 |
* the whole point of a pick is that it is available whether or not |
| 139 |
* you are wearing the theme it came from. |
| 140 |
* |
| 141 |
* @return void |
| 142 |
*/ |
| 143 |
function openstation_register_desktop_theme_wallpapers() { |
| 144 |
$sources = array(); |
| 145 |
|
| 146 |
foreach ( openstation_desktop_theme_registry() as $slug => $entry ) { |
| 147 |
$sources[ $slug ] = array( $entry, '', '' ); |
| 148 |
} |
| 149 |
// Uploaded themes win on a slug collision, matching the payload |
| 150 |
// builder's precedence. |
| 151 |
foreach ( openstation_desktop_themes_index() as $slug => $entry ) { |
| 152 |
$installed_at = isset( $entry['installedAt'] ) ? (int) $entry['installedAt'] : 0; |
| 153 |
$sources[ $slug ] = array( |
| 154 |
$entry, |
| 155 |
openstation_desktop_themes_url( $slug ), |
| 156 |
$installed_at > 0 ? (string) $installed_at : '', |
| 157 |
); |
| 158 |
} |
| 159 |
|
| 160 |
foreach ( $sources as $slug => $source ) { |
| 161 |
list( $entry, $base_url, $version ) = $source; |
| 162 |
if ( ! is_array( $entry ) || empty( $entry['manifest'] ) || ! is_array( $entry['manifest'] ) ) { |
| 163 |
continue; |
| 164 |
} |
| 165 |
$manifest = $entry['manifest']; |
| 166 |
if ( empty( $manifest['wallpapers'] ) || ! is_array( $manifest['wallpapers'] ) ) { |
| 167 |
continue; |
| 168 |
} |
| 169 |
$name = isset( $manifest['name'] ) ? (string) $manifest['name'] : $slug; |
| 170 |
|
| 171 |
foreach ( $manifest['wallpapers'] as $wallpaper ) { |
| 172 |
$value = openstation_desktop_theme_wallpaper_css( $wallpaper, $base_url, $version ); |
| 173 |
if ( '' === $value ) { |
| 174 |
continue; |
| 175 |
} |
| 176 |
// `<theme-slug>/<wallpaper-id>` — the wallpaper id is |
| 177 |
// derived from something stable (see the sanitizer), so a |
| 178 |
// user's stored selection survives a re-upload. |
| 179 |
$id = OPENSTATION_DESKTOP_THEME_WALLPAPER_PREFIX . $slug . '/' . $wallpaper['id']; |
| 180 |
|
| 181 |
openstation_register_wallpaper( |
| 182 |
$id, |
| 183 |
array( |
| 184 |
'label' => openstation_desktop_theme_wallpaper_label( |
| 185 |
$name, |
| 186 |
$slug, |
| 187 |
isset( $wallpaper['label'] ) ? (string) $wallpaper['label'] : '' |
| 188 |
), |
| 189 |
// Swatch and surface are the same artwork. The swatch |
| 190 |
// is a small box, so the same value on both keeps the |
| 191 |
// preview an honest miniature of what selecting it |
| 192 |
// produces. |
| 193 |
'preview' => $value, |
| 194 |
'value' => $value, |
| 195 |
'type' => 'css', |
| 196 |
'description' => ! empty( $wallpaper['description'] ) |
| 197 |
? (string) $wallpaper['description'] |
| 198 |
: ( isset( $manifest['description'] ) ? (string) $manifest['description'] : '' ), |
| 199 |
) |
| 200 |
); |
| 201 |
} |
| 202 |
} |
| 203 |
} |
| 204 |
add_action( 'init', 'openstation_register_desktop_theme_wallpapers', 20 ); |
| 205 |
|