PluginProbe
WP Super Minify • Minify, Compress and Cache HTML, CSS & JavaScript / trunk
WP Super Minify • Minify, Compress and Cache HTML, CSS & JavaScript vtrunk
trunk 1.0 1.1 1.2 1.3 1.3.1 1.3.2 1.4 1.5 1.5.1 1.6 2.0 2.0.1
wp-super-minify / includes / min / lib / Minify / Source / Factory.php

Factory.php in WP Super Minify • Minify, Compress and Cache HTML, CSS & JavaScript trunk, at includes/min/lib/Minify/Source/Factory.php

198 lines 6.7 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 class Minify_Source_Factory
4 {
5
6 /**
7 * @var array
8 */
9 protected $options;
10
11 /**
12 * @var callable[]
13 */
14 protected $handlers = array();
15
16 /**
17 * @var Minify_Env
18 */
19 protected $env;
20
21 /**
22 * @param Minify_Env $env
23 * @param array $options
24 *
25 * noMinPattern : Pattern matched against basename of the filepath (if present). If the pattern
26 * matches, Minify will try to avoid re-compressing the resource.
27 *
28 * fileChecker : Callable responsible for verifying the existence of the file.
29 *
30 * resolveDocRoot : If true, a leading "//" will be replaced with the document root.
31 *
32 * checkAllowDirs : If true, the filepath will be verified to be within one of the directories
33 * specified by allowDirs.
34 *
35 * allowDirs : Directory paths in which sources can be served.
36 *
37 * uploaderHoursBehind : How many hours behind are the file modification times of uploaded files?
38 * If you upload files from Windows to a non-Windows server, Windows may report
39 * incorrect mtimes for the files. Immediately after modifying and uploading a
40 * file, use the touch command to update the mtime on the server. If the mtime
41 * jumps ahead by a number of hours, set this variable to that number. If the mtime
42 * moves back, this should not be needed.
43 *
44 * @param Minify_CacheInterface $cache Optional cache for handling .less files.
45 *
46 */
47 public function __construct(Minify_Env $env, array $options = array(), ?Minify_CacheInterface $cache = null)
48 {
49 $this->env = $env;
50 $this->options = array_merge(array(
51 'noMinPattern' => '@[-\\.]min\\.(?:[a-zA-Z]+)$@i', // matched against basename
52 'fileChecker' => array($this, 'checkIsFile'),
53 'resolveDocRoot' => true,
54 'checkAllowDirs' => true,
55 'allowDirs' => array('//'),
56 'uploaderHoursBehind' => 0,
57 ), $options);
58
59 // resolve // in allowDirs
60 $docRoot = $env->getDocRoot();
61 foreach ($this->options['allowDirs'] as $i => $dir) {
62 if (0 === strpos($dir, '//')) {
63 $this->options['allowDirs'][$i] = $docRoot . substr($dir, 1);
64 }
65 }
66
67 if ($this->options['fileChecker'] && !is_callable($this->options['fileChecker'])) {
68 throw new InvalidArgumentException("fileChecker option is not callable");
69 }
70
71 $this->setHandler('~\.less$~i', function ($spec) use ($cache) {
72 return new Minify_LessCssSource($spec, $cache);
73 });
74
75 $this->setHandler('~\.scss~i', function ($spec) use ($cache) {
76 return new Minify_ScssCssSource($spec, $cache);
77 });
78
79 $this->setHandler('~\.(js|css)$~i', function ($spec) {
80 return new Minify_Source($spec);
81 });
82 }
83
84 /**
85 * @param string $basenamePattern A pattern tested against basename. E.g. "~\.css$~"
86 * @param callable $handler Function that recieves a $spec array and returns a Minify_SourceInterface
87 */
88 public function setHandler($basenamePattern, $handler)
89 {
90 $this->handlers[$basenamePattern] = $handler;
91 }
92
93 /**
94 * @param string $file
95 * @return string
96 *
97 * @throws Minify_Source_FactoryException
98 */
99 public function checkIsFile($file)
100 {
101 $realpath = realpath($file);
102 if (!$realpath) {
103 throw new Minify_Source_FactoryException("File failed realpath(): $file");
104 }
105
106 $basename = basename($file);
107 if (0 === strpos($basename, '.')) {
108 throw new Minify_Source_FactoryException("Filename starts with period (may be hidden): $basename");
109 }
110
111 if (!is_file($realpath) || !is_readable($realpath)) {
112 throw new Minify_Source_FactoryException("Not a file or isn't readable: $file");
113 }
114
115 return $realpath;
116 }
117
118 /**
119 * @param mixed $spec
120 *
121 * @return Minify_SourceInterface
122 *
123 * @throws Minify_Source_FactoryException
124 */
125 public function makeSource($spec)
126 {
127 if (is_string($spec)) {
128 $spec = array(
129 'filepath' => $spec,
130 );
131 } elseif ($spec instanceof Minify_SourceInterface) {
132 return $spec;
133 }
134
135 $source = null;
136
137 if (empty($spec['filepath'])) {
138 // not much we can check
139 return new Minify_Source($spec);
140 }
141
142 if ($this->options['resolveDocRoot'] && 0 === strpos($spec['filepath'], '//')) {
143 $spec['filepath'] = $this->env->getDocRoot() . substr($spec['filepath'], 1);
144 }
145
146 if (!empty($this->options['fileChecker'])) {
147 $spec['filepath'] = call_user_func($this->options['fileChecker'], $spec['filepath']);
148 }
149
150 if ($this->options['checkAllowDirs']) {
151 $allowDirs = (array)$this->options['allowDirs'];
152 $inAllowedDir = false;
153 $filePath = $this->env->normalizePath($spec['filepath']);
154 foreach ($allowDirs as $allowDir) {
155 if (strpos($filePath, $this->env->normalizePath($allowDir)) === 0) {
156 $inAllowedDir = true;
157 }
158 }
159
160 if (!$inAllowedDir) {
161 $allowDirsStr = implode(';', $allowDirs);
162 throw new Minify_Source_FactoryException("File '{$spec['filepath']}' is outside \$allowDirs "
163 . "($allowDirsStr). If the path is resolved via an alias/symlink, look into the "
164 . "\$min_symlinks option.");
165 }
166 }
167
168 $basename = basename($spec['filepath']);
169
170 if ($this->options['noMinPattern'] && preg_match($this->options['noMinPattern'], $basename)) {
171 if (preg_match('~\.(css|less)$~i', $basename)) {
172 $spec['minifyOptions']['compress'] = false;
173 // we still want URI rewriting to work for CSS
174 } else {
175 $spec['minifier'] = 'Minify::nullMinifier';
176 }
177 }
178
179 $hoursBehind = $this->options['uploaderHoursBehind'];
180 if ($hoursBehind != 0) {
181 $spec['uploaderHoursBehind'] = $hoursBehind;
182 }
183
184 foreach ($this->handlers as $basenamePattern => $handler) {
185 if (preg_match($basenamePattern, $basename)) {
186 $source = call_user_func($handler, $spec);
187 break;
188 }
189 }
190
191 if (!$source) {
192 throw new Minify_Source_FactoryException("Handler not found for file: $basename");
193 }
194
195 return $source;
196 }
197 }
198