PluginProbe
OpenStation: Desktop Windows, Dock & Virtual Desktops for WP Admin / 1.1.5
OpenStation: Desktop Windows, Dock & Virtual Desktops for WP Admin v1.1.5
1.1.10 1.1.9 1.1.8 1.1.7 1.1.6 1.1.5 1.1.4 1.1.3 1.1.2 1.1.1 1.1.0 1.0.1 1.0.0 0.9.8 0.9.7 0.9.6 0.9.4 0.9.5 0.9.3 0.9.2 0.9.1 0.9.0 0.8.9 0.8.8 0.8.7 All 34 releases
desktop-mode / includes / desktop-files / registry.php

registry.php in OpenStation: Desktop Windows, Dock & Virtual Desktops for WP Admin 1.1.5, at includes/desktop-files/registry.php

253 lines 7.2 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * OpenStation — file-type registry.
4 *
5 * Maps a file-type slug (`'post'`, `'user'`, `'folder'`, …) to the
6 * `OpenStation_File` subclass that adapts the underlying entity.
7 * Plugins extend the file system by registering their own subclass
8 * via {@see openstation_register_file_type()}; the desktop UI then
9 * knows how to render and resolve their entities just like the
10 * built-in types.
11 *
12 * @package OpenStation
13 */
14
15 defined( 'ABSPATH' ) || exit;
16
17 /**
18 * Internal static-store registry. Mirrors the wallpaper / native-
19 * window pattern (see `openstation_desktop_wallpaper_registry()`).
20 *
21 * @internal
22 *
23 * @param string $type File-type slug ('' to fetch the full store).
24 * @param array|null $entry Entry to write, or null to read.
25 * @return array|null Full store when `$type` is empty; entry when
26 * looking one up; `null` when not found.
27 */
28 function openstation_file_type_registry( $type = '', $entry = null ) {
29 static $store = array();
30
31 if ( '' === (string) $type ) {
32 return $store;
33 }
34 if ( null !== $entry ) {
35 $store[ (string) $type ] = $entry;
36 }
37 return isset( $store[ (string) $type ] ) ? $store[ (string) $type ] : null;
38 }
39
40 /**
41 * Registers a desktop file type.
42 *
43 * @param string $type File-type slug, e.g. `'post'`, `'user'`,
44 * `'jorvy-quote'`. Must be non-empty and unique.
45 * @param array $args {
46 * @type string $label Required. Human label for picker UIs.
47 * @type string $class Required. Fully-qualified
48 * `OpenStation_File` subclass name.
49 * @type string $script Optional. Enqueued script handle for the
50 * plugin's JS-side definition. The shell
51 * dynamically loads the URL on activation
52 * so a plugin's file types appear without
53 * a shell reload.
54 * @type int $sort Sort order in picker UIs. Default 100.
55 * @type string[] $capabilities Gate: ALL caps must match.
56 * }
57 * @return true|WP_Error `true` on success, `WP_Error` otherwise.
58 */
59 function openstation_register_file_type( $type, $args = array() ) {
60 $type = (string) $type;
61 if ( '' === $type ) {
62 return openstation_registration_error(
63 'openstation_missing_id',
64 __( 'File-type slug is required.', 'desktop-mode' )
65 );
66 }
67
68 $defaults = array(
69 'label' => '',
70 'class' => '',
71 'script' => '',
72 'sort' => 100,
73 'capabilities' => array(),
74 );
75 $args = wp_parse_args( $args, $defaults );
76
77 foreach ( (array) $args['capabilities'] as $cap ) {
78 if ( ! current_user_can( (string) $cap ) ) {
79 return openstation_registration_error(
80 'openstation_capability_denied',
81 sprintf(
82 /* translators: %s: capability slug. */
83 __( 'Current user lacks the %s capability required to register this file type.', 'desktop-mode' ),
84 (string) $cap
85 ),
86 array(
87 'capability' => (string) $cap,
88 'type' => $type,
89 )
90 );
91 }
92 }
93
94 if ( '' === (string) $args['label'] ) {
95 return openstation_registration_error(
96 'openstation_missing_label',
97 __( 'File-type registration requires a non-empty `label`.', 'desktop-mode' ),
98 array( 'type' => $type )
99 );
100 }
101
102 $class = (string) $args['class'];
103 if ( '' === $class || ! class_exists( $class ) ) {
104 return openstation_registration_error(
105 'openstation_invalid_class',
106 __( 'File-type registration requires an existing `class`.', 'desktop-mode' ),
107 array(
108 'type' => $type,
109 'class' => $class,
110 )
111 );
112 }
113 if ( ! is_subclass_of( $class, 'OpenStation_File' ) ) {
114 return openstation_registration_error(
115 'openstation_invalid_class',
116 __( '`class` must extend `OpenStation_File`.', 'desktop-mode' ),
117 array(
118 'type' => $type,
119 'class' => $class,
120 )
121 );
122 }
123
124 $entry = array(
125 'type' => $type,
126 'label' => (string) $args['label'],
127 'class' => $class,
128 'script' => (string) $args['script'],
129 'sort' => (int) $args['sort'],
130 );
131 openstation_file_type_registry( $type, $entry );
132
133 /**
134 * Fires after a desktop file type is successfully registered.
135 * Does NOT fire on `WP_Error` returns.
136 *
137 * @param string $type Type slug.
138 * @param array $entry Stored registry entry.
139 */
140 do_action( 'openstation_file_type_registered', $type, $entry );
141
142 return true;
143 }
144
145 /**
146 * Looks up a registered file-type entry.
147 *
148 * @param string $type Type slug.
149 * @return array|null Registry entry, or `null` if unknown.
150 */
151 function openstation_get_file_type( $type ) {
152 $entry = openstation_file_type_registry( (string) $type );
153 return is_array( $entry ) ? $entry : null;
154 }
155
156 /**
157 * Returns every registered file type, sorted by `sort` then label.
158 *
159 * @return array[]
160 */
161 function openstation_get_file_types() {
162 $registry = openstation_file_type_registry();
163 if ( ! is_array( $registry ) || empty( $registry ) ) {
164 return array();
165 }
166
167 /**
168 * Filters the full file-type registry before consumers see it.
169 * Plugins can hide built-in types or swap a class out at runtime.
170 *
171 * @param array[] $registry Registered entries keyed by slug.
172 */
173 $registry = apply_filters( 'openstation_file_types', $registry );
174 if ( ! is_array( $registry ) ) {
175 return array();
176 }
177
178 $entries = array_values( $registry );
179 usort(
180 $entries,
181 static function ( $a, $b ) {
182 $sa = isset( $a['sort'] ) ? (int) $a['sort'] : 100;
183 $sb = isset( $b['sort'] ) ? (int) $b['sort'] : 100;
184 if ( $sa !== $sb ) {
185 return $sa - $sb;
186 }
187 $la = isset( $a['label'] ) ? (string) $a['label'] : '';
188 $lb = isset( $b['label'] ) ? (string) $b['label'] : '';
189 return strcmp( $la, $lb );
190 }
191 );
192 return $entries;
193 }
194
195 /**
196 * Resolves a `(type, ref)` tuple into a `OpenStation_File` instance,
197 * or `null` if the type is unknown.
198 *
199 * @param string $type File-type slug.
200 * @param string|int $ref Entity reference.
201 * @return OpenStation_File|null
202 */
203 function openstation_resolve_file( $type, $ref ) {
204 $entry = openstation_get_file_type( $type );
205 if ( null === $entry ) {
206 return null;
207 }
208 $class = $entry['class'];
209 if ( ! class_exists( $class ) ) {
210 return null;
211 }
212 return new $class( $ref );
213 }
214
215 /**
216 * Builds the file-types payload sent to the shell. Only metadata
217 * (id, label, sort) and the resolved script URL cross the wire —
218 * the PHP class never serializes; the JS side has its own mirror.
219 *
220 * @return array[]
221 */
222 function openstation_build_file_types_payload() {
223 $entries = openstation_get_file_types();
224 if ( empty( $entries ) ) {
225 return array();
226 }
227 $out = array();
228 foreach ( $entries as $entry ) {
229 $handle = isset( $entry['script'] ) ? (string) $entry['script'] : '';
230 $payload = '' !== $handle
231 ? openstation_resolve_script_payload( $handle )
232 : array(
233 'url' => '',
234 'before' => array(),
235 'after' => array(),
236 'l10n' => array(),
237 'translations' => '',
238 );
239 $out[] = array(
240 'id' => (string) $entry['type'],
241 'label' => (string) $entry['label'],
242 'sort' => (int) $entry['sort'],
243 'scriptUrl' => $payload['url'],
244 'scriptHandle' => $handle,
245 'scriptBefore' => $payload['before'],
246 'scriptAfter' => $payload['after'],
247 'scriptL10n' => $payload['l10n'],
248 'scriptTranslations' => $payload['translations'],
249 );
250 }
251 return $out;
252 }
253