PluginProbe
WPSSO Core – Complete Schema Markup and Meta Tags / 22.7.0
WPSSO Core – Complete Schema Markup and Meta Tags v22.7.0
22.7.0 22.6.1 22.6.0 22.5.3 22.5.2 22.5.1 22.4.0 22.3.0 22.2.1 22.2.0 22.1.3 22.1.2 22.1.1 22.1.0 22.0.0 21.13.3 21.13.2 trunk 21.13.1
wpsso / lib / comment.php

comment.php in WPSSO Core – Complete Schema Markup and Meta Tags 22.7.0, at lib/comment.php

487 lines 12.4 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /*
3 * License: GPLv3
4 * License URI: https://www.gnu.org/licenses/gpl.txt
5 * Copyright 2012-2026 Jean-Sebastien Morisset (https://wpsso.com/)
6 */
7
8 if ( ! defined( 'ABSPATH' ) ) {
9
10 die( 'These aren\'t the droids you\'re looking for.' );
11 }
12
13 if ( ! defined( 'WPSSO_PLUGINDIR' ) ) {
14
15 die( 'Do. Or do not. There is no try.' );
16 }
17
18 if ( ! class_exists( 'WpssoAbstractWpMeta' ) ) {
19
20 require_once WPSSO_PLUGINDIR . 'lib/abstract/wp-meta.php';
21 }
22
23 if ( ! class_exists( 'WpssoComment' ) ) {
24
25 class WpssoComment extends WpssoAbstractWpMeta {
26
27 public function __construct( &$plugin ) {
28
29 $this->p =& $plugin;
30
31 if ( $this->p->debug->enabled ) {
32
33 $this->p->debug->mark();
34 }
35
36 /*
37 * This hook is fired once WordPress, plugins, and the theme are fully loaded and instantiated.
38 */
39 add_action( 'wp_loaded', array( $this, 'add_wp_callbacks' ) );
40 }
41
42 /*
43 * Add WordPress action and filter callbacks.
44 */
45 public function add_wp_callbacks() {
46
47 if ( $this->p->debug->enabled ) {
48
49 $this->p->debug->mark();
50 }
51
52 /*
53 * Since WPSSO Core v17.0.0.
54 *
55 * Register our comment meta.
56 */
57 $this->register_meta( $object_type = 'comment', WPSSO_META_NAME );
58
59 /*
60 * Called by wp_insert_comment(), which is called by wp_new_comment().
61 */
62 add_action( 'wp_insert_comment', array( $this, 'refresh_cache_insert_comment' ), PHP_INT_MAX, 2 );
63
64 /*
65 * Called by wp_transition_comment_status().
66 */
67 add_action( 'transition_comment_status', array( $this, 'refresh_cache_comment_status' ), PHP_INT_MAX, 3 );
68 }
69
70 /*
71 * Get the $mod object for a comment ID.
72 */
73 public function get_mod( $comment_id ) {
74
75 if ( $this->p->debug->enabled ) {
76
77 $this->p->debug->mark_caller();
78
79 $this->p->debug->log_args( array(
80 'comment_id' => $comment_id,
81 ) );
82 }
83
84 static $local_fifo = array();
85
86 /*
87 * Maybe return the array from the local cache.
88 */
89 if ( isset( $local_fifo[ $comment_id ] ) ) {
90
91 if ( ! $this->md_cache_disabled ) {
92
93 if ( $this->p->debug->enabled ) {
94
95 $this->p->debug->log( 'exiting early: comment id ' . $comment_id . ' mod array from local cache' );
96 }
97
98 return $local_fifo[ $comment_id ];
99
100 } else unset( $local_fifo[ $comment_id ] );
101 }
102
103 /*
104 * Maybe limit the number of array elements.
105 */
106 $local_fifo = SucomUtil::array_slice_fifo( $local_fifo, WPSSO_CACHE_ARRAY_FIFO_MAX );
107
108 $mod = self::get_mod_defaults();
109
110 /*
111 * Common elements.
112 */
113 $mod[ 'id' ] = is_numeric( $comment_id ) ? (int) $comment_id : 0; // Cast as integer.
114 $mod[ 'name' ] = 'comment';
115 $mod[ 'name_transl' ] = _x( 'comment', 'module name', 'wpsso' );
116 $mod[ 'obj' ] =& $this;
117
118 /*
119 * WpssoComment elements.
120 */
121 $mod[ 'is_comment' ] = true;
122
123 if ( $mod[ 'id' ] ) { // Just in case.
124
125 $mod[ 'wp_obj' ] = SucomUtilWP::get_comment_object( $mod[ 'id' ] );
126
127 if ( $mod[ 'wp_obj' ] instanceof WP_Comment ) { // Just in case.
128
129 $mod[ 'comment_author' ] = (int) $mod[ 'wp_obj' ]->user_id; // Comment author user ID.
130 $mod[ 'comment_author_name' ] = $mod[ 'wp_obj' ]->comment_author; // Comment author name.
131 $mod[ 'comment_author_url' ] = $mod[ 'wp_obj' ]->comment_author_url;
132 $mod[ 'comment_parent' ] = $mod[ 'wp_obj' ]->comment_parent;
133 $mod[ 'comment_time' ] = mysql2date( 'c', $mod[ 'wp_obj' ]->comment_date_gmt ); // ISO 8601 date.
134 $mod[ 'comment_timestamp' ] = mysql2date( 'U', $mod[ 'wp_obj' ]->comment_date_gmt ); // Unix timestamp.
135 $mod[ 'is_public' ] = $mod[ 'wp_obj' ]->comment_approved ? true : false;
136
137 $comment_rating = self::get_meta( $mod[ 'id' ], WPSSO_META_RATING_NAME, $single = true );
138
139 if ( is_numeric( $comment_rating ) ) {
140
141 $mod[ 'comment_rating' ] = $comment_rating;
142 }
143
144 } else $mod[ 'wp_obj' ] = false;
145 }
146
147 /*
148 * Filter the comment mod array.
149 */
150 $mod = apply_filters( 'wpsso_get_comment_mod', $mod, $comment_id );
151
152 if ( $this->p->debug->enabled ) {
153
154 $this->p->debug->log_arr( 'mod', $mod );
155 }
156
157 /*
158 * Maybe save the array to the local cache.
159 */
160 if ( ! $this->md_cache_disabled ) {
161
162 $local_fifo[ $comment_id ] = $mod;
163
164 if ( $this->p->debug->enabled ) {
165
166 $this->p->debug->log_size( 'local_fifo', $local_fifo );
167 }
168 }
169
170 return $mod;
171 }
172
173 public function get_mod_wp_object( array $mod ) {
174
175 if ( $mod[ 'wp_obj' ] instanceof WP_Comment ) {
176
177 return $mod[ 'wp_obj' ];
178 }
179
180 return SucomUtilWP::get_comment_object( $mod[ 'id' ] );
181 }
182
183 /*
184 * Option handling methods:
185 *
186 * get_defaults()
187 * get_options()
188 * save_options()
189 * delete_options()
190 */
191 public function get_options( $comment_id, $md_key = false, $filter_opts = true, $merge_defs = false ) {
192
193 if ( $this->p->debug->enabled ) {
194
195 $this->p->debug->mark_caller();
196
197 $this->p->debug->log_args( array(
198 'comment_id' => $comment_id,
199 'md_key' => $md_key,
200 'filter_opts' => $filter_opts,
201 'merge_defs' => $merge_defs,
202 ) );
203 }
204
205 static $local_fifo = array();
206
207 /*
208 * Use $comment_id and $filter_opts to create the cache ID string, but do not add $merge_defs.
209 */
210 $cache_id = SucomUtil::get_assoc_salt( array( 'id' => $comment_id, 'filter' => $filter_opts ) );
211
212 /*
213 * Maybe initialize a new local cache element. Use isset() instead of empty() to allow for an empty array.
214 */
215 if ( ! isset( $local_fifo[ $cache_id ] ) ) {
216
217 /*
218 * Maybe limit the number of array elements.
219 */
220 $local_fifo = SucomUtil::array_slice_fifo( $local_fifo, WPSSO_CACHE_ARRAY_FIFO_MAX );
221
222 $local_fifo[ $cache_id ] = null; // Create an element to reference.
223 }
224
225 $md_opts =& $local_fifo[ $cache_id ]; // Reference the local cache element.
226
227 if ( null === $md_opts ) { // Maybe read metadata into a new local cache element.
228
229 if ( $this->p->debug->enabled ) {
230
231 $this->p->debug->log( 'getting metadata for comment id ' . $comment_id );
232 }
233
234 $md_opts = self::get_meta( $comment_id, WPSSO_META_NAME, $single = true );
235
236 if ( ! is_array( $md_opts ) ) {
237
238 $md_opts = array(); // WPSSO_META_NAME not found.
239 }
240
241 unset( $md_opts[ 'opt_filtered' ] ); // Just in case.
242
243 /*
244 * Check if options need to be upgraded and saved.
245 */
246 if ( $this->p->opt->is_upgrade_required( $md_opts ) ) {
247
248 $md_opts = $this->upgrade_options( $md_opts, $comment_id );
249
250 self::update_meta( $comment_id, WPSSO_META_NAME, $md_opts );
251 }
252 }
253
254 if ( $filter_opts ) {
255
256 if ( ! empty( $md_opts[ 'opt_filtered' ] ) ) { // Set before calling filters to prevent recursion.
257
258 if ( $this->p->debug->enabled ) {
259
260 $this->p->debug->log( 'skipping filters: options already filtered' );
261 }
262
263 } else {
264
265 if ( $this->p->debug->enabled ) {
266
267 $this->p->debug->log( 'setting opt_filtered to 1' );
268 }
269
270 $md_opts[ 'opt_filtered' ] = 1; // Set before calling filters to prevent recursion.
271
272 if ( $this->p->debug->enabled ) {
273
274 $this->p->debug->log( 'required call to WpssoComment->get_mod() for comment ID ' . $comment_id );
275 }
276
277 $mod = $this->get_mod( $comment_id );
278
279 $filter_name = 'wpsso_get_md_options';
280
281 if ( $this->p->debug->enabled ) {
282
283 $this->p->debug->log( 'applying filters "' . $filter_name . '"' );
284 }
285
286 $md_opts = apply_filters( $filter_name, $md_opts, $mod );
287
288 /*
289 * Hooked by several integration modules to provide information about the current content.
290 * e-Commerce integration modules will provide information on their product (price,
291 * condition, etc.) and disable these options in the Document SSO metabox.
292 */
293 $filter_name = 'wpsso_get_' . $mod[ 'name' ] . '_options';
294
295 if ( $this->p->debug->enabled ) {
296
297 $this->p->debug->log( 'applying filters "' . $filter_name . '"' );
298 }
299
300 $md_opts = apply_filters( $filter_name, $md_opts, $comment_id, $mod );
301
302 $filter_name = 'wpsso_sanitize_md_options';
303
304 if ( $this->p->debug->enabled ) {
305
306 $this->p->debug->log( 'applying filters "' . $filter_name . '"' );
307 }
308
309 $md_opts = apply_filters( $filter_name, $md_opts, $mod );
310 }
311 }
312
313 /*
314 * Maybe save the array to the local cache.
315 */
316 if ( $this->md_cache_disabled ) {
317
318 $deref_md_opts = $local_fifo[ $cache_id ]; // Dereference.
319
320 unset( $local_fifo, $md_opts );
321
322 return $this->return_options( $comment_id, $deref_md_opts, $md_key, $merge_defs );
323 }
324
325 return $this->return_options( $comment_id, $md_opts, $md_key, $merge_defs );
326 }
327
328 /*
329 * Use $rel = false to extend WpssoAbstractWpMeta->save_options().
330 */
331 public function save_options( $comment_id, $rel = false ) {
332
333 if ( $this->p->debug->enabled ) {
334
335 $this->p->debug->log_args( array(
336 'comment_id' => $comment_id,
337 ) );
338 }
339
340 if ( empty( $comment_id ) ) { // Just in case.
341
342 if ( $this->p->debug->enabled ) {
343
344 $this->p->debug->log( 'exiting early: comment id is empty' );
345 }
346
347 return;
348
349 } elseif ( ! $this->verify_submit_nonce() ) {
350
351 if ( $this->p->debug->enabled ) {
352
353 $this->p->debug->log( 'exiting early: verify_submit_nonce failed' );
354 }
355
356 return;
357
358 /*
359 * Check user capability for the comment id.
360 */
361 } elseif ( ! $this->user_can_edit( $comment_id ) ) {
362
363 if ( $this->p->debug->enabled ) {
364
365 $user_id = get_current_user_id();
366
367 $this->p->debug->log( 'exiting early: user id ' . $user_id . ' cannot edit comment id ' . $comment_id );
368 }
369
370 return;
371 }
372
373 $this->md_cache_disable(); // Disable the local cache.
374
375 $mod = $this->get_mod( $comment_id );
376
377 $md_opts = $this->get_submit_opts( $mod ); // Merge previous + submitted options and then sanitize.
378
379 $this->md_cache_enable(); // Re-enable the local cache.
380
381 if ( false === $md_opts ) {
382
383 if ( $this->p->debug->enabled ) {
384
385 $this->p->debug->log( 'exiting early: returned submit options is false' );
386 }
387
388 return;
389 }
390
391 $md_opts = apply_filters( 'wpsso_save_md_options', $md_opts, $mod );
392
393 $md_opts = apply_filters( 'wpsso_save_' . $mod[ 'name' ] . '_options', $md_opts, $comment_id, $mod );
394
395 return self::update_meta( $comment_id, WPSSO_META_NAME, $md_opts );
396 }
397
398 /*
399 * Use $rel = false to extend WpssoAbstractWpMeta->delete_options().
400 */
401 public function delete_options( $comment_id, $rel = false ) {
402
403 return self::delete_meta( $comment_id, WPSSO_META_NAME );
404 }
405
406 public function refresh_cache_insert_comment( $comment_id, $comment ) {
407
408 if ( ! empty( $comment->comment_approved ) ) {
409
410 if ( ! empty( $comment->comment_post_ID ) ) {
411
412 $this->p->post->refresh_cache( $comment->comment_post_ID ); // Refresh the cache for a single post ID.
413 }
414 }
415 }
416
417 public function refresh_cache_comment_status( $new_status, $old_status, $comment ) {
418
419 if ( 'approved' === $new_status || 'approved' === $old_status ) {
420
421 if ( ! empty( $comment->comment_post_ID ) ) {
422
423 $this->p->post->refresh_cache( $comment->comment_post_ID ); // Refresh the cache for a single post ID.
424 }
425 }
426 }
427
428 /*
429 * Retrieves or updates the metadata cache by key and group.
430 */
431 public function get_update_meta_cache( $comment_id ) {
432
433 return SucomUtilWP::get_update_meta_cache( $comment_id, $meta_type = 'comment' );
434 }
435
436 /*
437 * Check user capability for the comment id.
438 *
439 * Use $rel = false to extend WpssoAbstractWpMeta->user_can_edit().
440 */
441 public function user_can_edit( $comment_id, $rel = false ) {
442
443 $capability = 'edit_comment';
444
445 if ( ! current_user_can( $capability, $comment_id ) ) {
446
447 if ( $this->p->debug->enabled ) {
448
449 $this->p->debug->log( 'exiting early: cannot ' . $capability . ' for comment id ' . $comment_id );
450 }
451
452 /*
453 * Add notice only if the admin notices have not already been shown.
454 */
455 if ( $this->p->notice->is_admin_pre_notices() ) {
456
457 $this->p->notice->err( sprintf( __( 'Insufficient privileges to edit comment ID %1$s.', 'wpsso' ), $comment_id ) );
458 }
459
460 return false;
461 }
462
463 return true;
464 }
465
466 /*
467 * If $meta_key is en empty string, retrieves all metadata for the specified object ID.
468 *
469 * See https://developer.wordpress.org/reference/functions/get_metadata/.
470 */
471 public static function get_meta( $comment_id, $meta_key = '', $single = false ) {
472
473 return get_metadata( 'comment', $comment_id, $meta_key, $single );
474 }
475
476 public static function update_meta( $comment_id, $meta_key, $value ) {
477
478 return update_metadata( 'comment', $comment_id, $meta_key, $value );
479 }
480
481 public static function delete_meta( $comment_id, $meta_key ) {
482
483 return delete_metadata( 'comment', $comment_id, $meta_key );
484 }
485 }
486 }
487