parent
43a7540f46
commit
07ae26789c
@ -0,0 +1,248 @@ |
|||||||
|
<?php |
||||||
|
|
||||||
|
/** |
||||||
|
* Abstract class to extend from when implementing a Pico plugin |
||||||
|
* |
||||||
|
* @see IPicoPlugin |
||||||
|
* |
||||||
|
* @author Daniel Rudolf |
||||||
|
* @link http://picocms.org |
||||||
|
* @license http://opensource.org/licenses/MIT |
||||||
|
* @version 1.0 |
||||||
|
*/ |
||||||
|
abstract class AbstractPicoPlugin implements IPicoPlugin |
||||||
|
{ |
||||||
|
/** |
||||||
|
* Current instance of Pico |
||||||
|
* |
||||||
|
* @var Pico |
||||||
|
* @see IPicoPlugin::__construct() |
||||||
|
* @see IPicoPlugin::getPico() |
||||||
|
*/ |
||||||
|
private $pico; |
||||||
|
|
||||||
|
/** |
||||||
|
* Boolean indicating if this plugin is enabled (true) or disabled (false) |
||||||
|
* |
||||||
|
* @var boolean |
||||||
|
* @see IPicoPlugin::isEnabled() |
||||||
|
* @see IPicoPlugin::setEnabled() |
||||||
|
*/ |
||||||
|
protected $enabled = true; |
||||||
|
|
||||||
|
/** |
||||||
|
* Boolean indicating if this plugin was ever enabled/disabled manually |
||||||
|
* |
||||||
|
* @var boolean |
||||||
|
* @see IPicoPlugin::isStatusChanged() |
||||||
|
*/ |
||||||
|
protected $statusChanged = false; |
||||||
|
|
||||||
|
/** |
||||||
|
* List of plugins this plugin depends on |
||||||
|
* |
||||||
|
* @var array<string> |
||||||
|
* @see IPicoPlugin::getDependencies() |
||||||
|
* @see AbstractPicoPlugin::checkDependencies() |
||||||
|
*/ |
||||||
|
protected $dependsOn = array(); |
||||||
|
|
||||||
|
/** |
||||||
|
* List of plugin which depend on this plugin |
||||||
|
* |
||||||
|
* @var array<object> |
||||||
|
* @see IPicoPlugin::getDependants() |
||||||
|
* @see AbstractPicoPlugin::checkDependants() |
||||||
|
*/ |
||||||
|
private $dependants; |
||||||
|
|
||||||
|
/** |
||||||
|
* @see IPicoPlugin::__construct() |
||||||
|
*/ |
||||||
|
public function __construct(Pico $pico) |
||||||
|
{ |
||||||
|
$this->pico = $pico; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* @see IPicoPlugin::handleEvent() |
||||||
|
*/ |
||||||
|
public function handleEvent($eventName, array $params) |
||||||
|
{ |
||||||
|
// plugins can be enabled/disabled using the config |
||||||
|
if ($eventName === 'onConfigLoaded') { |
||||||
|
$pluginEnabled = $this->getConfig(get_called_class().'.enabled'); |
||||||
|
if ($pluginEnabled !== null) { |
||||||
|
$this->setEnabled($pluginEnabled); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
if ($this->isEnabled() || ($eventName === 'onPluginsLoaded')) { |
||||||
|
if (method_exists($this, $eventName)) { |
||||||
|
call_user_func_array(array($this, $eventName), $params); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* @see IPicoPlugin::setEnabled() |
||||||
|
*/ |
||||||
|
public function setEnabled($enabled, $recursive = true, $auto = false) |
||||||
|
{ |
||||||
|
$this->statusChanged = (!$this->statusChanged) ? !$auto : true; |
||||||
|
$this->enabled = (bool) $enabled; |
||||||
|
|
||||||
|
if ($enabled) { |
||||||
|
$this->checkDependencies($recursive); |
||||||
|
} else { |
||||||
|
$this->checkDependants($recursive); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* @see IPicoPlugin::isEnabled() |
||||||
|
*/ |
||||||
|
public function isEnabled() |
||||||
|
{ |
||||||
|
return $this->enabled; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* @see IPicoPlugin::isStatusChanged() |
||||||
|
*/ |
||||||
|
public function isStatusChanged() |
||||||
|
{ |
||||||
|
return $this->statusChanged; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* @see IPicoPlugin::getPico() |
||||||
|
*/ |
||||||
|
public function getPico() |
||||||
|
{ |
||||||
|
return $this->pico; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Passes all not satisfiable method calls to {@link Pico} |
||||||
|
* |
||||||
|
* @param string $methodName name of the method to call |
||||||
|
* @param array $params parameters to pass |
||||||
|
* @return mixed return value of the called method |
||||||
|
*/ |
||||||
|
public function __call($methodName, array $params) |
||||||
|
{ |
||||||
|
if (method_exists($this->getPico(), $methodName)) { |
||||||
|
return call_user_func_array(array($this->getPico(), $methodName), $params); |
||||||
|
} |
||||||
|
|
||||||
|
throw new BadMethodCallException( |
||||||
|
'Call to undefined method '.get_class($this->getPico()).'::'.$methodName.'() ' |
||||||
|
. 'through '.get_called_class().'::__call()' |
||||||
|
); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Enables all plugins on which this plugin depends |
||||||
|
* |
||||||
|
* @param boolean $recursive enable required plugins automatically |
||||||
|
* @return void |
||||||
|
* @throws RuntimeException thrown when a dependency fails |
||||||
|
*/ |
||||||
|
protected function checkDependencies($recursive) |
||||||
|
{ |
||||||
|
foreach ($this->getDependencies() as $pluginName) { |
||||||
|
try { |
||||||
|
$plugin = $this->getPlugin($pluginName); |
||||||
|
} catch (RuntimeException $e) { |
||||||
|
throw new RuntimeException( |
||||||
|
"Unable to enable plugin '" . get_called_class() . "':" |
||||||
|
. "Required plugin '" . $pluginName . "' not found" |
||||||
|
); |
||||||
|
} |
||||||
|
|
||||||
|
// plugins which don't implement IPicoPlugin are always enabled |
||||||
|
if (is_a($plugin, 'IPicoPlugin') && !$plugin->isEnabled()) { |
||||||
|
if ($recursive) { |
||||||
|
if (!$plugin->isStatusChanged()) { |
||||||
|
$plugin->setEnabled(true, true, true); |
||||||
|
} else { |
||||||
|
throw new RuntimeException( |
||||||
|
"Unable to enable plugin '" . get_called_class() . "':" |
||||||
|
. "Required plugin '" . $pluginName . "' was disabled manually" |
||||||
|
); |
||||||
|
} |
||||||
|
} else { |
||||||
|
throw new RuntimeException( |
||||||
|
"Unable to enable plugin '" . get_called_class() . "':" |
||||||
|
. "Required plugin '" . $pluginName . "' is disabled" |
||||||
|
); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* @see IPicoPlugin::getDependencies() |
||||||
|
*/ |
||||||
|
public function getDependencies() |
||||||
|
{ |
||||||
|
return $this->dependsOn; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Disables all plugins which depend on this plugin |
||||||
|
* |
||||||
|
* @param boolean $recursive disabled dependant plugins automatically |
||||||
|
* @return void |
||||||
|
* @throws RuntimeException thrown when a dependency fails |
||||||
|
*/ |
||||||
|
protected function checkDependants($recursive) |
||||||
|
{ |
||||||
|
$dependants = $this->getDependants(); |
||||||
|
if (!empty($dependants)) { |
||||||
|
if ($recursive) { |
||||||
|
foreach ($this->getDependants() as $pluginName => $plugin) { |
||||||
|
if ($plugin->isEnabled()) { |
||||||
|
if (!$plugin->isStatusChanged()) { |
||||||
|
$plugin->setEnabled(false, true, true); |
||||||
|
} else { |
||||||
|
throw new RuntimeException( |
||||||
|
"Unable to disable plugin '" . get_called_class() . "': " |
||||||
|
+ "Required by manually enabled plugin '" . $pluginName . "'" |
||||||
|
); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} else { |
||||||
|
$dependantsList = 'plugin' . ((count($dependants) > 1) ? 's' : '') . ' '; |
||||||
|
$dependantsList .= "'" + implode("', '", array_keys($dependants)) + "'"; |
||||||
|
throw new RuntimeException( |
||||||
|
"Unable to disable plugin '" . get_called_class() . "': " |
||||||
|
+ "Required by " . $dependantsList |
||||||
|
); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* @see IPicoPlugin::getDependants() |
||||||
|
*/ |
||||||
|
public function getDependants() |
||||||
|
{ |
||||||
|
if ($this->dependants === null) { |
||||||
|
$this->dependants = array(); |
||||||
|
foreach ($this->getPlugins() as $pluginName => $plugin) { |
||||||
|
// only plugins which implement IPicoPlugin support dependencies |
||||||
|
if (is_a($plugin, 'IPicoPlugin')) { |
||||||
|
$dependencies = $plugin->getDependencies(); |
||||||
|
if (in_array(get_called_class(), $dependencies)) { |
||||||
|
$this->dependants[$pluginName] = $plugin; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
return $this->dependants; |
||||||
|
} |
||||||
|
} |
Loading…
Reference in new issue