1
|
|
|
<?php |
2
|
|
|
/** |
3
|
|
|
* Manages plugin packages under mod. |
4
|
|
|
* |
5
|
|
|
* @todo This should eventually be merged into \ElggPlugin. |
6
|
|
|
* Currently \ElggPlugin objects are only used to get and save |
7
|
|
|
* plugin settings and user settings, so not every plugin |
8
|
|
|
* has an \ElggPlugin object. It's not implemented in \ElggPlugin |
9
|
|
|
* right now because of conflicts with at least the constructor, |
10
|
|
|
* enable(), disable(), and private settings. |
11
|
|
|
* |
12
|
|
|
* Around 1.9 or so we should each plugin over to using |
13
|
|
|
* \ElggPlugin and merge \ElggPluginPackage and \ElggPlugin. |
14
|
|
|
* |
15
|
|
|
* @package Elgg.Core |
16
|
|
|
* @subpackage Plugins |
17
|
|
|
* @since 1.8 |
18
|
|
|
*/ |
19
|
|
|
class ElggPluginPackage { |
20
|
|
|
|
21
|
|
|
/** |
22
|
|
|
* The required files in the package |
23
|
|
|
* |
24
|
|
|
* @var array |
25
|
|
|
*/ |
26
|
|
|
private $requiredFiles = array( |
27
|
|
|
'start.php', 'manifest.xml' |
28
|
|
|
); |
29
|
|
|
|
30
|
|
|
/** |
31
|
|
|
* The optional files that can be read and served through the markdown page handler |
32
|
|
|
* @var array |
33
|
|
|
*/ |
34
|
|
|
private $textFiles = array( |
35
|
|
|
'README.txt', 'CHANGES.txt', |
36
|
|
|
'INSTALL.txt', 'COPYRIGHT.txt', 'LICENSE.txt', |
37
|
|
|
|
38
|
|
|
'README', 'README.md', 'README.markdown' |
39
|
|
|
); |
40
|
|
|
|
41
|
|
|
/** |
42
|
|
|
* Valid types for provides. |
43
|
|
|
* |
44
|
|
|
* @var array |
45
|
|
|
*/ |
46
|
|
|
private $providesSupportedTypes = array( |
47
|
|
|
'plugin', 'php_extension' |
48
|
|
|
); |
49
|
|
|
|
50
|
|
|
/** |
51
|
|
|
* The type of requires/conflicts supported |
52
|
|
|
* |
53
|
|
|
* @var array |
54
|
|
|
*/ |
55
|
|
|
private $depsSupportedTypes = array( |
56
|
|
|
'elgg_version', 'elgg_release', 'php_version', 'php_extension', 'php_ini', 'plugin', 'priority', |
57
|
|
|
); |
58
|
|
|
|
59
|
|
|
/** |
60
|
|
|
* An invalid plugin error. |
61
|
|
|
*/ |
62
|
|
|
private $errorMsg = ''; |
63
|
|
|
|
64
|
|
|
/** |
65
|
|
|
* The plugin's manifest object |
66
|
|
|
* |
67
|
|
|
* @var \ElggPluginManifest |
68
|
|
|
*/ |
69
|
|
|
protected $manifest; |
70
|
|
|
|
71
|
|
|
/** |
72
|
|
|
* The plugin's full path |
73
|
|
|
* |
74
|
|
|
* @var string |
75
|
|
|
*/ |
76
|
|
|
protected $path; |
77
|
|
|
|
78
|
|
|
/** |
79
|
|
|
* Is the plugin valid? |
80
|
|
|
* |
81
|
|
|
* @var mixed Bool after validation check, null before. |
82
|
|
|
*/ |
83
|
|
|
protected $valid = null; |
84
|
|
|
|
85
|
|
|
/** |
86
|
|
|
* The plugin ID (dir name) |
87
|
|
|
* |
88
|
|
|
* @var string |
89
|
|
|
*/ |
90
|
|
|
protected $id; |
91
|
|
|
|
92
|
|
|
/** |
93
|
|
|
* Load a plugin package from mod/$id or by full path. |
94
|
|
|
* |
95
|
|
|
* @param string $plugin The ID (directory name) or full path of the plugin. |
96
|
|
|
* @param bool $validate Automatically run isValid()? |
97
|
|
|
* |
98
|
|
|
* @throws PluginException |
99
|
|
|
*/ |
100
|
|
|
public function __construct($plugin, $validate = true) { |
101
|
|
|
$plugin_path = _elgg_services()->config->getPluginsPath(); |
102
|
|
|
// @todo wanted to avoid another is_dir() call here. |
103
|
|
|
// should do some profiling to see how much it affects |
104
|
|
|
if (strpos($plugin, $plugin_path) === 0 || is_dir($plugin)) { |
105
|
|
|
// this is a path |
106
|
|
|
$path = sanitise_filepath($plugin); |
107
|
|
|
|
108
|
|
|
// the id is the last element of the array |
109
|
|
|
$path_array = explode('/', trim($path, '/')); |
110
|
|
|
$id = array_pop($path_array); |
111
|
|
|
} else { |
112
|
|
|
// this is a plugin id |
113
|
|
|
// strict plugin names |
114
|
|
|
if (preg_match('/[^a-z0-9\.\-_]/i', $plugin)) { |
115
|
|
|
throw new \PluginException(_elgg_services()->translator->translate('PluginException:InvalidID', array($plugin))); |
116
|
|
|
} |
117
|
|
|
|
118
|
|
|
$path = "{$plugin_path}$plugin/"; |
119
|
|
|
$id = $plugin; |
120
|
|
|
} |
121
|
|
|
|
122
|
|
|
if (!is_dir($path)) { |
123
|
|
|
throw new \PluginException(_elgg_services()->translator->translate('PluginException:InvalidPath', array($path))); |
124
|
|
|
} |
125
|
|
|
|
126
|
|
|
$this->path = $path; |
127
|
|
|
$this->id = $id; |
128
|
|
|
|
129
|
|
|
if ($validate && !$this->isValid()) { |
130
|
|
|
if ($this->errorMsg) { |
131
|
|
|
throw new \PluginException(_elgg_services()->translator->translate('PluginException:InvalidPlugin:Details', |
132
|
|
|
array($plugin, $this->errorMsg))); |
133
|
|
|
} else { |
134
|
|
|
throw new \PluginException(_elgg_services()->translator->translate('PluginException:InvalidPlugin', array($plugin))); |
135
|
|
|
} |
136
|
|
|
} |
137
|
|
|
} |
138
|
|
|
|
139
|
|
|
/******************************** |
140
|
|
|
* Validation and sanity checks * |
141
|
|
|
********************************/ |
142
|
|
|
|
143
|
|
|
/** |
144
|
|
|
* Checks if this is a valid Elgg plugin. |
145
|
|
|
* |
146
|
|
|
* Checks for requires files as defined at the start of this |
147
|
|
|
* class. Will check require manifest fields via \ElggPluginManifest |
148
|
|
|
* for Elgg 1.8 plugins. |
149
|
|
|
* |
150
|
|
|
* @note This doesn't check dependencies or conflicts. |
151
|
|
|
* Use {@link \ElggPluginPackage::canActivate()} or |
152
|
|
|
* {@link \ElggPluginPackage::checkDependencies()} for that. |
153
|
|
|
* |
154
|
|
|
* @return bool |
155
|
|
|
*/ |
156
|
|
|
public function isValid() { |
157
|
|
|
if (!isset($this->valid)) { |
158
|
|
|
$this->valid = $this->validate(); |
159
|
|
|
} |
160
|
|
|
return $this->valid; |
161
|
|
|
} |
162
|
|
|
|
163
|
|
|
/** |
164
|
|
|
* @return bool |
165
|
|
|
*/ |
166
|
|
|
private function validate() { |
167
|
|
|
// check required files. |
168
|
|
|
$have_req_files = true; |
169
|
|
|
foreach ($this->requiredFiles as $file) { |
170
|
|
|
if (!is_readable($this->path . $file)) { |
171
|
|
|
$have_req_files = false; |
|
|
|
|
172
|
|
|
$this->errorMsg = |
173
|
|
|
_elgg_services()->translator->translate('ElggPluginPackage:InvalidPlugin:MissingFile', array($file)); |
174
|
|
|
return false; |
175
|
|
|
} |
176
|
|
|
} |
177
|
|
|
|
178
|
|
|
// check required files |
179
|
|
|
if (!$have_req_files) { |
180
|
|
|
return $this->valid = false; |
181
|
|
|
} |
182
|
|
|
|
183
|
|
|
// check for valid manifest. |
184
|
|
|
if (!$this->loadManifest()) { |
185
|
|
|
return false; |
186
|
|
|
} |
187
|
|
|
|
188
|
|
|
if (!$this->isNamedCorrectly()) { |
189
|
|
|
return false; |
190
|
|
|
} |
191
|
|
|
|
192
|
|
|
// can't require or conflict with yourself or something you provide. |
193
|
|
|
// make sure provides are all valid. |
194
|
|
|
if (!$this->hasSaneDependencies()) { |
195
|
|
|
return false; |
196
|
|
|
} |
197
|
|
|
|
198
|
|
|
return true; |
199
|
|
|
} |
200
|
|
|
|
201
|
|
|
/** |
202
|
|
|
* Check that the plugin is installed in the directory with name specified |
203
|
|
|
* in the manifest's "id" element. |
204
|
|
|
* |
205
|
|
|
* @return bool |
206
|
|
|
*/ |
207
|
|
|
private function isNamedCorrectly() { |
208
|
|
|
$manifest = $this->getManifest(); |
209
|
|
|
if ($manifest) { |
210
|
|
|
$required_id = $manifest->getID(); |
211
|
|
|
if (!empty($required_id) && ($required_id !== $this->id)) { |
212
|
|
|
$this->errorMsg = |
213
|
|
|
_elgg_services()->translator->translate('ElggPluginPackage:InvalidPlugin:InvalidId', array($required_id)); |
214
|
|
|
return false; |
215
|
|
|
} |
216
|
|
|
} |
217
|
|
|
return true; |
218
|
|
|
} |
219
|
|
|
|
220
|
|
|
/** |
221
|
|
|
* Check the plugin doesn't require or conflict with itself |
222
|
|
|
* or something provides. Also check that it only list |
223
|
|
|
* valid provides. Deps are checked in checkDependencies() |
224
|
|
|
* |
225
|
|
|
* @note Plugins always provide themselves. |
226
|
|
|
* |
227
|
|
|
* @todo Don't let them require and conflict the same thing |
228
|
|
|
* |
229
|
|
|
* @return bool |
230
|
|
|
*/ |
231
|
|
|
private function hasSaneDependencies() { |
232
|
|
|
// protection against plugins with no manifest file |
233
|
|
|
if (!$this->getManifest()) { |
234
|
|
|
return false; |
235
|
|
|
} |
236
|
|
|
|
237
|
|
|
// Note: $conflicts and $requires are not unused. They're called dynamically |
238
|
|
|
$conflicts = $this->getManifest()->getConflicts(); |
239
|
|
|
$requires = $this->getManifest()->getRequires(); |
240
|
|
|
$provides = $this->getManifest()->getProvides(); |
241
|
|
|
|
242
|
|
|
foreach ($provides as $provide) { |
243
|
|
|
// only valid provide types |
244
|
|
View Code Duplication |
if (!in_array($provide['type'], $this->providesSupportedTypes)) { |
245
|
|
|
$this->errorMsg = |
246
|
|
|
_elgg_services()->translator->translate('ElggPluginPackage:InvalidPlugin:InvalidProvides', array($provide['type'])); |
247
|
|
|
return false; |
248
|
|
|
} |
249
|
|
|
|
250
|
|
|
// doesn't conflict or require any of its provides |
251
|
|
|
$name = $provide['name']; |
252
|
|
|
foreach (array('conflicts', 'requires') as $dep_type) { |
253
|
|
|
foreach (${$dep_type} as $dep) { |
254
|
|
View Code Duplication |
if (!in_array($dep['type'], $this->depsSupportedTypes)) { |
255
|
|
|
$this->errorMsg = |
256
|
|
|
_elgg_services()->translator->translate('ElggPluginPackage:InvalidPlugin:InvalidDependency', array($dep['type'])); |
257
|
|
|
return false; |
258
|
|
|
} |
259
|
|
|
|
260
|
|
|
// make sure nothing is providing something it conflicts or requires. |
261
|
|
|
if (isset($dep['name']) && $dep['name'] == $name) { |
262
|
|
|
$version_compare = version_compare($provide['version'], $dep['version'], $dep['comparison']); |
263
|
|
|
|
264
|
|
View Code Duplication |
if ($version_compare) { |
265
|
|
|
$this->errorMsg = |
266
|
|
|
_elgg_services()->translator->translate('ElggPluginPackage:InvalidPlugin:CircularDep', |
267
|
|
|
array($dep['type'], $dep['name'], $this->id)); |
268
|
|
|
|
269
|
|
|
return false; |
270
|
|
|
} |
271
|
|
|
} |
272
|
|
|
} |
273
|
|
|
} |
274
|
|
|
} |
275
|
|
|
|
276
|
|
|
return true; |
277
|
|
|
} |
278
|
|
|
|
279
|
|
|
|
280
|
|
|
/************ |
281
|
|
|
* Manifest * |
282
|
|
|
************/ |
283
|
|
|
|
284
|
|
|
/** |
285
|
|
|
* Returns a parsed manifest file. |
286
|
|
|
* |
287
|
|
|
* @return \ElggPluginManifest |
288
|
|
|
*/ |
289
|
|
|
public function getManifest() { |
290
|
|
|
if (!$this->manifest) { |
291
|
|
|
if (!$this->loadManifest()) { |
292
|
|
|
return false; |
|
|
|
|
293
|
|
|
} |
294
|
|
|
} |
295
|
|
|
|
296
|
|
|
return $this->manifest; |
297
|
|
|
} |
298
|
|
|
|
299
|
|
|
/** |
300
|
|
|
* Loads the manifest into this->manifest as an |
301
|
|
|
* \ElggPluginManifest object. |
302
|
|
|
* |
303
|
|
|
* @return bool |
304
|
|
|
*/ |
305
|
|
|
private function loadManifest() { |
306
|
|
|
$file = $this->path . 'manifest.xml'; |
307
|
|
|
|
308
|
|
|
try { |
309
|
|
|
$this->manifest = new \ElggPluginManifest($file, $this->id); |
310
|
|
|
} catch (Exception $e) { |
311
|
|
|
$this->errorMsg = $e->getMessage(); |
312
|
|
|
return false; |
313
|
|
|
} |
314
|
|
|
|
315
|
|
|
if ($this->manifest instanceof \ElggPluginManifest) { |
316
|
|
|
return true; |
317
|
|
|
} |
318
|
|
|
|
319
|
|
|
$this->errorMsg = _elgg_services()->translator->translate('unknown_error'); |
320
|
|
|
return false; |
321
|
|
|
} |
322
|
|
|
|
323
|
|
|
/**************** |
324
|
|
|
* Readme Files * |
325
|
|
|
***************/ |
326
|
|
|
|
327
|
|
|
/** |
328
|
|
|
* Returns an array of present and readable text files |
329
|
|
|
* |
330
|
|
|
* @return array |
331
|
|
|
*/ |
332
|
|
|
public function getTextFilenames() { |
333
|
|
|
return $this->textFiles; |
334
|
|
|
} |
335
|
|
|
|
336
|
|
|
/*********************** |
337
|
|
|
* Dependencies system * |
338
|
|
|
***********************/ |
339
|
|
|
|
340
|
|
|
/** |
341
|
|
|
* Returns if the Elgg system meets the plugin's dependency |
342
|
|
|
* requirements. This includes both requires and conflicts. |
343
|
|
|
* |
344
|
|
|
* Full reports can be requested. The results are returned |
345
|
|
|
* as an array of arrays in the form array( |
346
|
|
|
* 'type' => requires|conflicts, |
347
|
|
|
* 'dep' => array( dependency array ), |
348
|
|
|
* 'status' => bool if depedency is met, |
349
|
|
|
* 'comment' => optional comment to display to the user. |
350
|
|
|
* ) |
351
|
|
|
* |
352
|
|
|
* @param bool $full_report Return a full report. |
353
|
|
|
* @return bool|array |
354
|
|
|
*/ |
355
|
|
|
public function checkDependencies($full_report = false) { |
356
|
|
|
// Note: $conflicts and $requires are not unused. They're called dynamically |
357
|
|
|
$requires = $this->getManifest()->getRequires(); |
358
|
|
|
$conflicts = $this->getManifest()->getConflicts(); |
359
|
|
|
|
360
|
|
|
$enabled_plugins = elgg_get_plugins('active'); |
361
|
|
|
$this_id = $this->getID(); |
362
|
|
|
$report = array(); |
363
|
|
|
|
364
|
|
|
// first, check if any active plugin conflicts with us. |
365
|
|
|
foreach ($enabled_plugins as $plugin) { |
|
|
|
|
366
|
|
|
$temp_conflicts = array(); |
367
|
|
|
$temp_manifest = $plugin->getManifest(); |
368
|
|
|
if ($temp_manifest instanceof \ElggPluginManifest) { |
369
|
|
|
$temp_conflicts = $plugin->getManifest()->getConflicts(); |
370
|
|
|
} |
371
|
|
|
foreach ($temp_conflicts as $conflict) { |
372
|
|
|
if ($conflict['type'] == 'plugin' && $conflict['name'] == $this_id) { |
373
|
|
|
$result = $this->checkDepPlugin($conflict, $enabled_plugins, false); |
374
|
|
|
|
375
|
|
|
// rewrite the conflict to show the originating plugin |
376
|
|
|
$conflict['name'] = $plugin->getManifest()->getName(); |
377
|
|
|
|
378
|
|
|
if (!$full_report && !$result['status']) { |
379
|
|
|
$this->errorMsg = "Conflicts with plugin \"{$plugin->getManifest()->getName()}\"."; |
380
|
|
|
return $result['status']; |
381
|
|
|
} else { |
382
|
|
|
$report[] = array( |
383
|
|
|
'type' => 'conflicted', |
384
|
|
|
'dep' => $conflict, |
385
|
|
|
'status' => $result['status'], |
386
|
|
|
'value' => $this->getManifest()->getVersion() |
387
|
|
|
); |
388
|
|
|
} |
389
|
|
|
} |
390
|
|
|
} |
391
|
|
|
} |
392
|
|
|
|
393
|
|
|
$check_types = array('requires', 'conflicts'); |
394
|
|
|
|
395
|
|
|
if ($full_report) { |
396
|
|
|
// Note: $suggests is not unused. It's called dynamically |
397
|
|
|
$suggests = $this->getManifest()->getSuggests(); |
398
|
|
|
$check_types[] = 'suggests'; |
399
|
|
|
} |
400
|
|
|
|
401
|
|
|
foreach ($check_types as $dep_type) { |
402
|
|
|
$inverse = ($dep_type == 'conflicts') ? true : false; |
403
|
|
|
|
404
|
|
|
foreach (${$dep_type} as $dep) { |
405
|
|
|
switch ($dep['type']) { |
406
|
|
|
case 'elgg_version': |
407
|
|
|
elgg_deprecated_notice("elgg_version in manifest.xml files is deprecated. Use elgg_release", 1.9); |
408
|
|
|
$result = $this->checkDepElgg($dep, elgg_get_version(), $inverse); |
|
|
|
|
409
|
|
|
break; |
410
|
|
|
|
411
|
|
|
case 'elgg_release': |
412
|
|
|
$result = $this->checkDepElgg($dep, elgg_get_version(true), $inverse); |
|
|
|
|
413
|
|
|
break; |
414
|
|
|
|
415
|
|
|
case 'plugin': |
416
|
|
|
$result = $this->checkDepPlugin($dep, $enabled_plugins, $inverse); |
417
|
|
|
break; |
418
|
|
|
|
419
|
|
|
case 'priority': |
420
|
|
|
$result = $this->checkDepPriority($dep, $enabled_plugins, $inverse); |
421
|
|
|
break; |
422
|
|
|
|
423
|
|
|
case 'php_version': |
424
|
|
|
$result = $this->checkDepPhpVersion($dep, $inverse); |
425
|
|
|
break; |
426
|
|
|
|
427
|
|
|
case 'php_extension': |
428
|
|
|
$result = $this->checkDepPhpExtension($dep, $inverse); |
429
|
|
|
break; |
430
|
|
|
|
431
|
|
|
case 'php_ini': |
432
|
|
|
$result = $this->checkDepPhpIni($dep, $inverse); |
433
|
|
|
break; |
434
|
|
|
|
435
|
|
|
default: |
436
|
|
|
$result = null;//skip further check |
437
|
|
|
break; |
438
|
|
|
} |
439
|
|
|
|
440
|
|
|
if ($result !== null) { |
441
|
|
|
// unless we're doing a full report, break as soon as we fail. |
442
|
|
|
if (!$full_report && !$result['status']) { |
443
|
|
|
$this->errorMsg = "Missing dependencies."; |
444
|
|
|
return $result['status']; |
445
|
|
|
} else { |
446
|
|
|
// build report element and comment |
447
|
|
|
$report[] = array( |
448
|
|
|
'type' => $dep_type, |
449
|
|
|
'dep' => $dep, |
450
|
|
|
'status' => $result['status'], |
451
|
|
|
'value' => $result['value'] |
452
|
|
|
); |
453
|
|
|
} |
454
|
|
|
} |
455
|
|
|
} |
456
|
|
|
} |
457
|
|
|
|
458
|
|
|
if ($full_report) { |
459
|
|
|
// add provides to full report |
460
|
|
|
$provides = $this->getManifest()->getProvides(); |
461
|
|
|
|
462
|
|
|
foreach ($provides as $provide) { |
463
|
|
|
$report[] = array( |
464
|
|
|
'type' => 'provides', |
465
|
|
|
'dep' => $provide, |
466
|
|
|
'status' => true, |
467
|
|
|
'value' => '' |
468
|
|
|
); |
469
|
|
|
} |
470
|
|
|
|
471
|
|
|
return $report; |
472
|
|
|
} |
473
|
|
|
|
474
|
|
|
return true; |
475
|
|
|
} |
476
|
|
|
|
477
|
|
|
/** |
478
|
|
|
* Checks if $plugins meets the requirement by $dep. |
479
|
|
|
* |
480
|
|
|
* @param array $dep An Elgg manifest.xml deps array |
481
|
|
|
* @param array $plugins A list of plugins as returned by elgg_get_plugins(); |
482
|
|
|
* @param bool $inverse Inverse the results to use as a conflicts. |
483
|
|
|
* @return bool |
484
|
|
|
*/ |
485
|
|
|
private function checkDepPlugin(array $dep, array $plugins, $inverse = false) { |
486
|
|
|
$r = _elgg_check_plugins_provides('plugin', $dep['name'], $dep['version'], $dep['comparison']); |
487
|
|
|
|
488
|
|
|
if ($inverse) { |
489
|
|
|
$r['status'] = !$r['status']; |
490
|
|
|
} |
491
|
|
|
|
492
|
|
|
return $r; |
493
|
|
|
} |
494
|
|
|
|
495
|
|
|
/** |
496
|
|
|
* Checks if $plugins meets the requirement by $dep. |
497
|
|
|
* |
498
|
|
|
* @param array $dep An Elgg manifest.xml deps array |
499
|
|
|
* @param array $plugins A list of plugins as returned by elgg_get_plugins(); |
500
|
|
|
* @param bool $inverse Inverse the results to use as a conflicts. |
501
|
|
|
* @return bool |
502
|
|
|
*/ |
503
|
|
|
private function checkDepPriority(array $dep, array $plugins, $inverse = false) { |
504
|
|
|
// grab the \ElggPlugin using this package. |
505
|
|
|
$plugin_package = elgg_get_plugin_from_id($this->getID()); |
506
|
|
|
if (!$plugin_package) { |
507
|
|
|
return array( |
508
|
|
|
'status' => true, |
509
|
|
|
'value' => 'uninstalled' |
510
|
|
|
); |
511
|
|
|
} |
512
|
|
|
|
513
|
|
|
$test_plugin = elgg_get_plugin_from_id($dep['plugin']); |
514
|
|
|
|
515
|
|
|
// If this isn't a plugin or the plugin isn't installed or active |
516
|
|
|
// priority doesn't matter. Use requires to check if a plugin is active. |
517
|
|
|
if (!$test_plugin || !$test_plugin->isActive()) { |
518
|
|
|
return array( |
519
|
|
|
'status' => true, |
520
|
|
|
'value' => 'uninstalled' |
521
|
|
|
); |
522
|
|
|
} |
523
|
|
|
|
524
|
|
|
$plugin_priority = $plugin_package->getPriority(); |
525
|
|
|
$test_plugin_priority = $test_plugin->getPriority(); |
526
|
|
|
|
527
|
|
|
switch ($dep['priority']) { |
528
|
|
|
case 'before': |
529
|
|
|
$status = $plugin_priority < $test_plugin_priority; |
530
|
|
|
break; |
531
|
|
|
|
532
|
|
|
case 'after': |
533
|
|
|
$status = $plugin_priority > $test_plugin_priority; |
534
|
|
|
break; |
535
|
|
|
|
536
|
|
|
default; |
537
|
|
|
$status = false; |
538
|
|
|
} |
539
|
|
|
|
540
|
|
|
// get the current value |
541
|
|
|
if ($plugin_priority < $test_plugin_priority) { |
542
|
|
|
$value = 'before'; |
543
|
|
|
} else { |
544
|
|
|
$value = 'after'; |
545
|
|
|
} |
546
|
|
|
|
547
|
|
|
if ($inverse) { |
548
|
|
|
$status = !$status; |
549
|
|
|
} |
550
|
|
|
|
551
|
|
|
return array( |
552
|
|
|
'status' => $status, |
553
|
|
|
'value' => $value |
554
|
|
|
); |
555
|
|
|
} |
556
|
|
|
|
557
|
|
|
/** |
558
|
|
|
* Checks if $elgg_version meets the requirement by $dep. |
559
|
|
|
* |
560
|
|
|
* @param array $dep An Elgg manifest.xml deps array |
561
|
|
|
* @param array $elgg_version An Elgg version (either YYYYMMDDXX or X.Y.Z) |
562
|
|
|
* @param bool $inverse Inverse the result to use as a conflicts. |
563
|
|
|
* @return bool |
564
|
|
|
*/ |
565
|
|
View Code Duplication |
private function checkDepElgg(array $dep, $elgg_version, $inverse = false) { |
|
|
|
|
566
|
|
|
$status = version_compare($elgg_version, $dep['version'], $dep['comparison']); |
567
|
|
|
|
568
|
|
|
if ($inverse) { |
569
|
|
|
$status = !$status; |
570
|
|
|
} |
571
|
|
|
|
572
|
|
|
return array( |
573
|
|
|
'status' => $status, |
574
|
|
|
'value' => $elgg_version |
575
|
|
|
); |
576
|
|
|
} |
577
|
|
|
|
578
|
|
|
/** |
579
|
|
|
* Checks if $php_version meets the requirement by $dep. |
580
|
|
|
* |
581
|
|
|
* @param array $dep An Elgg manifest.xml deps array |
582
|
|
|
* @param bool $inverse Inverse the result to use as a conflicts. |
583
|
|
|
* @return bool |
584
|
|
|
*/ |
585
|
|
View Code Duplication |
private function checkDepPhpVersion(array $dep, $inverse = false) { |
|
|
|
|
586
|
|
|
$php_version = phpversion(); |
587
|
|
|
$status = version_compare($php_version, $dep['version'], $dep['comparison']); |
588
|
|
|
|
589
|
|
|
if ($inverse) { |
590
|
|
|
$status = !$status; |
591
|
|
|
} |
592
|
|
|
|
593
|
|
|
return array( |
594
|
|
|
'status' => $status, |
595
|
|
|
'value' => $php_version |
596
|
|
|
); |
597
|
|
|
} |
598
|
|
|
|
599
|
|
|
/** |
600
|
|
|
* Checks if the PHP extension in $dep is loaded. |
601
|
|
|
* |
602
|
|
|
* @todo Can this be merged with the plugin checker? |
603
|
|
|
* |
604
|
|
|
* @param array $dep An Elgg manifest.xml deps array |
605
|
|
|
* @param bool $inverse Inverse the result to use as a conflicts. |
606
|
|
|
* @return array An array in the form array( |
607
|
|
|
* 'status' => bool |
608
|
|
|
* 'value' => string The version provided |
609
|
|
|
* ) |
610
|
|
|
*/ |
611
|
|
|
private function checkDepPhpExtension(array $dep, $inverse = false) { |
612
|
|
|
$name = $dep['name']; |
613
|
|
|
$version = $dep['version']; |
614
|
|
|
$comparison = $dep['comparison']; |
615
|
|
|
|
616
|
|
|
// not enabled. |
617
|
|
|
$status = extension_loaded($name); |
618
|
|
|
|
619
|
|
|
// enabled. check version. |
620
|
|
|
$ext_version = phpversion($name); |
621
|
|
|
|
622
|
|
|
if ($status) { |
623
|
|
|
// some extensions (like gd) don't provide versions. neat. |
624
|
|
|
// don't check version info and return a lie. |
625
|
|
|
if ($ext_version && $version) { |
626
|
|
|
$status = version_compare($ext_version, $version, $comparison); |
627
|
|
|
} |
628
|
|
|
|
629
|
|
|
if (!$ext_version) { |
630
|
|
|
$ext_version = '???'; |
631
|
|
|
} |
632
|
|
|
} |
633
|
|
|
|
634
|
|
|
// some php extensions can be emulated, so check provides. |
635
|
|
|
if ($status == false) { |
|
|
|
|
636
|
|
|
$provides = _elgg_check_plugins_provides('php_extension', $name, $version, $comparison); |
637
|
|
|
$status = $provides['status']; |
638
|
|
|
$ext_version = $provides['value']; |
639
|
|
|
} |
640
|
|
|
|
641
|
|
|
if ($inverse) { |
642
|
|
|
$status = !$status; |
643
|
|
|
} |
644
|
|
|
|
645
|
|
|
return array( |
646
|
|
|
'status' => $status, |
647
|
|
|
'value' => $ext_version |
648
|
|
|
); |
649
|
|
|
} |
650
|
|
|
|
651
|
|
|
/** |
652
|
|
|
* Check if the PHP ini setting satisfies $dep. |
653
|
|
|
* |
654
|
|
|
* @param array $dep An Elgg manifest.xml deps array |
655
|
|
|
* @param bool $inverse Inverse the result to use as a conflicts. |
656
|
|
|
* @return bool |
657
|
|
|
*/ |
658
|
|
|
private function checkDepPhpIni($dep, $inverse = false) { |
659
|
|
|
$name = $dep['name']; |
660
|
|
|
$value = $dep['value']; |
661
|
|
|
$comparison = $dep['comparison']; |
662
|
|
|
|
663
|
|
|
// ini_get() normalizes truthy values to 1 but falsey values to 0 or ''. |
664
|
|
|
// version_compare() considers '' < 0, so normalize '' to 0. |
665
|
|
|
// \ElggPluginManifest normalizes all bool values and '' to 1 or 0. |
666
|
|
|
$setting = ini_get($name); |
667
|
|
|
|
668
|
|
|
if ($setting === '') { |
669
|
|
|
$setting = 0; |
670
|
|
|
} |
671
|
|
|
|
672
|
|
|
$status = version_compare($setting, $value, $comparison); |
673
|
|
|
|
674
|
|
|
if ($inverse) { |
675
|
|
|
$status = !$status; |
676
|
|
|
} |
677
|
|
|
|
678
|
|
|
return array( |
679
|
|
|
'status' => $status, |
680
|
|
|
'value' => $setting |
681
|
|
|
); |
682
|
|
|
} |
683
|
|
|
|
684
|
|
|
/** |
685
|
|
|
* Returns the Plugin ID |
686
|
|
|
* |
687
|
|
|
* @return string |
688
|
|
|
*/ |
689
|
|
|
public function getID() { |
690
|
|
|
return $this->id; |
691
|
|
|
} |
692
|
|
|
|
693
|
|
|
/** |
694
|
|
|
* Returns the last error message. |
695
|
|
|
* |
696
|
|
|
* @return string |
697
|
|
|
*/ |
698
|
|
|
public function getError() { |
699
|
|
|
return $this->errorMsg; |
700
|
|
|
} |
701
|
|
|
} |
702
|
|
|
|
This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.
Both the
$myVar
assignment in line 1 and the$higher
assignment in line 2 are dead. The first because$myVar
is never used and the second because$higher
is always overwritten for every possible time line.