Completed
Push — add/sso-analytics ( 683a91...e67d7d )
by
unknown
162:06 queued 152:34
created

Jetpack_Sync_WP_Replicastore::set_callable()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 2

Duplication

Lines 0
Ratio 0 %
Metric Value
cc 1
eloc 2
nc 1
nop 2
dl 0
loc 3
rs 10
1
<?php
2
3
require_once 'interface.jetpack-sync-replicastore.php';
4
5
/**
6
 * An implementation of iJetpack_Sync_Replicastore which returns data stored in a WordPress.org DB.
7
 * This is useful to compare values in the local WP DB to values in the synced replica store
8
 */
9
class Jetpack_Sync_WP_Replicastore implements iJetpack_Sync_Replicastore {
10
	public function set_wp_version( $version ) {
11
		// makes no sense here?
12
	}
13
14
	public function get_wp_version() {
15
		global $wp_version;
16
17
		return $wp_version;
18
	}
19
20
	public function reset() {
21
		global $wpdb;
22
23
		$wpdb->query( "DELETE FROM $wpdb->posts" );
24
		$wpdb->query( "DELETE FROM $wpdb->comments" );
25
26
		// also need to delete terms from cache
27
		$term_ids = $wpdb->get_col( "SELECT term_id FROM $wpdb->terms" );
28
		foreach ( $term_ids as $term_id ) {
29
			wp_cache_delete( $term_id, 'terms' );
30
		}
31
32
		$wpdb->query( "DELETE FROM $wpdb->terms" );
33
34
		$wpdb->query( "DELETE FROM $wpdb->term_taxonomy" );
35
		$wpdb->query( "DELETE FROM $wpdb->term_relationships" );
36
37
		// callables and constants
38
		$wpdb->query( "DELETE FROM $wpdb->options WHERE option_name LIKE 'jetpack_%'" );
39
		$wpdb->query( "DELETE FROM $wpdb->postmeta WHERE meta_key NOT LIKE '\_%'" );
40
	}
41
42
	function full_sync_start() {
43
		$this->reset();
44
	}
45
46
	function full_sync_end( $checksum ) {
47
		// noop right now
48
	}
49
50
	public function post_count( $status = null ) {
51
		return count( $this->get_posts( $status ) );
52
	}
53
54
	public function get_posts( $status = null ) {
55
		$args = array( 'orderby' => 'ID' );
56
57
		if ( $status ) {
58
			$args['post_status'] = $status;
59
		} else {
60
			$args['post_status'] = 'any';
61
		}
62
63
		return get_posts( $args );
64
	}
65
66
	public function get_post( $id ) {
67
		return get_post( $id );
68
	}
69
70
	public function upsert_post( $post, $silent = false ) {
71
		global $wpdb;
72
73
		// reject the post if it's not a WP_Post
74
		if ( ! $post instanceof WP_Post ) {
0 ignored issues
show
Bug introduced by
The class WP_Post does not exist. Did you forget a USE statement, or did you not list all dependencies?

This error could be the result of:

1. Missing dependencies

PHP Analyzer uses your composer.json file (if available) to determine the dependencies of your project and to determine all the available classes and functions. It expects the composer.json to be in the root folder of your repository.

Are you sure this class is defined by one of your dependencies, or did you maybe not list a dependency in either the require or require-dev section?

2. Missing use statement

PHP does not complain about undefined classes in ìnstanceof checks. For example, the following PHP code will work perfectly fine:

if ($x instanceof DoesNotExist) {
    // Do something.
}

If you have not tested against this specific condition, such errors might go unnoticed.

Loading history...
75
			return;
76
		}
77
78
		$post = $post->to_array();
79
80
		// reject posts without an ID
81
		if ( ! isset( $post['ID'] ) ) {
82
			return;
83
		}
84
85
		$now     = current_time( 'mysql' );
86
		$now_gmt = get_gmt_from_date( $now );
87
88
		$defaults = array(
89
			'ID'                    => 0,
90
			'post_author'           => '0',
91
			'post_content'          => '',
92
			'post_content_filtered' => '',
93
			'post_title'            => '',
94
			'post_name'             => '',
95
			'post_excerpt'          => '',
96
			'post_status'           => 'draft',
97
			'post_type'             => 'post',
98
			'comment_status'        => 'closed',
99
			'comment_count'         => '0',
100
			'ping_status'           => '',
101
			'post_password'         => '',
102
			'to_ping'               => '',
103
			'pinged'                => '',
104
			'post_parent'           => 0,
105
			'menu_order'            => 0,
106
			'guid'                  => '',
107
			'post_date'             => $now,
108
			'post_date_gmt'         => $now_gmt,
109
			'post_modified'         => $now,
110
			'post_modified_gmt'     => $now_gmt,
111
		);
112
113
		$post = array_intersect_key( $post, $defaults );
114
115
		$post = sanitize_post( $post, 'db' );
116
117
		unset( $post['filter'] );
118
119
		$exists = $wpdb->get_var( $wpdb->prepare( "SELECT EXISTS( SELECT 1 FROM $wpdb->posts WHERE ID = %d )", $post['ID'] ) );
120
121
		if ( $exists ) {
122
			$wpdb->update( $wpdb->posts, $post, array( 'ID' => $post['ID'] ) );
123
		} else {
124
			$wpdb->insert( $wpdb->posts, $post );
125
		}
126
127
		clean_post_cache( $post['ID'] );
128
	}
129
130
	public function delete_post( $post_id ) {
131
		wp_delete_post( $post_id, true );
132
	}
133
134
	public function posts_checksum() {
135
		global $wpdb;
136
137
		$post_type_sql = Jetpack_Sync_Defaults::get_blacklisted_post_types_sql();
138
139
		$query = <<<ENDSQL
140
			SELECT CONV(BIT_XOR(CRC32(CONCAT(ID,post_modified))), 10, 16) 
141
				FROM $wpdb->posts
142
				WHERE $post_type_sql
143
ENDSQL;
144
145
		return $wpdb->get_var( $query );
146
	}
147
148
	public function comment_count( $status = null ) {
149
		global $wpdb;
150
151
		$comment_approved = $this->comment_status_to_approval_value( $status );
152
153
		if ( $comment_approved !== false ) {
154
			return $wpdb->get_var( $wpdb->prepare(
155
				"SELECT COUNT(*) FROM $wpdb->comments WHERE comment_approved = %s",
156
				$comment_approved
157
			) );
158
		} else {
159
			return $wpdb->get_var( "SELECT COUNT(*) FROM $wpdb->comments" );
160
		}
161
	}
162
163
	private function comment_status_to_approval_value( $status ) {
164
		switch ( $status ) {
165
			case 'approve':
166
				return "1";
167
			case 'hold':
168
				return "0";
169
			case 'spam':
170
				return 'spam';
171
			case 'trash':
172
				return 'trash';
173
			case 'any':
174
				return false;
175
			case 'all':
176
				return false;
177
			default:
178
				return false;
179
		}
180
	}
181
182
	public function get_comments( $status = null ) {
183
		$args = array( 'orderby' => 'ID', 'status' => 'all' );
184
185
		if ( $status ) {
186
			$args['status'] = $status;
187
		}
188
189
		return get_comments( $args );
190
	}
191
192
	public function get_comment( $id ) {
193
		return WP_Comment::get_instance( $id );
194
	}
195
196
	public function upsert_comment( $comment ) {
197
		global $wpdb, $wp_version;
198
199
		if ( version_compare( $wp_version, '4.4', '<' ) ) {
200
			$comment = (array) $comment;
201
		} else {
202
			// WP 4.4 introduced the WP_Comment Class
203
			$comment = $comment->to_array();
204
		}
205
206
		// filter by fields on comment table
207
		$comment_fields_whitelist = array(
208
			'comment_ID',
209
			'comment_post_ID',
210
			'comment_author',
211
			'comment_author_email',
212
			'comment_author_url',
213
			'comment_author_IP',
214
			'comment_date',
215
			'comment_date_gmt',
216
			'comment_content',
217
			'comment_karma',
218
			'comment_approved',
219
			'comment_agent',
220
			'comment_type',
221
			'comment_parent',
222
			'user_id'
223
		);
224
225
		foreach ( $comment as $key => $value ) {
226
			if ( ! in_array( $key, $comment_fields_whitelist ) ) {
227
				unset( $comment[ $key ] );
228
			}
229
		}
230
231
		$exists = $wpdb->get_var(
232
			$wpdb->prepare(
233
				"SELECT EXISTS( SELECT 1 FROM $wpdb->comments WHERE comment_ID = %d )",
234
				$comment['comment_ID']
235
			)
236
		);
237
238
		if ( $exists ) {
239
			$wpdb->update( $wpdb->comments, $comment, array( 'comment_ID' => $comment['comment_ID'] ) );
240
		} else {
241
			$wpdb->insert( $wpdb->comments, $comment );
242
		}
243
244
		wp_update_comment_count( $comment['comment_post_ID'] );
245
	}
246
247
	public function trash_comment( $comment_id ) {
248
		wp_delete_comment( $comment_id );
249
	}
250
251
	public function delete_comment( $comment_id ) {
252
		wp_delete_comment( $comment_id, true );
253
	}
254
255
	public function spam_comment( $comment_id ) {
256
		wp_spam_comment( $comment_id );
257
	}
258
259
	public function comments_checksum() {
260
		global $wpdb;
261
262
		$query = <<<ENDSQL
263
			SELECT CONV(BIT_XOR(CRC32(CONCAT(comment_ID,comment_content))), 10, 16) FROM $wpdb->comments
264
ENDSQL;
265
266
		return $wpdb->get_var( $query );
267
	}
268
269
	public function update_option( $option, $value ) {
270
		return update_option( $option, $value );
271
	}
272
273
	public function get_option( $option ) {
274
		return get_option( $option );
275
	}
276
277
	public function delete_option( $option ) {
278
		return delete_option( $option );
279
	}
280
281
	public function set_theme_support( $theme_support ) {
282
		// noop
283
	}
284
285
	public function current_theme_supports( $feature ) {
286
		return current_theme_supports( $feature );
287
	}
288
289
	public function get_metadata( $type, $object_id, $meta_key = '', $single = false ) {
290
		return get_metadata( $type, $object_id, $meta_key, $single );
291
	}
292
293
	/**
294
	 *
295
	 * Stores remote meta key/values alongside an ID mapping key
296
	 *
297
	 * @param $type
298
	 * @param $object_id
299
	 * @param $meta_key
300
	 * @param $meta_value
301
	 * @param $meta_id
302
	 *
303
	 * @return bool
304
	 */
305
	public function upsert_metadata( $type, $object_id, $meta_key, $meta_value, $meta_id ) {
306
307
		$table = _get_meta_table( $type );
308
		if ( ! $table ) {
309
			return false;
310
		}
311
312
		global $wpdb;
313
314
		$exists = $wpdb->get_var( $wpdb->prepare(
315
			"SELECT EXISTS( SELECT 1 FROM $table WHERE meta_id = %d )",
316
			$meta_id
317
		) );
318
319
		if ( $exists ) {
320
			$wpdb->update( $table, array( 'meta_key'   => $meta_key,
321
			                              'meta_value' => serialize( $meta_value )
322
			), array( 'meta_id' => $meta_id ) );
323
		} else {
324
			$object_id_field = $type . '_id';
325
			$wpdb->insert( $table, array( 'meta_id'        => $meta_id,
326
			                              $object_id_field => $object_id,
327
			                              'meta_key'       => $meta_key,
328
			                              'meta_value'     => serialize( $meta_value )
329
			) );
330
		}
331
332
		wp_cache_delete( $object_id, $type . '_meta' );
333
334
		return true;
335
	}
336
337
	public function delete_metadata( $type, $object_id, $meta_ids ) {
338
		global $wpdb;
339
340
		$table = _get_meta_table( $type );
341
		if ( ! $table ) {
342
			return false;
343
		}
344
345
		foreach ( $meta_ids as $meta_id ) {
346
			$wpdb->query( $wpdb->prepare( "DELETE FROM $table WHERE meta_id = %d", $meta_id ) );
347
		}
348
349
		// if we don't have an object ID what do we do - invalidate ALL meta?
350
		if ( $object_id ) {
351
			wp_cache_delete( $object_id, $type . '_meta' );
352
		}
353
	}
354
355
	// constants
356
	public function get_constant( $constant ) {
357
		$value = get_option( 'jetpack_constant_' . $constant );
358
359
		if ( $value ) {
360
			return $value;
361
		}
362
363
		return null;
364
	}
365
366
	public function set_constants( $constants ) {
367
		global $wpdb;
368
369
		$wpdb->query( "DELETE FROM $wpdb->options WHERE option_name LIKE 'jetpack_constant_%'" );
370
371
		foreach ( $constants as $key => $value ) {
372
			update_option( 'jetpack_constant_' . $key, $value );
373
		}
374
	}
375
376
	public function get_updates( $type ) {
377
		$all_updates = get_option( 'jetpack_updates', array() );
378
379
		if ( isset( $all_updates[ $type ] ) ) {
380
			return $all_updates[ $type ];
381
		} else {
382
			return null;
383
		}
384
	}
385
386
	public function set_updates( $type, $updates ) {
387
		$all_updates          = get_option( 'jetpack_updates', array() );
388
		$all_updates[ $type ] = $updates;
389
		update_option( 'jetpack_updates', $all_updates );
390
	}
391
392
	// functions
393
	public function get_callable( $name ) {
394
		$value = get_option( 'jetpack_' . $name );
395
396
		if ( $value ) {
397
			return $value;
398
		}
399
400
		return null;
401
	}
402
403
	public function set_callable( $name, $value ) {
404
		update_option( 'jetpack_' . $name, $value );
405
	}
406
407
	// network options
408
	public function get_site_option( $option ) {
409
		return get_option( 'jetpack_network_' . $option );
410
	}
411
412
	public function update_site_option( $option, $value ) {
413
		return update_option( 'jetpack_network_' . $option, $value );
414
	}
415
416
	public function delete_site_option( $option ) {
417
		return delete_option( 'jetpack_network_' . $option );
418
	}
419
420
	// terms
421
	// terms
422
	public function get_terms( $taxonomy ) {
423
		return get_terms( $taxonomy );
424
	}
425
426
	public function get_term( $taxonomy, $term_id, $is_term_id = true ) {
427
		$t = $this->ensure_taxonomy( $taxonomy );
428
		if ( ! $t || is_wp_error( $t ) ) {
429
			return $t;
430
		}
431
432
		return get_term( $term_id, $taxonomy );
433
	}
434
435
	private function ensure_taxonomy( $taxonomy ) {
436
		if ( ! taxonomy_exists( $taxonomy ) ) {
437
			// try re-registering synced taxonomies
438
			$taxonomies = $this->get_callable( 'taxonomies' );
439
			if ( ! isset( $taxonomies[ $taxonomy ] ) ) {
440
				// doesn't exist, or somehow hasn't been synced
441
				return new WP_Error( 'invalid_taxonomy', "The taxonomy '$taxonomy' doesn't exist" );
442
			}
443
			$t = $taxonomies[ $taxonomy ];
444
445
			return register_taxonomy(
446
				$taxonomy,
447
				$t->object_type,
448
				(array) $t
449
			);
450
		}
451
452
		return true;
453
	}
454
455
	public function get_the_terms( $object_id, $taxonomy ) {
456
		return get_the_terms( $object_id, $taxonomy );
457
	}
458
459
	public function update_term( $term_object ) {
460
		$taxonomy = $term_object->taxonomy;
461
		global $wpdb;
462
		$exists = $wpdb->get_var( $wpdb->prepare(
463
			"SELECT EXISTS( SELECT 1 FROM $wpdb->terms WHERE term_id = %d )",
464
			$term_object->term_id
465
		) );
466
		if ( ! $exists ) {
467
			$term_object   = sanitize_term( clone( $term_object ), $taxonomy, 'db' );
468
			$term          = array(
469
				'term_id'    => $term_object->term_id,
470
				'name'       => $term_object->name,
471
				'slug'       => $term_object->slug,
472
				'term_group' => $term_object->term_group,
473
			);
474
			$term_taxonomy = array(
475
				'term_taxonomy_id' => $term_object->term_taxonomy_id,
476
				'term_id'          => $term_object->term_id,
477
				'taxonomy'         => $term_object->taxonomy,
478
				'description'      => $term_object->description,
479
				'parent'           => (int) $term_object->parent,
480
				'count'            => (int) $term_object->count,
481
			);
482
			$wpdb->insert( $wpdb->terms, $term );
483
			$wpdb->insert( $wpdb->term_taxonomy, $term_taxonomy );
484
485
//			clean_term_cache( $term_object->term_id, $taxonomy );
486
487
			return true;
488
		}
489
490
		return wp_update_term( $term_object->term_id, $taxonomy, (array) $term_object );
491
	}
492
493
	public function delete_term( $term_id, $taxonomy ) {
494
		return wp_delete_term( $term_id, $taxonomy );
495
	}
496
497
	public function update_object_terms( $object_id, $taxonomy, $terms, $append ) {
498
		wp_set_object_terms( $object_id, $terms, $taxonomy, $append );
499
	}
500
501
	public function delete_object_terms( $object_id, $tt_ids ) {
502
		global $wpdb;
503
504
		if ( is_array( $tt_ids ) && ! empty( $tt_ids ) ) {
505
			$taxonomies = array();
506
			foreach ( $tt_ids as $tt_id ) {
507
				$term                            = get_term_by( 'term_taxonomy_id', $tt_id );
508
				$taxonomies[ $term->taxonomy ][] = $tt_id;
509
			}
510
			$in_tt_ids = "'" . implode( "', '", $tt_ids ) . "'";
511
512
			/**
513
			 * Fires immediately before an object-term relationship is deleted.
514
			 *
515
			 * @since 2.9.0
516
			 *
517
			 * @param int $object_id Object ID.
518
			 * @param array $tt_ids An array of term taxonomy IDs.
519
			 */
520
			do_action( 'delete_term_relationships', $object_id, $tt_ids );
521
			$deleted = $wpdb->query( $wpdb->prepare( "DELETE FROM $wpdb->term_relationships WHERE object_id = %d AND term_taxonomy_id IN ($in_tt_ids)", $object_id ) );
522
			foreach ( $taxonomies as $taxonomy => $taxonomy_tt_ids ) {
523
				wp_cache_delete( $object_id, $taxonomy . '_relationships' );
524
				/**
525
				 * Fires immediately after an object-term relationship is deleted.
526
				 *
527
				 * @since 2.9.0
528
				 *
529
				 * @param int $object_id Object ID.
530
				 * @param array $tt_ids An array of term taxonomy IDs.
531
				 */
532
				do_action( 'deleted_term_relationships', $object_id, $taxonomy_tt_ids );
533
				wp_update_term_count( $taxonomy_tt_ids, $taxonomy );
534
			}
535
536
			return (bool) $deleted;
537
		}
538
539
		return false;
540
	}
541
542
	// users
543
	public function user_count() {
544
545
	}
546
547
	public function get_user( $user_id ) {
548
		return WP_User::get_instance( $user_id );
549
	}
550
551
	public function upsert_user( $user ) {
552
		$this->invalid_call();
553
	}
554
555
	public function delete_user( $user_id ) {
556
		$this->invalid_call();
557
	}
558
559
	public function checksum_all() {
560
		return array(
561
			'posts'    => $this->posts_checksum(),
562
			'comments' => $this->comments_checksum()
563
		);
564
	}
565
566
	private function invalid_call() {
567
		$backtrace = debug_backtrace();
568
		$caller    = $backtrace[1]['function'];
569
		throw new Exception( "This function $caller is not supported on the WP Replicastore" );
570
	}
571
}
572