PluginProbe
OpenStation: Desktop Windows, Dock & Virtual Desktops for WP Admin / 1.1.10
OpenStation: Desktop Windows, Dock & Virtual Desktops for WP Admin v1.1.10
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
← All changes | includes/my-wordpress/media-usage.php +46 -77 0.9.31.1.10 View file →
@@ -1,7 +1,7 @@
1 1 <?php
2 2 /**
3 - * Desktop Mode — My WordPress: per-attachment "used in" endpoint.
3 + * OpenStation — My WordPress: per-attachment "used in" endpoint.
4 4 *
5 5 * `GET /desktop-mode/v1/media-usage/<id>` returns the list of public
6 6 * post-type entries that reference a given attachment, either as
7 7 * featured image (`_thumbnail_id` meta) or as an embed inside
@@ -27,10 +27,9 @@
27 27 * `read_post` gate runs on every request, so a cached scan can never
28 28 * leak rows across viewers with different capabilities. Cache is
29 29 * busted whenever any post is saved or deleted.
30 30 *
31 - * @package WPDesktopMode
32 - * @since 0.8.6
31 + * @package OpenStation
33 32 */
34 33
35 34 defined( 'ABSPATH' ) || exit;
36 35
@@ -35,18 +34,16 @@
35 34 defined( 'ABSPATH' ) || exit;
36 35
37 36 /**
38 37 * Register the route.
39 - *
40 - * @since 0.8.6
41 38 */
42 -function desktop_mode_my_wordpress_register_media_usage_route() {
39 +function openstation_my_wordpress_register_media_usage_route() {
43 40 register_rest_route(
44 41 'desktop-mode/v1',
45 42 '/media-usage/(?P<id>\d+)',
46 43 array(
47 44 'methods' => WP_REST_Server::READABLE,
48 - 'callback' => 'desktop_mode_my_wordpress_media_usage_callback',
45 + 'callback' => 'openstation_my_wordpress_media_usage_callback',
49 46 'permission_callback' => static function ( $request ) {
50 47 $id = (int) $request->get_param( 'id' );
51 48 if ( $id <= 0 ) {
52 49 return false;
@@ -66,9 +63,9 @@
66 63 ),
67 64 )
68 65 );
69 66 }
70 -add_action( 'rest_api_init', 'desktop_mode_my_wordpress_register_media_usage_route' );
67 +add_action( 'rest_api_init', 'openstation_my_wordpress_register_media_usage_route' );
71 68
72 69 /**
73 70 * Cache TTL (seconds). Filterable so sites that bulk-import media
74 71 * can shorten the window, or sites with stable libraries can
@@ -73,23 +70,19 @@
73 70 * Cache TTL (seconds). Filterable so sites that bulk-import media
74 71 * can shorten the window, or sites with stable libraries can
75 72 * lengthen it.
76 73 *
77 - * @since 0.8.6
78 - *
79 74 * @param int $attachment_id Attachment id.
80 75 * @return int
81 76 */
82 -function desktop_mode_my_wordpress_media_usage_ttl( $attachment_id ) {
77 +function openstation_my_wordpress_media_usage_ttl( $attachment_id ) {
83 78 /**
84 79 * Filter the media-usage transient TTL.
85 80 *
86 - * @since 0.8.6
87 - *
88 81 * @param int $seconds Default 300 (5 minutes).
89 82 * @param int $attachment_id Attachment id the cache key is for.
90 83 */
91 - return (int) apply_filters( 'desktop_mode_my_wordpress_media_usage_cache_ttl', 300, $attachment_id );
84 + return (int) apply_filters( 'openstation_my_wordpress_media_usage_cache_ttl', 300, $attachment_id );
92 85 }
93 86
94 87 /**
95 88 * Capability buckets the cache namespaces over. A second-tier
@@ -96,13 +89,11 @@
96 89 * change to the gating logic must update this list — the busters
97 90 * iterate over the same array, so the writer and the buster can
98 91 * never go out of sync.
99 92 *
100 - * @since 0.8.6
101 - *
102 93 * @return string[]
103 94 */
104 -function desktop_mode_my_wordpress_media_usage_cache_buckets() {
95 +function openstation_my_wordpress_media_usage_cache_buckets() {
105 96 return array( 'edit', 'read' );
106 97 }
107 98
108 99 /**
@@ -108,13 +99,11 @@
108 99 /**
109 100 * Bucket key for the current user — the writer's view of which
110 101 * cache slot to read/write.
111 102 *
112 - * @since 0.8.6
113 - *
114 103 * @return string
115 104 */
116 -function desktop_mode_my_wordpress_media_usage_current_bucket() {
105 +function openstation_my_wordpress_media_usage_current_bucket() {
117 106 return current_user_can( 'edit_others_posts' ) ? 'edit' : 'read';
118 107 }
119 108
120 109 /**
@@ -123,18 +112,16 @@
123 112 * viewer-independent reference map (per-row capability gating runs
124 113 * after the cache read), so the bucket is key hygiene rather than a
125 114 * security boundary.
126 115 *
127 - * @since 0.8.6
128 - *
129 116 * @param int $attachment_id Attachment id.
130 117 * @param string $bucket Optional bucket override. Defaults to
131 118 * the current user's bucket.
132 119 * @return string
133 120 */
134 -function desktop_mode_my_wordpress_media_usage_cache_key( $attachment_id, $bucket = null ) {
121 +function openstation_my_wordpress_media_usage_cache_key( $attachment_id, $bucket = null ) {
135 122 if ( null === $bucket ) {
136 - $bucket = desktop_mode_my_wordpress_media_usage_current_bucket();
123 + $bucket = openstation_my_wordpress_media_usage_current_bucket();
137 124 }
138 125 return 'dm_media_usage_' . (int) $attachment_id . '_' . $bucket . '_v1';
139 126 }
140 127
@@ -140,32 +127,30 @@
140 127
141 128 /**
142 129 * Endpoint callback. See file docblock for payload shape.
143 130 *
144 - * @since 0.8.6
145 - *
146 131 * @param WP_REST_Request $request REST request.
147 132 * @return array|WP_Error
148 133 */
149 -function desktop_mode_my_wordpress_media_usage_callback( $request ) {
134 +function openstation_my_wordpress_media_usage_callback( $request ) {
150 135 $attachment_id = (int) $request->get_param( 'id' );
151 136 $attachment = get_post( $attachment_id );
152 137 if ( ! $attachment || 'attachment' !== $attachment->post_type ) {
153 138 return new WP_Error(
154 - 'desktop_mode_media_not_found',
139 + 'openstation_media_not_found',
155 140 __( 'Attachment not found.', 'desktop-mode' ),
156 141 array( 'status' => 404 )
157 142 );
158 143 }
159 144
160 - $cache_key = desktop_mode_my_wordpress_media_usage_cache_key( $attachment_id );
145 + $cache_key = openstation_my_wordpress_media_usage_cache_key( $attachment_id );
161 146 $rows_by_post = get_transient( $cache_key );
162 147 if ( ! is_array( $rows_by_post ) ) {
163 - $rows_by_post = desktop_mode_my_wordpress_media_usage_collect( $attachment );
148 + $rows_by_post = openstation_my_wordpress_media_usage_collect( $attachment );
164 149 set_transient(
165 150 $cache_key,
166 151 $rows_by_post,
167 - desktop_mode_my_wordpress_media_usage_ttl( $attachment_id )
152 + openstation_my_wordpress_media_usage_ttl( $attachment_id )
168 153 );
169 154 }
170 155
171 156 /*
@@ -178,9 +163,9 @@
178 163 * heavy LIKE-scan portion stays cached. The base map only
179 164 * refreshes on the cache-bust events (save_post,
180 165 * before_delete_post, delete_attachment).
181 166 */
182 - $payload = desktop_mode_my_wordpress_media_usage_build( $attachment, $rows_by_post );
167 + $payload = openstation_my_wordpress_media_usage_build( $attachment, $rows_by_post );
183 168
184 169 /**
185 170 * Filter the media-usage payload before returning to the bundle.
186 171 * Plugins (ACF, page builders, Yoast image meta) can append rows
@@ -185,14 +170,12 @@
185 170 * Filter the media-usage payload before returning to the bundle.
186 171 * Plugins (ACF, page builders, Yoast image meta) can append rows
187 172 * to `usedIn` describing their own attachment references.
188 173 *
189 - * @since 0.8.6
190 - *
191 174 * @param array $payload Default payload.
192 175 * @param int $attachment_id Subject attachment id.
193 176 */
194 - return apply_filters( 'desktop_mode_my_wordpress_media_usage', $payload, $attachment_id );
177 + return apply_filters( 'openstation_my_wordpress_media_usage', $payload, $attachment_id );
195 178 }
196 179
197 180 /**
198 181 * Collect the viewer-independent reference map for an attachment:
@@ -198,18 +181,16 @@
198 181 * Collect the viewer-independent reference map for an attachment:
199 182 * post id => 'featured'|'content'. This is the heavy SQL portion of
200 183 * the payload and the ONLY part that gets transient-cached — the
201 184 * per-row `read_post` gate lives in
202 - * `desktop_mode_my_wordpress_media_usage_build()` and runs on every
185 + * `openstation_my_wordpress_media_usage_build()` and runs on every
203 186 * request, so a cached map can never leak rows across viewers with
204 187 * different capabilities.
205 188 *
206 - * @since 0.8.6
207 - *
208 189 * @param WP_Post $attachment Attachment post.
209 190 * @return array<int,string> Map of post id => usedAs kind.
210 191 */
211 -function desktop_mode_my_wordpress_media_usage_collect( $attachment ) {
192 +function openstation_my_wordpress_media_usage_collect( $attachment ) {
212 193 global $wpdb;
213 194
214 195 $attachment_id = (int) $attachment->ID;
215 196 $file_url = (string) wp_get_attachment_url( $attachment_id );
@@ -255,10 +236,10 @@
255 236 $basename_variants[] = $m[1] . $m[2];
256 237 }
257 238 $basename_variants = array_values( array_unique( $basename_variants ) );
258 239
259 - $class_pattern = '%wp-image-' . $attachment_id . '%';
260 - $url_patterns = array();
240 + $class_pattern = '%wp-image-' . $attachment_id . '%';
241 + $url_patterns = array();
261 242 foreach ( $basename_variants as $variant ) {
262 243 $url_patterns[] = '%' . $wpdb->esc_like( $variant ) . '%';
263 244 }
264 245
@@ -332,16 +313,14 @@
332 313 * it's collected fresh. Row building applies
333 314 * `current_user_can( 'read_post' )` per row on every call — never
334 315 * cache this function's output, it is viewer-specific.
335 316 *
336 - * @since 0.8.6
337 - *
338 317 * @param WP_Post $attachment Attachment post.
339 318 * @param array<int,string>|null $rows_by_post Optional precollected map of
340 319 * post id => usedAs kind.
341 320 * @return array
342 321 */
343 -function desktop_mode_my_wordpress_media_usage_build( $attachment, $rows_by_post = null ) {
322 +function openstation_my_wordpress_media_usage_build( $attachment, $rows_by_post = null ) {
344 323 $attachment_id = (int) $attachment->ID;
345 324 $file_url = (string) wp_get_attachment_url( $attachment_id );
346 325 $file_basename = '' !== $file_url ? wp_basename( $file_url ) : '';
347 326
@@ -359,9 +338,9 @@
359 338 ),
360 339 );
361 340
362 341 if ( ! is_array( $rows_by_post ) ) {
363 - $rows_by_post = desktop_mode_my_wordpress_media_usage_collect( $attachment );
342 + $rows_by_post = openstation_my_wordpress_media_usage_collect( $attachment );
364 343 }
365 344
366 345 $public_types = array_values( get_post_types( array( 'public' => true ), 'names' ) );
367 346 // Filter out `attachment` from the search — attachments don't
@@ -426,13 +405,11 @@
426 405 * buster can union pre + post sets — otherwise removing a
427 406 * `wp-image-N` block from a post would leave the cache for
428 407 * attachment N stale until the TTL expires.
429 408 *
430 - * @since 0.8.6
431 - *
432 409 * @var array<int,array<int,true>>
433 410 */
434 -$GLOBALS['desktop_mode_media_usage_pre_save_refs'] = array();
411 +$GLOBALS['openstation_media_usage_pre_save_refs'] = array();
435 412
436 413 /**
437 414 * Extract attachment ids referenced by a post — featured image plus
438 415 * everything resolvable from `post_content`. Defers to the canonical
@@ -439,26 +416,24 @@
439 416 * resolver in `attached-media.php` so this buster catches the same
440 417 * cases the REST field does (block-class scan, classic `[caption]`
441 418 * shortcodes, `data-id` / `data-attachment-id`, and raw `<img src>`
442 419 * URL resolution including `-scaled.jpg` ↔ original swaps), plus
443 - * any ids appended via the `desktop_mode_my_wordpress_attached_media`
420 + * any ids appended via the `openstation_my_wordpress_attached_media`
444 421 * filter (ACF, page builders, post-meta galleries). Without this
445 422 * delegation, editing a post to add or remove a raw URL embed
446 423 * wouldn't bust the affected attachment's media-usage cache until
447 424 * the TTL expired.
448 425 *
449 - * @since 0.8.6
450 - *
451 426 * @param int|WP_Post $post Post id or object.
452 427 * @return array<int,true> Set of attachment ids keyed for dedup.
453 428 */
454 -function desktop_mode_my_wordpress_media_usage_extract_refs( $post ) {
429 +function openstation_my_wordpress_media_usage_extract_refs( $post ) {
455 430 $ids = array();
456 431 $obj = is_object( $post ) ? $post : get_post( (int) $post );
457 432 if ( ! $obj || ! isset( $obj->ID ) ) {
458 433 return $ids;
459 434 }
460 - if ( ! function_exists( 'desktop_mode_my_wordpress_post_attached_media' ) ) {
435 + if ( ! function_exists( 'openstation_my_wordpress_post_attached_media' ) ) {
461 436 // Defensive: bootstrap order should always load
462 437 // attached-media.php before this can be called from a save
463 438 // hook, but fall back to the legacy minimal scan just in
464 439 // case so the buster never silently no-ops.
@@ -473,9 +448,9 @@
473 448 }
474 449 }
475 450 return $ids;
476 451 }
477 - foreach ( desktop_mode_my_wordpress_post_attached_media( (int) $obj->ID ) as $id ) {
452 + foreach ( openstation_my_wordpress_post_attached_media( (int) $obj->ID ) as $id ) {
478 453 $id = (int) $id;
479 454 if ( $id > 0 ) {
480 455 $ids[ $id ] = true;
481 456 }
@@ -488,21 +463,19 @@
488 463 * Fired by `pre_post_update`, which runs before the DB row mutates,
489 464 * so `get_post` here returns the OLD content. We stash the ref set
490 465 * in a per-request global and read it back in the `save_post` hook.
491 466 *
492 - * @since 0.8.6
493 - *
494 467 * @param int $post_id Post id about to be updated.
495 468 */
496 -function desktop_mode_my_wordpress_media_usage_snapshot_pre_save( $post_id ) {
469 +function openstation_my_wordpress_media_usage_snapshot_pre_save( $post_id ) {
497 470 $post_id = (int) $post_id;
498 471 if ( $post_id <= 0 ) {
499 472 return;
500 473 }
501 - $GLOBALS['desktop_mode_media_usage_pre_save_refs'][ $post_id ] =
502 - desktop_mode_my_wordpress_media_usage_extract_refs( $post_id );
474 + $GLOBALS['openstation_media_usage_pre_save_refs'][ $post_id ] =
475 + openstation_my_wordpress_media_usage_extract_refs( $post_id );
503 476 }
504 -add_action( 'pre_post_update', 'desktop_mode_my_wordpress_media_usage_snapshot_pre_save' );
477 +add_action( 'pre_post_update', 'openstation_my_wordpress_media_usage_snapshot_pre_save' );
505 478
506 479 /**
507 480 * Bust the transient when a post changes. The cache key is
508 481 * per-attachment, so we don't know which entries reference what —
@@ -516,34 +489,32 @@
516 489 *
517 490 * Bounded by the actual count of `wp-image-N` matches in either
518 491 * version of the content + the post's `_thumbnail_id`.
519 492 *
520 - * @since 0.8.6
521 - *
522 493 * @param int $post_id Post id that was just modified.
523 494 */
524 -function desktop_mode_my_wordpress_media_usage_bust_for_post( $post_id ) {
495 +function openstation_my_wordpress_media_usage_bust_for_post( $post_id ) {
525 496 $post_id = (int) $post_id;
526 497 if ( $post_id <= 0 ) {
527 498 return;
528 499 }
529 500
530 - $ids = desktop_mode_my_wordpress_media_usage_extract_refs( $post_id );
501 + $ids = openstation_my_wordpress_media_usage_extract_refs( $post_id );
531 502
532 - if ( isset( $GLOBALS['desktop_mode_media_usage_pre_save_refs'][ $post_id ] ) ) {
533 - $ids += $GLOBALS['desktop_mode_media_usage_pre_save_refs'][ $post_id ];
534 - unset( $GLOBALS['desktop_mode_media_usage_pre_save_refs'][ $post_id ] );
503 + if ( isset( $GLOBALS['openstation_media_usage_pre_save_refs'][ $post_id ] ) ) {
504 + $ids += $GLOBALS['openstation_media_usage_pre_save_refs'][ $post_id ];
505 + unset( $GLOBALS['openstation_media_usage_pre_save_refs'][ $post_id ] );
535 506 }
536 507
537 508 foreach ( array_keys( $ids ) as $attachment_id ) {
538 - foreach ( desktop_mode_my_wordpress_media_usage_cache_buckets() as $bucket ) {
509 + foreach ( openstation_my_wordpress_media_usage_cache_buckets() as $bucket ) {
539 510 delete_transient(
540 - desktop_mode_my_wordpress_media_usage_cache_key( (int) $attachment_id, $bucket )
511 + openstation_my_wordpress_media_usage_cache_key( (int) $attachment_id, $bucket )
541 512 );
542 513 }
543 514 }
544 515 }
545 -add_action( 'save_post', 'desktop_mode_my_wordpress_media_usage_bust_for_post' );
516 +add_action( 'save_post', 'openstation_my_wordpress_media_usage_bust_for_post' );
546 517 // `before_delete_post`, NOT `deleted_post`. By the time `deleted_post`
547 518 // fires, `delete_all_meta_for_post` has already wiped `_thumbnail_id`
548 519 // and the row itself is gone — `extract_refs()` would return an empty
549 520 // set, so the cache for any referenced attachment would survive until
@@ -549,9 +520,9 @@
549 520 // set, so the cache for any referenced attachment would survive until
550 521 // its 5-minute TTL. `before_delete_post` fires while the post + meta
551 522 // are still readable. Signature matches (we only consume the first
552 523 // arg, the post id).
553 -add_action( 'before_delete_post', 'desktop_mode_my_wordpress_media_usage_bust_for_post' );
524 +add_action( 'before_delete_post', 'openstation_my_wordpress_media_usage_bust_for_post' );
554 525 // New posts skip `pre_post_update` but still go through `save_post`,
555 526 // so the buster works as-is — the pre-snapshot is just empty.
556 527
557 528 /**
@@ -556,20 +527,18 @@
556 527
557 528 /**
558 529 * Bust the transient when the attachment itself is deleted.
559 530 *
560 - * @since 0.8.6
561 - *
562 531 * @param int $post_id Attachment id.
563 532 */
564 -function desktop_mode_my_wordpress_media_usage_bust_for_attachment( $post_id ) {
533 +function openstation_my_wordpress_media_usage_bust_for_attachment( $post_id ) {
565 534 $post_id = (int) $post_id;
566 535 if ( $post_id <= 0 ) {
567 536 return;
568 537 }
569 - foreach ( desktop_mode_my_wordpress_media_usage_cache_buckets() as $bucket ) {
538 + foreach ( openstation_my_wordpress_media_usage_cache_buckets() as $bucket ) {
570 539 delete_transient(
571 - desktop_mode_my_wordpress_media_usage_cache_key( $post_id, $bucket )
540 + openstation_my_wordpress_media_usage_cache_key( $post_id, $bucket )
572 541 );
573 542 }
574 543 }
575 -add_action( 'delete_attachment', 'desktop_mode_my_wordpress_media_usage_bust_for_attachment' );
544 +add_action( 'delete_attachment', 'openstation_my_wordpress_media_usage_bust_for_attachment' );