PluginProbe
Stream – Activity Log & Audit Trail / 3.2.2
Stream – Activity Log & Audit Trail v3.2.2
4.4.0 4.3.0 4.2.2 4.2.1 trunk 2.0.1 2.0.2 2.0.3 2.0.4 2.0.5 3.0.0 3.0.1 3.0.2 3.0.3 3.0.4 3.0.5 3.0.6 3.0.7 3.1 3.1.1 3.10.0 3.2.0 3.2.1 3.2.2 3.2.3 All 50 releases
stream / connectors / class-connector-posts.php

class-connector-posts.php in Stream – Activity Log & Audit Trail 3.2.2, at connectors/class-connector-posts.php

397 lines 9.6 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 namespace WP_Stream;
3
4 class Connector_Posts extends Connector {
5 /**
6 * Connector slug
7 *
8 * @var string
9 */
10 public $name = 'posts';
11
12 /**
13 * Actions registered for this connector
14 *
15 * @var array
16 */
17 public $actions = array(
18 'transition_post_status',
19 'deleted_post',
20 );
21
22 /**
23 * Register connector in the WP Frontend
24 *
25 * @var bool
26 */
27 public $register_frontend = false;
28
29 /**
30 * Return translated connector label
31 *
32 * @return string Translated connector label
33 */
34 public function get_label() {
35 return esc_html__( 'Posts', 'stream' );
36 }
37
38 /**
39 * Return translated action labels
40 *
41 * @return array Action label translations
42 */
43 public function get_action_labels() {
44 return array(
45 'updated' => esc_html__( 'Updated', 'stream' ),
46 'created' => esc_html__( 'Created', 'stream' ),
47 'trashed' => esc_html__( 'Trashed', 'stream' ),
48 'untrashed' => esc_html__( 'Restored', 'stream' ),
49 'deleted' => esc_html__( 'Deleted', 'stream' ),
50 );
51 }
52
53 /**
54 * Return translated context labels
55 *
56 * @return array Context label translations
57 */
58 public function get_context_labels() {
59 global $wp_post_types;
60
61 $post_types = wp_filter_object_list( $wp_post_types, array(), null, 'label' );
62 $post_types = array_diff_key( $post_types, array_flip( $this->get_excluded_post_types() ) );
63
64 add_action( 'registered_post_type', array( $this, '_registered_post_type' ), 10, 2 );
65
66 return $post_types;
67 }
68
69 /**
70 * Add action links to Stream drop row in admin list screen
71 *
72 * @filter wp_stream_action_links_{connector}
73 *
74 * @param array $links Previous links registered
75 * @param Record $record Stream record
76 *
77 * @return array Action links
78 */
79 public function action_links( $links, $record ) {
80 $post = get_post( $record->object_id );
81
82 if ( $post && $post->post_status === $record->get_meta( 'new_status', true ) ) {
83 $post_type_name = $this->get_post_type_name( get_post_type( $post->ID ) );
84
85 if ( 'trash' === $post->post_status ) {
86 $untrash = wp_nonce_url(
87 add_query_arg(
88 array(
89 'action' => 'untrash',
90 'post' => $post->ID,
91 ),
92 admin_url( 'post.php' )
93 ),
94 sprintf( 'untrash-post_%d', $post->ID )
95 );
96
97 $delete = wp_nonce_url(
98 add_query_arg(
99 array(
100 'action' => 'delete',
101 'post' => $post->ID,
102 ),
103 admin_url( 'post.php' )
104 ),
105 sprintf( 'delete-post_%d', $post->ID )
106 );
107
108 $links[ sprintf( esc_html_x( 'Restore %s', 'Post type singular name', 'stream' ), $post_type_name ) ] = $untrash;
109 $links[ sprintf( esc_html_x( 'Delete %s Permenantly', 'Post type singular name', 'stream' ), $post_type_name ) ] = $delete;
110 } else {
111 $links[ sprintf( esc_html_x( 'Edit %s', 'Post type singular name', 'stream' ), $post_type_name ) ] = get_edit_post_link( $post->ID );
112
113 if ( $view_link = get_permalink( $post->ID ) ) {
114 $links[ esc_html__( 'View', 'stream' ) ] = $view_link;
115 }
116
117 $revision_id = absint( $record->get_meta( 'revision_id', true ) );
118 $revision_id = $this->get_adjacent_post_revision( $revision_id, false );
119
120 if ( $revision_id ) {
121 $links[ esc_html__( 'Revision', 'stream' ) ] = get_edit_post_link( $revision_id );
122 }
123 }
124 }
125
126 return $links;
127 }
128
129 /**
130 * Catch registeration of post_types after initial loading, to cache its labels
131 *
132 * @action registered_post_type
133 *
134 * @param string $post_type Post type slug
135 * @param array $args Arguments used to register the post type
136 */
137 public function _registered_post_type( $post_type, $args ) {
138 unset( $args );
139
140 $post_type_obj = get_post_type_object( $post_type );
141 $label = $post_type_obj->label;
142
143 wp_stream_get_instance()->connectors->term_labels['stream_context'][ $post_type ] = $label;
144 }
145
146 /**
147 * Log all post status changes ( creating / updating / trashing )
148 *
149 * @action transition_post_status
150 *
151 * @param mixed $new
152 * @param mixed $old
153 * @param \WP_Post $post
154 */
155 public function callback_transition_post_status( $new, $old, $post ) {
156 if ( in_array( $post->post_type, $this->get_excluded_post_types(), true ) ) {
157 return;
158 }
159
160 if ( in_array( $new, array( 'auto-draft', 'inherit' ), true ) ) {
161 return;
162 } elseif ( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE ) {
163 return;
164 } elseif ( 'draft' === $new && 'publish' === $old ) {
165 $summary = _x(
166 '"%1$s" %2$s unpublished',
167 '1: Post title, 2: Post type singular name',
168 'stream'
169 );
170 } elseif ( 'trash' === $old && 'trash' !== $new ) {
171 $summary = _x(
172 '"%1$s" %2$s restored from trash',
173 '1: Post title, 2: Post type singular name',
174 'stream'
175 );
176 $action = 'untrashed';
177 } elseif ( 'draft' === $new && 'draft' === $old ) {
178 $summary = _x(
179 '"%1$s" %2$s draft saved',
180 '1: Post title, 2: Post type singular name',
181 'stream'
182 );
183 } elseif ( 'publish' === $new && 'draft' === $old ) {
184 $summary = _x(
185 '"%1$s" %2$s published',
186 '1: Post title, 2: Post type singular name',
187 'stream'
188 );
189 } elseif ( 'draft' === $new ) {
190 $summary = _x(
191 '"%1$s" %2$s drafted',
192 '1: Post title, 2: Post type singular name',
193 'stream'
194 );
195 } elseif ( 'pending' === $new ) {
196 $summary = _x(
197 '"%1$s" %2$s pending review',
198 '1: Post title, 2: Post type singular name',
199 'stream'
200 );
201 } elseif ( 'future' === $new ) {
202 $summary = _x(
203 '"%1$s" %2$s scheduled for %3$s',
204 '1: Post title, 2: Post type singular name, 3: Scheduled post date',
205 'stream'
206 );
207 } elseif ( 'future' === $old && 'publish' === $new ) {
208 $summary = _x(
209 '"%1$s" scheduled %2$s published',
210 '1: Post title, 2: Post type singular name',
211 'stream'
212 );
213 } elseif ( 'private' === $new ) {
214 $summary = _x(
215 '"%1$s" %2$s privately published',
216 '1: Post title, 2: Post type singular name',
217 'stream'
218 );
219 } elseif ( 'trash' === $new ) {
220 $summary = _x(
221 '"%1$s" %2$s trashed',
222 '1: Post title, 2: Post type singular name',
223 'stream'
224 );
225 $action = 'trashed';
226 } else {
227 $summary = _x(
228 '"%1$s" %2$s updated',
229 '1: Post title, 2: Post type singular name',
230 'stream'
231 );
232 }
233
234 if ( 'auto-draft' === $old && 'auto-draft' !== $new ) {
235 $action = 'created';
236 }
237
238 if ( empty( $action ) ) {
239 $action = 'updated';
240 }
241
242 $revision_id = null;
243
244 if ( wp_revisions_enabled( $post ) ) {
245 $revision = get_children(
246 array(
247 'post_type' => 'revision',
248 'post_status' => 'inherit',
249 'post_parent' => $post->ID,
250 'posts_per_page' => 1, // VIP safe
251 'orderby' => 'post_date',
252 'order' => 'DESC',
253 )
254 );
255
256 if ( $revision ) {
257 $revision = array_values( $revision );
258 $revision_id = $revision[0]->ID;
259 }
260 }
261
262 $post_type_name = strtolower( $this->get_post_type_name( $post->post_type ) );
263
264 $this->log(
265 $summary,
266 array(
267 'post_title' => $post->post_title,
268 'singular_name' => $post_type_name,
269 'post_date' => $post->post_date,
270 'post_date_gmt' => $post->post_date_gmt,
271 'new_status' => $new,
272 'old_status' => $old,
273 'revision_id' => $revision_id,
274 ),
275 $post->ID,
276 $post->post_type,
277 $action
278 );
279 }
280
281 /**
282 * Log post deletion
283 *
284 * @action deleted_post
285 *
286 * $param integer $post_id
287 */
288 public function callback_deleted_post( $post_id ) {
289 $post = get_post( $post_id );
290
291 // We check if post is an instance of WP_Post as it doesn't always resolve in unit testing
292 if ( ! ( $post instanceof \WP_Post ) || in_array( $post->post_type, $this->get_excluded_post_types(), true ) ) {
293 return;
294 }
295
296 // Ignore auto-drafts that are deleted by the system, see issue-293
297 if ( 'auto-draft' === $post->post_status ) {
298 return;
299 }
300
301 $post_type_name = strtolower( $this->get_post_type_name( $post->post_type ) );
302
303 $this->log(
304 _x(
305 '"%1$s" %2$s deleted from trash',
306 '1: Post title, 2: Post type singular name',
307 'stream'
308 ),
309 array(
310 'post_title' => $post->post_title,
311 'singular_name' => $post_type_name,
312 ),
313 $post->ID,
314 $post->post_type,
315 'deleted'
316 );
317 }
318
319 /**
320 * Constructs list of excluded post types for the Posts connector
321 *
322 * @return array List of excluded post types
323 */
324 public function get_excluded_post_types() {
325 return apply_filters(
326 'wp_stream_posts_exclude_post_types',
327 array(
328 'nav_menu_item',
329 'attachment',
330 'revision',
331 )
332 );
333 }
334
335 /**
336 * Gets the singular post type label
337 *
338 * @param string $post_type_slug
339 *
340 * @return string Post type label
341 */
342 public function get_post_type_name( $post_type_slug ) {
343 $name = esc_html__( 'Post', 'stream' ); // Default
344
345 if ( post_type_exists( $post_type_slug ) ) {
346 $post_type = get_post_type_object( $post_type_slug );
347 $name = $post_type->labels->singular_name;
348 }
349
350 return $name;
351 }
352
353 /**
354 * Get an adjacent post revision ID
355 *
356 * @param int $revision_id
357 * @param bool $previous
358 *
359 * @return int $revision_id
360 */
361 public function get_adjacent_post_revision( $revision_id, $previous = true ) {
362 if ( empty( $revision_id ) || ! wp_is_post_revision( $revision_id ) ) {
363 return false;
364 }
365
366 $revision = wp_get_post_revision( $revision_id );
367 $operator = ( $previous ) ? '<' : '>';
368 $order = ( $previous ) ? 'DESC' : 'ASC';
369
370 global $wpdb;
371 // @codingStandardsIgnoreStart
372 $revision_id = $wpdb->get_var( // db call okay
373 $wpdb->prepare(
374 "SELECT p.ID
375 FROM $wpdb->posts AS p
376 WHERE p.post_date {$operator} %s
377 AND p.post_type = 'revision'
378 AND p.post_parent = %d
379 ORDER BY p.post_date {$order}
380 LIMIT 1",
381 $revision->post_date,
382 $revision->post_parent
383 )
384 );
385 // @codingStandardsIgnoreEnd
386 // prepare okay
387
388 $revision_id = absint( $revision_id );
389
390 if ( ! wp_is_post_revision( $revision_id ) ) {
391 return false;
392 }
393
394 return $revision_id;
395 }
396 }
397