Index: minify_helper.php =================================================================== --- minify_helper.php (revision 15331) +++ minify_helper.php (working copy) @@ -24,48 +24,39 @@ var $debugMode = false; /** - * Path to compress information file + * Folder, that contains produced CSS/JS files * * @var string + * @access protected */ - var $infoFile = ''; + protected $resourceFolder = ''; - /** - * Compress information - * - * @var Array - */ - var $compressInfo = Array (); - function MinifyHelper() { parent::kHelper(); $this->debugMode = $this->Application->isDebugMode(false); - $this->infoFile = WRITEABLE . '/cache/compress_info.txt'; - - if ( file_exists($this->infoFile) ) { - $this->compressInfo = unserialize( file_get_contents($this->infoFile) ); - } + $this->resourceFolder = WRITEABLE . '/cache'; } /** * When used as non-block tag, then compress given files and return url to result * - * @param Array $files + * @param Array $params * @return string + * @access public */ - function CompressScriptTag($params) + public function CompressScriptTag($params) { // put to queue - if (array_key_exists('to', $params)) { + if ( array_key_exists('to', $params) ) { $files = $this->Application->GetVar($params['to'], ''); $this->Application->SetVar($params['to'], $files . '|' . $params['files']); return ''; } - if (array_key_exists('from', $params)) { + if ( array_key_exists('from', $params) ) { // get from queue $files = $this->Application->GetVar($params['from']); } @@ -75,39 +66,37 @@ } $files = $this->_getTemplatePaths( array_map('trim', explode('|', $files)) ); - $extension = pathinfo($files[0], PATHINFO_EXTENSION); - $hash = ($this->debugMode ? 'd' : 'c') . '_' . $this->_getHash($files); - $file_mask = 'cache/' . $hash . '_%s.' . $extension; + if ( !$files ) { + trigger_error('No files specified for compression.', E_USER_NOTICE); - $was_compressed = array_key_exists($hash, $this->compressInfo); + return ''; + } - if ($was_compressed) { - $current_file = WRITEABLE . '/' . sprintf($file_mask, $this->compressInfo[$hash]); + $extension = pathinfo($files[0], PATHINFO_EXTENSION); + $save_as = isset($params['save_as']) ? $params['save_as'] : false; + $dst_file = $this->resourceFolder . DIRECTORY_SEPARATOR . ($this->debugMode ? 'd' : 'c') . '_'; - if (!file_exists($current_file)) { - // when info exists, but file doesn't -> re-compress - $was_compressed = false; - } - - if ($this->debugMode) { - // check if any of listed files was changed since compressed file was created (only, when in debug mode) - foreach ($files as $file) { - if (filemtime($file) > $this->compressInfo[$hash]) { - $was_compressed = false; - break; - } - } - } + if ( $save_as ) { + $dst_file .= $save_as . ( strpos($save_as, '.') === false ? '.' . $extension : '' ); } + else { + $dst_file .= $this->_getHash($files) . '.' . $extension; + } - if (!$was_compressed) { + $was_compressed = file_exists($dst_file); + + if ( !$was_compressed || ($this->debugMode && filemtime($dst_file) < $this->_getMaxFileDate($files)) ) { $string = ''; $path_length = strlen(FULL_PATH) + 1; foreach ($files as $file) { + if ( !file_exists($file) ) { + continue; + } + // add filename before for easier debugging - if ($this->debugMode) { + if ( $this->debugMode ) { $string .= '/* === File: ' . substr($file, $path_length) . ' === */' . "\n"; $string .= '/* ' . str_repeat('=', strlen(substr($file, $path_length)) + 14) . ' */' . "\n\n"; } @@ -116,36 +105,50 @@ $string .= file_get_contents($file) . "\n\n"; } - // remove previous version of compressed file - if (isset($current_file)) { - if (file_exists($current_file)) { - unlink($current_file); - } + // replace templates base + if ( isset($params['templates_base']) ) { + $templates_base = $params['templates_base']; } + else { + $templates_base = $this->Application->ProcessParsedTag('m', 'TemplatesBase', Array ()); + } - // replace templates base - $templates_base = $this->Application->ProcessParsedTag('m', 'TemplatesBase', Array ()); $templates_base = preg_replace('/^' . preg_quote($this->Application->BaseURL(), '/') . '/', BASE_PATH . '/', $templates_base); $string = str_replace('@templates_base@', rtrim($templates_base, '/'), $string); - // compress collected data - $this->compressInfo[$hash] = adodb_mktime(); - - if (!$this->debugMode) { + if ( !$this->debugMode ) { // don't compress merged js/css file in debug mode to allow js/css debugging $this->compressString($string, $extension); } // save compressed file - $fp = fopen(WRITEABLE . '/' . sprintf($file_mask, $this->compressInfo[$hash]), 'w'); - fwrite($fp, $string); - fclose($fp); + file_put_contents($dst_file, $string); + } - $this->_saveInfo(); + $file_helper =& $this->Application->recallObject('FileHelper'); + /* @var $file_helper FileHelper */ + + return $file_helper->pathToUrl($dst_file) . '?ts=' . adodb_date('Y-m-d_H:i:s', filemtime($dst_file)); + } + + /** + * Returns maximal modification date across given files + * + * @param Array $files + * @return int + * @access protected + */ + protected function _getMaxFileDate($files) + { + $ret = 0; + + foreach ($files as $file) { + if ( file_exists($file) ) { + $ret = max($ret, filemtime($file)); + } } - // got compressed file -> use it - return $this->Application->BaseURL( str_replace(DIRECTORY_SEPARATOR, '/', WRITEBALE_BASE)) . sprintf($file_mask, $this->compressInfo[$hash]); + return $ret; } /** @@ -153,8 +156,9 @@ * * @param Array $files * @return int + * @access protected */ - function _getHash($files) + protected function _getHash($files) { $hash = $files; @@ -169,25 +173,20 @@ } /** - * Saves file with compress information - * - */ - function _saveInfo() - { - $fp = fopen($this->infoFile, 'w'); - fwrite($fp, serialize($this->compressInfo)); - fclose($fp); - } - - /** * Deletes compression info file * * @todo also delete all listed there files + * @access public */ - function delete() + public function delete() { - if (file_exists($this->infoFile)) { - unlink($this->infoFile); + $iterator = new DirectoryIterator($this->resourceFolder); + /* @var $file_info DirectoryIterator */ + + foreach ($iterator as $file_info) { + if ( !$file_info->isDir() && preg_match('/^(c|d)_.*.(css|js)$/', $file_info->getFilename()) ) { + unlink( $file_info->getPathname() ); + } } } @@ -235,27 +234,56 @@ * * @param Array $templates * @return Array + * @access protected */ - function _getTemplatePaths($templates) + protected function _getTemplatePaths($templates) { $ret = Array (); $reg_exp = '/^' . preg_quote($this->Application->BaseURL(), '/') . '(.*)/'; foreach ($templates as $template) { - if (!$template) { + if ( !$template ) { continue; } - if (preg_match($reg_exp, $template, $regs)) { + if ( preg_match($reg_exp, $template, $regs) ) { // full url (from current domain) to a file - $path = FULL_PATH . '/' . $regs[1]; + $ret[] = FULL_PATH . '/' . $regs[1]; } + elseif ( strpos($template, '{module_path}') !== false ) { + $ret = array_merge($ret, $this->_moduleInclude($template)); + } else { - list ($path, $module_filename) = $this->Application->TemplatesCache->GetTemplatePaths($template); - $path .= DIRECTORY_SEPARATOR . $module_filename; + $ret[] = $this->Application->TemplatesCache->GetRealFilename($template); } + } - $ret[] = $path; + return $ret; + } + + /** + * + * @param string $template + * @return Array + * @access protected + */ + protected function _moduleInclude($template) + { + $ret = $included = Array (); + + foreach ($this->Application->ModuleInfo as $module_name => $module_data) { + if ( $module_name == 'In-Portal' ) { + continue; + } + + $module_prefix = $this->Application->isAdmin ? mb_strtolower($module_name) . '/' : $module_data['TemplatePath']; + + if ( in_array($module_prefix, $included) ) { + continue; + } + + $ret[] = $this->Application->TemplatesCache->GetRealFilename(str_replace('{module_path}', $module_prefix, $template)); + $included[] = $module_prefix; } return $ret;