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
← All changes | lib/comment.php +486 -0 22.2.122.7.0 View file →
@@ -1,0 +1,486 @@
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 +}