debugMode = $this->Application->isDebugMode(false); $this->resourceFolder = WRITEABLE . '/cache'; } /** * When used as non-block tag, then compress given files and return url to result * * @param Array $params * @return string * @access public */ public function CompressScriptTag($params) { // put to queue 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) ) { // get from queue $files = $this->Application->GetVar($params['from']); } else { // get from tag $files = $params['files']; } $files = $this->_getTemplatePaths( array_map('trim', explode('|', $files)) ); $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 ( $save_as ) { $dst_file .= $save_as . ( strpos($save_as, '.') === false ? '.' . $extension : '' ); } else { $dst_file .= $this->_getHash($files) . '.' . $extension; } $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) { // add filename before for easier debugging if ( $this->debugMode ) { $string .= '/* === File: ' . substr($file, $path_length) . ' === */' . "\n"; $string .= '/* ' . str_repeat('=', strlen(substr($file, $path_length)) + 14) . ' */' . "\n\n"; } // add file content $string .= file_get_contents($file) . "\n\n"; } // 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); 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 file_put_contents($dst_file, $string); } $file_helper =& $this->Application->recallObject('FileHelper'); /* @var $file_helper FileHelper */ return $file_helper->pathToUrl($dst_file) . '?ts=' . 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) { $ret = max($ret, filemtime($file)); } return $ret; } /** * Returns hash string based on given files * * @param Array $files * @return int * @access protected */ protected function _getHash($files) { $hash = $files; if ($this->Application->isAdmin) { array_unshift($hash, 'A:1'); } else { array_unshift($hash, 'A:0;T:' . $this->Application->GetVar('m_theme')); } return crc32( implode('|', $hash) ); } /** * Deletes compression info file * * @todo also delete all listed there files * @access public */ public function delete() { $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() ); } } } /** * Compress $string based on $extension * * @param string $string * @param string $extension * @return void * @access protected */ public function compressString(&$string, $extension) { $tmp_file = tempnam('/tmp', 'to_compress_'); $fp = fopen($tmp_file, 'w'); fwrite($fp, $string); fclose($fp); $command = 'java -jar ' . dirname(__FILE__) . DIRECTORY_SEPARATOR . 'yuicompressor-2.4.2.jar --type ' . $extension . ' --charset utf-8 ' . $tmp_file; $compressed_string = shell_exec($command); unlink($tmp_file); if (!is_null($compressed_string) && $compressed_string) { $string = $compressed_string; return ; } // failed to compress using YUICompressor (maybe java not installed) if ($extension == 'js') { $minifier =& $this->Application->makeClass('JsMinifyHelper'); /* @var $minifier JsMinifyHelper */ $string = $minifier->minify($string); } elseif ($extension == 'css') { $minifier =& $this->Application->makeClass('CssMinifyHelper'); /* @var $minifier CssMinifyHelper */ $string = $minifier->minify($string); } } /** * Get full paths on disk for each of given templates * * @param Array $templates * @return Array * @access protected */ protected function _getTemplatePaths($templates) { $ret = Array (); $reg_exp = '/^' . preg_quote($this->Application->BaseURL(), '/') . '(.*)/'; foreach ($templates as $template) { if ( !$template ) { continue; } if ( preg_match($reg_exp, $template, $regs) ) { // full url (from current domain) to a file $path = FULL_PATH . '/' . $regs[1]; } else { list ($path, $module_filename) = $this->Application->TemplatesCache->GetTemplatePaths($template); $path .= DIRECTORY_SEPARATOR . $module_filename; } $ret[] = $path; } return $ret; } }