1
|
|
|
<?php |
2
|
|
|
|
3
|
|
|
/** |
4
|
|
|
* Extensions related functions. |
5
|
|
|
* |
6
|
|
|
* This class loads, registers, activates and deactivates extensions. |
7
|
|
|
* |
8
|
|
|
* The name of this file and many of the functions reflects the fact that extensions |
9
|
|
|
* used to be called "modules". Over time the term "module" will be completely |
10
|
|
|
* dropped from all APIs in favor of "extension", but it was decided that this would |
11
|
|
|
* be done partly as the APIs organically evolve, rather than renaming them all at |
12
|
|
|
* once. |
13
|
|
|
* |
14
|
|
|
* @package WordPoints\Extensions |
15
|
|
|
* @since 1.0.0 |
16
|
|
|
*/ |
17
|
|
|
|
18
|
|
|
/** |
19
|
|
|
* Checks if a module is active. |
20
|
|
|
* |
21
|
|
|
* @since 1.1.0 |
22
|
|
|
* |
23
|
|
|
* @param string $module The module file. |
24
|
|
|
* |
25
|
|
|
* @return bool Whether the module is active. |
26
|
|
|
*/ |
27
|
|
|
function is_wordpoints_module_active( $module ) { |
28
|
|
|
|
29
|
|
|
$is_active = ( |
30
|
|
|
in_array( |
31
|
|
|
$module |
32
|
|
|
, wordpoints_get_array_option( 'wordpoints_active_modules' ) |
33
|
|
|
, true |
34
|
|
|
) |
35
|
|
|
|| is_wordpoints_module_active_for_network( $module ) |
36
|
|
|
); |
37
|
|
|
|
38
|
|
|
/** |
39
|
|
|
* Filters whether a WordPoints extension is active. |
40
|
|
|
* |
41
|
|
|
* @since 2.4.0 |
42
|
|
|
* |
43
|
|
|
* @param bool $is_active Whether the extension is active. |
44
|
|
|
*/ |
45
|
|
|
return (bool) apply_filters( 'is_wordpoints_extension_active', $is_active ); |
|
|
|
|
46
|
|
|
} |
47
|
|
|
|
48
|
|
|
/** |
49
|
|
|
* Check if a module is active for the entire network. |
50
|
|
|
* |
51
|
|
|
* @since 1.1.0 |
52
|
|
|
* |
53
|
|
|
* @param string $module The module to check the activity status of. |
54
|
|
|
* |
55
|
|
|
* @return bool Whether the module is network active. |
56
|
|
|
*/ |
57
|
|
|
function is_wordpoints_module_active_for_network( $module ) { |
58
|
|
|
|
59
|
|
|
if ( ! is_wordpoints_network_active() ) { |
60
|
|
|
return false; |
61
|
|
|
} |
62
|
|
|
|
63
|
|
|
$modules = wordpoints_get_array_option( 'wordpoints_sitewide_active_modules', 'site' ); |
64
|
|
|
|
65
|
|
|
if ( isset( $modules[ $module ] ) ) { |
66
|
|
|
return true; |
67
|
|
|
} |
68
|
|
|
|
69
|
|
|
return false; |
70
|
|
|
} |
71
|
|
|
|
72
|
|
|
/** |
73
|
|
|
* Check whether a module is only to be network activated. |
74
|
|
|
* |
75
|
|
|
* Checks for "Network: true" in the module header to see if it should be activated |
76
|
|
|
* only as a network-wide module. (The module would also work when Multisite is not |
77
|
|
|
* enabled.) |
78
|
|
|
* |
79
|
|
|
* Note that passing an invalid path will result in errors. |
80
|
|
|
* |
81
|
|
|
* @since 1.1.0 |
82
|
|
|
* |
83
|
|
|
* @param string $module Basename path of the module to check. |
84
|
|
|
* |
85
|
|
|
* @return bool True if the module is network only, false otherwise. |
86
|
|
|
*/ |
87
|
|
|
function is_network_only_wordpoints_module( $module ) { // @codingStandardsIgnoreLine |
88
|
|
|
|
89
|
|
|
$module_data = wordpoints_get_module_data( wordpoints_extensions_dir() . '/' . $module ); |
90
|
|
|
|
91
|
|
|
return $module_data['network']; |
92
|
|
|
} |
93
|
|
|
|
94
|
|
|
/** |
95
|
|
|
* Check if a module has an uninstall file. |
96
|
|
|
* |
97
|
|
|
* @since 1.1.0 |
98
|
|
|
* |
99
|
|
|
* @param string $module The module to check. |
100
|
|
|
* |
101
|
|
|
* @return bool True if the module has an uninstall script, false otherwise. |
102
|
|
|
*/ |
103
|
|
|
function is_uninstallable_wordpoints_module( $module ) { // @codingStandardsIgnoreLine |
104
|
|
|
|
105
|
|
|
return ( file_exists( wordpoints_extensions_dir() . '/' . dirname( wordpoints_module_basename( $module ) ) . '/uninstall.php' ) ); |
106
|
|
|
} |
107
|
|
|
|
108
|
|
|
/** |
109
|
|
|
* Get the path to the extensions directory. |
110
|
|
|
* |
111
|
|
|
* @since 1.1.0 |
112
|
|
|
* @deprecated 2.4.0 Use wordpoints_extensions_dir() instead. |
113
|
|
|
* |
114
|
|
|
* @return string The full extension folder path. |
115
|
|
|
*/ |
116
|
|
|
function wordpoints_modules_dir() { |
117
|
|
|
|
118
|
|
|
_deprecated_function( __FUNCTION__, '2.4.0', 'wordpoints_extensions_dir' ); |
|
|
|
|
119
|
|
|
|
120
|
|
|
return wordpoints_extensions_dir(); |
121
|
|
|
} |
122
|
|
|
|
123
|
|
|
/** |
124
|
|
|
* Get the path to the extensions directory. |
125
|
|
|
* |
126
|
|
|
* The default is /wp-content/wordpoints-extensions/. To override this, define the |
127
|
|
|
* WORDPOINTS_EXTENSIONS_DIR constant in wp-config.php like this: |
128
|
|
|
* |
129
|
|
|
* define( 'WORDPOINTS_EXTENSIONS_DIR', '/my/custom/path/' ); |
130
|
|
|
* |
131
|
|
|
* The value may also be filtered with the 'wordpoints_extensions_dir' filter. |
132
|
|
|
* |
133
|
|
|
* @since 2.4.0 |
134
|
|
|
* |
135
|
|
|
* @return string The full module folder path. |
136
|
|
|
*/ |
137
|
|
|
function wordpoints_extensions_dir() { |
138
|
|
|
|
139
|
|
|
static $extensions_dir; |
140
|
|
|
|
141
|
|
|
if ( ! $extensions_dir ) { |
142
|
|
|
|
143
|
|
|
if ( defined( 'WORDPOINTS_EXTENSIONS_DIR' ) ) { |
144
|
|
|
|
145
|
|
|
$extensions_dir = trailingslashit( WORDPOINTS_EXTENSIONS_DIR ); |
|
|
|
|
146
|
|
|
|
147
|
|
|
} elseif ( defined( 'WORDPOINTS_MODULES_DIR' ) ) { |
148
|
|
|
|
149
|
|
|
_deprecated_argument( |
|
|
|
|
150
|
|
|
__FUNCTION__ |
151
|
|
|
, '2.4.0' |
152
|
|
|
, 'The WORDPOINTS_MODULES_DIR constant is deprecated in favor of WORDPOINTS_EXTENSIONS_DIR.' |
153
|
|
|
); |
154
|
|
|
|
155
|
|
|
$extensions_dir = trailingslashit( WORDPOINTS_MODULES_DIR ); |
|
|
|
|
156
|
|
|
|
157
|
|
|
} else { |
158
|
|
|
|
159
|
|
|
$extensions_dir = WP_CONTENT_DIR . '/wordpoints-extensions/'; |
|
|
|
|
160
|
|
|
} |
161
|
|
|
} |
162
|
|
|
|
163
|
|
|
/** |
164
|
|
|
* Filter the path to the extensions directory. |
165
|
|
|
* |
166
|
|
|
* @since 1.1.0 |
167
|
|
|
* @since 2.2.0 The filter is no longer called only once per page load. |
168
|
|
|
* |
169
|
|
|
* @param string $extensions_dir The full path to the extensions folder. |
170
|
|
|
*/ |
171
|
|
|
$dir = apply_filters_deprecated( |
|
|
|
|
172
|
|
|
'wordpoints_modules_dir' |
173
|
|
|
, array( $extensions_dir ) |
174
|
|
|
, '2.4.0' |
175
|
|
|
, 'wordpoints_extensions_dir' |
176
|
|
|
); |
177
|
|
|
|
178
|
|
|
/** |
179
|
|
|
* Filter the path to the extensions directory. |
180
|
|
|
* |
181
|
|
|
* @since 2.4.0 |
182
|
|
|
* |
183
|
|
|
* @param string $extensions_dir The full path to the extensions folder. |
184
|
|
|
*/ |
185
|
|
|
return apply_filters( 'wordpoints_extensions_dir', $dir ); |
186
|
|
|
} |
187
|
|
|
|
188
|
|
|
/** |
189
|
|
|
* Replaces the new extensions directory path with the legacy path as needed. |
190
|
|
|
* |
191
|
|
|
* @since 2.4.0 |
192
|
|
|
* |
193
|
|
|
* @WordPress\filter wordpoints_extensions_dir |
194
|
|
|
* @WordPress\filter wordpoints_extensions_url |
195
|
|
|
* |
196
|
|
|
* @param string $path The path. |
197
|
|
|
* |
198
|
|
|
* @return string The filtered path. |
199
|
|
|
*/ |
200
|
|
|
function wordpoints_legacy_modules_path( $path ) { |
201
|
|
|
|
202
|
|
|
if ( is_wordpoints_network_active() ) { |
203
|
|
|
$wordpoints_data = get_site_option( 'wordpoints_data' ); |
|
|
|
|
204
|
|
|
} else { |
205
|
|
|
$wordpoints_data = get_option( 'wordpoints_data' ); |
|
|
|
|
206
|
|
|
} |
207
|
|
|
|
208
|
|
|
// If the legacy directory could not be moved, or we haven't done the update yet. |
209
|
|
|
if ( |
210
|
|
|
get_site_option( 'wordpoints_legacy_extensions_dir' ) |
211
|
|
|
|| ( |
212
|
|
|
isset( $wordpoints_data['version'] ) |
213
|
|
|
&& version_compare( $wordpoints_data['version'], '2.4.0-alpha-3', '<' ) |
214
|
|
|
) |
215
|
|
|
) { |
216
|
|
|
$path = str_replace( |
217
|
|
|
'/wordpoints-extensions' |
218
|
|
|
, '/wordpoints-modules' |
219
|
|
|
, $path |
220
|
|
|
); |
221
|
|
|
} |
222
|
|
|
|
223
|
|
|
return $path; |
224
|
|
|
} |
225
|
|
|
|
226
|
|
|
/** |
227
|
|
|
* Get the URL for the extensions directory or to a specific file in that directory. |
228
|
|
|
* |
229
|
|
|
* @since 1.4.0 |
230
|
|
|
* @deprecated 2.4.0 Use wordpoints_extensions_url() instead. |
231
|
|
|
* |
232
|
|
|
* @param string $path A relative path to a file or folder. |
233
|
|
|
* @param string $module An extension file that the $path should be relative to. |
234
|
|
|
* |
235
|
|
|
* @return string The URL for the path passed. |
236
|
|
|
*/ |
237
|
|
|
function wordpoints_modules_url( $path = '', $module = '' ) { |
238
|
|
|
|
239
|
|
|
_deprecated_function( __FUNCTION__, '2.4.0', 'wordpoints_extensions_url' ); |
|
|
|
|
240
|
|
|
|
241
|
|
|
return wordpoints_extensions_url( $path, $module ); |
242
|
|
|
} |
243
|
|
|
|
244
|
|
|
/** |
245
|
|
|
* Get the URL for the extensions directory or to a specific file in that directory. |
246
|
|
|
* |
247
|
|
|
* @since 2.4.0 |
248
|
|
|
* |
249
|
|
|
* @param string $path A relative path to a file or folder. |
250
|
|
|
* @param string $extension An extension file that the $path should be relative to. |
251
|
|
|
* |
252
|
|
|
* @return string The URL for the path passed. |
253
|
|
|
*/ |
254
|
|
|
function wordpoints_extensions_url( $path = '', $extension = '' ) { |
255
|
|
|
|
256
|
|
|
$path = wp_normalize_path( $path ); |
|
|
|
|
257
|
|
|
$extension = wp_normalize_path( $extension ); |
258
|
|
|
|
259
|
|
|
if ( defined( 'WORDPOINTS_EXTENSIONS_URL' ) ) { |
260
|
|
|
|
261
|
|
|
$url = WORDPOINTS_EXTENSIONS_URL; |
|
|
|
|
262
|
|
|
|
263
|
|
|
} elseif ( defined( 'WORDPOINTS_MODULES_URL' ) ) { |
264
|
|
|
|
265
|
|
|
$url = WORDPOINTS_MODULES_URL; |
|
|
|
|
266
|
|
|
|
267
|
|
|
_deprecated_argument( |
|
|
|
|
268
|
|
|
__FUNCTION__ |
269
|
|
|
, '2.4.0' |
270
|
|
|
, 'The WORDPOINTS_MODULES_URL constant is deprecated in favor of WORDPOINTS_EXTENSIONS_URL.' |
271
|
|
|
); |
272
|
|
|
|
273
|
|
|
} else { |
274
|
|
|
|
275
|
|
|
$url = WP_CONTENT_URL . '/wordpoints-extensions'; |
|
|
|
|
276
|
|
|
} |
277
|
|
|
|
278
|
|
|
$url = set_url_scheme( $url ); |
|
|
|
|
279
|
|
|
|
280
|
|
|
if ( ! empty( $extension ) && is_string( $extension ) ) { |
281
|
|
|
|
282
|
|
|
$folder = dirname( wordpoints_module_basename( $extension ) ); |
283
|
|
|
|
284
|
|
|
if ( '.' !== $folder ) { |
285
|
|
|
$url .= '/' . ltrim( $folder, '/' ); |
286
|
|
|
} |
287
|
|
|
} |
288
|
|
|
|
289
|
|
|
if ( $path && is_string( $path ) ) { |
290
|
|
|
$url .= '/' . ltrim( $path, '/' ); |
291
|
|
|
} |
292
|
|
|
|
293
|
|
|
/** |
294
|
|
|
* Filters the URL of a file or folder in the extensions directory. |
295
|
|
|
* |
296
|
|
|
* @since 1.4.0 |
297
|
|
|
* @deprecated 2.4.0 Use 'wordpoints_extensions_url' instead. |
298
|
|
|
* |
299
|
|
|
* @param string $url The URL of the file or folder. |
300
|
|
|
* @param string $path A relative path to a file or folder. |
301
|
|
|
* @param string $extension An extension that the $path should be relative to. |
302
|
|
|
*/ |
303
|
|
|
$url = apply_filters_deprecated( |
|
|
|
|
304
|
|
|
'wordpoints_modules_url' |
305
|
|
|
, array( $url, $path, $extension ) |
306
|
|
|
, '2.4.0' |
307
|
|
|
, 'wordpoints_extensions_url' |
308
|
|
|
); |
309
|
|
|
|
310
|
|
|
/** |
311
|
|
|
* Filters the URL of a file or folder in the extensions directory. |
312
|
|
|
* |
313
|
|
|
* @since 2.4.0 |
314
|
|
|
* |
315
|
|
|
* @param string $url The URL of the file or folder. |
316
|
|
|
* @param string $path A relative path to a file or folder. |
317
|
|
|
* @param string $extension An extension that the $path should be relative to. |
318
|
|
|
*/ |
319
|
|
|
return apply_filters( 'wordpoints_extensions_url', $url, $path, $extension ); |
|
|
|
|
320
|
|
|
} |
321
|
|
|
|
322
|
|
|
/** |
323
|
|
|
* Get the basename of a module. |
324
|
|
|
* |
325
|
|
|
* @since 1.1.0 |
326
|
|
|
* |
327
|
|
|
* @param string $file The path to a module file. |
328
|
|
|
* |
329
|
|
|
* @return string The name of the module file. |
330
|
|
|
*/ |
331
|
|
|
function wordpoints_module_basename( $file ) { |
332
|
|
|
|
333
|
|
|
// Sanitize, and resolve possible symlink path from what is likely a real path. |
334
|
|
|
$file = WordPoints_Module_Paths::resolve( $file ); |
335
|
|
|
|
336
|
|
|
// Sanitize for Win32 installs and remove any duplicate slashes. |
337
|
|
|
$modules_dir = wp_normalize_path( wordpoints_extensions_dir() ); |
|
|
|
|
338
|
|
|
|
339
|
|
|
// Get the relative path from the modules directory, and trim off the slashes. |
340
|
|
|
$file = preg_replace( '#^' . preg_quote( $modules_dir, '#' ) . '#', '', $file ); |
341
|
|
|
$file = trim( $file, '/' ); |
342
|
|
|
|
343
|
|
|
return $file; |
344
|
|
|
} |
345
|
|
|
|
346
|
|
|
/** |
347
|
|
|
* Registers an extension. |
348
|
|
|
* |
349
|
|
|
* @since 2.4.0 |
350
|
|
|
* |
351
|
|
|
* @param string $data The header data for the extension. |
352
|
|
|
* @param string $file The full path to the main file of the extension. |
353
|
|
|
* |
354
|
|
|
* @return bool True, or false if the extension has already been registered. |
355
|
|
|
*/ |
356
|
|
|
function wordpoints_register_extension( $data, $file ) { |
357
|
|
|
return WordPoints_Modules::register( $data, $file ); |
358
|
|
|
} |
359
|
|
|
|
360
|
|
|
/** |
361
|
|
|
* Gets the installed version of an extension. |
362
|
|
|
* |
363
|
|
|
* @since 2.4.0 |
364
|
|
|
* |
365
|
|
|
* @param string $extension The full path to one of the extension's files. |
366
|
|
|
* |
367
|
|
|
* @return string|false The extension version, or false on failure. |
368
|
|
|
*/ |
369
|
|
|
function wordpoints_get_extension_version( $extension ) { |
370
|
|
|
return WordPoints_Modules::get_data( $extension, 'version' ); |
371
|
|
|
} |
372
|
|
|
|
373
|
|
|
/** |
374
|
|
|
* Parse the module contents to retrieve module's metadata. |
375
|
|
|
* |
376
|
|
|
* Module metadata headers are essentially the same as WordPress plugin headers. The |
377
|
|
|
* main difference is that the module name is "Extension Name:" instead of "Plugin |
378
|
|
|
* Name:". |
379
|
|
|
* |
380
|
|
|
* @since 1.1.0 |
381
|
|
|
* @since 1.6.0 The 'update_api' and 'ID' headers are now supported. |
382
|
|
|
* @since 1.10.0 The 'update_api' header is deprecated in favor of 'channel'. |
383
|
|
|
* @since 2.2.0 The 'namespace' header is now supported. |
384
|
|
|
* @since 2.4.0 - The 'channel' header is deprecated in favor of 'server'. |
385
|
|
|
* - The 'module_uri' header is deprecated in favor of 'uri'. |
386
|
|
|
* |
387
|
|
|
* @param string $module_file The file to parse for the headers. |
388
|
|
|
* @param bool $markup Whether to mark up the module data for display (default). |
389
|
|
|
* @param bool $translate Whether to translate the module data. Default is true. |
390
|
|
|
* |
391
|
|
|
* @return array { |
392
|
|
|
* The module header data. |
393
|
|
|
* |
394
|
|
|
* @type string $name The Extension Name. |
395
|
|
|
* @type string $title The module's title. May be a link if $markup is true. |
396
|
|
|
* @type string $uri The URI of the extension's home page. |
397
|
|
|
* @type string $version The module's version number. |
398
|
|
|
* @type string $description A description of the module. |
399
|
|
|
* @type string $author The module's author. May be a link if $markup is true. |
400
|
|
|
* @type string $author The module author's name. |
401
|
|
|
* @type string $author_uri The URI of the module author's home page. |
402
|
|
|
* @type string $text_domain The module's text domain. |
403
|
|
|
* @type string $domain_path The folder containing the module's *.mo translation files. |
404
|
|
|
* @type bool $network Whether the module should only be network activated. |
405
|
|
|
* @type string $server The slug of the remote server for this module (like for updates, etc.). |
406
|
|
|
* @type mixed $ID A unique identifier for this module, used by the update service. |
407
|
|
|
* @type string $namespace The namespace for this module. Should be Title_Case, and omit "WordPoints" prefix. |
408
|
|
|
* } |
409
|
|
|
*/ |
410
|
|
|
function wordpoints_get_module_data( $module_file, $markup = true, $translate = true ) { |
411
|
|
|
|
412
|
|
|
$default_headers = array( |
413
|
|
|
'name' => 'Extension Name', |
414
|
|
|
'uri' => 'Extension URI', |
415
|
|
|
'module_name' => 'Module Name', |
416
|
|
|
'module_uri' => 'Module URI', |
417
|
|
|
'version' => 'Version', |
418
|
|
|
'description' => 'Description', |
419
|
|
|
'author' => 'Author', |
420
|
|
|
'author_uri' => 'Author URI', |
421
|
|
|
'text_domain' => 'Text Domain', |
422
|
|
|
'domain_path' => 'Domain Path', |
423
|
|
|
'network' => 'Network', |
424
|
|
|
'update_api' => 'Update API', |
425
|
|
|
'channel' => 'Channel', |
426
|
|
|
'server' => 'Server', |
427
|
|
|
'ID' => 'ID', |
428
|
|
|
'namespace' => 'Namespace', |
429
|
|
|
); |
430
|
|
|
|
431
|
|
|
$module_data = WordPoints_Modules::get_data( $module_file ); |
432
|
|
|
|
433
|
|
|
if ( $module_data && wp_normalize_path( $module_file ) === $module_data['raw_file'] ) { |
|
|
|
|
434
|
|
|
unset( $module_data['raw'], $module_data['raw_file'] ); |
435
|
|
|
} else { |
436
|
|
|
$module_data = get_file_data( $module_file, $default_headers, 'wordpoints_module' ); |
|
|
|
|
437
|
|
|
} |
438
|
|
|
|
439
|
|
|
if ( ! empty( $module_data['update_api'] ) ) { |
440
|
|
|
_deprecated_argument( __FUNCTION__, '1.10.0', 'The "Update API" module header has been deprecated in favor of "Server".' ); |
|
|
|
|
441
|
|
|
} |
442
|
|
|
|
443
|
|
|
if ( ! empty( $module_data['channel'] ) ) { |
444
|
|
|
_deprecated_argument( __FUNCTION__, '2.4.0', 'The "Channel" extension header has been deprecated in favor of "Server".' ); |
445
|
|
|
$module_data['server'] = $module_data['channel']; |
446
|
|
|
} |
447
|
|
|
|
448
|
|
|
if ( ! empty( $module_data['module_name'] ) ) { |
449
|
|
|
_deprecated_argument( __FUNCTION__, '2.4.0', 'The "Module Name" extension header has been deprecated in favor of "Extension Name".' ); |
450
|
|
|
$module_data['name'] = $module_data['module_name']; |
451
|
|
|
} |
452
|
|
|
|
453
|
|
|
unset( $module_data['module_name'] ); |
454
|
|
|
|
455
|
|
|
if ( ! empty( $module_data['module_uri'] ) ) { |
456
|
|
|
_deprecated_argument( __FUNCTION__, '2.4.0', 'The "Module URI" extension header has been deprecated in favor of "Extension URI".' ); |
457
|
|
|
$module_data['uri'] = $module_data['module_uri']; |
458
|
|
|
} else { |
459
|
|
|
$module_data['module_uri'] = $module_data['uri']; |
460
|
|
|
} |
461
|
|
|
|
462
|
|
|
$module_data['network'] = ( 'true' === strtolower( $module_data['network'] ) ); |
463
|
|
|
|
464
|
|
|
/** |
465
|
|
|
* Filters the header data for an extension. |
466
|
|
|
* |
467
|
|
|
* @since 2.4.0 |
468
|
|
|
* |
469
|
|
|
* @param array $extension_data The extension header data. |
470
|
|
|
* @param string $extension_file The full path of the main extension file. |
471
|
|
|
*/ |
472
|
|
|
$module_data = apply_filters( 'wordpoints_extension_data', $module_data, $module_file ); |
|
|
|
|
473
|
|
|
|
474
|
|
|
if ( $markup || $translate ) { |
475
|
|
|
|
476
|
|
|
// Sanitize the plugin filename to a WP_module_DIR relative path |
477
|
|
|
$module_file = wordpoints_module_basename( $module_file ); |
478
|
|
|
|
479
|
|
|
// Translate fields |
480
|
|
|
if ( $translate ) { |
481
|
|
|
|
482
|
|
|
$textdomain = $module_data['text_domain']; |
483
|
|
|
|
484
|
|
|
if ( $textdomain ) { |
485
|
|
|
|
486
|
|
|
if ( ! is_textdomain_loaded( $textdomain ) ) { |
|
|
|
|
487
|
|
|
|
488
|
|
|
$domain_path = dirname( $module_file ); |
489
|
|
|
|
490
|
|
|
if ( $module_data['domain_path'] ) { |
491
|
|
|
$domain_path .= $module_data['domain_path']; |
492
|
|
|
} |
493
|
|
|
|
494
|
|
|
wordpoints_load_module_textdomain( $textdomain, $domain_path ); |
495
|
|
|
} |
496
|
|
|
|
497
|
|
|
foreach ( array( 'name', 'uri', 'module_uri', 'description', 'author', 'author_uri', 'version' ) as $field ) { |
498
|
|
|
|
499
|
|
|
$module_data[ $field ] = translate( $module_data[ $field ], $textdomain ); // @codingStandardsIgnoreLine |
|
|
|
|
500
|
|
|
} |
501
|
|
|
} |
502
|
|
|
} |
503
|
|
|
|
504
|
|
|
// Sanitize fields. |
505
|
|
|
$allowed_tags_in_links = array( |
506
|
|
|
'abbr' => array( 'title' => true ), |
507
|
|
|
'acronym' => array( 'title' => true ), |
508
|
|
|
'code' => true, |
509
|
|
|
'em' => true, |
510
|
|
|
'strong' => true, |
511
|
|
|
); |
512
|
|
|
|
513
|
|
|
$allowed_tags = $allowed_tags_in_links; |
514
|
|
|
$allowed_tags['a'] = array( 'href' => true, 'title' => true ); |
515
|
|
|
|
516
|
|
|
// Name and author ar marked up inside <a> tags. Don't allow these. |
517
|
|
|
$module_data['name'] = wp_kses( $module_data['name'] , $allowed_tags_in_links ); |
|
|
|
|
518
|
|
|
$module_data['author'] = wp_kses( $module_data['author'], $allowed_tags_in_links ); |
519
|
|
|
|
520
|
|
|
$module_data['description'] = wp_kses( $module_data['description'], $allowed_tags ); |
521
|
|
|
$module_data['version'] = wp_kses( $module_data['version'] , $allowed_tags ); |
522
|
|
|
|
523
|
|
|
$module_data['uri'] = esc_url( $module_data['uri'] ); |
|
|
|
|
524
|
|
|
$module_data['module_uri'] = esc_url( $module_data['module_uri'] ); |
525
|
|
|
$module_data['author_uri'] = esc_url( $module_data['author_uri'] ); |
526
|
|
|
|
527
|
|
|
$module_data['title'] = $module_data['name']; |
528
|
|
|
$module_data['author_name'] = $module_data['author']; |
529
|
|
|
|
530
|
|
|
// Apply markup. |
531
|
|
|
if ( $markup ) { |
532
|
|
|
|
533
|
|
|
if ( $module_data['uri'] && $module_data['name'] ) { |
534
|
|
|
$module_data['title'] = '<a href="' . $module_data['uri'] |
535
|
|
|
. '">' . $module_data['name'] . '</a>'; |
536
|
|
|
} |
537
|
|
|
|
538
|
|
|
if ( $module_data['author_uri'] && $module_data['author'] ) { |
539
|
|
|
$module_data['author'] = '<a href="' . $module_data['author_uri'] |
540
|
|
|
. '">' . $module_data['author'] . '</a>'; |
541
|
|
|
} |
542
|
|
|
|
543
|
|
|
$module_data['description'] = wptexturize( $module_data['description'] ); |
|
|
|
|
544
|
|
|
|
545
|
|
|
if ( $module_data['author'] ) { |
546
|
|
|
$module_data['description'] .= ' <cite>' |
547
|
|
|
// translators: Author name. |
548
|
|
|
. sprintf( __( 'By %s.', 'wordpoints' ), $module_data['author'] ) |
|
|
|
|
549
|
|
|
. '</cite>'; |
550
|
|
|
} |
551
|
|
|
} |
552
|
|
|
|
553
|
|
|
} else { |
554
|
|
|
|
555
|
|
|
$module_data['title'] = $module_data['name']; |
556
|
|
|
$module_data['author_name'] = $module_data['author']; |
557
|
|
|
|
558
|
|
|
} // End if ( $markup || $translate ) else. |
559
|
|
|
|
560
|
|
|
return $module_data; |
561
|
|
|
} |
562
|
|
|
|
563
|
|
|
/** |
564
|
|
|
* Get the server for an extension. |
565
|
|
|
* |
566
|
|
|
* @since 2.4.0 |
567
|
|
|
* |
568
|
|
|
* @param array $extension The extension to get the server for. |
569
|
|
|
* |
570
|
|
|
* @return WordPoints_Extension_ServerI|false The object for the server to use for |
571
|
|
|
* this extension, or false. |
572
|
|
|
*/ |
573
|
|
|
function wordpoints_get_server_for_extension( $extension ) { |
574
|
|
|
|
575
|
|
|
$server = false; |
576
|
|
|
|
577
|
|
|
if ( isset( $extension['server'] ) ) { |
578
|
|
|
$server = $extension['server']; |
579
|
|
|
} |
580
|
|
|
|
581
|
|
|
/** |
582
|
|
|
* Filter the server to use for an extension. |
583
|
|
|
* |
584
|
|
|
* @since 1.0.0 |
585
|
|
|
* |
586
|
|
|
* @param string|false $server The slug of the server to use, or false for none. |
587
|
|
|
* @param array $extension The extension's header data. |
588
|
|
|
*/ |
589
|
|
|
$server = apply_filters( 'wordpoints_server_for_extension', $server, $extension ); |
|
|
|
|
590
|
|
|
|
591
|
|
|
if ( ! $server ) { |
592
|
|
|
return false; |
593
|
|
|
} |
594
|
|
|
|
595
|
|
|
$server = new WordPoints_Extension_Server( $server ); |
596
|
|
|
|
597
|
|
|
/** |
598
|
|
|
* Filter the server object to use for an extension. |
599
|
|
|
* |
600
|
|
|
* @since 1.0.0 |
601
|
|
|
* |
602
|
|
|
* @param WordPoints_Extension_ServerI $server The server object to use. |
603
|
|
|
* @param array $extension The extension's header data. |
604
|
|
|
*/ |
605
|
|
|
$server = apply_filters( 'wordpoints_server_object_for_extension', $server, $extension ); |
606
|
|
|
|
607
|
|
|
if ( ! $server instanceof WordPoints_Extension_ServerI ) { |
608
|
|
|
return false; |
609
|
|
|
} |
610
|
|
|
|
611
|
|
|
return $server; |
612
|
|
|
} |
613
|
|
|
|
614
|
|
|
/** |
615
|
|
|
* Load a module's text domain. |
616
|
|
|
* |
617
|
|
|
* @since 1.1.0 |
618
|
|
|
* |
619
|
|
|
* @param string $domain The module's text domain. |
620
|
|
|
* @param string|bool $module_rel_path The module path relative to the modules |
621
|
|
|
* directory where the .mo files are, or false. |
622
|
|
|
* |
623
|
|
|
* @return bool Whether the textdoamin was loaded successfully. |
624
|
|
|
*/ |
625
|
|
|
function wordpoints_load_module_textdomain( $domain, $module_rel_path = false ) { |
626
|
|
|
|
627
|
|
|
$locale = get_locale(); |
|
|
|
|
628
|
|
|
|
629
|
|
|
/** |
630
|
|
|
* Filter a module's locale. |
631
|
|
|
* |
632
|
|
|
* @since 1.1.0 |
633
|
|
|
* |
634
|
|
|
* @param string $locale The module's current locale. |
635
|
|
|
* @param string $domain Text domain. Unique identifier for retrieving translated strings. |
636
|
|
|
*/ |
637
|
|
|
$locale = apply_filters( 'wordpoints_module_locale', $locale, $domain ); |
|
|
|
|
638
|
|
|
|
639
|
|
|
if ( false !== $module_rel_path ) { |
640
|
|
|
|
641
|
|
|
$path = wordpoints_extensions_dir() . '/' . trim( $module_rel_path, '/' ); |
|
|
|
|
642
|
|
|
|
643
|
|
|
} else { |
644
|
|
|
|
645
|
|
|
$path = wordpoints_extensions_dir(); |
646
|
|
|
} |
647
|
|
|
|
648
|
|
|
// Load the textdomain according to the module first. |
649
|
|
|
$mofile = $domain . '-' . $locale . '.mo'; |
650
|
|
|
|
651
|
|
|
if ( load_textdomain( $domain, $path . '/' . $mofile ) ) { |
|
|
|
|
652
|
|
|
return true; |
653
|
|
|
} |
654
|
|
|
|
655
|
|
|
// Otherwise, load from the languages directory. |
656
|
|
|
$mofile = WP_LANG_DIR . '/wordpoints-extensions/' . $mofile; |
|
|
|
|
657
|
|
|
|
658
|
|
|
return load_textdomain( $domain, $mofile ); |
659
|
|
|
} |
660
|
|
|
|
661
|
|
|
/** |
662
|
|
|
* Get a list of all main module files. |
663
|
|
|
* |
664
|
|
|
* The default usage retrieves a list of all module files in the /wp-content/wordpoints-extensions |
665
|
|
|
* directory. To get only the modules in a specific subfolder of that directory, pass |
666
|
|
|
* the folder name as the first parameter. |
667
|
|
|
* |
668
|
|
|
* @since 1.1.0 |
669
|
|
|
* @since 2.0.0 The $markup and $translate parameters were added. |
670
|
|
|
* |
671
|
|
|
* @param string $module_folder A specific subfolder of the modules directory to look |
672
|
|
|
* in. Default is empty (search in all folders). |
673
|
|
|
* @param bool $markup Whether to mark up the module data for display. |
674
|
|
|
* @param bool $translate Whether to translate the module data. |
675
|
|
|
* |
676
|
|
|
* @return array A list of the module files found (files with module headers). |
677
|
|
|
*/ |
678
|
|
|
function wordpoints_get_modules( $module_folder = '', $markup = false, $translate = false ) { |
679
|
|
|
|
680
|
|
|
$cache_modules = wp_cache_get( 'wordpoints_modules', 'wordpoints_modules' ); |
|
|
|
|
681
|
|
|
|
682
|
|
|
if ( ! $cache_modules ) { |
683
|
|
|
$cache_modules = array(); |
684
|
|
|
} |
685
|
|
|
|
686
|
|
|
if ( isset( $cache_modules[ $module_folder ] ) ) { |
687
|
|
|
return $cache_modules[ $module_folder ]; |
688
|
|
|
} |
689
|
|
|
|
690
|
|
|
$modules = array(); |
691
|
|
|
$module_root = wordpoints_extensions_dir(); |
692
|
|
|
|
693
|
|
|
if ( ! empty( $module_folder ) ) { |
694
|
|
|
$module_root .= $module_folder; |
695
|
|
|
} |
696
|
|
|
|
697
|
|
|
// Escape pattern-matching characters in the path. |
698
|
|
|
$module_escape_root = str_replace( array( '*', '?', '[' ), array( '[*]', '[?]', '[[]' ), $module_root ); |
699
|
|
|
|
700
|
|
|
// Get the top level files. |
701
|
|
|
$module_files = glob( "{$module_escape_root}/*.php" ); |
702
|
|
|
|
703
|
|
|
if ( false === $module_files ) { |
704
|
|
|
return $modules; |
705
|
|
|
} |
706
|
|
|
|
707
|
|
|
// Get the files of subfolders, if not already searching in a subfolder. |
708
|
|
|
if ( empty( $module_folder ) ) { |
709
|
|
|
|
710
|
|
|
$subfolder_files = glob( "{$module_escape_root}/*/*.php" ); |
711
|
|
|
|
712
|
|
|
if ( false === $subfolder_files ) { |
713
|
|
|
return $modules; |
714
|
|
|
} |
715
|
|
|
|
716
|
|
|
$module_files = array_merge( $module_files, $subfolder_files ); |
717
|
|
|
} |
718
|
|
|
|
719
|
|
|
if ( empty( $module_files ) ) { |
720
|
|
|
return $modules; |
721
|
|
|
} |
722
|
|
|
|
723
|
|
|
foreach ( $module_files as $module_file ) { |
724
|
|
|
|
725
|
|
|
if ( ! is_readable( $module_file ) ) { |
726
|
|
|
continue; |
727
|
|
|
} |
728
|
|
|
|
729
|
|
|
$module_data = wordpoints_get_module_data( $module_file, $markup, $translate ); |
730
|
|
|
|
731
|
|
|
if ( empty( $module_data['name'] ) ) { |
732
|
|
|
continue; |
733
|
|
|
} |
734
|
|
|
|
735
|
|
|
$module_file = wordpoints_module_basename( $module_file ); |
736
|
|
|
|
737
|
|
|
if ( $module_folder ) { |
738
|
|
|
$module_file = basename( $module_file ); |
739
|
|
|
} |
740
|
|
|
|
741
|
|
|
$modules[ $module_file ] = $module_data; |
742
|
|
|
} |
743
|
|
|
|
744
|
|
|
uasort( $modules, '_wordpoints_sort_uname_callback' ); |
745
|
|
|
|
746
|
|
|
$cache_modules[ $module_folder ] = $modules; |
747
|
|
|
wp_cache_set( 'wordpoints_modules', $cache_modules, 'wordpoints_modules' ); |
|
|
|
|
748
|
|
|
|
749
|
|
|
return $modules; |
750
|
|
|
} |
751
|
|
|
|
752
|
|
|
/** |
753
|
|
|
* Check that a module exists and has a valid header. |
754
|
|
|
* |
755
|
|
|
* @since 1.1.0 |
756
|
|
|
* |
757
|
|
|
* @param string $module The module's main file. |
758
|
|
|
* |
759
|
|
|
* @return true|WP_Error True on success, a WP_Error on failure. |
760
|
|
|
*/ |
761
|
|
|
function wordpoints_validate_module( $module ) { |
762
|
|
|
|
763
|
|
|
if ( validate_file( $module ) ) { |
|
|
|
|
764
|
|
|
return new WP_Error( 'module_invalid', __( 'Invalid extension path.', 'wordpoints' ) ); |
|
|
|
|
765
|
|
|
} |
766
|
|
|
|
767
|
|
|
if ( ! file_exists( wordpoints_extensions_dir() . '/' . $module ) ) { |
768
|
|
|
return new WP_Error( 'module_not_found', __( 'Extension file does not exist.', 'wordpoints' ) ); |
769
|
|
|
} |
770
|
|
|
|
771
|
|
|
$installed_modules = wordpoints_get_modules(); |
772
|
|
|
|
773
|
|
|
if ( ! isset( $installed_modules[ $module ] ) ) { |
774
|
|
|
return new WP_Error( 'no_module_header', __( 'The extension does not have a valid header.', 'wordpoints' ) ); |
775
|
|
|
} |
776
|
|
|
|
777
|
|
|
return true; |
778
|
|
|
} |
779
|
|
|
|
780
|
|
|
/** |
781
|
|
|
* Validate active modules. |
782
|
|
|
* |
783
|
|
|
* All active modules will be validated, and invalid ones will be deactivated. |
784
|
|
|
* |
785
|
|
|
* @since 1.1.0 |
786
|
|
|
* |
787
|
|
|
* @return null|WP_Error[] Invalid modules, module as key, error as value. |
788
|
|
|
*/ |
789
|
|
|
function wordpoints_validate_active_modules() { |
790
|
|
|
|
791
|
|
|
$modules = wordpoints_get_array_option( 'wordpoints_active_modules' ); |
792
|
|
|
|
793
|
|
View Code Duplication |
if ( is_multisite() && current_user_can( 'manage_network_wordpoints_extensions' ) ) { |
|
|
|
|
794
|
|
|
|
795
|
|
|
$network_modules = wordpoints_get_array_option( 'wordpoints_sitewide_active_modules', 'site' ); |
796
|
|
|
$modules = array_merge( $modules, array_keys( $network_modules ) ); |
797
|
|
|
} |
798
|
|
|
|
799
|
|
|
if ( empty( $modules ) ) { |
800
|
|
|
return null; |
801
|
|
|
} |
802
|
|
|
|
803
|
|
|
$invalid = array(); |
804
|
|
|
|
805
|
|
|
foreach ( $modules as $module ) { |
806
|
|
|
|
807
|
|
|
$result = wordpoints_validate_module( $module ); |
808
|
|
|
|
809
|
|
|
if ( is_wp_error( $result ) ) { |
|
|
|
|
810
|
|
|
$invalid[ $module ] = $result; |
811
|
|
|
wordpoints_deactivate_modules( $module, true ); |
812
|
|
|
} |
813
|
|
|
} |
814
|
|
|
|
815
|
|
|
return $invalid; |
816
|
|
|
} |
817
|
|
|
|
818
|
|
|
/** |
819
|
|
|
* Callback to sort an array by 'name' key. |
820
|
|
|
* |
821
|
|
|
* @since 1.1.0 |
822
|
|
|
* |
823
|
|
|
* @param array $a One item. |
824
|
|
|
* @param array $b Another item. |
825
|
|
|
* |
826
|
|
|
* @return int {@see strnatcasecmp()}. |
827
|
|
|
*/ |
828
|
|
|
function _wordpoints_sort_uname_callback( $a, $b ) { |
829
|
|
|
|
830
|
|
|
return strnatcasecmp( $a['name'], $b['name'] ); |
831
|
|
|
} |
832
|
|
|
|
833
|
|
|
/** |
834
|
|
|
* Activate a module. |
835
|
|
|
* |
836
|
|
|
* A module that is already activated will not attempt to be activated again. |
837
|
|
|
* |
838
|
|
|
* The way it works is by setting the redirection to the error before trying to |
839
|
|
|
* include the module file. If the module fails, then the redirection will not be |
840
|
|
|
* overwritten with the success message. Also, the options will not be updated and |
841
|
|
|
* the activation hook will not be called on module error. |
842
|
|
|
* |
843
|
|
|
* It should be noted that in no way the below code will actually prevent errors |
844
|
|
|
* within the file. The code should not be used elsewhere to replicate the "sandbox", |
845
|
|
|
* which uses redirection to work. |
846
|
|
|
* |
847
|
|
|
* If any errors are found or text is outputted, then it will be captured to ensure |
848
|
|
|
* that the success redirection will update the error redirection. |
849
|
|
|
* |
850
|
|
|
* @since 1.1.0 |
851
|
|
|
* |
852
|
|
|
* @param string $module The basename path to the main file of the module to activate. |
853
|
|
|
* @param string $redirect The URL to redirect to on failure. |
854
|
|
|
* @param bool $network_wide Whether to activate the module network wide. False by |
855
|
|
|
* default. Only applicable on multisite and when the |
856
|
|
|
* plugin is network activated. |
857
|
|
|
* @param bool $silent Whether to suppress the normal actions. False by default. |
858
|
|
|
* |
859
|
|
|
* @return WP_Error|null An error object on failure, or null on success. |
860
|
|
|
*/ |
861
|
|
|
function wordpoints_activate_module( $module, $redirect = '', $network_wide = false, $silent = false ) { |
862
|
|
|
|
863
|
|
|
$module = wordpoints_module_basename( $module ); |
864
|
|
|
|
865
|
|
|
$valid = wordpoints_validate_module( $module ); |
866
|
|
|
|
867
|
|
|
if ( is_wp_error( $valid ) ) { |
|
|
|
|
868
|
|
|
return $valid; |
869
|
|
|
} |
870
|
|
|
|
871
|
|
|
if ( is_network_only_wordpoints_module( $module ) ) { |
872
|
|
|
$network_wide = true; |
873
|
|
|
} |
874
|
|
|
|
875
|
|
|
if ( $network_wide && ! is_wordpoints_network_active() ) { |
876
|
|
|
$network_wide = false; |
877
|
|
|
} |
878
|
|
|
|
879
|
|
|
if ( $network_wide ) { |
880
|
|
|
|
881
|
|
|
$network_current = wordpoints_get_array_option( 'wordpoints_sitewide_active_modules', 'site' ); |
882
|
|
|
$current = array_keys( $network_current ); |
883
|
|
|
|
884
|
|
|
} else { |
885
|
|
|
|
886
|
|
|
$current = wordpoints_get_array_option( 'wordpoints_active_modules' ); |
887
|
|
|
} |
888
|
|
|
|
889
|
|
|
// If the module is already active, return. |
890
|
|
|
if ( in_array( $module, $current, true ) ) { |
891
|
|
|
return null; |
892
|
|
|
} |
893
|
|
|
|
894
|
|
|
if ( ! empty( $redirect ) ) { |
895
|
|
|
|
896
|
|
|
/* |
897
|
|
|
* Redirect. We'll override this later if the module can be included |
898
|
|
|
* without a fatal error. |
899
|
|
|
*/ |
900
|
|
|
wp_safe_redirect( |
|
|
|
|
901
|
|
|
add_query_arg( |
|
|
|
|
902
|
|
|
'_error_nonce' |
903
|
|
|
, wp_create_nonce( 'module-activation-error_' . $module ) |
|
|
|
|
904
|
|
|
, $redirect |
905
|
|
|
) |
906
|
|
|
); |
907
|
|
|
} |
908
|
|
|
|
909
|
|
|
ob_start(); |
910
|
|
|
|
911
|
|
|
$module_file = wordpoints_extensions_dir() . '/' . $module; |
912
|
|
|
WordPoints_Module_Paths::register( $module_file ); |
913
|
|
|
|
914
|
|
|
require_once $module_file; |
915
|
|
|
|
916
|
|
|
if ( ! $silent ) { |
917
|
|
|
|
918
|
|
|
/** |
919
|
|
|
* Fires before a module is activated. |
920
|
|
|
* |
921
|
|
|
* @since 1.1.0 |
922
|
|
|
* |
923
|
|
|
* @param string $module Base path to the main module file. |
924
|
|
|
* @param bool $network_wide Whether the module is being activated for |
925
|
|
|
* all sites in the network or just the |
926
|
|
|
* current site. |
927
|
|
|
*/ |
928
|
|
|
do_action( 'wordpoints_module_activate', $module, $network_wide ); |
|
|
|
|
929
|
|
|
|
930
|
|
|
/** |
931
|
|
|
* Fires before a module is activated. |
932
|
|
|
* |
933
|
|
|
* @since 1.0.0 |
934
|
|
|
* |
935
|
|
|
* @param bool $network_wide Whether the module is being activated for |
936
|
|
|
* all sites in the network or just the current |
937
|
|
|
* site. |
938
|
|
|
*/ |
939
|
|
|
do_action( "wordpoints_module_activate-{$module}", $network_wide ); |
940
|
|
|
|
941
|
|
|
WordPoints_Modules::install( |
942
|
|
|
WordPoints_Modules::get_slug( $module ) |
943
|
|
|
, $network_wide |
944
|
|
|
); |
945
|
|
|
} |
946
|
|
|
|
947
|
|
|
if ( $network_wide ) { |
948
|
|
|
|
949
|
|
|
$network_current[ $module ] = time(); |
950
|
|
|
update_site_option( 'wordpoints_sitewide_active_modules', $network_current ); |
|
|
|
|
951
|
|
|
|
952
|
|
|
} else { |
953
|
|
|
|
954
|
|
|
$current[] = $module; |
955
|
|
|
sort( $current ); |
956
|
|
|
update_option( 'wordpoints_active_modules', $current ); |
|
|
|
|
957
|
|
|
} |
958
|
|
|
|
959
|
|
|
if ( ! $silent ) { |
960
|
|
|
/** |
961
|
|
|
* Fires after a module has been activated in activate_plugin() when the $silent parameter is false. |
962
|
|
|
* |
963
|
|
|
* @since 1.1.0 |
964
|
|
|
* |
965
|
|
|
* @param string $module Base path to main module file. |
966
|
|
|
* @param bool $network_wide Whether the module is being activated for |
967
|
|
|
* all sites in the network or just the |
968
|
|
|
* current site. |
969
|
|
|
*/ |
970
|
|
|
do_action( 'wordpoints_activated_module', $module, $network_wide ); |
971
|
|
|
} |
972
|
|
|
|
973
|
|
|
if ( ob_get_length() > 0 ) { |
974
|
|
|
|
975
|
|
|
return new WP_Error( |
976
|
|
|
'unexpected_output' |
977
|
|
|
, __( 'The extension generated unexpected output.', 'wordpoints' ) |
|
|
|
|
978
|
|
|
, ob_get_contents() |
979
|
|
|
); |
980
|
|
|
} |
981
|
|
|
|
982
|
|
|
ob_end_clean(); |
983
|
|
|
|
984
|
|
|
return null; |
985
|
|
|
} |
986
|
|
|
|
987
|
|
|
/** |
988
|
|
|
* Deactivate one or more modules. |
989
|
|
|
* |
990
|
|
|
* @since 1.1.0 |
991
|
|
|
* |
992
|
|
|
* @param array|string $modules The module(s) to deactivate. |
993
|
|
|
* @param bool $silent Whether to suppress deactivation actions. |
994
|
|
|
* Default is false. |
995
|
|
|
* @param bool $network_wide Whether to apply the change network wide. |
996
|
|
|
*/ |
997
|
|
|
function wordpoints_deactivate_modules( $modules, $silent = false, $network_wide = null ) { |
998
|
|
|
|
999
|
|
|
$network_current = array(); |
1000
|
|
|
if ( is_wordpoints_network_active() ) { |
1001
|
|
|
$network_current = wordpoints_get_array_option( 'wordpoints_sitewide_active_modules', 'site' ); |
1002
|
|
|
} |
1003
|
|
|
|
1004
|
|
|
$current = wordpoints_get_array_option( 'wordpoints_active_modules' ); |
1005
|
|
|
|
1006
|
|
|
$do_network = false; |
1007
|
|
|
$do_blog = false; |
1008
|
|
|
|
1009
|
|
|
foreach ( (array) $modules as $module ) { |
1010
|
|
|
|
1011
|
|
|
$module = wordpoints_module_basename( $module ); |
1012
|
|
|
|
1013
|
|
|
if ( ! is_wordpoints_module_active( $module ) ) { |
1014
|
|
|
continue; |
1015
|
|
|
} |
1016
|
|
|
|
1017
|
|
|
$network_deactivating = ( false !== $network_wide && is_wordpoints_module_active_for_network( $module ) ); |
1018
|
|
|
|
1019
|
|
|
if ( ! $silent ) { |
1020
|
|
|
/** |
1021
|
|
|
* Fires for each module being deactivated in wordpoints_deactivate_modules(), before deactivation |
1022
|
|
|
* and when the $silent parameter is false. |
1023
|
|
|
* |
1024
|
|
|
* @since 1.1.0 |
1025
|
|
|
* |
1026
|
|
|
* @param string $module Module path to main module file with module data. |
1027
|
|
|
* @param bool $network_deactivating Whether the module is deactivated for all sites in the network |
1028
|
|
|
* or just the current site. Multisite only. Default is false. |
1029
|
|
|
*/ |
1030
|
|
|
do_action( 'wordpoints_deactivate_module', $module, $network_deactivating ); |
|
|
|
|
1031
|
|
|
} |
1032
|
|
|
|
1033
|
|
|
if ( false !== $network_wide ) { |
1034
|
|
|
|
1035
|
|
|
if ( is_wordpoints_module_active_for_network( $module ) ) { |
1036
|
|
|
|
1037
|
|
|
$do_network = true; |
1038
|
|
|
unset( $network_current[ $module ] ); |
1039
|
|
|
|
1040
|
|
|
} elseif ( $network_wide ) { |
1041
|
|
|
|
1042
|
|
|
continue; |
1043
|
|
|
} |
1044
|
|
|
} |
1045
|
|
|
|
1046
|
|
|
if ( true !== $network_wide ) { |
1047
|
|
|
|
1048
|
|
|
$key = array_search( $module, $current, true ); |
1049
|
|
|
|
1050
|
|
|
if ( false !== $key ) { |
1051
|
|
|
|
1052
|
|
|
$do_blog = true; |
1053
|
|
|
unset( $current[ $key ] ); |
1054
|
|
|
} |
1055
|
|
|
} |
1056
|
|
|
|
1057
|
|
|
if ( ! $silent ) { |
1058
|
|
|
/** |
1059
|
|
|
* Fires for each module being deactivated in wordpoints_deactivate_module(), after deactivation |
1060
|
|
|
* and when the $silent parameter is false. |
1061
|
|
|
* |
1062
|
|
|
* The action concatenates the 'deactivate_' prefix with the module's basename |
1063
|
|
|
* to create a dynamically-named action. |
1064
|
|
|
* |
1065
|
|
|
* @since 1.1.0 |
1066
|
|
|
* |
1067
|
|
|
* @param bool $network_deactivating Whether the module is deactivated for all sites in the network |
1068
|
|
|
* or just the current site. Multisite only. Default is false. |
1069
|
|
|
*/ |
1070
|
|
|
do_action( "wordpoints_deactivate_module-{$module}", $network_deactivating ); |
1071
|
|
|
|
1072
|
|
|
/** |
1073
|
|
|
* Fires for each module being deactivated in deactivate_plugins(), after deactivation |
1074
|
|
|
* and when the $silent parameter is false. |
1075
|
|
|
* |
1076
|
|
|
* @since 1.1.0 |
1077
|
|
|
* |
1078
|
|
|
* @param string $module Module path to main module file with module data. |
1079
|
|
|
* @param bool $network_deactivating Whether the module is deactivated for all sites in the network |
1080
|
|
|
* or just the current site. Multisite only. Default is false. |
1081
|
|
|
*/ |
1082
|
|
|
do_action( 'wordpoints_deactivated_module', $module, $network_deactivating ); |
1083
|
|
|
} |
1084
|
|
|
|
1085
|
|
|
} // End foreach ( $modules ). |
1086
|
|
|
|
1087
|
|
|
if ( $do_blog ) { |
1088
|
|
|
update_option( 'wordpoints_active_modules', $current ); |
|
|
|
|
1089
|
|
|
} |
1090
|
|
|
|
1091
|
|
|
if ( $do_network ) { |
1092
|
|
|
update_site_option( 'wordpoints_sitewide_active_modules', $network_current ); |
|
|
|
|
1093
|
|
|
} |
1094
|
|
|
} |
1095
|
|
|
|
1096
|
|
|
/** |
1097
|
|
|
* Remove directory and files of a module for a single or list of module(s). |
1098
|
|
|
* |
1099
|
|
|
* If the modules parameter list is empty, false will be returned. True when |
1100
|
|
|
* completed. |
1101
|
|
|
* |
1102
|
|
|
* @since 1.1.0 |
1103
|
|
|
* |
1104
|
|
|
* @param array $modules A list of modules to delete. |
1105
|
|
|
* |
1106
|
|
|
* @return bool|WP_Error True if all modules deleted successfully, false or WP_Error |
1107
|
|
|
* on failure. |
1108
|
|
|
*/ |
1109
|
|
|
function wordpoints_delete_modules( $modules ) { |
1110
|
|
|
|
1111
|
|
|
global $wp_filesystem; |
1112
|
|
|
|
1113
|
|
|
if ( empty( $modules ) ) { |
1114
|
|
|
return false; |
1115
|
|
|
} |
1116
|
|
|
|
1117
|
|
|
$checked = array(); |
1118
|
|
|
|
1119
|
|
|
foreach ( $modules as $module ) { |
1120
|
|
|
$checked[] = 'checked[]=' . $module; |
1121
|
|
|
} |
1122
|
|
|
|
1123
|
|
|
ob_start(); |
1124
|
|
|
|
1125
|
|
|
$url = wp_nonce_url( self_admin_url( 'admin.php?page=wordpoints_extensions&action=delete-selected&verify-delete=1&' . implode( '&', $checked ) ), 'bulk-modules' ); |
|
|
|
|
1126
|
|
|
|
1127
|
|
|
$credentials = request_filesystem_credentials( $url ); |
|
|
|
|
1128
|
|
|
|
1129
|
|
|
if ( false === $credentials ) { |
1130
|
|
|
|
1131
|
|
|
$data = ob_get_clean(); |
1132
|
|
|
|
1133
|
|
View Code Duplication |
if ( ! empty( $data ) ) { |
|
|
|
|
1134
|
|
|
|
1135
|
|
|
require_once ABSPATH . 'wp-admin/admin-header.php'; |
|
|
|
|
1136
|
|
|
echo $data; // XSS OK here, WPCS. |
1137
|
|
|
require ABSPATH . 'wp-admin/admin-footer.php'; |
1138
|
|
|
exit; |
|
|
|
|
1139
|
|
|
} |
1140
|
|
|
|
1141
|
|
|
return false; |
1142
|
|
|
} |
1143
|
|
|
|
1144
|
|
|
if ( ! WP_Filesystem( $credentials ) ) { |
|
|
|
|
1145
|
|
|
|
1146
|
|
|
// Failed to connect, Error and request again |
1147
|
|
|
request_filesystem_credentials( $url, '', true ); |
1148
|
|
|
|
1149
|
|
|
$data = ob_get_clean(); |
1150
|
|
|
|
1151
|
|
View Code Duplication |
if ( ! empty( $data ) ) { |
|
|
|
|
1152
|
|
|
|
1153
|
|
|
require_once ABSPATH . 'wp-admin/admin-header.php'; |
1154
|
|
|
echo $data; // XSS OK here too, WPCS. |
1155
|
|
|
require ABSPATH . 'wp-admin/admin-footer.php'; |
1156
|
|
|
exit; |
|
|
|
|
1157
|
|
|
} |
1158
|
|
|
|
1159
|
|
|
return false; |
1160
|
|
|
} |
1161
|
|
|
|
1162
|
|
|
if ( ! is_object( $wp_filesystem ) ) { |
1163
|
|
|
return new WP_Error( 'fs_unavailable', __( 'Could not access filesystem.', 'wordpoints' ) ); |
|
|
|
|
1164
|
|
|
} |
1165
|
|
|
|
1166
|
|
|
if ( is_wp_error( $wp_filesystem->errors ) && $wp_filesystem->errors->get_error_code() ) { |
|
|
|
|
1167
|
|
|
return new WP_Error( 'fs_error', __( 'Filesystem error.', 'wordpoints' ), $wp_filesystem->errors ); |
1168
|
|
|
} |
1169
|
|
|
|
1170
|
|
|
// Get the base module folder. |
1171
|
|
|
$modules_dir = $wp_filesystem->find_folder( wordpoints_extensions_dir() ); |
1172
|
|
|
|
1173
|
|
|
if ( empty( $modules_dir ) ) { |
1174
|
|
|
return new WP_Error( 'fs_no_modules_dir', __( 'Unable to locate WordPoints Extension directory.', 'wordpoints' ) ); |
1175
|
|
|
} |
1176
|
|
|
|
1177
|
|
|
$modules_dir = trailingslashit( $modules_dir ); |
|
|
|
|
1178
|
|
|
$errors = array(); |
1179
|
|
|
|
1180
|
|
|
foreach ( $modules as $module_file ) { |
1181
|
|
|
|
1182
|
|
|
$validate = wordpoints_validate_module( $module_file ); |
1183
|
|
|
|
1184
|
|
|
if ( is_wp_error( $validate ) ) { |
1185
|
|
|
$errors[] = $module_file; |
1186
|
|
|
continue; |
1187
|
|
|
} |
1188
|
|
|
|
1189
|
|
|
// Run uninstall hook. |
1190
|
|
|
if ( is_uninstallable_wordpoints_module( $module_file ) ) { |
1191
|
|
|
wordpoints_uninstall_module( $module_file ); |
1192
|
|
|
} |
1193
|
|
|
|
1194
|
|
|
$this_module_dir = trailingslashit( dirname( $modules_dir . $module_file ) ); |
1195
|
|
|
|
1196
|
|
|
// If module is in its own directory, recursively delete the directory. |
1197
|
|
|
if ( strpos( $module_file, '/' ) && $this_module_dir !== $modules_dir ) { |
1198
|
|
|
$deleted = $wp_filesystem->delete( $this_module_dir, true ); |
1199
|
|
|
} else { |
1200
|
|
|
$deleted = $wp_filesystem->delete( $modules_dir . $module_file ); |
1201
|
|
|
} |
1202
|
|
|
|
1203
|
|
|
if ( ! $deleted ) { |
1204
|
|
|
$errors[] = $module_file; |
1205
|
|
|
} |
1206
|
|
|
} |
1207
|
|
|
|
1208
|
|
|
/** |
1209
|
|
|
* Deleted modules. |
1210
|
|
|
* |
1211
|
|
|
* To get a list of the modules deleted successfully, do this: |
1212
|
|
|
* |
1213
|
|
|
* $deleted = array_diff( $modules, $errors ); |
1214
|
|
|
* |
1215
|
|
|
* @since 1.1.0 |
1216
|
|
|
* |
1217
|
|
|
* @param array $modules The modules that were to be deleted. |
1218
|
|
|
* @param array $errors The modules that failed to delete. |
1219
|
|
|
*/ |
1220
|
|
|
do_action( 'wordpoints_deleted_modules', $modules, $errors ); |
|
|
|
|
1221
|
|
|
|
1222
|
|
|
if ( ! empty( $errors ) ) { |
1223
|
|
|
return new WP_Error( |
1224
|
|
|
'could_not_remove_module' |
1225
|
|
|
, sprintf( |
1226
|
|
|
// translators: Extension or list of extensions. |
1227
|
|
|
_n( |
|
|
|
|
1228
|
|
|
'Could not fully remove the extension %s.' |
1229
|
|
|
, 'Could not fully remove the extensions %s.' |
1230
|
|
|
, count( $errors ) |
1231
|
|
|
, 'wordpoints' |
1232
|
|
|
) |
1233
|
|
|
, implode( ', ', $errors ) |
1234
|
|
|
) |
1235
|
|
|
); |
1236
|
|
|
} |
1237
|
|
|
|
1238
|
|
|
return true; |
1239
|
|
|
} |
1240
|
|
|
|
1241
|
|
|
/** |
1242
|
|
|
* Uninstall a single module. |
1243
|
|
|
* |
1244
|
|
|
* Includes the uninstall.php file, if it is available. |
1245
|
|
|
* |
1246
|
|
|
* @since 1.1.0 |
1247
|
|
|
* |
1248
|
|
|
* @param string $module Relative module path from module directory. |
1249
|
|
|
* |
1250
|
|
|
* @return bool Whether the module had an uninstall process. |
1251
|
|
|
*/ |
1252
|
|
|
function wordpoints_uninstall_module( $module ) { |
1253
|
|
|
|
1254
|
|
|
$file = wordpoints_module_basename( $module ); |
1255
|
|
|
$module_file = wordpoints_extensions_dir() . '/' . $file; |
1256
|
|
|
$module_dir = dirname( $module_file ); |
1257
|
|
|
$uninstall_file = $module_dir . '/uninstall.php'; |
1258
|
|
|
$un_installer_file = $module_dir . '/includes/class-un-installer.php'; |
1259
|
|
|
$installable_file = $module_dir . '/classes/installable.php'; |
1260
|
|
|
|
1261
|
|
|
if ( file_exists( $installable_file ) ) { |
1262
|
|
|
|
1263
|
|
|
WordPoints_Class_Autoloader::register_dir( dirname( $installable_file ) ); |
1264
|
|
|
|
1265
|
|
|
$slug = WordPoints_Modules::get_slug( $module ); |
1266
|
|
|
$data = wordpoints_get_module_data( $module_file, false, false ); |
1267
|
|
|
|
1268
|
|
|
$class = "WordPoints_{$data['namespace']}_Installable"; |
1269
|
|
|
|
1270
|
|
|
$uninstaller = new WordPoints_Uninstaller( new $class( $slug ) ); |
1271
|
|
|
$uninstaller->run(); |
1272
|
|
|
|
1273
|
|
|
return true; |
1274
|
|
|
|
1275
|
|
|
} elseif ( file_exists( $uninstall_file ) ) { |
1276
|
|
|
|
1277
|
|
|
if ( ! defined( 'WORDPOINTS_UNINSTALL_MODULE' ) ) { |
1278
|
|
|
/** |
1279
|
|
|
* Uninstalling a module. |
1280
|
|
|
* |
1281
|
|
|
* You should always check that this constant is set in your uninstall.php |
1282
|
|
|
* file, before running your uninstall process. And if you have an install |
1283
|
|
|
* process, you should have an uninstall process too. |
1284
|
|
|
* |
1285
|
|
|
* The value of this constant, when set, is boolean true. |
1286
|
|
|
* |
1287
|
|
|
* @since 1.1.0 |
1288
|
|
|
* |
1289
|
|
|
* @const WORDPOINTS_UNINSTALL_MODULE |
1290
|
|
|
*/ |
1291
|
|
|
define( 'WORDPOINTS_UNINSTALL_MODULE', true ); |
1292
|
|
|
} |
1293
|
|
|
|
1294
|
|
|
WordPoints_Module_Paths::register( $uninstall_file ); |
1295
|
|
|
include $uninstall_file; |
1296
|
|
|
|
1297
|
|
|
return true; |
1298
|
|
|
|
1299
|
|
|
} elseif ( file_exists( $un_installer_file ) ) { |
1300
|
|
|
|
1301
|
|
|
$slug = WordPoints_Modules::get_slug( $module ); |
1302
|
|
|
|
1303
|
|
|
$uninstaller = WordPoints_Installables::get_installer( |
1304
|
|
|
'module' |
1305
|
|
|
, $slug |
1306
|
|
|
, 'uninstall' // Required, but not really used. |
1307
|
|
|
, $un_installer_file |
1308
|
|
|
); |
1309
|
|
|
|
1310
|
|
|
$uninstaller->uninstall(); |
1311
|
|
|
|
1312
|
|
|
return true; |
1313
|
|
|
|
1314
|
|
|
} else { |
1315
|
|
|
|
1316
|
|
|
return false; |
1317
|
|
|
|
1318
|
|
|
} // End if ( uninstall file ) elseif ( uninstaller ) else. |
1319
|
|
|
} |
1320
|
|
|
|
1321
|
|
|
/** |
1322
|
|
|
* Load the active and valid modules. |
1323
|
|
|
* |
1324
|
|
|
* All modules active modules will be loaded by the function, provided that the |
1325
|
|
|
* module file is a valid path that actually exists, and it has the '.php' extension. |
1326
|
|
|
* |
1327
|
|
|
* Network active modules are loaded along with regular modules. This only happens |
1328
|
|
|
* when WordPoints is network activated on a multisite install. |
1329
|
|
|
* |
1330
|
|
|
* @since 1.1.0 |
1331
|
|
|
* |
1332
|
|
|
* @WordPress\action plugins_loaded 15 After components. |
1333
|
|
|
* |
1334
|
|
|
* @return void |
1335
|
|
|
*/ |
1336
|
|
|
function wordpoints_load_modules() { |
1337
|
|
|
|
1338
|
|
|
$active_modules = wordpoints_get_array_option( 'wordpoints_active_modules' ); |
1339
|
|
|
|
1340
|
|
View Code Duplication |
if ( is_wordpoints_network_active() ) { |
|
|
|
|
1341
|
|
|
|
1342
|
|
|
$network_active_modules = array_keys( |
1343
|
|
|
wordpoints_get_array_option( 'wordpoints_sitewide_active_modules', 'site' ) |
1344
|
|
|
); |
1345
|
|
|
|
1346
|
|
|
// On the network admin screens we only load the network active modules. |
1347
|
|
|
if ( is_network_admin() ) { |
|
|
|
|
1348
|
|
|
$active_modules = $network_active_modules; |
1349
|
|
|
} else { |
1350
|
|
|
$active_modules = array_merge( $active_modules, $network_active_modules ); |
1351
|
|
|
} |
1352
|
|
|
} |
1353
|
|
|
|
1354
|
|
|
if ( ! empty( $active_modules ) ) { |
1355
|
|
|
|
1356
|
|
|
$modules_dir = wordpoints_extensions_dir(); |
1357
|
|
|
|
1358
|
|
|
foreach ( $active_modules as $module ) { |
1359
|
|
|
|
1360
|
|
|
if ( |
1361
|
|
|
0 === validate_file( $module ) |
|
|
|
|
1362
|
|
|
&& '.php' === substr( $module, -4 ) |
1363
|
|
|
&& file_exists( $modules_dir . '/' . $module ) |
1364
|
|
|
) { |
1365
|
|
|
WordPoints_Module_Paths::register( $modules_dir . '/' . $module ); |
1366
|
|
|
include $modules_dir . '/' . $module; |
1367
|
|
|
} |
1368
|
|
|
} |
1369
|
|
|
} |
1370
|
|
|
|
1371
|
|
|
/** |
1372
|
|
|
* Fires after all active extensions are loaded. |
1373
|
|
|
* |
1374
|
|
|
* It will always be fired even when no extensions are active. |
1375
|
|
|
* |
1376
|
|
|
* @since 2.4.0 |
1377
|
|
|
*/ |
1378
|
|
|
do_action( 'wordpoints_extensions_loaded' ); |
|
|
|
|
1379
|
|
|
|
1380
|
|
|
/** |
1381
|
|
|
* Fires after all active extensions are loaded. |
1382
|
|
|
* |
1383
|
|
|
* It will always be fired even when no extensions are active. |
1384
|
|
|
* |
1385
|
|
|
* @since 1.0.0 |
1386
|
|
|
* @deprecated 2.4.0 Use wordpoints_extensions_loaded instead. |
1387
|
|
|
*/ |
1388
|
|
|
do_action_deprecated( 'wordpoints_modules_loaded', array(), '2.4.0', 'wordpoints_extensions_loaded' ); |
|
|
|
|
1389
|
|
|
} |
1390
|
|
|
|
1391
|
|
|
/** |
1392
|
|
|
* Register a function as the callback on module activation. |
1393
|
|
|
* |
1394
|
|
|
* @since 1.1.0 |
1395
|
|
|
* |
1396
|
|
|
* @param string $file The main file of the module the hook is for. |
1397
|
|
|
* @param string $function The callback function. |
1398
|
|
|
*/ |
1399
|
|
|
function wordpoints_register_module_activation_hook( $file, $function ) { |
1400
|
|
|
|
1401
|
|
|
$module_file = wordpoints_module_basename( $file ); |
1402
|
|
|
|
1403
|
|
|
add_action( "wordpoints_module_activate-{$module_file}", $function ); |
|
|
|
|
1404
|
|
|
} |
1405
|
|
|
|
1406
|
|
|
/** |
1407
|
|
|
* Register a function as the callback for module deactivation. |
1408
|
|
|
* |
1409
|
|
|
* @since 1.1.0 |
1410
|
|
|
* |
1411
|
|
|
* @param string $file The main file of the module the hook is for. |
1412
|
|
|
* @param string $function The callback function. |
1413
|
|
|
*/ |
1414
|
|
|
function wordpoints_register_module_deactivation_hook( $file, $function ) { |
1415
|
|
|
|
1416
|
|
|
$module_file = wordpoints_module_basename( $file ); |
1417
|
|
|
|
1418
|
|
|
add_action( "wordpoints_deactivate_module-{$module_file}", $function ); |
|
|
|
|
1419
|
|
|
} |
1420
|
|
|
|
1421
|
|
|
/** |
1422
|
|
|
* Gets the available extension updates. |
1423
|
|
|
* |
1424
|
|
|
* @since 2.4.0 |
1425
|
|
|
* |
1426
|
|
|
* @return WordPoints_Extension_UpdatesI The available extension updates. |
1427
|
|
|
*/ |
1428
|
|
|
function wordpoints_get_extension_updates() { |
1429
|
|
|
|
1430
|
|
|
$updates = new WordPoints_Extension_Updates(); |
1431
|
|
|
$updates->fill(); |
1432
|
|
|
|
1433
|
|
|
return $updates; |
1434
|
|
|
} |
1435
|
|
|
|
1436
|
|
|
/** |
1437
|
|
|
* Checks for extension updates. |
1438
|
|
|
* |
1439
|
|
|
* @since 2.4.0 |
1440
|
|
|
* |
1441
|
|
|
* @WordPress\action wordpoints_check_for_extension_updates Cron event registered by |
1442
|
|
|
* wordpoints_schedule_extension_update_checks(). |
1443
|
|
|
* |
1444
|
|
|
* @param int $cache_timeout Maximum acceptable age for the cache. If the cache is |
1445
|
|
|
* older than this, it will be updated. The default is 12 |
1446
|
|
|
* hours. |
1447
|
|
|
* |
1448
|
|
|
* @return WordPoints_Extension_UpdatesI|false The updates, or false if the check was |
1449
|
|
|
* not run (due to the cache being fresh |
1450
|
|
|
* enough, or some other reason). |
1451
|
|
|
*/ |
1452
|
|
|
function wordpoints_check_for_extension_updates( $cache_timeout = null ) { |
1453
|
|
|
|
1454
|
|
|
$check = new WordPoints_Extension_Updates_Check( $cache_timeout ); |
1455
|
|
|
return $check->run(); |
1456
|
|
|
} |
1457
|
|
|
|
1458
|
|
|
/** |
1459
|
|
|
* Schedules the extension updates check. |
1460
|
|
|
* |
1461
|
|
|
* @since 2.4.0 |
1462
|
|
|
* |
1463
|
|
|
* @WordPress\action init |
1464
|
|
|
*/ |
1465
|
|
|
function wordpoints_schedule_extension_updates_check() { |
1466
|
|
|
|
1467
|
|
|
$event = 'wordpoints_check_for_extension_updates'; |
1468
|
|
|
|
1469
|
|
|
if ( ! wp_next_scheduled( $event ) ) { |
|
|
|
|
1470
|
|
|
wp_schedule_event( time(), 'twicedaily', $event ); |
|
|
|
|
1471
|
|
|
} |
1472
|
|
|
} |
1473
|
|
|
|
1474
|
|
|
/** |
1475
|
|
|
* Reschedules the extension updates check from the current time. |
1476
|
|
|
* |
1477
|
|
|
* @since 2.4.0 |
1478
|
|
|
* |
1479
|
|
|
* @WordPress\action wordpoints_extension_update_check_completed |
1480
|
|
|
*/ |
1481
|
|
|
function wordpoints_reschedule_extension_updates_check() { |
1482
|
|
|
|
1483
|
|
|
wp_reschedule_event( |
|
|
|
|
1484
|
|
|
time() |
1485
|
|
|
, 'twicedaily' |
1486
|
|
|
, 'wordpoints_check_for_extension_updates' |
1487
|
|
|
); |
1488
|
|
|
} |
1489
|
|
|
|
1490
|
|
|
/** |
1491
|
|
|
* Checks for extension updates after an upgrade. |
1492
|
|
|
* |
1493
|
|
|
* @since 2.4.0 |
1494
|
|
|
* |
1495
|
|
|
* @WordPress\action upgrader_process_complete |
1496
|
|
|
* |
1497
|
|
|
* @param object $upgrader The upgrader. |
1498
|
|
|
* @param array $data Info about the upgrade. |
1499
|
|
|
*/ |
1500
|
|
|
function wordpoints_recheck_for_extension_updates_after_upgrade( $upgrader, $data ) { |
|
|
|
|
1501
|
|
|
|
1502
|
|
|
if ( isset( $data['type'] ) && 'translation' === $data['type'] ) { |
1503
|
|
|
return; |
1504
|
|
|
} |
1505
|
|
|
|
1506
|
|
|
wordpoints_check_for_extension_updates_now(); |
1507
|
|
|
} |
1508
|
|
|
|
1509
|
|
|
/** |
1510
|
|
|
* Checks for extension updates with a cache timeout of one hour. |
1511
|
|
|
* |
1512
|
|
|
* @since 2.4.0 |
1513
|
|
|
*/ |
1514
|
|
|
function wordpoints_check_for_extension_updates_hourly() { |
1515
|
|
|
wordpoints_check_for_extension_updates( HOUR_IN_SECONDS ); |
|
|
|
|
1516
|
|
|
} |
1517
|
|
|
|
1518
|
|
|
/** |
1519
|
|
|
* Checks for extension updates with a cache timeout of zero. |
1520
|
|
|
* |
1521
|
|
|
* @since 2.4.0 |
1522
|
|
|
*/ |
1523
|
|
|
function wordpoints_check_for_extension_updates_now() { |
1524
|
|
|
wordpoints_check_for_extension_updates( 0 ); |
1525
|
|
|
} |
1526
|
|
|
|
1527
|
|
|
/** |
1528
|
|
|
* Clean the extensions cache. |
1529
|
|
|
* |
1530
|
|
|
* @since 2.4.0 |
1531
|
|
|
* |
1532
|
|
|
* @param bool $clear_update_cache Whether to clear the updates cache. |
1533
|
|
|
*/ |
1534
|
|
|
function wordpoints_clean_extensions_cache( $clear_update_cache = true ) { |
1535
|
|
|
|
1536
|
|
|
if ( $clear_update_cache ) { |
1537
|
|
|
$updates = new WordPoints_Extension_Updates(); |
1538
|
|
|
$updates->set_time_checked( 0 ); |
1539
|
|
|
$updates->save(); |
1540
|
|
|
} |
1541
|
|
|
|
1542
|
|
|
wp_cache_delete( 'wordpoints_modules', 'wordpoints_modules' ); |
|
|
|
|
1543
|
|
|
} |
1544
|
|
|
|
1545
|
|
|
/** |
1546
|
|
|
* Add the extension update counts to the other update counts. |
1547
|
|
|
* |
1548
|
|
|
* @since 2.4.0 |
1549
|
|
|
* |
1550
|
|
|
* @WordPress\filter wp_get_update_data |
1551
|
|
|
* |
1552
|
|
|
* @param array $update_data The update data. |
1553
|
|
|
* |
1554
|
|
|
* @return array The updated update counts. |
1555
|
|
|
*/ |
1556
|
|
|
function wordpoints_extension_update_counts( $update_data ) { |
1557
|
|
|
|
1558
|
|
|
$update_data['counts']['wordpoints_extensions'] = 0; |
1559
|
|
|
|
1560
|
|
|
if ( current_user_can( 'update_wordpoints_extensions' ) ) { |
|
|
|
|
1561
|
|
|
$extension_updates = wordpoints_get_extension_updates()->get_new_versions(); |
1562
|
|
|
|
1563
|
|
|
if ( ! empty( $extension_updates ) ) { |
1564
|
|
|
$update_data['counts']['wordpoints_extensions'] = count( $extension_updates ); |
1565
|
|
|
|
1566
|
|
|
$title = sprintf( |
1567
|
|
|
// translators: Number of updates. |
1568
|
|
|
_n( |
|
|
|
|
1569
|
|
|
'%d WordPoints Extension Update' |
1570
|
|
|
, '%d WordPoints Extension Updates' |
1571
|
|
|
, $update_data['counts']['wordpoints_extensions'] |
1572
|
|
|
, 'wordpoints' |
1573
|
|
|
) |
1574
|
|
|
, $update_data['counts']['wordpoints_extensions'] |
1575
|
|
|
); |
1576
|
|
|
|
1577
|
|
|
if ( ! empty( $update_data['title'] ) ) { |
1578
|
|
|
$update_data['title'] .= ', '; |
1579
|
|
|
} |
1580
|
|
|
|
1581
|
|
|
$update_data['title'] .= esc_attr( $title ); |
|
|
|
|
1582
|
|
|
} |
1583
|
|
|
} |
1584
|
|
|
|
1585
|
|
|
$update_data['counts']['total'] += $update_data['counts']['wordpoints_extensions']; |
1586
|
|
|
|
1587
|
|
|
return $update_data; |
1588
|
|
|
} |
1589
|
|
|
|
1590
|
|
|
/** |
1591
|
|
|
* Filters the extension data to add missing server headers for specific extensions. |
1592
|
|
|
* |
1593
|
|
|
* A few extensions were released without the `ID` header set, either because it |
1594
|
|
|
* hadn't been invented yet or because we just forgot. Because of this, they are |
1595
|
|
|
* unable to receive updates from WordPoints.org. This function filters the headers |
1596
|
|
|
* for these extensions, and adds in the `ID` and `server` header values as needed. |
1597
|
|
|
* |
1598
|
|
|
* @since 2.4.0 |
1599
|
|
|
* |
1600
|
|
|
* @WordPress\filter wordpoints_extension_data |
1601
|
|
|
* |
1602
|
|
|
* @param array $data Extension header data. |
1603
|
|
|
* |
1604
|
|
|
* @return array The filtered extension header data. |
1605
|
|
|
*/ |
1606
|
|
|
function wordpoints_extension_data_missing_server_headers_filter( $data ) { |
1607
|
|
|
|
1608
|
|
|
$missing_headers = array( |
1609
|
|
|
'Beta Tester' => '316', |
1610
|
|
|
'Importer' => '430', |
1611
|
|
|
'WooCommerce' => '445', |
1612
|
|
|
'Points Logs Regenerator' => '530', |
1613
|
|
|
'Reset Points' => '540', |
1614
|
|
|
); |
1615
|
|
|
|
1616
|
|
|
if ( |
1617
|
|
|
empty( $data['ID'] ) |
1618
|
|
|
&& ( 'J.D. Grimes' === $data['author'] || 'WordPoints' === $data['author'] ) |
1619
|
|
|
&& isset( $missing_headers[ $data['name'] ] ) |
1620
|
|
|
) { |
1621
|
|
|
$data['server'] = 'wordpoints.org'; |
1622
|
|
|
$data['ID'] = $missing_headers[ $data['name'] ]; |
1623
|
|
|
} |
1624
|
|
|
|
1625
|
|
|
return $data; |
1626
|
|
|
} |
1627
|
|
|
|
1628
|
|
|
/** |
1629
|
|
|
* Filters the public key for an extension server. |
1630
|
|
|
* |
1631
|
|
|
* @since 2.5.0 |
1632
|
|
|
* |
1633
|
|
|
* @WordPress\filter wordpoints_extension_server_api_edd_sl_ed25519_public_key |
1634
|
|
|
* |
1635
|
|
|
* @param string|false $public_key The public key for the server, or |
1636
|
|
|
* false if none. |
1637
|
|
|
* @param WordPoints_Extension_ServerI $server The server. |
1638
|
|
|
* |
1639
|
|
|
* @return string|false The public key, or false if none. |
1640
|
|
|
*/ |
1641
|
|
|
function wordpoints_extension_server_ed25519_public_keys( $public_key, $server ) { |
1642
|
|
|
|
1643
|
|
|
if ( 'wordpoints.org' === $server->get_slug() ) { |
1644
|
|
|
$public_key = WORDPOINTS_ORG_EXTENSIONS_ED25519_PUBLIC_KEY; |
1645
|
|
|
} |
1646
|
|
|
|
1647
|
|
|
return $public_key; |
1648
|
|
|
} |
1649
|
|
|
|
1650
|
|
|
// EOF |
1651
|
|
|
|