1
|
|
|
<?php |
2
|
|
|
|
3
|
|
|
use Automattic\Jetpack\Sync\Replicastore; |
4
|
|
|
|
5
|
|
View Code Duplication |
if ( defined( 'IS_WPCOM' ) && IS_WPCOM ) { |
6
|
|
|
require_once ABSPATH . 'wp-content/mu-plugins/jetpack/sync/class.jetpack-sync-test-object-factory.php'; |
7
|
|
|
} else { |
8
|
|
|
// is running in jetpack |
9
|
|
|
require_once dirname( __FILE__ ) . '/server/class.jetpack-sync-test-object-factory.php'; |
10
|
|
|
} |
11
|
|
|
|
12
|
|
|
/* |
13
|
|
|
* Tests all known implementations of the replicastore |
14
|
|
|
*/ |
15
|
|
|
|
16
|
|
|
class WP_Test_iJetpack_Sync_Replicastore extends PHPUnit_Framework_TestCase { |
17
|
|
|
/** @var JetpackSyncTestObjectFactory $factory */ |
18
|
|
|
static $factory; |
19
|
|
|
static $token; |
20
|
|
|
static $all_replicastores; |
21
|
|
|
|
22
|
|
|
public static function setUpBeforeClass() { |
23
|
|
|
parent::setUpBeforeClass(); |
24
|
|
|
|
25
|
|
|
self::$token = (object) array( |
26
|
|
|
'blog_id' => 101881278, //newsite16.goldsounds.com |
27
|
|
|
'user_id' => 282285, //goldsounds |
28
|
|
|
'external_user_id' => 2, |
29
|
|
|
'role' => 'administrator' |
30
|
|
|
); |
31
|
|
|
|
32
|
|
|
self::$factory = new JetpackSyncTestObjectFactory(); |
33
|
|
|
} |
34
|
|
|
|
35
|
|
|
public function setUp() { |
36
|
|
|
parent::setUp(); |
37
|
|
|
|
38
|
|
|
if ( defined( 'IS_WPCOM' ) && IS_WPCOM ) { |
39
|
|
|
switch_to_blog( self::$token->blog_id ); |
40
|
|
|
} |
41
|
|
|
|
42
|
|
|
// this is a hack so that our setUp method can access the $store instance and call reset() |
43
|
|
|
$prop = new ReflectionProperty( 'PHPUnit_Framework_TestCase', 'data' ); |
44
|
|
|
$prop->setAccessible( true ); |
45
|
|
|
$test_data = $prop->getValue( $this ); |
46
|
|
|
|
47
|
|
|
if ( isset( $test_data[0] ) && $test_data[0] ) { |
48
|
|
|
$store = $test_data[0]; |
49
|
|
|
$store->reset(); |
50
|
|
|
} |
51
|
|
|
} |
52
|
|
|
|
53
|
|
|
public function tearDown() { |
54
|
|
|
parent::tearDown(); |
55
|
|
|
|
56
|
|
|
if ( defined( 'IS_WPCOM' ) && IS_WPCOM ) { |
57
|
|
|
restore_current_blog(); |
58
|
|
|
} |
59
|
|
|
} |
60
|
|
|
|
61
|
|
|
/** |
62
|
|
|
* Test that the checksum values between implementations are the same |
63
|
|
|
*/ |
64
|
|
|
function test_all_checksums_match() { |
65
|
|
|
$this->markTestSkipped( 'Not a Valid E2E test.' ); |
66
|
|
|
$post = self::$factory->post( 5 ); |
67
|
|
|
$second_post = self::$factory->post( 10 ); |
68
|
|
|
$comment = self::$factory->comment( 3, $post->ID ); |
69
|
|
|
$second_comment = self::$factory->comment( 6, $second_post->ID ); |
70
|
|
|
|
71
|
|
|
// create an instance of each type of replicastore |
72
|
|
|
$all_replicastores = array(); |
73
|
|
|
foreach ( get_declared_classes() as $className ) { |
74
|
|
|
if ( in_array( 'Automattic\\Jetpack\\Sync\\Replicastore_Interface', class_implements( $className ) ) ) { |
75
|
|
|
if ( method_exists( $className, 'getInstance' ) ) { |
76
|
|
|
$all_replicastores[] = call_user_func( array( $className, 'getInstance' ) ); |
77
|
|
|
} else { |
78
|
|
|
$all_replicastores[] = new $className(); |
79
|
|
|
} |
80
|
|
|
} |
81
|
|
|
} |
82
|
|
|
|
83
|
|
|
// insert the same data into all of them |
84
|
|
|
foreach ( $all_replicastores as $replicastore ) { |
85
|
|
|
$replicastore->upsert_post( $post ); |
86
|
|
|
$replicastore->upsert_metadata( 'post', $post->ID, 'imagedata', 'bar', 1 ); |
87
|
|
|
$replicastore->upsert_metadata( 'post', $post->ID, 'publicize_results', 'baz', 2 ); |
88
|
|
|
$replicastore->upsert_post( $second_post ); |
89
|
|
|
$replicastore->upsert_metadata( 'post', $second_post->ID, 'imagedata', 'bar', 5 ); |
90
|
|
|
$replicastore->upsert_metadata( 'post', $second_post->ID, 'publicize_results', 'baz', 10 ); |
91
|
|
|
$replicastore->upsert_comment( $comment ); |
92
|
|
|
$replicastore->upsert_metadata( 'comment', $comment->comment_ID, 'hc_avatar', 'bar', 1 ); |
93
|
|
|
$replicastore->upsert_metadata( 'comment', $comment->comment_ID, 'hc_post_as', 'baz', 4 ); |
94
|
|
|
$replicastore->upsert_comment( $second_comment ); |
95
|
|
|
$replicastore->upsert_metadata( 'comment', $second_comment->comment_ID, 'hc_avatar', 'boo', 7 ); |
96
|
|
|
$replicastore->upsert_metadata( 'comment', $second_comment->comment_ID, 'hc_post_as', 'bee', 10 ); |
97
|
|
|
} |
98
|
|
|
|
99
|
|
|
// ensure the checksums are the same |
100
|
|
|
$checksums = array_map( array( $this, 'get_all_checksums' ), $all_replicastores ); |
101
|
|
|
|
102
|
|
|
// for helpful debug output in case they don't match |
103
|
|
|
$labelled_checksums = array_combine( array_map( 'get_class', $all_replicastores ), $checksums ); |
104
|
|
|
|
105
|
|
|
// find unique checksums - if all checksums are the same, there should be only one element |
106
|
|
|
$unique_checksums_count = count( array_unique( array_map( 'serialize', array_values( $checksums ) ) ) ); |
107
|
|
|
|
108
|
|
|
$this->assertEquals( 1, $unique_checksums_count, 'Checksums do not match: ' . print_r( $labelled_checksums, 1 ) ); |
109
|
|
|
|
110
|
|
|
// compare post histograms |
111
|
|
|
$histograms = array_map( array( $this, 'get_all_post_histograms' ), $all_replicastores ); |
112
|
|
|
$labelled_histograms = array_combine( array_map( 'get_class', $all_replicastores ), $histograms ); |
113
|
|
|
$unique_histograms_count = count( array_unique( array_map( 'serialize', $histograms ) ) ); |
114
|
|
|
$this->assertEquals( 1, $unique_histograms_count, 'Post histograms do not match: ' . print_r( $labelled_histograms, 1 ) ); |
115
|
|
|
|
116
|
|
|
$histograms = array_map( array( $this, 'get_all_post_meta_histograms' ), $all_replicastores ); |
117
|
|
|
$labelled_histograms = array_combine( array_map( 'get_class', $all_replicastores ), $histograms ); |
118
|
|
|
$unique_histograms_count = count( array_unique( array_map( 'serialize', $histograms ) ) ); |
119
|
|
|
$this->assertEquals( 1, $unique_histograms_count, 'Post meta histograms do not match: ' . print_r( $labelled_histograms, 1 ) ); |
120
|
|
|
|
121
|
|
|
// compare comment histograms |
122
|
|
|
$histograms = array_map( array( $this, 'get_all_comment_histograms' ), $all_replicastores ); |
123
|
|
|
$labelled_histograms = array_combine( array_map( 'get_class', $all_replicastores ), $histograms ); |
124
|
|
|
$unique_histograms_count = count( array_unique( array_map( 'serialize', $histograms ) ) ); |
125
|
|
|
$this->assertEquals( 1, $unique_histograms_count, 'Comment histograms do not match: ' . print_r( $labelled_histograms, 1 ) ); |
126
|
|
|
|
127
|
|
|
$histograms = array_map( array( $this, 'get_all_comment_meta_histograms' ), $all_replicastores ); |
128
|
|
|
$labelled_histograms = array_combine( array_map( 'get_class', $all_replicastores ), $histograms ); |
129
|
|
|
$unique_histograms_count = count( array_unique( array_map( 'serialize', $histograms ) ) ); |
130
|
|
|
$this->assertEquals( 1, $unique_histograms_count, 'Comment meta histograms do not match: ' . print_r( $labelled_histograms, 1 ) ); |
131
|
|
|
} |
132
|
|
|
|
133
|
|
|
function get_all_checksums( $replicastore ) { |
134
|
|
|
return $replicastore->checksum_all(); |
135
|
|
|
} |
136
|
|
|
|
137
|
|
|
function get_all_post_histograms( $replicastore ) { |
138
|
|
|
return $replicastore->checksum_histogram( 'posts', 10 ); |
139
|
|
|
} |
140
|
|
|
|
141
|
|
|
function get_all_post_meta_histograms( $replicastore ) { |
142
|
|
|
return $replicastore->checksum_histogram( 'post_meta', 10 ); |
143
|
|
|
} |
144
|
|
|
|
145
|
|
|
function get_all_comment_histograms( $replicastore ) { |
146
|
|
|
return $replicastore->checksum_histogram( 'comments', 10 ); |
147
|
|
|
} |
148
|
|
|
|
149
|
|
|
function get_all_comment_meta_histograms( $replicastore ) { |
150
|
|
|
return $replicastore->checksum_histogram( 'comment_meta', 10 ); |
151
|
|
|
} |
152
|
|
|
|
153
|
|
|
/** |
154
|
|
|
* @dataProvider store_provider |
155
|
|
|
*/ |
156
|
|
|
function test_checksum_with_id_range( $store ) { |
157
|
|
|
$post = self::$factory->post( 5 ); |
158
|
|
|
$second_post = self::$factory->post( 10 ); |
159
|
|
|
$comment = self::$factory->comment( 3, $post->ID ); |
160
|
|
|
$second_comment = self::$factory->comment( 6, $second_post->ID ); |
161
|
|
|
|
162
|
|
|
$store->upsert_post( $post ); |
163
|
|
|
$store->upsert_metadata( 'post', $post->ID, 'imagedata', 'bar', 1 ); |
164
|
|
|
$store->upsert_metadata( 'post', $post->ID, 'publicize_results', 'baz', 2 ); |
165
|
|
|
$store->upsert_post( $second_post ); |
166
|
|
|
$store->upsert_metadata( 'post', $second_post->ID, 'imagedata', 'bar', 5 ); |
167
|
|
|
$store->upsert_metadata( 'post', $second_post->ID, 'publicize_results', 'baz', 10 ); |
168
|
|
|
$store->upsert_comment( $comment ); |
169
|
|
|
$store->upsert_metadata( 'comment', $comment->comment_ID, 'hc_avatar', 'bar', 1 ); |
170
|
|
|
$store->upsert_metadata( 'comment', $comment->comment_ID, 'hc_post_as', 'baz', 4 ); |
171
|
|
|
$store->upsert_comment( $second_comment ); |
172
|
|
|
$store->upsert_metadata( 'comment', $second_comment->comment_ID, 'hc_avatar', 'boo', 7 ); |
173
|
|
|
$store->upsert_metadata( 'comment', $second_comment->comment_ID, 'hc_post_as', 'bee', 10 ); |
174
|
|
|
|
175
|
|
|
// test posts checksum with ID range |
176
|
|
|
$histogram = $store->checksum_histogram( 'posts', 2 ); |
177
|
|
|
$this->assertEquals( $store->posts_checksum( 0, 5 ), $histogram['5'] ); |
178
|
|
|
$this->assertEquals( $store->posts_checksum( 6, 10 ), $histogram['10'] ); |
179
|
|
|
|
180
|
|
|
// test postmeta checksum with ID range |
181
|
|
|
$histogram = $store->checksum_histogram( 'post_meta', 2 ); |
182
|
|
|
|
183
|
|
|
// temporary hack due to missing post_meta_checksum implementation in the test replicastore |
184
|
|
View Code Duplication |
if ( 'Jetpack_Sync_Test_Replicastore' != get_class( $store ) ) { |
185
|
|
|
$this->assertEquals( $store->post_meta_checksum( 1, 2 ), $histogram['1-2'] ); |
186
|
|
|
$this->assertEquals( $store->post_meta_checksum( 5, 10 ), $histogram['5-10'] ); |
187
|
|
|
} |
188
|
|
|
|
189
|
|
|
// test comments checksum with ID range |
190
|
|
|
$histogram = $store->checksum_histogram( 'comments', 2 ); |
191
|
|
|
$this->assertEquals( $store->comments_checksum( 0, 5 ), $histogram['3'] ); |
192
|
|
|
$this->assertEquals( $store->comments_checksum( 6, 10 ), $histogram['6'] ); |
193
|
|
|
|
194
|
|
|
// test commentmeta checksum with ID range |
195
|
|
|
$histogram = $store->checksum_histogram( 'comment_meta', 2 ); |
196
|
|
|
|
197
|
|
|
// temporary hack due to missing comment_meta_checksum implementation in the test replicastore |
198
|
|
View Code Duplication |
if ( 'Jetpack_Sync_Test_Replicastore' != get_class( $store ) ) { |
199
|
|
|
$this->assertEquals( $store->comment_meta_checksum( 1, 4 ), $histogram['1-4'] ); |
200
|
|
|
$this->assertEquals( $store->comment_meta_checksum( 7, 10 ), $histogram['7-10'] ); |
201
|
|
|
} |
202
|
|
|
} |
203
|
|
|
|
204
|
|
|
/** |
205
|
|
|
* @dataProvider store_provider |
206
|
|
|
*/ |
207
|
|
|
function test_does_not_checksum_spam_comments( $store ) { |
208
|
|
|
$comment = self::$factory->comment( 3, 1 ); |
209
|
|
|
$spam_comment = self::$factory->comment( 6, 1, array( 'comment_approved' => 'spam' ) ); |
210
|
|
|
$trash_comment = self::$factory->comment( 9, 1, array( 'comment_approved' => 'trash' ) ); |
211
|
|
|
|
212
|
|
|
$store->upsert_comment( $comment ); |
213
|
|
|
$store->upsert_comment( $trash_comment ); |
214
|
|
|
|
215
|
|
|
$checksum = $store->comments_checksum(); |
216
|
|
|
|
217
|
|
|
// add a spam comment and assert that checksum didn't change |
218
|
|
|
$store->upsert_comment( $spam_comment ); |
219
|
|
|
|
220
|
|
|
$this->assertEquals( $checksum, $store->comments_checksum() ); |
221
|
|
|
} |
222
|
|
|
|
223
|
|
|
/** |
224
|
|
|
* @dataProvider store_provider |
225
|
|
|
*/ |
226
|
|
|
function test_strips_non_ascii_chars_for_checksum( $store ) { |
227
|
|
|
$utf8_post = self::$factory->post( 1, array( 'post_content' => 'Panamá' ) ); |
228
|
|
|
$ascii_post = self::$factory->post( 1, array( 'post_content' => 'Panam' ) ); |
229
|
|
|
$utf8_comment = self::$factory->comment( 1, 1, array( 'comment_content' => 'Panamá' ) ); |
230
|
|
|
$ascii_comment = self::$factory->comment( 1, 1, array( 'comment_content' => 'Panam' ) ); |
231
|
|
|
|
232
|
|
|
// generate checksums just for utf8 content |
233
|
|
|
$store->upsert_post( $utf8_post ); |
234
|
|
|
$store->upsert_comment( $utf8_comment ); |
235
|
|
|
|
236
|
|
|
$utf8_post_checksum = $store->posts_checksum(); |
237
|
|
|
$utf8_comment_checksum = $store->comments_checksum(); |
238
|
|
|
|
239
|
|
|
// generate checksums just for ascii content |
240
|
|
|
$store->upsert_post( $ascii_post ); |
241
|
|
|
$store->upsert_comment( $ascii_comment ); |
242
|
|
|
|
243
|
|
|
$this->assertEquals( $utf8_post_checksum, $store->posts_checksum() ); |
244
|
|
|
$this->assertEquals( $utf8_comment_checksum, $store->comments_checksum() ); |
245
|
|
|
} |
246
|
|
|
|
247
|
|
|
/** |
248
|
|
|
* Histograms |
249
|
|
|
**/ |
250
|
|
|
|
251
|
|
|
/** |
252
|
|
|
* @dataProvider store_provider |
253
|
|
|
*/ |
254
|
|
|
function test_checksum_histogram( $store ) { |
255
|
|
|
|
256
|
|
|
$min_post_id = 1000000; |
257
|
|
|
$max_post_id = 1; |
258
|
|
|
$min_comment_id = 1000000; |
259
|
|
|
$max_comment_id = 1; |
260
|
|
|
$generated_post_ids = array(); |
261
|
|
|
$generated_comment_ids = array(); |
262
|
|
|
|
263
|
|
|
for ( $i = 1; $i <= 20; $i += 1 ) { |
264
|
|
|
do { |
265
|
|
|
$post_id = rand( 1, 1000000 ); |
266
|
|
|
} while ( in_array( $post_id, $generated_post_ids ) ); |
267
|
|
|
|
268
|
|
|
$generated_post_ids[] = $post_id; |
269
|
|
|
|
270
|
|
|
$post = self::$factory->post( $post_id, array( 'post_content' => "Test post $i" ) ); |
271
|
|
|
$store->upsert_post( $post ); |
272
|
|
|
if ( $min_post_id > $post_id ) { |
273
|
|
|
$min_post_id = $post_id; |
274
|
|
|
} |
275
|
|
|
|
276
|
|
|
if ( $max_post_id < $post_id ) { |
277
|
|
|
$max_post_id = $post_id; |
278
|
|
|
} |
279
|
|
|
|
280
|
|
|
do { |
281
|
|
|
$comment_id = rand( 1, 1000000 ); |
282
|
|
|
} while ( in_array( $post_id, $generated_comment_ids ) ); |
283
|
|
|
|
284
|
|
|
$generated_comment_ids[] = $comment_id; |
285
|
|
|
|
286
|
|
|
$comment = self::$factory->comment( $comment_id, $post_id, array( 'comment_content' => "Test comment $i" ) ); |
287
|
|
|
$store->upsert_comment( $comment ); |
288
|
|
|
|
289
|
|
|
if ( $min_comment_id > $comment_id ) { |
290
|
|
|
$min_comment_id = $comment_id; |
291
|
|
|
} |
292
|
|
|
|
293
|
|
|
if ( $max_comment_id < $comment_id ) { |
294
|
|
|
$max_comment_id = $comment_id; |
295
|
|
|
} |
296
|
|
|
|
297
|
|
|
} |
298
|
|
|
|
299
|
|
|
foreach ( array( 'posts', 'comments' ) as $object_type ) { |
300
|
|
|
$histogram = $store->checksum_histogram( $object_type, 10, 0, 0 ); |
301
|
|
|
$this->assertEquals( 10, count( $histogram ) ); |
302
|
|
|
|
303
|
|
|
// histogram bucket should equal entire histogram of just the ID range for that bucket |
304
|
|
|
foreach ( $histogram as $range => $checksum ) { |
305
|
|
|
list( $min_id, $max_id ) = explode( '-', $range ); |
306
|
|
|
|
307
|
|
|
$range_histogram = $store->checksum_histogram( $object_type, 1, (int) $min_id, (int) $max_id ); |
308
|
|
|
$range_checksum = array_pop( $range_histogram ); |
309
|
|
|
|
310
|
|
|
$this->assertEquals( $checksum, $range_checksum ); |
311
|
|
|
} |
312
|
|
|
} |
313
|
|
|
|
314
|
|
|
// histogram with one bucket should equal checksum of corresponding object type |
315
|
|
|
$histogram = $store->checksum_histogram( 'posts', 1, 0, 0 ); |
316
|
|
|
$this->assertEquals( $store->posts_checksum(), $histogram["$min_post_id-$max_post_id"] ); |
317
|
|
|
|
318
|
|
|
$histogram = $store->checksum_histogram( 'comments', 1, 0, 0 ); |
319
|
|
|
$this->assertEquals( $store->comments_checksum(), $histogram["$min_comment_id-$max_comment_id"] ); |
320
|
|
|
} |
321
|
|
|
|
322
|
|
|
/** |
323
|
|
|
* @dataProvider store_provider |
324
|
|
|
*/ |
325
|
|
|
function test_replica_checksum_posts_return_different_values_on_enej_case( $store ) { |
326
|
|
|
$store->reset(); |
327
|
|
|
$post = self::$factory->post( 807 ); |
328
|
|
|
$store->upsert_post( $post ); |
329
|
|
|
$post = self::$factory->post( 811 ); |
330
|
|
|
$store->upsert_post( $post ); |
331
|
|
|
$post = self::$factory->post( 816 ); |
332
|
|
|
$store->upsert_post( $post ); |
333
|
|
|
$before_checksum = $store->posts_checksum(); |
334
|
|
|
$post = self::$factory->post( 812 ); |
335
|
|
|
$store->upsert_post( $post ); |
336
|
|
|
$post = self::$factory->post( 813 ); |
337
|
|
|
$store->upsert_post( $post ); |
338
|
|
|
$post = self::$factory->post( 814 ); |
339
|
|
|
$store->upsert_post( $post ); |
340
|
|
|
$post = self::$factory->post( 815 ); |
341
|
|
|
$store->upsert_post( $post ); |
342
|
|
|
$after_checksum = $store->posts_checksum(); |
343
|
|
|
$this->assertNotEquals( $before_checksum, $after_checksum ); |
344
|
|
|
} |
345
|
|
|
|
346
|
|
|
/** |
347
|
|
|
* @dataProvider store_provider |
348
|
|
|
*/ |
349
|
|
|
function test_histogram_accepts_columns( $store ) { |
350
|
|
|
for ( $i = 1; $i <= 20; $i += 1 ) { |
351
|
|
|
$post = self::$factory->post( $i, array( 'post_content' => "Test post $i" ) ); |
352
|
|
|
$store->upsert_post( $post ); |
353
|
|
|
|
354
|
|
|
$comment = self::$factory->comment( $i, $i, array( 'comment_content' => "Test comment $i" ) ); |
355
|
|
|
$store->upsert_comment( $comment ); |
356
|
|
|
} |
357
|
|
|
|
358
|
|
|
$histogram = $store->checksum_histogram( 'posts', 20, 0, 0, array( 'post_content' ) ); |
359
|
|
|
|
360
|
|
|
$post_checksum = $histogram['1']; |
361
|
|
|
|
362
|
|
|
$this->assertEquals( $post_checksum, (string) crc32( implode( '#', array( '' ,"Test post 1" ) ) ) ); |
363
|
|
|
} |
364
|
|
|
|
365
|
|
|
/** |
366
|
|
|
* @dataProvider store_provider |
367
|
|
|
*/ |
368
|
|
|
function test_histogram_detects_missing_columns( $store ) { |
369
|
|
|
global $wpdb; |
370
|
|
|
$suppressed = $wpdb->suppress_errors; |
371
|
|
|
$wpdb->suppress_errors = true; |
372
|
|
|
|
373
|
|
|
|
374
|
|
|
if ( $store instanceof Jetpack_Sync_Test_Replicastore ) { |
375
|
|
|
$this->markTestIncomplete( "The Test replicastore doesn't support detecting missing columns" ); |
376
|
|
|
} |
377
|
|
|
|
378
|
|
|
// check what happens when we pass in an invalid column |
379
|
|
|
$histogram = $store->checksum_histogram( 'posts', 20, 0, 0, array( 'this_column_doesnt_exist' ) ); |
380
|
|
|
|
381
|
|
|
if ( ! empty( $histogram ) ) { |
382
|
|
|
$this->assertTrue( is_wp_error( $histogram ) ); |
383
|
|
|
} else { |
384
|
|
|
$this->assertTrue( is_array( $histogram ) ); |
385
|
|
|
} |
386
|
|
|
|
387
|
|
|
|
388
|
|
|
$wpdb->suppress_errors = $suppressed; |
389
|
|
|
} |
390
|
|
|
|
391
|
|
|
/** |
392
|
|
|
* Posts |
393
|
|
|
*/ |
394
|
|
|
|
395
|
|
|
/** |
396
|
|
|
* @dataProvider store_provider |
397
|
|
|
*/ |
398
|
|
|
function test_replica_upsert_post( $store ) { |
399
|
|
|
$this->assertEquals( 0, $store->post_count() ); |
400
|
|
|
|
401
|
|
|
$post = self::$factory->post( 5 ); |
402
|
|
|
|
403
|
|
|
$store->upsert_post( $post ); |
404
|
|
|
|
405
|
|
|
$retrieved_post = $store->get_post( $post->ID ); |
406
|
|
|
|
407
|
|
|
// author is modified on save by the wpcom shadow replicastore |
408
|
|
|
unset( $post->post_author ); |
409
|
|
|
unset( $retrieved_post->post_author ); |
410
|
|
|
|
411
|
|
|
$this->assertEquals( $post, $retrieved_post ); |
412
|
|
|
|
413
|
|
|
// assert the DB has one post |
414
|
|
|
$this->assertEquals( 1, $store->post_count() ); |
415
|
|
|
|
416
|
|
|
// test that re-upserting doesn't add a new post, but modifies existing one |
417
|
|
|
$post->post_title = "A whole new title"; |
418
|
|
|
$store->upsert_post( $post ); |
419
|
|
|
$replica_post = $store->get_post( $post->ID ); |
420
|
|
|
|
421
|
|
|
$this->assertEquals( "A whole new title", $replica_post->post_title ); |
422
|
|
|
} |
423
|
|
|
|
424
|
|
|
/** |
425
|
|
|
* @dataProvider store_provider |
426
|
|
|
*/ |
427
|
|
|
function test_replica_get_posts( $store ) { |
428
|
|
|
$store->upsert_post( self::$factory->post( 1, array( 'post_status' => 'draft' ) ) ); |
429
|
|
|
$store->upsert_post( self::$factory->post( 2, array( 'post_status' => 'publish' ) ) ); |
430
|
|
|
$store->upsert_post( self::$factory->post( 3, array( 'post_status' => 'trash' ) ) ); |
431
|
|
|
$store->upsert_post( self::$factory->post( 4, array( 'post_status' => 'trash' ) ) ); |
432
|
|
|
|
433
|
|
|
$this->assertEquals( 1, $store->post_count( 'draft' ) ); |
434
|
|
|
$this->assertEquals( 1, $store->post_count( 'publish' ) ); |
435
|
|
|
$this->assertEquals( 2, $store->post_count( 'trash' ) ); |
436
|
|
|
|
437
|
|
|
$trash_posts = $store->get_posts( 'trash' ); |
438
|
|
|
|
439
|
|
|
$this->assertEquals( 2, count( $trash_posts ) ); |
440
|
|
|
|
441
|
|
|
// now let's delete a post |
442
|
|
|
$store->delete_post( 3 ); |
443
|
|
|
|
444
|
|
|
$this->assertEquals( null, $store->get_post( 3 ) ); |
445
|
|
|
$this->assertEquals( 1, $store->post_count( 'trash' ) ); |
446
|
|
|
} |
447
|
|
|
|
448
|
|
|
/** |
449
|
|
|
* @dataProvider store_provider |
450
|
|
|
*/ |
451
|
|
|
function test_replica_checksum_posts( $store ) { |
452
|
|
|
$before_checksum = $store->posts_checksum(); |
453
|
|
|
|
454
|
|
|
$post = self::$factory->post( 5 ); |
455
|
|
|
|
456
|
|
|
$store->upsert_post( $post ); |
457
|
|
|
|
458
|
|
|
$this->assertNotEquals( $before_checksum, $store->posts_checksum() ); |
459
|
|
|
} |
460
|
|
|
|
461
|
|
|
/** |
462
|
|
|
* Comments |
463
|
|
|
*/ |
464
|
|
|
|
465
|
|
|
/** |
466
|
|
|
* @dataProvider store_provider |
467
|
|
|
*/ |
468
|
|
|
function test_replica_upsert_comment( $store ) { |
469
|
|
|
$this->assertEquals( 0, $store->comment_count() ); |
470
|
|
|
|
471
|
|
|
$comment = self::$factory->comment( 3, 2 ); |
472
|
|
|
|
473
|
|
|
$store->upsert_comment( $comment ); |
474
|
|
|
|
475
|
|
|
$this->assertEquals( 1, $store->comment_count() ); |
476
|
|
|
|
477
|
|
|
$retrieved_comment = $store->get_comment( $comment->comment_ID ); |
478
|
|
|
|
479
|
|
|
// insane hack because sometimes MySQL retrurns dates that are off by a second or so. WTF? |
480
|
|
|
unset( $comment->comment_date ); |
481
|
|
|
unset( $comment->comment_date_gmt ); |
482
|
|
|
unset( $retrieved_comment->comment_date ); |
483
|
|
|
unset( $retrieved_comment->comment_date_gmt ); |
484
|
|
|
|
485
|
|
|
if ( $store instanceof Replicastore ) { |
486
|
|
|
$this->markTestIncomplete( "The WP replicastore doesn't support setting comments post_fields" ); |
487
|
|
|
} |
488
|
|
|
|
489
|
|
|
$this->assertEquals( $comment, $retrieved_comment ); |
490
|
|
|
} |
491
|
|
|
|
492
|
|
|
/** |
493
|
|
|
* @dataProvider store_provider |
494
|
|
|
*/ |
495
|
|
|
function test_replica_checksum_comments( $store ) { |
496
|
|
|
$before_checksum = $store->comments_checksum(); |
497
|
|
|
|
498
|
|
|
$comment = self::$factory->comment( 3, 2 ); |
499
|
|
|
|
500
|
|
|
$store->upsert_comment( $comment ); |
501
|
|
|
|
502
|
|
|
$this->assertNotEquals( $before_checksum, $store->comments_checksum() ); |
503
|
|
|
} |
504
|
|
|
|
505
|
|
|
/** |
506
|
|
|
* @dataProvider store_provider |
507
|
|
|
*/ |
508
|
|
|
function test_replica_get_comments( $store ) { |
509
|
|
|
$post_id = 1; |
510
|
|
|
self::$factory->post( $post_id, array( 'post_status' => 'publish' ) ); |
511
|
|
|
$store->upsert_comment( self::$factory->comment( 1, $post_id, array( 'comment_approved' => '0' ) ) ); |
512
|
|
|
$store->upsert_comment( self::$factory->comment( 2, $post_id, array( 'comment_approved' => '1' ) ) ); |
513
|
|
|
$store->upsert_comment( self::$factory->comment( 3, $post_id, array( 'comment_approved' => 'spam' ) ) ); |
514
|
|
|
$store->upsert_comment( self::$factory->comment( 4, $post_id, array( 'comment_approved' => 'spam' ) ) ); |
515
|
|
|
$store->upsert_comment( self::$factory->comment( 5, $post_id, array( 'comment_approved' => 'trash' ) ) ); |
516
|
|
|
|
517
|
|
|
$this->assertEquals( 1, $store->comment_count( 'hold' ) ); |
518
|
|
|
$this->assertEquals( 1, $store->comment_count( 'approve' ) ); |
519
|
|
|
$this->assertEquals( 1, $store->comment_count( 'trash' ) ); |
520
|
|
|
$this->assertEquals( 2, $store->comment_count( 'spam' ) ); |
521
|
|
|
} |
522
|
|
|
|
523
|
|
|
/** |
524
|
|
|
* Options |
525
|
|
|
*/ |
526
|
|
|
|
527
|
|
|
/** |
528
|
|
|
* @dataProvider store_provider |
529
|
|
|
*/ |
530
|
|
|
function test_replica_update_option( $store ) { |
531
|
|
|
$option_name = 'blogdescription'; |
532
|
|
|
$option_value = (string) rand(); |
533
|
|
|
$store->update_option( $option_name, $option_value ); |
534
|
|
|
$replica_option_value = $store->get_option( $option_name ); |
535
|
|
|
|
536
|
|
|
$this->assertEquals( $option_value, $replica_option_value ); |
537
|
|
|
} |
538
|
|
|
|
539
|
|
|
/** |
540
|
|
|
* @dataProvider store_provider |
541
|
|
|
*/ |
542
|
|
|
function test_replica_delete_option( $store ) { |
543
|
|
|
$option_name = 'test_replicastore_' . rand(); |
544
|
|
|
$option_value = (string) rand(); |
545
|
|
|
$store->update_option( $option_name, $option_value ); |
546
|
|
|
$store->delete_option( $option_name ); |
547
|
|
|
$replica_option_value = $store->get_option( $option_name ); |
548
|
|
|
|
549
|
|
|
$this->assertFalse( $replica_option_value ); |
550
|
|
|
} |
551
|
|
|
|
552
|
|
|
/** |
553
|
|
|
* @dataProvider store_provider |
554
|
|
|
*/ |
555
|
|
|
function test_replica_set_theme_support( $store ) { |
556
|
|
|
|
557
|
|
|
if ( $store instanceof Replicastore ) { |
558
|
|
|
$this->markTestIncomplete( "The WP replicastore doesn't support setting theme options directly" ); |
559
|
|
|
} |
560
|
|
|
|
561
|
|
|
$theme_features = array( |
562
|
|
|
'automatic-feed-links' => true, |
563
|
|
|
'title-tag' => true, |
564
|
|
|
'post-thumbnails' => true, |
565
|
|
|
'menus' => true, |
566
|
|
|
'html5' => |
567
|
|
|
array( |
568
|
|
|
0 => |
569
|
|
|
array( |
570
|
|
|
0 => 'search-form', |
571
|
|
|
1 => 'comment-form', |
572
|
|
|
2 => 'comment-list', |
573
|
|
|
3 => 'gallery', |
574
|
|
|
4 => 'caption', |
575
|
|
|
), |
576
|
|
|
), |
577
|
|
|
'post-formats' => |
578
|
|
|
array( |
579
|
|
|
0 => |
580
|
|
|
array( |
581
|
|
|
0 => 'aside', |
582
|
|
|
1 => 'image', |
583
|
|
|
2 => 'video', |
584
|
|
|
3 => 'quote', |
585
|
|
|
4 => 'link', |
586
|
|
|
5 => 'gallery', |
587
|
|
|
6 => 'status', |
588
|
|
|
7 => 'audio', |
589
|
|
|
8 => 'chat', |
590
|
|
|
), |
591
|
|
|
), |
592
|
|
|
'custom-background' => |
593
|
|
|
array( |
594
|
|
|
0 => |
595
|
|
|
array( |
596
|
|
|
'default-image' => '', |
597
|
|
|
'default-repeat' => 'repeat', |
598
|
|
|
'default-position-x' => 'left', |
599
|
|
|
'default-attachment' => 'fixed', |
600
|
|
|
'default-color' => 'f1f1f1', |
601
|
|
|
'wp-head-callback' => '_custom_background_cb', |
602
|
|
|
'admin-head-callback' => '', |
603
|
|
|
'admin-preview-callback' => '', |
604
|
|
|
), |
605
|
|
|
), |
606
|
|
|
'editor-style' => true, |
607
|
|
|
'custom-header' => |
608
|
|
|
array( |
609
|
|
|
0 => |
610
|
|
|
array( |
611
|
|
|
'default-image' => '', |
612
|
|
|
'random-default' => false, |
613
|
|
|
'width' => 954, |
614
|
|
|
'height' => 1300, |
615
|
|
|
'flex-height' => false, |
616
|
|
|
'flex-width' => false, |
617
|
|
|
'default-text-color' => '333333', |
618
|
|
|
'header-text' => true, |
619
|
|
|
'uploads' => true, |
620
|
|
|
'wp-head-callback' => 'twentyfifteen_header_style', |
621
|
|
|
'admin-head-callback' => '', |
622
|
|
|
'admin-preview-callback' => '', |
623
|
|
|
), |
624
|
|
|
), |
625
|
|
|
'jetpack-responsive-videos' => true, |
626
|
|
|
'site-logo' => |
627
|
|
|
array( |
628
|
|
|
0 => |
629
|
|
|
array( |
630
|
|
|
'size' => 'twentyfifteen-logo', |
631
|
|
|
), |
632
|
|
|
), |
633
|
|
|
'infinite-scroll' => |
634
|
|
|
array( |
635
|
|
|
0 => |
636
|
|
|
array( |
637
|
|
|
'container' => 'main', |
638
|
|
|
'footer' => 'page', |
639
|
|
|
), |
640
|
|
|
), |
641
|
|
|
'widgets' => true, |
642
|
|
|
'custom_colors_extra_css' => |
643
|
|
|
array( |
644
|
|
|
0 => 'twentyfifteen_extra_css', |
645
|
|
|
), |
646
|
|
|
); |
647
|
|
|
|
648
|
|
|
$store->set_callable( 'theme_support', $theme_features ); |
649
|
|
|
|
650
|
|
|
// the "current_theme_supports" API is only supposed to return "true" if there's a setting |
651
|
|
|
foreach ( $theme_features as $theme_feature => $theme_feature_value ) { |
652
|
|
|
$replica_theme_support_value = $store->current_theme_supports( $theme_feature ); |
653
|
|
|
$this->assertEquals( $theme_feature_value || false, $replica_theme_support_value ); |
654
|
|
|
} |
655
|
|
|
} |
656
|
|
|
|
657
|
|
|
/** |
658
|
|
|
* Meta |
659
|
|
|
*/ |
660
|
|
|
|
661
|
|
|
/** |
662
|
|
|
* @dataProvider store_provider |
663
|
|
|
*/ |
664
|
|
|
function test_replica_reset_preserves_internal_keys( $store ) { |
665
|
|
|
if ( $store instanceof Jetpack_Sync_Test_Replicastore ) { |
666
|
|
|
$this->markTestIncomplete( "Test replicastore resets fully every time - this is only necessary on WPCOM" ); |
667
|
|
|
} |
668
|
|
|
|
669
|
|
|
$store->upsert_post( self::$factory->post( 1 ) ); |
670
|
|
|
|
671
|
|
|
$store->upsert_metadata( 'post', 1, 'foo', 'bar', 3 ); |
672
|
|
|
$store->upsert_metadata( 'post', 1, '_fee', 'baz', 4 ); |
673
|
|
|
|
674
|
|
|
$store->reset(); |
675
|
|
|
|
676
|
|
|
// sadly this is still necessary since we're bulk deleting post meta |
677
|
|
|
// but not bulk-cache-invalidating it |
678
|
|
|
wp_cache_delete( 1, 'post_meta' ); |
679
|
|
|
|
680
|
|
|
$this->assertEquals( null, $store->get_metadata( 'post', 1, 'foo', true ) ); |
681
|
|
|
$this->assertEquals( 'baz', $store->get_metadata( 'post', 1, '_fee', true ) ); |
682
|
|
|
} |
683
|
|
|
|
684
|
|
|
/** |
685
|
|
|
* @dataProvider store_provider |
686
|
|
|
*/ |
687
|
|
|
function test_replica_update_meta( $store ) { |
688
|
|
|
$store->upsert_post( self::$factory->post( 1 ) ); |
689
|
|
|
|
690
|
|
|
$store->upsert_metadata( 'post', 1, 'foo', 'bar', 3 ); |
691
|
|
|
|
692
|
|
|
$this->assertEquals( array( 'bar' ), $store->get_metadata( 'post', 1, 'foo' ) ); |
693
|
|
|
|
694
|
|
|
$store->delete_metadata( 'post', 1, array( 3 ) ); |
695
|
|
|
|
696
|
|
|
$this->assertEquals( array(), $store->get_metadata( 'post', 1, 'foo' ) ); |
697
|
|
|
} |
698
|
|
|
|
699
|
|
|
/** |
700
|
|
|
* @dataProvider store_provider |
701
|
|
|
*/ |
702
|
|
|
function test_replica_update_meta_array( $store ) { |
703
|
|
|
$meta_array = array( 'trees' => 'green', 'ocean' => 'blue' ); |
704
|
|
|
|
705
|
|
|
$store->upsert_post( self::$factory->post( 1 ) ); |
706
|
|
|
$store->upsert_metadata( 'post', 1, 'colors', $meta_array, 3 ); |
707
|
|
|
|
708
|
|
|
$color_meta = $store->get_metadata( 'post', 1, 'colors' ); |
709
|
|
|
|
710
|
|
|
$this->assertTrue( $this->arrays_are_similar( $meta_array, $color_meta[0] ) ); |
711
|
|
|
} |
712
|
|
|
|
713
|
|
|
/** |
714
|
|
|
* Determine if two associative arrays are similar |
715
|
|
|
* |
716
|
|
|
* Both arrays must have the same indexes with identical values |
717
|
|
|
* without respect to key ordering |
718
|
|
|
* |
719
|
|
|
* @param array $a |
720
|
|
|
* @param array $b |
721
|
|
|
* |
722
|
|
|
* @return bool |
723
|
|
|
*/ |
724
|
|
|
function arrays_are_similar( $a, $b ) { |
725
|
|
|
// if the indexes don't match, return immediately |
726
|
|
|
if ( count( array_diff_assoc( $a, $b ) ) ) { |
727
|
|
|
return false; |
728
|
|
|
} |
729
|
|
|
// we know that the indexes, but maybe not values, match. |
730
|
|
|
// compare the values between the two arrays |
731
|
|
|
foreach ( $a as $k => $v ) { |
732
|
|
|
if ( $v !== $b[ $k ] ) { |
733
|
|
|
return false; |
734
|
|
|
} |
735
|
|
|
} |
736
|
|
|
|
737
|
|
|
// we have identical indexes, and no unequal values |
738
|
|
|
return true; |
739
|
|
|
} |
740
|
|
|
|
741
|
|
|
/** |
742
|
|
|
* Constants |
743
|
|
|
*/ |
744
|
|
|
|
745
|
|
|
/** |
746
|
|
|
* @dataProvider store_provider |
747
|
|
|
*/ |
748
|
|
|
function test_replica_set_constant( $store ) { |
749
|
|
|
$this->assertNull( $store->get_constant( 'FOO' ) ); |
750
|
|
|
|
751
|
|
|
$store->set_constant( 'FOO', array( 'foo' => 'bar' ) ); |
752
|
|
|
|
753
|
|
|
$this->assertEquals( array( 'foo' => 'bar' ), $store->get_constant( 'FOO' ) ); |
754
|
|
|
} |
755
|
|
|
|
756
|
|
|
/** |
757
|
|
|
* Updates |
758
|
|
|
*/ |
759
|
|
|
|
760
|
|
|
/** |
761
|
|
|
* @dataProvider store_provider |
762
|
|
|
*/ |
763
|
|
|
function test_replica_set_updates( $store ) { |
764
|
|
|
$this->assertNull( $store->get_updates( 'core' ) ); |
765
|
|
|
|
766
|
|
|
$store->set_updates( 'core', 1 ); |
767
|
|
|
|
768
|
|
|
$this->assertEquals( 1, $store->get_updates( 'core' ) ); |
769
|
|
|
} |
770
|
|
|
|
771
|
|
|
/** |
772
|
|
|
* Callables |
773
|
|
|
*/ |
774
|
|
|
|
775
|
|
|
/** |
776
|
|
|
* @dataProvider store_provider |
777
|
|
|
*/ |
778
|
|
|
function test_replica_set_callables( $store ) { |
779
|
|
|
if ( $store instanceof Replicastore ) { |
780
|
|
|
$this->markTestIncomplete( "The WP replicastore doesn't support setting callables directly" ); |
781
|
|
|
} |
782
|
|
|
|
783
|
|
|
$this->assertNull( $store->get_callable( 'is_main_network' ) ); |
784
|
|
|
|
785
|
|
|
$store->set_callable( 'is_main_network', '1' ); |
786
|
|
|
|
787
|
|
|
$this->assertEquals( '1', $store->get_callable( 'is_main_network' ) ); |
788
|
|
|
} |
789
|
|
|
|
790
|
|
|
/** |
791
|
|
|
* Site (aka Network) options |
792
|
|
|
*/ |
793
|
|
|
|
794
|
|
|
/** |
795
|
|
|
* @dataProvider store_provider |
796
|
|
|
*/ |
797
|
|
|
function test_replica_set_site_options( $store ) { |
798
|
|
|
$this->assertFalse( $store->get_site_option( 'foo' ), 'Site option Not empty.' ); |
799
|
|
|
|
800
|
|
|
$store->update_site_option( 'foo', 'bar' ); |
801
|
|
|
|
802
|
|
|
$this->assertEquals( 'bar', $store->get_site_option( 'foo' ), 'Site option Not bar.' ); |
803
|
|
|
} |
804
|
|
|
|
805
|
|
|
/** |
806
|
|
|
* @dataProvider store_provider |
807
|
|
|
*/ |
808
|
|
|
function test_replica_delete_site_option( $store ) { |
809
|
|
|
$store->update_site_option( 'to_delete', 'me' ); |
810
|
|
|
|
811
|
|
|
$this->assertEquals( 'me', $store->get_site_option( 'to_delete' ), 'Site option is NOT set to me.' ); |
812
|
|
|
|
813
|
|
|
$store->delete_site_option( 'to_delete' ); |
814
|
|
|
|
815
|
|
|
$this->assertEquals( false, $store->get_site_option( 'to_delete' ), 'Site option was NOT deleted.' ); |
816
|
|
|
} |
817
|
|
|
|
818
|
|
|
/** |
819
|
|
|
* Users |
820
|
|
|
*/ |
821
|
|
|
|
822
|
|
|
/** |
823
|
|
|
* @dataProvider store_provider |
824
|
|
|
*/ |
825
|
|
|
function test_replica_update_users( $store ) { |
826
|
|
|
if ( $store instanceof Replicastore ) { |
827
|
|
|
$this->markTestIncomplete( "The WP replicastore doesn't support setting users" ); |
828
|
|
|
} |
829
|
|
|
|
830
|
|
|
$this->assertNull( $store->get_user( 12 ) ); |
831
|
|
|
|
832
|
|
|
$user = self::$factory->user( 12, 'example_user' ); |
833
|
|
|
|
834
|
|
|
$store->upsert_user( $user ); |
835
|
|
|
|
836
|
|
|
$this->assertNotNull( $store->get_user( 12 ) ); |
837
|
|
|
|
838
|
|
|
// delete stuff that shouldn't be included because we don't sync that data |
839
|
|
|
unset( $user->data->user_activation_key ); |
840
|
|
|
|
841
|
|
|
$stored_user = $store->get_user( 12 ); |
842
|
|
|
|
843
|
|
|
if ( $store instanceof Jetpack_Sync_WPCOM_Shadow_Replicastore ) { |
|
|
|
|
844
|
|
|
$this->assertEquals( $user->ID, $stored_user->external_user_id ); |
845
|
|
|
$this->assertFalse( isset( $user->data->user_activation_key ) ); |
846
|
|
|
} else { |
847
|
|
|
$this->assertEquals( $user->ID, $stored_user->ID ); |
848
|
|
|
} |
849
|
|
|
|
850
|
|
|
$this->assertEquals( $user->data->user_login, $stored_user->data->user_login ); |
851
|
|
|
$this->assertEquals( $user->data->user_nicename, $stored_user->data->user_nicename ); |
852
|
|
|
$this->assertEquals( $user->data->user_email, $stored_user->data->user_email ); |
853
|
|
|
$this->assertEquals( $user->data->user_url, $stored_user->data->user_url ); |
854
|
|
|
$this->assertEquals( $user->data->user_registered, $stored_user->data->user_registered ); |
855
|
|
|
$this->assertEquals( $user->data->user_status, $stored_user->data->user_status ); |
856
|
|
|
$this->assertEquals( $user->data->display_name, $stored_user->data->display_name ); |
857
|
|
|
|
858
|
|
|
$store->delete_user( 12 ); |
859
|
|
|
|
860
|
|
|
$this->assertNull( $store->get_user( 12 ) ); |
861
|
|
|
} |
862
|
|
|
|
863
|
|
|
/** |
864
|
|
|
* @dataProvider store_provider |
865
|
|
|
*/ |
866
|
|
|
function test_replica_get_allowed_mime_types( $store ) { |
867
|
|
|
if ( $store instanceof Replicastore ) { |
868
|
|
|
$this->markTestIncomplete( "The WP replicastore doesn't support setting users" ); |
869
|
|
|
} |
870
|
|
|
|
871
|
|
|
$this->assertNull( $store->get_user( 12 ) ); |
872
|
|
|
|
873
|
|
|
$user = self::$factory->user( 12, 'example_user' ); |
874
|
|
|
$user_allowed_mime_types = $user->data->allowed_mime_types; |
875
|
|
|
$store->upsert_user( $user ); |
876
|
|
|
$this->assertEquals( $user_allowed_mime_types, $store->get_allowed_mime_types( 12 ) ); |
877
|
|
|
} |
878
|
|
|
|
879
|
|
|
/** |
880
|
|
|
* Terms |
881
|
|
|
*/ |
882
|
|
|
|
883
|
|
|
/** |
884
|
|
|
* @dataProvider store_provider |
885
|
|
|
*/ |
886
|
|
|
public function test_replica_update_terms( $store ) { |
887
|
|
|
$taxonomy = 'test_shadow_taxonomy_term'; |
888
|
|
|
|
889
|
|
|
$this->ensure_synced_taxonomy( $store, $taxonomy ); |
890
|
|
|
|
891
|
|
|
$term_object = self::$factory->term( 22, |
892
|
|
|
array( |
893
|
|
|
'name' => 'Female', |
894
|
|
|
'slug' => 'female', |
895
|
|
|
'term_taxonomy_id' => 22, |
896
|
|
|
'taxonomy' => $taxonomy, |
897
|
|
|
) |
898
|
|
|
); |
899
|
|
|
|
900
|
|
|
$this->assertEmpty( $store->get_term( $term_object->taxonomy, $term_object->term_id ) ); |
901
|
|
|
|
902
|
|
|
$store->update_term( $term_object ); |
903
|
|
|
|
904
|
|
|
$term = $store->get_term( $term_object->taxonomy, $term_object->term_id ); |
905
|
|
|
|
906
|
|
|
$this->assertEquals( (array) $term_object, (array) $term ); |
907
|
|
|
} |
908
|
|
|
|
909
|
|
|
/** |
910
|
|
|
* @dataProvider store_provider |
911
|
|
|
*/ |
912
|
|
|
function test_replica_delete_terms( $store ) { |
913
|
|
|
$taxonomy = 'test_shadow_taxonomy_term'; |
914
|
|
|
|
915
|
|
|
$this->ensure_synced_taxonomy( $store, $taxonomy ); |
916
|
|
|
|
917
|
|
|
$term_object = self::$factory->term( 22, |
918
|
|
|
array( |
919
|
|
|
'name' => 'Female', |
920
|
|
|
'slug' => 'female', |
921
|
|
|
'term_taxonomy_id' => 22, |
922
|
|
|
'taxonomy' => $taxonomy, |
923
|
|
|
) |
924
|
|
|
); |
925
|
|
|
|
926
|
|
|
$store->update_term( $term_object ); |
927
|
|
|
|
928
|
|
|
$store->delete_term( $term_object->term_id, $taxonomy ); |
929
|
|
|
|
930
|
|
|
$this->assertEmpty( $store->get_term( $term_object->taxonomy, $term_object->term_id ) ); |
931
|
|
|
} |
932
|
|
|
|
933
|
|
|
/** |
934
|
|
|
* @dataProvider store_provider |
935
|
|
|
*/ |
936
|
|
|
function test_replica_update_post_terms( $store ) { |
937
|
|
|
$taxonomy = 'test_shadow_taxonomy_term'; |
938
|
|
|
$this->ensure_synced_taxonomy( $store, $taxonomy ); |
939
|
|
|
|
940
|
|
|
$term_object = self::$factory->term( 22, |
941
|
|
|
array( |
942
|
|
|
'name' => 'Female', |
943
|
|
|
'slug' => 'female', |
944
|
|
|
'term_taxonomy_id' => 22, |
945
|
|
|
'taxonomy' => $taxonomy, |
946
|
|
|
) |
947
|
|
|
); |
948
|
|
|
|
949
|
|
|
$store->update_term( $term_object ); |
950
|
|
|
|
951
|
|
|
$post = self::$factory->post( 5 ); |
952
|
|
|
$store->upsert_post( $post ); |
953
|
|
|
$replica_post = $store->get_post( 5 ); |
954
|
|
|
|
955
|
|
|
$store->update_object_terms( $replica_post->ID, $taxonomy, array( 22 ), true ); |
956
|
|
|
|
957
|
|
|
$terms = $store->get_the_terms( $replica_post->ID, $taxonomy ); |
958
|
|
|
|
959
|
|
|
$this->assertEquals( 1, $terms[0]->count ); |
960
|
|
|
$this->assertEquals( 22, $terms[0]->term_id ); |
961
|
|
|
$this->assertEquals( 22, $terms[0]->term_taxonomy_id ); |
962
|
|
|
$this->assertEquals( 'female', $terms[0]->slug ); |
963
|
|
|
$this->assertEquals( 'Female', $terms[0]->name ); |
964
|
|
|
} |
965
|
|
|
|
966
|
|
|
/** |
967
|
|
|
* @dataProvider store_provider |
968
|
|
|
*/ |
969
|
|
|
function test_replica_delete_post_terms( $store ) { |
970
|
|
|
$this->markTestIncomplete( 'contains SQL' ); |
971
|
|
|
global $wpdb; |
972
|
|
|
$taxonomy = 'test_shadow_taxonomy_term'; |
973
|
|
|
|
974
|
|
|
$this->ensure_synced_taxonomy( $store, $taxonomy ); |
975
|
|
|
|
976
|
|
|
$term_object = (object) array( |
977
|
|
|
'term_id' => 22, |
978
|
|
|
'name' => 'Female', |
979
|
|
|
'slug' => 'female', |
980
|
|
|
'term_group' => 0, |
981
|
|
|
'term_taxonomy_id' => 22, |
982
|
|
|
'taxonomy' => $taxonomy, |
983
|
|
|
'description' => '', |
984
|
|
|
'parent' => 0, |
985
|
|
|
'count' => 0, |
986
|
|
|
'filter' => 'raw', |
987
|
|
|
); |
988
|
|
|
|
989
|
|
|
$store->update_term( $term_object ); |
990
|
|
|
|
991
|
|
|
$post = self::$factory->post( 5 ); |
992
|
|
|
$store->upsert_post( $post ); |
993
|
|
|
$replica_post = $store->get_post( 5 ); |
994
|
|
|
|
995
|
|
|
$store->update_object_terms( $replica_post->ID, $taxonomy, array( 22 ), true ); |
996
|
|
|
|
997
|
|
|
$terms = get_the_terms( $replica_post->ID, $taxonomy ); |
998
|
|
|
$this->assertEquals( 1, $terms[0]->count ); |
999
|
|
|
|
1000
|
|
|
$store->delete_object_terms( $replica_post->ID, array( 22 ) ); |
1001
|
|
|
|
1002
|
|
|
$this->assertEquals( null, $wpdb->get_row( "SELECT * FROM $wpdb->term_relationships WHERE object_id = 5 " ) ); |
1003
|
|
|
|
1004
|
|
|
$terms = get_the_terms( $replica_post->ID, $taxonomy ); |
1005
|
|
|
$this->assertEquals( 0, $terms[0]->count ); |
1006
|
|
|
} |
1007
|
|
|
|
1008
|
|
|
public function store_provider( $name ) { |
1009
|
|
View Code Duplication |
if ( ! self::$all_replicastores ) { |
1010
|
|
|
// detect classes that implement iJetpack_Sync_Replicastore |
1011
|
|
|
self::$all_replicastores = array(); |
1012
|
|
|
|
1013
|
|
|
foreach ( get_declared_classes() as $className ) { |
1014
|
|
|
if ( in_array( 'Automattic\\Jetpack\\Sync\\Replicastore_Interface', class_implements( $className ) ) ) { |
1015
|
|
|
self::$all_replicastores[] = $className; |
1016
|
|
|
} |
1017
|
|
|
} |
1018
|
|
|
} |
1019
|
|
|
|
1020
|
|
|
$return = array(); |
1021
|
|
|
|
1022
|
|
|
foreach ( self::$all_replicastores as $replicastore_class ) { |
1023
|
|
|
if ( method_exists( $replicastore_class, 'getInstance' ) ) { |
1024
|
|
|
$instance = call_user_func( array( $replicastore_class, 'getInstance' ) ); |
1025
|
|
|
} else { |
1026
|
|
|
$instance = new $replicastore_class(); |
1027
|
|
|
} |
1028
|
|
|
|
1029
|
|
|
$return[] = array( $instance ); |
1030
|
|
|
} |
1031
|
|
|
|
1032
|
|
|
return $return; |
1033
|
|
|
} |
1034
|
|
|
|
1035
|
|
|
private function ensure_synced_taxonomy( $store, $slug, $type = 'post' ) { |
1036
|
|
|
register_taxonomy( |
1037
|
|
|
$slug, |
1038
|
|
|
$type, |
1039
|
|
|
array( |
1040
|
|
|
'label' => __( $slug ), |
1041
|
|
|
'rewrite' => array( 'slug' => $slug ), |
1042
|
|
|
'hierarchical' => true, |
1043
|
|
|
) |
1044
|
|
|
); |
1045
|
|
|
|
1046
|
|
|
// fetch the taxonomy, sync it then delete it |
1047
|
|
|
global $wp_taxonomies; |
1048
|
|
|
|
1049
|
|
|
$store->set_callable( 'taxonomies', array( $slug => $wp_taxonomies[ $slug ] ) ); |
1050
|
|
|
|
1051
|
|
|
// unregister_taxonomy( $slug ); |
1052
|
|
|
} |
1053
|
|
|
} |
1054
|
|
|
|
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 thecomposer.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
orrequire-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 you have not tested against this specific condition, such errors might go unnoticed.