From 6624e27e575d6056da7881bc05e9972c50ec1128 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Julien=20Moumn=C3=A9?= Date: Tue, 17 Dec 2013 17:52:36 +0100 Subject: fixes #4373, #1640 --- LEGALNOTICE | 10 - composer.json | 3 +- core/AssetManager.php | 710 ++++++-------------- core/AssetManager/UIAsset.php | 63 ++ core/AssetManager/UIAsset/InMemoryUIAsset.php | 65 ++ core/AssetManager/UIAsset/OnDiskUIAsset.php | 115 ++++ core/AssetManager/UIAssetCacheBuster.php | 47 ++ core/AssetManager/UIAssetCatalog.php | 83 +++ core/AssetManager/UIAssetCatalogSorter.php | 61 ++ core/AssetManager/UIAssetFetcher.php | 121 ++++ .../UIAssetFetcher/JScriptUIAssetFetcher.php | 85 +++ .../UIAssetFetcher/StaticUIAssetFetcher.php | 39 ++ .../UIAssetFetcher/StylesheetUIAssetFetcher.php | 70 ++ core/AssetManager/UIAssetMerger.php | 212 ++++++ .../UIAssetMerger/JScriptUIAssetMerger.php | 91 +++ .../UIAssetMerger/StylesheetUIAssetMerger.php | 142 ++++ core/AssetManager/UIAssetMinifier.php | 67 ++ core/Db/BatchInsert.php | 2 +- core/Filesystem.php | 4 +- core/Plugin.php | 2 +- core/Plugin/Manager.php | 31 +- core/ProxyHttp.php | 3 +- core/Theme.php | 26 +- core/Twig.php | 4 +- core/View.php | 3 +- libs/cssmin/MIT-LICENSE.txt | 19 - libs/cssmin/cssmin.php | 47 -- libs/jsmin/jsmin.php | 291 --------- plugins/Installation/Controller.php | 2 +- plugins/Proxy/Controller.php | 33 +- .../Core/AssetManager/PluginManagerMock.php | 70 ++ tests/PHPUnit/Core/AssetManager/PluginMock.php | 132 ++++ tests/PHPUnit/Core/AssetManager/ThemeMock.php | 76 +++ .../Core/AssetManager/UIAssetCacheBusterMock.php | 48 ++ .../Core/AssetManager/UIAssetCacheBusterTest.php | 31 + .../Core/AssetManager/UIAssetCatalogSorterTest.php | 52 ++ .../Core/AssetManager/UIAssetMinifierTest.php | 55 ++ .../configs/merged-assets-disabled.ini.php | 2 + .../configs/merged-assets-enabled.ini.php | 2 + .../Core/AssetManager/configs/plugins.ini.php | 3 + .../scripts/ExpectedMergeResultCore.js | 6 + .../scripts/ExpectedMergeResultNonCore.js | 3 + .../Core/AssetManager/scripts/SimpleAlert.js | 1 + .../Core/AssetManager/scripts/SimpleArray.js | 1 + .../Core/AssetManager/scripts/SimpleComments.js | 1 + .../Core/AssetManager/scripts/SimpleObject.js | 18 + .../Core/AssetManager/stylesheets/CssWithURLs.css | 12 + .../stylesheets/ExpectedMergeResult.css | 30 + .../AssetManager/stylesheets/ImportedLess.less | 12 + .../Core/AssetManager/stylesheets/SimpleBody.css | 3 + .../Core/AssetManager/stylesheets/SimpleLess.less | 17 + .../AssetManager/stylesheets/images/test-image.png | Bin 0 -> 290 bytes tests/PHPUnit/Core/AssetManagerTest.php | 712 ++++++++++++++++++++- tests/PHPUnit/Core/ServeStaticFileTest.php | 3 +- tests/PHPUnit/UI | 2 +- tests/PHPUnit/UITest.php | 2 +- 56 files changed, 2818 insertions(+), 927 deletions(-) create mode 100644 core/AssetManager/UIAsset.php create mode 100644 core/AssetManager/UIAsset/InMemoryUIAsset.php create mode 100644 core/AssetManager/UIAsset/OnDiskUIAsset.php create mode 100644 core/AssetManager/UIAssetCacheBuster.php create mode 100644 core/AssetManager/UIAssetCatalog.php create mode 100644 core/AssetManager/UIAssetCatalogSorter.php create mode 100644 core/AssetManager/UIAssetFetcher.php create mode 100644 core/AssetManager/UIAssetFetcher/JScriptUIAssetFetcher.php create mode 100644 core/AssetManager/UIAssetFetcher/StaticUIAssetFetcher.php create mode 100644 core/AssetManager/UIAssetFetcher/StylesheetUIAssetFetcher.php create mode 100644 core/AssetManager/UIAssetMerger.php create mode 100644 core/AssetManager/UIAssetMerger/JScriptUIAssetMerger.php create mode 100644 core/AssetManager/UIAssetMerger/StylesheetUIAssetMerger.php create mode 100644 core/AssetManager/UIAssetMinifier.php delete mode 100644 libs/cssmin/MIT-LICENSE.txt delete mode 100644 libs/cssmin/cssmin.php delete mode 100644 libs/jsmin/jsmin.php create mode 100644 tests/PHPUnit/Core/AssetManager/PluginManagerMock.php create mode 100644 tests/PHPUnit/Core/AssetManager/PluginMock.php create mode 100644 tests/PHPUnit/Core/AssetManager/ThemeMock.php create mode 100644 tests/PHPUnit/Core/AssetManager/UIAssetCacheBusterMock.php create mode 100644 tests/PHPUnit/Core/AssetManager/UIAssetCacheBusterTest.php create mode 100644 tests/PHPUnit/Core/AssetManager/UIAssetCatalogSorterTest.php create mode 100644 tests/PHPUnit/Core/AssetManager/UIAssetMinifierTest.php create mode 100644 tests/PHPUnit/Core/AssetManager/configs/merged-assets-disabled.ini.php create mode 100644 tests/PHPUnit/Core/AssetManager/configs/merged-assets-enabled.ini.php create mode 100644 tests/PHPUnit/Core/AssetManager/configs/plugins.ini.php create mode 100644 tests/PHPUnit/Core/AssetManager/scripts/ExpectedMergeResultCore.js create mode 100644 tests/PHPUnit/Core/AssetManager/scripts/ExpectedMergeResultNonCore.js create mode 100644 tests/PHPUnit/Core/AssetManager/scripts/SimpleAlert.js create mode 100644 tests/PHPUnit/Core/AssetManager/scripts/SimpleArray.js create mode 100644 tests/PHPUnit/Core/AssetManager/scripts/SimpleComments.js create mode 100644 tests/PHPUnit/Core/AssetManager/scripts/SimpleObject.js create mode 100644 tests/PHPUnit/Core/AssetManager/stylesheets/CssWithURLs.css create mode 100644 tests/PHPUnit/Core/AssetManager/stylesheets/ExpectedMergeResult.css create mode 100644 tests/PHPUnit/Core/AssetManager/stylesheets/ImportedLess.less create mode 100644 tests/PHPUnit/Core/AssetManager/stylesheets/SimpleBody.css create mode 100644 tests/PHPUnit/Core/AssetManager/stylesheets/SimpleLess.less create mode 100644 tests/PHPUnit/Core/AssetManager/stylesheets/images/test-image.png diff --git a/LEGALNOTICE b/LEGALNOTICE index 3863c68c12..f394df67e4 100644 --- a/LEGALNOTICE +++ b/LEGALNOTICE @@ -114,16 +114,6 @@ THIRD-PARTY COMPONENTS AND LIBRARIES Notes: - reference implementation - Name: cssmin - Link: http://code.google.com/p/cssmin/ - License: MIT - - Name: jsmin - Link: http://code.google.com/p/jsmin-php/ - License: MIT - Notes: - - contains additional clause "The Software shall be used for Good, not Evil." - Name: sparkline Link: https//sourceforge.net/projects/sparkline/ License: Dual-licensed: New BSD or GPL v2 diff --git a/composer.json b/composer.json index 190c5de277..039faa8a66 100644 --- a/composer.json +++ b/composer.json @@ -22,6 +22,7 @@ "php": ">=5.3.0", "twig/twig": "1.*", "leafo/lessphp": "0.3.*", - "symfony/console": ">=v2.3.5" + "symfony/console": ">=v2.3.5", + "tedivm/jshrink": "v0.5.1" } } 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 = "\n"; const JS_IMPORT_DIRECTIVE = "\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 - * - * @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 "; + 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 * * @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 "; - $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 + * 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 '; + } + + /** + * @return UIAsset[] + */ + private function generateAllMergedAssets() + { + $this->triggerGetMergedStylesheet(); + $stylesheetAsset = $this->mergedAsset; + + $this->triggerGetMergedCoreJavaScript(); + $coreJsAsset = $this->mergedAsset; + + $this->triggerGetMergedNonCoreJavaScript(); + $nonCoreJsAsset = $this->mergedAsset; + + $this->assertTrue($stylesheetAsset->exists()); + $this->assertTrue($coreJsAsset->exists()); + $this->assertTrue($nonCoreJsAsset->exists()); + + return array($stylesheetAsset, $coreJsAsset, $nonCoreJsAsset); + } + + /** + * @group Core + */ + public function test_getMergedCoreJavaScript_NotGenerated() + { + $this->setJSCacheBuster(self::FIRST_CACHE_BUSTER_JS); + + $this->triggerGetMergedCoreJavaScript(); + + $this->validateMergedCoreJs(); + } + + /** + * @group Core + */ + public function test_getMergedNonCoreJavaScript_NotGenerated() + { + $this->setJSCacheBuster(self::FIRST_CACHE_BUSTER_JS); + + $this->triggerGetMergedNonCoreJavaScript(); + + $this->validateMergedNonCoreJs(); + } + + /** + * @group Core + */ + public function test_getMergedNonCoreJavaScript_NotGenerated_NoNonCorePlugin() + { + $this->setUpCorePluginOnly(); + + $this->setJSCacheBuster(self::FIRST_CACHE_BUSTER_JS); + + $this->triggerGetMergedNonCoreJavaScript(); + + $expectedContent = $this->adjustExpectedJsContent('/* Piwik Javascript - cb={{{CACHE-BUSTER-JS}}}*/' . PHP_EOL); + + $this->validateExpectedContent($expectedContent); + } + + /** + * @group Core + */ + public function test_getMergedCoreJavaScript_AlreadyGenerated_MergedAssetsDisabled_UpToDate() + { + $this->disableMergedAssets(); + + $this->setJSCacheBuster(self::FIRST_CACHE_BUSTER_JS); + + $this->triggerGetMergedCoreJavaScript(); + + $modDateBeforeSecondRequest = $this->waitAndGetModificationDate(); + + $this->triggerGetMergedCoreJavaScript(); + + $this->validateDateDidNotChange($modDateBeforeSecondRequest); + } + + /** + * @group Core + */ + public function test_getMergedCoreJavaScript_AlreadyGenerated_MergedAssetsDisabled_Stale() + { + $this->disableMergedAssets(); + + $this->setJSCacheBuster(self::FIRST_CACHE_BUSTER_JS); + + $this->triggerGetMergedCoreJavaScript(); + + $modDateBeforeSecondRequest = $this->waitAndGetModificationDate(); + + $this->setJSCacheBuster(self::SECOND_CACHE_BUSTER_JS); + + $this->triggerGetMergedCoreJavaScript(); + + $this->validateDateIsMoreRecent($modDateBeforeSecondRequest); + + $this->validateMergedCoreJs(); + } + + /** + * @group Core + */ + public function test_getMergedStylesheet_NotGenerated() + { + $this->setStylesheetCacheBuster(self::FIRST_CACHE_BUSTER_SS); + + $this->triggerGetMergedStylesheet(); + + $this->validateMergedStylesheet(); + } + + /** + * @group Core + */ + public function test_getMergedStylesheet_Generated_MergedAssetsEnabled_Stale() + { + $this->setStylesheetCacheBuster(self::FIRST_CACHE_BUSTER_SS); + + $this->triggerGetMergedStylesheet(); + + $modDateBeforeSecondRequest = $this->waitAndGetModificationDate(); + + $this->setStylesheetCacheBuster(self::SECOND_CACHE_BUSTER_SS); + + $this->triggerGetMergedStylesheet(); + + $this->validateDateDidNotChange($modDateBeforeSecondRequest); + } + + /** + * @group Core + */ + public function test_getMergedStylesheet_Generated_MergedAssetsDisabled_Stale() + { + $this->disableMergedAssets(); + + $this->setStylesheetCacheBuster(self::FIRST_CACHE_BUSTER_SS); + + $this->triggerGetMergedStylesheet(); + + $modDateBeforeSecondRequest = $this->waitAndGetModificationDate(); + + $this->setStylesheetCacheBuster(self::SECOND_CACHE_BUSTER_SS); + + $this->triggerGetMergedStylesheet(); + + $this->validateDateIsMoreRecent($modDateBeforeSecondRequest); + + $this->validateMergedStylesheet(); + } + + + /** + * @group Core + */ + public function test_getMergedStylesheet_Generated_MergedAssetsDisabled_UpToDate() + { + $this->disableMergedAssets(); + + $this->setStylesheetCacheBuster(self::FIRST_CACHE_BUSTER_SS); + + $this->triggerGetMergedStylesheet(); + + $modDateBeforeSecondRequest = $this->waitAndGetModificationDate(); + + $this->triggerGetMergedStylesheet(); + + $this->validateDateDidNotChange($modDateBeforeSecondRequest); + } + + /** + * @group Core + */ + public function test_getCssInclusionDirective() + { + $expectedCssInclusionDirective = '' . PHP_EOL; + + $this->assertEquals($expectedCssInclusionDirective, $this->assetManager->getCssInclusionDirective()); + } + + /** + * @group Core + */ + public function test_getJsInclusionDirective_MergedAssetsDisabled() + { + $this->disableMergedAssets(); + + $expectedJsInclusionDirective = + $this->getJsTranslationScript() . + '' . PHP_EOL . + '' . PHP_EOL . + '' . PHP_EOL . + '' . PHP_EOL; + + $this->assertEquals($expectedJsInclusionDirective, $this->assetManager->getJsInclusionDirective()); + } + + /** + * @group Core + */ + public function test_getJsInclusionDirective_MergedAssetsEnabled() + { + $expectedJsInclusionDirective = + $this->getJsTranslationScript() . + '' . PHP_EOL . + '' . PHP_EOL; + + $this->assertEquals($expectedJsInclusionDirective, $this->assetManager->getJsInclusionDirective()); + } + + /** + * @group Core + */ + public function test_getCompiledBaseCss() + { + $this->setStylesheetCacheBuster(self::FIRST_CACHE_BUSTER_SS); + + $staticStylesheetList = array_merge($this->getCorePluginStylesheetFiles(), array($this->getCoreThemeStylesheet())); + + $minimalAssetFetcher = new StaticUIAssetFetcher( + array_reverse($staticStylesheetList), + $staticStylesheetList, + $this->getCoreTheme() + ); + + $this->assetManager->setMinimalStylesheetFetcher($minimalAssetFetcher); + + $this->mergedAsset = $this->assetManager->getCompiledBaseCss(); + + $this->validateMergedStylesheet(); + } + + /** + * @group Core + */ + public function test_removeMergedAssets() + { + list($stylesheetAsset, $coreJsAsset, $nonCoreJsAsset) = $this->generateAllMergedAssets(); + + $this->assetManager->removeMergedAssets(); + + $this->assertFalse($stylesheetAsset->exists()); + $this->assertFalse($coreJsAsset->exists()); + $this->assertFalse($nonCoreJsAsset->exists()); + } + + /** + * @group Core + */ + public function test_removeMergedAssets_PluginNameSpecified_PluginWithoutAssets() + { + list($stylesheetAsset, $coreJsAsset, $nonCoreJsAsset) = $this->generateAllMergedAssets(); + + $this->assetManager->removeMergedAssets(self::CORE_PLUGIN_WITHOUT_ASSETS_NAME); + + $this->assertFalse($stylesheetAsset->exists()); + $this->assertTrue($coreJsAsset->exists()); + $this->assertTrue($nonCoreJsAsset->exists()); + } + + /** + * @group Core + */ + public function test_removeMergedAssets_PluginNameSpecified_CorePlugin() + { + list($stylesheetAsset, $coreJsAsset, $nonCoreJsAsset) = $this->generateAllMergedAssets(); + + $this->assetManager->removeMergedAssets(self::CORE_PLUGIN_NAME); + + $this->assertFalse($stylesheetAsset->exists()); + $this->assertFalse($coreJsAsset->exists()); + $this->assertTrue($nonCoreJsAsset->exists()); + } + + /** + * @group Core + */ + public function test_removeMergedAssets_PluginNameSpecified_NonCoreThemeWithAssets() + { + list($stylesheetAsset, $coreJsAsset, $nonCoreJsAsset) = $this->generateAllMergedAssets(); + + $this->assetManager->removeMergedAssets(self::NON_CORE_THEME_PLUGIN_NAME); + + $this->assertFalse($stylesheetAsset->exists()); + $this->assertTrue($coreJsAsset->exists()); + $this->assertFalse($nonCoreJsAsset->exists()); } -} +} \ No newline at end of file diff --git a/tests/PHPUnit/Core/ServeStaticFileTest.php b/tests/PHPUnit/Core/ServeStaticFileTest.php index 9482227fea..d97fa4a6cf 100644 --- a/tests/PHPUnit/Core/ServeStaticFileTest.php +++ b/tests/PHPUnit/Core/ServeStaticFileTest.php @@ -477,8 +477,7 @@ class Test_Piwik_ServeStaticFile extends PHPUnit_Framework_TestCase private function getCompressedFileLocation() { - $path = PIWIK_PATH_TEST_TO_ROOT . \Piwik\AssetManager::COMPRESSED_FILE_LOCATION . basename(TEST_FILE_LOCATION); - return \Piwik\SettingsPiwik::rewriteTmpPathWithHostname($path); + return \Piwik\AssetManager::getInstance()->getAssetDirectory() . '/' . basename(TEST_FILE_LOCATION); } private function removeCompressedFiles() diff --git a/tests/PHPUnit/UI b/tests/PHPUnit/UI index cbf0922b35..673d21c6a7 160000 --- a/tests/PHPUnit/UI +++ b/tests/PHPUnit/UI @@ -1 +1 @@ -Subproject commit cbf0922b352e6592076908ee1fab095cd8e0642c +Subproject commit 673d21c6a750d8280f4e9ab9d203072dd8d844d2 diff --git a/tests/PHPUnit/UITest.php b/tests/PHPUnit/UITest.php index 5d7c555a32..cd2b86833c 100644 --- a/tests/PHPUnit/UITest.php +++ b/tests/PHPUnit/UITest.php @@ -49,7 +49,7 @@ abstract class UITest extends IntegrationTestCase DbHelper::createAnonymousUser(); - AssetManager::removeMergedAssets(); + AssetManager::getInstance()->removeMergedAssets(); // launch archiving so tests don't run out of time Rules::$purgeDisabledByTests = true; -- cgit v1.2.3