public static function hostfile($hostfile) { $config = csscrush::$config; $options = csscrush::$options; $regex = csscrush::$regex; // Keep track of all import file info for later logging $mtimes = array(); $filenames = array(); // Determine input; string or file // Extract the comments then strings $stream = isset($hostfile->string) ? $hostfile->string : file_get_contents($hostfile->path); // If there's a prepend file, prepend it if ($prependFile = csscrush_util::find('Prepend-local.css', 'Prepend.css')) { $stream = file_get_contents($prependFile) . $stream; } $stream = csscrush::extractComments($stream); $stream = csscrush::extractStrings($stream); // This may be set non-zero during the script if an absolute URL is encountered $searchOffset = 0; // Recurses until the nesting heirarchy is flattened and all files are combined while (preg_match($regex->import, $stream, $match, PREG_OFFSET_CAPTURE, $searchOffset)) { $fullMatch = $match[0][0]; // Full match $matchStart = $match[0][1]; // Full match offset $matchEnd = $matchStart + strlen($fullMatch); $mediaContext = trim($match[2][0]); // The media context if specified $preStatement = substr($stream, 0, $matchStart); $postStatement = substr($stream, $matchEnd); // If just stripping the import statements if (isset($hostfile->importIgnore)) { $stream = $preStatement . $postStatement; continue; } $url = trim($match[1][0]); // Url may be a string token if (preg_match($regex->token->string, $url)) { $import_url_token = new csscrush_string($url); $url = $import_url_token->value; // $import_url_token = csscrush::$storage->tokens->strings[ $url ]; // $url = trim( $import_url_token, '\'"' ); } // csscrush::log( $url ); // Pass over absolute urls // Move the search pointer forward if (preg_match($regex->absoluteUrl, $url)) { $searchOffset = $matchEnd; continue; } // Create import object $import = new stdClass(); $import->url = $url; $import->mediaContext = $mediaContext; $import->hostDir = $hostfile->dir; // Check to see if the url is root relative // Flatten import path for convenience if (strpos($import->url, '/') === 0) { $import->path = realpath($config->docRoot . $import->url); } else { $import->path = realpath("{$hostfile->dir}/{$import->url}"); } $import->content = @file_get_contents($import->path); // Failed to open import, just continue with the import line removed if (!$import->content) { csscrush::log("Import file '{$import->url}' not found"); $stream = $preStatement . $postStatement; continue; } else { // Start with extracting comments in the import $import->content = csscrush::extractComments($import->content); $import->dir = dirname($import->url); // Store import file info for cache validation $mtimes[] = filemtime($import->path); $filenames[] = $import->url; // Alter all the url strings to be paths relative to the hostfile: // Match all @import statements in the import content // Store the replacements we might find $matchCount = preg_match_all($regex->import, $import->content, $matchAll, PREG_OFFSET_CAPTURE); $replacements = array(); for ($index = 0; $index < $matchCount; $index++) { $fullMatch = $matchAll[0][$index][0]; $urlMatch = $matchAll[1][$index][0]; $search = $urlMatch; $replace = "{$import->dir}/{$urlMatch}"; // Try to resolve absolute paths // On failure strip the @import statement if (strpos($urlMatch, '/') === 0) { $replace = self::resolveAbsolutePath($urlMatch); if (!$replace) { $search = $fullMatch; $replace = ''; } } // Trim the statement and set the resolved path $statement = trim(str_replace($search, $replace, $fullMatch)); // Normalise import statement to be without url() syntax: // This is so relative urls can easily be targeted later $statement = self::normalizeImportStatement($statement); $replacements[$fullMatch] = $statement; } // If we've stored any altered @import strings then we need to apply them if (count($replacements)) { $import->content = str_replace(array_keys($replacements), array_values($replacements), $import->content); } // Now @import urls have been adjusted extract strings $import->content = csscrush::extractStrings($import->content); // Optionally rewrite relative url and custom function data-uri references if ($options['rewrite_import_urls']) { $import->content = self::rewriteImportRelativeUrls($import); } // Add media context if it exists if ($import->mediaContext) { $import->content = "@media {$import->mediaContext} {" . $import->content . '}'; } $stream = $preStatement . $import->content . $postStatement; } } // End while // Save only if the hostfile object is associated with a real file if ($hostfile->path) { self::save(array('imports' => $filenames, 'datem_sum' => array_sum($mtimes) + $hostfile->mtime, 'options' => $options)); } return $stream; }