Skip to content
Extraits de code Groupes Projets
AssetManager.php 11,3 ko
Newer Older
  • Learn to ignore specific revisions
  •  * Piwik - free/libre analytics platform
    
    robocoder's avatar
    robocoder a validé
     * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
    
    use Piwik\AssetManager\UIAsset;
    
    Julien Moumné's avatar
    Julien Moumné a validé
    use Piwik\AssetManager\UIAsset\InMemoryUIAsset;
    use Piwik\AssetManager\UIAsset\OnDiskUIAsset;
    use Piwik\AssetManager\UIAssetCacheBuster;
    use Piwik\AssetManager\UIAssetFetcher\JScriptUIAssetFetcher;
    use Piwik\AssetManager\UIAssetFetcher\StaticUIAssetFetcher;
    use Piwik\AssetManager\UIAssetFetcher\StylesheetUIAssetFetcher;
    
    use Piwik\AssetManager\UIAssetFetcher;
    
    Julien Moumné's avatar
    Julien Moumné a validé
    use Piwik\AssetManager\UIAssetMerger\JScriptUIAssetMerger;
    use Piwik\AssetManager\UIAssetMerger\StylesheetUIAssetMerger;
    
    use Piwik\Container\StaticContainer;
    
    Julien Moumné's avatar
    Julien Moumné a validé
    use Piwik\Plugin\Manager;
    
    robocoder's avatar
    robocoder a validé
    
    
     * AssetManager is the class used to manage the inclusion of UI assets:
    
    robocoder's avatar
    robocoder a validé
     * JavaScript and CSS files.
    
    robocoder's avatar
    robocoder a validé
     * It performs the following actions:
    
     *  - Identifies required assets
    
     *  - Includes assets in the rendered HTML page
     *  - Manages asset merging and minifying
    
    robocoder's avatar
    robocoder a validé
     *
     * Whether assets are included individually or as merged files is defined by
    
     * the global option 'disable_merged_assets'. See the documentation in the global
     * config for more information.
    
     * @method static AssetManager getInstance()
    
    Julien Moumné's avatar
    Julien Moumné a validé
    class AssetManager extends Singleton
    
        const MERGED_CSS_FILE = "asset_manager_global_css.css";
    
    Julien Moumné's avatar
    Julien Moumné a validé
        const MERGED_CORE_JS_FILE = "asset_manager_core_js.js";
        const MERGED_NON_CORE_JS_FILE = "asset_manager_non_core_js.js";
    
    mattab's avatar
    mattab a validé
    
    
        const CSS_IMPORT_DIRECTIVE = "<link rel=\"stylesheet\" type=\"text/css\" href=\"%s\" />\n";
        const JS_IMPORT_DIRECTIVE = "<script type=\"text/javascript\" src=\"%s\"></script>\n";
        const GET_CSS_MODULE_ACTION = "index.php?module=Proxy&action=getCss";
    
    Julien Moumné's avatar
    Julien Moumné a validé
        const GET_CORE_JS_MODULE_ACTION = "index.php?module=Proxy&action=getCoreJs";
        const GET_NON_CORE_JS_MODULE_ACTION = "index.php?module=Proxy&action=getNonCoreJs";
    
    Julien Moumné's avatar
    Julien Moumné a validé
         * @var UIAssetCacheBuster
    
    Julien Moumné's avatar
    Julien Moumné a validé
        private $cacheBuster;
    
    Julien Moumné's avatar
    Julien Moumné a validé
         * @var UIAssetFetcher
    
    Julien Moumné's avatar
    Julien Moumné a validé
        private $minimalStylesheetFetcher;
    
    Julien Moumné's avatar
    Julien Moumné a validé
         * @var Theme
    
    Julien Moumné's avatar
    Julien Moumné a validé
        private $theme;
    
        public function __construct()
    
    Julien Moumné's avatar
    Julien Moumné a validé
        {
            $this->cacheBuster = UIAssetCacheBuster::getInstance();
    
            $this->minimalStylesheetFetcher =  new StaticUIAssetFetcher(array('plugins/Morpheus/stylesheets/base.less', 'plugins/Morpheus/stylesheets/general/_forms.less'), array(), $this->theme);
    
            $theme = Manager::getInstance()->getThemeEnabled();
    
    Julien Moumné's avatar
    Julien Moumné a validé
                $this->theme = new Theme();
    
    Julien Moumné's avatar
    Julien Moumné a validé
         * @param UIAssetCacheBuster $cacheBuster
    
    Julien Moumné's avatar
    Julien Moumné a validé
        public function setCacheBuster($cacheBuster)
    
    Julien Moumné's avatar
    Julien Moumné a validé
            $this->cacheBuster = $cacheBuster;
    
    Julien Moumné's avatar
    Julien Moumné a validé
         * @param UIAssetFetcher $minimalStylesheetFetcher
    
    Julien Moumné's avatar
    Julien Moumné a validé
        public function setMinimalStylesheetFetcher($minimalStylesheetFetcher)
    
    Julien Moumné's avatar
    Julien Moumné a validé
            $this->minimalStylesheetFetcher = $minimalStylesheetFetcher;
    
    mattab's avatar
    mattab a validé
        }
    
    Julien Moumné's avatar
    Julien Moumné a validé
        /**
         * @param Theme $theme
         */
        public function setTheme($theme)
    
    Julien Moumné's avatar
    Julien Moumné a validé
            $this->theme = $theme;
    
    Julien Moumné's avatar
    Julien Moumné a validé
         * Return CSS file inclusion directive(s) using the markup <link>
    
    Julien Moumné's avatar
    Julien Moumné a validé
        public function getCssInclusionDirective()
    
    Julien Moumné's avatar
    Julien Moumné a validé
            return sprintf(self::CSS_IMPORT_DIRECTIVE, self::GET_CSS_MODULE_ACTION);
    
    Julien Moumné's avatar
    Julien Moumné a validé
        /**
         * Return JS file inclusion directive(s) using the markup <script>
         *
         * @return string
    
    Julien Moumné's avatar
    Julien Moumné a validé
        public function getJsInclusionDirective()
    
    Julien Moumné's avatar
    Julien Moumné a validé
            $result = "<script type=\"text/javascript\">\n" . Translate::getJavascriptTranslations() . "\n</script>";
    
    Julien Moumné's avatar
    Julien Moumné a validé
            if ($this->isMergedAssetsDisabled()) {
                $this->getMergedCoreJSAsset()->delete();
                $this->getMergedNonCoreJSAsset()->delete();
    
    Julien Moumné's avatar
    Julien Moumné a validé
                $result .= $this->getIndividualJsIncludes();
            } else {
                $result .= sprintf(self::JS_IMPORT_DIRECTIVE, self::GET_CORE_JS_MODULE_ACTION);
                $result .= sprintf(self::JS_IMPORT_DIRECTIVE, self::GET_NON_CORE_JS_MODULE_ACTION);
    
    mattab's avatar
    mattab a validé
            }
    
    
    Julien Moumné's avatar
    Julien Moumné a validé
            return $result;
    
    mattab's avatar
    mattab a validé
        }
    
        /**
    
    Julien Moumné's avatar
    Julien Moumné a validé
         * Return the base.less compiled to css
    
    Julien Moumné's avatar
    Julien Moumné a validé
         * @return UIAsset
    
    Julien Moumné's avatar
    Julien Moumné a validé
        public function getCompiledBaseCss()
    
    Julien Moumné's avatar
    Julien Moumné a validé
            $mergedAsset = new InMemoryUIAsset();
    
    Julien Moumné's avatar
    Julien Moumné a validé
            $assetMerger = new StylesheetUIAssetMerger($mergedAsset, $this->minimalStylesheetFetcher, $this->cacheBuster);
    
    Julien Moumné's avatar
    Julien Moumné a validé
            $assetMerger->generateFile();
    
    Julien Moumné's avatar
    Julien Moumné a validé
            return $mergedAsset;
    
    Julien Moumné's avatar
    Julien Moumné a validé
         * Return the css merged file absolute location.
         * If there is none, the generation process will be triggered.
    
    Julien Moumné's avatar
    Julien Moumné a validé
         * @return UIAsset
    
    Julien Moumné's avatar
    Julien Moumné a validé
        public function getMergedStylesheet()
    
    Julien Moumné's avatar
    Julien Moumné a validé
            $mergedAsset = $this->getMergedStylesheetAsset();
    
    Julien Moumné's avatar
    Julien Moumné a validé
            $assetFetcher = new StylesheetUIAssetFetcher(Manager::getInstance()->getLoadedPluginsName(), $this->theme);
    
    Julien Moumné's avatar
    Julien Moumné a validé
            $assetMerger = new StylesheetUIAssetMerger($mergedAsset, $assetFetcher, $this->cacheBuster);
    
            $assetMerger->generateFile();
    
            return $mergedAsset;
    
    Julien Moumné's avatar
    Julien Moumné a validé
         * Return the core js merged file absolute location.
         * If there is none, the generation process will be triggered.
    
    Julien Moumné's avatar
    Julien Moumné a validé
         * @return UIAsset
    
    Julien Moumné's avatar
    Julien Moumné a validé
        public function getMergedCoreJavaScript()
    
    Julien Moumné's avatar
    Julien Moumné a validé
            return $this->getMergedJavascript($this->getCoreJScriptFetcher(), $this->getMergedCoreJSAsset());
    
    Julien Moumné's avatar
    Julien Moumné a validé
         * Return the non core js merged file absolute location.
         * If there is none, the generation process will be triggered.
    
    Julien Moumné's avatar
    Julien Moumné a validé
         * @return UIAsset
    
    Julien Moumné's avatar
    Julien Moumné a validé
        public function getMergedNonCoreJavaScript()
    
    Julien Moumné's avatar
    Julien Moumné a validé
            return $this->getMergedJavascript($this->getNonCoreJScriptFetcher(), $this->getMergedNonCoreJSAsset());
    
    Julien Moumné's avatar
    Julien Moumné a validé
         * @param boolean $core
         * @return string[]
    
    Julien Moumné's avatar
    Julien Moumné a validé
        public function getLoadedPlugins($core)
    
    Julien Moumné's avatar
    Julien Moumné a validé
            $loadedPlugins = array();
    
            foreach (Manager::getInstance()->getPluginsLoadedAndActivated() as $plugin) {
    
                $pluginName = $plugin->getPluginName();
    
    Julien Moumné's avatar
    Julien Moumné a validé
                $pluginIsCore = Manager::getInstance()->isPluginBundledWithCore($pluginName);
    
    
                if (($pluginIsCore && $core) || (!$pluginIsCore && !$core)) {
    
    Julien Moumné's avatar
    Julien Moumné a validé
                    $loadedPlugins[] = $pluginName;
    
    Julien Moumné's avatar
    Julien Moumné a validé
    
            return $loadedPlugins;
    
    Julien Moumné's avatar
    Julien Moumné a validé
         * Remove previous merged assets
    
    Julien Moumné's avatar
    Julien Moumné a validé
        public function removeMergedAssets($pluginName = false)
    
    Julien Moumné's avatar
    Julien Moumné a validé
            $assetsToRemove = array($this->getMergedStylesheetAsset());
    
    
            if ($pluginName) {
                if ($this->pluginContainsJScriptAssets($pluginName)) {
                    if (Manager::getInstance()->isPluginBundledWithCore($pluginName)) {
    
    Julien Moumné's avatar
    Julien Moumné a validé
                        $assetsToRemove[] = $this->getMergedCoreJSAsset();
                    } else {
                        $assetsToRemove[] = $this->getMergedNonCoreJSAsset();
                    }
                }
            } else {
                $assetsToRemove[] = $this->getMergedCoreJSAsset();
                $assetsToRemove[] = $this->getMergedNonCoreJSAsset();
    
    Julien Moumné's avatar
    Julien Moumné a validé
            $this->removeAssets($assetsToRemove);
    
    Julien Moumné's avatar
    Julien Moumné a validé
         * Check if the merged file directory exists and is writable.
    
    Julien Moumné's avatar
    Julien Moumné a validé
         * @return string The directory location
         * @throws Exception if directory is not writable.
    
    Julien Moumné's avatar
    Julien Moumné a validé
        public function getAssetDirectory()
    
            $mergedFileDirectory = StaticContainer::get('path.tmp') . '/assets';
    
    Julien Moumné's avatar
    Julien Moumné a validé
            if (!is_dir($mergedFileDirectory)) {
                Filesystem::mkdir($mergedFileDirectory);
    
    Julien Moumné's avatar
    Julien Moumné a validé
            if (!is_writable($mergedFileDirectory)) {
                throw new Exception("Directory " . $mergedFileDirectory . " has to be writable.");
            }
    
            return $mergedFileDirectory;
    
    Julien Moumné's avatar
    Julien Moumné a validé
         * Return the global option disable_merged_assets
    
    Julien Moumné's avatar
    Julien Moumné a validé
         * @return boolean
    
    Julien Moumné's avatar
    Julien Moumné a validé
        public function isMergedAssetsDisabled()
    
    Martin Keckeis's avatar
    Martin Keckeis a validé
            if (Config::getInstance()->Development['disable_merged_assets'] == 1) {
                return true;
            }
            
            if (isset($_GET['disable_merged_assets']) && $_GET['disable_merged_assets'] == 1) {
                return true;
            }
            
            return false;
    
    Julien Moumné's avatar
    Julien Moumné a validé
         * @param UIAssetFetcher $assetFetcher
         * @param UIAsset $mergedAsset
         * @return UIAsset
    
    Julien Moumné's avatar
    Julien Moumné a validé
        private function getMergedJavascript($assetFetcher, $mergedAsset)
    
    Julien Moumné's avatar
    Julien Moumné a validé
            $assetMerger = new JScriptUIAssetMerger($mergedAsset, $assetFetcher, $this->cacheBuster);
    
    Julien Moumné's avatar
    Julien Moumné a validé
            $assetMerger->generateFile();
    
    Julien Moumné's avatar
    Julien Moumné a validé
            return $mergedAsset;
    
    Julien Moumné's avatar
    Julien Moumné a validé
         * Return individual JS file inclusion directive(s) using the markup <script>
    
    Julien Moumné's avatar
    Julien Moumné a validé
         * @return string
    
    Julien Moumné's avatar
    Julien Moumné a validé
        private function getIndividualJsIncludes()
    
    Julien Moumné's avatar
    Julien Moumné a validé
            return
                $this->getIndividualJsIncludesFromAssetFetcher($this->getCoreJScriptFetcher()) .
                $this->getIndividualJsIncludesFromAssetFetcher($this->getNonCoreJScriptFetcher());
    
    Julien Moumné's avatar
    Julien Moumné a validé
         * @param UIAssetFetcher $assetFetcher
         * @return string
    
    Julien Moumné's avatar
    Julien Moumné a validé
        private function getIndividualJsIncludesFromAssetFetcher($assetFetcher)
    
    Julien Moumné's avatar
    Julien Moumné a validé
            $jsIncludeString = '';
    
    Julien Moumné's avatar
    Julien Moumné a validé
            foreach ($assetFetcher->getCatalog()->getAssets() as $jsFile) {
                $jsFile->validateFile();
                $jsIncludeString = $jsIncludeString . sprintf(self::JS_IMPORT_DIRECTIVE, $jsFile->getRelativeLocation());
    
    Julien Moumné's avatar
    Julien Moumné a validé
    
            return $jsIncludeString;
    
    Julien Moumné's avatar
    Julien Moumné a validé
        private function getCoreJScriptFetcher()
    
    Julien Moumné's avatar
    Julien Moumné a validé
            return new JScriptUIAssetFetcher($this->getLoadedPlugins(true), $this->theme);
    
    Julien Moumné's avatar
    Julien Moumné a validé
        private function getNonCoreJScriptFetcher()
    
    Julien Moumné's avatar
    Julien Moumné a validé
            return new JScriptUIAssetFetcher($this->getLoadedPlugins(false), $this->theme);
    
    Julien Moumné's avatar
    Julien Moumné a validé
         * @param string $pluginName
         * @return boolean
    
    Julien Moumné's avatar
    Julien Moumné a validé
        private function pluginContainsJScriptAssets($pluginName)
    
    Julien Moumné's avatar
    Julien Moumné a validé
            $fetcher = new JScriptUIAssetFetcher(array($pluginName), $this->theme);
    
            try {
                $assets = $fetcher->getCatalog()->getAssets();
    
            } catch (\Exception $e) {
    
                // This can happen when a plugin is not valid (eg. Piwik 1.x format)
                // When posting the event to the plugin, it returns an exception "Plugin has not been loaded"
                return false;
            }
    
    Julien Moumné's avatar
    Julien Moumné a validé
            $plugin = Manager::getInstance()->getLoadedPlugin($pluginName);
    
    Julien Moumné's avatar
    Julien Moumné a validé
                $theme = Manager::getInstance()->getTheme($pluginName);
    
                $javaScriptFiles = $theme->getJavaScriptFiles();
    
    
                if (!empty($javaScriptFiles)) {
    
    Julien Moumné's avatar
    Julien Moumné a validé
                    $assets = array_merge($assets, $javaScriptFiles);
    
    Julien Moumné's avatar
    Julien Moumné a validé
            }
    
            return !empty($assets);
    
    Julien Moumné's avatar
    Julien Moumné a validé
         * @param UIAsset[] $uiAssets
    
        public function removeAssets($uiAssets)
    
            foreach ($uiAssets as $uiAsset) {
    
    Julien Moumné's avatar
    Julien Moumné a validé
                $uiAsset->delete();
            }
    
    Julien Moumné's avatar
    Julien Moumné a validé
         * @return UIAsset
    
        public function getMergedStylesheetAsset()
    
    Julien Moumné's avatar
    Julien Moumné a validé
            return $this->getMergedUIAsset(self::MERGED_CSS_FILE);
    
    Julien Moumné's avatar
    Julien Moumné a validé
         * @return UIAsset
    
    Julien Moumné's avatar
    Julien Moumné a validé
        private function getMergedCoreJSAsset()
    
    Julien Moumné's avatar
    Julien Moumné a validé
            return $this->getMergedUIAsset(self::MERGED_CORE_JS_FILE);
    
    Julien Moumné's avatar
    Julien Moumné a validé
         * @return UIAsset
    
    Julien Moumné's avatar
    Julien Moumné a validé
        private function getMergedNonCoreJSAsset()
    
    Julien Moumné's avatar
    Julien Moumné a validé
            return $this->getMergedUIAsset(self::MERGED_NON_CORE_JS_FILE);
    
    Julien Moumné's avatar
    Julien Moumné a validé
         * @param string $fileName
         * @return UIAsset
    
    Julien Moumné's avatar
    Julien Moumné a validé
        private function getMergedUIAsset($fileName)
    
    Julien Moumné's avatar
    Julien Moumné a validé
            return new OnDiskUIAsset($this->getAssetDirectory(), $fileName);