Newer
Older
mattpiwik
a validé
<?php
/**
* Piwik - Open source web analytics
*
* @link http://piwik.org
* @license http://www.gnu.org/licenses/gpl-3.0.html Gpl v3 or later
mattpiwik
a validé
*
mattpiwik
a validé
* @package Piwik
*/
mattpiwik
a validé
* @see core/Menu/Abstract.php
* @see core/Menu/Main.php
* @see core/Menu/Admin.php
* @see core/Menu/Top.php
* @see core/PluginsFunctions/WidgetsList.php
* @see core/PluginsFunctions/Sql.php
*/
mattpiwik
a validé
require_once PIWIK_INCLUDE_PATH . '/core/Menu/Abstract.php';
require_once PIWIK_INCLUDE_PATH . '/core/Menu/Main.php';
require_once PIWIK_INCLUDE_PATH . '/core/Menu/Admin.php';
require_once PIWIK_INCLUDE_PATH . '/core/Menu/Top.php';
require_once PIWIK_INCLUDE_PATH . '/core/PluginsFunctions/WidgetsList.php';
require_once PIWIK_INCLUDE_PATH . '/core/PluginsFunctions/Sql.php';
mattpiwik
a validé
/**
* @package Piwik
* @subpackage Piwik_PluginsManager
mattpiwik
a validé
*/
class Piwik_PluginsManager
{
/**
* @var Event_Dispatcher
*/
public $dispatcher;
protected $pluginsToLoad = array();
protected $languageToLoad = null;
protected $doLoadPlugins = true;
mattpiwik
a validé
protected $loadedPlugins = array();
protected $doLoadAlwaysActivatedPlugins = true;
protected $pluginToAlwaysActivate = array( 'CoreHome',
'CoreUpdater',
'CoreAdminHome',
'CorePluginsAdmin',
'Installation',
'SitesManager',
mattpiwik
a validé
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
static private $instance = null;
/**
* Returns the singleton Piwik_PluginsManager
*
* @return Piwik_PluginsManager
*/
static public function getInstance()
{
if (self::$instance == null)
{
$c = __CLASS__;
self::$instance = new $c();
}
return self::$instance;
}
private function __construct()
{
$this->dispatcher = Event_Dispatcher::getInstance();
}
public function isPluginAlwaysActivated( $name )
{
return in_array( $name, $this->pluginToAlwaysActivate);
}
public function isPluginActivated( $name )
{
return in_array( $name, $this->pluginsToLoad)
|| $this->isPluginAlwaysActivated( $name );
}
public function isPluginLoaded( $name )
{
return isset($this->loadedPlugins[$name]);
}
mattpiwik
a validé
/**
* Reads the directories inside the plugins/ directory and returns their names in an array
*
* @return array
*/
public function readPluginsDirectory()
{
robocoder
a validé
$pluginsName = _glob( PIWIK_INCLUDE_PATH . '/plugins/*', GLOB_ONLYDIR);
$pluginsName = $pluginsName == false ? array() : array_map('basename', $pluginsName);
mattpiwik
a validé
return $pluginsName;
}
public function deactivatePlugin($pluginName)
{
$plugins = $this->pluginsToLoad;
$key = array_search($pluginName,$plugins);
if($key !== false)
{
unset($plugins[$key]);
Zend_Registry::get('config')->Plugins = $plugins;
}
$pluginsTracker = Zend_Registry::get('config')->Plugins_Tracker->Plugins_Tracker;
if(!is_null($pluginsTracker))
{
$pluginsTracker = $pluginsTracker->toArray();
$key = array_search($pluginName,$pluginsTracker);
if($key !== false)
mattpiwik
a validé
{
unset($pluginsTracker[$key]);
Zend_Registry::get('config')->Plugins_Tracker = array('Plugins_Tracker' => $pluginsTracker);
mattpiwik
a validé
}
// Delete merged js/css files to force regenerations to exclude the deactivated plugin
Piwik_AssetManager::removeMergedAssets();
Piwik_View::clearCompiledTemplates();
mattpiwik
a validé
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
}
public function installLoadedPlugins()
{
foreach($this->getLoadedPlugins() as $plugin)
{
try {
$this->installPluginIfNecessary( $plugin );
}catch(Exception $e){
echo $e->getMessage();
}
}
}
public function activatePlugin($pluginName)
{
$plugins = Zend_Registry::get('config')->Plugins->Plugins->toArray();
if(in_array($pluginName,$plugins))
{
throw new Exception("Plugin '$pluginName' already activated.");
}
$existingPlugins = $this->readPluginsDirectory();
if( array_search($pluginName,$existingPlugins) === false)
{
throw new Exception("Unable to find the plugin '$pluginName'.");
}
$plugin = $this->loadPlugin($pluginName);
$this->installPluginIfNecessary($plugin);
// we add the plugin to the list of activated plugins
$plugins[] = $pluginName;
mattpiwik
a validé
// the config file will automatically be saved with the new plugin
Zend_Registry::get('config')->Plugins = $plugins;
// Delete merged js/css files to force regenerations to include the activated plugin
Piwik_AssetManager::removeMergedAssets();
Piwik_View::clearCompiledTemplates();
mattpiwik
a validé
}
public function loadPlugins( array $pluginsToLoad )
mattpiwik
a validé
{
// case no plugins to load
if(is_null($pluginsToLoad))
{
$pluginsToLoad = array();
}
$this->pluginsToLoad = $pluginsToLoad;
$this->reloadPlugins();
mattpiwik
a validé
}
public function doNotLoadPlugins()
{
$this->doLoadPlugins = false;
}
public function doNotLoadAlwaysActivatedPlugins()
{
$this->doLoadAlwaysActivatedPlugins = false;
}
public function loadTranslations()
mattpiwik
a validé
{
foreach($plugins as $plugin)
{
$this->loadTranslation( $plugin, $this->languageToLoad );
}
}
public function postLoadPlugins()
{
$plugins = $this->getLoadedPlugins();
foreach($plugins as $plugin)
{
mattpiwik
a validé
}
/**
* Returns an array containing the plugins class names (eg. 'Piwik_UserCountry' and NOT 'UserCountry')
*
* @return array
*/
public function getLoadedPluginsName()
{
robocoder
a validé
return array_map('get_class', $this->getLoadedPlugins());
mattpiwik
a validé
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
}
/**
* Returns an array of key,value with the following format: array(
* 'UserCountry' => Piwik_Plugin $pluginObject,
* 'UserSettings' => Piwik_Plugin $pluginObject,
* );
*
* @return array
*/
public function getLoadedPlugins()
{
return $this->loadedPlugins;
}
/**
* Returns the given Piwik_Plugin object
*
* @param string $name
* @return Piwik_Piwik
*/
public function getLoadedPlugin($name)
{
if(!isset($this->loadedPlugins[$name]))
{
throw new Exception("The plugin '$name' has not been loaded.");
}
return $this->loadedPlugins[$name];
}
mattpiwik
a validé
/**
* Load the plugins classes installed.
* Register the observers for every plugin.
*
*/
private function reloadPlugins()
mattpiwik
a validé
{
$this->pluginsToLoad = array_unique($this->pluginsToLoad);
mattpiwik
a validé
if($this->doLoadAlwaysActivatedPlugins)
{
$this->pluginsToLoad = array_merge($this->pluginsToLoad, $this->pluginToAlwaysActivate);
mattpiwik
a validé
}
mattpiwik
a validé
{
if(!$this->isPluginLoaded($pluginName))
mattpiwik
a validé
{
$newPlugin = $this->loadPlugin($pluginName);
if($this->doLoadPlugins
&& $this->isPluginActivated($pluginName))
{
$this->addPluginObservers( $newPlugin );
}
mattpiwik
a validé
}
}
}
/**
* Loads the plugin filename and instantiates the plugin with the given name, eg. UserCountry
mattpiwik
a validé
* Do NOT give the class name ie. Piwik_UserCountry, but give the plugin name ie. UserCountry
*
mattpiwik
a validé
*/
public function loadPlugin( $pluginName )
{
if(isset($this->loadedPlugins[$pluginName]))
{
return $this->loadedPlugins[$pluginName];
}
$pluginFileName = $pluginName . '/' . $pluginName . '.php';
$pluginClassName = 'Piwik_'.$pluginName;
mattpiwik
a validé
if( !Piwik_Common::isValidFilename($pluginName))
{
throw new Exception("The plugin filename '$pluginFileName' is not a valid filename");
}
mattpiwik
a validé
if(!file_exists($path))
{
throw new Exception("Unable to load plugin '$pluginName' because '$path' couldn't be found.
You can manually uninstall the plugin by removing the line <code>Plugins[] = $pluginName</code> from the Piwik config file.");
// Don't remove this.
// Our autoloader can't find plugins/PluginName/PluginName.php
require_once $path; // prefixed by PIWIK_INCLUDE_PATH
mattpiwik
a validé
if(!class_exists($pluginClassName, false))
mattpiwik
a validé
{
throw new Exception("The class $pluginClassName couldn't be found in the file '$path'");
}
$newPlugin = new $pluginClassName();
mattpiwik
a validé
if(!($newPlugin instanceof Piwik_Plugin))
{
throw new Exception("The plugin $pluginClassName in the file $path must inherit from Piwik_Plugin.");
}
$this->addLoadedPlugin( $pluginName, $newPlugin);
mattpiwik
a validé
return $newPlugin;
}
public function setLanguageToLoad( $code )
{
$this->languageToLoad = $code;
}
mattpiwik
a validé
public function unloadPlugin( $plugin )
{
if(!($plugin instanceof Piwik_Plugin ))
{
$plugin = $this->loadPlugin( $plugin );
}
$hooks = $plugin->getListHooksRegistered();
foreach($hooks as $hookName => $methodToCall)
{
$success = $this->dispatcher->removeObserver( array( $plugin, $methodToCall), $hookName );
if($success !== true)
{
throw new Exception("Error unloading plugin = ".$plugin->getClassName() . ", method = $methodToCall, hook = $hookName ");
mattpiwik
a validé
}
}
unset($this->loadedPlugins[$plugin->getClassName()]);
}
public function unloadPlugins()
{
$pluginsLoaded = $this->getLoadedPlugins();
foreach($pluginsLoaded as $plugin)
{
$this->unloadPlugin($plugin);
}
}
private function installPlugins()
{
foreach($this->getLoadedPlugins() as $plugin)
{
$this->installPlugin($plugin);
private function installPlugin( Piwik_Plugin $plugin )
{
try{
$plugin->install();
} catch(Exception $e) {
throw new Piwik_PluginsManager_PluginException($plugin->getClassName(), $e->getMessage()); }
/**
* For the given plugin, add all the observers of this plugin.
*/
private function addPluginObservers( Piwik_Plugin $plugin )
{
$hooks = $plugin->getListHooksRegistered();
foreach($hooks as $hookName => $methodToCall)
{
$this->dispatcher->addObserver( array( $plugin, $methodToCall), $hookName );
}
}
/**
* Add a plugin in the loaded plugins array
*
* @param string plugin name without prefix (eg. 'UserCountry')
* @param Piwik_Plugin $newPlugin
*/
private function addLoadedPlugin( $pluginName, Piwik_Plugin $newPlugin )
{
$this->loadedPlugins[$pluginName] = $newPlugin;
}
mattpiwik
a validé
/**
* @param Piwik_Plugin $plugin
* @param string $langCode
*/
mattpiwik
a validé
{
// we are in Tracker mode if Piwik_Loader is not (yet) loaded
if(!class_exists('Piwik_Loader', false))
mattpiwik
a validé
{
return ;
}
mattpiwik
a validé
$infos = $plugin->getInformation();
if(!isset($infos['translationAvailable']))
{
$infos['translationAvailable'] = false;
}
$translationAvailable = $infos['translationAvailable'];
if(!$translationAvailable)
{
return;
}
mattpiwik
a validé
$pluginName = $plugin->getClassName();
$path = PIWIK_INCLUDE_PATH . '/plugins/' . $pluginName .'/lang/%s.php';
mattpiwik
a validé
$defaultLangPath = sprintf($path, $langCode);
$defaultEnglishLangPath = sprintf($path, 'en');
$translations = array();
mattpiwik
a validé
{
require $defaultLangPath;
}
elseif(file_exists($defaultEnglishLangPath))
mattpiwik
a validé
{
require $defaultEnglishLangPath;
}
else
{
throw new Exception("Language file not found for the plugin '$pluginName'.");
}
Piwik_Translate::getInstance()->mergeTranslationArray($translations);
mattpiwik
a validé
}
if(!class_exists('Zend_Registry', false))
throw new Exception("Not possible to list installed plugins (case Tracker module)");
$pluginNames = Zend_Registry::get('config')->PluginsInstalled->PluginsInstalled->toArray();
return $pluginNames;
private function installPluginIfNecessary( Piwik_Plugin $plugin )
{
$pluginName = $plugin->getClassName();
// is the plugin already installed or is it the first time we activate it?
$pluginsInstalled = $this->getInstalledPluginsName();
if(!in_array($pluginName,$pluginsInstalled))
{
$this->installPlugin($plugin);
$pluginsInstalled[] = $pluginName;
Zend_Registry::get('config')->PluginsInstalled = array('PluginsInstalled' => $pluginsInstalled);
}
$information = $plugin->getInformation();
// if the plugin is to be loaded during the statistics logging
if(isset($information['TrackerPlugin'])
&& $information['TrackerPlugin'] === true)
$pluginsTracker = Zend_Registry::get('config')->Plugins_Tracker->Plugins_Tracker;
if(is_null($pluginsTracker))
$pluginsTracker = array();
$pluginsTracker = $pluginsTracker->toArray();
if(!in_array($pluginName, $pluginsTracker))
$pluginsTracker[] = $pluginName;
Zend_Registry::get('config')->Plugins_Tracker = array('Plugins_Tracker' => $pluginsTracker);
mattpiwik
a validé
/**
* @package Piwik
* @subpackage Piwik_PluginsManager
*/
class Piwik_PluginsManager_PluginException extends Exception
mattpiwik
a validé
{
function __construct($pluginName, $message)
mattpiwik
a validé
{
parent::__construct("There was a problem installing the plugin ". $pluginName . ": " . $message. "
If this plugin has already been installed, and if you want to hide this message</b>, you must add the following line under the
[PluginsInstalled]
entry in your config/config.ini.php file:
PluginsInstalled[] = $pluginName" );
mattpiwik
a validé
}
}
/**
* Post an event to the dispatcher which will notice the observers
* @param $object Object, array or string that the listeners can read and/or modify.
* Listeners can call $object =& $notification->getNotificationObject(); to fetch and then modify this variable.
* @param $info Additional array of data that can be used by the listeners, but not edited
mattpiwik
a validé
*/
function Piwik_PostEvent( $eventName, &$object = null, $info = array() )
{
mattpiwik
a validé
$notification = new Piwik_Event_Notification($object, $eventName, $info);
Piwik_PluginsManager::getInstance()->dispatcher->postNotification( $notification, true, false );
mattpiwik
a validé
}
/**
* Register an action to execute for a given event
*/
function Piwik_AddAction( $hookName, $function )
{
Piwik_PluginsManager::getInstance()->dispatcher->addObserver( $function, $hookName );
mattpiwik
a validé
* @see Event_Notification, libs/Event/Notification.php
* @link http://pear.php.net/package/Event_Dispatcher/docs/latest/Event_Dispatcher/Event_Notification.html
mattpiwik
a validé
class Piwik_Event_Notification extends Event_Notification
{
static $showProfiler = false;
function increaseNotificationCount(/* array($className|object, $method) */) {
mattpiwik
a validé
parent::increaseNotificationCount();
if(self::$showProfiler && func_num_args() == 1)
mattpiwik
a validé
{
$callback = func_get_arg(0);
if(is_array($callback)) {
$className = is_object($callback[0]) ? get_class($callback[0]) : $callback[0];
$method = $callback[1];
echo "after $className -> $method <br />";
echo "-"; Piwik::printTimer();
echo "<br />";
echo "-"; Piwik::printMemoryLeak();
echo "<br />";
}