Completed
Push — fix/issue-5159 ( e5f9c0...935047 )
by
unknown
55:37 queued 42:38
created

sync/class.jetpack-sync-wp-replicastore.php (7 issues)

Upgrade to new PHP Analysis Engine

These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more

1
<?php
2
3
require_once dirname( __FILE__ ) . '/interface.jetpack-sync-replicastore.php';
4
require_once dirname( __FILE__ ) . '/class.jetpack-sync-defaults.php';
5
6
/**
7
 * An implementation of iJetpack_Sync_Replicastore which returns data stored in a WordPress.org DB.
8
 * This is useful to compare values in the local WP DB to values in the synced replica store
9
 */
10
class Jetpack_Sync_WP_Replicastore implements iJetpack_Sync_Replicastore {
11
12
13
	public function reset() {
14
		global $wpdb;
15
16
		$wpdb->query( "DELETE FROM $wpdb->posts" );
17
		$wpdb->query( "DELETE FROM $wpdb->comments" );
18
19
		// also need to delete terms from cache
20
		$term_ids = $wpdb->get_col( "SELECT term_id FROM $wpdb->terms" );
21
		foreach ( $term_ids as $term_id ) {
22
			wp_cache_delete( $term_id, 'terms' );
23
		}
24
25
		$wpdb->query( "DELETE FROM $wpdb->terms" );
26
27
		$wpdb->query( "DELETE FROM $wpdb->term_taxonomy" );
28
		$wpdb->query( "DELETE FROM $wpdb->term_relationships" );
29
30
		// callables and constants
31
		$wpdb->query( "DELETE FROM $wpdb->options WHERE option_name LIKE 'jetpack_%'" );
32
		$wpdb->query( "DELETE FROM $wpdb->postmeta WHERE meta_key NOT LIKE '\_%'" );
33
	}
34
35
	function full_sync_start( $config ) {
36
		$this->reset();
37
	}
38
39
	function full_sync_end( $checksum ) {
40
		// noop right now
41
	}
42
43 View Code Duplication
	public function post_count( $status = null, $min_id = null, $max_id = null ) {
44
		global $wpdb;
45
46
		$where = '';
47
48
		if ( $status ) {
49
			$where = "post_status = '" . esc_sql( $status ) . "'";
50
		} else {
51
			$where = '1=1';
52
		}
53
54
		if ( null != $min_id ) {
55
			$where .= ' AND ID >= ' . intval( $min_id );
56
		}
57
58
		if ( null != $max_id ) {
59
			$where .= ' AND ID <= ' . intval( $max_id );
60
		}
61
62
		return $wpdb->get_var( "SELECT COUNT(*) FROM $wpdb->posts WHERE $where" );
63
	}
64
65
	// TODO: actually use max_id/min_id
66
	public function get_posts( $status = null, $min_id = null, $max_id = null ) {
67
		$args = array( 'orderby' => 'ID', 'posts_per_page' => -1 );
68
69
		if ( $status ) {
70
			$args['post_status'] = $status;
71
		} else {
72
			$args['post_status'] = 'any';
73
		}
74
75
		return get_posts( $args );
76
	}
77
78
	public function get_post( $id ) {
79
		return get_post( $id );
80
	}
81
82
	public function upsert_post( $post, $silent = false ) {
83
		global $wpdb;
84
85
		// reject the post if it's not a WP_Post
86
		if ( ! $post instanceof WP_Post ) {
87
			return;
88
		}
89
90
		$post = $post->to_array();
91
92
		// reject posts without an ID
93
		if ( ! isset( $post['ID'] ) ) {
94
			return;
95
		}
96
97
		$now     = current_time( 'mysql' );
98
		$now_gmt = get_gmt_from_date( $now );
99
100
		$defaults = array(
101
			'ID'                    => 0,
102
			'post_author'           => '0',
103
			'post_content'          => '',
104
			'post_content_filtered' => '',
105
			'post_title'            => '',
106
			'post_name'             => '',
107
			'post_excerpt'          => '',
108
			'post_status'           => 'draft',
109
			'post_type'             => 'post',
110
			'comment_status'        => 'closed',
111
			'comment_count'         => '0',
112
			'ping_status'           => '',
113
			'post_password'         => '',
114
			'to_ping'               => '',
115
			'pinged'                => '',
116
			'post_parent'           => 0,
117
			'menu_order'            => 0,
118
			'guid'                  => '',
119
			'post_date'             => $now,
120
			'post_date_gmt'         => $now_gmt,
121
			'post_modified'         => $now,
122
			'post_modified_gmt'     => $now_gmt,
123
		);
124
125
		$post = array_intersect_key( $post, $defaults );
126
127
		$post = sanitize_post( $post, 'db' );
128
129
		unset( $post['filter'] );
130
131
		$exists = $wpdb->get_var( $wpdb->prepare( "SELECT EXISTS( SELECT 1 FROM $wpdb->posts WHERE ID = %d )", $post['ID'] ) );
132
133
		if ( $exists ) {
134
			$wpdb->update( $wpdb->posts, $post, array( 'ID' => $post['ID'] ) );
135
		} else {
136
			$wpdb->insert( $wpdb->posts, $post );
137
		}
138
139
		clean_post_cache( $post['ID'] );
140
	}
141
142
	public function delete_post( $post_id ) {
143
		wp_delete_post( $post_id, true );
144
	}
145
146
	public function posts_checksum( $min_id = null, $max_id = null ) {
147
		global $wpdb;
148
		return $this->table_checksum( $wpdb->posts, Jetpack_Sync_Defaults::$default_post_checksum_columns , 'ID', Jetpack_Sync_Settings::get_blacklisted_post_types_sql(), $min_id, $max_id );
149
	}
150
151
	public function post_meta_checksum( $min_id = null, $max_id = null ) {
152
		global $wpdb;
153
		return $this->table_checksum( $wpdb->postmeta, Jetpack_Sync_Defaults::$default_post_meta_checksum_columns , 'meta_id', Jetpack_Sync_Settings::get_whitelisted_post_meta_sql(), $min_id, $max_id );
0 ignored issues
show
The property default_post_meta_checksum_columns cannot be accessed from this context as it is declared private in class Jetpack_Sync_Defaults.

This check looks for access to properties that are not accessible from the current context.

If you need to make a property accessible to another context you can either raise its visibility level or provide an accessible getter in the defining class.

Loading history...
154
	}
155
156 View Code Duplication
	public function comment_count( $status = null, $min_id = null, $max_id = null ) {
157
		global $wpdb;
158
159
		$comment_approved = $this->comment_status_to_approval_value( $status );
160
161
		if ( $comment_approved !== false ) {
162
			$where = "comment_approved = '" . esc_sql( $comment_approved ) . "'";
163
		} else {
164
			$where = '1=1';
165
		}
166
167
		if ( $min_id != null ) {
168
			$where .= ' AND comment_ID >= ' . intval( $min_id );
169
		}
170
171
		if ( $max_id != null ) {
172
			$where .= ' AND comment_ID <= ' . intval( $max_id );
173
		}
174
175
		return $wpdb->get_var( "SELECT COUNT(*) FROM $wpdb->comments WHERE $where" );
176
	}
177
178
	private function comment_status_to_approval_value( $status ) {
179
		switch ( $status ) {
180
			case 'approve':
181
				return '1';
182
			case 'hold':
183
				return '0';
184
			case 'spam':
185
				return 'spam';
186
			case 'trash':
187
				return 'trash';
188
			case 'any':
189
				return false;
190
			case 'all':
191
				return false;
192
			default:
193
				return false;
194
		}
195
	}
196
197
	// TODO: actually use max_id/min_id
198
	public function get_comments( $status = null, $min_id = null, $max_id = null ) {
199
		$args = array( 'orderby' => 'ID', 'status' => 'all' );
200
201
		if ( $status ) {
202
			$args['status'] = $status;
203
		}
204
205
		return get_comments( $args );
206
	}
207
208
	public function get_comment( $id ) {
209
		return WP_Comment::get_instance( $id );
210
	}
211
212
	public function upsert_comment( $comment ) {
213
		global $wpdb, $wp_version;
214
215
		if ( version_compare( $wp_version, '4.4', '<' ) ) {
216
			$comment = (array) $comment;
217
		} else {
218
			// WP 4.4 introduced the WP_Comment Class
219
			$comment = $comment->to_array();
220
		}
221
222
		// filter by fields on comment table
223
		$comment_fields_whitelist = array(
224
			'comment_ID',
225
			'comment_post_ID',
226
			'comment_author',
227
			'comment_author_email',
228
			'comment_author_url',
229
			'comment_author_IP',
230
			'comment_date',
231
			'comment_date_gmt',
232
			'comment_content',
233
			'comment_karma',
234
			'comment_approved',
235
			'comment_agent',
236
			'comment_type',
237
			'comment_parent',
238
			'user_id',
239
		);
240
241
		foreach ( $comment as $key => $value ) {
242
			if ( ! in_array( $key, $comment_fields_whitelist ) ) {
243
				unset( $comment[ $key ] );
244
			}
245
		}
246
247
		$exists = $wpdb->get_var(
248
			$wpdb->prepare(
249
				"SELECT EXISTS( SELECT 1 FROM $wpdb->comments WHERE comment_ID = %d )",
250
				$comment['comment_ID']
251
			)
252
		);
253
254
		if ( $exists ) {
255
			$wpdb->update( $wpdb->comments, $comment, array( 'comment_ID' => $comment['comment_ID'] ) );
256
		} else {
257
			$wpdb->insert( $wpdb->comments, $comment );
258
		}
259
260
		wp_update_comment_count( $comment['comment_post_ID'] );
261
	}
262
263
	public function trash_comment( $comment_id ) {
264
		wp_delete_comment( $comment_id );
265
	}
266
267
	public function delete_comment( $comment_id ) {
268
		wp_delete_comment( $comment_id, true );
269
	}
270
271
	public function spam_comment( $comment_id ) {
272
		wp_spam_comment( $comment_id );
273
	}
274
275
	public function trashed_post_comments( $post_id, $statuses ) {
276
		wp_trash_post_comments( $post_id );
277
	}
278
279
	public function untrashed_post_comments( $post_id ) {
280
		wp_untrash_post_comments( $post_id );
281
	}
282
283
	public function comments_checksum( $min_id = null, $max_id = null ) {
284
		global $wpdb;
285
		return $this->table_checksum( $wpdb->comments, Jetpack_Sync_Defaults::$default_comment_checksum_columns, 'comment_ID', Jetpack_Sync_Settings::get_comments_filter_sql(), $min_id, $max_id );
0 ignored issues
show
The property default_comment_checksum_columns cannot be accessed from this context as it is declared private in class Jetpack_Sync_Defaults.

This check looks for access to properties that are not accessible from the current context.

If you need to make a property accessible to another context you can either raise its visibility level or provide an accessible getter in the defining class.

Loading history...
286
	}
287
288
	public function comment_meta_checksum( $min_id = null, $max_id = null ) {
289
		global $wpdb;
290
		return $this->table_checksum( $wpdb->commentmeta, Jetpack_Sync_Defaults::$default_comment_meta_checksum_columns , 'meta_id', Jetpack_Sync_Settings::get_whitelisted_comment_meta_sql(), $min_id, $max_id );
0 ignored issues
show
The property default_comment_meta_checksum_columns cannot be accessed from this context as it is declared private in class Jetpack_Sync_Defaults.

This check looks for access to properties that are not accessible from the current context.

If you need to make a property accessible to another context you can either raise its visibility level or provide an accessible getter in the defining class.

Loading history...
291
	}
292
293
	public function options_checksum() {
294
		global $wpdb;
295
296
		$options_whitelist = "'" . implode( "', '", Jetpack_Sync_Defaults::$default_options_whitelist ) . "'";
297
		$where_sql = "option_name IN ( $options_whitelist )";
298
299
		return $this->table_checksum( $wpdb->options, Jetpack_Sync_Defaults::$default_option_checksum_columns, null, $where_sql, null, null );
300
	}
301
302
303
	public function update_option( $option, $value ) {
304
		return update_option( $option, $value );
305
	}
306
307
	public function get_option( $option, $default = false ) {
308
		return get_option( $option, $default );
309
	}
310
311
	public function delete_option( $option ) {
312
		return delete_option( $option );
313
	}
314
315
	public function set_theme_support( $theme_support ) {
316
		// noop
317
	}
318
319
	public function current_theme_supports( $feature ) {
320
		return current_theme_supports( $feature );
321
	}
322
323
	public function get_metadata( $type, $object_id, $meta_key = '', $single = false ) {
324
		return get_metadata( $type, $object_id, $meta_key, $single );
325
	}
326
327
	/**
328
	 *
329
	 * Stores remote meta key/values alongside an ID mapping key
330
	 *
331
	 * @param $type
332
	 * @param $object_id
333
	 * @param $meta_key
334
	 * @param $meta_value
335
	 * @param $meta_id
336
	 *
337
	 * @return bool
338
	 */
339
	public function upsert_metadata( $type, $object_id, $meta_key, $meta_value, $meta_id ) {
340
341
		$table = _get_meta_table( $type );
342
		if ( ! $table ) {
343
			return false;
344
		}
345
346
		global $wpdb;
347
348
		$exists = $wpdb->get_var( $wpdb->prepare(
349
			"SELECT EXISTS( SELECT 1 FROM $table WHERE meta_id = %d )",
350
			$meta_id
351
		) );
352
353
		if ( $exists ) {
354
			$wpdb->update( $table, array(
355
				'meta_key'   => $meta_key,
356
				'meta_value' => maybe_serialize( $meta_value ),
357
			), array( 'meta_id' => $meta_id ) );
358
		} else {
359
			$object_id_field = $type . '_id';
360
			$wpdb->insert( $table, array(
361
				'meta_id'        => $meta_id,
362
				$object_id_field => $object_id,
363
				'meta_key'       => $meta_key,
364
				'meta_value'     => maybe_serialize( $meta_value ),
365
			) );
366
		}
367
368
		wp_cache_delete( $object_id, $type . '_meta' );
369
370
		return true;
371
	}
372
373
	public function delete_metadata( $type, $object_id, $meta_ids ) {
374
		global $wpdb;
375
376
		$table = _get_meta_table( $type );
377
		if ( ! $table ) {
378
			return false;
379
		}
380
381
		foreach ( $meta_ids as $meta_id ) {
382
			$wpdb->query( $wpdb->prepare( "DELETE FROM $table WHERE meta_id = %d", $meta_id ) );
383
		}
384
385
		// if we don't have an object ID what do we do - invalidate ALL meta?
386
		if ( $object_id ) {
387
			wp_cache_delete( $object_id, $type . '_meta' );
388
		}
389
	}
390
391
	// constants
392
	public function get_constant( $constant ) {
393
		$value = get_option( 'jetpack_constant_' . $constant );
394
395
		if ( $value ) {
396
			return $value;
397
		}
398
399
		return null;
400
	}
401
402
	public function set_constant( $constant, $value ) {
403
		update_option( 'jetpack_constant_' . $constant, $value );
404
	}
405
406
	public function get_updates( $type ) {
407
		$all_updates = get_option( 'jetpack_updates', array() );
408
409
		if ( isset( $all_updates[ $type ] ) ) {
410
			return $all_updates[ $type ];
411
		} else {
412
			return null;
413
		}
414
	}
415
416
	public function set_updates( $type, $updates ) {
417
		$all_updates          = get_option( 'jetpack_updates', array() );
418
		$all_updates[ $type ] = $updates;
419
		update_option( 'jetpack_updates', $all_updates );
420
	}
421
422
	// functions
423
	public function get_callable( $name ) {
424
		$value = get_option( 'jetpack_' . $name );
425
426
		if ( $value ) {
427
			return $value;
428
		}
429
430
		return null;
431
	}
432
433
	public function set_callable( $name, $value ) {
434
		update_option( 'jetpack_' . $name, $value );
435
	}
436
437
	// network options
438
	public function get_site_option( $option ) {
439
		return get_option( 'jetpack_network_' . $option );
440
	}
441
442
	public function update_site_option( $option, $value ) {
443
		return update_option( 'jetpack_network_' . $option, $value );
444
	}
445
446
	public function delete_site_option( $option ) {
447
		return delete_option( 'jetpack_network_' . $option );
448
	}
449
450
	// terms
451
	// terms
452
	public function get_terms( $taxonomy ) {
453
		return get_terms( $taxonomy );
454
	}
455
456
	public function get_term( $taxonomy, $term_id, $is_term_id = true ) {
457
		$t = $this->ensure_taxonomy( $taxonomy );
458
		if ( ! $t || is_wp_error( $t ) ) {
459
			return $t;
460
		}
461
462
		return get_term( $term_id, $taxonomy );
463
	}
464
465
	private function ensure_taxonomy( $taxonomy ) {
466
		if ( ! taxonomy_exists( $taxonomy ) ) {
467
			// try re-registering synced taxonomies
468
			$taxonomies = $this->get_callable( 'taxonomies' );
469
			if ( ! isset( $taxonomies[ $taxonomy ] ) ) {
470
				// doesn't exist, or somehow hasn't been synced
471
				return new WP_Error( 'invalid_taxonomy', "The taxonomy '$taxonomy' doesn't exist" );
472
			}
473
			$t = $taxonomies[ $taxonomy ];
474
475
			return register_taxonomy(
476
				$taxonomy,
477
				$t->object_type,
478
				(array) $t
479
			);
480
		}
481
482
		return true;
483
	}
484
485
	public function get_the_terms( $object_id, $taxonomy ) {
486
		return get_the_terms( $object_id, $taxonomy );
487
	}
488
489
	public function update_term( $term_object ) {
490
		$taxonomy = $term_object->taxonomy;
491
		global $wpdb;
492
		$exists = $wpdb->get_var( $wpdb->prepare(
493
			"SELECT EXISTS( SELECT 1 FROM $wpdb->terms WHERE term_id = %d )",
494
			$term_object->term_id
495
		) );
496
		if ( ! $exists ) {
497
			$term_object   = sanitize_term( clone( $term_object ), $taxonomy, 'db' );
498
			$term          = array(
499
				'term_id'    => $term_object->term_id,
500
				'name'       => $term_object->name,
501
				'slug'       => $term_object->slug,
502
				'term_group' => $term_object->term_group,
503
			);
504
			$term_taxonomy = array(
505
				'term_taxonomy_id' => $term_object->term_taxonomy_id,
506
				'term_id'          => $term_object->term_id,
507
				'taxonomy'         => $term_object->taxonomy,
508
				'description'      => $term_object->description,
509
				'parent'           => (int) $term_object->parent,
510
				'count'            => (int) $term_object->count,
511
			);
512
			$wpdb->insert( $wpdb->terms, $term );
513
			$wpdb->insert( $wpdb->term_taxonomy, $term_taxonomy );
514
515
			return true;
516
		}
517
518
		return wp_update_term( $term_object->term_id, $taxonomy, (array) $term_object );
519
	}
520
521
	public function delete_term( $term_id, $taxonomy ) {
522
		return wp_delete_term( $term_id, $taxonomy );
523
	}
524
525
	public function update_object_terms( $object_id, $taxonomy, $terms, $append ) {
526
		wp_set_object_terms( $object_id, $terms, $taxonomy, $append );
527
	}
528
529
	public function delete_object_terms( $object_id, $tt_ids ) {
530
		global $wpdb;
531
532
		if ( is_array( $tt_ids ) && ! empty( $tt_ids ) ) {
533
			$taxonomies = array();
534
			foreach ( $tt_ids as $tt_id ) {
535
				$term                            = get_term_by( 'term_taxonomy_id', $tt_id );
536
				$taxonomies[ $term->taxonomy ][] = $tt_id;
537
			}
538
			$in_tt_ids = "'" . implode( "', '", $tt_ids ) . "'";
539
540
			/**
541
			 * Fires immediately before an object-term relationship is deleted.
542
			 *
543
			 * @since 2.9.0
544
			 *
545
			 * @param int $object_id Object ID.
546
			 * @param array $tt_ids An array of term taxonomy IDs.
547
			 */
548
			do_action( 'delete_term_relationships', $object_id, $tt_ids );
549
			$deleted = $wpdb->query( $wpdb->prepare( "DELETE FROM $wpdb->term_relationships WHERE object_id = %d AND term_taxonomy_id IN ($in_tt_ids)", $object_id ) );
550
			foreach ( $taxonomies as $taxonomy => $taxonomy_tt_ids ) {
551
				wp_cache_delete( $object_id, $taxonomy . '_relationships' );
552
				/**
553
				 * Fires immediately after an object-term relationship is deleted.
554
				 *
555
				 * @since 2.9.0
556
				 *
557
				 * @param int $object_id Object ID.
558
				 * @param array $tt_ids An array of term taxonomy IDs.
559
				 */
560
				do_action( 'deleted_term_relationships', $object_id, $taxonomy_tt_ids );
561
				wp_update_term_count( $taxonomy_tt_ids, $taxonomy );
562
			}
563
564
			return (bool) $deleted;
565
		}
566
567
		return false;
568
	}
569
570
	// users
571
	public function user_count() {
572
573
	}
574
575
	public function get_user( $user_id ) {
576
		return WP_User::get_instance( $user_id );
577
	}
578
579
	public function upsert_user( $user ) {
580
		$this->invalid_call();
581
	}
582
583
	public function delete_user( $user_id ) {
584
		$this->invalid_call();
585
	}
586
587
	public function get_allowed_mime_types( $user_id ) {
588
589
	}
590
591
	public function checksum_all() {
592
		$post_meta_checksum = $this->checksum_histogram( 'post_meta', 1 );
593
		$comment_meta_checksum = $this->checksum_histogram( 'comment_meta', 1 );
594
595
		return array(
596
			'posts'    => $this->posts_checksum(),
597
			'comments' => $this->comments_checksum(),
598
			'post_meta'=> reset( $post_meta_checksum ),
599
			'comment_meta'=> reset( $comment_meta_checksum ),
600
		);
601
	}
602
603
	function checksum_histogram( $object_type, $buckets, $start_id = null, $end_id = null, $columns = null, $strip_non_ascii = true ) {
604
		global $wpdb;
605
606
		$wpdb->queries = array();
607
608
		switch( $object_type ) {
609
			case "posts":
610
				$object_count = $this->post_count( null, $start_id, $end_id );
611
				$object_table = $wpdb->posts;
612
				$id_field     = 'ID';
613
				$where_sql    = Jetpack_Sync_Settings::get_blacklisted_post_types_sql();
614
				if ( empty( $columns ) ) {
615
					$columns  = Jetpack_Sync_Defaults::$default_post_checksum_columns;
616
				}
617
				break;
618 View Code Duplication
			case "post_meta":
619
				$object_table = $wpdb->postmeta;
620
				$where_sql    = Jetpack_Sync_Settings::get_whitelisted_post_meta_sql();
621
				$object_count = $this->meta_count( $object_table, $where_sql, $start_id, $end_id );
622
				$id_field     = 'meta_id';
623
				
624
				if ( empty( $columns ) ) {
625
					$columns  = Jetpack_Sync_Defaults::$default_post_meta_checksum_columns;
0 ignored issues
show
The property default_post_meta_checksum_columns cannot be accessed from this context as it is declared private in class Jetpack_Sync_Defaults.

This check looks for access to properties that are not accessible from the current context.

If you need to make a property accessible to another context you can either raise its visibility level or provide an accessible getter in the defining class.

Loading history...
Equals sign not aligned correctly; expected 1 space but found 2 spaces

This check looks for improperly formatted assignments.

Every assignment must have exactly one space before and one space after the equals operator.

To illustrate:

$a = "a";
$ab = "ab";
$abc = "abc";

will have no issues, while

$a   = "a";
$ab  = "ab";
$abc = "abc";

will report issues in lines 1 and 2.

Loading history...
626
				}
627
				break;
628
			case "comments":
629
				$object_count = $this->comment_count( null, $start_id, $end_id );
630
				$object_table = $wpdb->comments;
631
				$id_field     = 'comment_ID';
632
				$where_sql    = Jetpack_Sync_Settings::get_comments_filter_sql();
633
				if ( empty( $columns ) ) {
634
					$columns  = Jetpack_Sync_Defaults::$default_comment_checksum_columns;
635
				}
636
				break;
637 View Code Duplication
			case "comment_meta":
638
				$object_table = $wpdb->commentmeta;
639
				$where_sql    = Jetpack_Sync_Settings::get_whitelisted_comment_meta_sql();
640
				$object_count = $this->meta_count( $object_table, $where_sql, $start_id, $end_id );
641
				$id_field     = 'meta_id';
642
				if ( empty( $columns ) ) {
643
					$columns  = Jetpack_Sync_Defaults::$default_post_meta_checksum_columns;
0 ignored issues
show
The property default_post_meta_checksum_columns cannot be accessed from this context as it is declared private in class Jetpack_Sync_Defaults.

This check looks for access to properties that are not accessible from the current context.

If you need to make a property accessible to another context you can either raise its visibility level or provide an accessible getter in the defining class.

Loading history...
Equals sign not aligned correctly; expected 1 space but found 2 spaces

This check looks for improperly formatted assignments.

Every assignment must have exactly one space before and one space after the equals operator.

To illustrate:

$a = "a";
$ab = "ab";
$abc = "abc";

will have no issues, while

$a   = "a";
$ab  = "ab";
$abc = "abc";

will report issues in lines 1 and 2.

Loading history...
644
				}
645
				break;
646
			default:
647
				return false;
648
		}
649
650
		$bucket_size  = intval( ceil( $object_count / $buckets ) );
651
		$previous_max_id = 0;
652
		$histogram    = array();
653
654
		$where = '1=1';
655
656
		if ( $start_id ) {
657
			$where .= " AND $id_field >= " . intval( $start_id );
658
		}
659
660
		if ( $end_id ) {
661
			$where .= " AND $id_field <= " . intval( $end_id );
662
		}
663
664
		do {
665
			list( $first_id, $last_id ) = $wpdb->get_row(
666
				"SELECT MIN($id_field) as min_id, MAX($id_field) as max_id FROM ( SELECT $id_field FROM $object_table WHERE $where AND $id_field > $previous_max_id ORDER BY $id_field ASC LIMIT $bucket_size ) as ids",
667
				ARRAY_N
668
			);
669
670
			// get the checksum value
671
			$value = $this->table_checksum( $object_table, $columns, $id_field, $where_sql, $first_id, $last_id, $strip_non_ascii );
672
673
			if ( is_wp_error( $value ) ) {
674
				return $value;
675
			}
676
677
			if ( $first_id === null || $last_id === null ) {
678
				break;
679
			} elseif ( $first_id === $last_id ) {
680
				$histogram[ $first_id ] = $value;
681
			} else {
682
				$histogram[ "{$first_id}-{$last_id}" ] = $value;
683
			}
684
685
			$previous_max_id = $last_id;
686
		} while ( true );
687
688
		return $histogram;
689
	}
690
691
	private function table_checksum( $table, $columns, $id_column, $where_sql = '1=1', $min_id = null, $max_id = null, $strip_non_ascii = true ) {
692
		global $wpdb;
693
694
		// sanitize to just valid MySQL column names
695
		$sanitized_columns = preg_grep ( '/^[0-9,a-z,A-Z$_]+$/i', $columns );
696
697
		if ( $strip_non_ascii ) {
698
			$columns_sql = implode( ',', array_map( array( $this, 'strip_non_ascii_sql' ), $sanitized_columns ) );
699
		} else {
700
			$columns_sql = implode( ',', $sanitized_columns );
701
		}
702
703
		if ( $min_id !== null ) {
704
			$min_id = intval( $min_id );
705
			$where_sql .= " AND $id_column >= $min_id";
706
		}
707
708
		if ( $max_id !== null ) {
709
			$max_id = intval( $max_id );
710
			$where_sql .= " AND $id_column <= $max_id";
711
		}
712
713
		$query = <<<ENDSQL
714
			SELECT CONV(BIT_XOR(CRC32(CONCAT({$columns_sql}))), 10, 16)
715
				FROM $table
716
				WHERE $where_sql
717
ENDSQL;
718
		$result = $wpdb->get_var( $query );
719
720
		if ( $wpdb->last_error ) {
721
			return new WP_Error( 'database_error', $wpdb->last_error );
722
		}
723
724
		return $result;
725
726
	}
727
728
	private function meta_count( $table, $where_sql, $min_id, $max_id ) {
729
		global $wpdb;
730
731
		if ( $min_id != null ) {
732
			$where_sql .= ' AND meta_id >= ' . intval( $min_id );
733
		}
734
735
		if ( $max_id != null ) {
736
			$where_sql .= ' AND meta_id <= ' . intval( $max_id );
737
		}
738
739
		return $wpdb->get_var( "SELECT COUNT(*) FROM $table WHERE $where_sql" );
740
	}
741
742
	/**
743
	 * Wraps a column name in SQL which strips non-ASCII chars.
744
	 * This helps normalize data to avoid checksum differences caused by
745
	 * badly encoded data in the DB
746
	 */
747
	function strip_non_ascii_sql( $column_name ) {
748
		return "REPLACE( CONVERT( $column_name USING ascii ), '?', '' )";
749
	}
750
751
	private function invalid_call() {
752
		$backtrace = debug_backtrace();
753
		$caller    = $backtrace[1]['function'];
754
		throw new Exception( "This function $caller is not supported on the WP Replicastore" );
755
	}
756
}
757