scripts[$path] = 1; } else { Kohana_Log::add("error", "Can't find script file: $file"); } } /** * Provide a url to a resource within the current theme. This allows us to refer to theme * resources without naming the theme itself which makes themes easier to copy. */ public function url($path, $absolute_url=false) { $arg = "themes/{$this->theme_name}/$path"; return $absolute_url ? url::abs_file($arg) : url::file($arg); } /** * Add a css file to the combined css list. * @param $file the file name or path of the script to include. If a path is specified then * it needs to be relative to DOCROOT. Just specifying a file name will result * in searching Kohana's cascading file system. */ public function css($file) { if (($path = gallery::find_file("css", $file, false))) { $this->css[$path] = 1; } else { Kohana_Log::add("error", "Can't find css file: $file"); } } /** * Combine a series of files into a single one and cache it in the database. */ protected function combine_files($paths, $type) { $links = array(); if (empty($paths)) { return; } // Include the url in the cache key so that if the Gallery moves, we don't use old cached // entries. $key = array(url::abs_file("")); foreach (array_keys($paths) as $path) { $stats = stat($path); // 7 == size, 9 == mtime, see http://php.net/stat $key[] = "$path $stats[7] $stats[9]"; } $key = md5(join(" ", $key)); $cache = Cache::instance(); $contents = $cache->get($key); if (empty($contents)) { $contents = ""; foreach (array_keys($paths) as $path) { if ($type == "css") { $contents .= "/* $path */\n" . $this->process_css($path) . "\n"; } else { $contents .= "/* $path */\n" . file_get_contents($path) . "\n"; } } $cache->set($key, $contents, array($type), 30 * 84600); $use_gzip = function_exists("gzencode") && (int) ini_get("zlib.output_compression") === 0; if ($use_gzip) { $cache->set("{$key}_gz", gzencode($contents, 9, FORCE_GZIP), array($type, "gzip"), 30 * 84600); } } if ($type == "css") { return "\n" . html::stylesheet("combined/css/$key", "screen,print,projection", true); } else { return "\n" . html::script("combined/javascript/$key", true); } } /** * Convert relative references inside a CSS file to absolute ones so that when it's served from * a new location as part of a combined bundle the references are still correct. * @param string the path to the css file */ private function process_css($css_file) { static $PATTERN = "#url\(\s*['|\"]{0,1}(.*?)['|\"]{0,1}\s*\)#"; $docroot_length = strlen(DOCROOT); $css = file_get_contents($css_file); if (preg_match_all($PATTERN, $css, $matches, PREG_SET_ORDER)) { $search = $replace = array(); foreach ($matches as $match) { $relative = dirname($css_file) . "/$match[1]"; if (!empty($relative)) { $search[] = $match[0]; $replace[] = "url('" . url::abs_file($relative) . "')"; } else { Kohana_Log::add("error", "Missing URL reference '{$match[1]}' in CSS file '$css_file'"); } } $replace = str_replace(DIRECTORY_SEPARATOR, "/", $replace); $css = str_replace($search, $replace, $css); } $imports = preg_match_all("#@import\s*['|\"]{0,1}(.*?)['|\"]{0,1};#", $css, $matches, PREG_SET_ORDER); if ($imports) { $search = $replace = array(); foreach ($matches as $match) { $search[] = $match[0]; $replace[] = $this->process_css(dirname($css_file) . "/$match[1]"); } $css = str_replace($search, $replace, $css); } return $css; } }