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/recycle-bin/store.php +214 -203 0.8.81.1.10 View file →
@@ -1,7 +1,7 @@
1 1 <?php
2 2 /**
3 - * Desktop Mode — Recycle Bin: store.
3 + * OpenStation — Recycle Bin: store.
4 4 *
5 5 * Read/restore/purge primitives that the REST layer wraps. Backed
6 6 * entirely by core post-table state — no custom tables, no options
7 7 * blob. "Trashed" items are exactly the rows with
@@ -6,14 +6,13 @@
6 6 * entirely by core post-table state — no custom tables, no options
7 7 * blob. "Trashed" items are exactly the rows with
8 8 * `post_status = 'trash'` for the post types the bin tracks.
9 9 *
10 - * Every read goes through `desktop_mode_recycle_bin_query_args` so
10 + * Every read goes through `openstation_recycle_bin_query_args` so
11 11 * plugins can scope the bin (e.g. show only the current user's
12 12 * trash, or filter by author/role for compliance use cases).
13 13 *
14 - * @package WPDesktopMode
15 - * @since 0.19.0
14 + * @package OpenStation
16 15 */
17 16
18 17 defined( 'ABSPATH' ) || exit;
19 18
@@ -20,10 +19,8 @@
20 19 /**
21 20 * Returns the list of trashed items the current user is allowed to
22 21 * see, shaped for the table component.
23 22 *
24 - * @since 0.19.0
25 - *
26 23 * @param array $args {
27 24 * Optional. Query overrides.
28 25 *
29 26 * @type int $per_page Default 100.
@@ -35,9 +32,9 @@
35 32 * @type array $items List of items shaped for the JS layer.
36 33 * @type int $total Total matching rows (across pages).
37 34 * }
38 35 */
39 -function desktop_mode_recycle_bin_get_items( $args = array() ) {
36 +function openstation_recycle_bin_get_items( $args = array() ) {
40 37 $args = wp_parse_args(
41 38 $args,
42 39 array(
43 40 'per_page' => 100,
@@ -59,9 +56,9 @@
59 56
60 57 // Source gates: each `$type` filter narrows down to the
61 58 // owning store. `''` (All) loads every source. The files-on-
62 59 // desktop sources (`shortcut` / `placement` / `folder`) live in
63 - // `desktop_mode_files_list_trashed_for_recycle_bin` — never run
60 + // `openstation_files_list_trashed_for_recycle_bin` — never run
64 61 // the WP-core post / comment queries when one of those is the
65 62 // active filter, otherwise trashed posts leak into the
66 63 // "Shortcuts" / "Folders" tabs.
67 64 $files_types = array( 'desktop', 'placement', 'shortcut', 'folder' );
@@ -68,12 +65,12 @@
68 65 $is_files_filter = in_array( $type, $files_types, true );
69 66 $wants_post_types = '' === $type
70 67 || ( 'comment' !== $type && ! $is_files_filter );
71 68 $wants_comments = ( '' === $type || 'comment' === $type )
72 - && desktop_mode_recycle_bin_comments_enabled();
69 + && openstation_recycle_bin_comments_enabled();
73 70
74 71 if ( $wants_post_types ) {
75 - $post_types = desktop_mode_recycle_bin_capture_post_types();
72 + $post_types = openstation_recycle_bin_capture_post_types();
76 73 if ( '' !== $type && in_array( $type, $post_types, true ) ) {
77 74 $post_types = array( $type );
78 75 }
79 76
@@ -90,21 +87,19 @@
90 87
91 88 /**
92 89 * Filter the WP_Query args used to populate the recycle bin.
93 90 *
94 - * @since 0.19.0
95 - *
96 91 * @param array $query_args Args passed to WP_Query.
97 92 * @param array $args Caller-provided args.
98 93 */
99 - $query_args = apply_filters( 'desktop_mode_recycle_bin_query_args', $query_args, $args );
94 + $query_args = apply_filters( 'openstation_recycle_bin_query_args', $query_args, $args );
100 95
101 96 $query = new WP_Query( $query_args );
102 97 foreach ( $query->posts as $post ) {
103 - if ( ! desktop_mode_recycle_bin_user_can_view( $post ) ) {
98 + if ( ! openstation_recycle_bin_user_can_view( $post ) ) {
104 99 continue;
105 100 }
106 - $items_posts[] = desktop_mode_recycle_bin_shape_item( $post );
101 + $items_posts[] = openstation_recycle_bin_shape_item( $post );
107 102 }
108 103 }
109 104
110 105 if ( $wants_comments ) {
@@ -120,17 +115,15 @@
120 115
121 116 /**
122 117 * Filter the `WP_Comment_Query` args used to populate the
123 118 * recycle bin's comments. Mirror of
124 - * `desktop_mode_recycle_bin_query_args` for comments.
119 + * `openstation_recycle_bin_query_args` for comments.
125 120 *
126 - * @since 0.21.0
127 - *
128 121 * @param array $comment_args Args passed to `get_comments()`.
129 122 * @param array $args Caller-provided args.
130 123 */
131 124 $comment_args = apply_filters(
132 - 'desktop_mode_recycle_bin_comment_query_args',
125 + 'openstation_recycle_bin_comment_query_args',
133 126 $comment_args,
134 127 $args
135 128 );
136 129
@@ -136,12 +129,12 @@
136 129
137 130 $comments = get_comments( $comment_args );
138 131 if ( is_array( $comments ) ) {
139 132 foreach ( $comments as $comment ) {
140 - if ( ! desktop_mode_recycle_bin_user_can_view_comment( $comment ) ) {
133 + if ( ! openstation_recycle_bin_user_can_view_comment( $comment ) ) {
141 134 continue;
142 135 }
143 - $items_comments[] = desktop_mode_recycle_bin_shape_comment_item( $comment );
136 + $items_comments[] = openstation_recycle_bin_shape_comment_item( $comment );
144 137 }
145 138 }
146 139 }
147 140
@@ -148,9 +141,9 @@
148 141 // Files-on-the-Desktop trash — soft-trashed placements
149 142 // (shortcuts) and folders. Returned in the same item shape so
150 143 // the JS layer treats them uniformly. The `placement` and
151 144 // `folder` types route to the desktop-files trash module on
152 - // restore / purge (see `desktop_mode_recycle_bin_handle_files_*`).
145 + // restore / purge (see `openstation_recycle_bin_handle_files_*`).
153 146 $items_files = array();
154 147 // Map UI filter → set of `type` values to keep from the
155 148 // files-on-desktop helper. The "Shortcuts" segment in the bin
156 149 // UI now covers both registered icons (`shortcut`) AND user
@@ -174,11 +167,11 @@
174 167 break;
175 168 }
176 169 if (
177 170 ! empty( $wanted_files_types )
178 - && function_exists( 'desktop_mode_files_list_trashed_for_recycle_bin' )
171 + && function_exists( 'openstation_files_list_trashed_for_recycle_bin' )
179 172 ) {
180 - $file_items = desktop_mode_files_list_trashed_for_recycle_bin(
173 + $file_items = openstation_files_list_trashed_for_recycle_bin(
181 174 get_current_user_id()
182 175 );
183 176 foreach ( (array) $file_items as $item ) {
184 177 if ( ! in_array( (string) $item['type'], $wanted_files_types, true ) ) {
@@ -193,11 +186,14 @@
193 186 // Sort the merged list chronologically by deleted_at desc. The
194 187 // shape always carries a sortable string in `deleted_at`, so a
195 188 // straight string compare is enough (`Y-m-d H:i:s` is sortable
196 189 // lexicographically).
197 - usort( $items, static function ( $a, $b ) {
198 - return strcmp( (string) $b['deleted_at'], (string) $a['deleted_at'] );
199 - } );
190 + usort(
191 + $items,
192 + static function ( $a, $b ) {
193 + return strcmp( (string) $b['deleted_at'], (string) $a['deleted_at'] );
194 + }
195 + );
200 196
201 197 // `total` reports the GLOBAL trash count (every type, every
202 198 // row, ignoring the current filter / search). The dock-tile
203 199 // + desktop-icon badge consume this directly — `setRecycleBinBadge`
@@ -203,9 +199,9 @@
203 199 // + desktop-icon badge consume this directly — `setRecycleBinBadge`
204 200 // only cares about "how many things are sitting in the bin
205 201 // right now". A future paginated UI that needs a filtered
206 202 // count can compute it from `count( $items )` itself.
207 - $total = desktop_mode_recycle_bin_count();
203 + $total = openstation_recycle_bin_count();
208 204
209 205 $offset = max( 0, ( max( 1, (int) $args['page'] ) - 1 ) * $per_page );
210 206 $sliced = array_slice( $items, $offset, $per_page );
211 207
@@ -211,15 +207,13 @@
211 207
212 208 /**
213 209 * Filter the final list of items returned to the JS layer.
214 210 *
215 - * @since 0.19.0
216 - *
217 211 * @param array $items Shaped list (id, title, type, deleted_at, …).
218 212 * @param array|null $query Underlying post query, or null for the
219 - * merged post+comment shape (since 0.21.0).
213 + * merged post+comment shape.
220 214 */
221 - $sliced = apply_filters( 'desktop_mode_recycle_bin_items', $sliced, null );
215 + $sliced = apply_filters( 'openstation_recycle_bin_items', $sliced, null );
222 216
223 217 return array(
224 218 'items' => $sliced,
225 219 'total' => $total,
@@ -229,34 +223,76 @@
229 223 /**
230 224 * Total number of items in the recycle bin, summed across every
231 225 * tracked source (post types + comments).
232 226 *
233 - * Cheaper than `desktop_mode_recycle_bin_get_items()` because it never
227 + * Cheaper than `openstation_recycle_bin_get_items()` because it never
234 228 * loads the row data — just the COUNT(*) under the hood. Used by
235 229 * the badge on the dock tile + desktop icon, and by the REST
236 230 * `/count` endpoint subscribers refresh on broadcasts.
237 231 *
238 - * @since 0.21.0
232 + * The post component mirrors the per-item `edit_post` gate the list
233 + * applies, at the aggregate level: tracked types the user cannot edit
234 + * at all contribute zero, and types where the user can only edit their
235 + * own posts are counted author-scoped — so the badge never discloses
236 + * the global trash total to low-capability users.
239 237 *
240 238 * @return int
241 239 */
242 -function desktop_mode_recycle_bin_count() {
243 - $post_types = desktop_mode_recycle_bin_capture_post_types();
240 +function openstation_recycle_bin_count() {
241 + $post_types = openstation_recycle_bin_capture_post_types();
244 242
245 - $post_query = new WP_Query(
246 - array(
247 - 'post_type' => $post_types,
248 - 'post_status' => 'trash',
249 - 'posts_per_page' => 1,
250 - 'fields' => 'ids',
251 - 'no_found_rows' => false,
252 - 'suppress_filters' => false,
253 - )
254 - );
255 - $post_count = (int) $post_query->found_posts;
243 + // Bucket the tracked types by what the current user may edit:
244 + // full count when they hold the type's `edit_others_posts`,
245 + // author-scoped count when they only hold `edit_posts`, nothing
246 + // otherwise. At most two cheap COUNT(*) queries.
247 + $all_types = array();
248 + $own_types = array();
249 + foreach ( $post_types as $post_type ) {
250 + $post_type_obj = get_post_type_object( $post_type );
251 + if ( ! $post_type_obj ) {
252 + continue;
253 + }
254 + if ( ! current_user_can( $post_type_obj->cap->edit_posts ) ) {
255 + continue;
256 + }
257 + if ( current_user_can( $post_type_obj->cap->edit_others_posts ) ) {
258 + $all_types[] = $post_type;
259 + } else {
260 + $own_types[] = $post_type;
261 + }
262 + }
256 263
264 + $post_count = 0;
265 + if ( ! empty( $all_types ) ) {
266 + $post_query = new WP_Query(
267 + array(
268 + 'post_type' => $all_types,
269 + 'post_status' => 'trash',
270 + 'posts_per_page' => 1,
271 + 'fields' => 'ids',
272 + 'no_found_rows' => false,
273 + 'suppress_filters' => false,
274 + )
275 + );
276 + $post_count += (int) $post_query->found_posts;
277 + }
278 + if ( ! empty( $own_types ) ) {
279 + $own_query = new WP_Query(
280 + array(
281 + 'post_type' => $own_types,
282 + 'post_status' => 'trash',
283 + 'posts_per_page' => 1,
284 + 'fields' => 'ids',
285 + 'no_found_rows' => false,
286 + 'suppress_filters' => false,
287 + 'author' => get_current_user_id(),
288 + )
289 + );
290 + $post_count += (int) $own_query->found_posts;
291 + }
292 +
257 293 $comment_count = 0;
258 - if ( desktop_mode_recycle_bin_comments_enabled() ) {
294 + if ( openstation_recycle_bin_comments_enabled() ) {
259 295 $comment_count = (int) get_comments(
260 296 array(
261 297 'status' => 'trash',
262 298 'count' => true,
@@ -264,10 +300,10 @@
264 300 );
265 301 }
266 302
267 303 $files_count = 0;
268 - if ( function_exists( 'desktop_mode_files_count_trashed_for_recycle_bin' ) ) {
269 - $files_count = (int) desktop_mode_files_count_trashed_for_recycle_bin( get_current_user_id() );
304 + if ( function_exists( 'openstation_files_count_trashed_for_recycle_bin' ) ) {
305 + $files_count = (int) openstation_files_count_trashed_for_recycle_bin( get_current_user_id() );
270 306 }
271 307
272 308 $total = $post_count + $comment_count + $files_count;
273 309
@@ -273,16 +309,15 @@
273 309
274 310 /**
275 311 * Filter the total count surfaced to the badge.
276 312 *
277 - * @since 0.21.0
278 - *
279 313 * @param int $total Default sum (posts + comments + files visible to the user).
280 - * @param int $post_count Items in trash from the post-type query.
314 + * @param int $post_count Items in trash from the post-type query, capability-scoped
315 + * to what the current user can edit.
281 316 * @param int $comment_count Items in trash from the comment query.
282 - * @param int $files_count Items in trash from the desktop-files trash (since 0.8.0).
317 + * @param int $files_count Items in trash from the desktop-files trash.
283 318 */
284 - return (int) apply_filters( 'desktop_mode_recycle_bin_count', $total, $post_count, $comment_count, $files_count );
319 + return (int) apply_filters( 'openstation_recycle_bin_count', $total, $post_count, $comment_count, $files_count );
285 320 }
286 321
287 322 /**
288 323 * Whether comments are part of the bin. Filterable so installs
@@ -288,23 +323,19 @@
288 323 * Whether comments are part of the bin. Filterable so installs
289 324 * that don't moderate comments at all (read-only blogs, headless
290 325 * setups) can hide the segment without touching the JS.
291 326 *
292 - * @since 0.21.0
293 - *
294 327 * @return bool
295 328 */
296 -function desktop_mode_recycle_bin_comments_enabled() {
329 +function openstation_recycle_bin_comments_enabled() {
297 330 $on = current_user_can( 'moderate_comments' );
298 331
299 332 /**
300 333 * Filter whether the recycle bin tracks comments.
301 334 *
302 - * @since 0.21.0
303 - *
304 335 * @param bool $on Default: current user has `moderate_comments`.
305 336 */
306 - return (bool) apply_filters( 'desktop_mode_recycle_bin_comments_enabled', $on );
337 + return (bool) apply_filters( 'openstation_recycle_bin_comments_enabled', $on );
307 338 }
308 339
309 340 /**
310 341 * Whether the current user can see a given trashed item.
@@ -312,70 +343,58 @@
312 343 * Mirrors `current_user_can( 'edit_post', $id )` for the consistent
313 344 * "if you can edit it, you can manage its trash" rule. Filterable for
314 345 * stricter / looser policies.
315 346 *
316 - * @since 0.19.0
317 - *
318 347 * @param WP_Post $post Trashed post.
319 348 * @return bool
320 349 */
321 -function desktop_mode_recycle_bin_user_can_view( $post ) {
350 +function openstation_recycle_bin_user_can_view( $post ) {
322 351 $can = current_user_can( 'edit_post', $post->ID );
323 352
324 353 /**
325 354 * Filter whether the current user can see a given trashed item.
326 355 *
327 - * @since 0.19.0
328 - *
329 356 * @param bool $can Default: edit_post capability check.
330 357 * @param WP_Post $post Trashed post.
331 358 */
332 - return (bool) apply_filters( 'desktop_mode_recycle_bin_user_can_view', $can, $post );
359 + return (bool) apply_filters( 'openstation_recycle_bin_user_can_view', $can, $post );
333 360 }
334 361
335 362 /**
336 363 * Whether the current user can restore a given trashed item.
337 364 *
338 - * @since 0.19.0
339 - *
340 365 * @param WP_Post $post Trashed post.
341 366 * @return bool
342 367 */
343 -function desktop_mode_recycle_bin_user_can_restore( $post ) {
368 +function openstation_recycle_bin_user_can_restore( $post ) {
344 369 $can = current_user_can( 'delete_post', $post->ID );
345 370
346 371 /**
347 372 * Filter whether the current user can restore a given trashed item.
348 373 *
349 - * @since 0.19.0
350 - *
351 374 * @param bool $can Default: delete_post capability check (the same
352 375 * gate WP itself uses for trash/untrash).
353 376 * @param WP_Post $post Trashed post.
354 377 */
355 - return (bool) apply_filters( 'desktop_mode_recycle_bin_user_can_restore', $can, $post );
378 + return (bool) apply_filters( 'openstation_recycle_bin_user_can_restore', $can, $post );
356 379 }
357 380
358 381 /**
359 382 * Whether the current user can permanently delete a trashed item.
360 383 *
361 - * @since 0.19.0
362 - *
363 384 * @param WP_Post $post Trashed post.
364 385 * @return bool
365 386 */
366 -function desktop_mode_recycle_bin_user_can_purge( $post ) {
387 +function openstation_recycle_bin_user_can_purge( $post ) {
367 388 $can = current_user_can( 'delete_post', $post->ID );
368 389
369 390 /**
370 391 * Filter whether the current user can permanently delete a trashed item.
371 392 *
372 - * @since 0.19.0
373 - *
374 393 * @param bool $can Default: delete_post capability check.
375 394 * @param WP_Post $post Trashed post.
376 395 */
377 - return (bool) apply_filters( 'desktop_mode_recycle_bin_user_can_purge', $can, $post );
396 + return (bool) apply_filters( 'openstation_recycle_bin_user_can_purge', $can, $post );
378 397 }
379 398
380 399 /**
381 400 * Capability gates for trashed comments. Mirror of the post gates,
@@ -380,56 +399,47 @@
380 399 /**
381 400 * Capability gates for trashed comments. Mirror of the post gates,
382 401 * with `edit_comment`/`moderate_comments` as the WP-native checks.
383 402 *
384 - * @since 0.21.0
385 - *
386 403 * @param WP_Comment $comment Trashed comment.
387 404 * @return bool
388 405 */
389 -function desktop_mode_recycle_bin_user_can_view_comment( $comment ) {
406 +function openstation_recycle_bin_user_can_view_comment( $comment ) {
390 407 $can = current_user_can( 'edit_comment', $comment->comment_ID );
391 408
392 409 /**
393 - * @since 0.21.0
394 410 * @param bool $can Default: edit_comment capability check.
395 411 * @param WP_Comment $comment Trashed comment.
396 412 */
397 - return (bool) apply_filters( 'desktop_mode_recycle_bin_user_can_view_comment', $can, $comment );
413 + return (bool) apply_filters( 'openstation_recycle_bin_user_can_view_comment', $can, $comment );
398 414 }
399 415
400 416 /**
401 - * @since 0.21.0
402 - *
403 417 * @param WP_Comment $comment Trashed comment.
404 418 * @return bool
405 419 */
406 -function desktop_mode_recycle_bin_user_can_restore_comment( $comment ) {
420 +function openstation_recycle_bin_user_can_restore_comment( $comment ) {
407 421 $can = current_user_can( 'edit_comment', $comment->comment_ID );
408 422
409 423 /**
410 - * @since 0.21.0
411 424 * @param bool $can Default: edit_comment capability check.
412 425 * @param WP_Comment $comment Trashed comment.
413 426 */
414 - return (bool) apply_filters( 'desktop_mode_recycle_bin_user_can_restore_comment', $can, $comment );
427 + return (bool) apply_filters( 'openstation_recycle_bin_user_can_restore_comment', $can, $comment );
415 428 }
416 429
417 430 /**
418 - * @since 0.21.0
419 - *
420 431 * @param WP_Comment $comment Trashed comment.
421 432 * @return bool
422 433 */
423 -function desktop_mode_recycle_bin_user_can_purge_comment( $comment ) {
434 +function openstation_recycle_bin_user_can_purge_comment( $comment ) {
424 435 $can = current_user_can( 'edit_comment', $comment->comment_ID );
425 436
426 437 /**
427 - * @since 0.21.0
428 438 * @param bool $can Default: edit_comment capability check.
429 439 * @param WP_Comment $comment Trashed comment.
430 440 */
431 - return (bool) apply_filters( 'desktop_mode_recycle_bin_user_can_purge_comment', $can, $comment );
441 + return (bool) apply_filters( 'openstation_recycle_bin_user_can_purge_comment', $can, $comment );
432 442 }
433 443
434 444 /**
435 445 * Shape a `WP_Comment` into the JSON the JS table consumes.
@@ -438,14 +448,12 @@
438 448 * have to special-case the row by `type`. The `title` reads as
439 449 * "<author> on <post title>"; the `subtitle` carries a 100-char
440 450 * excerpt of `comment_content`.
441 451 *
442 - * @since 0.21.0
443 - *
444 452 * @param WP_Comment $comment Trashed comment.
445 453 * @return array
446 454 */
447 -function desktop_mode_recycle_bin_shape_comment_item( $comment ) {
455 +function openstation_recycle_bin_shape_comment_item( $comment ) {
448 456 $user_id = (int) get_comment_meta( $comment->comment_ID, '_desktop_mode_trash_user_id', true );
449 457 $deleted_at = (string) get_comment_meta( $comment->comment_ID, '_desktop_mode_trash_time_gmt', true );
450 458
451 459 if ( '' === $deleted_at ) {
@@ -452,9 +460,9 @@
452 460 $deleted_at = (string) $comment->comment_date_gmt;
453 461 }
454 462
455 463 $parent = $comment->comment_post_ID ? get_post( (int) $comment->comment_post_ID ) : null;
456 - $parent_text = $parent ? get_the_title( $parent ) : '';
464 + $parent_text = $parent ? openstation_recycle_bin_plain_text( get_the_title( $parent ) ) : '';
457 465 $author = $comment->comment_author
458 466 ? (string) $comment->comment_author
459 467 : __( 'Anonymous', 'desktop-mode' );
460 468
@@ -466,9 +474,9 @@
466 474 $parent_text
467 475 )
468 476 : $author;
469 477
470 - $subtitle = wp_trim_words( wp_strip_all_tags( (string) $comment->comment_content ), 18, '…' );
478 + $subtitle = wp_trim_words( openstation_recycle_bin_plain_text( (string) $comment->comment_content ), 18, '…' );
471 479
472 480 $user = $user_id ? get_userdata( $user_id ) : false;
473 481 $user_name = $user ? $user->display_name : '';
474 482
@@ -483,10 +491,10 @@
483 491 'icon' => 'dashicons-admin-comments',
484 492 'deleted_at' => $deleted_at,
485 493 'deleted_by' => $user_name,
486 494 'deleted_by_id' => $user_id,
487 - 'can_restore' => desktop_mode_recycle_bin_user_can_restore_comment( $comment ),
488 - 'can_purge' => desktop_mode_recycle_bin_user_can_purge_comment( $comment ),
495 + 'can_restore' => openstation_recycle_bin_user_can_restore_comment( $comment ),
496 + 'can_purge' => openstation_recycle_bin_user_can_purge_comment( $comment ),
489 497 'edit_link' => (string) get_edit_comment_link( $comment->comment_ID ),
490 498 );
491 499
492 500 /**
@@ -491,25 +499,42 @@
491 499
492 500 /**
493 501 * Filter the comment item shape.
494 502 *
495 - * @since 0.21.0
496 - *
497 503 * @param array $item Item shape.
498 504 * @param WP_Comment $comment Source comment.
499 505 */
500 - return (array) apply_filters( 'desktop_mode_recycle_bin_comment_item', $item, $comment );
506 + return (array) apply_filters( 'openstation_recycle_bin_comment_item', $item, $comment );
501 507 }
502 508
503 509 /**
510 + * Collapse a title/subtitle to plain text for the wire.
511 + *
512 + * `get_the_title()` runs the `the_title` filter chain, and
513 + * `wptexturize` in it encodes punctuation as numeric entities
514 + * (apostrophe → `&#8217;`, quotes, dashes) — correct for HTML
515 + * output, wrong for the bin table, which renders every cell via
516 + * `textContent` and would show the literal entity. Strip tags first,
517 + * then decode entities back to characters.
518 + *
519 + * @param string $text Raw filtered text.
520 + * @return string
521 + */
522 +function openstation_recycle_bin_plain_text( $text ) {
523 + return html_entity_decode(
524 + wp_strip_all_tags( (string) $text ),
525 + ENT_QUOTES,
526 + get_bloginfo( 'charset' )
527 + );
528 +}
529 +
530 +/**
504 531 * Shape one WP_Post into the JSON the JS table consumes.
505 532 *
506 - * @since 0.19.0
507 - *
508 533 * @param WP_Post $post Trashed post.
509 534 * @return array
510 535 */
511 -function desktop_mode_recycle_bin_shape_item( $post ) {
536 +function openstation_recycle_bin_shape_item( $post ) {
512 537 $user_id = (int) get_post_meta( $post->ID, '_desktop_mode_trash_user_id', true );
513 538 $deleted_at = (string) get_post_meta( $post->ID, '_desktop_mode_trash_time_gmt', true );
514 539
515 540 // Fall back to post_modified_gmt — set when wp_trash_post runs and
@@ -518,9 +543,9 @@
518 543 $deleted_at = (string) $post->post_modified_gmt;
519 544 }
520 545
521 546 $type = (string) $post->post_type;
522 - $title = (string) get_the_title( $post );
547 + $title = openstation_recycle_bin_plain_text( (string) get_the_title( $post ) );
523 548 $mime = (string) $post->post_mime_type;
524 549 $preview = '';
525 550 $icon = '';
526 551 $subtitle = '';
@@ -532,18 +557,33 @@
532 557 $thumb = wp_get_attachment_image_src( $post->ID, array( 64, 64 ), true );
533 558 if ( is_array( $thumb ) ) {
534 559 $preview = (string) $thumb[0];
535 560 }
536 - $icon = desktop_mode_recycle_bin_icon_for_mime( $mime );
561 + $icon = openstation_recycle_bin_icon_for_mime( $mime );
537 562 $subtitle = $mime;
538 563 } elseif ( 'post' === $type ) {
539 564 $icon = 'dashicons-admin-post';
540 - $subtitle = wp_trim_words( wp_strip_all_tags( (string) $post->post_excerpt ?: (string) $post->post_content ), 18, '…' );
565 + $excerpt = (string) $post->post_excerpt;
566 + $subtitle = wp_trim_words( openstation_recycle_bin_plain_text( $excerpt ? $excerpt : (string) $post->post_content ), 18, '…' );
541 567 } elseif ( 'page' === $type ) {
542 568 $icon = 'dashicons-admin-page';
543 - $subtitle = wp_trim_words( wp_strip_all_tags( (string) $post->post_content ), 18, '…' );
569 + $subtitle = wp_trim_words( openstation_recycle_bin_plain_text( (string) $post->post_content ), 18, '…' );
544 570 } else {
545 - $icon = 'dashicons-media-default';
571 + // Custom post types: reuse the type's own menu Dashicon when it
572 + // registered one, so a trashed product row reads as a product
573 + // instead of a generic file. Content excerpt as the subtitle,
574 + // same as posts.
575 + $icon = 'dashicons-media-default';
576 + $post_type_obj = get_post_type_object( $type );
577 + if (
578 + $post_type_obj
579 + && is_string( $post_type_obj->menu_icon )
580 + && str_starts_with( $post_type_obj->menu_icon, 'dashicons-' )
581 + ) {
582 + $icon = $post_type_obj->menu_icon;
583 + }
584 + $excerpt = (string) $post->post_excerpt;
585 + $subtitle = wp_trim_words( openstation_recycle_bin_plain_text( $excerpt ? $excerpt : (string) $post->post_content ), 18, '…' );
546 586 }
547 587
548 588 $user = $user_id ? get_userdata( $user_id ) : false;
549 589 $user_name = $user ? $user->display_name : '';
@@ -575,10 +615,10 @@
575 615 'icon' => $icon,
576 616 'deleted_at' => $deleted_at,
577 617 'deleted_by' => $user_name,
578 618 'deleted_by_id' => $user_id,
579 - 'can_restore' => desktop_mode_recycle_bin_user_can_restore( $post ),
580 - 'can_purge' => desktop_mode_recycle_bin_user_can_purge( $post ),
619 + 'can_restore' => openstation_recycle_bin_user_can_restore( $post ),
620 + 'can_purge' => openstation_recycle_bin_user_can_purge( $post ),
581 621 'edit_link' => (string) get_edit_post_link( $post->ID, 'raw' ),
582 622 );
583 623
584 624 /**
@@ -587,25 +627,21 @@
587 627 * Add custom columns or override the icon/preview for a custom
588 628 * post type. The id/type/deleted_at trio is load-bearing — keep
589 629 * them in the returned array.
590 630 *
591 - * @since 0.19.0
592 - *
593 631 * @param array $item Item shape.
594 632 * @param WP_Post $post Source post.
595 633 */
596 - return (array) apply_filters( 'desktop_mode_recycle_bin_item', $item, $post );
634 + return (array) apply_filters( 'openstation_recycle_bin_item', $item, $post );
597 635 }
598 636
599 637 /**
600 638 * Map a mime type to a Dashicon for the type cell.
601 639 *
602 - * @since 0.19.0
603 - *
604 640 * @param string $mime Mime type.
605 641 * @return string Dashicon class.
606 642 */
607 -function desktop_mode_recycle_bin_icon_for_mime( $mime ) {
643 +function openstation_recycle_bin_icon_for_mime( $mime ) {
608 644 if ( '' === $mime ) {
609 645 return 'dashicons-media-default';
610 646 }
611 647 if ( str_starts_with( $mime, 'image/' ) ) {
@@ -648,51 +684,46 @@
648 684 * everything else through `wp_untrash_post`. The legacy single-arg
649 685 * call (id only) defaults to `'post'` so older clients that haven't
650 686 * migrated to the typed API keep working.
651 687 *
652 - * @since 0.19.0
653 - * @since 0.21.0 Added `$type` parameter.
654 - *
655 688 * @param int $id Post id (or comment id when `$type === 'comment'`).
656 689 * @param string $type Entity type — '', 'post', 'page', 'attachment', or 'comment'.
657 690 * @return true|WP_Error
658 691 */
659 -function desktop_mode_recycle_bin_restore( $id, $type = '' ) {
692 +function openstation_recycle_bin_restore( $id, $type = '' ) {
660 693 $id = (int) $id;
661 694 if ( 'comment' === $type ) {
662 - return desktop_mode_recycle_bin_restore_comment( $id );
695 + return openstation_recycle_bin_restore_comment( $id );
663 696 }
664 - if ( ( 'placement' === $type || 'shortcut' === $type ) && function_exists( 'desktop_mode_files_restore_placement' ) ) {
665 - return desktop_mode_files_restore_placement( get_current_user_id(), $id );
697 + if ( ( 'placement' === $type || 'shortcut' === $type ) && function_exists( 'openstation_files_restore_placement' ) ) {
698 + return openstation_files_restore_placement( get_current_user_id(), $id );
666 699 }
667 - if ( 'folder' === $type && function_exists( 'desktop_mode_files_restore_folder' ) ) {
668 - return desktop_mode_files_restore_folder( get_current_user_id(), $id );
700 + if ( 'folder' === $type && function_exists( 'openstation_files_restore_folder' ) ) {
701 + return openstation_files_restore_folder( get_current_user_id(), $id );
669 702 }
670 703
671 704 $post = get_post( $id );
672 705 if ( ! $post ) {
673 - return new WP_Error( 'desktop_mode_recycle_bin_not_found', __( 'Item not found.', 'desktop-mode' ), array( 'status' => 404 ) );
706 + return new WP_Error( 'openstation_recycle_bin_not_found', __( 'Item not found.', 'desktop-mode' ), array( 'status' => 404 ) );
674 707 }
675 708 if ( 'trash' !== $post->post_status ) {
676 - return new WP_Error( 'desktop_mode_recycle_bin_not_trashed', __( 'Item is not in the trash.', 'desktop-mode' ), array( 'status' => 409 ) );
709 + return new WP_Error( 'openstation_recycle_bin_not_trashed', __( 'Item is not in the trash.', 'desktop-mode' ), array( 'status' => 409 ) );
677 710 }
678 - if ( ! desktop_mode_recycle_bin_user_can_restore( $post ) ) {
679 - return new WP_Error( 'desktop_mode_recycle_bin_forbidden', __( 'You are not allowed to restore this item.', 'desktop-mode' ), array( 'status' => 403 ) );
711 + if ( ! openstation_recycle_bin_user_can_restore( $post ) ) {
712 + return new WP_Error( 'openstation_recycle_bin_forbidden', __( 'You are not allowed to restore this item.', 'desktop-mode' ), array( 'status' => 403 ) );
680 713 }
681 714
682 715 /**
683 716 * Fires before a recycle-bin item is restored.
684 717 *
685 - * @since 0.19.0
686 - *
687 718 * @param int $id Post id about to be restored.
688 719 * @param WP_Post $post Trashed post object.
689 720 */
690 - do_action( 'desktop_mode_recycle_bin_before_restore', $id, $post );
721 + do_action( 'openstation_recycle_bin_before_restore', $id, $post );
691 722
692 723 $ok = wp_untrash_post( $id );
693 724 if ( ! $ok ) {
694 - return new WP_Error( 'desktop_mode_recycle_bin_restore_failed', __( 'Failed to restore item.', 'desktop-mode' ), array( 'status' => 500 ) );
725 + return new WP_Error( 'openstation_recycle_bin_restore_failed', __( 'Failed to restore item.', 'desktop-mode' ), array( 'status' => 500 ) );
695 726 }
696 727
697 728 delete_post_meta( $id, '_desktop_mode_trash_user_id' );
698 729 delete_post_meta( $id, '_desktop_mode_trash_time_gmt' );
@@ -699,13 +730,11 @@
699 730
700 731 /**
701 732 * Fires after a recycle-bin item is restored.
702 733 *
703 - * @since 0.19.0
704 - *
705 734 * @param int $id Post id that was restored.
706 735 */
707 - do_action( 'desktop_mode_recycle_bin_after_restore', $id );
736 + do_action( 'openstation_recycle_bin_after_restore', $id );
708 737
709 738 return true;
710 739 }
711 740
@@ -711,40 +740,36 @@
711 740
712 741 /**
713 742 * Restore a single trashed comment.
714 743 *
715 - * @since 0.21.0
716 - *
717 744 * @param int $comment_id Comment id.
718 745 * @return true|WP_Error
719 746 */
720 -function desktop_mode_recycle_bin_restore_comment( $comment_id ) {
747 +function openstation_recycle_bin_restore_comment( $comment_id ) {
721 748 $comment_id = (int) $comment_id;
722 749 $comment = get_comment( $comment_id );
723 750
724 751 if ( ! $comment ) {
725 - return new WP_Error( 'desktop_mode_recycle_bin_not_found', __( 'Comment not found.', 'desktop-mode' ), array( 'status' => 404 ) );
752 + return new WP_Error( 'openstation_recycle_bin_not_found', __( 'Comment not found.', 'desktop-mode' ), array( 'status' => 404 ) );
726 753 }
727 754 if ( 'trash' !== $comment->comment_approved ) {
728 - return new WP_Error( 'desktop_mode_recycle_bin_not_trashed', __( 'Comment is not in the trash.', 'desktop-mode' ), array( 'status' => 409 ) );
755 + return new WP_Error( 'openstation_recycle_bin_not_trashed', __( 'Comment is not in the trash.', 'desktop-mode' ), array( 'status' => 409 ) );
729 756 }
730 - if ( ! desktop_mode_recycle_bin_user_can_restore_comment( $comment ) ) {
731 - return new WP_Error( 'desktop_mode_recycle_bin_forbidden', __( 'You are not allowed to restore this comment.', 'desktop-mode' ), array( 'status' => 403 ) );
757 + if ( ! openstation_recycle_bin_user_can_restore_comment( $comment ) ) {
758 + return new WP_Error( 'openstation_recycle_bin_forbidden', __( 'You are not allowed to restore this comment.', 'desktop-mode' ), array( 'status' => 403 ) );
732 759 }
733 760
734 761 /**
735 762 * Fires before a comment is restored from the recycle bin.
736 763 *
737 - * @since 0.21.0
738 - *
739 764 * @param int $comment_id Comment id.
740 765 * @param WP_Comment $comment Trashed comment.
741 766 */
742 - do_action( 'desktop_mode_recycle_bin_before_restore_comment', $comment_id, $comment );
767 + do_action( 'openstation_recycle_bin_before_restore_comment', $comment_id, $comment );
743 768
744 769 $ok = wp_untrash_comment( $comment_id );
745 770 if ( ! $ok ) {
746 - return new WP_Error( 'desktop_mode_recycle_bin_restore_failed', __( 'Failed to restore comment.', 'desktop-mode' ), array( 'status' => 500 ) );
771 + return new WP_Error( 'openstation_recycle_bin_restore_failed', __( 'Failed to restore comment.', 'desktop-mode' ), array( 'status' => 500 ) );
747 772 }
748 773
749 774 delete_comment_meta( $comment_id, '_desktop_mode_trash_user_id' );
750 775 delete_comment_meta( $comment_id, '_desktop_mode_trash_time_gmt' );
@@ -751,13 +776,11 @@
751 776
752 777 /**
753 778 * Fires after a comment is restored from the recycle bin.
754 779 *
755 - * @since 0.21.0
756 - *
757 780 * @param int $comment_id Comment id.
758 781 */
759 - do_action( 'desktop_mode_recycle_bin_after_restore_comment', $comment_id );
782 + do_action( 'openstation_recycle_bin_after_restore_comment', $comment_id );
760 783
761 784 return true;
762 785 }
763 786
@@ -763,51 +786,48 @@
763 786
764 787 /**
765 788 * Permanently delete a single trashed item. Dispatches by `$type`.
766 789 *
767 - * @since 0.19.0
768 - * @since 0.21.0 Added `$type` parameter.
769 - *
770 790 * @param int $id Post id (or comment id when `$type === 'comment'`).
771 791 * @param string $type Entity type — '', 'post', 'page', 'attachment', or 'comment'.
772 792 * @return true|WP_Error
773 793 */
774 -function desktop_mode_recycle_bin_purge( $id, $type = '' ) {
794 +function openstation_recycle_bin_purge( $id, $type = '' ) {
775 795 $id = (int) $id;
776 796 if ( 'comment' === $type ) {
777 - return desktop_mode_recycle_bin_purge_comment( $id );
797 + return openstation_recycle_bin_purge_comment( $id );
778 798 }
779 - if ( ( 'placement' === $type || 'shortcut' === $type ) && function_exists( 'desktop_mode_files_purge_placement' ) ) {
780 - return desktop_mode_files_purge_placement( get_current_user_id(), $id );
799 + if ( ( 'placement' === $type || 'shortcut' === $type ) && function_exists( 'openstation_files_purge_placement' ) ) {
800 + return openstation_files_purge_placement( get_current_user_id(), $id );
781 801 }
782 - if ( 'folder' === $type && function_exists( 'desktop_mode_files_purge_folder' ) ) {
783 - return desktop_mode_files_purge_folder( get_current_user_id(), $id );
802 + if ( 'folder' === $type && function_exists( 'openstation_files_purge_folder' ) ) {
803 + return openstation_files_purge_folder( get_current_user_id(), $id );
784 804 }
785 805
786 806 $post = get_post( $id );
787 807 if ( ! $post ) {
788 - return new WP_Error( 'desktop_mode_recycle_bin_not_found', __( 'Item not found.', 'desktop-mode' ), array( 'status' => 404 ) );
808 + return new WP_Error( 'openstation_recycle_bin_not_found', __( 'Item not found.', 'desktop-mode' ), array( 'status' => 404 ) );
789 809 }
790 810 if ( 'trash' !== $post->post_status ) {
791 - return new WP_Error( 'desktop_mode_recycle_bin_not_trashed', __( 'Item is not in the trash.', 'desktop-mode' ), array( 'status' => 409 ) );
811 + return new WP_Error( 'openstation_recycle_bin_not_trashed', __( 'Item is not in the trash.', 'desktop-mode' ), array( 'status' => 409 ) );
792 812 }
793 - if ( ! desktop_mode_recycle_bin_user_can_purge( $post ) ) {
794 - return new WP_Error( 'desktop_mode_recycle_bin_forbidden', __( 'You are not allowed to permanently delete this item.', 'desktop-mode' ), array( 'status' => 403 ) );
813 + if ( ! openstation_recycle_bin_user_can_purge( $post ) ) {
814 + return new WP_Error( 'openstation_recycle_bin_forbidden', __( 'You are not allowed to permanently delete this item.', 'desktop-mode' ), array( 'status' => 403 ) );
795 815 }
796 816
797 817 /**
798 818 * Fires before a recycle-bin item is permanently deleted.
799 819 *
800 - * @since 0.19.0
801 - *
802 820 * @param int $id Post id about to be deleted.
803 821 * @param WP_Post $post Trashed post object.
804 822 */
805 - do_action( 'desktop_mode_recycle_bin_before_purge', $id, $post );
823 + do_action( 'openstation_recycle_bin_before_purge', $id, $post );
806 824
807 825 if ( 'attachment' === $post->post_type ) {
808 - // Force-delete bypasses our `pre_delete_attachment` interception
809 - // (which would loop us back into trash) and removes the file.
826 + // Force-delete (`true`) removes the attachment and its file
827 + // permanently. (The item is already trashed, so even with
828 + // MEDIA_TRASH enabled core would not re-route it to trash;
829 + // `true` simply makes the purge intent explicit.)
810 830 $result = wp_delete_attachment( $id, true );
811 831 } else {
812 832 $result = wp_delete_post( $id, true );
813 833 }
@@ -812,20 +832,18 @@
812 832 $result = wp_delete_post( $id, true );
813 833 }
814 834
815 835 if ( ! $result ) {
816 - return new WP_Error( 'desktop_mode_recycle_bin_purge_failed', __( 'Failed to permanently delete item.', 'desktop-mode' ), array( 'status' => 500 ) );
836 + return new WP_Error( 'openstation_recycle_bin_purge_failed', __( 'Failed to permanently delete item.', 'desktop-mode' ), array( 'status' => 500 ) );
817 837 }
818 838
819 839 /**
820 840 * Fires after a recycle-bin item is permanently deleted.
821 841 *
822 - * @since 0.19.0
823 - *
824 842 * @param int $id Post id that was purged.
825 843 * @param string $type Post type of the purged item.
826 844 */
827 - do_action( 'desktop_mode_recycle_bin_after_purge', $id, $post->post_type );
845 + do_action( 'openstation_recycle_bin_after_purge', $id, $post->post_type );
828 846
829 847 return true;
830 848 }
831 849
@@ -831,51 +849,45 @@
831 849
832 850 /**
833 851 * Permanently delete a single trashed comment.
834 852 *
835 - * @since 0.21.0
836 - *
837 853 * @param int $comment_id Comment id.
838 854 * @return true|WP_Error
839 855 */
840 -function desktop_mode_recycle_bin_purge_comment( $comment_id ) {
856 +function openstation_recycle_bin_purge_comment( $comment_id ) {
841 857 $comment_id = (int) $comment_id;
842 858 $comment = get_comment( $comment_id );
843 859
844 860 if ( ! $comment ) {
845 - return new WP_Error( 'desktop_mode_recycle_bin_not_found', __( 'Comment not found.', 'desktop-mode' ), array( 'status' => 404 ) );
861 + return new WP_Error( 'openstation_recycle_bin_not_found', __( 'Comment not found.', 'desktop-mode' ), array( 'status' => 404 ) );
846 862 }
847 863 if ( 'trash' !== $comment->comment_approved ) {
848 - return new WP_Error( 'desktop_mode_recycle_bin_not_trashed', __( 'Comment is not in the trash.', 'desktop-mode' ), array( 'status' => 409 ) );
864 + return new WP_Error( 'openstation_recycle_bin_not_trashed', __( 'Comment is not in the trash.', 'desktop-mode' ), array( 'status' => 409 ) );
849 865 }
850 - if ( ! desktop_mode_recycle_bin_user_can_purge_comment( $comment ) ) {
851 - return new WP_Error( 'desktop_mode_recycle_bin_forbidden', __( 'You are not allowed to permanently delete this comment.', 'desktop-mode' ), array( 'status' => 403 ) );
866 + if ( ! openstation_recycle_bin_user_can_purge_comment( $comment ) ) {
867 + return new WP_Error( 'openstation_recycle_bin_forbidden', __( 'You are not allowed to permanently delete this comment.', 'desktop-mode' ), array( 'status' => 403 ) );
852 868 }
853 869
854 870 /**
855 871 * Fires before a comment is permanently deleted via the bin.
856 872 *
857 - * @since 0.21.0
858 - *
859 873 * @param int $comment_id Comment id.
860 874 * @param WP_Comment $comment Trashed comment.
861 875 */
862 - do_action( 'desktop_mode_recycle_bin_before_purge_comment', $comment_id, $comment );
876 + do_action( 'openstation_recycle_bin_before_purge_comment', $comment_id, $comment );
863 877
864 878 $result = wp_delete_comment( $comment_id, true );
865 879
866 880 if ( ! $result ) {
867 - return new WP_Error( 'desktop_mode_recycle_bin_purge_failed', __( 'Failed to permanently delete comment.', 'desktop-mode' ), array( 'status' => 500 ) );
881 + return new WP_Error( 'openstation_recycle_bin_purge_failed', __( 'Failed to permanently delete comment.', 'desktop-mode' ), array( 'status' => 500 ) );
868 882 }
869 883
870 884 /**
871 885 * Fires after a comment is permanently deleted via the bin.
872 886 *
873 - * @since 0.21.0
874 - *
875 887 * @param int $comment_id Comment id.
876 888 */
877 - do_action( 'desktop_mode_recycle_bin_after_purge_comment', $comment_id );
889 + do_action( 'openstation_recycle_bin_after_purge_comment', $comment_id );
878 890
879 891 return true;
880 892 }
881 893
@@ -888,13 +900,11 @@
888 900 * Processes at most one chunk per call. The cap protects against PHP
889 901 * timeouts on large bins; the client iterates while `remaining > 0`
890 902 * (and bails when `remaining === skipped`, i.e. nothing the user can
891 903 * purge is left). Site owners with longer execution budgets can tune
892 - * the chunk size via the `desktop_mode_recycle_bin_empty_chunk_size`
904 + * the chunk size via the `openstation_recycle_bin_empty_chunk_size`
893 905 * filter.
894 906 *
895 - * @since 0.19.0
896 - *
897 907 * @return array {
898 908 * @type int $purged Items successfully purged in this call.
899 909 * @type int $skipped Items skipped (capability or error).
900 910 * @type int $remaining Items still in the bin after this call (across pages).
@@ -899,9 +909,9 @@
899 909 * @type int $skipped Items skipped (capability or error).
900 910 * @type int $remaining Items still in the bin after this call (across pages).
901 911 * }
902 912 */
903 -function desktop_mode_recycle_bin_empty() {
913 +function openstation_recycle_bin_empty() {
904 914 $purged = 0;
905 915 $skipped = 0;
906 916
907 917 /**
@@ -906,19 +916,17 @@
906 916
907 917 /**
908 918 * Filter the per-call chunk size for the empty-bin loop.
909 919 *
910 - * `desktop_mode_recycle_bin_empty()` only purges this many items
920 + * `openstation_recycle_bin_empty()` only purges this many items
911 921 * per invocation. The client iterates while `remaining > 0`. The
912 922 * default (200) is conservative for shared hosts; sites with
913 923 * generous PHP execution limits can raise it to make emptying a
914 924 * large bin take fewer roundtrips.
915 925 *
916 - * @since 0.21.1
917 - *
918 926 * @param int $chunk_size Items processed per call. Default 200.
919 927 */
920 - $chunk_size = (int) apply_filters( 'desktop_mode_recycle_bin_empty_chunk_size', 200 );
928 + $chunk_size = (int) apply_filters( 'openstation_recycle_bin_empty_chunk_size', 200 );
921 929 if ( $chunk_size < 1 ) {
922 930 $chunk_size = 1;
923 931 }
924 932
@@ -925,11 +933,16 @@
925 933 // Loop in chunks — `wp_delete_post()` is cheap individually but
926 934 // hammering it on a 10k-item bin without yielding back to PHP can
927 935 // still time out. The client re-invokes us until `remaining` hits
928 936 // zero (or stalls at `skipped`).
929 - $batch = desktop_mode_recycle_bin_get_items( array( 'per_page' => $chunk_size, 'page' => 1 ) );
937 + $batch = openstation_recycle_bin_get_items(
938 + array(
939 + 'per_page' => $chunk_size,
940 + 'page' => 1,
941 + )
942 + );
930 943 foreach ( $batch['items'] as $item ) {
931 - $result = desktop_mode_recycle_bin_purge(
944 + $result = openstation_recycle_bin_purge(
932 945 (int) $item['id'],
933 946 (string) ( $item['type'] ?? '' )
934 947 );
935 948 if ( is_wp_error( $result ) ) {
@@ -941,14 +954,12 @@
941 954
942 955 /**
943 956 * Fires after the recycle bin is emptied.
944 957 *
945 - * @since 0.19.0
946 - *
947 958 * @param int $purged Items successfully purged in this call.
948 959 * @param int $skipped Items skipped (capability or error).
949 960 */
950 - do_action( 'desktop_mode_recycle_bin_emptied', $purged, $skipped );
961 + do_action( 'openstation_recycle_bin_emptied', $purged, $skipped );
951 962
952 963 return array(
953 964 'purged' => $purged,
954 965 'skipped' => $skipped,