Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/matomo-org/matomo.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJulien Moumné <julien@piwik.org>2013-12-17 20:52:36 +0400
committerJulien Moumné <julien@piwik.org>2013-12-17 20:52:36 +0400
commit6624e27e575d6056da7881bc05e9972c50ec1128 (patch)
tree06bec63f550d16ccc8a428d40a79604496ce0985 /core/AssetManager.php
parent5d44202fb79a9b2aa70b00ec88fd316f83a440b0 (diff)
fixes #4373, #1640
Diffstat (limited to 'core/AssetManager.php')
-rw-r--r--core/AssetManager.php710
1 files changed, 199 insertions, 511 deletions
diff --git a/core/AssetManager.php b/core/AssetManager.php
index ec850de0db..1104ed42d8 100644
--- a/core/AssetManager.php
+++ b/core/AssetManager.php
@@ -11,14 +11,19 @@
namespace Piwik;
use Exception;
-use JSMin;
-use lessc;
+use Piwik\AssetManager\UIAsset;
+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;
+use Piwik\AssetManager\UIAssetMerger\JScriptUIAssetMerger;
+use Piwik\AssetManager\UIAssetMerger\StylesheetUIAssetMerger;
+use Piwik\Plugin\Manager;
use Piwik\Translate;
-
-/**
- * @see libs/jsmin/jsmin.php
- */
-require_once PIWIK_INCLUDE_PATH . '/libs/jsmin/jsmin.php';
+use Piwik\Config as PiwikConfig;
/**
* AssetManager is the class used to manage the inclusion of UI assets:
@@ -36,678 +41,361 @@ require_once PIWIK_INCLUDE_PATH . '/libs/jsmin/jsmin.php';
* When set to 0, files will be included within a pair of files: 1 JavaScript
* and 1 css file.
*
+ * @method static \Piwik\AssetManager getInstance()
* @package Piwik
*/
-class AssetManager
+class AssetManager extends Singleton
{
const MERGED_CSS_FILE = "asset_manager_global_css.css";
- const MERGED_JS_FILE = "asset_manager_global_js.js";
- const STYLESHEET_IMPORT_EVENT = "AssetManager.getStylesheetFiles";
- const JAVASCRIPT_IMPORT_EVENT = "AssetManager.getJavaScriptFiles";
- const MERGED_FILE_DIR = "tmp/assets/";
- const COMPRESSED_FILE_LOCATION = "/tmp/assets/";
+ const MERGED_CORE_JS_FILE = "asset_manager_core_js.js";
+ const MERGED_NON_CORE_JS_FILE = "asset_manager_non_core_js.js";
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";
- const GET_JS_MODULE_ACTION = "index.php?module=Proxy&action=getJs";
- const MINIFIED_JS_RATIO = 100;
+ 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";
/**
- * @param $file
- * @param $less
- * @internal param $mergedContent
- * @return string
+ * @var UIAssetCacheBuster
*/
- protected static function getCssContentFromFile($file, $less)
- {
- self::validateCssFile($file);
-
- $fileLocation = self::getAbsoluteLocation($file);
- $less->addImportDir(dirname($fileLocation));
-
- $content = file_get_contents($fileLocation);
- $content = self::rewriteCssPathsDirectives($file, $content);
-
- return $content;
- }
+ private $cacheBuster;
/**
- * Returns CSS file inclusion directive(s) using the markup <link>
- *
- * @return string
+ * @var UIAssetFetcher
*/
- public static function getCssAssets()
- {
- return sprintf(self::CSS_IMPORT_DIRECTIVE, self::GET_CSS_MODULE_ACTION);
- }
+ private $minimalStylesheetFetcher;
/**
- * Returns JS file inclusion directive(s) using the markup <script>
- *
- * @return string
+ * @var Theme
*/
- public static function getJsAssets()
- {
- $result = "<script type=\"text/javascript\">\n" . Translate::getJavascriptTranslations() . "\n</script>";
+ private $theme;
- if (self::isMergedAssetsDisabled()) {
- // Individual includes mode
- self::removeMergedAsset(self::MERGED_JS_FILE);
- $result .= self::getIndividualJsIncludes();
- } else {
- $result .= sprintf(self::JS_IMPORT_DIRECTIVE, self::GET_JS_MODULE_ACTION);
- }
+ function __construct()
+ {
+ $this->cacheBuster = UIAssetCacheBuster::getInstance();
+ $this->minimalStylesheetFetcher = new StaticUIAssetFetcher(array('plugins/Zeitgeist/stylesheets/base.less'), array(), $this->theme);
- return $result;
+ if(Manager::getInstance()->getThemeEnabled() != null)
+ $this->theme = new Theme();
}
/**
- * Assets are cached in the browser and Piwik server returns 304 after initial download.
- * when the Cache buster string changes, the assets will be re-generated
- *
- * @return string
+ * @param UIAssetCacheBuster $cacheBuster
*/
- public static function generateAssetsCacheBuster()
+ public function setCacheBuster($cacheBuster)
{
- $currentGitHash = @file_get_contents(PIWIK_INCLUDE_PATH . '/.git/refs/heads/master');
- $pluginList = md5(implode(",", \Piwik\Plugin\Manager::getInstance()->getLoadedPluginsName()));
- $cacheBuster = md5(SettingsPiwik::getSalt() . $pluginList . PHP_VERSION . Version::VERSION . trim($currentGitHash));
- return $cacheBuster;
+ $this->cacheBuster = $cacheBuster;
}
/**
- * Generate the merged css file.
- *
- * @throws Exception if a file can not be opened in write mode
+ * @param UIAssetFetcher $minimalStylesheetFetcher
*/
- private static function prepareMergedCssFile()
+ public function setMinimalStylesheetFetcher($minimalStylesheetFetcher)
{
- $mergedCssAlreadyGenerated = self::isGenerated(self::MERGED_CSS_FILE);
- $isDevelopingPiwik = self::isMergedAssetsDisabled();
-
- if ($mergedCssAlreadyGenerated && !$isDevelopingPiwik) {
- return;
- }
-
- $files = self::getStylesheetFiles();
- $less = self::makeLess();
-
- // Loop through each css file
- $mergedContent = "";
- foreach ($files as $file) {
- $mergedContent .= self::getCssContentFromFile($file, $less, $mergedContent);
- }
-
- $fileHash = md5($mergedContent);
- $firstLineCompileHash = "/* compile_me_once=$fileHash */";
-
- // Disable Merged Assets ==> Check on each request if file needs re-compiling
- if ($mergedCssAlreadyGenerated
- && !$isDevelopingPiwik
- ) {
- $mergedFile = self::MERGED_CSS_FILE;
- $cacheIsValid = self::isFirstLineMatching($mergedFile, $firstLineCompileHash);
- if($cacheIsValid) {
- return;
- }
- // Some CSS file in the merge, has changed since last merged asset was generated
- // Note: we do not detect changes in @import'ed LESS files
- }
-
- $mergedContent = $less->compile($mergedContent);
-
- /**
- * Triggered after all less stylesheets are compiled to CSS, minified and merged into
- * one file, but before the generated CSS is written to disk.
- *
- * This event can be used to modify merged CSS.
- *
- * @param string &$mergedContent The merged and minified CSS.
- */
- Piwik::postEvent('AssetManager.filterMergedStylesheets', array(&$mergedContent));
-
- $theme = new Theme;
- $mergedContent = $theme->rewriteAssetsPathToTheme($mergedContent);
-
- $mergedContent =
- $firstLineCompileHash . "\n"
- . "/* Piwik CSS file is compiled with Less. You may be interested in writing a custom Theme for Piwik! */\n"
- . $mergedContent;
-
- self::writeAssetToFile($mergedContent, self::MERGED_CSS_FILE);
+ $this->minimalStylesheetFetcher = $minimalStylesheetFetcher;
}
- protected static function makeLess()
+ /**
+ * @param Theme $theme
+ */
+ public function setTheme($theme)
{
- if (!class_exists("lessc")) {
- throw new Exception("Less was added to composer during 2.0. ==> Execute this command to update composer packages: \$ php composer.phar install");
- }
- $less = new lessc;
- return $less;
+ $this->theme = $theme;
}
/**
- * Returns the base.less compiled to css
+ * Return CSS file inclusion directive(s) using the markup <link>
*
* @return string
*/
- public static function getCompiledBaseCss()
+ public function getCssInclusionDirective()
{
- $file = '/plugins/Zeitgeist/stylesheets/base.less';
- $less = self::makeLess();
- $lessContent = self::getCssContentFromFile($file, $less);
- $css = $less->compile($lessContent);
- return $css;
+ return sprintf(self::CSS_IMPORT_DIRECTIVE, self::GET_CSS_MODULE_ACTION);
}
- /*
- * Rewrite css url directives
- * - rewrites relative paths
- * - rewrite windows directory separator \\ to /
+ /**
+ * Return JS file inclusion directive(s) using the markup <script>
+ *
+ * @return string
*/
- protected static function rewriteCssPathsDirectives($relativePath, $content)
+ public function getJsInclusionDirective()
{
- static $rootDirectoryLength = null;
- if (is_null($rootDirectoryLength)) {
- $rootDirectoryLength = self::countDirectoriesInPathToRoot();
- }
+ $result = "<script type=\"text/javascript\">\n" . Translate::getJavascriptTranslations() . "\n</script>";
- $baseDirectory = dirname($relativePath);
- $content = preg_replace_callback(
- "/(url\(['\"]?)([^'\")]*)/",
- function ($matches) use ($rootDirectoryLength, $baseDirectory) {
- $absolutePath = substr(realpath(PIWIK_DOCUMENT_ROOT . "/$baseDirectory/" . $matches[2]), $rootDirectoryLength);
- $rewritten = str_replace('\\', '/', $absolutePath);
+ if ($this->isMergedAssetsDisabled()) {
- if (is_file($rewritten)) { // only rewrite the URL if transforming it points to a valid file
- return $matches[1] . $rewritten;
- } else {
- return $matches[1] . $matches[2];
- }
- },
- $content
- );
- return $content;
- }
+ $this->getMergedCoreJSAsset()->delete();
+ $this->getMergedNonCoreJSAsset()->delete();
- protected static function countDirectoriesInPathToRoot()
- {
- $rootDirectory = realpath(PIWIK_DOCUMENT_ROOT);
- if ($rootDirectory != '/' && substr_compare($rootDirectory, '/', -1)) {
- $rootDirectory .= '/';
- }
- $rootDirectoryLen = strlen($rootDirectory);
- return $rootDirectoryLen;
- }
+ $result .= $this->getIndividualJsIncludes();
- private static function writeAssetToFile($mergedContent, $name)
- {
- // Remove the previous file
- self::removeMergedAsset($name);
-
- // Tries to open the new file
- $newFilePath = self::getAbsoluteMergedFileLocation($name);
- $newFile = @fopen($newFilePath, "w");
+ } else {
- if (!$newFile) {
- throw new Exception ("The file : " . $newFile . " can not be opened in write mode.");
+ $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);
}
- // Write the content in the new file
- fwrite($newFile, $mergedContent);
- fclose($newFile);
+ return $result;
}
/**
- * Returns individual CSS file inclusion directive(s) using the markup <link>
+ * Return the base.less compiled to css
*
- * @return string
+ * @return UIAsset
*/
- private static function getIndividualCssIncludes()
+ public function getCompiledBaseCss()
{
- $cssIncludeString = '';
-
- $stylesheets = self::getStylesheetFiles();
+ $mergedAsset = new InMemoryUIAsset();
- foreach ($stylesheets as $cssFile) {
+ $assetMerger = new StylesheetUIAssetMerger($mergedAsset, $this->minimalStylesheetFetcher, $this->cacheBuster);
- self::validateCssFile($cssFile);
- $cssIncludeString = $cssIncludeString . sprintf(self::CSS_IMPORT_DIRECTIVE, $cssFile);
- }
+ $assetMerger->generateFile();
- return $cssIncludeString;
+ return $mergedAsset;
}
/**
- * Returns required CSS files
+ * Return the css merged file absolute location.
+ * If there is none, the generation process will be triggered.
*
- * @return Array
+ * @return UIAsset
*/
- private static function getStylesheetFiles()
+ public function getMergedStylesheet()
{
- $stylesheets = array();
-
- /**
- * Triggered when gathering the list of all stylesheets (CSS and LESS) needed by
- * Piwik and its plugins.
- *
- * Plugins that have stylesheets should use this event to make those stylesheets
- * load.
- *
- * Stylesheets should be placed within a **stylesheets** subdirectory in your plugin's
- * root directory.
- *
- * _Note: While you are developing your plugin you should enable the config setting
- * `[Debug] disable_merged_assets` so your stylesheets will be reloaded immediately
- * after a change._
- *
- * **Example**
- *
- * public function getStylesheetFiles(&$stylesheets)
- * {
- * $stylesheets[] = "plugins/MyPlugin/stylesheets/myfile.less";
- * $stylesheets[] = "plugins/MyPlugin/stylesheets/myotherfile.css";
- * }
- *
- * @param string[] &$stylesheets The list of stylesheet paths.
- */
- Piwik::postEvent(self::STYLESHEET_IMPORT_EVENT, array(&$stylesheets));
-
- $stylesheets = self::sortCssFiles($stylesheets);
-
- $theme = new Theme;
- $themeStylesheet = $theme->getStylesheet();
- if($themeStylesheet) {
- $stylesheets[] = $themeStylesheet;
- }
+ $mergedAsset = $this->getMergedStylesheetAsset();
- return $stylesheets;
- }
+ $assetFetcher = new StylesheetUIAssetFetcher(Manager::getInstance()->getLoadedPluginsName(), $this->theme);
- /**
- * Ensure CSS stylesheets are loaded in a particular order regardless of the order that plugins are loaded.
- *
- * @param array $stylesheets Array of CSS stylesheet files
- * @return array
- */
- private static function sortCssFiles($stylesheets)
- {
- $priorityCssOrdered = array(
- 'libs/',
- 'plugins/CoreHome/stylesheets/color_manager.css', // must be before other Piwik stylesheets
- 'plugins/Zeitgeist/stylesheets/base.less',
- 'plugins/Zeitgeist/stylesheets/',
- 'plugins/',
- 'plugins/Dashboard/stylesheets/dashboard.less',
- 'tests/',
- );
-
- return self::prioritySort($priorityCssOrdered, $stylesheets);
+ $assetMerger = new StylesheetUIAssetMerger($mergedAsset, $assetFetcher, $this->cacheBuster);
+
+ $assetMerger->generateFile();
+
+ return $mergedAsset;
}
/**
- * Check the validity of the css file
+ * Return the core js merged file absolute location.
+ * If there is none, the generation process will be triggered.
*
- * @param string $cssFile CSS file name
- * @return boolean
- * @throws Exception if a file can not be opened in write mode
+ * @return UIAsset
*/
- private static function validateCssFile($cssFile)
+ public function getMergedCoreJavaScript()
{
- if (!self::assetIsReadable($cssFile)) {
- throw new Exception("The css asset with 'href' = " . $cssFile . " is not readable");
- }
+ return $this->getMergedJavascript($this->getCoreJScriptFetcher(), $this->getMergedCoreJSAsset());
}
/**
- * Generate the merged js file.
+ * Return the non core js merged file absolute location.
+ * If there is none, the generation process will be triggered.
*
- * @throws Exception if a file can not be opened in write mode
+ * @return UIAsset
*/
- private static function generateMergedJsFile()
+ public function getMergedNonCoreJavaScript()
{
- $mergedContent = self::getFirstLineOfMergedJs();
-
- $files = self::getJsFiles();
- foreach ($files as $file) {
- self::validateJsFile($file);
- $fileLocation = self::getAbsoluteLocation($file);
- $content = file_get_contents($fileLocation);
- if (!self::isMinifiedJs($content)) {
- $content = JSMin::minify($content);
- }
- $mergedContent = $mergedContent . PHP_EOL . $content;
- }
- $mergedContent = str_replace("\n", "\r\n", $mergedContent);
-
- /**
- * Triggered after all the JavaScript files Piwik uses are minified and merged into a
- * single file, but before the merged JavaScript is written to disk.
- *
- * Plugins can use this event to modify merged JavaScript or do something else
- * with it.
- *
- * @param string &$mergedContent The minified and merged JavaScript.
- */
- Piwik::postEvent('AssetManager.filterMergedJavaScripts', array(&$mergedContent));
-
- $theme = new Theme;
- $mergedContent = $theme->rewriteAssetsPathToTheme($mergedContent);
-
- self::writeAssetToFile($mergedContent, self::MERGED_JS_FILE);
+ return $this->getMergedJavascript($this->getNonCoreJScriptFetcher(), $this->getMergedNonCoreJSAsset());
}
/**
- * Returns individual JS file inclusion directive(s) using the markup <script>
- *
- * @return string
+ * @param boolean $core
+ * @return string[]
*/
- private static function getIndividualJsIncludes()
+ public function getLoadedPlugins($core)
{
- $jsIncludeString = '';
+ $loadedPlugins = array();
- $jsFiles = self::getJsFiles();
- foreach ($jsFiles as $jsFile) {
- self::validateJsFile($jsFile);
- $jsIncludeString = $jsIncludeString . sprintf(self::JS_IMPORT_DIRECTIVE, $jsFile);
+ foreach(Manager::getInstance()->getLoadedPluginsName() as $pluginName) {
+
+ $pluginIsCore = Manager::getInstance()->isPluginBundledWithCore($pluginName);
+
+ if(($pluginIsCore && $core) || (!$pluginIsCore && !$core))
+ $loadedPlugins[] = $pluginName;
}
- return $jsIncludeString;
+
+ return $loadedPlugins;
}
/**
- * Returns required JS files
- *
- * @return Array
+ * Remove previous merged assets
*/
- private static function getJsFiles()
+ public function removeMergedAssets($pluginName = false)
{
- $jsFiles = array();
-
- /**
- * Triggered when gathering the list of all JavaScript files needed by Piwik
- * and its plugins.
- *
- * Plugins that have their own JavaScript should use this event to make those
- * files load in the browser.
- *
- * JavaScript files should be placed within a **javascripts** subdirectory in your
- * plugin's root directory.
- *
- * _Note: While you are developing your plugin you should enable the config setting
- * `[Debug] disable_merged_assets` so JavaScript files will be reloaded immediately
- * after every change._
- *
- * **Example**
- *
- * public function getJsFiles(&$jsFiles)
- * {
- * $jsFiles[] = "plugins/MyPlugin/javascripts/myfile.js";
- * $jsFiles[] = "plugins/MyPlugin/javascripts/anotherone.js";
- * }
- *
- * @param string[] $jsFiles The JavaScript files to load.
- */
- Piwik::postEvent(self::JAVASCRIPT_IMPORT_EVENT, array(&$jsFiles));
-
- $theme = new Theme;
- $jsInThemes = $theme->getJavaScriptFiles();
- if(!empty($jsInThemes)) {
- $jsFiles = array_merge($jsFiles, $jsInThemes);
+ $assetsToRemove = array($this->getMergedStylesheetAsset());
+
+ if($pluginName) {
+
+ if($this->pluginContainsJScriptAssets($pluginName)) {
+
+ PiwikConfig::getInstance()->init();
+ if(Manager::getInstance()->isPluginBundledWithCore($pluginName)) {
+
+ $assetsToRemove[] = $this->getMergedCoreJSAsset();
+
+ } else {
+
+ $assetsToRemove[] = $this->getMergedNonCoreJSAsset();
+ }
+ }
+
+ } else {
+
+ $assetsToRemove[] = $this->getMergedCoreJSAsset();
+ $assetsToRemove[] = $this->getMergedNonCoreJSAsset();
}
- $jsFiles = self::sortJsFiles($jsFiles);
- return $jsFiles;
+ $this->removeAssets($assetsToRemove);
}
/**
- * Ensure core JS (jQuery etc.) are loaded in a particular order regardless of the order that plugins are loaded.
+ * Check if the merged file directory exists and is writable.
*
- * @param array $jsFiles Arry of JavaScript files
- * @return array
+ * @return string The directory location
+ * @throws Exception if directory is not writable.
*/
- private static function sortJsFiles($jsFiles)
+ public function getAssetDirectory()
{
- $priorityJsOrdered = array(
- 'libs/jquery/jquery.js',
- 'libs/jquery/jquery-ui.js',
- 'libs/jquery/jquery.browser.js',
- 'libs/',
- 'plugins/Zeitgeist/javascripts/piwikHelper.js',
- 'plugins/Zeitgeist/javascripts/',
- 'plugins/CoreHome/javascripts/broadcast.js',
- 'plugins/',
- 'tests/',
- );
-
- return self::prioritySort($priorityJsOrdered, $jsFiles);
- }
+ $mergedFileDirectory = PIWIK_USER_PATH . "/tmp/assets";
+ $mergedFileDirectory = SettingsPiwik::rewriteTmpPathWithHostname($mergedFileDirectory);
- /**
- * Check the validity of the js file
- *
- * @param string $jsFile JavaScript file name
- * @return boolean
- * @throws Exception if js file is not valid
- */
- private static function validateJsFile($jsFile)
- {
- if (!self::assetIsReadable($jsFile)) {
- throw new Exception("The js asset with 'src' = " . $jsFile . " is not readable");
+ if (!is_dir($mergedFileDirectory)) {
+ Filesystem::mkdir($mergedFileDirectory);
}
- }
- /**
- * Returns the global option disable_merged_assets
- *
- * @return string
- */
- public static function isMergedAssetsDisabled()
- {
- return Config::getInstance()->Debug['disable_merged_assets'];
+ if (!is_writable($mergedFileDirectory)) {
+ throw new Exception("Directory " . $mergedFileDirectory . " has to be writable.");
+ }
+
+ return $mergedFileDirectory;
}
/**
- * Returns the css merged file absolute location.
- * If there is none, the generation process will be triggered.
+ * Return the global option disable_merged_assets
*
- * @return string The absolute location of the css merged file
+ * @return boolean
*/
- public static function getMergedCssFileLocation()
+ public function isMergedAssetsDisabled()
{
- self::prepareMergedCssFile();
- return self::getAbsoluteMergedFileLocation(self::MERGED_CSS_FILE);
+ return Config::getInstance()->Debug['disable_merged_assets'];
}
/**
- * Returns the js merged file absolute location.
- * If there is none, the generation process will be triggered.
- *
- * @return string The absolute location of the js merged file
+ * @param UIAssetFetcher $assetFetcher
+ * @param UIAsset $mergedAsset
+ * @return UIAsset
*/
- public static function getMergedJsFileLocation()
+ private function getMergedJavascript($assetFetcher, $mergedAsset)
{
- $isGenerated = self::isGenerated(self::MERGED_JS_FILE);
+ $assetMerger = new JScriptUIAssetMerger($mergedAsset, $assetFetcher, $this->cacheBuster);
- // Make sure the merged JS is re-generated if there are new commits
- if($isGenerated) {
- $expectedFirstLine = self::getFirstLineOfMergedJs();
- $isGenerated = self::isFirstLineMatching(self::MERGED_JS_FILE, $expectedFirstLine);
- }
- if (!$isGenerated) {
- self::generateMergedJsFile();
- }
+ $assetMerger->generateFile();
- return self::getAbsoluteMergedFileLocation(self::MERGED_JS_FILE);
+ return $mergedAsset;
}
/**
- * Check if the provided merged file is generated
+ * Return individual JS file inclusion directive(s) using the markup <script>
*
- * @param string $filename filename of the merged asset
- * @return boolean true is file exists and is readable, false otherwise
+ * @return string
*/
- private static function isGenerated($filename)
+ private function getIndividualJsIncludes()
{
- return is_readable(self::getAbsoluteMergedFileLocation($filename));
+ return
+ $this->getIndividualJsIncludesFromAssetFetcher($this->getCoreJScriptFetcher()) .
+ $this->getIndividualJsIncludesFromAssetFetcher($this->getNonCoreJScriptFetcher());
}
/**
- * Removes the previous merged file if it exists.
- * Also tries to remove compressed version of the merged file.
- *
- * @param string $filename filename of the merged asset
- * @see ProxyStaticFile::serveStaticFile(serveFile
- * @throws Exception if the file couldn't be deleted
+ * @param UIAssetFetcher $assetFetcher
+ * @return string
*/
- private static function removeMergedAsset($filename)
+ private function getIndividualJsIncludesFromAssetFetcher($assetFetcher)
{
- $isGenerated = self::isGenerated($filename);
-
- if ($isGenerated) {
- if (!unlink(self::getAbsoluteMergedFileLocation($filename))) {
- throw new Exception("Unable to delete merged file : " . $filename . ". Please delete the file and refresh");
- }
+ $jsIncludeString = '';
- // Tries to remove compressed version of the merged file.
- // See ProxyHttp::serverStaticFile() for more info on static file compression
- $compressedFileLocation = PIWIK_USER_PATH . self::COMPRESSED_FILE_LOCATION . $filename;
- $compressedFileLocation = SettingsPiwik::rewriteTmpPathWithHostname($compressedFileLocation);
+ foreach ($assetFetcher->getCatalog()->getAssets() as $jsFile) {
- @unlink($compressedFileLocation . ".deflate");
- @unlink($compressedFileLocation . ".gz");
+ $jsFile->validateFile();
+ $jsIncludeString = $jsIncludeString . sprintf(self::JS_IMPORT_DIRECTIVE, $jsFile->getRelativeLocation());
}
+
+ return $jsIncludeString;
}
- /**
- * Remove previous merged assets
- */
- public static function removeMergedAssets()
+ private function getCoreJScriptFetcher()
{
- self::removeMergedAsset(self::MERGED_CSS_FILE);
- self::removeMergedAsset(self::MERGED_JS_FILE);
+ return new JScriptUIAssetFetcher($this->getLoadedPlugins(true), $this->theme);
}
- /**
- * Check if asset is readable
- *
- * @param string $relativePath Relative path to file
- * @return boolean
- */
- private static function assetIsReadable($relativePath)
+ private function getNonCoreJScriptFetcher()
{
- return is_readable(self::getAbsoluteLocation($relativePath));
+ return new JScriptUIAssetFetcher($this->getLoadedPlugins(false), $this->theme);
}
/**
- * Check if the merged file directory exists and is writable.
- *
- * @return string The directory location
- * @throws Exception if directory is not writable.
+ * @param string $pluginName
+ * @return boolean
*/
- private static function getMergedFileDirectory()
+ private function pluginContainsJScriptAssets($pluginName)
{
- $mergedFileDirectory = PIWIK_USER_PATH . '/' . self::MERGED_FILE_DIR;
- $mergedFileDirectory = SettingsPiwik::rewriteTmpPathWithHostname($mergedFileDirectory);
+ $fetcher = new JScriptUIAssetFetcher(array($pluginName), $this->theme);
- if (!is_dir($mergedFileDirectory)) {
- Filesystem::mkdir($mergedFileDirectory);
- }
+ $assets = $fetcher->getCatalog()->getAssets();
- if (!is_writable($mergedFileDirectory)) {
- throw new Exception("Directory " . $mergedFileDirectory . " has to be writable.");
- }
+ $plugin = Manager::getInstance()->getLoadedPlugin($pluginName);
- return $mergedFileDirectory;
- }
+ if($plugin->isTheme()) {
- /**
- * Builds the absolute location of the requested merged file
- *
- * @param string $mergedFile Name of the merge file
- * @return string absolute location of the merged file
- */
- private static function getAbsoluteMergedFileLocation($mergedFile)
- {
- return self::getMergedFileDirectory() . $mergedFile;
+ $theme = Manager::getInstance()->getTheme($pluginName);
+
+ $javaScriptFiles = $theme->getJavaScriptFiles();
+
+ if(!empty($javaScriptFiles))
+ $assets = array_merge($assets, $javaScriptFiles);
+ }
+
+ return !empty($assets);
}
/**
- * Returns the full path of an asset file
- *
- * @param string $relativePath Relative path to file
- * @return string
+ * @param UIAsset[] $uiAssets
*/
- private static function getAbsoluteLocation($relativePath)
+ private function removeAssets($uiAssets)
{
- // served by web server directly, so must be a public path
- return PIWIK_DOCUMENT_ROOT . "/" . $relativePath;
+ foreach($uiAssets as $uiAsset) {
+ $uiAsset->delete();
+ }
}
/**
- * Indicates if the provided JavaScript content has already been minified or not.
- * The heuristic is based on a custom ratio : (size of file) / (number of lines).
- * The threshold (100) has been found empirically on existing files :
- * - the ratio never exceeds 50 for non-minified content and
- * - it never goes under 150 for minified content.
- *
- * @param string $content Contents of the JavaScript file
- * @return boolean
+ * @return UIAsset
*/
- private static function isMinifiedJs($content)
+ private function getMergedStylesheetAsset()
{
- $lineCount = substr_count($content, "\n");
- if ($lineCount == 0) {
- return true;
- }
-
- $contentSize = strlen($content);
-
- $ratio = $contentSize / $lineCount;
-
- return $ratio > self::MINIFIED_JS_RATIO;
+ return $this->getMergedUIAsset(self::MERGED_CSS_FILE);
}
/**
- * Sort files according to priority order. Duplicates are also removed.
- *
- * @param array $priorityOrder Ordered array of paths (first to last) serving as buckets
- * @param array $files Unsorted array of files
- * @return array
+ * @return UIAsset
*/
- public static function prioritySort($priorityOrder, $files)
+ private function getMergedCoreJSAsset()
{
- $newFiles = array();
- foreach ($priorityOrder as $filePattern) {
- $newFiles = array_merge($newFiles, preg_grep('~^' . $filePattern . '~', $files));
- }
- return array_keys(array_flip($newFiles));
+ return $this->getMergedUIAsset(self::MERGED_CORE_JS_FILE);
}
/**
- * @param $mergedFile
- * @param $firstLineCompileHash
- * @return bool
+ * @return UIAsset
*/
- private static function isFirstLineMatching($mergedFile, $firstLineCompileHash)
+ private function getMergedNonCoreJSAsset()
{
- $pathMerged = self::getAbsoluteMergedFileLocation($mergedFile);
- $f = fopen($pathMerged, 'r');
- $firstLine = fgets($f);
- fclose($f);
- if (!empty($firstLine)
- && trim($firstLine) == trim($firstLineCompileHash)
- ) {
- return true;
- }
- return false;
+ return $this->getMergedUIAsset(self::MERGED_NON_CORE_JS_FILE);
}
/**
- * @return string
+ * @param string $fileName
+ * @return UIAsset
*/
- private static function getFirstLineOfMergedJs()
+ private function getMergedUIAsset($fileName)
{
- return "/* Piwik Javascript - cb=" . self::generateAssetsCacheBuster() . "*/\n";
+ return new OnDiskUIAsset($this->getAssetDirectory(), $fileName);
}
} \ No newline at end of file