/** * See {@link combine_files()} * */ private function _process_combined_files($type) { // Make a map of files that could be potentially combined $combinerCheck = array(); foreach ($this->combine_files[$type] as $combinedFile => $sourceItems) { foreach ($sourceItems as $id => $sourceItem) { if (isset($combinerCheck[$sourceItem]) && $combinerCheck[$sourceItem] != $combinedFile) { Kohana::log('alert', "Requirements_Backend::process_combined_files - file '{$sourceItem}' appears in two combined files:" . " '{$combinerCheck[$sourceItem]}' and '{$combinedFile}'"); } $combinerCheck[$sourceItem] = $combinedFile; $combinerCheck[$id] = $combinedFile; } } // Work out the relative URL for the combined files from the base folder $combinedFilesFolder = $this->getCombinedFilesFolder() ? $this->getCombinedFilesFolder() . '/' : ''; // Figure out which ones apply to this pageview $combinedFiles = array(); $newRequirements = array(); foreach ($this->{$type} as $id => $params) { $file = $type == 'js' ? $params : $params['file']; if (isset($combinerCheck[$file])) { $newRequirements[$combinerCheck[$file]] = $type == 'js' ? $combinedFilesFolder . $combinerCheck[$file] : array('file' => $combinedFilesFolder . $combinerCheck[$file]); $combinedFiles[$combinerCheck[$file]] = true; } elseif (isset($combinerCheck[$id])) { $newRequirements[$combinerCheck[$id]] = $type == 'js' ? $combinedFilesFolder . $combinerCheck[$id] : array('file' => $combinedFilesFolder . $combinerCheck[$id]); $combinedFiles[$combinerCheck[$id]] = true; } else { $newRequirements[$id] = $params; } } // Process the combined files $base = DOCROOT; foreach (array_diff_key($combinedFiles, $this->blocked) as $combinedFile => $dummy) { $fileList = $this->combine_files[$type][$combinedFile]; $combinedFilePath = $base . $combinedFilesFolder . $combinedFile; // Check for RTL alternatives if ($type == 'css' and ush_locale::is_rtl_language()) { $has_rtl_files = FALSE; foreach ($fileList as $index => $file) { $rtlFile = substr($file, 0, strpos($file, ".{$type}")) . "-rtl" . substr($file, strpos($file, ".{$type}")); if (file_exists(DOCROOT . $rtlFile)) { $fileList[$index] = $rtlFile; $has_rtl_files = TRUE; } } // Update combined files details, only if the include RTL alternatives // We store the RTL version separate from the LTR version, so we don't regenerate every time someone changes language if ($has_rtl_files) { $combinedFile = substr($combinedFile, 0, -4) . '-rtl.css'; $combinedFilePath = $base . $combinedFilesFolder . $combinedFile; $newRequirements[$combinedFile] = $type == 'js' ? $combinedFilesFolder . $combinedFile : array('file' => $combinedFilesFolder . $combinedFile); } } // Make the folder if necessary if (!file_exists(dirname($combinedFilePath))) { mkdir(dirname($combinedFilePath)); } // If the file isn't writebale, don't even bother trying to make the combined file // Complex test because is_writable fails if the file doesn't exist yet. if (file_exists($combinedFilePath) && !is_writable($combinedFilePath) || !file_exists($combinedFilePath) && !is_writable(dirname($combinedFilePath))) { Kohana::log('alert', "Requirements_Backend::process_combined_files(): Couldn't create '{$combinedFilePath}'"); continue; } // Determine if we need to build the combined include if (file_exists($combinedFilePath) && !isset($_GET['flush'])) { // file exists, check modification date of every contained file $srcLastMod = 0; foreach ($fileList as $file) { $srcLastMod = max(filemtime($base . $file), $srcLastMod); } $refresh = $srcLastMod > filemtime($combinedFilePath); } else { // file doesn't exist, or refresh was explicitly required $refresh = true; } if (!$refresh) { continue; } $combinedData = ""; foreach (array_diff($fileList, $this->blocked) as $id => $file) { $fileContent = file_get_contents($base . $file); // if we have a javascript file and jsmin is enabled, minify the content if ($type == 'js' && $this->combine_js_with_jsmin) { $fileContent = JSMin::minify($fileContent); } if ($type == 'css') { // Rewrite urls in css to be relative to the docroot // Docroot param needs to be actual server docroot, not root of ushahidi site. // Using $_SERVER['DOCUMENT_ROOT']. Should possibly use DOCROOT, but remove Kohana::config('core.site_domain', TRUE); $fileContent = Minify_CSS_UriRewriter::rewrite($fileContent, pathinfo($base . $file, PATHINFO_DIRNAME), $_SERVER['DOCUMENT_ROOT']); // compress css (if enabled) if ($this->combine_css_with_cssmin) { $fileContent = CSSmin::go($fileContent); } } // write a header comment for each file for easier identification and debugging // also the semicolon between each file is required for jQuery to be combinable properly $combinedData .= "/****** FILE: {$file} *****/\n" . $fileContent . "\n" . ($type == 'js' ? ';' : '') . "\n"; } $successfulWrite = false; $fh = fopen($combinedFilePath, 'wb'); if ($fh) { if (fwrite($fh, $combinedData) == strlen($combinedData)) { $successfulWrite = true; } fclose($fh); unset($fh); } // Should we push this to the CDN too? if (Kohana::config("cdn.cdn_store_dynamic_content") and Kohana::config("requirements.cdn_store_combined_files")) { $cdn_combined_path = cdn::upload($combinedFilesFolder . $combinedFile, FALSE); } // Unsuccessful write - just include the regular JS files, rather than the combined one if (!$successfulWrite) { Kohana::log('alert', "Requirements_Backend::process_combined_files(): Couldn't create '{$combinedFilePath}'"); continue; } } // @todo Alters the original information, which means you can't call this // method repeatedly - it will behave different on the second call! $this->{$type} = $newRequirements; }