Newer
Older
mattpiwik
a validé
<?php
/**
* Piwik - free/libre analytics platform
mattpiwik
a validé
* @link http://piwik.org
mattpiwik
a validé
*/
mattab
a validé
namespace Piwik\Plugin;
mattab
a validé
use Piwik\Application\Kernel\PluginList;
use Piwik\Cache;
use Piwik\Columns\Dimension;
Matthieu Aubry
a validé
use Piwik\Config as PiwikConfig;
use Piwik\Container\StaticContainer;
Thomas Steur
a validé
use Piwik\Notification;
Matthieu Napoli
a validé
use Piwik\Piwik;
Matthieu Aubry
a validé
use Piwik\Plugin\Dimension\ActionDimension;
use Piwik\Plugin\Dimension\ConversionDimension;
use Piwik\Plugin\Dimension\VisitDimension;
use Piwik\Settings\Storage as SettingsStorage;
use Piwik\Theme;
use Piwik\Translation\Translator;
mattpiwik
a validé
require_once PIWIK_INCLUDE_PATH . '/core/EventDispatcher.php';
mattpiwik
a validé
/**
diosmosis
a validé
* The singleton that manages plugin loading/unloading and installation/uninstallation.
mattpiwik
a validé
*/
mattpiwik
a validé
{
/**
* @return self
*/
public static function getInstance()
{
return StaticContainer::get('Piwik\Plugin\Manager');
}
protected $pluginsToLoad = array();
protected $doLoadPlugins = true;
Thomas Steur
a validé
private $pluginsLoadedAndActivated;
/**
* @var Plugin[]
*/
protected $loadedPlugins = array();
/**
* Default theme used in Piwik.
*/
const DEFAULT_THEME = "Morpheus";
protected $doLoadAlwaysActivatedPlugins = true;
mattab
a validé
// These are always activated and cannot be deactivated
protected $pluginToAlwaysActivate = array(
'CoreHome',
'Diagnostics',
'CoreUpdater',
'CoreAdminHome',
'CorePluginsAdmin',
'Installation',
'SitesManager',
'UsersManager',
'API',
'Proxy',
'LanguagesManager',
self::DEFAULT_THEME,
/**
* @var PluginList
*/
private $pluginList;
public function __construct(PluginList $pluginList)
{
$this->pluginList = $pluginList;
}
mattab
a validé
/**
* Loads plugin that are enabled
*/
public function loadActivatedPlugins()
{
$pluginsToLoad = $this->getActivatedPluginsFromConfig();
mattab
a validé
$this->loadPlugins($pluginsToLoad);
}
/**
* Called during Tracker
*/
public function loadCorePluginsDuringTracker()
{
$pluginsToLoad = $this->pluginList->getActivatedPlugins();
$pluginsToLoad = array_diff($pluginsToLoad, $this->getTrackerPluginsNotToLoad());
mattab
a validé
$this->loadPlugins($pluginsToLoad);
}
/**
* @return array names of plugins that have been loaded
*/
public function loadTrackerPlugins()
{
$cacheId = 'PluginsTracker';
$cache = Cache::getEagerCache();
if ($cache->contains($cacheId)) {
$pluginsTracker = $cache->fetch($cacheId);
} else {
$this->unloadPlugins();
$this->loadActivatedPlugins();
$pluginsTracker = array();
foreach ($this->loadedPlugins as $pluginName => $plugin) {
if ($this->isTrackerPlugin($plugin)) {
$pluginsTracker[] = $pluginName;
}
}
if (!empty($pluginsTracker)) {
$cache->save($cacheId, $pluginsTracker);
}
}
$pluginsTracker = array_diff($pluginsTracker, $this->getTrackerPluginsNotToLoad());
$this->doNotLoadAlwaysActivatedPlugins();
$this->loadPlugins($pluginsTracker);
// we could simply unload all plugins first before loading plugins but this way it is much faster
// since we won't have to create each plugin again and we won't have to parse each plugin metadata file
// again etc
$this->makeSureOnlyActivatedPluginsAreLoaded();
return $pluginsTracker;
}
/**
* Do not load the specified plugins (used during testing, to disable Provider plugin)
* @param array $plugins
*/
public function setTrackerPluginsNotToLoad($plugins)
{
$this->trackerPluginsNotToLoad = $plugins;
}
/**
* Get list of plugins to not load
*
* @return array
*/
public function getTrackerPluginsNotToLoad()
{
return $this->trackerPluginsNotToLoad;
}
// If a plugin hooks onto at least an event starting with "Tracker.", we load the plugin during tracker
const TRACKER_EVENT_PREFIX = 'Tracker.';
/**
* @param $pluginName
* @return bool
*/
public function isPluginOfficialAndNotBundledWithCore($pluginName)
{
static $gitModules;
Thomas Steur
a validé
if (empty($gitModules)) {
$gitModules = file_get_contents(PIWIK_INCLUDE_PATH . '/.gitmodules');
}
// All submodules are officially maintained plugins
$isSubmodule = false !== strpos($gitModules, "plugins/" . $pluginName . "\n");
}
/**
* Update Plugins config
*
mattab
a validé
* @param array $pluginsToLoad Plugins
private function updatePluginsConfig($pluginsToLoad)
diosmosis
a validé
$pluginsToLoad = $this->pluginList->sortPlugins($pluginsToLoad);
$section = PiwikConfig::getInstance()->Plugins;
$section['Plugins'] = $pluginsToLoad;
PiwikConfig::getInstance()->Plugins = $section;
}
/**
* Update PluginsInstalled config
*
* @param array $plugins Plugins
*/
private function updatePluginsInstalledConfig($plugins)
{
$section = PiwikConfig::getInstance()->PluginsInstalled;
$section['PluginsInstalled'] = $plugins;
PiwikConfig::getInstance()->PluginsInstalled = $section;
public function clearPluginsInstalledConfig()
{
$this->updatePluginsInstalledConfig(array());
mattab
a validé
PiwikConfig::getInstance()->forceSave();
}
/**
* Returns true if plugin is always activated
*
* @param string $name Name of plugin
* @return bool
*/
private function isPluginAlwaysActivated($name)
{
return in_array($name, $this->pluginToAlwaysActivate);
}
/**
* Returns true if the plugin can be uninstalled. Any non-core plugin can be uninstalled.
*
* @param $name
* @return bool
*/
private function isPluginUninstallable($name)
{
return !$this->isPluginBundledWithCore($name);
}
* Returns `true` if a plugin has been activated.
diosmosis
a validé
* @param string $name Name of plugin, eg, `'Actions'`.
* @return bool
diosmosis
a validé
* @api
*/
public function isPluginActivated($name)
{
return in_array($name, $this->pluginsToLoad)
|| ($this->doLoadAlwaysActivatedPlugins && $this->isPluginAlwaysActivated($name));
/**
* Checks whether the given plugin is activated, if not triggers an exception.
*
* @param string $pluginName
* @throws PluginDeactivatedException
*/
public function checkIsPluginActivated($pluginName)
{
if (!$this->isPluginActivated($pluginName)) {
throw new PluginDeactivatedException($pluginName);
}
}
* Returns `true` if plugin is loaded (in memory).
diosmosis
a validé
* @param string $name Name of plugin, eg, `'Acions'`.
* @return bool
diosmosis
a validé
* @api
*/
public function isPluginLoaded($name)
{
return isset($this->loadedPlugins[$name]);
}
/**
* Reads the directories inside the plugins/ directory and returns their names in an array
*
* @return array
*/
public function readPluginsDirectory()
{
Benaka Moorthi
a validé
$pluginsName = _glob(self::getPluginsDirectory() . '*', GLOB_ONLYDIR);
$result = array();
if ($pluginsName != false) {
foreach ($pluginsName as $path) {
Benaka Moorthi
a validé
if (self::pluginStructureLooksValid($path)) {
$result[] = basename($path);
}
}
}
return $result;
}
Benaka Moorthi
a validé
public static function getPluginsDirectory()
/**
* Deactivate plugin
*
* @param string $pluginName Name of plugin
*/
public function deactivatePlugin($pluginName)
{
$this->clearCache($pluginName);
// execute deactivate() to let the plugin do cleanups
$this->executePluginDeactivate($pluginName);
$this->unloadPluginFromMemory($pluginName);
$this->removePluginFromConfig($pluginName);
Matthieu Napoli
a validé
/**
* Event triggered after a plugin has been deactivated.
*
* @param string $pluginName The plugin that has been deactivated.
*/
Piwik::postEvent('PluginManager.pluginDeactivated', array($pluginName));
}
Thomas Steur
a validé
/**
* Tries to find the given components such as a Menu or Tasks implemented by plugins.
* This method won't cache the found components. If you need to find the same component multiple times you might
* want to cache the result to save a tiny bit of time.
*
* @param string $componentName The name of the component you want to look for. In case you request a
* component named 'Menu' it'll look for a file named 'Menu.php' within the
* root of all plugin folders that implement a class named
* Piwik\Plugin\$PluginName\Menu.
* @param string $expectedSubclass If not empty, a check will be performed whether a found file extends the
* given subclass. If the requested file exists but does not extend this class
* a warning will be shown to advice a developer to extend this certain class.
*
* @return \stdClass[]
*/
public function findComponents($componentName, $expectedSubclass)
{
Thomas Steur
a validé
$plugins = $this->getPluginsLoadedAndActivated();
Thomas Steur
a validé
$components = array();
foreach ($plugins as $plugin) {
Thomas Steur
a validé
$component = $plugin->findComponent($componentName, $expectedSubclass);
if (!empty($component)) {
$components[] = $component;
}
}
return $components;
}
Thomas Steur
a validé
public function findMultipleComponents($directoryWithinPlugin, $expectedSubclass)
{
Thomas Steur
a validé
$plugins = $this->getPluginsLoadedAndActivated();
Thomas Steur
a validé
$found = array();
foreach ($plugins as $plugin) {
$components = $plugin->findMultipleComponents($directoryWithinPlugin, $expectedSubclass);
if (!empty($components)) {
$found = array_merge($found, $components);
}
}
return $found;
}
/**
* Uninstalls a Plugin (deletes plugin files from the disk)
* Only deactivated plugins can be uninstalled
*
* @param $pluginName
*/
public function uninstallPlugin($pluginName)
{
mattab
a validé
if ($this->isPluginLoaded($pluginName)) {
throw new \Exception("To uninstall the plugin $pluginName, first disable it in Piwik > Settings > Plugins");
}
$this->loadAllPluginsAndGetTheirInfo();
Thomas Steur
a validé
Thomas Steur
a validé
SettingsStorage\Backend\PluginSettingsTable::removeAllSettingsForPlugin($pluginName);
SettingsStorage\Backend\MeasurableSettingsTable::removeAllSettingsForPlugin($pluginName);
Thomas Steur
a validé
$this->executePluginDeactivate($pluginName);
$this->executePluginUninstall($pluginName);
Thomas Steur
a validé
$this->removePluginFromPluginsInstalledConfig($pluginName);
$this->unloadPluginFromMemory($pluginName);
$this->removePluginFromConfig($pluginName);
$this->removeInstalledVersionFromOptionTable($pluginName);
Thomas Steur
a validé
self::deletePluginFromFilesystem($pluginName);
if ($this->isPluginInFilesystem($pluginName)) {
return false;
}
/**
* Event triggered after a plugin has been uninstalled.
*
* @param string $pluginName The plugin that has been uninstalled.
*/
Piwik::postEvent('PluginManager.pluginUninstalled', array($pluginName));
return true;
}
/**
* @param string $pluginName
*/
private function clearCache($pluginName)
{
$this->resetTransientCache();
Filesystem::deleteAllCacheOnUpdate($pluginName);
}
public static function deletePluginFromFilesystem($plugin)
{
Filesystem::unlinkRecursive(PIWIK_INCLUDE_PATH . '/plugins/' . $plugin, $deleteRootToo = true);
}
/**
* Install loaded plugins
* @throws
* @return array Error messages of plugin install fails
*/
public function installLoadedPlugins()
{
Log::debug("Loaded plugins: " . implode(", ", array_keys($this->getLoadedPlugins())));
foreach ($this->getLoadedPlugins() as $plugin) {
$this->installPluginIfNecessary($plugin);
}
}
/**
* Activate the specified plugin and install (if needed)
*
* @param string $pluginName Name of plugin
*/
public function activatePlugin($pluginName)
{
$plugins = $this->pluginList->getActivatedPlugins();
if (in_array($pluginName, $plugins)) {
Matthieu Aubry
a validé
// plugin is already activated
return;
if (!$this->isPluginInFilesystem($pluginName)) {
throw new \Exception("Plugin '$pluginName' cannot be found in the filesystem in plugins/ directory.");
$this->deactivateThemeIfTheme($pluginName);
$plugin = $this->loadPlugin($pluginName);
if ($plugin === null) {
throw new \Exception("The plugin '$pluginName' was found in the filesystem, but could not be loaded.'");
}
$this->installPluginIfNecessary($plugin);
$plugin->activate();
mattab
a validé
EventDispatcher::getInstance()->postPendingEventsTo($plugin);
$this->pluginsToLoad[] = $pluginName;
mattab
a validé
$this->updatePluginsConfig($this->pluginsToLoad);
PiwikConfig::getInstance()->forceSave();
Matthieu Napoli
a validé
/**
* Event triggered after a plugin has been activated.
*
* @param string $pluginName The plugin that has been activated.
*/
Piwik::postEvent('PluginManager.pluginActivated', array($pluginName));
public function isPluginInFilesystem($pluginName)
{
$existingPlugins = $this->readPluginsDirectory();
$isPluginInFilesystem = array_search($pluginName, $existingPlugins) !== false;
return $this->isValidPluginName($pluginName)
}
* Returns the currently enabled theme.
Thomas Steur
a validé
* If no theme is enabled, the **Morpheus** plugin is returned (this is the base and default theme).
* @return Plugin
diosmosis
a validé
* @api
public function getThemeEnabled()
$theme = false;
/* @var $plugin Plugin */
if ($plugin->isTheme()
&& $this->isPluginActivated($plugin->getPluginName())
) {
if ($plugin->getPluginName() != self::DEFAULT_THEME) {
return $plugin; // enabled theme (not default)
}
$theme = $plugin; // default theme
/**
* @param string $themeName
* @throws \Exception
* @return Theme
*/
public function getTheme($themeName)
{
$plugins = $this->getLoadedPlugins();
foreach ($plugins as $plugin) {
if ($plugin->isTheme() && $plugin->getPluginName() == $themeName) {
throw new \Exception('Theme not found : ' . $themeName);
}
public function getNumberOfActivatedPluginsExcludingAlwaysActivated()
{
$counter = 0;
$pluginNames = $this->getLoadedPluginsName();
foreach ($pluginNames as $pluginName) {
if ($this->isPluginActivated($pluginName)
&& !$this->isPluginAlwaysActivated($pluginName)) {
$counter++;
}
}
return $counter;
}
/**
diosmosis
a validé
* Returns info regarding all plugins. Loads plugins that can be loaded.
* @return array An array that maps plugin names with arrays of plugin information. Plugin
* information consists of the following entries:
diosmosis
a validé
* - **activated**: Whether the plugin is activated.
* - **alwaysActivated**: Whether the plugin should always be activated,
* or not.
* - **uninstallable**: Whether the plugin is uninstallable or not.
* - **invalid**: If the plugin is invalid, this property will be set to true.
* If the plugin is not invalid, this property will not exist.
* - **info**: If the plugin was loaded, will hold the plugin information.
* See {@link Piwik\Plugin::getInformation()}.
diosmosis
a validé
* @api
public function loadAllPluginsAndGetTheirInfo()
/** @var Translator $translator */
$translator = StaticContainer::get('Piwik\Translation\Translator');
$plugins = array();
$listPlugins = array_merge(
$this->readPluginsDirectory(),
$this->pluginList->getActivatedPlugins()
);
$listPlugins = array_unique($listPlugins);
foreach ($listPlugins as $pluginName) {
// Hide plugins that are never going to be used
Thomas Steur
a validé
if ($this->isPluginBogus($pluginName)) {
continue;
}
// If the plugin is not core and looks bogus, do not load
if ($this->isPluginThirdPartyAndBogus($pluginName)) {
$info = array(
'invalid' => true,
'activated' => false,
'alwaysActivated' => false,
'uninstallable' => true,
);
} else {
$translator->addDirectory(self::getPluginsDirectory() . $pluginName . '/lang');
$this->loadPlugin($pluginName);
$info = array(
'activated' => $this->isPluginActivated($pluginName),
'alwaysActivated' => $this->isPluginAlwaysActivated($pluginName),
'uninstallable' => $this->isPluginUninstallable($pluginName),
);
}
$plugins[$pluginName] = $info;
}
$loadedPlugins = $this->getLoadedPlugins();
foreach ($loadedPlugins as $oPlugin) {
$pluginName = $oPlugin->getPluginName();
$info = array(
'info' => $oPlugin->getInformation(),
'activated' => $this->isPluginActivated($pluginName),
'alwaysActivated' => $this->isPluginAlwaysActivated($pluginName),
Matthieu Aubry
a validé
'missingRequirements' => $oPlugin->getMissingDependenciesAsString(),
'uninstallable' => $this->isPluginUninstallable($pluginName),
);
$plugins[$pluginName] = $info;
Thomas Steur
a validé
return $plugins;
}
protected static function isManifestFileFound($path)
{
return file_exists($path . "/" . MetadataLoader::PLUGIN_JSON_FILENAME);
}
diosmosis
a validé
/**
* Returns `true` if the plugin is bundled with core or `false` if it is third party.
*
diosmosis
a validé
* @param string $name The name of the plugin, eg, `'Actions'`.
* @return bool
*/
public function isPluginBundledWithCore($name)
return $this->isPluginEnabledByDefault($name)
|| in_array($name, $this->pluginList->getCorePluginsDisabledByDefault())
}
/**
* @param $pluginName
* @return bool
* @ignore
*/
public function isPluginThirdPartyAndBogus($pluginName)
Thomas Steur
a validé
if ($this->isPluginBundledWithCore($pluginName)) {
Thomas Steur
a validé
if ($this->isPluginBogus($pluginName)) {
Thomas Steur
a validé
if (!$this->isManifestFileFound($path)) {
}
Thomas Steur
a validé
* Load AND activates the specified plugins. It will also overwrite all previously loaded plugins, so it acts
* @param array $pluginsToLoad Array of plugins to load.
*/
public function loadPlugins(array $pluginsToLoad)
{
$this->resetTransientCache();
$this->pluginsToLoad = $this->makePluginsToLoad($pluginsToLoad);
$this->reloadActivatedPlugins();
}
/**
*/
public function doNotLoadPlugins()
{
$this->doLoadPlugins = false;
}
/**
* Disable loading of "always activated" plugins.
*/
public function doNotLoadAlwaysActivatedPlugins()
{
$this->doLoadAlwaysActivatedPlugins = false;
}
/**
* Execute postLoad() hook for loaded plugins
*/
public function postLoadPlugins()
{
$plugins = $this->getLoadedPlugins();
foreach ($plugins as $plugin) {
$plugin->postLoad();
}
}
/**
mattab
a validé
* Returns an array containing the plugins class names (eg. 'UserCountry' and NOT 'UserCountry')
*
* @return array
*/
public function getLoadedPluginsName()
{
mattab
a validé
return array_keys($this->getLoadedPlugins());
}
/**
diosmosis
a validé
* Returns an array mapping loaded plugin names with their plugin objects, eg,
*
diosmosis
a validé
* array(
* 'UserCountry' => Plugin $pluginObject,
* 'UserLanguage' => Plugin $pluginObject,
diosmosis
a validé
* );
* @return Plugin[]
*/
public function getLoadedPlugins()
{
return $this->loadedPlugins;
}
/**
* @param string $piwikVersion
* @return Plugin[]
*/
public function getIncompatiblePlugins($piwikVersion)
{
$plugins = $this->getLoadedPlugins();
$incompatible = array();
foreach ($plugins as $plugin) {
if ($plugin->hasMissingDependencies($piwikVersion)) {
$incompatible[] = $plugin;
}
}
return $incompatible;
}
/**
* Returns an array of plugins that are currently loaded and activated,
* mapping loaded plugin names with their plugin objects, eg,
*
* array(
* 'UserCountry' => Plugin $pluginObject,
* 'UserLanguage' => Plugin $pluginObject,
* );
*
* @return Plugin[]
*/
public function getPluginsLoadedAndActivated()
{
if (is_null($this->pluginsLoadedAndActivated)) {
$enabled = $this->getActivatedPlugins();
if (empty($enabled)) {
return array();
}
$plugins = $this->getLoadedPlugins();
$enabled = array_combine($enabled, $enabled);
$plugins = array_intersect_key($plugins, $enabled);
$this->pluginsLoadedAndActivated = $plugins;
return $this->pluginsLoadedAndActivated;
/**
* Returns a list of all names of currently activated plugin eg,
*
* array(
* 'UserCountry'
* );
*
* @return string[]
*/
public function getActivatedPlugins()
{
return $this->pluginsToLoad;
}
public function getActivatedPluginsFromConfig()
{
$plugins = $this->pluginList->getActivatedPlugins();
Matthieu Napoli
a validé
return $this->makePluginsToLoad($plugins);
diosmosis
a validé
* Returns a Plugin object by name.
diosmosis
a validé
* @param string $name The name of the plugin, eg, `'Actions'`.
* @throws \Exception If the plugin has not been loaded.
*/
public function getLoadedPlugin($name)
{
if (!isset($this->loadedPlugins[$name]) || is_null($this->loadedPlugins[$name])) {
throw new \Exception("The plugin '$name' has not been loaded.");
}
return $this->loadedPlugins[$name];
}
/**
* Load the plugins classes installed.
* Register the observers for every plugin.
*/
private function reloadActivatedPlugins()
$pluginsToPostPendingEventsTo = array();
foreach ($this->pluginsToLoad as $pluginName) {
$pluginsToPostPendingEventsTo = $this->reloadActivatedPlugin($pluginName, $pluginsToPostPendingEventsTo);
}
mattab
a validé
// post pending events after all plugins are successfully loaded
foreach ($pluginsToPostPendingEventsTo as $plugin) {
EventDispatcher::getInstance()->postPendingEventsTo($plugin);
}
}
Thomas Steur
a validé
private function reloadActivatedPlugin($pluginName, $pluginsToPostPendingEventsTo)
{
if ($this->isPluginLoaded($pluginName) || $this->isPluginThirdPartyAndBogus($pluginName)) {
return $pluginsToPostPendingEventsTo;
}
Thomas Steur
a validé
$newPlugin = $this->loadPlugin($pluginName);
if ($newPlugin === null) {
return $pluginsToPostPendingEventsTo;
}
$requirements = $newPlugin->getMissingDependencies();
if (!empty($requirements)) {
foreach ($requirements as $requirement) {
$possiblePluginName = $requirement['requirement'];
if (in_array($possiblePluginName, $this->pluginsToLoad, $strict = true)) {
$pluginsToPostPendingEventsTo = $this->reloadActivatedPlugin($possiblePluginName, $pluginsToPostPendingEventsTo);
}
}
}
if ($newPlugin->hasMissingDependencies()) {
Thomas Steur
a validé
$this->unloadPluginFromMemory($pluginName);
// at this state we do not know yet whether current user has super user access. We do not even know
// if someone is actually logged in.
Thomas Steur
a validé
$message = Piwik::translate('CorePluginsAdmin_WeCouldNotLoadThePluginAsItHasMissingDependencies', array($pluginName, $newPlugin->getMissingDependenciesAsString()));
$message .= ' ';
$message .= Piwik::translate('General_PleaseContactYourPiwikAdministrator');
$notification = new Notification($message);
$notification->context = Notification::CONTEXT_ERROR;
Thomas Steur
a validé
Notification\Manager::notify('PluginManager_PluginUnloaded', $notification);
return $pluginsToPostPendingEventsTo;
}
$pluginsToPostPendingEventsTo[] = $newPlugin;
return $pluginsToPostPendingEventsTo;
public function getIgnoredBogusPlugins()
{
$ignored = array();
foreach ($this->pluginsToLoad as $pluginName) {
if ($this->isPluginThirdPartyAndBogus($pluginName)) {
$ignored[] = $pluginName;
}
}
return $ignored;
}
/**
* Returns the name of all plugins found in this Piwik instance
*
* @return array
*/
public static function getAllPluginsNames()
{
$pluginList = StaticContainer::get('Piwik\Application\Kernel\PluginList');
$pluginsToLoad = array_merge(
self::getInstance()->readPluginsDirectory(),
$pluginList->getCorePluginsDisabledByDefault()
);
$pluginsToLoad = array_values(array_unique($pluginsToLoad));
return $pluginsToLoad;
}
Thomas Steur
a validé
* Loads the plugin filename and instantiates the plugin with the given name, eg. UserCountry.
* Contrary to loadPlugins() it does not activate the plugin, it only loads it.
*
* @param string $pluginName
* @throws \Exception
* @return Plugin|null
*/
public function loadPlugin($pluginName)
{
if (isset($this->loadedPlugins[$pluginName])) {
return $this->loadedPlugins[$pluginName];
}
$newPlugin = $this->makePluginClass($pluginName);
$this->addLoadedPlugin($pluginName, $newPlugin);
return $newPlugin;
}
public function isValidPluginName($pluginName)
{
return (bool) preg_match('/^[a-zA-Z]([a-zA-Z0-9_]*)$/D', $pluginName);
$pluginFileName = sprintf("%s/%s.php", $pluginName, $pluginName);
mattab
a validé
$pluginClassName = $pluginName;
if (!$this->isValidPluginName($pluginName)) {
throw new \Exception(sprintf("The plugin filename '%s' is not a valid plugin name", $pluginFileName));
Benaka Moorthi
a validé
$path = self::getPluginsDirectory() . $pluginFileName;
if (!file_exists($path)) {
Thomas Steur
a validé
// Eg. Used for Morpheus default theme which does not have a Morpheus.php file
return new Plugin($pluginName);
mattab
a validé
$namespacedClass = $this->getClassNamePlugin($pluginName);
if (!class_exists($namespacedClass, false)) {
throw new \Exception("The class $pluginClassName couldn't be found in the file '$path'");
mattab
a validé
$newPlugin = new $namespacedClass;
if (!($newPlugin instanceof Plugin)) {
throw new \Exception("The plugin $pluginClassName in the file $path must inherit from Plugin.");
}
return $newPlugin;
}
mattab
a validé
protected function getClassNamePlugin($pluginName)
{
$className = $pluginName;
mattab
a validé
$className = 'Plugin';
}
return "\\Piwik\\Plugins\\$pluginName\\$className";
}
private function resetTransientCache()
{
$this->pluginsLoadedAndActivated = null;
}
/**
* Unload plugin
*
* @param Plugin|string $plugin
* @throws \Exception
*/
public function unloadPlugin($plugin)
{