Skip to content
Extraits de code Groupes Projets
Manager.php 30,5 ko
Newer Older
  • Learn to ignore specific revisions
  • <?php
    /**
     * Piwik - Open source web analytics
    
    robocoder's avatar
    robocoder a validé
     *
    
    robocoder's avatar
    robocoder a validé
     * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
    
    robocoder's avatar
    robocoder a validé
     *
    
    robocoder's avatar
    robocoder a validé
     * @category Piwik
    
    namespace Piwik\Plugin;
    
    mattab's avatar
    mattab a validé
    use Piwik\EventDispatcher;
    use Piwik\Filesystem;
    use Piwik\Option;
    use Piwik\Plugin;
    
    use Piwik\Translate;
    
    mattab's avatar
    mattab a validé
    use Piwik\Updater;
    
    Julien Moumné's avatar
    Julien Moumné a validé
    use Piwik\Theme;
    
    require_once PIWIK_INCLUDE_PATH . '/core/EventDispatcher.php';
    
     * The singleton that manages plugin loading/unloading and installation/uninstallation.
    
    robocoder's avatar
    robocoder a validé
     *
    
     * @method static \Piwik\Plugin\Manager getInstance()
    
     * @subpackage Manager
    
        protected $pluginsToLoad = array();
    
        protected $doLoadPlugins = true;
    
        protected $loadedPlugins = array();
    
        const DEFAULT_THEME = "Zeitgeist";
    
    
        protected $doLoadAlwaysActivatedPlugins = true;
        protected $pluginToAlwaysActivate = array(
            'CoreHome',
            'CoreUpdater',
            'CoreAdminHome',
    
            'CoreConsole',
    
            'CoreVisualizations',
    
            'Installation',
            'SitesManager',
            'UsersManager',
            'API',
            'Proxy',
            'LanguagesManager',
    
    mattab's avatar
    mattab a validé
    
            // default Piwik theme, always enabled
    
        protected $corePluginsDisabledByDefault = array(
            'DBStats',
            'DevicesDetection',
    
            'ExampleCommand',
            'ExampleSettingsPlugin',
            'ExampleUI',
            'ExampleVisualization',
    
            'ExamplePluginTemplate',
            'ExampleTheme',
    
    mattab's avatar
    mattab a validé
            'LeftMenu'
    
    mattab's avatar
    mattab a validé
        public function getCorePluginsDisabledByDefault()
        {
            return $this->corePluginsDisabledByDefault;
        }
    
    
    mattab's avatar
    mattab a validé
        // If a plugin hooks onto at least an event starting with "Tracker.", we load the plugin during tracker
        const TRACKER_EVENT_PREFIX = 'Tracker.';
    
    
        /**
         * Update Plugins config
         *
         * @param array $plugins Plugins
         */
        private function updatePluginsConfig($plugins)
        {
    
            $section = PiwikConfig::getInstance()->Plugins;
    
            $section['Plugins'] = $plugins;
    
            PiwikConfig::getInstance()->Plugins = $section;
    
        }
    
        /**
         * Update Plugins_Tracker config
         *
         * @param array $plugins Plugins
         */
        private function updatePluginsTrackerConfig($plugins)
        {
    
            $section = PiwikConfig::getInstance()->Plugins_Tracker;
    
            $section['Plugins_Tracker'] = $plugins;
    
            PiwikConfig::getInstance()->Plugins_Tracker = $section;
    
        }
    
        /**
         * Update PluginsInstalled config
         *
         * @param array $plugins Plugins
         */
        private function updatePluginsInstalledConfig($plugins)
        {
    
            $section = PiwikConfig::getInstance()->PluginsInstalled;
    
            $section['PluginsInstalled'] = $plugins;
    
            PiwikConfig::getInstance()->PluginsInstalled = $section;
    
        }
    
        /**
         * Returns true if plugin is always activated
         *
    
         * @param string $name Name of plugin
    
        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.
    
         * @param string $name Name of plugin, eg, `'Actions'`.
    
         */
        public function isPluginActivated($name)
        {
            return in_array($name, $this->pluginsToLoad)
    
            || $this->isPluginAlwaysActivated($name);
    
         * Returns `true` if plugin is loaded (in memory).
    
         * @param string $name Name of plugin, eg, `'Acions'`.
    
         */
        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()
        {
    
            $pluginsName = _glob(self::getPluginsDirectory() . '*', GLOB_ONLYDIR);
    
            $result = array();
            if ($pluginsName != false) {
                foreach ($pluginsName as $path) {
    
                    if (self::pluginStructureLooksValid($path)) {
                        $result[] = basename($path);
    
        public static function getPluginsDirectory()
    
    mattab's avatar
    mattab a validé
        {
            return PIWIK_INCLUDE_PATH . '/plugins/';
        }
    
    
        /**
         * Uninstalls a Plugin (deletes plugin files from the disk)
         * Only deactivated plugins can be uninstalled
         *
         * @param $pluginName
    
         * @throws \Exception
         * @return bool
    
         */
        public function uninstallPlugin($pluginName)
        {
    
            if ($this->isPluginLoaded($pluginName)) {
    
                throw new \Exception("To uninstall the plugin $pluginName, first disable it in Piwik > Settings > Plugins");
    
            $this->returnLoadedPluginsInfo();
    
            try {
                $plugin = $this->getLoadedPlugin($pluginName);
                $plugin->uninstall();
            } catch(\Exception $e) {
            }
    
            Option::delete('version_' . $pluginName);
    
    
            $this->removePluginFromPluginsConfig($pluginName);
            $this->removePluginFromPluginsInstalledConfig($pluginName);
            $this->removePluginFromTrackerConfig($pluginName);
    
            PiwikConfig::getInstance()->forceSave();
    
            \Piwik\Settings\Manager::cleanupPluginSettings($pluginName);
    
    Julien Moumné's avatar
    Julien Moumné a validé
            $this->clearCache($pluginName);
    
            self::deletePluginFromFilesystem($pluginName);
    
            if ($this->isPluginInFilesystem($pluginName)) {
    
    Julien Moumné's avatar
    Julien Moumné a validé
        /**
         * @param string $pluginName
         */
        private function clearCache($pluginName)
        {
            Filesystem::deleteAllCacheOnUpdate($pluginName);
        }
    
    
        public static function deletePluginFromFilesystem($plugin)
        {
    
            Filesystem::unlinkRecursive(PIWIK_INCLUDE_PATH . '/plugins/' . $plugin, $deleteRootToo = true);
    
         * @param string $pluginName Name of plugin
    
         * @param array|bool $plugins Array of plugin names
         * @return array|bool
    
    mattab's avatar
    mattab a validé
        public function deactivatePlugin($pluginName, $plugins = false)
    
    mattab's avatar
    mattab a validé
                $plugins = $this->pluginsToLoad;
            }
    
            if(!$this->isPluginBogus($pluginName)) {
                $plugin = $this->loadPlugin($pluginName);
                if ($plugin !== null) {
                    $plugin->deactivate();
                }
    
    mattab's avatar
    mattab a validé
            $plugins = $this->removePluginFromPluginsConfig($pluginName, $plugins);
    
            $this->removePluginFromTrackerConfig($pluginName);
    
            PiwikConfig::getInstance()->forceSave();
    
    Julien Moumné's avatar
    Julien Moumné a validé
            $this->clearCache($pluginName);
    
    mattab's avatar
    mattab a validé
    
            return $plugins;
    
         *
         * @return array Error messages of plugin install fails
    
         */
        public function installLoadedPlugins()
        {
    
    mattab's avatar
    mattab a validé
            $messages = array();
    
            foreach ($this->getLoadedPlugins() as $plugin) {
                try {
                    $this->installPluginIfNecessary($plugin);
    
                } catch (\Exception $e) {
    
                    $messages[] = $e->getMessage();
    
        }
    
        /**
         * Activate the specified plugin and install (if needed)
         *
    
         * @param string $pluginName Name of plugin
    
         * @throws \Exception
    
         */
        public function activatePlugin($pluginName)
        {
    
            $plugins = PiwikConfig::getInstance()->Plugins['Plugins'];
    
            if (in_array($pluginName, $plugins)) {
    
                throw new \Exception("Plugin '$pluginName' already activated.");
    
            if (!$this->isPluginInFilesystem($pluginName)) {
    
                //Piwik::log(sprintf("Unable to find the plugin '%s' in activatePlugin.", $pluginName));
                return;
            }
    
    
            // Only one theme enabled at a time
    
            $themeEnabled = $this->getThemeEnabled();
    
    mattab's avatar
    mattab a validé
            if ($themeEnabled->getPluginName() != self::DEFAULT_THEME) {
    
                $themeAlreadyEnabled = $themeEnabled->getPluginName();
    
                $plugin = $this->loadPlugin($pluginName);
    
                if ($plugin->isTheme()) {
                    $plugins = $this->deactivatePlugin($themeAlreadyEnabled, $plugins);
    
            $plugin = $this->loadPlugin($pluginName);
            if ($plugin === null) {
                return;
            }
            $this->installPluginIfNecessary($plugin);
            $plugin->activate();
    
    
            EventDispatcher::getInstance()->postPendingEventsTo($plugin);
    
    
    
            // we add the plugin to the list of activated plugins
            if (!in_array($pluginName, $plugins)) {
                $plugins[] = $pluginName;
    
    mattab's avatar
    mattab a validé
            }
            $plugins = array_unique($plugins);
    
    
    
            // the config file will automatically be saved with the new plugin
            $this->updatePluginsConfig($plugins);
    
            PiwikConfig::getInstance()->forceSave();
    
    Julien Moumné's avatar
    Julien Moumné a validé
            $this->clearCache($pluginName);
    
        protected function isPluginInFilesystem($pluginName)
        {
            $existingPlugins = $this->readPluginsDirectory();
            $isPluginInFilesystem = array_search($pluginName, $existingPlugins) !== false;
    
            return Filesystem::isValidFilename($pluginName)
    
            && $isPluginInFilesystem;
    
    mattab's avatar
    mattab a validé
        /**
    
         * Returns the currently enabled theme.
         * 
         * If no theme is enabled, the **Zeitgeist** plugin is returned (this is the base and default theme).
    
    mattab's avatar
    mattab a validé
         *
    
    mattab's avatar
    mattab a validé
         */
    
    mattab's avatar
    mattab a validé
        {
            $plugins = $this->getLoadedPlugins();
    
            foreach ($plugins as $plugin) {
    
                if ($plugin->isTheme()
                    && $this->isPluginActivated($plugin->getPluginName())
                ) {
                    if ($plugin->getPluginName() != self::DEFAULT_THEME) {
    
                        return $plugin; // enabled theme (not default)
                    }
                    $theme = $plugin; // default theme
    
    mattab's avatar
    mattab a validé
                }
            }
    
    mattab's avatar
    mattab a validé
        }
    
    
    Julien Moumné's avatar
    Julien Moumné a validé
        /**
         * @param string $themeName
         * @throws \Exception
         * @return Theme
         */
        public function getTheme($themeName)
        {
            $plugins = $this->getLoadedPlugins();
    
            foreach ($plugins as $plugin)
                if ($plugin->isTheme() && $plugin->getPluginName() == $themeName)
                    return new Theme($plugin);
    
            throw new \Exception('Theme not found : ' . $themeName);
        }
    
    
        public function getNumberOfActivatedPlugins()
        {
            $counter = 0;
    
            $pluginNames = $this->getLoadedPluginsName();
            foreach ($pluginNames as $pluginName) {
                if ($this->isPluginActivated($pluginName)) {
                    $counter++;
                }
            }
    
            return $counter;
        }
    
    
         * 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:
         * 
    
         *               - **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()}.
    
         */
        public function returnLoadedPluginsInfo()
        {
    
            $language = Translate::getLanguageToLoad();
    
    
            $plugins = array();
    
            $listPlugins = array_merge(
                $this->readPluginsDirectory(),
    
                PiwikConfig::getInstance()->Plugins['Plugins']
    
            );
            $listPlugins = array_unique($listPlugins);
            foreach ($listPlugins as $pluginName) {
    
    
                // Hide plugins that are never going to be used
                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 {
    
                    $this->loadTranslation($pluginName, $language);
    
                    $this->loadPlugin($pluginName);
                    $info = array(
                        'activated'       => $this->isPluginActivated($pluginName),
                        'alwaysActivated' => $this->isPluginAlwaysActivated($pluginName),
                        'uninstallable'   => $this->isPluginUninstallable($pluginName),
                    );
    
            }
            $this->loadPluginTranslations();
    
            $loadedPlugins = $this->getLoadedPlugins();
            foreach ($loadedPlugins as $oPlugin) {
                $pluginName = $oPlugin->getPluginName();
                $plugins[$pluginName]['info'] = $oPlugin->getInformation();
            }
            return $plugins;
        }
    
    
        protected static function isManifestFileFound($path)
        {
            return file_exists($path . "/" . MetadataLoader::PLUGIN_JSON_FILENAME);
        }
    
    
         * Returns `true` if the plugin is bundled with core or `false` if it is third party.
    
         * @param string $name The name of the plugin, eg, `'Actions'`.
         * @return bool
         */
    
        public function isPluginBundledWithCore($name)
    
        {
            // Reading the plugins from the global.ini.php config file
    
            $pluginsBundledWithPiwik = PiwikConfig::getInstance()->getFromGlobalConfig('Plugins');
    
            $pluginsBundledWithPiwik = $pluginsBundledWithPiwik['Plugins'];
    
    
    mattab's avatar
    mattab a validé
            return (!empty($pluginsBundledWithPiwik)
    
    mattab's avatar
    mattab a validé
                        && in_array($name, $pluginsBundledWithPiwik))
    
    mattab's avatar
    mattab a validé
                    || in_array($name, $this->getCorePluginsDisabledByDefault())
                    || $name == self::DEFAULT_THEME;
    
        }
    
        protected function isPluginThirdPartyAndBogus($pluginName)
        {
    
    mattab's avatar
    mattab a validé
            if($this->isPluginBundledWithCore($pluginName)) {
                return false;
            }
    
            if($this->isPluginBogus($pluginName)) {
                return true;
    
    mattab's avatar
    mattab a validé
            }
    
    mattab's avatar
    mattab a validé
    
    
    mattab's avatar
    mattab a validé
            $path = $this->getPluginsDirectory() . $pluginName;
            if(!$this->isManifestFileFound($path)) {
                return true;
            }
            return false;
    
         * Load the specified plugins.
    
         * @param array $pluginsToLoad Array of plugins to load.
    
         */
        public function loadPlugins(array $pluginsToLoad)
        {
            // case no plugins to load
            if (is_null($pluginsToLoad)) {
                $pluginsToLoad = array();
            }
    
    mattab's avatar
    mattab a validé
            $pluginsToLoad = array_unique($pluginsToLoad);
    
            $this->pluginsToLoad = $pluginsToLoad;
            $this->reloadPlugins();
        }
    
        /**
    
         * Disable plugin loading.
    
         */
        public function doNotLoadPlugins()
        {
            $this->doLoadPlugins = false;
        }
    
        /**
    
         * Disable loading of "always activated" plugins.
    
         */
        public function doNotLoadAlwaysActivatedPlugins()
        {
            $this->doLoadAlwaysActivatedPlugins = false;
        }
    
        /**
         * Load translations for loaded plugins
         *
    
         * @param bool|string $language Optional language code
    
         */
        public function loadPluginTranslations($language = false)
        {
            if (empty($language)) {
    
                $language = Translate::getLanguageToLoad();
    
            }
            $plugins = $this->getLoadedPlugins();
    
            foreach ($plugins as $plugin) {
                $this->loadTranslation($plugin, $language);
            }
        }
    
        /**
         * Execute postLoad() hook for loaded plugins
         */
        public function postLoadPlugins()
        {
            $plugins = $this->getLoadedPlugins();
            foreach ($plugins as $plugin) {
                $plugin->postLoad();
            }
        }
    
        /**
    
         * Returns an array containing the plugins class names (eg. 'UserCountry' and NOT 'UserCountry')
    
         *
         * @return array
         */
        public function getLoadedPluginsName()
        {
    
            return array_keys($this->getLoadedPlugins());
    
         * Returns an array mapping loaded plugin names with their plugin objects, eg,
    
         *     array(
         *         'UserCountry' => Plugin $pluginObject,
         *         'UserSettings' => Plugin $pluginObject,
         *     );
    
         */
        public function getLoadedPlugins()
        {
            return $this->loadedPlugins;
        }
    
    
        /**
         * Returns a list of all names of currently activated plugin eg,
         *
         *     array(
         *         'UserCountry'
         *         'UserSettings'
         *     );
         *
         * @return string[]
         */
        public function getActivatedPlugins()
        {
            return $this->pluginsToLoad;
        }
    
    
         * @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])) {
    
                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 reloadPlugins()
        {
            if ($this->doLoadAlwaysActivatedPlugins) {
                $this->pluginsToLoad = array_merge($this->pluginsToLoad, $this->pluginToAlwaysActivate);
            }
    
    
    mattab's avatar
    mattab a validé
            $this->pluginsToLoad = array_unique($this->pluginsToLoad);
    
    
            foreach ($this->pluginsToLoad as $pluginName) {
    
                if (!$this->isPluginLoaded($pluginName)
    
                    && !$this->isPluginThirdPartyAndBogus($pluginName)
                ) {
    
                    $newPlugin = $this->loadPlugin($pluginName);
                    if ($newPlugin === null) {
                        continue;
                    }
    
    
                    EventDispatcher::getInstance()->postPendingEventsTo($newPlugin);
    
        public function getIgnoredBogusPlugins()
        {
            $ignored = array();
    
            foreach ($this->pluginsToLoad as $pluginName) {
                if ($this->isPluginThirdPartyAndBogus($pluginName)) {
    
        /**
         * Returns the name of all plugins found in this Piwik instance
    
    mattab's avatar
    mattab a validé
         * (including those not enabled and themes)
    
         *
         * Used in tests
         *
         * @return array
         */
        public static function getAllPluginsNames()
        {
            $pluginsToLoad = array_merge(
                PiwikConfig::getInstance()->Plugins['Plugins'],
                self::getInstance()->readPluginsDirectory(),
                self::getInstance()->getCorePluginsDisabledByDefault()
            );
            $pluginsToLoad = array_values(array_unique($pluginsToLoad));
            return $pluginsToLoad;
        }
    
    
    
        /**
         * Loads the plugin filename and instantiates the plugin with the given name, eg. UserCountry
         *
         * @param string $pluginName
    
         * @throws \Exception
         * @return Plugin|null
    
         */
        public function loadPlugin($pluginName)
        {
            if (isset($this->loadedPlugins[$pluginName])) {
                return $this->loadedPlugins[$pluginName];
            }
    
    mattab's avatar
    mattab a validé
            $newPlugin = $this->makePluginClass($pluginName);
    
            $this->addLoadedPlugin($pluginName, $newPlugin);
            return $newPlugin;
        }
    
        /**
         * @param $pluginName
    
         * @return Plugin
         * @throws \Exception
    
    mattab's avatar
    mattab a validé
         */
        protected function makePluginClass($pluginName)
        {
    
            $pluginFileName = sprintf("%s/%s.php", $pluginName, $pluginName);
    
            if (!Filesystem::isValidFilename($pluginName)) {
    
                throw new \Exception(sprintf("The plugin filename '%s' is not a valid filename", $pluginFileName));
    
            $path = self::getPluginsDirectory() . $pluginFileName;
    
    mattab's avatar
    mattab a validé
                // Create the smallest minimal Piwik Plugin
                // Eg. Used for Zeitgeist default theme which does not have a Zeitgeist.php file
    
    mattab's avatar
    mattab a validé
            require_once $path;
    
            $namespacedClass = $this->getClassNamePlugin($pluginName);
    
            if (!class_exists($namespacedClass, false)) {
    
                throw new \Exception("The class $pluginClassName couldn't be found in the file '$path'");
    
            if (!($newPlugin instanceof Plugin)) {
                throw new \Exception("The plugin $pluginClassName in the file $path must inherit from Plugin.");
    
        protected function getClassNamePlugin($pluginName)
        {
            $className = $pluginName;
    
            if ($pluginName == 'API') {
    
                $className = 'Plugin';
            }
            return "\\Piwik\\Plugins\\$pluginName\\$className";
        }
    
    
         * @param Plugin|string $plugin
         * @throws \Exception
    
         */
        public function unloadPlugin($plugin)
        {
    
            if (!($plugin instanceof Plugin)) {
    
                $oPlugin = $this->loadPlugin($plugin);
                if ($oPlugin === null) {
                    unset($this->loadedPlugins[$plugin]);
                    return;
                }
    
                $plugin = $oPlugin;
            }
    
            unset($this->loadedPlugins[$plugin->getPluginName()]);
        }
    
        /**
         * Unload all loaded plugins
         */
        public function unloadPlugins()
        {
            $pluginsLoaded = $this->getLoadedPlugins();
            foreach ($pluginsLoaded as $plugin) {
                $this->unloadPlugin($plugin);
            }
        }
    
        /**
         * Install loaded plugins
         */
        private function installPlugins()
        {
            foreach ($this->getLoadedPlugins() as $plugin) {
                $this->installPlugin($plugin);
            }
        }
    
        /**
         * Install a specific plugin
         *
    
    mattab's avatar
    mattab a validé
         * @throws \Piwik\Plugin\Manager_PluginException if installation fails
    
        private function installPlugin(Plugin $plugin)
    
            } catch (\Exception $e) {
    
    mattab's avatar
    mattab a validé
                throw new \Piwik\Plugin\PluginException($plugin->getPluginName(), $e->getMessage());
    
            Updater::recordComponentSuccessfullyUpdated($plugin->getPluginName(), $plugin->getVersion());
    
        }
    
        /**
         * Add a plugin in the loaded plugins array
         *
    
         * @param string $pluginName plugin name without prefix (eg. 'UserCountry')
    
        private function addLoadedPlugin($pluginName, Plugin $newPlugin)
    
        {
            $this->loadedPlugins[$pluginName] = $newPlugin;
        }
    
        /**
         * Load translation
         *
    
         * @throws \Exception
    
    mattab's avatar
    mattab a validé
         * @return bool whether the translation was found and loaded
    
         */
        private function loadTranslation($plugin, $langCode)
        {
    
            // we are in Tracker mode if Loader is not (yet) loaded
    
            if (!class_exists('Piwik\\Loader', false)) {
    
                return false;
    
            if (is_string($plugin)) {
                $pluginName = $plugin;
            } else {
                $pluginName = $plugin->getPluginName();
            }
    
            $path = self::getPluginsDirectory() . $pluginName . '/lang/%s.json';
    
    
            $defaultLangPath = sprintf($path, $langCode);
            $defaultEnglishLangPath = sprintf($path, 'en');
    
    
            $translationsLoaded = false;
    
            // merge in english translations as default first
            if (file_exists($defaultEnglishLangPath)) {
    
                $translations = $this->getTranslationsFromFile($defaultEnglishLangPath);
    
                $translationsLoaded = true;
                if (isset($translations[$pluginName])) {
                    // only merge translations of plugin - prevents overwritten strings
                    Translate::mergeTranslationArray(array($pluginName => $translations[$pluginName]));
                }
    
            // merge in specific language translations (to overwrite english defaults)
            if (file_exists($defaultLangPath)) {
                $translations = $this->getTranslationsFromFile($defaultLangPath);
                $translationsLoaded = true;
                if (isset($translations[$pluginName])) {
                    // only merge translations of plugin - prevents overwritten strings
                    Translate::mergeTranslationArray(array($pluginName => $translations[$pluginName]));
                }
    
         * Return names of all installed plugins.
    
         */
        public function getInstalledPluginsName()
        {
    
            $pluginNames = PiwikConfig::getInstance()->PluginsInstalled['PluginsInstalled'];
    
            return $pluginNames;
        }
    
        /**
         * Returns names of plugins that should be loaded, but cannot be since their
         * files cannot be found.
         *
         * @return array
    
         */
        public function getMissingPlugins()
        {
            $missingPlugins = array();
    
            if (isset(PiwikConfig::getInstance()->Plugins['Plugins'])) {
                $plugins = PiwikConfig::getInstance()->Plugins['Plugins'];
    
                foreach ($plugins as $pluginName) {
                    // if a plugin is listed in the config, but is not loaded, it does not exist in the folder
    
                    if (!self::getInstance()->isPluginLoaded($pluginName)
                        && !$this->isPluginBogus($pluginName)
                    ) {
    
                        $missingPlugins[] = $pluginName;
                    }
                }
            }
            return $missingPlugins;
        }
    
        /**
         * Install a plugin, if necessary
         *
    
        private function installPluginIfNecessary(Plugin $plugin)
    
        {
            $pluginName = $plugin->getPluginName();
    
            $saveConfig = false;
    
            // 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;
                $this->updatePluginsInstalledConfig($pluginsInstalled);
                $saveConfig = true;
            }
    
    
    mattab's avatar
    mattab a validé
            if ($this->isTrackerPlugin($plugin)) {
    
                $pluginsTracker = PiwikConfig::getInstance()->Plugins_Tracker['Plugins_Tracker'];
    
                if (is_null($pluginsTracker)) {
                    $pluginsTracker = array();
                }
                if (!in_array($pluginName, $pluginsTracker)) {
                    $pluginsTracker[] = $pluginName;
                    $this->updatePluginsTrackerConfig($pluginsTracker);
                    $saveConfig = true;
                }
            }
    
            if ($saveConfig) {
    
                PiwikConfig::getInstance()->forceSave();
    
    mattab's avatar
    mattab a validé
    
    
        protected function isTrackerPlugin(Plugin $plugin)
    
    mattab's avatar
    mattab a validé
        {
            $hooks = $plugin->getListHooksRegistered();
            $hookNames = array_keys($hooks);
            foreach ($hookNames as $name) {
                if (strpos($name, self::TRACKER_EVENT_PREFIX) === 0) {
                    return true;
                }
            }
            return false;
        }
    
        private static function pluginStructureLooksValid($path)
        {
            $name = basename($path);
            return file_exists($path . "/" . $name . ".php")
    
            || self::isManifestFileFound($path);
    
    
        /**
         * @param $pluginName
         */
        private function removePluginFromPluginsInstalledConfig($pluginName)
        {
    
            $pluginsInstalled = PiwikConfig::getInstance()->PluginsInstalled['PluginsInstalled'];
    
            $key = array_search($pluginName, $pluginsInstalled);
            if ($key !== false) {
                unset($pluginsInstalled[$key]);
            }
    
            $this->updatePluginsInstalledConfig($pluginsInstalled);
        }
    
        /**
         * @param $pluginName
         * @param $plugins
         * @return mixed
         */
        private function removePluginFromPluginsConfig($pluginName, $plugins = false)
        {
            if (empty($plugins)) {
                $plugins = $this->pluginsToLoad;
            }
    
            $key = array_search($pluginName, $plugins);
    
            if ($key !== false) {
                unset($plugins[$key]);
            }
    
            $this->updatePluginsConfig($plugins);
    
    mattab's avatar
    mattab a validé
    
            return $plugins;