1
|
|
|
<?php |
2
|
|
|
|
3
|
|
|
/** |
4
|
|
|
* Installable class. |
5
|
|
|
* |
6
|
|
|
* @package WordPoints |
7
|
|
|
* @since 2.4.0 |
8
|
|
|
*/ |
9
|
|
|
|
10
|
|
|
/** |
11
|
|
|
* Represents an installable entity. |
12
|
|
|
* |
13
|
|
|
* Provides info about the entity and getters and setters for some stored data |
14
|
|
|
* relating to it. |
15
|
|
|
* |
16
|
|
|
* @since 2.4.0 |
17
|
|
|
*/ |
18
|
|
|
abstract class WordPoints_Installable implements WordPoints_InstallableI { |
19
|
|
|
|
20
|
|
|
/** |
21
|
|
|
* The type of entity. |
22
|
|
|
* |
23
|
|
|
* For example, 'module' or 'component'. |
24
|
|
|
* |
25
|
|
|
* Note that this is singular, even though in the 'wordpoints_data' option the |
26
|
|
|
* plural forms are used for legacy reasons. |
27
|
|
|
* |
28
|
|
|
* @since 2.4.0 |
29
|
|
|
* |
30
|
|
|
* @var string |
31
|
|
|
*/ |
32
|
|
|
protected $type; |
33
|
|
|
|
34
|
|
|
/** |
35
|
|
|
* The slug of this entity. |
36
|
|
|
* |
37
|
|
|
* @since 2.4.0 |
38
|
|
|
* |
39
|
|
|
* @var string |
40
|
|
|
*/ |
41
|
|
|
protected $slug; |
42
|
|
|
|
43
|
|
|
/** |
44
|
|
|
* @since 2.4.0 |
45
|
|
|
*/ |
46
|
|
|
public function get_slug() { |
47
|
|
|
return $this->slug; |
48
|
|
|
} |
49
|
|
|
|
50
|
|
|
/** |
51
|
|
|
* @since 2.4.0 |
52
|
|
|
*/ |
53
|
|
|
public function get_db_version( $network = false ) { |
54
|
|
|
|
55
|
|
|
$wordpoints_data = wordpoints_get_maybe_network_array_option( |
56
|
|
|
'wordpoints_data' |
57
|
|
|
, $network |
58
|
|
|
); |
59
|
|
|
|
60
|
|
|
if ( 'wordpoints' === $this->slug ) { |
61
|
|
|
|
62
|
|
|
if ( isset( $wordpoints_data['version'] ) ) { |
63
|
|
|
return $wordpoints_data['version']; |
64
|
|
|
} |
65
|
|
|
|
66
|
|
|
} elseif ( isset( $wordpoints_data[ "{$this->type}s" ][ $this->slug ]['version'] ) ) { |
67
|
|
|
return $wordpoints_data[ "{$this->type}s" ][ $this->slug ]['version']; |
68
|
|
|
} |
69
|
|
|
|
70
|
|
|
return false; |
71
|
|
|
} |
72
|
|
|
|
73
|
|
|
/** |
74
|
|
|
* @since 2.4.0 |
75
|
|
|
*/ |
76
|
|
|
public function set_db_version( $version = null, $network = false ) { |
77
|
|
|
|
78
|
|
|
if ( null === $version ) { |
79
|
|
|
$version = $this->get_version(); |
80
|
|
|
} |
81
|
|
|
|
82
|
|
|
$wordpoints_data = wordpoints_get_maybe_network_array_option( |
83
|
|
|
'wordpoints_data' |
84
|
|
|
, $network |
85
|
|
|
); |
86
|
|
|
|
87
|
|
|
if ( 'wordpoints' === $this->slug ) { |
88
|
|
|
$wordpoints_data['version'] = $version; |
89
|
|
|
} else { |
90
|
|
|
$wordpoints_data[ "{$this->type}s" ][ $this->slug ]['version'] = $version; |
91
|
|
|
} |
92
|
|
|
|
93
|
|
|
wordpoints_update_maybe_network_option( |
94
|
|
|
'wordpoints_data' |
95
|
|
|
, $wordpoints_data |
96
|
|
|
, $network |
97
|
|
|
); |
98
|
|
|
} |
99
|
|
|
|
100
|
|
|
/** |
101
|
|
|
* @since 2.4.0 |
102
|
|
|
*/ |
103
|
|
|
public function unset_db_version( $network = false ) { |
104
|
|
|
|
105
|
|
|
$wordpoints_data = wordpoints_get_maybe_network_array_option( |
106
|
|
|
'wordpoints_data' |
107
|
|
|
, $network |
108
|
|
|
); |
109
|
|
|
|
110
|
|
|
if ( 'wordpoints' === $this->slug ) { |
111
|
|
|
unset( $wordpoints_data['version'] ); |
112
|
|
|
} else { |
113
|
|
|
unset( $wordpoints_data[ "{$this->type}s" ][ $this->slug ]['version'] ); |
114
|
|
|
} |
115
|
|
|
|
116
|
|
|
wordpoints_update_maybe_network_option( |
117
|
|
|
'wordpoints_data' |
118
|
|
|
, $wordpoints_data |
119
|
|
|
, $network |
120
|
|
|
); |
121
|
|
|
} |
122
|
|
|
|
123
|
|
|
/** |
124
|
|
|
* @since 2.4.0 |
125
|
|
|
*/ |
126
|
|
|
public function is_network_installed() { |
127
|
|
|
|
128
|
|
|
$network_installed = wordpoints_get_array_option( |
129
|
|
|
'wordpoints_network_installed' |
130
|
|
|
, 'site' |
131
|
|
|
); |
132
|
|
|
|
133
|
|
|
return isset( $network_installed[ $this->type ][ $this->slug ] ); |
134
|
|
|
} |
135
|
|
|
|
136
|
|
|
/** |
137
|
|
|
* @since 2.4.0 |
138
|
|
|
*/ |
139
|
|
|
public function set_network_installed() { |
140
|
|
|
$this->set_option( 'network_installed' ); |
141
|
|
|
} |
142
|
|
|
|
143
|
|
|
/** |
144
|
|
|
* @since 2.4.0 |
145
|
|
|
*/ |
146
|
|
|
public function unset_network_installed() { |
147
|
|
|
$this->unset_option( 'network_installed' ); |
148
|
|
|
} |
149
|
|
|
|
150
|
|
|
/** |
151
|
|
|
* @since 2.4.0 |
152
|
|
|
*/ |
153
|
|
|
public function set_network_install_skipped() { |
154
|
|
|
$this->set_option( 'network_install_skipped' ); |
155
|
|
|
} |
156
|
|
|
|
157
|
|
|
/** |
158
|
|
|
* @since 2.4.0 |
159
|
|
|
*/ |
160
|
|
|
public function unset_network_install_skipped() { |
161
|
|
|
$this->unset_option( 'network_install_skipped' ); |
162
|
|
|
} |
163
|
|
|
|
164
|
|
|
/** |
165
|
|
|
* @since 2.4.0 |
166
|
|
|
*/ |
167
|
|
|
public function set_network_update_skipped( $updating_from = null ) { |
168
|
|
|
|
169
|
|
|
if ( ! isset( $updating_from ) ) { |
170
|
|
|
$updating_from = $this->get_db_version( true ); |
171
|
|
|
} |
172
|
|
|
|
173
|
|
|
$this->set_option( 'network_update_skipped', $updating_from ); |
174
|
|
|
} |
175
|
|
|
|
176
|
|
|
/** |
177
|
|
|
* @since 2.4.0 |
178
|
|
|
*/ |
179
|
|
|
public function unset_network_update_skipped() { |
180
|
|
|
$this->unset_option( 'network_update_skipped' ); |
181
|
|
|
} |
182
|
|
|
|
183
|
|
|
/** |
184
|
|
|
* Sets an option in the database for this entity. |
185
|
|
|
* |
186
|
|
|
* @since 2.4.0 |
187
|
|
|
* |
188
|
|
|
* @param string $option The name of the option to set. |
189
|
|
|
* @param mixed $value The value of the option. |
190
|
|
|
*/ |
191
|
|
View Code Duplication |
protected function set_option( $option, $value = true ) { |
|
|
|
|
192
|
|
|
|
193
|
|
|
$data = wordpoints_get_array_option( |
194
|
|
|
"wordpoints_{$option}" |
195
|
|
|
, 'site' |
196
|
|
|
); |
197
|
|
|
|
198
|
|
|
$data[ $this->type ][ $this->slug ] = $value; |
199
|
|
|
|
200
|
|
|
update_site_option( "wordpoints_{$option}", $data ); |
|
|
|
|
201
|
|
|
} |
202
|
|
|
|
203
|
|
|
/** |
204
|
|
|
* Deletes an option in the database for this entity. |
205
|
|
|
* |
206
|
|
|
* @since 2.4.0 |
207
|
|
|
* |
208
|
|
|
* @param string $option The name of the option to delete. |
209
|
|
|
*/ |
210
|
|
View Code Duplication |
protected function unset_option( $option ) { |
|
|
|
|
211
|
|
|
|
212
|
|
|
$data = wordpoints_get_array_option( |
213
|
|
|
"wordpoints_{$option}" |
214
|
|
|
, 'site' |
215
|
|
|
); |
216
|
|
|
|
217
|
|
|
unset( $data[ $this->type ][ $this->slug ] ); |
218
|
|
|
|
219
|
|
|
update_site_option( "wordpoints_{$option}", $data ); |
|
|
|
|
220
|
|
|
} |
221
|
|
|
|
222
|
|
|
/** |
223
|
|
|
* @since 2.4.0 |
224
|
|
|
*/ |
225
|
|
|
public function get_installed_site_ids() { |
226
|
|
|
|
227
|
|
|
if ( $this->is_network_installed() ) { |
228
|
|
|
|
229
|
|
|
$site_ids = $this->get_all_site_ids(); |
230
|
|
|
|
231
|
|
|
} else { |
232
|
|
|
|
233
|
|
|
$site_ids = wordpoints_get_array_option( |
234
|
|
|
$this->get_installed_site_ids_option_name() |
235
|
|
|
, 'site' |
236
|
|
|
); |
237
|
|
|
|
238
|
|
|
$site_ids = $this->validate_site_ids( $site_ids ); |
239
|
|
|
} |
240
|
|
|
|
241
|
|
|
return $site_ids; |
242
|
|
|
} |
243
|
|
|
|
244
|
|
|
/** |
245
|
|
|
* Gets the name of the option where the list of installed sites is stored. |
246
|
|
|
* |
247
|
|
|
* @since 2.4.0 |
248
|
|
|
* |
249
|
|
|
* @return string The option name. |
250
|
|
|
*/ |
251
|
|
|
protected function get_installed_site_ids_option_name() { |
252
|
|
|
|
253
|
|
|
if ( 'wordpoints' === $this->slug ) { |
254
|
|
|
$option_prefix = 'wordpoints'; |
255
|
|
|
} elseif ( 'component' === $this->type ) { |
256
|
|
|
$option_prefix = "wordpoints_{$this->slug}"; |
257
|
|
|
} else { |
258
|
|
|
$option_prefix = "wordpoints_{$this->type}_{$this->slug}"; |
259
|
|
|
} |
260
|
|
|
|
261
|
|
|
return "{$option_prefix}_installed_sites"; |
262
|
|
|
} |
263
|
|
|
|
264
|
|
|
/** |
265
|
|
|
* Gets the IDs of all sites on the network. |
266
|
|
|
* |
267
|
|
|
* @since 2.4.0 |
268
|
|
|
* |
269
|
|
|
* @return array The IDs of all sites on the network. |
270
|
|
|
*/ |
271
|
|
|
protected function get_all_site_ids() { |
272
|
|
|
|
273
|
|
|
return get_sites( |
|
|
|
|
274
|
|
|
array( |
275
|
|
|
'fields' => 'ids', |
276
|
|
|
'network_id' => get_current_network_id(), |
|
|
|
|
277
|
|
|
'number' => 0, |
278
|
|
|
) |
279
|
|
|
); |
280
|
|
|
} |
281
|
|
|
|
282
|
|
|
/** |
283
|
|
|
* Validates a list of site IDs against the database. |
284
|
|
|
* |
285
|
|
|
* @since 2.4.0 |
286
|
|
|
* |
287
|
|
|
* @param array $site_ids The site IDs to validate. |
288
|
|
|
* |
289
|
|
|
* @return int[] The validated site IDs. |
290
|
|
|
*/ |
291
|
|
View Code Duplication |
protected function validate_site_ids( $site_ids ) { |
|
|
|
|
292
|
|
|
|
293
|
|
|
if ( empty( $site_ids ) || ! is_array( $site_ids ) ) { |
294
|
|
|
return array(); |
295
|
|
|
} |
296
|
|
|
|
297
|
|
|
$site_ids = get_sites( |
|
|
|
|
298
|
|
|
array( |
299
|
|
|
'fields' => 'ids', |
300
|
|
|
'network_id' => get_current_network_id(), |
|
|
|
|
301
|
|
|
'number' => 0, |
302
|
|
|
'site__in' => $site_ids, |
303
|
|
|
) |
304
|
|
|
); |
305
|
|
|
|
306
|
|
|
return $site_ids; |
307
|
|
|
} |
308
|
|
|
|
309
|
|
|
/** |
310
|
|
|
* @since 2.4.0 |
311
|
|
|
*/ |
312
|
|
|
public function add_installed_site_id( $id = null ) { |
313
|
|
|
|
314
|
|
|
if ( empty( $id ) ) { |
315
|
|
|
$id = get_current_blog_id(); |
|
|
|
|
316
|
|
|
} |
317
|
|
|
|
318
|
|
|
$option_name = $this->get_installed_site_ids_option_name(); |
319
|
|
|
|
320
|
|
|
$sites = wordpoints_get_array_option( $option_name, 'site' ); |
321
|
|
|
|
322
|
|
|
if ( ! in_array( $id, $sites, true ) ) { |
323
|
|
|
|
324
|
|
|
$sites[] = $id; |
325
|
|
|
|
326
|
|
|
update_site_option( $option_name, $sites ); |
|
|
|
|
327
|
|
|
} |
328
|
|
|
} |
329
|
|
|
|
330
|
|
|
/** |
331
|
|
|
* @since 2.4.0 |
332
|
|
|
*/ |
333
|
|
|
public function delete_installed_site_ids() { |
334
|
|
|
delete_site_option( $this->get_installed_site_ids_option_name() ); |
|
|
|
|
335
|
|
|
} |
336
|
|
|
|
337
|
|
|
/** |
338
|
|
|
* @since 2.4.0 |
339
|
|
|
*/ |
340
|
|
|
public function get_install_routines() { |
341
|
|
|
|
342
|
|
|
return array_merge_recursive( |
343
|
|
|
$this->get_db_tables_install_routines() |
344
|
|
|
, $this->get_custom_caps_install_routines() |
345
|
|
|
); |
346
|
|
|
} |
347
|
|
|
|
348
|
|
|
/** |
349
|
|
|
* Gets the install routines for database tables for this entity. |
350
|
|
|
* |
351
|
|
|
* @since 2.4.0 |
352
|
|
|
* |
353
|
|
|
* @return WordPoints_Installer_DB_Tables[] Routines for installing DB tables. |
354
|
|
|
*/ |
355
|
|
|
protected function get_db_tables_install_routines() { |
356
|
|
|
|
357
|
|
|
$routines = array(); |
358
|
|
|
|
359
|
|
|
$db_tables = wordpoints_map_context_shortcuts( $this->get_db_tables() ); |
360
|
|
|
|
361
|
|
View Code Duplication |
if ( isset( $db_tables['single'] ) ) { |
|
|
|
|
362
|
|
|
$routines['single'][] = new WordPoints_Installer_DB_Tables( |
363
|
|
|
$db_tables['single'] |
364
|
|
|
, 'base' |
365
|
|
|
); |
366
|
|
|
} |
367
|
|
|
|
368
|
|
|
if ( isset( $db_tables['site'] ) ) { |
369
|
|
|
$routines['site'][] = new WordPoints_Installer_DB_Tables( |
370
|
|
|
$db_tables['site'] |
371
|
|
|
); |
372
|
|
|
} |
373
|
|
|
|
374
|
|
View Code Duplication |
if ( isset( $db_tables['network'] ) ) { |
|
|
|
|
375
|
|
|
$routines['network'][] = new WordPoints_Installer_DB_Tables( |
376
|
|
|
$db_tables['network'] |
377
|
|
|
, 'base' |
378
|
|
|
); |
379
|
|
|
} |
380
|
|
|
|
381
|
|
|
return $routines; |
382
|
|
|
} |
383
|
|
|
|
384
|
|
|
/** |
385
|
|
|
* Gets database tables for this entity. |
386
|
|
|
* |
387
|
|
|
* An array of arrays, where each sub-array holds the tables for a particular |
388
|
|
|
* context. Within each sub-array, the value of each element is the DB field |
389
|
|
|
* schema for a table (i.e., the part of the CREATE TABLE query within the main |
390
|
|
|
* parentheses), and the keys are the table names. The base DB prefix will be |
391
|
|
|
* prepended to table names for $single and $network, while $site tables will be |
392
|
|
|
* prepended with blog prefix instead. |
393
|
|
|
* |
394
|
|
|
* @since 2.4.0 |
395
|
|
|
* |
396
|
|
|
* @return string[][] $db_tables { |
397
|
|
|
* @type string[] $single Tables for a single site (non-multisite) install. |
398
|
|
|
* @type string[] $site Tables for each site in a multisite network. |
399
|
|
|
* @type string[] $network Tables for a multisite network. |
400
|
|
|
* @type string[] $local Tables for $single and $site. |
401
|
|
|
* @type string[] $global Tables for $single and $network. |
402
|
|
|
* @type string[] $universal Tables for $single, $site, and $network. |
403
|
|
|
* } |
404
|
|
|
*/ |
405
|
|
|
protected function get_db_tables() { |
406
|
|
|
return array(); |
407
|
|
|
} |
408
|
|
|
|
409
|
|
|
/** |
410
|
|
|
* Gets install routines for custom capabilities for this entity. |
411
|
|
|
* |
412
|
|
|
* @since 2.4.0 |
413
|
|
|
* |
414
|
|
|
* @return WordPoints_Installer_Caps[][] Custom caps installers. |
415
|
|
|
*/ |
416
|
|
|
protected function get_custom_caps_install_routines() { |
417
|
|
|
|
418
|
|
|
$caps = $this->get_custom_caps(); |
419
|
|
|
|
420
|
|
|
if ( empty( $caps ) ) { |
421
|
|
|
return array(); |
422
|
|
|
} |
423
|
|
|
|
424
|
|
|
return array( |
425
|
|
|
'site' => array( new WordPoints_Installer_Caps( $caps ) ), |
426
|
|
|
'single' => array( new WordPoints_Installer_Caps( $caps ) ), |
427
|
|
|
); |
428
|
|
|
} |
429
|
|
|
|
430
|
|
|
/** |
431
|
|
|
* Gets the custom capabilities used by this entity. |
432
|
|
|
* |
433
|
|
|
* The function should return an array of capabilities of the format processed |
434
|
|
|
* by {@see wordpoints_add_custom_caps()}. |
435
|
|
|
* |
436
|
|
|
* @since 2.4.0 |
437
|
|
|
* |
438
|
|
|
* @return string[] The custom caps (keys) and their corresponding core caps |
439
|
|
|
* (values). |
440
|
|
|
*/ |
441
|
|
|
protected function get_custom_caps() { |
442
|
|
|
return array(); |
443
|
|
|
} |
444
|
|
|
|
445
|
|
|
/** |
446
|
|
|
* @since 2.4.0 |
447
|
|
|
*/ |
448
|
|
|
public function get_update_routine_factories() { |
449
|
|
|
return array(); |
450
|
|
|
} |
451
|
|
|
|
452
|
|
|
/** |
453
|
|
|
* @since 2.4.0 |
454
|
|
|
*/ |
455
|
|
|
public function get_uninstall_routines() { |
456
|
|
|
|
457
|
|
|
$routines = array( |
458
|
|
|
'single' => array(), |
459
|
|
|
'site' => array(), |
460
|
|
|
'network' => array(), |
461
|
|
|
); |
462
|
|
|
|
463
|
|
|
$factories = $this->get_uninstall_routine_factories(); |
464
|
|
|
|
465
|
|
|
if ( is_multisite() ) { |
|
|
|
|
466
|
|
|
|
467
|
|
|
foreach ( $factories as $factory ) { |
468
|
|
|
|
469
|
|
|
if ( $factory instanceof WordPoints_Uninstaller_Factory_SiteI ) { |
470
|
|
|
$routines['site'] = array_merge( $routines['site'], $factory->get_for_site() ); |
471
|
|
|
} |
472
|
|
|
|
473
|
|
|
if ( $factory instanceof WordPoints_Uninstaller_Factory_NetworkI ) { |
474
|
|
|
$routines['network'] = array_merge( $routines['network'], $factory->get_for_network() ); |
475
|
|
|
} |
476
|
|
|
} |
477
|
|
|
|
478
|
|
|
} else { |
479
|
|
|
|
480
|
|
|
foreach ( $factories as $factory ) { |
481
|
|
|
if ( $factory instanceof WordPoints_Uninstaller_Factory_SingleI ) { |
482
|
|
|
$routines['single'] = array_merge( $routines['single'], $factory->get_for_single() ); |
483
|
|
|
} |
484
|
|
|
} |
485
|
|
|
} |
486
|
|
|
|
487
|
|
|
return $routines; |
488
|
|
|
} |
489
|
|
|
|
490
|
|
|
/** |
491
|
|
|
* Gets a list of factories to create the uninstall routines for this entity. |
492
|
|
|
* |
493
|
|
|
* @since 2.4.0 |
494
|
|
|
* |
495
|
|
|
* @return object[] Uninstall routine factories. |
496
|
|
|
*/ |
497
|
|
|
protected function get_uninstall_routine_factories() { |
498
|
|
|
|
499
|
|
|
$factories = array(); |
500
|
|
|
|
501
|
|
|
$db_tables = $this->get_db_tables(); |
502
|
|
|
|
503
|
|
|
if ( ! empty( $db_tables ) ) { |
504
|
|
|
$factories[] = new WordPoints_Uninstaller_Factory_DB_Tables( |
505
|
|
|
array_map( 'array_keys', $db_tables ) |
506
|
|
|
); |
507
|
|
|
} |
508
|
|
|
|
509
|
|
|
$custom_caps = $this->get_custom_caps(); |
510
|
|
|
|
511
|
|
|
if ( ! empty( $custom_caps ) ) { |
512
|
|
|
$factories[] = new WordPoints_Uninstaller_Factory_Caps( |
513
|
|
|
array_keys( $custom_caps ) |
514
|
|
|
); |
515
|
|
|
} |
516
|
|
|
|
517
|
|
|
return $factories; |
518
|
|
|
} |
519
|
|
|
} |
520
|
|
|
|
521
|
|
|
// EOF |
522
|
|
|
|
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.