Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.
Common duplication problems, and corresponding solutions are:
Complex classes like Replicastore often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes. You can also have a look at the cohesion graph to spot any un-connected, or weakly-connected components.
Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.
While breaking up the class, it is a good idea to analyze how other classes use Replicastore, and based on these observations, apply Extract Interface, too.
1 | <?php |
||
18 | class Replicastore implements Replicastore_Interface { |
||
19 | /** |
||
20 | * Empty and reset the replicastore. |
||
21 | * |
||
22 | * @access public |
||
23 | */ |
||
24 | public function reset() { |
||
25 | global $wpdb; |
||
26 | |||
27 | $wpdb->query( "DELETE FROM $wpdb->posts" ); |
||
28 | |||
29 | // Delete comments from cache. |
||
30 | $comment_ids = $wpdb->get_col( "SELECT comment_ID FROM $wpdb->comments" ); |
||
31 | if ( ! empty( $comment_ids ) ) { |
||
32 | clean_comment_cache( $comment_ids ); |
||
33 | } |
||
34 | $wpdb->query( "DELETE FROM $wpdb->comments" ); |
||
35 | |||
36 | // Also need to delete terms from cache. |
||
37 | $term_ids = $wpdb->get_col( "SELECT term_id FROM $wpdb->terms" ); |
||
38 | foreach ( $term_ids as $term_id ) { |
||
39 | wp_cache_delete( $term_id, 'terms' ); |
||
40 | } |
||
41 | |||
42 | $wpdb->query( "DELETE FROM $wpdb->terms" ); |
||
43 | |||
44 | $wpdb->query( "DELETE FROM $wpdb->term_taxonomy" ); |
||
45 | $wpdb->query( "DELETE FROM $wpdb->term_relationships" ); |
||
46 | |||
47 | // Callables and constants. |
||
48 | $wpdb->query( "DELETE FROM $wpdb->options WHERE option_name LIKE 'jetpack_%'" ); |
||
49 | $wpdb->query( "DELETE FROM $wpdb->postmeta WHERE meta_key NOT LIKE '\_%'" ); |
||
50 | } |
||
51 | |||
52 | /** |
||
53 | * Ran when full sync has just started. |
||
54 | * |
||
55 | * @access public |
||
56 | * |
||
57 | * @param array $config Full sync configuration for this sync module. |
||
58 | */ |
||
59 | public function full_sync_start( $config ) { // phpcs:ignore VariableAnalysis.CodeAnalysis.VariableAnalysis.UnusedVariable |
||
60 | $this->reset(); |
||
61 | } |
||
62 | |||
63 | /** |
||
64 | * Ran when full sync has just finished. |
||
65 | * |
||
66 | * @access public |
||
67 | * |
||
68 | * @param string $checksum Deprecated since 7.3.0. |
||
69 | */ |
||
70 | public function full_sync_end( $checksum ) { // phpcs:ignore VariableAnalysis.CodeAnalysis.VariableAnalysis.UnusedVariable |
||
71 | // Noop right now. |
||
72 | } |
||
73 | |||
74 | /** |
||
75 | * Retrieve the number of terms. |
||
76 | * |
||
77 | * @access public |
||
78 | * |
||
79 | * @return int Number of terms. |
||
80 | */ |
||
81 | public function term_count() { |
||
82 | global $wpdb; |
||
83 | return $wpdb->get_var( "SELECT COUNT(*) FROM $wpdb->terms" ); |
||
84 | } |
||
85 | |||
86 | /** |
||
87 | * Retrieve the number of rows in the `term_taxonomy` table. |
||
88 | * |
||
89 | * @access public |
||
90 | * |
||
91 | * @return int Number of terms. |
||
92 | */ |
||
93 | public function term_taxonomy_count() { |
||
94 | global $wpdb; |
||
95 | return $wpdb->get_var( "SELECT COUNT(*) FROM $wpdb->term_taxonomy" ); |
||
96 | } |
||
97 | |||
98 | /** |
||
99 | * Retrieve the number of term relationships. |
||
100 | * |
||
101 | * @access public |
||
102 | * |
||
103 | * @return int Number of rows in the term relationships table. |
||
104 | */ |
||
105 | public function term_relationship_count() { |
||
106 | global $wpdb; |
||
107 | return $wpdb->get_var( "SELECT COUNT(*) FROM $wpdb->term_relationships" ); |
||
108 | } |
||
109 | |||
110 | /** |
||
111 | * Retrieve the number of posts with a particular post status within a certain range. |
||
112 | * |
||
113 | * @access public |
||
114 | * |
||
115 | * @todo Prepare the SQL query before executing it. |
||
116 | * |
||
117 | * @param string $status Post status. |
||
|
|||
118 | * @param int $min_id Minimum post ID. |
||
119 | * @param int $max_id Maximum post ID. |
||
120 | * @return int Number of posts. |
||
121 | */ |
||
122 | View Code Duplication | public function post_count( $status = null, $min_id = null, $max_id = null ) { |
|
123 | global $wpdb; |
||
124 | |||
125 | $where = ''; |
||
126 | |||
127 | if ( $status ) { |
||
128 | $where = "post_status = '" . esc_sql( $status ) . "'"; |
||
129 | } else { |
||
130 | $where = '1=1'; |
||
131 | } |
||
132 | |||
133 | if ( ! empty( $min_id ) ) { |
||
134 | $where .= ' AND ID >= ' . (int) $min_id; |
||
135 | } |
||
136 | |||
137 | if ( ! empty( $max_id ) ) { |
||
138 | $where .= ' AND ID <= ' . (int) $max_id; |
||
139 | } |
||
140 | |||
141 | // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared |
||
142 | return $wpdb->get_var( "SELECT COUNT(*) FROM $wpdb->posts WHERE $where" ); |
||
143 | } |
||
144 | |||
145 | /** |
||
146 | * Retrieve the posts with a particular post status. |
||
147 | * |
||
148 | * @access public |
||
149 | * |
||
150 | * @todo Implement range and actually use max_id/min_id arguments. |
||
151 | * |
||
152 | * @param string $status Post status. |
||
153 | * @param int $min_id Minimum post ID. |
||
154 | * @param int $max_id Maximum post ID. |
||
155 | * @return array Array of posts. |
||
156 | */ |
||
157 | public function get_posts( $status = null, $min_id = null, $max_id = null ) { // phpcs:ignore VariableAnalysis.CodeAnalysis.VariableAnalysis.UnusedVariable |
||
158 | $args = array( |
||
159 | 'orderby' => 'ID', |
||
160 | 'posts_per_page' => -1, |
||
161 | ); |
||
162 | |||
163 | if ( $status ) { |
||
164 | $args['post_status'] = $status; |
||
165 | } else { |
||
166 | $args['post_status'] = 'any'; |
||
167 | } |
||
168 | |||
169 | return get_posts( $args ); |
||
170 | } |
||
171 | |||
172 | /** |
||
173 | * Retrieve a post object by the post ID. |
||
174 | * |
||
175 | * @access public |
||
176 | * |
||
177 | * @param int $id Post ID. |
||
178 | * @return \WP_Post Post object. |
||
179 | */ |
||
180 | public function get_post( $id ) { |
||
181 | return get_post( $id ); |
||
182 | } |
||
183 | |||
184 | /** |
||
185 | * Update or insert a post. |
||
186 | * |
||
187 | * @access public |
||
188 | * |
||
189 | * @param \WP_Post $post Post object. |
||
190 | * @param bool $silent Whether to perform a silent action. Not used in this implementation. |
||
191 | */ |
||
192 | public function upsert_post( $post, $silent = false ) { // phpcs:ignore VariableAnalysis.CodeAnalysis.VariableAnalysis.UnusedVariable |
||
193 | global $wpdb; |
||
194 | |||
195 | // Reject the post if it's not a \WP_Post. |
||
196 | if ( ! $post instanceof \WP_Post ) { |
||
197 | return; |
||
198 | } |
||
199 | |||
200 | $post = $post->to_array(); |
||
201 | |||
202 | // Reject posts without an ID. |
||
203 | if ( ! isset( $post['ID'] ) ) { |
||
204 | return; |
||
205 | } |
||
206 | |||
207 | $now = current_time( 'mysql' ); |
||
208 | $now_gmt = get_gmt_from_date( $now ); |
||
209 | |||
210 | $defaults = array( |
||
211 | 'ID' => 0, |
||
212 | 'post_author' => '0', |
||
213 | 'post_content' => '', |
||
214 | 'post_content_filtered' => '', |
||
215 | 'post_title' => '', |
||
216 | 'post_name' => '', |
||
217 | 'post_excerpt' => '', |
||
218 | 'post_status' => 'draft', |
||
219 | 'post_type' => 'post', |
||
220 | 'comment_status' => 'closed', |
||
221 | 'comment_count' => '0', |
||
222 | 'ping_status' => '', |
||
223 | 'post_password' => '', |
||
224 | 'to_ping' => '', |
||
225 | 'pinged' => '', |
||
226 | 'post_parent' => 0, |
||
227 | 'menu_order' => 0, |
||
228 | 'guid' => '', |
||
229 | 'post_date' => $now, |
||
230 | 'post_date_gmt' => $now_gmt, |
||
231 | 'post_modified' => $now, |
||
232 | 'post_modified_gmt' => $now_gmt, |
||
233 | ); |
||
234 | |||
235 | $post = array_intersect_key( $post, $defaults ); |
||
236 | |||
237 | $post = sanitize_post( $post, 'db' ); |
||
238 | |||
239 | unset( $post['filter'] ); |
||
240 | |||
241 | $exists = $wpdb->get_var( $wpdb->prepare( "SELECT EXISTS( SELECT 1 FROM $wpdb->posts WHERE ID = %d )", $post['ID'] ) ); |
||
242 | |||
243 | if ( $exists ) { |
||
244 | $wpdb->update( $wpdb->posts, $post, array( 'ID' => $post['ID'] ) ); |
||
245 | } else { |
||
246 | $wpdb->insert( $wpdb->posts, $post ); |
||
247 | } |
||
248 | |||
249 | clean_post_cache( $post['ID'] ); |
||
250 | } |
||
251 | |||
252 | /** |
||
253 | * Delete a post by the post ID. |
||
254 | * |
||
255 | * @access public |
||
256 | * |
||
257 | * @param int $post_id Post ID. |
||
258 | */ |
||
259 | public function delete_post( $post_id ) { |
||
260 | wp_delete_post( $post_id, true ); |
||
261 | } |
||
262 | |||
263 | /** |
||
264 | * Retrieve the checksum for posts within a range. |
||
265 | * |
||
266 | * @access public |
||
267 | * |
||
268 | * @param int $min_id Minimum post ID. |
||
269 | * @param int $max_id Maximum post ID. |
||
270 | * @return int The checksum. |
||
271 | */ |
||
272 | public function posts_checksum( $min_id = null, $max_id = null ) { |
||
273 | return $this->summarize_checksum_histogram( $this->checksum_histogram( 'posts', null, $min_id, $max_id ) ); |
||
274 | } |
||
275 | |||
276 | /** |
||
277 | * Retrieve the checksum for post meta within a range. |
||
278 | * |
||
279 | * @access public |
||
280 | * |
||
281 | * @param int $min_id Minimum post meta ID. |
||
282 | * @param int $max_id Maximum post meta ID. |
||
283 | * @return int The checksum. |
||
284 | */ |
||
285 | public function post_meta_checksum( $min_id = null, $max_id = null ) { |
||
286 | return $this->summarize_checksum_histogram( $this->checksum_histogram( 'postmeta', null, $min_id, $max_id ) ); |
||
287 | } |
||
288 | |||
289 | /** |
||
290 | * Retrieve the number of comments with a particular comment status within a certain range. |
||
291 | * |
||
292 | * @access public |
||
293 | * |
||
294 | * @todo Prepare the SQL query before executing it. |
||
295 | * |
||
296 | * @param string $status Comment status. |
||
297 | * @param int $min_id Minimum comment ID. |
||
298 | * @param int $max_id Maximum comment ID. |
||
299 | * @return int Number of comments. |
||
300 | */ |
||
301 | View Code Duplication | public function comment_count( $status = null, $min_id = null, $max_id = null ) { |
|
302 | global $wpdb; |
||
303 | |||
304 | $comment_approved = $this->comment_status_to_approval_value( $status ); |
||
305 | |||
306 | if ( false !== $comment_approved ) { |
||
307 | $where = "comment_approved = '" . esc_sql( $comment_approved ) . "'"; |
||
308 | } else { |
||
309 | $where = '1=1'; |
||
310 | } |
||
311 | |||
312 | if ( ! empty( $min_id ) ) { |
||
313 | $where .= ' AND comment_ID >= ' . (int) $min_id; |
||
314 | } |
||
315 | |||
316 | if ( ! empty( $max_id ) ) { |
||
317 | $where .= ' AND comment_ID <= ' . (int) $max_id; |
||
318 | } |
||
319 | |||
320 | // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared |
||
321 | return $wpdb->get_var( "SELECT COUNT(*) FROM $wpdb->comments WHERE $where" ); |
||
322 | } |
||
323 | |||
324 | /** |
||
325 | * Translate a comment status to a value of the comment_approved field. |
||
326 | * |
||
327 | * @access protected |
||
328 | * |
||
329 | * @param string $status Comment status. |
||
330 | * @return string|bool New comment_approved value, false if the status doesn't affect it. |
||
331 | */ |
||
332 | protected function comment_status_to_approval_value( $status ) { |
||
333 | switch ( (string) $status ) { |
||
334 | case 'approve': |
||
335 | case '1': |
||
336 | return '1'; |
||
337 | case 'hold': |
||
338 | case '0': |
||
339 | return '0'; |
||
340 | case 'spam': |
||
341 | return 'spam'; |
||
342 | case 'trash': |
||
343 | return 'trash'; |
||
344 | case 'post-trashed': |
||
345 | return 'post-trashed'; |
||
346 | case 'any': |
||
347 | case 'all': |
||
348 | default: |
||
349 | return false; |
||
350 | } |
||
351 | } |
||
352 | |||
353 | /** |
||
354 | * Retrieve the comments with a particular comment status. |
||
355 | * |
||
356 | * @access public |
||
357 | * |
||
358 | * @todo Implement range and actually use max_id/min_id arguments. |
||
359 | * |
||
360 | * @param string $status Comment status. |
||
361 | * @param int $min_id Minimum comment ID. |
||
362 | * @param int $max_id Maximum comment ID. |
||
363 | * @return array Array of comments. |
||
364 | */ |
||
365 | public function get_comments( $status = null, $min_id = null, $max_id = null ) { // phpcs:ignore VariableAnalysis.CodeAnalysis.VariableAnalysis.UnusedVariable |
||
366 | $args = array( |
||
367 | 'orderby' => 'ID', |
||
368 | 'status' => 'all', |
||
369 | ); |
||
370 | |||
371 | if ( $status ) { |
||
372 | $args['status'] = $status; |
||
373 | } |
||
374 | |||
375 | return get_comments( $args ); |
||
376 | } |
||
377 | |||
378 | /** |
||
379 | * Retrieve a comment object by the comment ID. |
||
380 | * |
||
381 | * @access public |
||
382 | * |
||
383 | * @param int $id Comment ID. |
||
384 | * @return \WP_Comment Comment object. |
||
385 | */ |
||
386 | public function get_comment( $id ) { |
||
387 | return \WP_Comment::get_instance( $id ); |
||
388 | } |
||
389 | |||
390 | /** |
||
391 | * Update or insert a comment. |
||
392 | * |
||
393 | * @access public |
||
394 | * |
||
395 | * @param \WP_Comment $comment Comment object. |
||
396 | */ |
||
397 | public function upsert_comment( $comment ) { |
||
398 | global $wpdb; |
||
399 | |||
400 | $comment = $comment->to_array(); |
||
401 | |||
402 | // Filter by fields on comment table. |
||
403 | $comment_fields_whitelist = array( |
||
404 | 'comment_ID', |
||
405 | 'comment_post_ID', |
||
406 | 'comment_author', |
||
407 | 'comment_author_email', |
||
408 | 'comment_author_url', |
||
409 | 'comment_author_IP', |
||
410 | 'comment_date', |
||
411 | 'comment_date_gmt', |
||
412 | 'comment_content', |
||
413 | 'comment_karma', |
||
414 | 'comment_approved', |
||
415 | 'comment_agent', |
||
416 | 'comment_type', |
||
417 | 'comment_parent', |
||
418 | 'user_id', |
||
419 | ); |
||
420 | |||
421 | foreach ( $comment as $key => $value ) { |
||
422 | if ( ! in_array( $key, $comment_fields_whitelist, true ) ) { |
||
423 | unset( $comment[ $key ] ); |
||
424 | } |
||
425 | } |
||
426 | |||
427 | $exists = $wpdb->get_var( |
||
428 | $wpdb->prepare( |
||
429 | "SELECT EXISTS( SELECT 1 FROM $wpdb->comments WHERE comment_ID = %d )", |
||
430 | $comment['comment_ID'] |
||
431 | ) |
||
432 | ); |
||
433 | |||
434 | if ( $exists ) { |
||
435 | $wpdb->update( $wpdb->comments, $comment, array( 'comment_ID' => $comment['comment_ID'] ) ); |
||
436 | } else { |
||
437 | $wpdb->insert( $wpdb->comments, $comment ); |
||
438 | } |
||
439 | // Remove comment from cache. |
||
440 | clean_comment_cache( $comment['comment_ID'] ); |
||
441 | |||
442 | wp_update_comment_count( $comment['comment_post_ID'] ); |
||
443 | } |
||
444 | |||
445 | /** |
||
446 | * Trash a comment by the comment ID. |
||
447 | * |
||
448 | * @access public |
||
449 | * |
||
450 | * @param int $comment_id Comment ID. |
||
451 | */ |
||
452 | public function trash_comment( $comment_id ) { |
||
453 | wp_delete_comment( $comment_id ); |
||
454 | } |
||
455 | |||
456 | /** |
||
457 | * Delete a comment by the comment ID. |
||
458 | * |
||
459 | * @access public |
||
460 | * |
||
461 | * @param int $comment_id Comment ID. |
||
462 | */ |
||
463 | public function delete_comment( $comment_id ) { |
||
464 | wp_delete_comment( $comment_id, true ); |
||
465 | } |
||
466 | |||
467 | /** |
||
468 | * Mark a comment by the comment ID as spam. |
||
469 | * |
||
470 | * @access public |
||
471 | * |
||
472 | * @param int $comment_id Comment ID. |
||
473 | */ |
||
474 | public function spam_comment( $comment_id ) { |
||
475 | wp_spam_comment( $comment_id ); |
||
476 | } |
||
477 | |||
478 | /** |
||
479 | * Trash the comments of a post. |
||
480 | * |
||
481 | * @access public |
||
482 | * |
||
483 | * @param int $post_id Post ID. |
||
484 | * @param array $statuses Post statuses. Not used in this implementation. |
||
485 | */ |
||
486 | public function trashed_post_comments( $post_id, $statuses ) { // phpcs:ignore VariableAnalysis.CodeAnalysis.VariableAnalysis.UnusedVariable |
||
487 | wp_trash_post_comments( $post_id ); |
||
488 | } |
||
489 | |||
490 | /** |
||
491 | * Untrash the comments of a post. |
||
492 | * |
||
493 | * @access public |
||
494 | * |
||
495 | * @param int $post_id Post ID. |
||
496 | */ |
||
497 | public function untrashed_post_comments( $post_id ) { |
||
498 | wp_untrash_post_comments( $post_id ); |
||
499 | } |
||
500 | |||
501 | /** |
||
502 | * Retrieve the checksum for comments within a range. |
||
503 | * |
||
504 | * @access public |
||
505 | * |
||
506 | * @param int $min_id Minimum comment ID. |
||
507 | * @param int $max_id Maximum comment ID. |
||
508 | * @return int The checksum. |
||
509 | */ |
||
510 | public function comments_checksum( $min_id = null, $max_id = null ) { |
||
511 | return $this->summarize_checksum_histogram( $this->checksum_histogram( 'comments', null, $min_id, $max_id ) ); |
||
512 | } |
||
513 | |||
514 | /** |
||
515 | * Retrieve the checksum for comment meta within a range. |
||
516 | * |
||
517 | * @access public |
||
518 | * |
||
519 | * @param int $min_id Minimum comment meta ID. |
||
520 | * @param int $max_id Maximum comment meta ID. |
||
521 | * @return int The checksum. |
||
522 | */ |
||
523 | public function comment_meta_checksum( $min_id = null, $max_id = null ) { |
||
524 | return $this->summarize_checksum_histogram( $this->checksum_histogram( 'commentmeta', null, $min_id, $max_id ) ); |
||
525 | } |
||
526 | |||
527 | /** |
||
528 | * Update the value of an option. |
||
529 | * |
||
530 | * @access public |
||
531 | * |
||
532 | * @param string $option Option name. |
||
533 | * @param mixed $value Option value. |
||
534 | * @return bool False if value was not updated and true if value was updated. |
||
535 | */ |
||
536 | public function update_option( $option, $value ) { |
||
537 | return update_option( $option, $value ); |
||
538 | } |
||
539 | |||
540 | /** |
||
541 | * Retrieve an option value based on an option name. |
||
542 | * |
||
543 | * @access public |
||
544 | * |
||
545 | * @param string $option Name of option to retrieve. |
||
546 | * @param mixed $default Optional. Default value to return if the option does not exist. |
||
547 | * @return mixed Value set for the option. |
||
548 | */ |
||
549 | public function get_option( $option, $default = false ) { |
||
550 | return get_option( $option, $default ); |
||
551 | } |
||
552 | |||
553 | /** |
||
554 | * Remove an option by name. |
||
555 | * |
||
556 | * @access public |
||
557 | * |
||
558 | * @param string $option Name of option to remove. |
||
559 | * @return bool True, if option is successfully deleted. False on failure. |
||
560 | */ |
||
561 | public function delete_option( $option ) { |
||
562 | return delete_option( $option ); |
||
563 | } |
||
564 | |||
565 | /** |
||
566 | * Change the info of the current theme. |
||
567 | * |
||
568 | * @access public |
||
569 | * |
||
570 | * @param array $theme_info Theme info array. |
||
571 | */ |
||
572 | public function set_theme_info( $theme_info ) { // phpcs:ignore VariableAnalysis.CodeAnalysis.VariableAnalysis.UnusedVariable |
||
573 | // Noop. |
||
574 | } |
||
575 | |||
576 | /** |
||
577 | * Whether the current theme supports a certain feature. |
||
578 | * |
||
579 | * @access public |
||
580 | * |
||
581 | * @param string $feature Name of the feature. |
||
582 | */ |
||
583 | public function current_theme_supports( $feature ) { |
||
584 | return current_theme_supports( $feature ); |
||
585 | } |
||
586 | |||
587 | /** |
||
588 | * Retrieve metadata for the specified object. |
||
589 | * |
||
590 | * @access public |
||
591 | * |
||
592 | * @param string $type Meta type. |
||
593 | * @param int $object_id ID of the object. |
||
594 | * @param string $meta_key Meta key. |
||
595 | * @param bool $single If true, return only the first value of the specified meta_key. |
||
596 | * |
||
597 | * @return mixed Single metadata value, or array of values. |
||
598 | */ |
||
599 | public function get_metadata( $type, $object_id, $meta_key = '', $single = false ) { |
||
600 | return get_metadata( $type, $object_id, $meta_key, $single ); |
||
601 | } |
||
602 | |||
603 | /** |
||
604 | * Stores remote meta key/values alongside an ID mapping key. |
||
605 | * |
||
606 | * @access public |
||
607 | * |
||
608 | * @todo Refactor to not use interpolated values when preparing the SQL query. |
||
609 | * |
||
610 | * @param string $type Meta type. |
||
611 | * @param int $object_id ID of the object. |
||
612 | * @param string $meta_key Meta key. |
||
613 | * @param mixed $meta_value Meta value. |
||
614 | * @param int $meta_id ID of the meta. |
||
615 | * |
||
616 | * @return bool False if meta table does not exist, true otherwise. |
||
617 | */ |
||
618 | public function upsert_metadata( $type, $object_id, $meta_key, $meta_value, $meta_id ) { |
||
619 | $table = _get_meta_table( $type ); |
||
620 | if ( ! $table ) { |
||
621 | return false; |
||
622 | } |
||
623 | |||
624 | global $wpdb; |
||
625 | |||
626 | $exists = $wpdb->get_var( |
||
627 | $wpdb->prepare( |
||
628 | // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared |
||
629 | "SELECT EXISTS( SELECT 1 FROM $table WHERE meta_id = %d )", |
||
630 | $meta_id |
||
631 | ) |
||
632 | ); |
||
633 | |||
634 | if ( $exists ) { |
||
635 | $wpdb->update( |
||
636 | $table, |
||
637 | array( |
||
638 | 'meta_key' => $meta_key, |
||
639 | 'meta_value' => maybe_serialize( $meta_value ), |
||
640 | ), |
||
641 | array( 'meta_id' => $meta_id ) |
||
642 | ); |
||
643 | } else { |
||
644 | $object_id_field = $type . '_id'; |
||
645 | $wpdb->insert( |
||
646 | $table, |
||
647 | array( |
||
648 | 'meta_id' => $meta_id, |
||
649 | $object_id_field => $object_id, |
||
650 | 'meta_key' => $meta_key, |
||
651 | 'meta_value' => maybe_serialize( $meta_value ), |
||
652 | ) |
||
653 | ); |
||
654 | } |
||
655 | |||
656 | wp_cache_delete( $object_id, $type . '_meta' ); |
||
657 | |||
658 | return true; |
||
659 | } |
||
660 | |||
661 | /** |
||
662 | * Delete metadata for the specified object. |
||
663 | * |
||
664 | * @access public |
||
665 | * |
||
666 | * @todo Refactor to not use interpolated values when preparing the SQL query. |
||
667 | * |
||
668 | * @param string $type Meta type. |
||
669 | * @param int $object_id ID of the object. |
||
670 | * @param array $meta_ids IDs of the meta objects to delete. |
||
671 | */ |
||
672 | public function delete_metadata( $type, $object_id, $meta_ids ) { |
||
673 | global $wpdb; |
||
674 | |||
675 | $table = _get_meta_table( $type ); |
||
676 | if ( ! $table ) { |
||
677 | return false; |
||
678 | } |
||
679 | |||
680 | foreach ( $meta_ids as $meta_id ) { |
||
681 | // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared |
||
682 | $wpdb->query( $wpdb->prepare( "DELETE FROM $table WHERE meta_id = %d", $meta_id ) ); |
||
683 | } |
||
684 | |||
685 | // If we don't have an object ID what do we do - invalidate ALL meta? |
||
686 | if ( $object_id ) { |
||
687 | wp_cache_delete( $object_id, $type . '_meta' ); |
||
688 | } |
||
689 | } |
||
690 | |||
691 | /** |
||
692 | * Delete metadata with a certain key for the specified objects. |
||
693 | * |
||
694 | * @access public |
||
695 | * |
||
696 | * @todo Test this out to make sure it works as expected. |
||
697 | * @todo Refactor to not use interpolated values when preparing the SQL query. |
||
698 | * |
||
699 | * @param string $type Meta type. |
||
700 | * @param array $object_ids IDs of the objects. |
||
701 | * @param string $meta_key Meta key. |
||
702 | */ |
||
703 | public function delete_batch_metadata( $type, $object_ids, $meta_key ) { |
||
704 | global $wpdb; |
||
705 | |||
706 | $table = _get_meta_table( $type ); |
||
707 | if ( ! $table ) { |
||
708 | return false; |
||
709 | } |
||
710 | $column = sanitize_key( $type . '_id' ); |
||
711 | // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared |
||
712 | $wpdb->query( $wpdb->prepare( "DELETE FROM $table WHERE $column IN (%s) && meta_key = %s", implode( ',', $object_ids ), $meta_key ) ); |
||
713 | |||
714 | // If we don't have an object ID what do we do - invalidate ALL meta? |
||
715 | foreach ( $object_ids as $object_id ) { |
||
716 | wp_cache_delete( $object_id, $type . '_meta' ); |
||
717 | } |
||
718 | } |
||
719 | |||
720 | /** |
||
721 | * Retrieve value of a constant based on the constant name. |
||
722 | * |
||
723 | * We explicitly return null instead of false if the constant doesn't exist. |
||
724 | * |
||
725 | * @access public |
||
726 | * |
||
727 | * @param string $constant Name of constant to retrieve. |
||
728 | * @return mixed Value set for the constant. |
||
729 | */ |
||
730 | public function get_constant( $constant ) { |
||
731 | $value = get_option( 'jetpack_constant_' . $constant ); |
||
732 | |||
733 | if ( $value ) { |
||
734 | return $value; |
||
735 | } |
||
736 | |||
737 | return null; |
||
738 | } |
||
739 | |||
740 | /** |
||
741 | * Set the value of a constant. |
||
742 | * |
||
743 | * @access public |
||
744 | * |
||
745 | * @param string $constant Name of constant to retrieve. |
||
746 | * @param mixed $value Value set for the constant. |
||
747 | */ |
||
748 | public function set_constant( $constant, $value ) { |
||
749 | update_option( 'jetpack_constant_' . $constant, $value ); |
||
750 | } |
||
751 | |||
752 | /** |
||
753 | * Retrieve the number of the available updates of a certain type. |
||
754 | * Type is one of: `plugins`, `themes`, `wordpress`, `translations`, `total`, `wp_update_version`. |
||
755 | * |
||
756 | * @access public |
||
757 | * |
||
758 | * @param string $type Type of updates to retrieve. |
||
759 | * @return int|null Number of updates available, `null` if type is invalid or missing. |
||
760 | */ |
||
761 | public function get_updates( $type ) { |
||
762 | $all_updates = get_option( 'jetpack_updates', array() ); |
||
763 | |||
764 | if ( isset( $all_updates[ $type ] ) ) { |
||
765 | return $all_updates[ $type ]; |
||
766 | } else { |
||
767 | return null; |
||
768 | } |
||
769 | } |
||
770 | |||
771 | /** |
||
772 | * Set the available updates of a certain type. |
||
773 | * Type is one of: `plugins`, `themes`, `wordpress`, `translations`, `total`, `wp_update_version`. |
||
774 | * |
||
775 | * @access public |
||
776 | * |
||
777 | * @param string $type Type of updates to set. |
||
778 | * @param int $updates Total number of updates. |
||
779 | */ |
||
780 | public function set_updates( $type, $updates ) { |
||
781 | $all_updates = get_option( 'jetpack_updates', array() ); |
||
782 | $all_updates[ $type ] = $updates; |
||
783 | update_option( 'jetpack_updates', $all_updates ); |
||
784 | } |
||
785 | |||
786 | /** |
||
787 | * Retrieve a callable value based on its name. |
||
788 | * |
||
789 | * @access public |
||
790 | * |
||
791 | * @param string $name Name of the callable to retrieve. |
||
792 | * @return mixed Value of the callable. |
||
793 | */ |
||
794 | public function get_callable( $name ) { |
||
795 | $value = get_option( 'jetpack_' . $name ); |
||
796 | |||
797 | if ( $value ) { |
||
798 | return $value; |
||
799 | } |
||
800 | |||
801 | return null; |
||
802 | } |
||
803 | |||
804 | /** |
||
805 | * Update the value of a callable. |
||
806 | * |
||
807 | * @access public |
||
808 | * |
||
809 | * @param string $name Callable name. |
||
810 | * @param mixed $value Callable value. |
||
811 | */ |
||
812 | public function set_callable( $name, $value ) { |
||
813 | update_option( 'jetpack_' . $name, $value ); |
||
814 | } |
||
815 | |||
816 | /** |
||
817 | * Retrieve a network option value based on a network option name. |
||
818 | * |
||
819 | * @access public |
||
820 | * |
||
821 | * @param string $option Name of network option to retrieve. |
||
822 | * @return mixed Value set for the network option. |
||
823 | */ |
||
824 | public function get_site_option( $option ) { |
||
825 | return get_option( 'jetpack_network_' . $option ); |
||
826 | } |
||
827 | |||
828 | /** |
||
829 | * Update the value of a network option. |
||
830 | * |
||
831 | * @access public |
||
832 | * |
||
833 | * @param string $option Network option name. |
||
834 | * @param mixed $value Network option value. |
||
835 | * @return bool False if value was not updated and true if value was updated. |
||
836 | */ |
||
837 | public function update_site_option( $option, $value ) { |
||
838 | return update_option( 'jetpack_network_' . $option, $value ); |
||
839 | } |
||
840 | |||
841 | /** |
||
842 | * Remove a network option by name. |
||
843 | * |
||
844 | * @access public |
||
845 | * |
||
846 | * @param string $option Name of option to remove. |
||
847 | * @return bool True, if option is successfully deleted. False on failure. |
||
848 | */ |
||
849 | public function delete_site_option( $option ) { |
||
850 | return delete_option( 'jetpack_network_' . $option ); |
||
851 | } |
||
852 | |||
853 | /** |
||
854 | * Retrieve the terms from a particular taxonomy. |
||
855 | * |
||
856 | * @access public |
||
857 | * |
||
858 | * @param string $taxonomy Taxonomy slug. |
||
859 | * @return array|\WP_Error Array of terms or WP_Error object on failure. |
||
860 | */ |
||
861 | public function get_terms( $taxonomy ) { |
||
862 | $t = $this->ensure_taxonomy( $taxonomy ); |
||
863 | if ( ! $t || is_wp_error( $t ) ) { |
||
864 | return $t; |
||
865 | } |
||
866 | return get_terms( $taxonomy ); |
||
867 | } |
||
868 | |||
869 | /** |
||
870 | * Retrieve a particular term. |
||
871 | * |
||
872 | * @access public |
||
873 | * |
||
874 | * @param string $taxonomy Taxonomy slug. |
||
875 | * @param int $term_id ID of the term. |
||
876 | * @param string $term_key ID Field `term_id` or `term_taxonomy_id`. |
||
877 | * @return \WP_Term|\WP_Error Term object on success, \WP_Error object on failure. |
||
878 | */ |
||
879 | public function get_term( $taxonomy, $term_id, $term_key = 'term_id' ) { |
||
880 | |||
881 | // Full Sync will pass false for the $taxonomy so a check for term_taxonomy_id is needed before ensure_taxonomy. |
||
882 | if ( 'term_taxonomy_id' === $term_key ) { |
||
883 | return get_term_by( 'term_taxonomy_id', $term_id ); |
||
884 | } |
||
885 | |||
886 | $t = $this->ensure_taxonomy( $taxonomy ); |
||
887 | if ( ! $t || is_wp_error( $t ) ) { |
||
888 | return $t; |
||
889 | } |
||
890 | |||
891 | return get_term( $term_id, $taxonomy ); |
||
892 | } |
||
893 | |||
894 | /** |
||
895 | * Verify a taxonomy is legitimate and register it if necessary. |
||
896 | * |
||
897 | * @access private |
||
898 | * |
||
899 | * @param string $taxonomy Taxonomy slug. |
||
900 | * @return bool|void|\WP_Error True if already exists; void if it was registered; \WP_Error on error. |
||
901 | */ |
||
902 | private function ensure_taxonomy( $taxonomy ) { |
||
903 | if ( ! taxonomy_exists( $taxonomy ) ) { |
||
904 | // Try re-registering synced taxonomies. |
||
905 | $taxonomies = $this->get_callable( 'taxonomies' ); |
||
906 | if ( ! isset( $taxonomies[ $taxonomy ] ) ) { |
||
907 | // Doesn't exist, or somehow hasn't been synced. |
||
908 | return new \WP_Error( 'invalid_taxonomy', "The taxonomy '$taxonomy' doesn't exist" ); |
||
909 | } |
||
910 | $t = $taxonomies[ $taxonomy ]; |
||
911 | |||
912 | return register_taxonomy( |
||
913 | $taxonomy, |
||
914 | $t->object_type, |
||
915 | (array) $t |
||
916 | ); |
||
917 | } |
||
918 | |||
919 | return true; |
||
920 | } |
||
921 | |||
922 | /** |
||
923 | * Retrieve all terms from a taxonomy that are related to an object with a particular ID. |
||
924 | * |
||
925 | * @access public |
||
926 | * |
||
927 | * @param int $object_id Object ID. |
||
928 | * @param string $taxonomy Taxonomy slug. |
||
929 | * @return array|bool|\WP_Error Array of terms on success, `false` if no terms or post doesn't exist, \WP_Error on failure. |
||
930 | */ |
||
931 | public function get_the_terms( $object_id, $taxonomy ) { |
||
932 | return get_the_terms( $object_id, $taxonomy ); |
||
933 | } |
||
934 | |||
935 | /** |
||
936 | * Insert or update a term. |
||
937 | * |
||
938 | * @access public |
||
939 | * |
||
940 | * @param \WP_Term $term_object Term object. |
||
941 | * @return array|bool|\WP_Error Array of term_id and term_taxonomy_id if updated, true if inserted, \WP_Error on failure. |
||
942 | */ |
||
943 | public function update_term( $term_object ) { |
||
944 | $taxonomy = $term_object->taxonomy; |
||
945 | global $wpdb; |
||
946 | $exists = $wpdb->get_var( |
||
947 | $wpdb->prepare( |
||
948 | "SELECT EXISTS( SELECT 1 FROM $wpdb->terms WHERE term_id = %d )", |
||
949 | $term_object->term_id |
||
950 | ) |
||
951 | ); |
||
952 | if ( ! $exists ) { |
||
953 | $term_object = sanitize_term( clone $term_object, $taxonomy, 'db' ); |
||
954 | $term = array( |
||
955 | 'term_id' => $term_object->term_id, |
||
956 | 'name' => $term_object->name, |
||
957 | 'slug' => $term_object->slug, |
||
958 | 'term_group' => $term_object->term_group, |
||
959 | ); |
||
960 | $term_taxonomy = array( |
||
961 | 'term_taxonomy_id' => $term_object->term_taxonomy_id, |
||
962 | 'term_id' => $term_object->term_id, |
||
963 | 'taxonomy' => $term_object->taxonomy, |
||
964 | 'description' => $term_object->description, |
||
965 | 'parent' => (int) $term_object->parent, |
||
966 | 'count' => (int) $term_object->count, |
||
967 | ); |
||
968 | $wpdb->insert( $wpdb->terms, $term ); |
||
969 | $wpdb->insert( $wpdb->term_taxonomy, $term_taxonomy ); |
||
970 | |||
971 | return true; |
||
972 | } |
||
973 | |||
974 | return wp_update_term( $term_object->term_id, $taxonomy, (array) $term_object ); |
||
975 | } |
||
976 | |||
977 | /** |
||
978 | * Delete a term by the term ID and its corresponding taxonomy. |
||
979 | * |
||
980 | * @access public |
||
981 | * |
||
982 | * @param int $term_id Term ID. |
||
983 | * @param string $taxonomy Taxonomy slug. |
||
984 | * @return bool|int|\WP_Error True on success, false if term doesn't exist. Zero if trying with default category. \WP_Error on invalid taxonomy. |
||
985 | */ |
||
986 | public function delete_term( $term_id, $taxonomy ) { |
||
987 | $this->ensure_taxonomy( $taxonomy ); |
||
988 | return wp_delete_term( $term_id, $taxonomy ); |
||
989 | } |
||
990 | |||
991 | /** |
||
992 | * Add/update terms of a particular taxonomy of an object with the specified ID. |
||
993 | * |
||
994 | * @access public |
||
995 | * |
||
996 | * @param int $object_id The object to relate to. |
||
997 | * @param string $taxonomy The context in which to relate the term to the object. |
||
998 | * @param string|int|array $terms A single term slug, single term id, or array of either term slugs or ids. |
||
999 | * @param bool $append Optional. If false will delete difference of terms. Default false. |
||
1000 | */ |
||
1001 | public function update_object_terms( $object_id, $taxonomy, $terms, $append ) { |
||
1002 | $this->ensure_taxonomy( $taxonomy ); |
||
1003 | wp_set_object_terms( $object_id, $terms, $taxonomy, $append ); |
||
1004 | } |
||
1005 | |||
1006 | /** |
||
1007 | * Remove certain term relationships from the specified object. |
||
1008 | * |
||
1009 | * @access public |
||
1010 | * |
||
1011 | * @todo Refactor to not use interpolated values when preparing the SQL query. |
||
1012 | * |
||
1013 | * @param int $object_id ID of the object. |
||
1014 | * @param array $tt_ids Term taxonomy IDs. |
||
1015 | * @return bool True on success, false on failure. |
||
1016 | */ |
||
1017 | public function delete_object_terms( $object_id, $tt_ids ) { |
||
1018 | global $wpdb; |
||
1019 | |||
1020 | if ( is_array( $tt_ids ) && ! empty( $tt_ids ) ) { |
||
1021 | // Escape. |
||
1022 | $tt_ids_sanitized = array_map( 'intval', $tt_ids ); |
||
1023 | |||
1024 | $taxonomies = array(); |
||
1025 | foreach ( $tt_ids_sanitized as $tt_id ) { |
||
1026 | $term = get_term_by( 'term_taxonomy_id', $tt_id ); |
||
1027 | $taxonomies[ $term->taxonomy ][] = $tt_id; |
||
1028 | } |
||
1029 | $in_tt_ids = implode( ', ', $tt_ids_sanitized ); |
||
1030 | |||
1031 | /** |
||
1032 | * Fires immediately before an object-term relationship is deleted. |
||
1033 | * |
||
1034 | * @since 2.9.0 |
||
1035 | * |
||
1036 | * @param int $object_id Object ID. |
||
1037 | * @param array $tt_ids An array of term taxonomy IDs. |
||
1038 | */ |
||
1039 | do_action( 'delete_term_relationships', $object_id, $tt_ids_sanitized ); |
||
1040 | // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared |
||
1041 | $deleted = $wpdb->query( $wpdb->prepare( "DELETE FROM $wpdb->term_relationships WHERE object_id = %d AND term_taxonomy_id IN ($in_tt_ids)", $object_id ) ); |
||
1042 | foreach ( $taxonomies as $taxonomy => $taxonomy_tt_ids ) { |
||
1043 | $this->ensure_taxonomy( $taxonomy ); |
||
1044 | wp_cache_delete( $object_id, $taxonomy . '_relationships' ); |
||
1045 | /** |
||
1046 | * Fires immediately after an object-term relationship is deleted. |
||
1047 | * |
||
1048 | * @since 2.9.0 |
||
1049 | * |
||
1050 | * @param int $object_id Object ID. |
||
1051 | * @param array $tt_ids An array of term taxonomy IDs. |
||
1052 | */ |
||
1053 | do_action( 'deleted_term_relationships', $object_id, $taxonomy_tt_ids ); |
||
1054 | wp_update_term_count( $taxonomy_tt_ids, $taxonomy ); |
||
1055 | } |
||
1056 | |||
1057 | return (bool) $deleted; |
||
1058 | } |
||
1059 | |||
1060 | return false; |
||
1061 | } |
||
1062 | |||
1063 | /** |
||
1064 | * Retrieve the number of users. |
||
1065 | * Not supported in this replicastore. |
||
1066 | * |
||
1067 | * @access public |
||
1068 | */ |
||
1069 | public function user_count() { |
||
1070 | // Noop. |
||
1071 | } |
||
1072 | |||
1073 | /** |
||
1074 | * Retrieve a user object by the user ID. |
||
1075 | * |
||
1076 | * @access public |
||
1077 | * |
||
1078 | * @param int $user_id User ID. |
||
1079 | * @return \WP_User User object. |
||
1080 | */ |
||
1081 | public function get_user( $user_id ) { |
||
1082 | return \WP_User::get_instance( $user_id ); |
||
1083 | } |
||
1084 | |||
1085 | /** |
||
1086 | * Insert or update a user. |
||
1087 | * Not supported in this replicastore. |
||
1088 | * |
||
1089 | * @access public |
||
1090 | * @throws Exception If this method is invoked. |
||
1091 | * |
||
1092 | * @param \WP_User $user User object. |
||
1093 | */ |
||
1094 | public function upsert_user( $user ) { // phpcs:ignore VariableAnalysis.CodeAnalysis.VariableAnalysis.UnusedVariable |
||
1095 | $this->invalid_call(); |
||
1096 | } |
||
1097 | |||
1098 | /** |
||
1099 | * Delete a user. |
||
1100 | * Not supported in this replicastore. |
||
1101 | * |
||
1102 | * @access public |
||
1103 | * @throws Exception If this method is invoked. |
||
1104 | * |
||
1105 | * @param int $user_id User ID. |
||
1106 | */ |
||
1107 | public function delete_user( $user_id ) { // phpcs:ignore VariableAnalysis.CodeAnalysis.VariableAnalysis.UnusedVariable |
||
1108 | $this->invalid_call(); |
||
1109 | } |
||
1110 | |||
1111 | /** |
||
1112 | * Update/insert user locale. |
||
1113 | * Not supported in this replicastore. |
||
1114 | * |
||
1115 | * @access public |
||
1116 | * @throws Exception If this method is invoked. |
||
1117 | * |
||
1118 | * @param int $user_id User ID. |
||
1119 | * @param string $local The user locale. |
||
1120 | */ |
||
1121 | public function upsert_user_locale( $user_id, $local ) { // phpcs:ignore VariableAnalysis.CodeAnalysis.VariableAnalysis.UnusedVariable |
||
1122 | $this->invalid_call(); |
||
1123 | } |
||
1124 | |||
1125 | /** |
||
1126 | * Delete user locale. |
||
1127 | * Not supported in this replicastore. |
||
1128 | * |
||
1129 | * @access public |
||
1130 | * @throws Exception If this method is invoked. |
||
1131 | * |
||
1132 | * @param int $user_id User ID. |
||
1133 | */ |
||
1134 | public function delete_user_locale( $user_id ) { // phpcs:ignore VariableAnalysis.CodeAnalysis.VariableAnalysis.UnusedVariable |
||
1135 | $this->invalid_call(); |
||
1136 | } |
||
1137 | |||
1138 | /** |
||
1139 | * Retrieve the user locale. |
||
1140 | * |
||
1141 | * @access public |
||
1142 | * |
||
1143 | * @param int $user_id User ID. |
||
1144 | * @return string The user locale. |
||
1145 | */ |
||
1146 | public function get_user_locale( $user_id ) { |
||
1147 | return get_user_locale( $user_id ); |
||
1148 | } |
||
1149 | |||
1150 | /** |
||
1151 | * Retrieve the allowed mime types for the user. |
||
1152 | * Not supported in this replicastore. |
||
1153 | * |
||
1154 | * @access public |
||
1155 | * |
||
1156 | * @param int $user_id User ID. |
||
1157 | */ |
||
1158 | public function get_allowed_mime_types( $user_id ) { // phpcs:ignore VariableAnalysis.CodeAnalysis.VariableAnalysis.UnusedVariable |
||
1159 | // Noop. |
||
1160 | } |
||
1161 | |||
1162 | /** |
||
1163 | * Retrieve all the checksums we are interested in. |
||
1164 | * Currently that is posts, comments, post meta and comment meta. |
||
1165 | * |
||
1166 | * @access public |
||
1167 | * |
||
1168 | * @return array Checksums. |
||
1169 | */ |
||
1170 | public function checksum_all() { |
||
1171 | $post_checksum = $this->checksum_histogram( 'posts' ); |
||
1172 | $comments_checksum = $this->checksum_histogram( 'comments' ); |
||
1173 | $post_meta_checksum = $this->checksum_histogram( 'postmeta' ); |
||
1174 | $comment_meta_checksum = $this->checksum_histogram( 'commentmeta' ); |
||
1175 | $terms_checksum = $this->checksum_histogram( 'terms' ); |
||
1176 | $term_relationships_checksum = $this->checksum_histogram( 'term_relationships' ); |
||
1177 | $term_taxonomy_checksum = $this->checksum_histogram( 'term_taxonomy' ); |
||
1178 | |||
1179 | return array( |
||
1180 | 'posts' => $this->summarize_checksum_histogram( $post_checksum ), |
||
1181 | 'comments' => $this->summarize_checksum_histogram( $comments_checksum ), |
||
1182 | 'post_meta' => $this->summarize_checksum_histogram( $post_meta_checksum ), |
||
1183 | 'comment_meta' => $this->summarize_checksum_histogram( $comment_meta_checksum ), |
||
1184 | 'terms' => $this->summarize_checksum_histogram( $terms_checksum ), |
||
1185 | 'term_relationships' => $this->summarize_checksum_histogram( $term_relationships_checksum ), |
||
1186 | 'term_taxonomy' => $this->summarize_checksum_histogram( $term_taxonomy_checksum ), |
||
1187 | ); |
||
1188 | } |
||
1189 | |||
1190 | /** |
||
1191 | * Return the summarized checksum from buckets or the WP_Error. |
||
1192 | * |
||
1193 | * @param array $histogram checksum_histogram result. |
||
1194 | * |
||
1195 | * @return int|WP_Error checksum or Error. |
||
1196 | */ |
||
1197 | protected function summarize_checksum_histogram( $histogram ) { |
||
1198 | if ( is_wp_error( $histogram ) ) { |
||
1199 | return $histogram; |
||
1200 | } else { |
||
1201 | return array_sum( $histogram ); |
||
1202 | } |
||
1203 | } |
||
1204 | |||
1205 | /** |
||
1206 | * Grabs the minimum and maximum object ids for the given parameters. |
||
1207 | * |
||
1208 | * @access public |
||
1209 | * |
||
1210 | * @param string $id_field The id column in the table to query. |
||
1211 | * @param string $object_table The table to query. |
||
1212 | * @param string $where A sql where clause without 'WHERE'. |
||
1213 | * @param int $bucket_size The maximum amount of objects to include in the query. |
||
1214 | * For `term_relationships` table, the bucket size will refer to the amount |
||
1215 | * of distinct object ids. This will likely include more database rows than |
||
1216 | * the bucket size implies. |
||
1217 | * |
||
1218 | * @return object An object with min_id and max_id properties. |
||
1219 | */ |
||
1220 | public function get_min_max_object_id( $id_field, $object_table, $where, $bucket_size ) { |
||
1239 | |||
1240 | /** |
||
1241 | * Retrieve the checksum histogram for a specific object type. |
||
1242 | * |
||
1243 | * @access public |
||
1244 | * |
||
1245 | * @param string $table Object type. |
||
1246 | * @param null $buckets Number of buckets to split the objects to. |
||
1247 | * @param null $start_id Minimum object ID. |
||
1248 | * @param null $end_id Maximum object ID. |
||
1249 | * @param null $columns Table columns to calculate the checksum from. |
||
1250 | * @param bool $strip_non_ascii Whether to strip non-ASCII characters. |
||
1251 | * @param string $salt Salt, used for $wpdb->prepare()'s args. |
||
1252 | * @param bool $only_range_edges Only return the range edges and not the actual checksums. |
||
1253 | * @param bool $detailed_drilldown If the call should return a detailed drilldown for the checksum or only the checksum. |
||
1254 | * |
||
1255 | * @return array|WP_Error The checksum histogram. |
||
1256 | * @throws Exception Throws an exception if data validation fails inside `Table_Checksum` calls. |
||
1257 | */ |
||
1258 | public function checksum_histogram( $table, $buckets = null, $start_id = null, $end_id = null, $columns = null, $strip_non_ascii = true, $salt = '', $only_range_edges = false, $detailed_drilldown = false ) { |
||
1259 | global $wpdb; |
||
1260 | |||
1261 | $wpdb->queries = array(); |
||
1262 | try { |
||
1263 | $checksum_table = new Table_Checksum( $table, $salt ); |
||
1264 | } catch ( Exception $ex ) { |
||
1265 | return new WP_Error( 'checksum_disabled', $ex->getMessage() ); |
||
1266 | } |
||
1267 | |||
1268 | // Validate / Determine Buckets. |
||
1269 | if ( is_null( $buckets ) || $buckets < 1 ) { |
||
1270 | $buckets = $this->calculate_buckets( $table, $start_id, $end_id ); |
||
1271 | } |
||
1272 | if ( is_wp_error( $buckets ) ) { |
||
1273 | return $buckets; |
||
1274 | } |
||
1275 | |||
1276 | $range_edges = $checksum_table->get_range_edges( $start_id, $end_id ); |
||
1277 | |||
1278 | if ( $only_range_edges ) { |
||
1279 | return $range_edges; |
||
1280 | } |
||
1281 | |||
1282 | $object_count = $range_edges['item_count']; |
||
1283 | |||
1284 | $bucket_size = (int) ceil( $object_count / $buckets ); |
||
1285 | $previous_max_id = max( 0, $range_edges['min_range'] ); |
||
1286 | $histogram = array(); |
||
1287 | |||
1288 | do { |
||
1289 | $ids_range = $checksum_table->get_range_edges( $previous_max_id, null, $bucket_size ); |
||
1290 | |||
1291 | if ( empty( $ids_range['min_range'] ) || empty( $ids_range['max_range'] ) ) { |
||
1292 | // Nothing to checksum here... |
||
1293 | break; |
||
1294 | } |
||
1295 | |||
1296 | // Get the checksum value. |
||
1297 | $batch_checksum = $checksum_table->calculate_checksum( $ids_range['min_range'], $ids_range['max_range'], null, $detailed_drilldown ); |
||
1298 | |||
1299 | if ( is_wp_error( $batch_checksum ) ) { |
||
1300 | return $batch_checksum; |
||
1301 | } |
||
1302 | |||
1303 | if ( $ids_range['min_range'] === $ids_range['max_range'] ) { |
||
1304 | $histogram[ $ids_range['min_range'] ] = $batch_checksum; |
||
1305 | } else { |
||
1306 | $histogram[ "{$ids_range[ 'min_range' ]}-{$ids_range[ 'max_range' ]}" ] = $batch_checksum; |
||
1307 | } |
||
1308 | |||
1309 | $previous_max_id = $ids_range['max_range'] + 1; |
||
1310 | // If we've reached the max_range lets bail out. |
||
1311 | if ( $previous_max_id >= $range_edges['max_range'] ) { |
||
1312 | break; |
||
1313 | } |
||
1314 | } while ( true ); |
||
1315 | |||
1316 | return $histogram; |
||
1317 | } |
||
1318 | |||
1319 | /** |
||
1320 | * Retrieve the type of the checksum. |
||
1321 | * |
||
1322 | * @access public |
||
1323 | * |
||
1324 | * @return string Type of the checksum. |
||
1325 | */ |
||
1326 | public function get_checksum_type() { |
||
1329 | |||
1330 | /** |
||
1331 | * Used in methods that are not implemented and shouldn't be invoked. |
||
1332 | * |
||
1333 | * @access private |
||
1334 | * @throws Exception If this method is invoked. |
||
1335 | */ |
||
1336 | private function invalid_call() { |
||
1342 | |||
1343 | /** |
||
1344 | * Determine number of buckets to use in full table checksum. |
||
1345 | * |
||
1346 | * @param string $table Object Type. |
||
1347 | * @param int $start_id Min Object ID. |
||
1348 | * @param int $end_id Max Object ID. |
||
1349 | * @return int|WP_Error Number of Buckets to use. |
||
1350 | */ |
||
1351 | private function calculate_buckets( $table, $start_id = null, $end_id = null ) { |
||
1376 | } |
||
1377 |
This check looks for
@param
annotations where the type inferred by our type inference engine differs from the declared type.It makes a suggestion as to what type it considers more descriptive.
Most often this is a case of a parameter that can be null in addition to its declared types.