namibia
df0489e1eeeeab5a9bd44e1d84fce49924fe1bac
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 |
<?php /** * Class Minify_ImportProcessor * @package Minify */ /** * Linearize a CSS/JS file by including content specified by CSS import * declarations. In CSS files, relative URIs are fixed. * * @imports will be processed regardless of where they appear in the source * files; i.e. @imports commented out or in string content will still be * processed! * * This has a unit test but should be considered "experimental". * * @package Minify * @author Stephen Clay <steve@mrclay.org> * @author Simon Schick <simonsimcity@gmail.com> */ class Minify_ImportProcessor { public static $filesIncluded = array(); public static function process($file) { self::$filesIncluded = array(); self::$_isCss = (strtolower(substr($file, -4)) === '.css'); $obj = new Minify_ImportProcessor(dirname($file)); return $obj->_getContent($file); } // allows callback funcs to know the current directory private $_currentDir = null; // allows callback funcs to know the directory of the file that inherits this one private $_previewsDir = null; // allows _importCB to write the fetched content back to the obj private $_importedContent = ''; private static $_isCss = null; /** * @param String $currentDir * @param String $previewsDir Is only used internally */ private function __construct($currentDir, $previewsDir = "") { $this->_currentDir = $currentDir; $this->_previewsDir = $previewsDir; } private function _getContent($file, $is_imported = false) { $file = realpath($file); if (! $file || in_array($file, self::$filesIncluded) || false === ($content = @file_get_contents($file)) ) { // file missing, already included, or failed read return ''; } self::$filesIncluded[] = realpath($file); $this->_currentDir = dirname($file); // remove UTF-8 BOM if present if (pack("CCC",0xef,0xbb,0xbf) === substr($content, 0, 3)) { $content = substr($content, 3); } // ensure uniform EOLs $content = str_replace("\r\n", "\n", $content); // process @imports $content = preg_replace_callback( '/ @import\\s+ (?:url\\(\\s*)? # maybe url( [\'"]? # maybe quote (.*?) # 1 = URI [\'"]? # maybe end quote (?:\\s*\\))? # maybe ) ([a-zA-Z,\\s]*)? # 2 = media list ; # end token /x' ,array($this, '_importCB') ,$content ); // You only need to rework the import-path if the script is imported if (self::$_isCss && $is_imported) { // rewrite remaining relative URIs $content = preg_replace_callback( '/url\\(\\s*([^\\)\\s]+)\\s*\\)/' ,array($this, '_urlCB') ,$content ); } return $this->_importedContent . $content; } private function _importCB($m) { $url = $m[1]; $mediaList = preg_replace('/\\s+/', '', $m[2]); if (strpos($url, '://') > 0) { // protocol, leave in place for CSS, comment for JS return self::$_isCss ? $m[0] : "/* Minify_ImportProcessor will not include remote content */"; } if ('/' === $url[0]) { // protocol-relative or root path $url = ltrim($url, '/'); $file = realpath($_SERVER['DOCUMENT_ROOT']) . DIRECTORY_SEPARATOR . strtr($url, '/', DIRECTORY_SEPARATOR); } else { // relative to current path $file = $this->_currentDir . DIRECTORY_SEPARATOR . strtr($url, '/', DIRECTORY_SEPARATOR); } $obj = new Minify_ImportProcessor(dirname($file), $this->_currentDir); $content = $obj->_getContent($file, true); if ('' === $content) { // failed. leave in place for CSS, comment for JS return self::$_isCss ? $m[0] : "/* Minify_ImportProcessor could not fetch '{$file}' */"; } return (!self::$_isCss || preg_match('@(?:^$|\\ball\\b)@', $mediaList)) ? $content : "@media {$mediaList} {\n{$content}\n}\n"; } private function _urlCB($m) { // $m[1] is either quoted or not $quote = ($m[1][0] === "'" || $m[1][0] === '"') ? $m[1][0] : ''; $url = ($quote === '') ? $m[1] : substr($m[1], 1, strlen($m[1]) - 2); if ('/' !== $url[0]) { if (strpos($url, '//') > 0) { // probably starts with protocol, do not alter } else { // prepend path with current dir separator (OS-independent) $path = $this->_currentDir . DIRECTORY_SEPARATOR . strtr($url, '/', DIRECTORY_SEPARATOR); // update the relative path by the directory of the file that imported this one $url = self::getPathDiff(realpath($this->_previewsDir), $path); } } return "url({$quote}{$url}{$quote})"; } /** * @param string $from * @param string $to * @param string $ps * @return string */ private function getPathDiff($from, $to, $ps = DIRECTORY_SEPARATOR) { $realFrom = $this->truepath($from); $realTo = $this->truepath($to); $arFrom = explode($ps, rtrim($realFrom, $ps)); $arTo = explode($ps, rtrim($realTo, $ps)); while (count($arFrom) && count($arTo) && ($arFrom[0] == $arTo[0])) { array_shift($arFrom); array_shift($arTo); } return str_pad("", count($arFrom) * 3, '..' . $ps) . implode($ps, $arTo); } /** * This function is to replace PHP's extremely buggy realpath(). * @param string $path The original path, can be relative etc. * @return string The resolved path, it might not exist. * @see http://stackoverflow.com/questions/4049856/replace-phps-realpath */ function truepath($path) { // whether $path is unix or not $unipath = strlen($path) == 0 || $path{0} != '/'; // attempts to detect if path is relative in which case, add cwd if (strpos($path, ':') === false && $unipath) $path = $this->_currentDir . DIRECTORY_SEPARATOR . $path; // resolve path parts (single dot, double dot and double delimiters) $path = str_replace(array('/', '\\'), DIRECTORY_SEPARATOR, $path); $parts = array_filter(explode(DIRECTORY_SEPARATOR, $path), 'strlen'); $absolutes = array(); foreach ($parts as $part) { if ('.' == $part) continue; if ('..' == $part) { array_pop($absolutes); } else { $absolutes[] = $part; } } $path = implode(DIRECTORY_SEPARATOR, $absolutes); // resolve any symlinks if (file_exists($path) && linkinfo($path) > 0) $path = readlink($path); // put initial separator that could have been lost $path = !$unipath ? '/' . $path : $path; return $path; } } |
Commits for namibiapublic/min/lib/Minify/ImportProcessor.php
Revision | Author | Commited | Message |
---|---|---|---|
df0489 ... | Mark | Fri 14 Oct, 2016 10:01:00 +0000 | initial commit |