1
|
|
|
<?php |
2
|
|
|
/** |
3
|
|
|
* Functions that mock WordPress core functionality for testing purposes. |
4
|
|
|
* |
5
|
|
|
* @package automattic/jetpack-autoloader |
6
|
|
|
*/ |
7
|
|
|
|
8
|
|
|
if ( ! function_exists( 'trailingslashit' ) ) { |
9
|
|
|
|
10
|
|
|
/** |
11
|
|
|
* A drop-in for a WordPress core function. |
12
|
|
|
* |
13
|
|
|
* @param String $string string. |
14
|
|
|
* @return String |
15
|
|
|
*/ |
16
|
|
|
function trailingslashit( $string ) { |
17
|
|
|
return rtrim( $string, '/\\' ) . '/'; |
18
|
|
|
} |
19
|
|
|
} |
20
|
|
|
|
21
|
|
|
if ( ! function_exists( 'wp_unslash' ) ) { |
22
|
|
|
/** |
23
|
|
|
* A drop-in for a WordPress core function. |
24
|
|
|
* |
25
|
|
|
* @param string|string[] $value String or array of strings to unslash. |
26
|
|
|
* @return string|string[] Unslashed $value |
27
|
|
|
*/ |
28
|
|
|
function wp_unslash( $value ) { |
29
|
|
|
return stripslashes_deep( $value ); |
30
|
|
|
} |
31
|
|
|
|
32
|
|
|
/** |
33
|
|
|
* A drop-in for a WordPress core function. |
34
|
|
|
* |
35
|
|
|
* @param mixed $value The value to be stripped. |
36
|
|
|
* @return mixed Stripped value. |
37
|
|
|
*/ |
38
|
|
|
function stripslashes_deep( $value ) { |
39
|
|
|
return map_deep( $value, 'stripslashes_from_strings_only' ); |
40
|
|
|
} |
41
|
|
|
|
42
|
|
|
/** |
43
|
|
|
* A drop-in for a WordPress core function. |
44
|
|
|
* |
45
|
|
|
* @param mixed $value The array, object, or scalar. |
46
|
|
|
* @param callable $callback The function to map onto $value. |
47
|
|
|
* @return mixed The value with the callback applied to all non-arrays and non-objects inside it. |
48
|
|
|
*/ |
49
|
|
View Code Duplication |
function map_deep( $value, $callback ) { |
|
|
|
|
50
|
|
|
if ( is_array( $value ) ) { |
51
|
|
|
foreach ( $value as $index => $item ) { |
52
|
|
|
$value[ $index ] = map_deep( $item, $callback ); |
53
|
|
|
} |
54
|
|
|
} elseif ( is_object( $value ) ) { |
55
|
|
|
$object_vars = get_object_vars( $value ); |
56
|
|
|
foreach ( $object_vars as $property_name => $property_value ) { |
57
|
|
|
$value->$property_name = map_deep( $property_value, $callback ); |
58
|
|
|
} |
59
|
|
|
} else { |
60
|
|
|
$value = call_user_func( $callback, $value ); |
61
|
|
|
} |
62
|
|
|
|
63
|
|
|
return $value; |
64
|
|
|
} |
65
|
|
|
|
66
|
|
|
/** |
67
|
|
|
* A drop-in for a WordPress core function. |
68
|
|
|
* |
69
|
|
|
* @param mixed $value The array or string to be stripped. |
70
|
|
|
* @return mixed $value The stripped value. |
71
|
|
|
*/ |
72
|
|
|
function stripslashes_from_strings_only( $value ) { |
73
|
|
|
return is_string( $value ) ? stripslashes( $value ) : $value; |
74
|
|
|
} |
75
|
|
|
} |
76
|
|
|
|
77
|
|
|
if ( ! function_exists( 'get_option' ) ) { |
78
|
|
|
/** |
79
|
|
|
* A drop-in for a WordPress core function. |
80
|
|
|
* |
81
|
|
|
* Note that the `$test_options` global can be used to set options to be returned via this function. |
82
|
|
|
* |
83
|
|
|
* @param string $option Name of the option to retrieve. Expected to not be SQL-escaped. |
84
|
|
|
* @param mixed $default Default value to return if the option does not exist. |
85
|
|
|
* @return mixed Value set for the option. |
86
|
|
|
*/ |
87
|
|
|
function get_option( $option, $default = false ) { |
88
|
|
|
global $test_options; |
89
|
|
|
|
90
|
|
|
if ( isset( $test_options[ $option ] ) ) { |
91
|
|
|
return $test_options[ $option ]; |
92
|
|
|
} |
93
|
|
|
|
94
|
|
|
return $default; |
95
|
|
|
} |
96
|
|
|
|
97
|
|
|
/** |
98
|
|
|
* Adds an option to be used in tests. |
99
|
|
|
* |
100
|
|
|
* @param string $option The option to set. |
101
|
|
|
* @param mixed $value The value to set to the option. |
102
|
|
|
*/ |
103
|
|
|
function add_test_option( $option, $value ) { |
104
|
|
|
global $test_options; |
105
|
|
|
$test_options[ $option ] = $value; |
106
|
|
|
} |
107
|
|
|
|
108
|
|
|
/** |
109
|
|
|
* A drop-in for a WordPress core function. |
110
|
|
|
* |
111
|
|
|
* @param string $option Name of the option to retrieve. Expected to not be SQL-escaped. |
112
|
|
|
* @param mixed $default Default value to return if the option does not exist. |
113
|
|
|
* @return mixed Value set for the option. |
114
|
|
|
*/ |
115
|
|
|
function get_site_option( $option, $default = false ) { |
116
|
|
|
global $test_site_options; |
117
|
|
|
|
118
|
|
|
if ( isset( $test_site_options[ $option ] ) ) { |
119
|
|
|
return $test_site_options[ $option ]; |
120
|
|
|
} |
121
|
|
|
|
122
|
|
|
return $default; |
123
|
|
|
} |
124
|
|
|
|
125
|
|
|
/** |
126
|
|
|
* Adds a site option to be used in tests. |
127
|
|
|
* |
128
|
|
|
* @param string $option The option to set. |
129
|
|
|
* @param mixed $value The value to set to the option. |
130
|
|
|
*/ |
131
|
|
|
function add_test_site_option( $option, $value ) { |
132
|
|
|
global $test_site_options; |
133
|
|
|
$test_site_options[ $option ] = $value; |
134
|
|
|
} |
135
|
|
|
} |
136
|
|
|
|
137
|
|
|
if ( ! function_exists( 'get_transient' ) ) { |
138
|
|
|
/** |
139
|
|
|
* A drop-in for a WordPress core function. |
140
|
|
|
* |
141
|
|
|
* @param string $transient The transient to fetch. |
142
|
|
|
* @return mixed Transient value. |
143
|
|
|
*/ |
144
|
|
|
function get_transient( $transient ) { |
145
|
|
|
global $test_transients; |
146
|
|
|
if ( ! isset( $test_transients[ $transient ] ) ) { |
147
|
|
|
return false; |
148
|
|
|
} |
149
|
|
|
|
150
|
|
|
return $test_transients[ $transient ]['value']; |
151
|
|
|
} |
152
|
|
|
|
153
|
|
|
/** |
154
|
|
|
* A drop-in for a WordPress core function. |
155
|
|
|
* |
156
|
|
|
* @param string $transient The transient to set. |
157
|
|
|
* @param mixed $value The value to set. |
158
|
|
|
* @param int $expiration The expiration value, 0 for forever. |
159
|
|
|
* @return mixed Transient value. |
160
|
|
|
*/ |
161
|
|
|
function set_transient( $transient, $value, $expiration = 0 ) { |
162
|
|
|
global $test_transients; |
163
|
|
|
$test_transients[ $transient ] = array( |
164
|
|
|
'value' => $value, |
165
|
|
|
'expiration' => $expiration, |
166
|
|
|
); |
167
|
|
|
|
168
|
|
|
return true; |
169
|
|
|
} |
170
|
|
|
|
171
|
|
|
/** |
172
|
|
|
* Checks to see whether or not the test transient has been set to a specific value. |
173
|
|
|
* |
174
|
|
|
* @param string $transient The transient to check. |
175
|
|
|
* @param mixed $value The value to find. |
176
|
|
|
* @param int $expiration The expiration value, 0 for roever. |
177
|
|
|
* @return bool True if the transient is set, otherwise false. |
178
|
|
|
*/ |
179
|
|
|
function test_has_transient( $transient, $value, $expiration = 0 ) { |
180
|
|
|
global $test_transients; |
181
|
|
|
|
182
|
|
|
if ( ! isset( $test_transients[ $transient ] ) ) { |
183
|
|
|
return false; |
184
|
|
|
} |
185
|
|
|
|
186
|
|
|
$transient = $test_transients[ $transient ]; |
187
|
|
|
|
188
|
|
|
return $value === $transient['value'] && $expiration === $transient['expiration']; |
189
|
|
|
} |
190
|
|
|
} |
191
|
|
|
|
192
|
|
|
if ( ! function_exists( 'wp_normalize_path' ) ) { |
193
|
|
|
/** |
194
|
|
|
* A drop-in for a WordPress core function. |
195
|
|
|
* |
196
|
|
|
* @param string $path The path to normalize. |
197
|
|
|
* @return string The normalized path. |
198
|
|
|
*/ |
199
|
|
|
function wp_normalize_path( $path ) { |
200
|
|
|
$wrapper = ''; |
201
|
|
|
|
202
|
|
|
// Standardise all paths to use '/'. |
203
|
|
|
$path = str_replace( '\\', '/', $path ); |
204
|
|
|
|
205
|
|
|
// Replace multiple slashes down to a singular, allowing for network shares having two slashes. |
206
|
|
|
$path = preg_replace( '|(?<=.)/+|', '/', $path ); |
207
|
|
|
|
208
|
|
|
// Windows paths should uppercase the drive letter. |
209
|
|
|
if ( ':' === substr( $path, 1, 1 ) ) { |
210
|
|
|
$path = ucfirst( $path ); |
211
|
|
|
} |
212
|
|
|
|
213
|
|
|
return $wrapper . $path; |
214
|
|
|
} |
215
|
|
|
} |
216
|
|
|
|
217
|
|
|
if ( ! function_exists( 'is_multisite' ) ) { |
218
|
|
|
/** |
219
|
|
|
* A drop-in for a WordPress core function. |
220
|
|
|
* |
221
|
|
|
* @return bool |
222
|
|
|
*/ |
223
|
|
|
function is_multisite() { |
224
|
|
|
global $test_is_multisite; |
225
|
|
|
return (bool) $test_is_multisite; |
226
|
|
|
} |
227
|
|
|
|
228
|
|
|
/** |
229
|
|
|
* Sets whether or not we should be testing as multisite. |
230
|
|
|
* |
231
|
|
|
* @param bool $is_multisite What is returned by `is_multisite()`. |
232
|
|
|
*/ |
233
|
|
|
function set_test_is_multisite( $is_multisite ) { |
234
|
|
|
global $test_is_multisite; |
235
|
|
|
$test_is_multisite = $is_multisite; |
236
|
|
|
} |
237
|
|
|
} |
238
|
|
|
|
239
|
|
|
if ( ! function_exists( 'wp_json_encode' ) ) { |
240
|
|
|
/** |
241
|
|
|
* A drop-in for a WordPress core function. |
242
|
|
|
* |
243
|
|
|
* @param mixed $data Variable (usually an array or object) to encode as JSON. |
244
|
|
|
* @param int $options Options to be passed to json_encode(). Default 0. |
245
|
|
|
* @param int $depth Maximum depth to walk through $data. Must be greater than 0. |
246
|
|
|
* |
247
|
|
|
* @return false|string The JSON encoded string, or false if it cannot be encoded. |
248
|
|
|
*/ |
249
|
|
|
function wp_json_encode( $data, $options = 0, $depth = 512 ) { |
250
|
|
|
// phpcs:ignore WordPress.WP.AlternativeFunctions.json_encode_json_encode |
251
|
|
|
return json_encode( $data, $options, $depth ); |
252
|
|
|
} |
253
|
|
|
} |
254
|
|
|
|
255
|
|
|
if ( ! function_exists( 'add_action' ) ) { |
256
|
|
|
/** |
257
|
|
|
* A drop-in replacement for a WordPress function. |
258
|
|
|
* |
259
|
|
|
* @param string $tag The name of the action which is hooked. |
260
|
|
|
* @param callable $callable The function to call. |
261
|
|
|
* @param int $priority Used to specify the priority of the action. |
262
|
|
|
* @param int $accepted_args Used to specify the number of arguments the callable accepts. |
263
|
|
|
* |
264
|
|
|
* @return true |
265
|
|
|
*/ |
266
|
|
|
function add_action( $tag, $callable, $priority = 10, $accepted_args = 1 ) { |
267
|
|
|
return add_filter( $tag, $callable, $priority, $accepted_args ); |
268
|
|
|
} |
269
|
|
|
|
270
|
|
|
/** |
271
|
|
|
* A drop-in replacement for a WordPress function. |
272
|
|
|
* |
273
|
|
|
* @param string $tag The name of the action which is hooked. |
274
|
|
|
* @param callable $callable The function to call. |
275
|
|
|
* @param int $priority Used to specify the priority of the action. |
276
|
|
|
* @param int $accepted_args Used to specify the number of arguments the callable accepts. |
277
|
|
|
* |
278
|
|
|
* @return true |
279
|
|
|
*/ |
280
|
|
|
function add_filter( $tag, $callable, $priority = 10, $accepted_args = 1 ) { |
281
|
|
|
global $test_filters; |
282
|
|
|
|
283
|
|
|
$test_filters[ $tag ][] = array( |
284
|
|
|
'callable' => $callable, |
285
|
|
|
'priority' => $priority, |
286
|
|
|
'accepted_args' => $accepted_args, |
287
|
|
|
); |
288
|
|
|
|
289
|
|
|
return true; |
290
|
|
|
} |
291
|
|
|
|
292
|
|
|
/** |
293
|
|
|
* A drop-in replacement for a WordPress function. |
294
|
|
|
* |
295
|
|
|
* @param string $tag The name of the action which is hooked. |
296
|
|
|
* @param callable $callable The function to call. |
297
|
|
|
* @param int $priority Used to specify the priority of the action. |
298
|
|
|
* |
299
|
|
|
* @return bool True if removed, false if not. |
300
|
|
|
*/ |
301
|
|
|
function remove_action( $tag, $callable, $priority = 10 ) { |
302
|
|
|
return remove_filter( $tag, $callable, $priority ); |
303
|
|
|
} |
304
|
|
|
|
305
|
|
|
/** |
306
|
|
|
* A drop-in replacement for a WordPress function. |
307
|
|
|
* |
308
|
|
|
* @param string $tag The name of the filter which is hooked. |
309
|
|
|
* @param callable $callable The function to call. |
310
|
|
|
* @param int $priority Used to specify the priority of the filter. |
311
|
|
|
* |
312
|
|
|
* @return bool True if removed, false if not. |
313
|
|
|
*/ |
314
|
|
|
function remove_filter( $tag, $callable, $priority = 10 ) { |
315
|
|
|
global $test_filters; |
316
|
|
|
|
317
|
|
|
if ( ! isset( $test_filters[ $tag ] ) ) { |
318
|
|
|
return false; |
319
|
|
|
} |
320
|
|
|
|
321
|
|
|
foreach ( $test_filters[ $tag ] as $key => $record ) { |
322
|
|
|
if ( $record['callable'] !== $callable ) { |
323
|
|
|
continue; |
324
|
|
|
} |
325
|
|
|
|
326
|
|
|
if ( $record['priority'] !== $priority ) { |
327
|
|
|
continue; |
328
|
|
|
} |
329
|
|
|
|
330
|
|
|
unset( $test_filters[ $tag ][ $key ] ); |
331
|
|
|
return true; |
332
|
|
|
} |
333
|
|
|
|
334
|
|
|
return false; |
335
|
|
|
} |
336
|
|
|
|
337
|
|
|
/** |
338
|
|
|
* A drop-in replacement for a WordPress function. |
339
|
|
|
* |
340
|
|
|
* @param string $tag The name of the action which is hooked. |
341
|
|
|
* @param mixed ...$arg The arguments to pass to the action. |
342
|
|
|
*/ |
343
|
|
|
function do_action( $tag, ...$arg ) { |
344
|
|
|
global $test_executed_actions; |
345
|
|
|
|
346
|
|
|
if ( ! isset( $test_executed_actions ) ) { |
347
|
|
|
$test_executed_actions = array(); |
348
|
|
|
} |
349
|
|
|
|
350
|
|
|
$test_executed_actions[ $tag ][] = $arg; |
351
|
|
|
|
352
|
|
|
global $test_filters; |
353
|
|
|
if ( isset( $test_filters[ $tag ] ) ) { |
354
|
|
|
foreach ( $test_filters[ $tag ] as $record ) { |
355
|
|
|
if ( empty( $record['accepted_args'] ) ) { |
356
|
|
|
call_user_func( $record['callable'] ); |
357
|
|
|
} else { |
358
|
|
|
call_user_func_array( $record['callable'], $arg ); |
359
|
|
|
} |
360
|
|
|
} |
361
|
|
|
} |
362
|
|
|
} |
363
|
|
|
|
364
|
|
|
/** |
365
|
|
|
* A drop-in replacement for a WordPress function. |
366
|
|
|
* |
367
|
|
|
* @param string $tag The name of the action which is hooked. |
368
|
|
|
* @return bool True if the action was executed, otherwise false. |
369
|
|
|
*/ |
370
|
|
|
function did_action( $tag ) { |
371
|
|
|
global $test_executed_actions; |
372
|
|
|
return isset( $test_executed_actions[ $tag ] ); |
373
|
|
|
} |
374
|
|
|
|
375
|
|
|
/** |
376
|
|
|
* Checks to see if the given filter has been added. |
377
|
|
|
* |
378
|
|
|
* @param string $tag The name of the action which is hooked. |
379
|
|
|
* @param callable $callable The function to call. |
380
|
|
|
* @param int $priority Used to specify the priority of the action. |
381
|
|
|
* @param int $accepted_args Used to specify the number of arguments the callable accepts. |
382
|
|
|
* |
383
|
|
|
* @return bool |
384
|
|
|
*/ |
385
|
|
|
function test_has_filter( $tag, $callable, $priority = 10, $accepted_args = 1 ) { |
386
|
|
|
global $test_filters; |
387
|
|
|
|
388
|
|
|
if ( ! isset( $test_filters[ $tag ] ) ) { |
389
|
|
|
return false; |
390
|
|
|
} |
391
|
|
|
|
392
|
|
|
foreach ( $test_filters[ $tag ] as $record ) { |
393
|
|
|
if ( $record['callable'] !== $callable ) { |
394
|
|
|
continue; |
395
|
|
|
} |
396
|
|
|
|
397
|
|
|
if ( $record['priority'] !== $priority ) { |
398
|
|
|
continue; |
399
|
|
|
} |
400
|
|
|
|
401
|
|
|
if ( $record['accepted_args'] !== $accepted_args ) { |
402
|
|
|
continue; |
403
|
|
|
} |
404
|
|
|
|
405
|
|
|
return true; |
406
|
|
|
} |
407
|
|
|
|
408
|
|
|
return false; |
409
|
|
|
} |
410
|
|
|
} |
411
|
|
|
|
412
|
|
|
/** |
413
|
|
|
* A function to clean up all of the test data added by the test suite. |
414
|
|
|
*/ |
415
|
|
|
function cleanup_test_wordpress_data() { |
416
|
|
|
global $test_options; |
417
|
|
|
$test_options = array(); |
418
|
|
|
global $test_site_options; |
419
|
|
|
$test_site_options = array(); |
420
|
|
|
global $test_is_multisite; |
421
|
|
|
$test_is_multisite = false; |
422
|
|
|
global $test_filters; |
423
|
|
|
$test_filters = array(); |
424
|
|
|
global $test_transients; |
425
|
|
|
$test_transients = array(); |
426
|
|
|
} |
427
|
|
|
|
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.
You can also find more detailed suggestions in the “Code” section of your repository.