29 private $requiredFiles = [
37 private $textFiles = [
53 private $providesSupportedTypes = [
63 private $depsSupportedTypes = [
75 private $errorMsg =
'';
122 $path_array = explode(
'/', trim(
$path,
'/'));
123 $id = array_pop($path_array);
127 if (preg_match(
'/[^a-z0-9\.\-_]/i',
$plugin)) {
132 $path =
"{$plugin_path}$plugin/";
136 if (!is_dir(
$path)) {
144 if ($validate && !$this->
isValid()) {
145 if ($this->errorMsg) {
146 $msg =
elgg_echo(
'PluginException:InvalidPlugin:Details', [
$plugin, $this->errorMsg]);
173 if (!isset($this->valid)) {
174 $this->valid = $this->validate();
183 private function validate() {
185 foreach ($this->requiredFiles as
$file) {
186 if (!is_readable($this->
path . $file)) {
187 $this->errorMsg =
elgg_echo(
'ElggPluginPackage:InvalidPlugin:MissingFile', [$file]);
194 if (!$this->loadManifest()) {
198 if (!$this->isNamedCorrectly()) {
204 if (!$this->hasSaneDependencies()) {
208 if (!$this->hasReadableConfigFile()) {
221 private function hasReadableConfigFile() {
222 $file =
"{$this->path}/" . self::STATIC_CONFIG_FILENAME;
223 if (!is_file(
$file)) {
227 if (is_readable(
$file)) {
231 $this->errorMsg =
elgg_echo(
'ElggPluginPackage:InvalidPlugin:UnreadableConfig');
242 private function isNamedCorrectly() {
246 if (!empty($required_id) && ($required_id !== $this->
id)) {
247 $this->errorMsg =
elgg_echo(
'ElggPluginPackage:InvalidPlugin:InvalidId', [$required_id]);
267 private function hasSaneDependencies() {
278 foreach ($provides as $provide) {
280 if (!in_array($provide[
'type'], $this->providesSupportedTypes)) {
281 $this->errorMsg =
elgg_echo(
'ElggPluginPackage:InvalidPlugin:InvalidProvides', [
289 $name = $provide[
'name'];
290 foreach ([
'conflicts',
'requires'] as $dep_type) {
291 foreach (${$dep_type} as $dep) {
292 if (!in_array($dep[
'type'], $this->depsSupportedTypes)) {
293 $this->errorMsg =
elgg_echo(
'ElggPluginPackage:InvalidPlugin:InvalidDependency', [
301 if (isset($dep[
'name']) && $dep[
'name'] ==
$name) {
302 $version_compare = version_compare($provide[
'version'], $dep[
'version'], $dep[
'comparison']);
304 if ($version_compare) {
305 $this->errorMsg =
elgg_echo(
'ElggPluginPackage:InvalidPlugin:CircularDep', [
332 if (!$this->manifest) {
333 if (!$this->loadManifest()) {
347 private function loadManifest() {
351 $this->manifest = new \ElggPluginManifest(
$file, $this->
id);
355 $this->errorMsg = $e->getMessage();
364 $this->errorMsg =
elgg_echo(
'unknown_error');
379 return $this->textFiles;
408 $this_id = $this->
getID();
412 foreach ($enabled_plugins as
$plugin) {
413 $temp_conflicts = [];
414 $temp_manifest = $plugin->getManifest();
416 $temp_conflicts = $plugin->getManifest()->getConflicts();
418 foreach ($temp_conflicts as $conflict) {
419 if ($conflict[
'type'] ==
'plugin' && $conflict[
'name'] == $this_id) {
420 $result = $this->checkDepPlugin($conflict, $enabled_plugins,
false);
423 $conflict[
'name'] = $plugin->getDisplayName();
425 if (!$full_report && !
$result[
'status']) {
426 $css_id = preg_replace(
'/[^a-z0-9-]/i',
'-', $plugin->getManifest()->getID());
428 'text' => $plugin->getDisplayName(),
429 'href' =>
"#$css_id",
432 $key =
'ElggPluginPackage:InvalidPlugin:ConflictsWithPlugin';
433 $this->errorMsg =
elgg_echo($key, [$link]);
438 'type' =>
'conflicted',
448 $check_types = [
'requires',
'conflicts'];
453 $check_types[] =
'suggests';
456 foreach ($check_types as $dep_type) {
457 $inverse = ($dep_type ==
'conflicts') ?
true :
false;
459 foreach (${$dep_type} as $dep) {
460 switch ($dep[
'type']) {
466 $result = $this->checkDepPlugin($dep, $enabled_plugins, $inverse);
470 $result = $this->checkDepPriority($dep, $enabled_plugins, $inverse);
474 $result = $this->checkDepPhpVersion($dep, $inverse);
477 case 'php_extension':
478 $result = $this->checkDepPhpExtension($dep, $inverse);
482 $result = $this->checkDepPhpIni($dep, $inverse);
492 if (!$full_report && !
$result[
'status']) {
493 $type = $dep[
'type'];
495 if (
$type ===
'priority') {
496 $text =
"{$dep['priority']} {$dep['plugin']}";
498 $text = $dep[
'name'];
501 $this->errorMsg =
elgg_echo(
'admin:plugins:label:missing_dependency', [
"{$type}: {$text}"]);
521 foreach ($provides as $provide) {
523 'type' =>
'provides',
545 private function checkDepPlugin(array $dep, array
$plugins, $inverse =
false) {
546 $r =
_elgg_services()->plugins->checkProvides(
'plugin', $dep[
'name'], $dep[
'version'], $dep[
'comparison']);
549 $r[
'status'] = !$r[
'status'];
564 private function checkDepPriority(array $dep, array $plugins, $inverse =
false) {
567 if (!$plugin_package) {
570 'value' =>
'uninstalled' 578 if (!$test_plugin || !$test_plugin->isActive()) {
581 'value' =>
'uninstalled' 585 $plugin_priority = $plugin_package->getPriority();
586 $test_plugin_priority = $test_plugin->getPriority();
588 switch ($dep[
'priority']) {
590 $status = $plugin_priority < $test_plugin_priority;
594 $status = $plugin_priority > $test_plugin_priority;
602 if ($plugin_priority < $test_plugin_priority) {
627 private function checkDepElgg(array $dep, $elgg_version, $inverse =
false) {
628 $status = version_compare($elgg_version, $dep[
'version'], $dep[
'comparison']);
636 'value' => $elgg_version
648 private function checkDepPhpVersion(array $dep, $inverse =
false) {
649 $php_version = phpversion();
650 $status = version_compare($php_version, $dep[
'version'], $dep[
'comparison']);
658 'value' => $php_version
675 private function checkDepPhpExtension(array $dep, $inverse =
false) {
676 $name = $dep[
'name'];
678 $comparison = $dep[
'comparison'];
681 $status = extension_loaded(
$name);
684 $ext_version = phpversion(
$name);
690 $status = version_compare($ext_version,
$version, $comparison);
694 $ext_version =
'???';
699 if ($status ==
false) {
701 $status = $provides[
'status'];
702 $ext_version = $provides[
'value'];
711 'value' => $ext_version
723 private function checkDepPhpIni($dep, $inverse =
false) {
724 $name = $dep[
'name'];
726 $comparison = $dep[
'comparison'];
731 $setting = ini_get(
$name);
733 if ($setting ===
'') {
737 $status = version_compare($setting,
$value, $comparison);
764 return $this->errorMsg;
if(!$user||!$user->canDelete()) $name
if(!array_key_exists($filename, $text_files)) $file
getManifest()
Returns a parsed manifest file.
checkDependencies($full_report=false)
Returns if the Elgg system meets the plugin's dependency requirements.
elgg_echo($message_key, array $args=[], $language="")
Given a message key, returns an appropriately translated full-text string.
$CONFIG path
Legacy documentation for the old $CONFIG object.
if(!$item instanceof ElggEntity) $link
getTextFilenames()
Returns an array of present and readable text files.
static factory($reason, ElggPlugin $plugin=null, $message=null, Throwable $previous=null)
Create a new plugin exception.
elgg_log($message, $level=\Psr\Log\LogLevel::NOTICE)
Log a message.
elgg_get_plugins($status= 'active')
Returns an ordered list of plugins.
if($container instanceof ElggGroup &&$container->guid!=elgg_get_page_owner_guid()) $key
_elgg_config()
Get the Elgg config service.
__construct($plugin, $validate=true)
Load a plugin package from mod/$id or by full path.
elgg_get_version($human_readable=false)
Get the current Elgg version information.
getError()
Returns the last error message.
static sanitize($path, $append_slash=true)
Sanitise file paths ensuring that they begin and end with slashes etc.
_elgg_services()
Get the global service provider.
getID()
Returns the Plugin ID.
elgg_view($view, $vars=[], $viewtype= '')
Return a parsed view.
isValid()
Checks if this is a valid Elgg plugin.
const STATIC_CONFIG_FILENAME
elgg_get_plugin_from_id($plugin_id)
Returns an object with the path $path.