diff options
Diffstat (limited to 'app/php')
-rw-r--r-- | app/php/web/ClientScriptManager.php | 220 |
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); + } + } ?> |