aboutsummaryrefslogtreecommitdiff
path: root/engine/classes/ElggPlugin.php
diff options
context:
space:
mode:
Diffstat (limited to 'engine/classes/ElggPlugin.php')
-rw-r--r--engine/classes/ElggPlugin.php312
1 files changed, 180 insertions, 132 deletions
diff --git a/engine/classes/ElggPlugin.php b/engine/classes/ElggPlugin.php
index 18d97d23a..545b9a53c 100644
--- a/engine/classes/ElggPlugin.php
+++ b/engine/classes/ElggPlugin.php
@@ -9,11 +9,12 @@
* @subpackage Plugins.Settings
*/
class ElggPlugin extends ElggObject {
- public $package;
- public $manifest;
+ private $package;
+ private $manifest;
private $path;
private $pluginID;
+ private $errorMsg = '';
/**
* Set subtype to 'plugin'
@@ -29,15 +30,15 @@ class ElggPlugin extends ElggObject {
$this->access_id = ACCESS_PUBLIC;
}
-
/**
* Loads the plugin by GUID or path.
*
* @warning Unlike other ElggEntity objects, you cannot null instantiate
* ElggPlugin. You must point it to an actual plugin GUID or location.
*
- * @param mixed $plugin The GUID of the ElggPlugin object or the path of
- * the plugin to load.
+ * @param mixed $plugin The GUID of the ElggPlugin object or the path of the plugin to load.
+ *
+ * @throws PluginException
*/
public function __construct($plugin) {
if (!$plugin) {
@@ -77,19 +78,9 @@ class ElggPlugin extends ElggObject {
parent::__construct($existing_guid);
}
- // We have to let the entity load so we can manipulate it with the API.
- // If the path is wrong or would cause an exception, catch it,
- // disable the plugin, and emit an error.
- try {
- $this->package = new ElggPluginPackage($this->path, false);
- $this->manifest = $this->package->getManifest();
- } catch (Exception $e) {
- // we always have to allow the entity to load.
- elgg_log("Failed to load $this->guid as a plugin. " . $e->getMessage(), 'WARNING');
- }
+ _elgg_cache_plugin_by_id($this);
}
-
/**
* Save the plugin object. Make sure required values exist.
*
@@ -128,6 +119,21 @@ class ElggPlugin extends ElggObject {
}
/**
+ * Returns the manifest's name if available, otherwise the ID.
+ *
+ * @return string
+ * @since 1.8.1
+ */
+ public function getFriendlyName() {
+ $manifest = $this->getManifest();
+ if ($manifest) {
+ return $manifest->getName();
+ }
+
+ return $this->getID();
+ }
+
+ /**
* Returns the plugin's full path with trailing slash.
*
* @return string
@@ -136,17 +142,33 @@ class ElggPlugin extends ElggObject {
return sanitise_filepath($this->path);
}
-
/**
* Sets the location of this plugin.
*
- * @param path $id The path to the plugin's dir.
+ * @param string $id The path to the plugin's dir.
* @return bool
*/
public function setID($id) {
return $this->attributes['title'] = $id;
}
+ /**
+ * Returns an array of available markdown files for this plugin
+ *
+ * @return array
+ */
+ public function getAvailableTextFiles() {
+ $filenames = $this->getPackage()->getTextFilenames();
+
+ $files = array();
+ foreach ($filenames as $filename) {
+ if ($this->canReadFile($filename)) {
+ $files[$filename] = "$this->path/$filename";
+ }
+ }
+
+ return $files;
+ }
// Load Priority
@@ -160,7 +182,6 @@ class ElggPlugin extends ElggObject {
return $this->$name;
}
-
/**
* Sets the priority of the plugin
*
@@ -177,8 +198,9 @@ class ElggPlugin extends ElggObject {
$db_prefix = get_config('dbprefix');
$name = elgg_namespace_plugin_private_setting('internal', 'priority');
- // if no priority assume a priority of 0
+ // if no priority assume a priority of 1
$old_priority = (int) $this->getPriority();
+ $old_priority = (!$old_priority) ? 1 : $old_priority;
$max_priority = elgg_get_max_plugin_priority();
// can't use switch here because it's not strict and
@@ -194,15 +216,11 @@ class ElggPlugin extends ElggObject {
}
// should be a number by now
- if ($priority) {
+ if ($priority > 0) {
if (!is_numeric($priority)) {
return false;
}
- if ($priority == $old_priority) {
- return false;
- }
-
// there's nothing above the max.
if ($priority > $max_priority) {
$priority = $max_priority;
@@ -234,7 +252,6 @@ class ElggPlugin extends ElggObject {
// set this priority
if ($this->set($name, $priority)) {
- //return elgg_plugins_reindex_priorities();
return true;
} else {
return false;
@@ -250,8 +267,6 @@ class ElggPlugin extends ElggObject {
/**
* Returns a plugin setting
*
- * @todo These need to be namespaced
- *
* @param string $name The setting name
* @return mixed
*/
@@ -284,27 +299,21 @@ class ElggPlugin extends ElggObject {
$private_settings = get_data($q);
- if ($private_settings) {
- $return = array();
+ $return = array();
+ if ($private_settings) {
foreach ($private_settings as $setting) {
- $name = substr($setting->name, $ps_prefix_len);
- $value = $setting->value;
-
- $return[$name] = $value;
+ $return[$setting->name] = $setting->value;
}
-
- return $return;
}
- return false;
+ return $return;
}
/**
* Set a plugin setting for the plugin
*
* @todo This will only work once the plugin has a GUID.
- * @todo These need to be namespaced.
*
* @param string $name The name to set
* @param string $value The value to set
@@ -315,18 +324,10 @@ class ElggPlugin extends ElggObject {
if (!$this->guid) {
return false;
}
- // Hook to validate setting
- $value = elgg_trigger_plugin_hook('plugin:setting', 'plugin', array(
- 'plugin' => $this->pluginID,
- 'plugin_object' => $this,
- 'name' => $name,
- 'value' => $value
- ), $value);
return $this->set($name, $value);
}
-
/**
* Removes a plugin setting name and value.
*
@@ -338,7 +339,6 @@ class ElggPlugin extends ElggObject {
return remove_private_setting($this->guid, $name);
}
-
/**
* Removes all settings for this plugin.
*
@@ -348,11 +348,14 @@ class ElggPlugin extends ElggObject {
*/
public function unsetAllSettings() {
$db_prefix = get_config('dbprefix');
- $ps_prefix = elgg_namespace_plugin_private_setting('setting', '');
+
+ $us_prefix = elgg_namespace_plugin_private_setting('user_setting', '', $this->getID());
+ $is_prefix = elgg_namespace_plugin_private_setting('internal', '', $this->getID());
$q = "DELETE FROM {$db_prefix}private_settings
WHERE entity_guid = $this->guid
- AND name NOT LIKE '$ps_prefix%'";
+ AND name NOT LIKE '$us_prefix%'
+ AND name NOT LIKE '$is_prefix%'";
return delete_data($q);
}
@@ -418,20 +421,18 @@ class ElggPlugin extends ElggObject {
$private_settings = get_data($q);
- if ($private_settings) {
- $return = array();
+ $return = array();
+ if ($private_settings) {
foreach ($private_settings as $setting) {
$name = substr($setting->name, $ps_prefix_len);
$value = $setting->value;
$return[$name] = $value;
}
-
- return $return;
}
- return false;
+ return $return;
}
/**
@@ -457,10 +458,11 @@ class ElggPlugin extends ElggObject {
}
// Hook to validate setting
- // note this doesn't pass the namespaced name!
- $value = elgg_trigger_plugin_hook('plugin:usersetting', 'user', array(
+ // note: this doesn't pass the namespaced name
+ $value = elgg_trigger_plugin_hook('usersetting', 'plugin', array(
'user' => $user,
- 'plugin' => $this->getID(),
+ 'plugin' => $this,
+ 'plugin_id' => $this->getID(),
'name' => $name,
'value' => $value
), $value);
@@ -498,7 +500,6 @@ class ElggPlugin extends ElggObject {
return remove_private_setting($user->guid, $name);
}
-
/**
* Removes all User Settings for this plugin
*
@@ -519,7 +520,6 @@ class ElggPlugin extends ElggObject {
return delete_data($q);
}
-
/**
* Removes this plugin's user settings for all users.
*
@@ -545,27 +545,29 @@ class ElggPlugin extends ElggObject {
* Returns if the plugin is complete, meaning has all required files
* and Elgg can read them and they make sense.
*
- * @todo bad name? This could be confused with isValid() from ElggPackage.
+ * @todo bad name? This could be confused with isValid() from ElggPluginPackage.
*
* @return bool
*/
public function isValid() {
if (!$this->getID()) {
+ $this->errorMsg = elgg_echo('ElggPlugin:NoId', array($this->guid));
return false;
}
- if (!$this->package instanceof ElggPluginPackage) {
+ if (!$this->getPackage() instanceof ElggPluginPackage) {
+ $this->errorMsg = elgg_echo('ElggPlugin:NoPluginPackagePackage', array($this->getID(), $this->guid));
return false;
}
- if (!$this->package->isValid()) {
+ if (!$this->getPackage()->isValid()) {
+ $this->errorMsg = $this->getPackage()->getError();
return false;
}
return true;
}
-
/**
* Is this plugin active?
*
@@ -590,17 +592,23 @@ class ElggPlugin extends ElggObject {
return check_entity_relationship($this->guid, 'active_plugin', $site->guid);
}
-
/**
* Checks if this plugin can be activated on the current
* Elgg installation.
*
+ * @todo remove $site_guid param or implement it
+ *
* @param mixed $site_guid Optional site guid
* @return bool
*/
public function canActivate($site_guid = null) {
- if ($this->package) {
- return $this->package->isValid() && $this->package->checkDependencies();
+ if ($this->getPackage()) {
+ $result = $this->getPackage()->isValid() && $this->getPackage()->checkDependencies();
+ if (!$result) {
+ $this->errorMsg = $this->getPackage()->getError();
+ }
+
+ return $result;
}
return false;
@@ -638,24 +646,14 @@ class ElggPlugin extends ElggObject {
// if there are any on_enable functions, start the plugin now and run them
// Note: this will not run re-run the init hooks!
- $functions = $this->manifest->getOnActivate();
- if ($return && $functions) {
- $flags = ELGG_PLUGIN_INCLUDE_START | ELGG_PLUGIN_REGISTER_CLASSES
- | ELGG_PLUGIN_REGISTER_LANGUAGES | ELGG_PLUGIN_REGISTER_VIEWS;
-
- $this->start($flags);
- foreach ($functions as $function) {
- if (!is_callable($function)) {
- $return = false;
- } else {
- $result = call_user_func($function);
- // allow null to mean "I don't care" like other subsystems
- $return = ($result === false) ? false: true;
- }
-
- if ($return === false) {
- break;
- }
+ if ($return) {
+ if ($this->canReadFile('activate.php')) {
+ $flags = ELGG_PLUGIN_INCLUDE_START | ELGG_PLUGIN_REGISTER_CLASSES |
+ ELGG_PLUGIN_REGISTER_LANGUAGES | ELGG_PLUGIN_REGISTER_VIEWS;
+
+ $this->start($flags);
+
+ $return = $this->includeFile('activate.php');
}
}
@@ -669,7 +667,6 @@ class ElggPlugin extends ElggObject {
return false;
}
-
/**
* Deactivates the plugin.
*
@@ -689,27 +686,10 @@ class ElggPlugin extends ElggObject {
$return = elgg_trigger_event('deactivate', 'plugin', $params);
- // run any deactivate functions
- // check for the manifest in case we haven't fully loaded the plugin.
- if ($this->manifest) {
- $functions = $this->manifest->getOnDeactivate();
- } else {
- $functions = array();
- }
-
- if ($return && $functions) {
- foreach ($functions as $function) {
- if (!is_callable($function)) {
- $return = false;
- } else {
- $result = call_user_func($function);
- // allow null to mean "I don't care" like other subsystems
- $return = ($result === false) ? false : true;
- }
-
- if ($return === false) {
- break;
- }
+ // run any deactivate code
+ if ($return) {
+ if ($this->canReadFile('deactivate.php')) {
+ $return = $this->includeFile('deactivate.php');
}
}
@@ -720,7 +700,6 @@ class ElggPlugin extends ElggObject {
}
}
-
/**
* Start the plugin.
*
@@ -729,13 +708,18 @@ class ElggPlugin extends ElggObject {
* @throws PluginException
*/
public function start($flags) {
- if (!$this->canActivate()) {
- return false;
- }
+ //if (!$this->canActivate()) {
+ // return false;
+ //}
+ // include classes
+ if ($flags & ELGG_PLUGIN_REGISTER_CLASSES) {
+ $this->registerClasses();
+ }
+
// include start file
if ($flags & ELGG_PLUGIN_INCLUDE_START) {
- $this->includeStart();
+ $this->includeFile('start.php');
}
// include views
@@ -748,11 +732,6 @@ class ElggPlugin extends ElggObject {
$this->registerLanguages();
}
- // include classes
- if ($flags & ELGG_PLUGIN_REGISTER_CLASSES) {
- $this->registerClasses();
- }
-
return true;
}
@@ -760,24 +739,39 @@ class ElggPlugin extends ElggObject {
// start helpers
/**
- * Includes the plugin's start file
+ * Includes one of the plugins files
+ *
+ * @param string $filename The name of the file
*
* @throws PluginException
- * @return true
+ * @return mixed The return value of the included file (or 1 if there is none)
*/
- protected function includeStart() {
+ protected function includeFile($filename) {
// This needs to be here to be backwards compatible for 1.0-1.7.
// They expect the global config object to be available in start.php.
- global $CONFIG;
+ if ($filename == 'start.php') {
+ global $CONFIG;
+ }
- $start = "$this->path/start.php";
- if (!include($start)) {
- $msg = elgg_echo('ElggPlugin:Exception:CannotIncludeStart',
- array($this->getID(), $this->guid, $this->path));
+ $filepath = "$this->path/$filename";
+
+ if (!$this->canReadFile($filename)) {
+ $msg = elgg_echo('ElggPlugin:Exception:CannotIncludeFile',
+ array($filename, $this->getID(), $this->guid, $this->path));
throw new PluginException($msg);
}
- return true;
+ return include $filepath;
+ }
+
+ /**
+ * Checks whether a plugin file with the given name exists
+ *
+ * @param string $filename The name of the file
+ * @return bool
+ */
+ protected function canReadFile($filename) {
+ return is_readable($this->path . '/' . $filename);
}
/**
@@ -857,12 +851,7 @@ class ElggPlugin extends ElggObject {
return true;
}
- // but need to have working ones.
- if (!elgg_register_classes($classes_path)) {
- $msg = elgg_echo('ElggPlugin:Exception:CannotRegisterClasses',
- array($this->getID(), $this->guid, $classes_path));
- throw new PluginException($msg);
- }
+ elgg_register_classes($classes_path);
return true;
}
@@ -904,7 +893,9 @@ class ElggPlugin extends ElggObject {
}
/**
- * Save a value to private settings.
+ * Save a value as private setting or attribute.
+ *
+ * Attributes include title and description.
*
* @param string $name Name
* @param mixed $value Value
@@ -922,6 +913,14 @@ class ElggPlugin extends ElggObject {
return true;
} else {
+ // Hook to validate setting
+ $value = elgg_trigger_plugin_hook('setting', 'plugin', array(
+ 'plugin_id' => $this->pluginID,
+ 'plugin' => $this,
+ 'name' => $name,
+ 'value' => $value
+ ), $value);
+
return $this->setPrivateSetting($name, $value);
}
}
@@ -955,4 +954,53 @@ class ElggPlugin extends ElggObject {
return remove_entity_relationship($this->guid, 'active_plugin', $site->guid);
}
}
+
+ /**
+ * Returns the last error message registered.
+ *
+ * @return string|null
+ */
+ public function getError() {
+ return $this->errorMsg;
+ }
+
+ /**
+ * Returns this plugin's ElggPluginManifest object
+ *
+ * @return ElggPluginManifest
+ */
+ public function getManifest() {
+ if ($this->manifest instanceof ElggPluginManifest) {
+ return $this->manifest;
+ }
+
+ try {
+ $this->manifest = $this->getPackage()->getManifest();
+ } catch (Exception $e) {
+ elgg_log("Failed to load manifest for plugin $this->guid. " . $e->getMessage(), 'WARNING');
+ $this->errorMsg = $e->getmessage();
+ }
+
+ return $this->manifest;
+ }
+
+ /**
+ * Returns this plugin's ElggPluginPackage object
+ *
+ * @return ElggPluginPackage
+ */
+ public function getPackage() {
+ if ($this->package instanceof ElggPluginPackage) {
+ return $this->package;
+ }
+
+ try {
+ $this->package = new ElggPluginPackage($this->path, false);
+ } catch (Exception $e) {
+ elgg_log("Failed to load package for $this->guid. " . $e->getMessage(), 'WARNING');
+ $this->errorMsg = $e->getmessage();
+ }
+
+ return $this->package;
+ }
}