PluginProbe
OpenStation: Desktop Windows, Dock & Virtual Desktops for WP Admin / 0.9.6
OpenStation: Desktop Windows, Dock & Virtual Desktops for WP Admin v0.9.6
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 / recycle-bin / capture.php

capture.php in OpenStation: Desktop Windows, Dock & Virtual Desktops for WP Admin 0.9.6, at includes/recycle-bin/capture.php

171 lines 6.0 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Desktop Mode — Recycle Bin: capture.
4 *
5 * Stamps "who-deleted-what-when" metadata onto posts, pages, and
6 * comments as they pass through `wp_trash_post()` / `trashed_comment`,
7 * so the Recycle Bin window can show "deleted by Alice, 5 minutes ago"
8 * without a second roundtrip.
9 *
10 * Media attachments are NOT auto-routed through Trash — they follow
11 * vanilla WordPress behavior (permanent-delete on first click). To
12 * enable trash for media, define `MEDIA_TRASH` as `true` in
13 * `wp-config.php`; the Recycle Bin window will surface trashed
14 * attachments automatically because `attachment` is in the default
15 * `desktop_mode_recycle_bin_capture_post_types` list.
16 *
17 * - `desktop_mode_recycle_bin_capture_post_types` controls which post
18 * types we listen for in the first place.
19 * - The `desktop_mode_recycle_bin_item_captured` action fires after a
20 * successful capture so plugins can mirror the event (audit log,
21 * external storage, etc.).
22 *
23 * @package WPDesktopMode
24 * @since 0.6.0
25 */
26
27 defined( 'ABSPATH' ) || exit;
28
29 /**
30 * Default list of post types the recycle bin is willing to capture.
31 *
32 * Posts and pages already trash by default; the value of capturing them
33 * here is consistency: every "deleted" thing flows through the same
34 * filter pipeline, so a plugin that wants a single audit log can
35 * subscribe once.
36 *
37 * Custom post types with an admin UI (`show_ui`, non-builtin) are
38 * included by default since 0.9.6 — a trashed WooCommerce product or
39 * portfolio entry belongs in the site-wide bin just as much as a
40 * post does. Visibility stays safe because every row is still gated
41 * per-item on `edit_post` before it is listed. Headless CPTs
42 * (`show_ui => false`, e.g. the pinned-notes `wpd_note`) stay out
43 * unless their owning feature opts in via the filter.
44 *
45 * @since 0.6.0
46 * @since 0.9.6 Non-builtin `show_ui` post types are included by default.
47 *
48 * @return string[]
49 */
50 function desktop_mode_recycle_bin_capture_post_types() {
51 $types = array( 'post', 'page', 'attachment' );
52
53 $custom = get_post_types(
54 array(
55 'show_ui' => true,
56 '_builtin' => false,
57 ),
58 'names'
59 );
60 $types = array_merge( $types, array_values( (array) $custom ) );
61
62 /**
63 * Filter the post types the recycle bin tracks.
64 *
65 * Returning a list excluding `attachment` stops the bin from
66 * stamping and listing trashed attachments; it does not change how
67 * WordPress deletes media (that is governed by `MEDIA_TRASH`).
68 * Remove a custom post type here to keep its trash out of the bin,
69 * or add a headless (`show_ui => false`) type to opt it in.
70 *
71 * @since 0.6.0
72 *
73 * @param string[] $types Post types whose deletions the recycle bin tracks.
74 */
75 $types = apply_filters( 'desktop_mode_recycle_bin_capture_post_types', $types );
76
77 return array_values( array_unique( array_filter( array_map( 'strval', (array) $types ) ) ) );
78 }
79
80 /**
81 * Mirror the capture for posts/pages so the bin has a uniform record
82 * of "who deleted this and when."
83 *
84 * Core's `wp_trash_post_meta` is set on every trash but it doesn't
85 * include the user id — we stash that ourselves under a private meta
86 * key so the table can show "deleted by Alice".
87 *
88 * @since 0.6.0
89 *
90 * @param int $post_id Post being trashed.
91 */
92 function desktop_mode_recycle_bin_on_trash_post( $post_id ) {
93 $post = get_post( $post_id );
94 if ( ! $post ) {
95 return;
96 }
97 if ( ! in_array( $post->post_type, desktop_mode_recycle_bin_capture_post_types(), true ) ) {
98 return;
99 }
100 desktop_mode_recycle_bin_record_capture( $post_id );
101 }
102
103 /**
104 * Persist who-deleted-what-when metadata for a single item.
105 *
106 * Stored under `_desktop_mode_trash_*` postmeta on the trashed post itself —
107 * survives un-trash naturally because we only consult it while in the
108 * bin, and gets cleaned up by core when the post is permanently
109 * deleted via the standard postmeta cascade.
110 *
111 * @since 0.6.0
112 *
113 * @param int $post_id Post id being captured.
114 */
115 function desktop_mode_recycle_bin_record_capture( $post_id ) {
116 $user_id = get_current_user_id();
117 $now_gmt = current_time( 'mysql', true );
118
119 update_post_meta( $post_id, '_desktop_mode_trash_user_id', (int) $user_id );
120 update_post_meta( $post_id, '_desktop_mode_trash_time_gmt', $now_gmt );
121
122 /**
123 * Fires after the recycle bin records a capture.
124 *
125 * Use this to mirror the event into an external audit log or to
126 * extend the captured payload with custom postmeta.
127 *
128 * @since 0.6.0
129 *
130 * @param int $post_id Post id that was captured.
131 * @param int $user_id User id who triggered the capture.
132 * @param string $now_gmt MySQL-format GMT timestamp.
133 */
134 do_action( 'desktop_mode_recycle_bin_item_captured', $post_id, $user_id, $now_gmt );
135 }
136
137 add_action( 'wp_trash_post', 'desktop_mode_recycle_bin_on_trash_post', 10, 1 );
138
139 /**
140 * Capture deleted-by metadata for comments — symmetric to
141 * `desktop_mode_recycle_bin_record_capture` but writing to `commentmeta`
142 * instead of `postmeta`. Comments use `wp_set_comment_status('trash')`
143 * which fires `trashed_comment`; we don't need to short-circuit
144 * anything (core already routes to a real trash status), just
145 * stamp the moment so the bin can show "by Alice, 5 minutes ago".
146 *
147 * @since 0.6.0
148 *
149 * @param int $comment_id Comment about to be trashed.
150 */
151 function desktop_mode_recycle_bin_on_trash_comment( $comment_id ) {
152 $comment_id = (int) $comment_id;
153 $user_id = get_current_user_id();
154 $now_gmt = current_time( 'mysql', true );
155
156 update_comment_meta( $comment_id, '_desktop_mode_trash_user_id', $user_id );
157 update_comment_meta( $comment_id, '_desktop_mode_trash_time_gmt', $now_gmt );
158
159 /**
160 * Fires after the recycle bin records a comment capture.
161 *
162 * @since 0.6.0
163 *
164 * @param int $comment_id Comment id that was captured.
165 * @param int $user_id User id who triggered the capture.
166 * @param string $now_gmt MySQL-format GMT timestamp.
167 */
168 do_action( 'desktop_mode_recycle_bin_comment_captured', $comment_id, $user_id, $now_gmt );
169 }
170 add_action( 'trashed_comment', 'desktop_mode_recycle_bin_on_trash_comment', 10, 1 );
171