summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authoremkael <emkael@tlen.pl>2016-04-29 14:36:48 +0200
committeremkael <emkael@tlen.pl>2016-04-29 14:36:48 +0200
commit19bae03b6f86776599d0f95b521d739ba66d5e76 (patch)
tree1a6de6110fd1dc0aeadc8032e5bff600d0f56669
parent85f4c67f0843e5f5ad0260097efb385565daf5a2 (diff)
* CSS minification in client script manager
-rw-r--r--app/php/web/ClientScriptManager.php220
1 files changed, 215 insertions, 5 deletions
diff --git a/app/php/web/ClientScriptManager.php b/app/php/web/ClientScriptManager.php
index 749bbcc..2dab6e9 100644
--- a/app/php/web/ClientScriptManager.php
+++ b/app/php/web/ClientScriptManager.php
@@ -16,11 +16,14 @@ class ClientScriptManager extends TClientScriptManager {
private function _getBasePaths($urls) {
$basePath = $this->_getBasePath();
- return array_map(
- function($path) use($basePath) {
- return $basePath . DIRECTORY_SEPARATOR . $path;
- },
- $urls
+ return array_combine(
+ $urls,
+ array_map(
+ function($path) use($basePath) {
+ return $basePath . DIRECTORY_SEPARATOR . $path;
+ },
+ $urls
+ )
);
}
@@ -247,6 +250,213 @@ class ClientScriptManager extends TClientScriptManager {
return parent::registerHeadScriptFile($key, $file);
}
+ // Stylesheets
+
+ private $_renderedSheetsInitialized = FALSE;
+
+ private function _getRenderedSheets() {
+ $sessionKey = $this->_getRenderedSheetsStoreKey();
+ if ($this->_page->IsCallBack || $this->_renderedSheetsInitialized) {
+ return $this->_getCache()->get($sessionKey) ?: [];
+ } else {
+ $this->_getCache()->delete($sessionKey);
+ $this->_renderedSheetsInitialized = TRUE;
+ return [];
+ }
+ }
+
+ private function _appendRenderedSheets(array $newSheets, $compiledFileKey) {
+ $sheets = $this->_getRenderedSheets();
+ if (!isset($sheets[$compiledFileKey])) {
+ $sheets[$compiledFileKey] = [];
+ }
+ $sheets[$compiledFileKey] = array_merge(
+ $sheets[$compiledFileKey],
+ $newSheets
+ );
+ $this->_getCache()->set(
+ $this->_getRenderedSheetsStoreKey(),
+ $sheets
+ );
+ }
+
+ private function _fixStyleSheetPaths($content, $originalUrl) {
+ $originalDir = dirname($originalUrl);
+ return preg_replace_callback(
+ '/url\s*\([\'"]?(.*?)[\'"]?\)/',
+ function($matches) use($originalDir) {
+ $url = parse_url($matches[1]);
+ if (isset($url['scheme']) || isset($url['host'])) {
+ return $matches[0];
+ }
+ return str_replace(
+ $matches[1],
+ $originalDir . '/' . $matches[1],
+ $matches[0]
+ );
+ },
+ $content
+ );
+ }
+
+ private function _compileSheetFiles($files) {
+ $paths = $this->_getBasePaths(
+ array_map('reset', $files)
+ );
+ $cacheKey = $this->_getFileCollectionCacheKey($paths);
+ $cacheFile = $this->_getCacheFilePath($cacheKey . '.css', 'styles');
+ $this->_appendRenderedSheets($files, $cacheFile);
+ if (!file_exists($cacheFile)
+ || (filemtime($cacheFile)
+ < $this->_getFileCollectionMTime($paths))) {
+ Prado::using('Lib.cssmin.CssMin');
+ $styleContent = implode(
+ PHP_EOL,
+ array_map(
+ function($origPath, $path) {
+ return trim(
+ CssMin::minify(
+ $this->_fixStyleSheetPaths(
+ file_get_contents($path),
+ $origPath
+ )
+ )
+ );
+ },
+ array_keys($paths),
+ $paths
+ )
+ );
+ file_put_contents($cacheFile, $styleContent);
+ }
+ return $this->Application->AssetManager->publishFilePath($cacheFile);
+ }
+
+ private function _determineLocalSheetFiles($files) {
+ $basePath = $this->_getBasePath();
+ return array_filter(
+ $files,
+ function($file) use($basePath) {
+ return file_exists($basePath . DIRECTORY_SEPARATOR . $file[0]);
+ }
+ );
+ }
+
+ private function _renderSheetFileTag(THtmlWriter $writer, $href, $media) {
+ $writer->addAttribute('rel', 'stylesheet');
+ $writer->addAttribute('type', 'text/css');
+ $writer->addAttribute('media', $media);
+ $writer->addAttribute('href', $href);
+ $writer->renderBeginTag('link');
+ $writer->write(PHP_EOL);
+ }
+
+ private function _renderLocalSheetFiles(THtmlWriter $writer, $localFiles) {
+ if ($localFiles) {
+ $fileTypes = [];
+ foreach ($localFiles as $file) {
+ $type = $file[1] ?: 'all';
+ if (!isset($fileTypes[$type])) {
+ $fileTypes[$type] = [];
+ }
+ $fileTypes[$type][] = $file;
+ }
+ foreach ($fileTypes as $type => $files) {
+ $assetPath = $this->_compileSheetFiles($files);
+ $this->_renderSheetFileTag($writer, $assetPath, $type);
+ }
+ }
+ }
+
+ private function _renderExternalSheetFiles(THtmlWriter $writer, $externalFiles) {
+ if ($externalFiles) {
+ foreach ($externalFiles as $file) {
+ $this->_appendRenderedSheets([$file], $file[0]);
+ $this->_renderSheetFileTag($writer, $file[0], $file[1] ?: 'all');
+ }
+ }
+ }
+
+ public function renderStyleSheetFiles($writer) {
+ if ($this->getApplication()->getMode() !== TApplicationMode::Debug) {
+ $files = $this->_styles;
+ if ($files) {
+ $localFiles = $this->_determineLocalSheetFiles($files);
+ $this->_renderLocalSheetFiles($writer, $localFiles);
+ $externalFiles = array_diff_key($files, $localFiles);
+ $this->_renderExternalSheetFiles($writer, $externalFiles);
+ }
+ } else {
+ parent::renderStyleSheetFiles($writer);
+ }
+ }
+
+ private function _getRenderedSheetUrl($registeredSheet) {
+ $renderedSheets = $this->_getRenderedSheets();
+ foreach ($renderedSheets as $compiledFile => $sheets) {
+ foreach ($sheets as $sheet) {
+ if ($registeredSheet[0] == $sheet[0]) {
+ if (file_exists($compiledFile)) {
+ return $this->Application->AssetManager->getPublishedUrl(
+ $compiledFile
+ );
+ } else {
+ return $registeredSheet[0];
+ }
+ }
+ }
+ }
+ return FALSE;
+ }
+
+ public function getStyleSheetUrls() {
+ if ($this->getApplication()->getMode() !== TApplicationMode::Debug) {
+ $registeredSheets = $this->_styles;
+ $sheetUrls = [];
+ $newSheets = [];
+ foreach ($registeredSheets as $registeredSheet) {
+ $renderedSheetUrl = $this->_getRenderedSheetUrl(
+ $registeredSheet
+ );
+ if ($renderedSheetUrl) {
+ $sheetUrls[] = $renderedSheetUrl;
+ } else {
+ $newSheets[] = $registeredSheet;
+ }
+ }
+ $newLocalSheets = $this->_determineLocalSheetFiles($newSheets);
+ $newLocalUrls = array_map('reset', $newLocalSheets);
+ $newRemoteSheets = array_filter(
+ $newSheets,
+ function($sheet) use($newLocalUrls) {
+ return !in_array($sheet[0], $newLocalUrls);
+ }
+ );
+ $newRemoteUrls = array_map('reset', $newRemoteSheets);
+ if ($newLocalSheets) {
+ $sheetUrls[] = $this->_compileSheetFiles($newLocalSheets);
+ }
+ $sheetUrls = array_values(
+ array_unique(array_merge($sheetUrls, $newRemoteUrls))
+ );
+ return $sheetUrls;
+ }
+ return parent::getStyleSheetUrls();
+ }
+
+ private $_styles = [];
+ private $_themeStyles = [];
+
+ public function registerStyleSheetFile($key, $file, $media = '') {
+ $this->_styles[$key] = [$file, $media];
+ return parent::registerStyleSheetFile($key, $file, $media);
+ }
+
+ public function registerThemeStyleSheetFile($key, $file, $media = '') {
+ $this->_themeStyles[$key] = $file;
+ return $this->registerStyleSheetFile($key, $file, $media);
+ }
+
}
?>