Completed
Push — release-2.1 ( c71d4f...42c11a )
by John
06:53
created
index.php 1 patch
Spacing   +1 added lines, -1 removed lines patch added patch discarded remove patch
@@ -104,7 +104,7 @@
 block discarded – undo
104 104
  *
105 105
  * @param string $class The fully-qualified class name.
106 106
  */
107
-spl_autoload_register(function ($class) use ($sourcedir)
107
+spl_autoload_register(function($class) use ($sourcedir)
108 108
 {
109 109
 	$classMap = array(
110 110
 		'ReCaptcha\\' => 'ReCaptcha/',
Please login to merge, or discard this patch.
Sources/minify/path-converter/src/Converter.php 1 patch
Indentation   +169 added lines, -169 removed lines patch added patch discarded remove patch
@@ -18,178 +18,178 @@
 block discarded – undo
18 18
  */
19 19
 class Converter
20 20
 {
21
-    /**
22
-     * @var string
23
-     */
24
-    protected $from;
25
-
26
-    /**
27
-     * @var string
28
-     */
29
-    protected $to;
30
-
31
-    /**
32
-     * @param string $from The original base path (directory, not file!)
33
-     * @param string $to   The new base path (directory, not file!)
34
-     */
35
-    public function __construct($from, $to)
36
-    {
37
-        $shared = $this->shared($from, $to);
38
-        if ($shared === '') {
39
-            // when both paths have nothing in common, one of them is probably
40
-            // absolute while the other is relative
41
-            $cwd = getcwd();
42
-            $from = strpos($from, $cwd) === 0 ? $from : $cwd.'/'.$from;
43
-            $to = strpos($to, $cwd) === 0 ? $to : $cwd.'/'.$to;
44
-
45
-            // or traveling the tree via `..`
46
-            // attempt to resolve path, or assume it's fine if it doesn't exist
47
-            $from = realpath($from) ?: $from;
48
-            $to = realpath($to) ?: $to;
49
-        }
50
-
51
-        $from = $this->dirname($from);
52
-        $to = $this->dirname($to);
53
-
54
-        $from = $this->normalize($from);
55
-        $to = $this->normalize($to);
56
-
57
-        $this->from = $from;
58
-        $this->to = $to;
59
-    }
60
-
61
-    /**
62
-     * Normalize path.
63
-     *
64
-     * @param string $path
65
-     *
66
-     * @return string
67
-     */
68
-    protected function normalize($path)
69
-    {
70
-        // deal with different operating systems' directory structure
71
-        $path = rtrim(str_replace(DIRECTORY_SEPARATOR, '/', $path), '/');
72
-
73
-        /*
21
+	/**
22
+	 * @var string
23
+	 */
24
+	protected $from;
25
+
26
+	/**
27
+	 * @var string
28
+	 */
29
+	protected $to;
30
+
31
+	/**
32
+	 * @param string $from The original base path (directory, not file!)
33
+	 * @param string $to   The new base path (directory, not file!)
34
+	 */
35
+	public function __construct($from, $to)
36
+	{
37
+		$shared = $this->shared($from, $to);
38
+		if ($shared === '') {
39
+			// when both paths have nothing in common, one of them is probably
40
+			// absolute while the other is relative
41
+			$cwd = getcwd();
42
+			$from = strpos($from, $cwd) === 0 ? $from : $cwd.'/'.$from;
43
+			$to = strpos($to, $cwd) === 0 ? $to : $cwd.'/'.$to;
44
+
45
+			// or traveling the tree via `..`
46
+			// attempt to resolve path, or assume it's fine if it doesn't exist
47
+			$from = realpath($from) ?: $from;
48
+			$to = realpath($to) ?: $to;
49
+		}
50
+
51
+		$from = $this->dirname($from);
52
+		$to = $this->dirname($to);
53
+
54
+		$from = $this->normalize($from);
55
+		$to = $this->normalize($to);
56
+
57
+		$this->from = $from;
58
+		$this->to = $to;
59
+	}
60
+
61
+	/**
62
+	 * Normalize path.
63
+	 *
64
+	 * @param string $path
65
+	 *
66
+	 * @return string
67
+	 */
68
+	protected function normalize($path)
69
+	{
70
+		// deal with different operating systems' directory structure
71
+		$path = rtrim(str_replace(DIRECTORY_SEPARATOR, '/', $path), '/');
72
+
73
+		/*
74 74
          * Example:
75 75
          *     /home/forkcms/frontend/cache/compiled_templates/../../core/layout/css/../images/img.gif
76 76
          * to
77 77
          *     /home/forkcms/frontend/core/layout/images/img.gif
78 78
          */
79
-        do {
80
-            $path = preg_replace('/[^\/]+(?<!\.\.)\/\.\.\//', '', $path, -1, $count);
81
-        } while ($count);
82
-
83
-        return $path;
84
-    }
85
-
86
-    /**
87
-     * Figure out the shared path of 2 locations.
88
-     *
89
-     * Example:
90
-     *     /home/forkcms/frontend/core/layout/images/img.gif
91
-     * and
92
-     *     /home/forkcms/frontend/cache/minified_css
93
-     * share
94
-     *     /home/forkcms/frontend
95
-     *
96
-     * @param string $path1
97
-     * @param string $path2
98
-     *
99
-     * @return string
100
-     */
101
-    protected function shared($path1, $path2)
102
-    {
103
-        // $path could theoretically be empty (e.g. no path is given), in which
104
-        // case it shouldn't expand to array(''), which would compare to one's
105
-        // root /
106
-        $path1 = $path1 ? explode('/', $path1) : array();
107
-        $path2 = $path2 ? explode('/', $path2) : array();
108
-
109
-        $shared = array();
110
-
111
-        // compare paths & strip identical ancestors
112
-        foreach ($path1 as $i => $chunk) {
113
-            if (isset($path2[$i]) && $path1[$i] == $path2[$i]) {
114
-                $shared[] = $chunk;
115
-            } else {
116
-                break;
117
-            }
118
-        }
119
-
120
-        return implode('/', $shared);
121
-    }
122
-
123
-    /**
124
-     * Convert paths relative from 1 file to another.
125
-     *
126
-     * E.g.
127
-     *     ../images/img.gif relative to /home/forkcms/frontend/core/layout/css
128
-     * should become:
129
-     *     ../../core/layout/images/img.gif relative to
130
-     *     /home/forkcms/frontend/cache/minified_css
131
-     *
132
-     * @param string $path The relative path that needs to be converted.
133
-     *
134
-     * @return string The new relative path.
135
-     */
136
-    public function convert($path)
137
-    {
138
-        // quit early if conversion makes no sense
139
-        if ($this->from === $this->to) {
140
-            return $path;
141
-        }
142
-
143
-        $path = $this->normalize($path);
144
-        // if we're not dealing with a relative path, just return absolute
145
-        if (strpos($path, '/') === 0) {
146
-            return $path;
147
-        }
148
-
149
-        // normalize paths
150
-        $path = $this->normalize($this->from.'/'.$path);
151
-
152
-        // strip shared ancestor paths
153
-        $shared = $this->shared($path, $this->to);
154
-        $path = mb_substr($path, mb_strlen($shared));
155
-        $to = mb_substr($this->to, mb_strlen($shared));
156
-
157
-        // add .. for every directory that needs to be traversed to new path
158
-        $to = str_repeat('../', mb_substr_count($to, '/'));
159
-
160
-        return $to.ltrim($path, '/');
161
-    }
162
-
163
-    /**
164
-     * Attempt to get the directory name from a path.
165
-     *
166
-     * @param string $path
167
-     *
168
-     * @return string
169
-     */
170
-    public function dirname($path)
171
-    {
172
-        if (is_file($path)) {
173
-            return dirname($path);
174
-        }
175
-
176
-        if (is_dir($path)) {
177
-            return rtrim($path, '/');
178
-        }
179
-
180
-        // no known file/dir, start making assumptions
181
-
182
-        // ends in / = dir
183
-        if (mb_substr($path, -1) === '/') {
184
-            return rtrim($path, '/');
185
-        }
186
-
187
-        // has a dot in the name, likely a file
188
-        if (preg_match('/.*\..*$/', basename($path)) !== 0) {
189
-            return dirname($path);
190
-        }
191
-
192
-        // you're on your own here!
193
-        return $path;
194
-    }
79
+		do {
80
+			$path = preg_replace('/[^\/]+(?<!\.\.)\/\.\.\//', '', $path, -1, $count);
81
+		} while ($count);
82
+
83
+		return $path;
84
+	}
85
+
86
+	/**
87
+	 * Figure out the shared path of 2 locations.
88
+	 *
89
+	 * Example:
90
+	 *     /home/forkcms/frontend/core/layout/images/img.gif
91
+	 * and
92
+	 *     /home/forkcms/frontend/cache/minified_css
93
+	 * share
94
+	 *     /home/forkcms/frontend
95
+	 *
96
+	 * @param string $path1
97
+	 * @param string $path2
98
+	 *
99
+	 * @return string
100
+	 */
101
+	protected function shared($path1, $path2)
102
+	{
103
+		// $path could theoretically be empty (e.g. no path is given), in which
104
+		// case it shouldn't expand to array(''), which would compare to one's
105
+		// root /
106
+		$path1 = $path1 ? explode('/', $path1) : array();
107
+		$path2 = $path2 ? explode('/', $path2) : array();
108
+
109
+		$shared = array();
110
+
111
+		// compare paths & strip identical ancestors
112
+		foreach ($path1 as $i => $chunk) {
113
+			if (isset($path2[$i]) && $path1[$i] == $path2[$i]) {
114
+				$shared[] = $chunk;
115
+			} else {
116
+				break;
117
+			}
118
+		}
119
+
120
+		return implode('/', $shared);
121
+	}
122
+
123
+	/**
124
+	 * Convert paths relative from 1 file to another.
125
+	 *
126
+	 * E.g.
127
+	 *     ../images/img.gif relative to /home/forkcms/frontend/core/layout/css
128
+	 * should become:
129
+	 *     ../../core/layout/images/img.gif relative to
130
+	 *     /home/forkcms/frontend/cache/minified_css
131
+	 *
132
+	 * @param string $path The relative path that needs to be converted.
133
+	 *
134
+	 * @return string The new relative path.
135
+	 */
136
+	public function convert($path)
137
+	{
138
+		// quit early if conversion makes no sense
139
+		if ($this->from === $this->to) {
140
+			return $path;
141
+		}
142
+
143
+		$path = $this->normalize($path);
144
+		// if we're not dealing with a relative path, just return absolute
145
+		if (strpos($path, '/') === 0) {
146
+			return $path;
147
+		}
148
+
149
+		// normalize paths
150
+		$path = $this->normalize($this->from.'/'.$path);
151
+
152
+		// strip shared ancestor paths
153
+		$shared = $this->shared($path, $this->to);
154
+		$path = mb_substr($path, mb_strlen($shared));
155
+		$to = mb_substr($this->to, mb_strlen($shared));
156
+
157
+		// add .. for every directory that needs to be traversed to new path
158
+		$to = str_repeat('../', mb_substr_count($to, '/'));
159
+
160
+		return $to.ltrim($path, '/');
161
+	}
162
+
163
+	/**
164
+	 * Attempt to get the directory name from a path.
165
+	 *
166
+	 * @param string $path
167
+	 *
168
+	 * @return string
169
+	 */
170
+	public function dirname($path)
171
+	{
172
+		if (is_file($path)) {
173
+			return dirname($path);
174
+		}
175
+
176
+		if (is_dir($path)) {
177
+			return rtrim($path, '/');
178
+		}
179
+
180
+		// no known file/dir, start making assumptions
181
+
182
+		// ends in / = dir
183
+		if (mb_substr($path, -1) === '/') {
184
+			return rtrim($path, '/');
185
+		}
186
+
187
+		// has a dot in the name, likely a file
188
+		if (preg_match('/.*\..*$/', basename($path)) !== 0) {
189
+			return dirname($path);
190
+		}
191
+
192
+		// you're on your own here!
193
+		return $path;
194
+	}
195 195
 }
Please login to merge, or discard this patch.
Sources/minify/src/CSS.php 2 patches
Indentation   +488 added lines, -488 removed lines patch added patch discarded remove patch
@@ -17,96 +17,96 @@  discard block
 block discarded – undo
17 17
  */
18 18
 class CSS extends Minify
19 19
 {
20
-    /**
21
-     * @var int
22
-     */
23
-    protected $maxImportSize = 5;
24
-
25
-    /**
26
-     * @var string[]
27
-     */
28
-    protected $importExtensions = array(
29
-        'gif' => 'data:image/gif',
30
-        'png' => 'data:image/png',
31
-        'jpe' => 'data:image/jpeg',
32
-        'jpg' => 'data:image/jpeg',
33
-        'jpeg' => 'data:image/jpeg',
34
-        'svg' => 'data:image/svg+xml',
35
-        'woff' => 'data:application/x-font-woff',
36
-        'tif' => 'image/tiff',
37
-        'tiff' => 'image/tiff',
38
-        'xbm' => 'image/x-xbitmap',
39
-    );
40
-
41
-    /**
42
-     * Set the maximum size if files to be imported.
43
-     *
44
-     * Files larger than this size (in kB) will not be imported into the CSS.
45
-     * Importing files into the CSS as data-uri will save you some connections,
46
-     * but we should only import relatively small decorative images so that our
47
-     * CSS file doesn't get too bulky.
48
-     *
49
-     * @param int $size Size in kB
50
-     */
51
-    public function setMaxImportSize($size)
52
-    {
53
-        $this->maxImportSize = $size;
54
-    }
55
-
56
-    /**
57
-     * Set the type of extensions to be imported into the CSS (to save network
58
-     * connections).
59
-     * Keys of the array should be the file extensions & respective values
60
-     * should be the data type.
61
-     *
62
-     * @param string[] $extensions Array of file extensions
63
-     */
64
-    public function setImportExtensions(array $extensions)
65
-    {
66
-        $this->importExtensions = $extensions;
67
-    }
68
-
69
-    /**
70
-     * Move any import statements to the top.
71
-     *
72
-     * @param string $content Nearly finished CSS content
73
-     *
74
-     * @return string
75
-     */
76
-    protected function moveImportsToTop($content)
77
-    {
78
-        if (preg_match_all('/@import[^;]+;/', $content, $matches)) {
79
-            // remove from content
80
-            foreach ($matches[0] as $import) {
81
-                $content = str_replace($import, '', $content);
82
-            }
83
-
84
-            // add to top
85
-            $content = implode('', $matches[0]).$content;
86
-        }
87
-
88
-        return $content;
89
-    }
90
-
91
-    /**
92
-     * Combine CSS from import statements.
93
-     *
94
-     * @import's will be loaded and their content merged into the original file,
95
-     * to save HTTP requests.
96
-     *
97
-     * @param string   $source  The file to combine imports for
98
-     * @param string   $content The CSS content to combine imports for
99
-     * @param string[] $parents Parent paths, for circular reference checks
100
-     *
101
-     * @return string
102
-     *
103
-     * @throws FileImportException
104
-     */
105
-    protected function combineImports($source, $content, $parents)
106
-    {
107
-        $importRegexes = array(
108
-            // @import url(xxx)
109
-            '/
20
+	/**
21
+	 * @var int
22
+	 */
23
+	protected $maxImportSize = 5;
24
+
25
+	/**
26
+	 * @var string[]
27
+	 */
28
+	protected $importExtensions = array(
29
+		'gif' => 'data:image/gif',
30
+		'png' => 'data:image/png',
31
+		'jpe' => 'data:image/jpeg',
32
+		'jpg' => 'data:image/jpeg',
33
+		'jpeg' => 'data:image/jpeg',
34
+		'svg' => 'data:image/svg+xml',
35
+		'woff' => 'data:application/x-font-woff',
36
+		'tif' => 'image/tiff',
37
+		'tiff' => 'image/tiff',
38
+		'xbm' => 'image/x-xbitmap',
39
+	);
40
+
41
+	/**
42
+	 * Set the maximum size if files to be imported.
43
+	 *
44
+	 * Files larger than this size (in kB) will not be imported into the CSS.
45
+	 * Importing files into the CSS as data-uri will save you some connections,
46
+	 * but we should only import relatively small decorative images so that our
47
+	 * CSS file doesn't get too bulky.
48
+	 *
49
+	 * @param int $size Size in kB
50
+	 */
51
+	public function setMaxImportSize($size)
52
+	{
53
+		$this->maxImportSize = $size;
54
+	}
55
+
56
+	/**
57
+	 * Set the type of extensions to be imported into the CSS (to save network
58
+	 * connections).
59
+	 * Keys of the array should be the file extensions & respective values
60
+	 * should be the data type.
61
+	 *
62
+	 * @param string[] $extensions Array of file extensions
63
+	 */
64
+	public function setImportExtensions(array $extensions)
65
+	{
66
+		$this->importExtensions = $extensions;
67
+	}
68
+
69
+	/**
70
+	 * Move any import statements to the top.
71
+	 *
72
+	 * @param string $content Nearly finished CSS content
73
+	 *
74
+	 * @return string
75
+	 */
76
+	protected function moveImportsToTop($content)
77
+	{
78
+		if (preg_match_all('/@import[^;]+;/', $content, $matches)) {
79
+			// remove from content
80
+			foreach ($matches[0] as $import) {
81
+				$content = str_replace($import, '', $content);
82
+			}
83
+
84
+			// add to top
85
+			$content = implode('', $matches[0]).$content;
86
+		}
87
+
88
+		return $content;
89
+	}
90
+
91
+	/**
92
+	 * Combine CSS from import statements.
93
+	 *
94
+	 * @import's will be loaded and their content merged into the original file,
95
+	 * to save HTTP requests.
96
+	 *
97
+	 * @param string   $source  The file to combine imports for
98
+	 * @param string   $content The CSS content to combine imports for
99
+	 * @param string[] $parents Parent paths, for circular reference checks
100
+	 *
101
+	 * @return string
102
+	 *
103
+	 * @throws FileImportException
104
+	 */
105
+	protected function combineImports($source, $content, $parents)
106
+	{
107
+		$importRegexes = array(
108
+			// @import url(xxx)
109
+			'/
110 110
             # import statement
111 111
             @import
112 112
 
@@ -151,8 +151,8 @@  discard block
 block discarded – undo
151 151
 
152 152
             /ix',
153 153
 
154
-            // @import 'xxx'
155
-            '/
154
+			// @import 'xxx'
155
+			'/
156 156
 
157 157
             # import statement
158 158
             @import
@@ -191,173 +191,173 @@  discard block
 block discarded – undo
191 191
             ;?
192 192
 
193 193
             /ix',
194
-        );
195
-
196
-        // find all relative imports in css
197
-        $matches = array();
198
-        foreach ($importRegexes as $importRegex) {
199
-            if (preg_match_all($importRegex, $content, $regexMatches, PREG_SET_ORDER)) {
200
-                $matches = array_merge($matches, $regexMatches);
201
-            }
202
-        }
203
-
204
-        $search = array();
205
-        $replace = array();
206
-
207
-        // loop the matches
208
-        foreach ($matches as $match) {
209
-            // get the path for the file that will be imported
210
-            $importPath = dirname($source).'/'.$match['path'];
211
-
212
-            // only replace the import with the content if we can grab the
213
-            // content of the file
214
-            if ($this->canImportFile($importPath)) {
215
-                // check if current file was not imported previously in the same
216
-                // import chain.
217
-                if (in_array($importPath, $parents)) {
218
-                    throw new FileImportException('Failed to import file "'.$importPath.'": circular reference detected.');
219
-                }
220
-
221
-                // grab referenced file & minify it (which may include importing
222
-                // yet other @import statements recursively)
223
-                $minifier = new static($importPath);
224
-                $importContent = $minifier->execute($source, $parents);
225
-
226
-                // check if this is only valid for certain media
227
-                if (!empty($match['media'])) {
228
-                    $importContent = '@media '.$match['media'].'{'.$importContent.'}';
229
-                }
230
-
231
-                // add to replacement array
232
-                $search[] = $match[0];
233
-                $replace[] = $importContent;
234
-            }
235
-        }
236
-
237
-        // replace the import statements
238
-        $content = str_replace($search, $replace, $content);
239
-
240
-        return $content;
241
-    }
242
-
243
-    /**
244
-     * Import files into the CSS, base64-ized.
245
-     *
246
-     * @url(image.jpg) images will be loaded and their content merged into the
247
-     * original file, to save HTTP requests.
248
-     *
249
-     * @param string $source  The file to import files for
250
-     * @param string $content The CSS content to import files for
251
-     *
252
-     * @return string
253
-     */
254
-    protected function importFiles($source, $content)
255
-    {
256
-        $extensions = array_keys($this->importExtensions);
257
-        $regex = '/url\((["\']?)((?!["\']?data:).*?\.('.implode('|', $extensions).'))\\1\)/i';
258
-        if ($extensions && preg_match_all($regex, $content, $matches, PREG_SET_ORDER)) {
259
-            $search = array();
260
-            $replace = array();
261
-
262
-            // loop the matches
263
-            foreach ($matches as $match) {
264
-                // get the path for the file that will be imported
265
-                $path = $match[2];
266
-                $path = dirname($source).'/'.$path;
267
-                $extension = $match[3];
268
-
269
-                // only replace the import with the content if we're able to get
270
-                // the content of the file, and it's relatively small
271
-                if ($this->canImportFile($path) && $this->canImportBySize($path)) {
272
-                    // grab content && base64-ize
273
-                    $importContent = $this->load($path);
274
-                    $importContent = base64_encode($importContent);
275
-
276
-                    // build replacement
277
-                    $search[] = $match[0];
278
-                    $replace[] = 'url('.$this->importExtensions[$extension].';base64,'.$importContent.')';
279
-                }
280
-            }
281
-
282
-            // replace the import statements
283
-            $content = str_replace($search, $replace, $content);
284
-        }
285
-
286
-        return $content;
287
-    }
288
-
289
-    /**
290
-     * Minify the data.
291
-     * Perform CSS optimizations.
292
-     *
293
-     * @param string[optional] $path    Path to write the data to
294
-     * @param string[]         $parents Parent paths, for circular reference checks
295
-     *
296
-     * @return string The minified data
297
-     */
298
-    public function execute($path = null, $parents = array())
299
-    {
300
-        $content = '';
301
-
302
-        // loop css data (raw data and files)
303
-        foreach ($this->data as $source => $css) {
304
-            /*
194
+		);
195
+
196
+		// find all relative imports in css
197
+		$matches = array();
198
+		foreach ($importRegexes as $importRegex) {
199
+			if (preg_match_all($importRegex, $content, $regexMatches, PREG_SET_ORDER)) {
200
+				$matches = array_merge($matches, $regexMatches);
201
+			}
202
+		}
203
+
204
+		$search = array();
205
+		$replace = array();
206
+
207
+		// loop the matches
208
+		foreach ($matches as $match) {
209
+			// get the path for the file that will be imported
210
+			$importPath = dirname($source).'/'.$match['path'];
211
+
212
+			// only replace the import with the content if we can grab the
213
+			// content of the file
214
+			if ($this->canImportFile($importPath)) {
215
+				// check if current file was not imported previously in the same
216
+				// import chain.
217
+				if (in_array($importPath, $parents)) {
218
+					throw new FileImportException('Failed to import file "'.$importPath.'": circular reference detected.');
219
+				}
220
+
221
+				// grab referenced file & minify it (which may include importing
222
+				// yet other @import statements recursively)
223
+				$minifier = new static($importPath);
224
+				$importContent = $minifier->execute($source, $parents);
225
+
226
+				// check if this is only valid for certain media
227
+				if (!empty($match['media'])) {
228
+					$importContent = '@media '.$match['media'].'{'.$importContent.'}';
229
+				}
230
+
231
+				// add to replacement array
232
+				$search[] = $match[0];
233
+				$replace[] = $importContent;
234
+			}
235
+		}
236
+
237
+		// replace the import statements
238
+		$content = str_replace($search, $replace, $content);
239
+
240
+		return $content;
241
+	}
242
+
243
+	/**
244
+	 * Import files into the CSS, base64-ized.
245
+	 *
246
+	 * @url(image.jpg) images will be loaded and their content merged into the
247
+	 * original file, to save HTTP requests.
248
+	 *
249
+	 * @param string $source  The file to import files for
250
+	 * @param string $content The CSS content to import files for
251
+	 *
252
+	 * @return string
253
+	 */
254
+	protected function importFiles($source, $content)
255
+	{
256
+		$extensions = array_keys($this->importExtensions);
257
+		$regex = '/url\((["\']?)((?!["\']?data:).*?\.('.implode('|', $extensions).'))\\1\)/i';
258
+		if ($extensions && preg_match_all($regex, $content, $matches, PREG_SET_ORDER)) {
259
+			$search = array();
260
+			$replace = array();
261
+
262
+			// loop the matches
263
+			foreach ($matches as $match) {
264
+				// get the path for the file that will be imported
265
+				$path = $match[2];
266
+				$path = dirname($source).'/'.$path;
267
+				$extension = $match[3];
268
+
269
+				// only replace the import with the content if we're able to get
270
+				// the content of the file, and it's relatively small
271
+				if ($this->canImportFile($path) && $this->canImportBySize($path)) {
272
+					// grab content && base64-ize
273
+					$importContent = $this->load($path);
274
+					$importContent = base64_encode($importContent);
275
+
276
+					// build replacement
277
+					$search[] = $match[0];
278
+					$replace[] = 'url('.$this->importExtensions[$extension].';base64,'.$importContent.')';
279
+				}
280
+			}
281
+
282
+			// replace the import statements
283
+			$content = str_replace($search, $replace, $content);
284
+		}
285
+
286
+		return $content;
287
+	}
288
+
289
+	/**
290
+	 * Minify the data.
291
+	 * Perform CSS optimizations.
292
+	 *
293
+	 * @param string[optional] $path    Path to write the data to
294
+	 * @param string[]         $parents Parent paths, for circular reference checks
295
+	 *
296
+	 * @return string The minified data
297
+	 */
298
+	public function execute($path = null, $parents = array())
299
+	{
300
+		$content = '';
301
+
302
+		// loop css data (raw data and files)
303
+		foreach ($this->data as $source => $css) {
304
+			/*
305 305
              * Let's first take out strings & comments, since we can't just remove
306 306
              * whitespace anywhere. If whitespace occurs inside a string, we should
307 307
              * leave it alone. E.g.:
308 308
              * p { content: "a   test" }
309 309
              */
310
-            $this->extractStrings();
311
-            $this->stripComments();
312
-            $css = $this->replace($css);
310
+			$this->extractStrings();
311
+			$this->stripComments();
312
+			$css = $this->replace($css);
313 313
 
314
-            $css = $this->stripWhitespace($css);
315
-            $css = $this->shortenHex($css);
316
-            $css = $this->shortenZeroes($css);
317
-            $css = $this->shortenFontWeights($css);
318
-            $css = $this->stripEmptyTags($css);
314
+			$css = $this->stripWhitespace($css);
315
+			$css = $this->shortenHex($css);
316
+			$css = $this->shortenZeroes($css);
317
+			$css = $this->shortenFontWeights($css);
318
+			$css = $this->stripEmptyTags($css);
319 319
 
320
-            // restore the string we've extracted earlier
321
-            $css = $this->restoreExtractedData($css);
320
+			// restore the string we've extracted earlier
321
+			$css = $this->restoreExtractedData($css);
322 322
 
323
-            $source = is_int($source) ? '' : $source;
324
-            $parents = $source ? array_merge($parents, array($source)) : $parents;
325
-            $css = $this->combineImports($source, $css, $parents);
326
-            $css = $this->importFiles($source, $css);
323
+			$source = is_int($source) ? '' : $source;
324
+			$parents = $source ? array_merge($parents, array($source)) : $parents;
325
+			$css = $this->combineImports($source, $css, $parents);
326
+			$css = $this->importFiles($source, $css);
327 327
 
328
-            /*
328
+			/*
329 329
              * If we'll save to a new path, we'll have to fix the relative paths
330 330
              * to be relative no longer to the source file, but to the new path.
331 331
              * If we don't write to a file, fall back to same path so no
332 332
              * conversion happens (because we still want it to go through most
333 333
              * of the move code...)
334 334
              */
335
-            $converter = new Converter($source, $path ?: $source);
336
-            $css = $this->move($converter, $css);
337
-
338
-            // combine css
339
-            $content .= $css;
340
-        }
341
-
342
-        $content = $this->moveImportsToTop($content);
343
-
344
-        return $content;
345
-    }
346
-
347
-    /**
348
-     * Moving a css file should update all relative urls.
349
-     * Relative references (e.g. ../images/image.gif) in a certain css file,
350
-     * will have to be updated when a file is being saved at another location
351
-     * (e.g. ../../images/image.gif, if the new CSS file is 1 folder deeper).
352
-     *
353
-     * @param Converter $converter Relative path converter
354
-     * @param string    $content   The CSS content to update relative urls for
355
-     *
356
-     * @return string
357
-     */
358
-    protected function move(Converter $converter, $content)
359
-    {
360
-        /*
335
+			$converter = new Converter($source, $path ?: $source);
336
+			$css = $this->move($converter, $css);
337
+
338
+			// combine css
339
+			$content .= $css;
340
+		}
341
+
342
+		$content = $this->moveImportsToTop($content);
343
+
344
+		return $content;
345
+	}
346
+
347
+	/**
348
+	 * Moving a css file should update all relative urls.
349
+	 * Relative references (e.g. ../images/image.gif) in a certain css file,
350
+	 * will have to be updated when a file is being saved at another location
351
+	 * (e.g. ../../images/image.gif, if the new CSS file is 1 folder deeper).
352
+	 *
353
+	 * @param Converter $converter Relative path converter
354
+	 * @param string    $content   The CSS content to update relative urls for
355
+	 *
356
+	 * @return string
357
+	 */
358
+	protected function move(Converter $converter, $content)
359
+	{
360
+		/*
361 361
          * Relative path references will usually be enclosed by url(). @import
362 362
          * is an exception, where url() is not necessary around the path (but is
363 363
          * allowed).
@@ -368,9 +368,9 @@  discard block
 block discarded – undo
368 368
          * recent PCRE version. That's why I'm doing 2 separate regular
369 369
          * expressions & combining the matches after executing of both.
370 370
          */
371
-        $relativeRegexes = array(
372
-            // url(xxx)
373
-            '/
371
+		$relativeRegexes = array(
372
+			// url(xxx)
373
+			'/
374 374
             # open url()
375 375
             url\(
376 376
 
@@ -402,8 +402,8 @@  discard block
 block discarded – undo
402 402
 
403 403
             /ix',
404 404
 
405
-            // @import "xxx"
406
-            '/
405
+			// @import "xxx"
406
+			'/
407 407
             # import statement
408 408
             @import
409 409
 
@@ -432,243 +432,243 @@  discard block
 block discarded – undo
432 432
                 (?P=quotes)
433 433
 
434 434
             /ix',
435
-        );
436
-
437
-        // find all relative urls in css
438
-        $matches = array();
439
-        foreach ($relativeRegexes as $relativeRegex) {
440
-            if (preg_match_all($relativeRegex, $content, $regexMatches, PREG_SET_ORDER)) {
441
-                $matches = array_merge($matches, $regexMatches);
442
-            }
443
-        }
444
-
445
-        $search = array();
446
-        $replace = array();
447
-
448
-        // loop all urls
449
-        foreach ($matches as $match) {
450
-            // determine if it's a url() or an @import match
451
-            $type = (strpos($match[0], '@import') === 0 ? 'import' : 'url');
452
-
453
-            // attempting to interpret GET-params makes no sense, so let's discard them for awhile
454
-            $params = strrchr($match['path'], '?');
455
-            $url = $params ? substr($match['path'], 0, -strlen($params)) : $match['path'];
456
-
457
-            // fix relative url
458
-            $url = $converter->convert($url);
459
-
460
-            // now that the path has been converted, re-apply GET-params
461
-            $url .= $params;
462
-
463
-            // build replacement
464
-            $search[] = $match[0];
465
-            if ($type == 'url') {
466
-                $replace[] = 'url('.$url.')';
467
-            } elseif ($type == 'import') {
468
-                $replace[] = '@import "'.$url.'"';
469
-            }
470
-        }
471
-
472
-        // replace urls
473
-        $content = str_replace($search, $replace, $content);
474
-
475
-        return $content;
476
-    }
477
-
478
-    /**
479
-     * Shorthand hex color codes.
480
-     * #FF0000 -> #F00.
481
-     *
482
-     * @param string $content The CSS content to shorten the hex color codes for
483
-     *
484
-     * @return string
485
-     */
486
-    protected function shortenHex($content)
487
-    {
488
-        $content = preg_replace('/(?<=[: ])#([0-9a-z])\\1([0-9a-z])\\2([0-9a-z])\\3(?=[; }])/i', '#$1$2$3', $content);
489
-
490
-        // we can shorten some even more by replacing them with their color name
491
-        $colors = array(
492
-            '#F0FFFF' => 'azure',
493
-            '#F5F5DC' => 'beige',
494
-            '#A52A2A' => 'brown',
495
-            '#FF7F50' => 'coral',
496
-            '#FFD700' => 'gold',
497
-            '#808080' => 'gray',
498
-            '#008000' => 'green',
499
-            '#4B0082' => 'indigo',
500
-            '#FFFFF0' => 'ivory',
501
-            '#F0E68C' => 'khaki',
502
-            '#FAF0E6' => 'linen',
503
-            '#800000' => 'maroon',
504
-            '#000080' => 'navy',
505
-            '#808000' => 'olive',
506
-            '#CD853F' => 'peru',
507
-            '#FFC0CB' => 'pink',
508
-            '#DDA0DD' => 'plum',
509
-            '#800080' => 'purple',
510
-            '#F00' => 'red',
511
-            '#FA8072' => 'salmon',
512
-            '#A0522D' => 'sienna',
513
-            '#C0C0C0' => 'silver',
514
-            '#FFFAFA' => 'snow',
515
-            '#D2B48C' => 'tan',
516
-            '#FF6347' => 'tomato',
517
-            '#EE82EE' => 'violet',
518
-            '#F5DEB3' => 'wheat',
519
-        );
520
-
521
-        return preg_replace_callback(
522
-            '/(?<=[: ])('.implode(array_keys($colors), '|').')(?=[; }])/i',
523
-            function ($match) use ($colors) {
524
-                return $colors[strtoupper($match[0])];
525
-            },
526
-            $content
527
-        );
528
-    }
529
-
530
-    /**
531
-     * Shorten CSS font weights.
532
-     *
533
-     * @param string $content The CSS content to shorten the font weights for
534
-     *
535
-     * @return string
536
-     */
537
-    protected function shortenFontWeights($content)
538
-    {
539
-        $weights = array(
540
-            'normal' => 400,
541
-            'bold' => 700,
542
-        );
543
-
544
-        $callback = function ($match) use ($weights) {
545
-            return $match[1].$weights[$match[2]];
546
-        };
547
-
548
-        return preg_replace_callback('/(font-weight\s*:\s*)('.implode('|', array_keys($weights)).')(?=[;}])/', $callback, $content);
549
-    }
550
-
551
-    /**
552
-     * Shorthand 0 values to plain 0, instead of e.g. -0em.
553
-     *
554
-     * @param string $content The CSS content to shorten the zero values for
555
-     *
556
-     * @return string
557
-     */
558
-    protected function shortenZeroes($content)
559
-    {
560
-        // reusable bits of code throughout these regexes:
561
-        // before & after are used to make sure we don't match lose unintended
562
-        // 0-like values (e.g. in #000, or in http://url/1.0)
563
-        // units can be stripped from 0 values, or used to recognize non 0
564
-        // values (where wa may be able to strip a .0 suffix)
565
-        $before = '(?<=[:(, ])';
566
-        $after = '(?=[ ,);}])';
567
-        $units = '(em|ex|%|px|cm|mm|in|pt|pc|ch|rem|vh|vw|vmin|vmax|vm)';
568
-
569
-        // strip units after zeroes (0px -> 0)
570
-        // NOTE: it should be safe to remove all units for a 0 value, but in
571
-        // practice, Webkit (especially Safari) seems to stumble over at least
572
-        // 0%, potentially other units as well. Only stripping 'px' for now.
573
-        // @see https://github.com/matthiasmullie/minify/issues/60
574
-        $content = preg_replace('/'.$before.'(-?0*(\.0+)?)(?<=0)px'.$after.'/', '\\1', $content);
575
-
576
-        // strip 0-digits (.0 -> 0)
577
-        $content = preg_replace('/'.$before.'\.0+'.$units.'?'.$after.'/', '0\\1', $content);
578
-        // strip trailing 0: 50.10 -> 50.1, 50.10px -> 50.1px
579
-        $content = preg_replace('/'.$before.'(-?[0-9]+\.[0-9]+)0+'.$units.'?'.$after.'/', '\\1\\2', $content);
580
-        // strip trailing 0: 50.00 -> 50, 50.00px -> 50px
581
-        $content = preg_replace('/'.$before.'(-?[0-9]+)\.0+'.$units.'?'.$after.'/', '\\1\\2', $content);
582
-        // strip leading 0: 0.1 -> .1, 01.1 -> 1.1
583
-        $content = preg_replace('/'.$before.'(-?)0+([0-9]*\.[0-9]+)'.$units.'?'.$after.'/', '\\1\\2\\3', $content);
584
-
585
-        // strip negative zeroes (-0 -> 0) & truncate zeroes (00 -> 0)
586
-        $content = preg_replace('/'.$before.'-?0+'.$units.'?'.$after.'/', '0\\1', $content);
587
-
588
-        // remove zeroes where they make no sense in calc: e.g. calc(100px - 0)
589
-        // the 0 doesn't have any effect, and this isn't even valid without unit
590
-        // strip all `+ 0` or `- 0` occurrences: calc(10% + 0) -> calc(10%)
591
-        // looped because there may be multiple 0s inside 1 group of parentheses
592
-        do {
593
-            $previous = $content;
594
-            $content = preg_replace('/\(([^\(\)]+)\s+[\+\-]\s+0(\s+[^\(\)]+)?\)/', '(\\1\\2)', $content);
595
-        } while ($content !== $previous);
596
-        // strip all `0 +` occurrences: calc(0 + 10%) -> calc(10%)
597
-        $content = preg_replace('/\(\s*0\s+\+\s+([^\(\)]+)\)/', '(\\1)', $content);
598
-        // strip all `0 -` occurrences: calc(0 - 10%) -> calc(-10%)
599
-        $content = preg_replace('/\(\s*0\s+\-\s+([^\(\)]+)\)/', '(-\\1)', $content);
600
-        // I'm not going to attempt to optimize away `x * 0` instances:
601
-        // it's dumb enough code already that it likely won't occur, and it's
602
-        // too complex to do right (order of operations would have to be
603
-        // respected etc)
604
-        // what I cared about most here was fixing incorrectly truncated units
605
-
606
-        return $content;
607
-    }
608
-
609
-    /**
610
-     * Strip comments from source code.
611
-     *
612
-     * @param string $content
613
-     *
614
-     * @return string
615
-     */
616
-    protected function stripEmptyTags($content)
617
-    {
618
-        return preg_replace('/(^|\}|;)[^\{\};]+\{\s*\}/', '\\1', $content);
619
-    }
620
-
621
-    /**
622
-     * Strip comments from source code.
623
-     */
624
-    protected function stripComments()
625
-    {
626
-        $this->registerPattern('/\/\*.*?\*\//s', '');
627
-    }
628
-
629
-    /**
630
-     * Strip whitespace.
631
-     *
632
-     * @param string $content The CSS content to strip the whitespace for
633
-     *
634
-     * @return string
635
-     */
636
-    protected function stripWhitespace($content)
637
-    {
638
-        // remove leading & trailing whitespace
639
-        $content = preg_replace('/^\s*/m', '', $content);
640
-        $content = preg_replace('/\s*$/m', '', $content);
641
-
642
-        // replace newlines with a single space
643
-        $content = preg_replace('/\s+/', ' ', $content);
644
-
645
-        // remove whitespace around meta characters
646
-        // inspired by stackoverflow.com/questions/15195750/minify-compress-css-with-regex
647
-        $content = preg_replace('/\s*([\*$~^|]?+=|[{};,>~]|!important\b)\s*/', '$1', $content);
648
-        $content = preg_replace('/([\[(:])\s+/', '$1', $content);
649
-        $content = preg_replace('/\s+([\]\)])/', '$1', $content);
650
-        $content = preg_replace('/\s+(:)(?![^\}]*\{)/', '$1', $content);
651
-
652
-        // whitespace around + and - can only be stripped in selectors, like
653
-        // :nth-child(3+2n), not in things like calc(3px + 2px) or shorthands
654
-        // like 3px -2px
655
-        $content = preg_replace('/\s*([+-])\s*(?=[^}]*{)/', '$1', $content);
656
-
657
-        // remove semicolon/whitespace followed by closing bracket
658
-        $content = str_replace(';}', '}', $content);
659
-
660
-        return trim($content);
661
-    }
662
-
663
-    /**
664
-     * Check if file is small enough to be imported.
665
-     *
666
-     * @param string $path The path to the file
667
-     *
668
-     * @return bool
669
-     */
670
-    protected function canImportBySize($path)
671
-    {
672
-        return ($size = @filesize($path)) && $size <= $this->maxImportSize * 1024;
673
-    }
435
+		);
436
+
437
+		// find all relative urls in css
438
+		$matches = array();
439
+		foreach ($relativeRegexes as $relativeRegex) {
440
+			if (preg_match_all($relativeRegex, $content, $regexMatches, PREG_SET_ORDER)) {
441
+				$matches = array_merge($matches, $regexMatches);
442
+			}
443
+		}
444
+
445
+		$search = array();
446
+		$replace = array();
447
+
448
+		// loop all urls
449
+		foreach ($matches as $match) {
450
+			// determine if it's a url() or an @import match
451
+			$type = (strpos($match[0], '@import') === 0 ? 'import' : 'url');
452
+
453
+			// attempting to interpret GET-params makes no sense, so let's discard them for awhile
454
+			$params = strrchr($match['path'], '?');
455
+			$url = $params ? substr($match['path'], 0, -strlen($params)) : $match['path'];
456
+
457
+			// fix relative url
458
+			$url = $converter->convert($url);
459
+
460
+			// now that the path has been converted, re-apply GET-params
461
+			$url .= $params;
462
+
463
+			// build replacement
464
+			$search[] = $match[0];
465
+			if ($type == 'url') {
466
+				$replace[] = 'url('.$url.')';
467
+			} elseif ($type == 'import') {
468
+				$replace[] = '@import "'.$url.'"';
469
+			}
470
+		}
471
+
472
+		// replace urls
473
+		$content = str_replace($search, $replace, $content);
474
+
475
+		return $content;
476
+	}
477
+
478
+	/**
479
+	 * Shorthand hex color codes.
480
+	 * #FF0000 -> #F00.
481
+	 *
482
+	 * @param string $content The CSS content to shorten the hex color codes for
483
+	 *
484
+	 * @return string
485
+	 */
486
+	protected function shortenHex($content)
487
+	{
488
+		$content = preg_replace('/(?<=[: ])#([0-9a-z])\\1([0-9a-z])\\2([0-9a-z])\\3(?=[; }])/i', '#$1$2$3', $content);
489
+
490
+		// we can shorten some even more by replacing them with their color name
491
+		$colors = array(
492
+			'#F0FFFF' => 'azure',
493
+			'#F5F5DC' => 'beige',
494
+			'#A52A2A' => 'brown',
495
+			'#FF7F50' => 'coral',
496
+			'#FFD700' => 'gold',
497
+			'#808080' => 'gray',
498
+			'#008000' => 'green',
499
+			'#4B0082' => 'indigo',
500
+			'#FFFFF0' => 'ivory',
501
+			'#F0E68C' => 'khaki',
502
+			'#FAF0E6' => 'linen',
503
+			'#800000' => 'maroon',
504
+			'#000080' => 'navy',
505
+			'#808000' => 'olive',
506
+			'#CD853F' => 'peru',
507
+			'#FFC0CB' => 'pink',
508
+			'#DDA0DD' => 'plum',
509
+			'#800080' => 'purple',
510
+			'#F00' => 'red',
511
+			'#FA8072' => 'salmon',
512
+			'#A0522D' => 'sienna',
513
+			'#C0C0C0' => 'silver',
514
+			'#FFFAFA' => 'snow',
515
+			'#D2B48C' => 'tan',
516
+			'#FF6347' => 'tomato',
517
+			'#EE82EE' => 'violet',
518
+			'#F5DEB3' => 'wheat',
519
+		);
520
+
521
+		return preg_replace_callback(
522
+			'/(?<=[: ])('.implode(array_keys($colors), '|').')(?=[; }])/i',
523
+			function ($match) use ($colors) {
524
+				return $colors[strtoupper($match[0])];
525
+			},
526
+			$content
527
+		);
528
+	}
529
+
530
+	/**
531
+	 * Shorten CSS font weights.
532
+	 *
533
+	 * @param string $content The CSS content to shorten the font weights for
534
+	 *
535
+	 * @return string
536
+	 */
537
+	protected function shortenFontWeights($content)
538
+	{
539
+		$weights = array(
540
+			'normal' => 400,
541
+			'bold' => 700,
542
+		);
543
+
544
+		$callback = function ($match) use ($weights) {
545
+			return $match[1].$weights[$match[2]];
546
+		};
547
+
548
+		return preg_replace_callback('/(font-weight\s*:\s*)('.implode('|', array_keys($weights)).')(?=[;}])/', $callback, $content);
549
+	}
550
+
551
+	/**
552
+	 * Shorthand 0 values to plain 0, instead of e.g. -0em.
553
+	 *
554
+	 * @param string $content The CSS content to shorten the zero values for
555
+	 *
556
+	 * @return string
557
+	 */
558
+	protected function shortenZeroes($content)
559
+	{
560
+		// reusable bits of code throughout these regexes:
561
+		// before & after are used to make sure we don't match lose unintended
562
+		// 0-like values (e.g. in #000, or in http://url/1.0)
563
+		// units can be stripped from 0 values, or used to recognize non 0
564
+		// values (where wa may be able to strip a .0 suffix)
565
+		$before = '(?<=[:(, ])';
566
+		$after = '(?=[ ,);}])';
567
+		$units = '(em|ex|%|px|cm|mm|in|pt|pc|ch|rem|vh|vw|vmin|vmax|vm)';
568
+
569
+		// strip units after zeroes (0px -> 0)
570
+		// NOTE: it should be safe to remove all units for a 0 value, but in
571
+		// practice, Webkit (especially Safari) seems to stumble over at least
572
+		// 0%, potentially other units as well. Only stripping 'px' for now.
573
+		// @see https://github.com/matthiasmullie/minify/issues/60
574
+		$content = preg_replace('/'.$before.'(-?0*(\.0+)?)(?<=0)px'.$after.'/', '\\1', $content);
575
+
576
+		// strip 0-digits (.0 -> 0)
577
+		$content = preg_replace('/'.$before.'\.0+'.$units.'?'.$after.'/', '0\\1', $content);
578
+		// strip trailing 0: 50.10 -> 50.1, 50.10px -> 50.1px
579
+		$content = preg_replace('/'.$before.'(-?[0-9]+\.[0-9]+)0+'.$units.'?'.$after.'/', '\\1\\2', $content);
580
+		// strip trailing 0: 50.00 -> 50, 50.00px -> 50px
581
+		$content = preg_replace('/'.$before.'(-?[0-9]+)\.0+'.$units.'?'.$after.'/', '\\1\\2', $content);
582
+		// strip leading 0: 0.1 -> .1, 01.1 -> 1.1
583
+		$content = preg_replace('/'.$before.'(-?)0+([0-9]*\.[0-9]+)'.$units.'?'.$after.'/', '\\1\\2\\3', $content);
584
+
585
+		// strip negative zeroes (-0 -> 0) & truncate zeroes (00 -> 0)
586
+		$content = preg_replace('/'.$before.'-?0+'.$units.'?'.$after.'/', '0\\1', $content);
587
+
588
+		// remove zeroes where they make no sense in calc: e.g. calc(100px - 0)
589
+		// the 0 doesn't have any effect, and this isn't even valid without unit
590
+		// strip all `+ 0` or `- 0` occurrences: calc(10% + 0) -> calc(10%)
591
+		// looped because there may be multiple 0s inside 1 group of parentheses
592
+		do {
593
+			$previous = $content;
594
+			$content = preg_replace('/\(([^\(\)]+)\s+[\+\-]\s+0(\s+[^\(\)]+)?\)/', '(\\1\\2)', $content);
595
+		} while ($content !== $previous);
596
+		// strip all `0 +` occurrences: calc(0 + 10%) -> calc(10%)
597
+		$content = preg_replace('/\(\s*0\s+\+\s+([^\(\)]+)\)/', '(\\1)', $content);
598
+		// strip all `0 -` occurrences: calc(0 - 10%) -> calc(-10%)
599
+		$content = preg_replace('/\(\s*0\s+\-\s+([^\(\)]+)\)/', '(-\\1)', $content);
600
+		// I'm not going to attempt to optimize away `x * 0` instances:
601
+		// it's dumb enough code already that it likely won't occur, and it's
602
+		// too complex to do right (order of operations would have to be
603
+		// respected etc)
604
+		// what I cared about most here was fixing incorrectly truncated units
605
+
606
+		return $content;
607
+	}
608
+
609
+	/**
610
+	 * Strip comments from source code.
611
+	 *
612
+	 * @param string $content
613
+	 *
614
+	 * @return string
615
+	 */
616
+	protected function stripEmptyTags($content)
617
+	{
618
+		return preg_replace('/(^|\}|;)[^\{\};]+\{\s*\}/', '\\1', $content);
619
+	}
620
+
621
+	/**
622
+	 * Strip comments from source code.
623
+	 */
624
+	protected function stripComments()
625
+	{
626
+		$this->registerPattern('/\/\*.*?\*\//s', '');
627
+	}
628
+
629
+	/**
630
+	 * Strip whitespace.
631
+	 *
632
+	 * @param string $content The CSS content to strip the whitespace for
633
+	 *
634
+	 * @return string
635
+	 */
636
+	protected function stripWhitespace($content)
637
+	{
638
+		// remove leading & trailing whitespace
639
+		$content = preg_replace('/^\s*/m', '', $content);
640
+		$content = preg_replace('/\s*$/m', '', $content);
641
+
642
+		// replace newlines with a single space
643
+		$content = preg_replace('/\s+/', ' ', $content);
644
+
645
+		// remove whitespace around meta characters
646
+		// inspired by stackoverflow.com/questions/15195750/minify-compress-css-with-regex
647
+		$content = preg_replace('/\s*([\*$~^|]?+=|[{};,>~]|!important\b)\s*/', '$1', $content);
648
+		$content = preg_replace('/([\[(:])\s+/', '$1', $content);
649
+		$content = preg_replace('/\s+([\]\)])/', '$1', $content);
650
+		$content = preg_replace('/\s+(:)(?![^\}]*\{)/', '$1', $content);
651
+
652
+		// whitespace around + and - can only be stripped in selectors, like
653
+		// :nth-child(3+2n), not in things like calc(3px + 2px) or shorthands
654
+		// like 3px -2px
655
+		$content = preg_replace('/\s*([+-])\s*(?=[^}]*{)/', '$1', $content);
656
+
657
+		// remove semicolon/whitespace followed by closing bracket
658
+		$content = str_replace(';}', '}', $content);
659
+
660
+		return trim($content);
661
+	}
662
+
663
+	/**
664
+	 * Check if file is small enough to be imported.
665
+	 *
666
+	 * @param string $path The path to the file
667
+	 *
668
+	 * @return bool
669
+	 */
670
+	protected function canImportBySize($path)
671
+	{
672
+		return ($size = @filesize($path)) && $size <= $this->maxImportSize * 1024;
673
+	}
674 674
 }
Please login to merge, or discard this patch.
Spacing   +20 added lines, -20 removed lines patch added patch discarded remove patch
@@ -82,7 +82,7 @@  discard block
 block discarded – undo
82 82
             }
83 83
 
84 84
             // add to top
85
-            $content = implode('', $matches[0]).$content;
85
+            $content = implode('', $matches[0]) . $content;
86 86
         }
87 87
 
88 88
         return $content;
@@ -207,7 +207,7 @@  discard block
 block discarded – undo
207 207
         // loop the matches
208 208
         foreach ($matches as $match) {
209 209
             // get the path for the file that will be imported
210
-            $importPath = dirname($source).'/'.$match['path'];
210
+            $importPath = dirname($source) . '/' . $match['path'];
211 211
 
212 212
             // only replace the import with the content if we can grab the
213 213
             // content of the file
@@ -215,7 +215,7 @@  discard block
 block discarded – undo
215 215
                 // check if current file was not imported previously in the same
216 216
                 // import chain.
217 217
                 if (in_array($importPath, $parents)) {
218
-                    throw new FileImportException('Failed to import file "'.$importPath.'": circular reference detected.');
218
+                    throw new FileImportException('Failed to import file "' . $importPath . '": circular reference detected.');
219 219
                 }
220 220
 
221 221
                 // grab referenced file & minify it (which may include importing
@@ -225,7 +225,7 @@  discard block
 block discarded – undo
225 225
 
226 226
                 // check if this is only valid for certain media
227 227
                 if (!empty($match['media'])) {
228
-                    $importContent = '@media '.$match['media'].'{'.$importContent.'}';
228
+                    $importContent = '@media ' . $match['media'] . '{' . $importContent . '}';
229 229
                 }
230 230
 
231 231
                 // add to replacement array
@@ -254,7 +254,7 @@  discard block
 block discarded – undo
254 254
     protected function importFiles($source, $content)
255 255
     {
256 256
         $extensions = array_keys($this->importExtensions);
257
-        $regex = '/url\((["\']?)((?!["\']?data:).*?\.('.implode('|', $extensions).'))\\1\)/i';
257
+        $regex = '/url\((["\']?)((?!["\']?data:).*?\.(' . implode('|', $extensions) . '))\\1\)/i';
258 258
         if ($extensions && preg_match_all($regex, $content, $matches, PREG_SET_ORDER)) {
259 259
             $search = array();
260 260
             $replace = array();
@@ -263,7 +263,7 @@  discard block
 block discarded – undo
263 263
             foreach ($matches as $match) {
264 264
                 // get the path for the file that will be imported
265 265
                 $path = $match[2];
266
-                $path = dirname($source).'/'.$path;
266
+                $path = dirname($source) . '/' . $path;
267 267
                 $extension = $match[3];
268 268
 
269 269
                 // only replace the import with the content if we're able to get
@@ -275,7 +275,7 @@  discard block
 block discarded – undo
275 275
 
276 276
                     // build replacement
277 277
                     $search[] = $match[0];
278
-                    $replace[] = 'url('.$this->importExtensions[$extension].';base64,'.$importContent.')';
278
+                    $replace[] = 'url(' . $this->importExtensions[$extension] . ';base64,' . $importContent . ')';
279 279
                 }
280 280
             }
281 281
 
@@ -463,9 +463,9 @@  discard block
 block discarded – undo
463 463
             // build replacement
464 464
             $search[] = $match[0];
465 465
             if ($type == 'url') {
466
-                $replace[] = 'url('.$url.')';
466
+                $replace[] = 'url(' . $url . ')';
467 467
             } elseif ($type == 'import') {
468
-                $replace[] = '@import "'.$url.'"';
468
+                $replace[] = '@import "' . $url . '"';
469 469
             }
470 470
         }
471 471
 
@@ -519,8 +519,8 @@  discard block
 block discarded – undo
519 519
         );
520 520
 
521 521
         return preg_replace_callback(
522
-            '/(?<=[: ])('.implode(array_keys($colors), '|').')(?=[; }])/i',
523
-            function ($match) use ($colors) {
522
+            '/(?<=[: ])(' . implode(array_keys($colors), '|') . ')(?=[; }])/i',
523
+            function($match) use ($colors) {
524 524
                 return $colors[strtoupper($match[0])];
525 525
             },
526 526
             $content
@@ -541,11 +541,11 @@  discard block
 block discarded – undo
541 541
             'bold' => 700,
542 542
         );
543 543
 
544
-        $callback = function ($match) use ($weights) {
545
-            return $match[1].$weights[$match[2]];
544
+        $callback = function($match) use ($weights) {
545
+            return $match[1] . $weights[$match[2]];
546 546
         };
547 547
 
548
-        return preg_replace_callback('/(font-weight\s*:\s*)('.implode('|', array_keys($weights)).')(?=[;}])/', $callback, $content);
548
+        return preg_replace_callback('/(font-weight\s*:\s*)(' . implode('|', array_keys($weights)) . ')(?=[;}])/', $callback, $content);
549 549
     }
550 550
 
551 551
     /**
@@ -571,19 +571,19 @@  discard block
 block discarded – undo
571 571
         // practice, Webkit (especially Safari) seems to stumble over at least
572 572
         // 0%, potentially other units as well. Only stripping 'px' for now.
573 573
         // @see https://github.com/matthiasmullie/minify/issues/60
574
-        $content = preg_replace('/'.$before.'(-?0*(\.0+)?)(?<=0)px'.$after.'/', '\\1', $content);
574
+        $content = preg_replace('/' . $before . '(-?0*(\.0+)?)(?<=0)px' . $after . '/', '\\1', $content);
575 575
 
576 576
         // strip 0-digits (.0 -> 0)
577
-        $content = preg_replace('/'.$before.'\.0+'.$units.'?'.$after.'/', '0\\1', $content);
577
+        $content = preg_replace('/' . $before . '\.0+' . $units . '?' . $after . '/', '0\\1', $content);
578 578
         // strip trailing 0: 50.10 -> 50.1, 50.10px -> 50.1px
579
-        $content = preg_replace('/'.$before.'(-?[0-9]+\.[0-9]+)0+'.$units.'?'.$after.'/', '\\1\\2', $content);
579
+        $content = preg_replace('/' . $before . '(-?[0-9]+\.[0-9]+)0+' . $units . '?' . $after . '/', '\\1\\2', $content);
580 580
         // strip trailing 0: 50.00 -> 50, 50.00px -> 50px
581
-        $content = preg_replace('/'.$before.'(-?[0-9]+)\.0+'.$units.'?'.$after.'/', '\\1\\2', $content);
581
+        $content = preg_replace('/' . $before . '(-?[0-9]+)\.0+' . $units . '?' . $after . '/', '\\1\\2', $content);
582 582
         // strip leading 0: 0.1 -> .1, 01.1 -> 1.1
583
-        $content = preg_replace('/'.$before.'(-?)0+([0-9]*\.[0-9]+)'.$units.'?'.$after.'/', '\\1\\2\\3', $content);
583
+        $content = preg_replace('/' . $before . '(-?)0+([0-9]*\.[0-9]+)' . $units . '?' . $after . '/', '\\1\\2\\3', $content);
584 584
 
585 585
         // strip negative zeroes (-0 -> 0) & truncate zeroes (00 -> 0)
586
-        $content = preg_replace('/'.$before.'-?0+'.$units.'?'.$after.'/', '0\\1', $content);
586
+        $content = preg_replace('/' . $before . '-?0+' . $units . '?' . $after . '/', '0\\1', $content);
587 587
 
588 588
         // remove zeroes where they make no sense in calc: e.g. calc(100px - 0)
589 589
         // the 0 doesn't have any effect, and this isn't even valid without unit
Please login to merge, or discard this patch.
Sources/minify/src/JS.php 2 patches
Indentation   +415 added lines, -415 removed lines patch added patch discarded remove patch
@@ -14,134 +14,134 @@  discard block
 block discarded – undo
14 14
  */
15 15
 class JS extends Minify
16 16
 {
17
-    /**
18
-     * Var-matching regex based on http://stackoverflow.com/a/9337047/802993.
19
-     *
20
-     * Note that regular expressions using that bit must have the PCRE_UTF8
21
-     * pattern modifier (/u) set.
22
-     *
23
-     * @var string
24
-     */
25
-    const REGEX_VARIABLE = '\b[$A-Z\_a-z\xaa\xb5\xba\xc0-\xd6\xd8-\xf6\xf8-\x{02c1}\x{02c6}-\x{02d1}\x{02e0}-\x{02e4}\x{02ec}\x{02ee}\x{0370}-\x{0374}\x{0376}\x{0377}\x{037a}-\x{037d}\x{0386}\x{0388}-\x{038a}\x{038c}\x{038e}-\x{03a1}\x{03a3}-\x{03f5}\x{03f7}-\x{0481}\x{048a}-\x{0527}\x{0531}-\x{0556}\x{0559}\x{0561}-\x{0587}\x{05d0}-\x{05ea}\x{05f0}-\x{05f2}\x{0620}-\x{064a}\x{066e}\x{066f}\x{0671}-\x{06d3}\x{06d5}\x{06e5}\x{06e6}\x{06ee}\x{06ef}\x{06fa}-\x{06fc}\x{06ff}\x{0710}\x{0712}-\x{072f}\x{074d}-\x{07a5}\x{07b1}\x{07ca}-\x{07ea}\x{07f4}\x{07f5}\x{07fa}\x{0800}-\x{0815}\x{081a}\x{0824}\x{0828}\x{0840}-\x{0858}\x{08a0}\x{08a2}-\x{08ac}\x{0904}-\x{0939}\x{093d}\x{0950}\x{0958}-\x{0961}\x{0971}-\x{0977}\x{0979}-\x{097f}\x{0985}-\x{098c}\x{098f}\x{0990}\x{0993}-\x{09a8}\x{09aa}-\x{09b0}\x{09b2}\x{09b6}-\x{09b9}\x{09bd}\x{09ce}\x{09dc}\x{09dd}\x{09df}-\x{09e1}\x{09f0}\x{09f1}\x{0a05}-\x{0a0a}\x{0a0f}\x{0a10}\x{0a13}-\x{0a28}\x{0a2a}-\x{0a30}\x{0a32}\x{0a33}\x{0a35}\x{0a36}\x{0a38}\x{0a39}\x{0a59}-\x{0a5c}\x{0a5e}\x{0a72}-\x{0a74}\x{0a85}-\x{0a8d}\x{0a8f}-\x{0a91}\x{0a93}-\x{0aa8}\x{0aaa}-\x{0ab0}\x{0ab2}\x{0ab3}\x{0ab5}-\x{0ab9}\x{0abd}\x{0ad0}\x{0ae0}\x{0ae1}\x{0b05}-\x{0b0c}\x{0b0f}\x{0b10}\x{0b13}-\x{0b28}\x{0b2a}-\x{0b30}\x{0b32}\x{0b33}\x{0b35}-\x{0b39}\x{0b3d}\x{0b5c}\x{0b5d}\x{0b5f}-\x{0b61}\x{0b71}\x{0b83}\x{0b85}-\x{0b8a}\x{0b8e}-\x{0b90}\x{0b92}-\x{0b95}\x{0b99}\x{0b9a}\x{0b9c}\x{0b9e}\x{0b9f}\x{0ba3}\x{0ba4}\x{0ba8}-\x{0baa}\x{0bae}-\x{0bb9}\x{0bd0}\x{0c05}-\x{0c0c}\x{0c0e}-\x{0c10}\x{0c12}-\x{0c28}\x{0c2a}-\x{0c33}\x{0c35}-\x{0c39}\x{0c3d}\x{0c58}\x{0c59}\x{0c60}\x{0c61}\x{0c85}-\x{0c8c}\x{0c8e}-\x{0c90}\x{0c92}-\x{0ca8}\x{0caa}-\x{0cb3}\x{0cb5}-\x{0cb9}\x{0cbd}\x{0cde}\x{0ce0}\x{0ce1}\x{0cf1}\x{0cf2}\x{0d05}-\x{0d0c}\x{0d0e}-\x{0d10}\x{0d12}-\x{0d3a}\x{0d3d}\x{0d4e}\x{0d60}\x{0d61}\x{0d7a}-\x{0d7f}\x{0d85}-\x{0d96}\x{0d9a}-\x{0db1}\x{0db3}-\x{0dbb}\x{0dbd}\x{0dc0}-\x{0dc6}\x{0e01}-\x{0e30}\x{0e32}\x{0e33}\x{0e40}-\x{0e46}\x{0e81}\x{0e82}\x{0e84}\x{0e87}\x{0e88}\x{0e8a}\x{0e8d}\x{0e94}-\x{0e97}\x{0e99}-\x{0e9f}\x{0ea1}-\x{0ea3}\x{0ea5}\x{0ea7}\x{0eaa}\x{0eab}\x{0ead}-\x{0eb0}\x{0eb2}\x{0eb3}\x{0ebd}\x{0ec0}-\x{0ec4}\x{0ec6}\x{0edc}-\x{0edf}\x{0f00}\x{0f40}-\x{0f47}\x{0f49}-\x{0f6c}\x{0f88}-\x{0f8c}\x{1000}-\x{102a}\x{103f}\x{1050}-\x{1055}\x{105a}-\x{105d}\x{1061}\x{1065}\x{1066}\x{106e}-\x{1070}\x{1075}-\x{1081}\x{108e}\x{10a0}-\x{10c5}\x{10c7}\x{10cd}\x{10d0}-\x{10fa}\x{10fc}-\x{1248}\x{124a}-\x{124d}\x{1250}-\x{1256}\x{1258}\x{125a}-\x{125d}\x{1260}-\x{1288}\x{128a}-\x{128d}\x{1290}-\x{12b0}\x{12b2}-\x{12b5}\x{12b8}-\x{12be}\x{12c0}\x{12c2}-\x{12c5}\x{12c8}-\x{12d6}\x{12d8}-\x{1310}\x{1312}-\x{1315}\x{1318}-\x{135a}\x{1380}-\x{138f}\x{13a0}-\x{13f4}\x{1401}-\x{166c}\x{166f}-\x{167f}\x{1681}-\x{169a}\x{16a0}-\x{16ea}\x{16ee}-\x{16f0}\x{1700}-\x{170c}\x{170e}-\x{1711}\x{1720}-\x{1731}\x{1740}-\x{1751}\x{1760}-\x{176c}\x{176e}-\x{1770}\x{1780}-\x{17b3}\x{17d7}\x{17dc}\x{1820}-\x{1877}\x{1880}-\x{18a8}\x{18aa}\x{18b0}-\x{18f5}\x{1900}-\x{191c}\x{1950}-\x{196d}\x{1970}-\x{1974}\x{1980}-\x{19ab}\x{19c1}-\x{19c7}\x{1a00}-\x{1a16}\x{1a20}-\x{1a54}\x{1aa7}\x{1b05}-\x{1b33}\x{1b45}-\x{1b4b}\x{1b83}-\x{1ba0}\x{1bae}\x{1baf}\x{1bba}-\x{1be5}\x{1c00}-\x{1c23}\x{1c4d}-\x{1c4f}\x{1c5a}-\x{1c7d}\x{1ce9}-\x{1cec}\x{1cee}-\x{1cf1}\x{1cf5}\x{1cf6}\x{1d00}-\x{1dbf}\x{1e00}-\x{1f15}\x{1f18}-\x{1f1d}\x{1f20}-\x{1f45}\x{1f48}-\x{1f4d}\x{1f50}-\x{1f57}\x{1f59}\x{1f5b}\x{1f5d}\x{1f5f}-\x{1f7d}\x{1f80}-\x{1fb4}\x{1fb6}-\x{1fbc}\x{1fbe}\x{1fc2}-\x{1fc4}\x{1fc6}-\x{1fcc}\x{1fd0}-\x{1fd3}\x{1fd6}-\x{1fdb}\x{1fe0}-\x{1fec}\x{1ff2}-\x{1ff4}\x{1ff6}-\x{1ffc}\x{2071}\x{207f}\x{2090}-\x{209c}\x{2102}\x{2107}\x{210a}-\x{2113}\x{2115}\x{2119}-\x{211d}\x{2124}\x{2126}\x{2128}\x{212a}-\x{212d}\x{212f}-\x{2139}\x{213c}-\x{213f}\x{2145}-\x{2149}\x{214e}\x{2160}-\x{2188}\x{2c00}-\x{2c2e}\x{2c30}-\x{2c5e}\x{2c60}-\x{2ce4}\x{2ceb}-\x{2cee}\x{2cf2}\x{2cf3}\x{2d00}-\x{2d25}\x{2d27}\x{2d2d}\x{2d30}-\x{2d67}\x{2d6f}\x{2d80}-\x{2d96}\x{2da0}-\x{2da6}\x{2da8}-\x{2dae}\x{2db0}-\x{2db6}\x{2db8}-\x{2dbe}\x{2dc0}-\x{2dc6}\x{2dc8}-\x{2dce}\x{2dd0}-\x{2dd6}\x{2dd8}-\x{2dde}\x{2e2f}\x{3005}-\x{3007}\x{3021}-\x{3029}\x{3031}-\x{3035}\x{3038}-\x{303c}\x{3041}-\x{3096}\x{309d}-\x{309f}\x{30a1}-\x{30fa}\x{30fc}-\x{30ff}\x{3105}-\x{312d}\x{3131}-\x{318e}\x{31a0}-\x{31ba}\x{31f0}-\x{31ff}\x{3400}-\x{4db5}\x{4e00}-\x{9fcc}\x{a000}-\x{a48c}\x{a4d0}-\x{a4fd}\x{a500}-\x{a60c}\x{a610}-\x{a61f}\x{a62a}\x{a62b}\x{a640}-\x{a66e}\x{a67f}-\x{a697}\x{a6a0}-\x{a6ef}\x{a717}-\x{a71f}\x{a722}-\x{a788}\x{a78b}-\x{a78e}\x{a790}-\x{a793}\x{a7a0}-\x{a7aa}\x{a7f8}-\x{a801}\x{a803}-\x{a805}\x{a807}-\x{a80a}\x{a80c}-\x{a822}\x{a840}-\x{a873}\x{a882}-\x{a8b3}\x{a8f2}-\x{a8f7}\x{a8fb}\x{a90a}-\x{a925}\x{a930}-\x{a946}\x{a960}-\x{a97c}\x{a984}-\x{a9b2}\x{a9cf}\x{aa00}-\x{aa28}\x{aa40}-\x{aa42}\x{aa44}-\x{aa4b}\x{aa60}-\x{aa76}\x{aa7a}\x{aa80}-\x{aaaf}\x{aab1}\x{aab5}\x{aab6}\x{aab9}-\x{aabd}\x{aac0}\x{aac2}\x{aadb}-\x{aadd}\x{aae0}-\x{aaea}\x{aaf2}-\x{aaf4}\x{ab01}-\x{ab06}\x{ab09}-\x{ab0e}\x{ab11}-\x{ab16}\x{ab20}-\x{ab26}\x{ab28}-\x{ab2e}\x{abc0}-\x{abe2}\x{ac00}-\x{d7a3}\x{d7b0}-\x{d7c6}\x{d7cb}-\x{d7fb}\x{f900}-\x{fa6d}\x{fa70}-\x{fad9}\x{fb00}-\x{fb06}\x{fb13}-\x{fb17}\x{fb1d}\x{fb1f}-\x{fb28}\x{fb2a}-\x{fb36}\x{fb38}-\x{fb3c}\x{fb3e}\x{fb40}\x{fb41}\x{fb43}\x{fb44}\x{fb46}-\x{fbb1}\x{fbd3}-\x{fd3d}\x{fd50}-\x{fd8f}\x{fd92}-\x{fdc7}\x{fdf0}-\x{fdfb}\x{fe70}-\x{fe74}\x{fe76}-\x{fefc}\x{ff21}-\x{ff3a}\x{ff41}-\x{ff5a}\x{ff66}-\x{ffbe}\x{ffc2}-\x{ffc7}\x{ffca}-\x{ffcf}\x{ffd2}-\x{ffd7}\x{ffda}-\x{ffdc}][$A-Z\_a-z\xaa\xb5\xba\xc0-\xd6\xd8-\xf6\xf8-\x{02c1}\x{02c6}-\x{02d1}\x{02e0}-\x{02e4}\x{02ec}\x{02ee}\x{0370}-\x{0374}\x{0376}\x{0377}\x{037a}-\x{037d}\x{0386}\x{0388}-\x{038a}\x{038c}\x{038e}-\x{03a1}\x{03a3}-\x{03f5}\x{03f7}-\x{0481}\x{048a}-\x{0527}\x{0531}-\x{0556}\x{0559}\x{0561}-\x{0587}\x{05d0}-\x{05ea}\x{05f0}-\x{05f2}\x{0620}-\x{064a}\x{066e}\x{066f}\x{0671}-\x{06d3}\x{06d5}\x{06e5}\x{06e6}\x{06ee}\x{06ef}\x{06fa}-\x{06fc}\x{06ff}\x{0710}\x{0712}-\x{072f}\x{074d}-\x{07a5}\x{07b1}\x{07ca}-\x{07ea}\x{07f4}\x{07f5}\x{07fa}\x{0800}-\x{0815}\x{081a}\x{0824}\x{0828}\x{0840}-\x{0858}\x{08a0}\x{08a2}-\x{08ac}\x{0904}-\x{0939}\x{093d}\x{0950}\x{0958}-\x{0961}\x{0971}-\x{0977}\x{0979}-\x{097f}\x{0985}-\x{098c}\x{098f}\x{0990}\x{0993}-\x{09a8}\x{09aa}-\x{09b0}\x{09b2}\x{09b6}-\x{09b9}\x{09bd}\x{09ce}\x{09dc}\x{09dd}\x{09df}-\x{09e1}\x{09f0}\x{09f1}\x{0a05}-\x{0a0a}\x{0a0f}\x{0a10}\x{0a13}-\x{0a28}\x{0a2a}-\x{0a30}\x{0a32}\x{0a33}\x{0a35}\x{0a36}\x{0a38}\x{0a39}\x{0a59}-\x{0a5c}\x{0a5e}\x{0a72}-\x{0a74}\x{0a85}-\x{0a8d}\x{0a8f}-\x{0a91}\x{0a93}-\x{0aa8}\x{0aaa}-\x{0ab0}\x{0ab2}\x{0ab3}\x{0ab5}-\x{0ab9}\x{0abd}\x{0ad0}\x{0ae0}\x{0ae1}\x{0b05}-\x{0b0c}\x{0b0f}\x{0b10}\x{0b13}-\x{0b28}\x{0b2a}-\x{0b30}\x{0b32}\x{0b33}\x{0b35}-\x{0b39}\x{0b3d}\x{0b5c}\x{0b5d}\x{0b5f}-\x{0b61}\x{0b71}\x{0b83}\x{0b85}-\x{0b8a}\x{0b8e}-\x{0b90}\x{0b92}-\x{0b95}\x{0b99}\x{0b9a}\x{0b9c}\x{0b9e}\x{0b9f}\x{0ba3}\x{0ba4}\x{0ba8}-\x{0baa}\x{0bae}-\x{0bb9}\x{0bd0}\x{0c05}-\x{0c0c}\x{0c0e}-\x{0c10}\x{0c12}-\x{0c28}\x{0c2a}-\x{0c33}\x{0c35}-\x{0c39}\x{0c3d}\x{0c58}\x{0c59}\x{0c60}\x{0c61}\x{0c85}-\x{0c8c}\x{0c8e}-\x{0c90}\x{0c92}-\x{0ca8}\x{0caa}-\x{0cb3}\x{0cb5}-\x{0cb9}\x{0cbd}\x{0cde}\x{0ce0}\x{0ce1}\x{0cf1}\x{0cf2}\x{0d05}-\x{0d0c}\x{0d0e}-\x{0d10}\x{0d12}-\x{0d3a}\x{0d3d}\x{0d4e}\x{0d60}\x{0d61}\x{0d7a}-\x{0d7f}\x{0d85}-\x{0d96}\x{0d9a}-\x{0db1}\x{0db3}-\x{0dbb}\x{0dbd}\x{0dc0}-\x{0dc6}\x{0e01}-\x{0e30}\x{0e32}\x{0e33}\x{0e40}-\x{0e46}\x{0e81}\x{0e82}\x{0e84}\x{0e87}\x{0e88}\x{0e8a}\x{0e8d}\x{0e94}-\x{0e97}\x{0e99}-\x{0e9f}\x{0ea1}-\x{0ea3}\x{0ea5}\x{0ea7}\x{0eaa}\x{0eab}\x{0ead}-\x{0eb0}\x{0eb2}\x{0eb3}\x{0ebd}\x{0ec0}-\x{0ec4}\x{0ec6}\x{0edc}-\x{0edf}\x{0f00}\x{0f40}-\x{0f47}\x{0f49}-\x{0f6c}\x{0f88}-\x{0f8c}\x{1000}-\x{102a}\x{103f}\x{1050}-\x{1055}\x{105a}-\x{105d}\x{1061}\x{1065}\x{1066}\x{106e}-\x{1070}\x{1075}-\x{1081}\x{108e}\x{10a0}-\x{10c5}\x{10c7}\x{10cd}\x{10d0}-\x{10fa}\x{10fc}-\x{1248}\x{124a}-\x{124d}\x{1250}-\x{1256}\x{1258}\x{125a}-\x{125d}\x{1260}-\x{1288}\x{128a}-\x{128d}\x{1290}-\x{12b0}\x{12b2}-\x{12b5}\x{12b8}-\x{12be}\x{12c0}\x{12c2}-\x{12c5}\x{12c8}-\x{12d6}\x{12d8}-\x{1310}\x{1312}-\x{1315}\x{1318}-\x{135a}\x{1380}-\x{138f}\x{13a0}-\x{13f4}\x{1401}-\x{166c}\x{166f}-\x{167f}\x{1681}-\x{169a}\x{16a0}-\x{16ea}\x{16ee}-\x{16f0}\x{1700}-\x{170c}\x{170e}-\x{1711}\x{1720}-\x{1731}\x{1740}-\x{1751}\x{1760}-\x{176c}\x{176e}-\x{1770}\x{1780}-\x{17b3}\x{17d7}\x{17dc}\x{1820}-\x{1877}\x{1880}-\x{18a8}\x{18aa}\x{18b0}-\x{18f5}\x{1900}-\x{191c}\x{1950}-\x{196d}\x{1970}-\x{1974}\x{1980}-\x{19ab}\x{19c1}-\x{19c7}\x{1a00}-\x{1a16}\x{1a20}-\x{1a54}\x{1aa7}\x{1b05}-\x{1b33}\x{1b45}-\x{1b4b}\x{1b83}-\x{1ba0}\x{1bae}\x{1baf}\x{1bba}-\x{1be5}\x{1c00}-\x{1c23}\x{1c4d}-\x{1c4f}\x{1c5a}-\x{1c7d}\x{1ce9}-\x{1cec}\x{1cee}-\x{1cf1}\x{1cf5}\x{1cf6}\x{1d00}-\x{1dbf}\x{1e00}-\x{1f15}\x{1f18}-\x{1f1d}\x{1f20}-\x{1f45}\x{1f48}-\x{1f4d}\x{1f50}-\x{1f57}\x{1f59}\x{1f5b}\x{1f5d}\x{1f5f}-\x{1f7d}\x{1f80}-\x{1fb4}\x{1fb6}-\x{1fbc}\x{1fbe}\x{1fc2}-\x{1fc4}\x{1fc6}-\x{1fcc}\x{1fd0}-\x{1fd3}\x{1fd6}-\x{1fdb}\x{1fe0}-\x{1fec}\x{1ff2}-\x{1ff4}\x{1ff6}-\x{1ffc}\x{2071}\x{207f}\x{2090}-\x{209c}\x{2102}\x{2107}\x{210a}-\x{2113}\x{2115}\x{2119}-\x{211d}\x{2124}\x{2126}\x{2128}\x{212a}-\x{212d}\x{212f}-\x{2139}\x{213c}-\x{213f}\x{2145}-\x{2149}\x{214e}\x{2160}-\x{2188}\x{2c00}-\x{2c2e}\x{2c30}-\x{2c5e}\x{2c60}-\x{2ce4}\x{2ceb}-\x{2cee}\x{2cf2}\x{2cf3}\x{2d00}-\x{2d25}\x{2d27}\x{2d2d}\x{2d30}-\x{2d67}\x{2d6f}\x{2d80}-\x{2d96}\x{2da0}-\x{2da6}\x{2da8}-\x{2dae}\x{2db0}-\x{2db6}\x{2db8}-\x{2dbe}\x{2dc0}-\x{2dc6}\x{2dc8}-\x{2dce}\x{2dd0}-\x{2dd6}\x{2dd8}-\x{2dde}\x{2e2f}\x{3005}-\x{3007}\x{3021}-\x{3029}\x{3031}-\x{3035}\x{3038}-\x{303c}\x{3041}-\x{3096}\x{309d}-\x{309f}\x{30a1}-\x{30fa}\x{30fc}-\x{30ff}\x{3105}-\x{312d}\x{3131}-\x{318e}\x{31a0}-\x{31ba}\x{31f0}-\x{31ff}\x{3400}-\x{4db5}\x{4e00}-\x{9fcc}\x{a000}-\x{a48c}\x{a4d0}-\x{a4fd}\x{a500}-\x{a60c}\x{a610}-\x{a61f}\x{a62a}\x{a62b}\x{a640}-\x{a66e}\x{a67f}-\x{a697}\x{a6a0}-\x{a6ef}\x{a717}-\x{a71f}\x{a722}-\x{a788}\x{a78b}-\x{a78e}\x{a790}-\x{a793}\x{a7a0}-\x{a7aa}\x{a7f8}-\x{a801}\x{a803}-\x{a805}\x{a807}-\x{a80a}\x{a80c}-\x{a822}\x{a840}-\x{a873}\x{a882}-\x{a8b3}\x{a8f2}-\x{a8f7}\x{a8fb}\x{a90a}-\x{a925}\x{a930}-\x{a946}\x{a960}-\x{a97c}\x{a984}-\x{a9b2}\x{a9cf}\x{aa00}-\x{aa28}\x{aa40}-\x{aa42}\x{aa44}-\x{aa4b}\x{aa60}-\x{aa76}\x{aa7a}\x{aa80}-\x{aaaf}\x{aab1}\x{aab5}\x{aab6}\x{aab9}-\x{aabd}\x{aac0}\x{aac2}\x{aadb}-\x{aadd}\x{aae0}-\x{aaea}\x{aaf2}-\x{aaf4}\x{ab01}-\x{ab06}\x{ab09}-\x{ab0e}\x{ab11}-\x{ab16}\x{ab20}-\x{ab26}\x{ab28}-\x{ab2e}\x{abc0}-\x{abe2}\x{ac00}-\x{d7a3}\x{d7b0}-\x{d7c6}\x{d7cb}-\x{d7fb}\x{f900}-\x{fa6d}\x{fa70}-\x{fad9}\x{fb00}-\x{fb06}\x{fb13}-\x{fb17}\x{fb1d}\x{fb1f}-\x{fb28}\x{fb2a}-\x{fb36}\x{fb38}-\x{fb3c}\x{fb3e}\x{fb40}\x{fb41}\x{fb43}\x{fb44}\x{fb46}-\x{fbb1}\x{fbd3}-\x{fd3d}\x{fd50}-\x{fd8f}\x{fd92}-\x{fdc7}\x{fdf0}-\x{fdfb}\x{fe70}-\x{fe74}\x{fe76}-\x{fefc}\x{ff21}-\x{ff3a}\x{ff41}-\x{ff5a}\x{ff66}-\x{ffbe}\x{ffc2}-\x{ffc7}\x{ffca}-\x{ffcf}\x{ffd2}-\x{ffd7}\x{ffda}-\x{ffdc}0-9\x{0300}-\x{036f}\x{0483}-\x{0487}\x{0591}-\x{05bd}\x{05bf}\x{05c1}\x{05c2}\x{05c4}\x{05c5}\x{05c7}\x{0610}-\x{061a}\x{064b}-\x{0669}\x{0670}\x{06d6}-\x{06dc}\x{06df}-\x{06e4}\x{06e7}\x{06e8}\x{06ea}-\x{06ed}\x{06f0}-\x{06f9}\x{0711}\x{0730}-\x{074a}\x{07a6}-\x{07b0}\x{07c0}-\x{07c9}\x{07eb}-\x{07f3}\x{0816}-\x{0819}\x{081b}-\x{0823}\x{0825}-\x{0827}\x{0829}-\x{082d}\x{0859}-\x{085b}\x{08e4}-\x{08fe}\x{0900}-\x{0903}\x{093a}-\x{093c}\x{093e}-\x{094f}\x{0951}-\x{0957}\x{0962}\x{0963}\x{0966}-\x{096f}\x{0981}-\x{0983}\x{09bc}\x{09be}-\x{09c4}\x{09c7}\x{09c8}\x{09cb}-\x{09cd}\x{09d7}\x{09e2}\x{09e3}\x{09e6}-\x{09ef}\x{0a01}-\x{0a03}\x{0a3c}\x{0a3e}-\x{0a42}\x{0a47}\x{0a48}\x{0a4b}-\x{0a4d}\x{0a51}\x{0a66}-\x{0a71}\x{0a75}\x{0a81}-\x{0a83}\x{0abc}\x{0abe}-\x{0ac5}\x{0ac7}-\x{0ac9}\x{0acb}-\x{0acd}\x{0ae2}\x{0ae3}\x{0ae6}-\x{0aef}\x{0b01}-\x{0b03}\x{0b3c}\x{0b3e}-\x{0b44}\x{0b47}\x{0b48}\x{0b4b}-\x{0b4d}\x{0b56}\x{0b57}\x{0b62}\x{0b63}\x{0b66}-\x{0b6f}\x{0b82}\x{0bbe}-\x{0bc2}\x{0bc6}-\x{0bc8}\x{0bca}-\x{0bcd}\x{0bd7}\x{0be6}-\x{0bef}\x{0c01}-\x{0c03}\x{0c3e}-\x{0c44}\x{0c46}-\x{0c48}\x{0c4a}-\x{0c4d}\x{0c55}\x{0c56}\x{0c62}\x{0c63}\x{0c66}-\x{0c6f}\x{0c82}\x{0c83}\x{0cbc}\x{0cbe}-\x{0cc4}\x{0cc6}-\x{0cc8}\x{0cca}-\x{0ccd}\x{0cd5}\x{0cd6}\x{0ce2}\x{0ce3}\x{0ce6}-\x{0cef}\x{0d02}\x{0d03}\x{0d3e}-\x{0d44}\x{0d46}-\x{0d48}\x{0d4a}-\x{0d4d}\x{0d57}\x{0d62}\x{0d63}\x{0d66}-\x{0d6f}\x{0d82}\x{0d83}\x{0dca}\x{0dcf}-\x{0dd4}\x{0dd6}\x{0dd8}-\x{0ddf}\x{0df2}\x{0df3}\x{0e31}\x{0e34}-\x{0e3a}\x{0e47}-\x{0e4e}\x{0e50}-\x{0e59}\x{0eb1}\x{0eb4}-\x{0eb9}\x{0ebb}\x{0ebc}\x{0ec8}-\x{0ecd}\x{0ed0}-\x{0ed9}\x{0f18}\x{0f19}\x{0f20}-\x{0f29}\x{0f35}\x{0f37}\x{0f39}\x{0f3e}\x{0f3f}\x{0f71}-\x{0f84}\x{0f86}\x{0f87}\x{0f8d}-\x{0f97}\x{0f99}-\x{0fbc}\x{0fc6}\x{102b}-\x{103e}\x{1040}-\x{1049}\x{1056}-\x{1059}\x{105e}-\x{1060}\x{1062}-\x{1064}\x{1067}-\x{106d}\x{1071}-\x{1074}\x{1082}-\x{108d}\x{108f}-\x{109d}\x{135d}-\x{135f}\x{1712}-\x{1714}\x{1732}-\x{1734}\x{1752}\x{1753}\x{1772}\x{1773}\x{17b4}-\x{17d3}\x{17dd}\x{17e0}-\x{17e9}\x{180b}-\x{180d}\x{1810}-\x{1819}\x{18a9}\x{1920}-\x{192b}\x{1930}-\x{193b}\x{1946}-\x{194f}\x{19b0}-\x{19c0}\x{19c8}\x{19c9}\x{19d0}-\x{19d9}\x{1a17}-\x{1a1b}\x{1a55}-\x{1a5e}\x{1a60}-\x{1a7c}\x{1a7f}-\x{1a89}\x{1a90}-\x{1a99}\x{1b00}-\x{1b04}\x{1b34}-\x{1b44}\x{1b50}-\x{1b59}\x{1b6b}-\x{1b73}\x{1b80}-\x{1b82}\x{1ba1}-\x{1bad}\x{1bb0}-\x{1bb9}\x{1be6}-\x{1bf3}\x{1c24}-\x{1c37}\x{1c40}-\x{1c49}\x{1c50}-\x{1c59}\x{1cd0}-\x{1cd2}\x{1cd4}-\x{1ce8}\x{1ced}\x{1cf2}-\x{1cf4}\x{1dc0}-\x{1de6}\x{1dfc}-\x{1dff}\x{200c}\x{200d}\x{203f}\x{2040}\x{2054}\x{20d0}-\x{20dc}\x{20e1}\x{20e5}-\x{20f0}\x{2cef}-\x{2cf1}\x{2d7f}\x{2de0}-\x{2dff}\x{302a}-\x{302f}\x{3099}\x{309a}\x{a620}-\x{a629}\x{a66f}\x{a674}-\x{a67d}\x{a69f}\x{a6f0}\x{a6f1}\x{a802}\x{a806}\x{a80b}\x{a823}-\x{a827}\x{a880}\x{a881}\x{a8b4}-\x{a8c4}\x{a8d0}-\x{a8d9}\x{a8e0}-\x{a8f1}\x{a900}-\x{a909}\x{a926}-\x{a92d}\x{a947}-\x{a953}\x{a980}-\x{a983}\x{a9b3}-\x{a9c0}\x{a9d0}-\x{a9d9}\x{aa29}-\x{aa36}\x{aa43}\x{aa4c}\x{aa4d}\x{aa50}-\x{aa59}\x{aa7b}\x{aab0}\x{aab2}-\x{aab4}\x{aab7}\x{aab8}\x{aabe}\x{aabf}\x{aac1}\x{aaeb}-\x{aaef}\x{aaf5}\x{aaf6}\x{abe3}-\x{abea}\x{abec}\x{abed}\x{abf0}-\x{abf9}\x{fb1e}\x{fe00}-\x{fe0f}\x{fe20}-\x{fe26}\x{fe33}\x{fe34}\x{fe4d}-\x{fe4f}\x{ff10}-\x{ff19}\x{ff3f}]*\b';
26
-
27
-    /**
28
-     * Full list of JavaScript reserved words.
29
-     * Will be loaded from /data/js/keywords_reserved.txt.
30
-     *
31
-     * @see https://mathiasbynens.be/notes/reserved-keywords
32
-     *
33
-     * @var string[]
34
-     */
35
-    protected $keywordsReserved = array();
36
-
37
-    /**
38
-     * List of JavaScript reserved words that accept a <variable, value, ...>
39
-     * after them. Some end of lines are not the end of a statement, like with
40
-     * these keywords.
41
-     *
42
-     * E.g.: we shouldn't insert a ; after this else
43
-     * else
44
-     *     console.log('this is quite fine')
45
-     *
46
-     * Will be loaded from /data/js/keywords_before.txt
47
-     *
48
-     * @var string[]
49
-     */
50
-    protected $keywordsBefore = array();
51
-
52
-    /**
53
-     * List of JavaScript reserved words that accept a <variable, value, ...>
54
-     * before them. Some end of lines are not the end of a statement, like when
55
-     * continued by one of these keywords on the newline.
56
-     *
57
-     * E.g.: we shouldn't insert a ; before this instanceof
58
-     * variable
59
-     *     instanceof String
60
-     *
61
-     * Will be loaded from /data/js/keywords_after.txt
62
-     *
63
-     * @var string[]
64
-     */
65
-    protected $keywordsAfter = array();
66
-
67
-    /**
68
-     * List of all JavaScript operators.
69
-     *
70
-     * Will be loaded from /data/js/operators.txt
71
-     *
72
-     * @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Expressions_and_Operators
73
-     *
74
-     * @var string[]
75
-     */
76
-    protected $operators = array();
77
-
78
-    /**
79
-     * List of JavaScript operators that accept a <variable, value, ...> after
80
-     * them. Some end of lines are not the end of a statement, like with these
81
-     * operators.
82
-     *
83
-     * Note: Most operators are fine, we've only removed !, ++ and --.
84
-     * There can't be a newline separating ! and whatever it is negating.
85
-     * ++ & -- have to be joined with the value they're in-/decrementing.
86
-     *
87
-     * Will be loaded from /data/js/operators_before.txt
88
-     *
89
-     * @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Expressions_and_Operators
90
-     *
91
-     * @var string[]
92
-     */
93
-    protected $operatorsBefore = array();
94
-
95
-    /**
96
-     * List of JavaScript operators that accept a <variable, value, ...> before
97
-     * them. Some end of lines are not the end of a statement, like when
98
-     * continued by one of these operators on the newline.
99
-     *
100
-     * Note: Most operators are fine, we've only removed ), ], ++ and --.
101
-     * ++ & -- have to be joined with the value they're in-/decrementing.
102
-     * ) & ] are "special" in that they have lots or usecases. () for example
103
-     * is used for function calls, for grouping, in if () and for (), ...
104
-     *
105
-     * Will be loaded from /data/js/operators_after.txt
106
-     *
107
-     * @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Expressions_and_Operators
108
-     *
109
-     * @var string[]
110
-     */
111
-    protected $operatorsAfter = array();
112
-
113
-    /**
114
-     * {@inheritdoc}
115
-     */
116
-    public function __construct()
117
-    {
118
-        call_user_func_array(array('parent', '__construct'), func_get_args());
119
-
120
-        $dataDir = __DIR__.'/../data/js/';
121
-        $options = FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES;
122
-        $this->keywordsReserved = file($dataDir.'keywords_reserved.txt', $options);
123
-        $this->keywordsBefore = file($dataDir.'keywords_before.txt', $options);
124
-        $this->keywordsAfter = file($dataDir.'keywords_after.txt', $options);
125
-        $this->operators = file($dataDir.'operators.txt', $options);
126
-        $this->operatorsBefore = file($dataDir.'operators_before.txt', $options);
127
-        $this->operatorsAfter = file($dataDir.'operators_after.txt', $options);
128
-    }
129
-
130
-    /**
131
-     * Minify the data.
132
-     * Perform JS optimizations.
133
-     *
134
-     * @param string[optional] $path Path to write the data to
135
-     *
136
-     * @return string The minified data
137
-     */
138
-    public function execute($path = null)
139
-    {
140
-        $content = '';
141
-
142
-        // loop files
143
-        foreach ($this->data as $source => $js) {
144
-            /*
17
+	/**
18
+	 * Var-matching regex based on http://stackoverflow.com/a/9337047/802993.
19
+	 *
20
+	 * Note that regular expressions using that bit must have the PCRE_UTF8
21
+	 * pattern modifier (/u) set.
22
+	 *
23
+	 * @var string
24
+	 */
25
+	const REGEX_VARIABLE = '\b[$A-Z\_a-z\xaa\xb5\xba\xc0-\xd6\xd8-\xf6\xf8-\x{02c1}\x{02c6}-\x{02d1}\x{02e0}-\x{02e4}\x{02ec}\x{02ee}\x{0370}-\x{0374}\x{0376}\x{0377}\x{037a}-\x{037d}\x{0386}\x{0388}-\x{038a}\x{038c}\x{038e}-\x{03a1}\x{03a3}-\x{03f5}\x{03f7}-\x{0481}\x{048a}-\x{0527}\x{0531}-\x{0556}\x{0559}\x{0561}-\x{0587}\x{05d0}-\x{05ea}\x{05f0}-\x{05f2}\x{0620}-\x{064a}\x{066e}\x{066f}\x{0671}-\x{06d3}\x{06d5}\x{06e5}\x{06e6}\x{06ee}\x{06ef}\x{06fa}-\x{06fc}\x{06ff}\x{0710}\x{0712}-\x{072f}\x{074d}-\x{07a5}\x{07b1}\x{07ca}-\x{07ea}\x{07f4}\x{07f5}\x{07fa}\x{0800}-\x{0815}\x{081a}\x{0824}\x{0828}\x{0840}-\x{0858}\x{08a0}\x{08a2}-\x{08ac}\x{0904}-\x{0939}\x{093d}\x{0950}\x{0958}-\x{0961}\x{0971}-\x{0977}\x{0979}-\x{097f}\x{0985}-\x{098c}\x{098f}\x{0990}\x{0993}-\x{09a8}\x{09aa}-\x{09b0}\x{09b2}\x{09b6}-\x{09b9}\x{09bd}\x{09ce}\x{09dc}\x{09dd}\x{09df}-\x{09e1}\x{09f0}\x{09f1}\x{0a05}-\x{0a0a}\x{0a0f}\x{0a10}\x{0a13}-\x{0a28}\x{0a2a}-\x{0a30}\x{0a32}\x{0a33}\x{0a35}\x{0a36}\x{0a38}\x{0a39}\x{0a59}-\x{0a5c}\x{0a5e}\x{0a72}-\x{0a74}\x{0a85}-\x{0a8d}\x{0a8f}-\x{0a91}\x{0a93}-\x{0aa8}\x{0aaa}-\x{0ab0}\x{0ab2}\x{0ab3}\x{0ab5}-\x{0ab9}\x{0abd}\x{0ad0}\x{0ae0}\x{0ae1}\x{0b05}-\x{0b0c}\x{0b0f}\x{0b10}\x{0b13}-\x{0b28}\x{0b2a}-\x{0b30}\x{0b32}\x{0b33}\x{0b35}-\x{0b39}\x{0b3d}\x{0b5c}\x{0b5d}\x{0b5f}-\x{0b61}\x{0b71}\x{0b83}\x{0b85}-\x{0b8a}\x{0b8e}-\x{0b90}\x{0b92}-\x{0b95}\x{0b99}\x{0b9a}\x{0b9c}\x{0b9e}\x{0b9f}\x{0ba3}\x{0ba4}\x{0ba8}-\x{0baa}\x{0bae}-\x{0bb9}\x{0bd0}\x{0c05}-\x{0c0c}\x{0c0e}-\x{0c10}\x{0c12}-\x{0c28}\x{0c2a}-\x{0c33}\x{0c35}-\x{0c39}\x{0c3d}\x{0c58}\x{0c59}\x{0c60}\x{0c61}\x{0c85}-\x{0c8c}\x{0c8e}-\x{0c90}\x{0c92}-\x{0ca8}\x{0caa}-\x{0cb3}\x{0cb5}-\x{0cb9}\x{0cbd}\x{0cde}\x{0ce0}\x{0ce1}\x{0cf1}\x{0cf2}\x{0d05}-\x{0d0c}\x{0d0e}-\x{0d10}\x{0d12}-\x{0d3a}\x{0d3d}\x{0d4e}\x{0d60}\x{0d61}\x{0d7a}-\x{0d7f}\x{0d85}-\x{0d96}\x{0d9a}-\x{0db1}\x{0db3}-\x{0dbb}\x{0dbd}\x{0dc0}-\x{0dc6}\x{0e01}-\x{0e30}\x{0e32}\x{0e33}\x{0e40}-\x{0e46}\x{0e81}\x{0e82}\x{0e84}\x{0e87}\x{0e88}\x{0e8a}\x{0e8d}\x{0e94}-\x{0e97}\x{0e99}-\x{0e9f}\x{0ea1}-\x{0ea3}\x{0ea5}\x{0ea7}\x{0eaa}\x{0eab}\x{0ead}-\x{0eb0}\x{0eb2}\x{0eb3}\x{0ebd}\x{0ec0}-\x{0ec4}\x{0ec6}\x{0edc}-\x{0edf}\x{0f00}\x{0f40}-\x{0f47}\x{0f49}-\x{0f6c}\x{0f88}-\x{0f8c}\x{1000}-\x{102a}\x{103f}\x{1050}-\x{1055}\x{105a}-\x{105d}\x{1061}\x{1065}\x{1066}\x{106e}-\x{1070}\x{1075}-\x{1081}\x{108e}\x{10a0}-\x{10c5}\x{10c7}\x{10cd}\x{10d0}-\x{10fa}\x{10fc}-\x{1248}\x{124a}-\x{124d}\x{1250}-\x{1256}\x{1258}\x{125a}-\x{125d}\x{1260}-\x{1288}\x{128a}-\x{128d}\x{1290}-\x{12b0}\x{12b2}-\x{12b5}\x{12b8}-\x{12be}\x{12c0}\x{12c2}-\x{12c5}\x{12c8}-\x{12d6}\x{12d8}-\x{1310}\x{1312}-\x{1315}\x{1318}-\x{135a}\x{1380}-\x{138f}\x{13a0}-\x{13f4}\x{1401}-\x{166c}\x{166f}-\x{167f}\x{1681}-\x{169a}\x{16a0}-\x{16ea}\x{16ee}-\x{16f0}\x{1700}-\x{170c}\x{170e}-\x{1711}\x{1720}-\x{1731}\x{1740}-\x{1751}\x{1760}-\x{176c}\x{176e}-\x{1770}\x{1780}-\x{17b3}\x{17d7}\x{17dc}\x{1820}-\x{1877}\x{1880}-\x{18a8}\x{18aa}\x{18b0}-\x{18f5}\x{1900}-\x{191c}\x{1950}-\x{196d}\x{1970}-\x{1974}\x{1980}-\x{19ab}\x{19c1}-\x{19c7}\x{1a00}-\x{1a16}\x{1a20}-\x{1a54}\x{1aa7}\x{1b05}-\x{1b33}\x{1b45}-\x{1b4b}\x{1b83}-\x{1ba0}\x{1bae}\x{1baf}\x{1bba}-\x{1be5}\x{1c00}-\x{1c23}\x{1c4d}-\x{1c4f}\x{1c5a}-\x{1c7d}\x{1ce9}-\x{1cec}\x{1cee}-\x{1cf1}\x{1cf5}\x{1cf6}\x{1d00}-\x{1dbf}\x{1e00}-\x{1f15}\x{1f18}-\x{1f1d}\x{1f20}-\x{1f45}\x{1f48}-\x{1f4d}\x{1f50}-\x{1f57}\x{1f59}\x{1f5b}\x{1f5d}\x{1f5f}-\x{1f7d}\x{1f80}-\x{1fb4}\x{1fb6}-\x{1fbc}\x{1fbe}\x{1fc2}-\x{1fc4}\x{1fc6}-\x{1fcc}\x{1fd0}-\x{1fd3}\x{1fd6}-\x{1fdb}\x{1fe0}-\x{1fec}\x{1ff2}-\x{1ff4}\x{1ff6}-\x{1ffc}\x{2071}\x{207f}\x{2090}-\x{209c}\x{2102}\x{2107}\x{210a}-\x{2113}\x{2115}\x{2119}-\x{211d}\x{2124}\x{2126}\x{2128}\x{212a}-\x{212d}\x{212f}-\x{2139}\x{213c}-\x{213f}\x{2145}-\x{2149}\x{214e}\x{2160}-\x{2188}\x{2c00}-\x{2c2e}\x{2c30}-\x{2c5e}\x{2c60}-\x{2ce4}\x{2ceb}-\x{2cee}\x{2cf2}\x{2cf3}\x{2d00}-\x{2d25}\x{2d27}\x{2d2d}\x{2d30}-\x{2d67}\x{2d6f}\x{2d80}-\x{2d96}\x{2da0}-\x{2da6}\x{2da8}-\x{2dae}\x{2db0}-\x{2db6}\x{2db8}-\x{2dbe}\x{2dc0}-\x{2dc6}\x{2dc8}-\x{2dce}\x{2dd0}-\x{2dd6}\x{2dd8}-\x{2dde}\x{2e2f}\x{3005}-\x{3007}\x{3021}-\x{3029}\x{3031}-\x{3035}\x{3038}-\x{303c}\x{3041}-\x{3096}\x{309d}-\x{309f}\x{30a1}-\x{30fa}\x{30fc}-\x{30ff}\x{3105}-\x{312d}\x{3131}-\x{318e}\x{31a0}-\x{31ba}\x{31f0}-\x{31ff}\x{3400}-\x{4db5}\x{4e00}-\x{9fcc}\x{a000}-\x{a48c}\x{a4d0}-\x{a4fd}\x{a500}-\x{a60c}\x{a610}-\x{a61f}\x{a62a}\x{a62b}\x{a640}-\x{a66e}\x{a67f}-\x{a697}\x{a6a0}-\x{a6ef}\x{a717}-\x{a71f}\x{a722}-\x{a788}\x{a78b}-\x{a78e}\x{a790}-\x{a793}\x{a7a0}-\x{a7aa}\x{a7f8}-\x{a801}\x{a803}-\x{a805}\x{a807}-\x{a80a}\x{a80c}-\x{a822}\x{a840}-\x{a873}\x{a882}-\x{a8b3}\x{a8f2}-\x{a8f7}\x{a8fb}\x{a90a}-\x{a925}\x{a930}-\x{a946}\x{a960}-\x{a97c}\x{a984}-\x{a9b2}\x{a9cf}\x{aa00}-\x{aa28}\x{aa40}-\x{aa42}\x{aa44}-\x{aa4b}\x{aa60}-\x{aa76}\x{aa7a}\x{aa80}-\x{aaaf}\x{aab1}\x{aab5}\x{aab6}\x{aab9}-\x{aabd}\x{aac0}\x{aac2}\x{aadb}-\x{aadd}\x{aae0}-\x{aaea}\x{aaf2}-\x{aaf4}\x{ab01}-\x{ab06}\x{ab09}-\x{ab0e}\x{ab11}-\x{ab16}\x{ab20}-\x{ab26}\x{ab28}-\x{ab2e}\x{abc0}-\x{abe2}\x{ac00}-\x{d7a3}\x{d7b0}-\x{d7c6}\x{d7cb}-\x{d7fb}\x{f900}-\x{fa6d}\x{fa70}-\x{fad9}\x{fb00}-\x{fb06}\x{fb13}-\x{fb17}\x{fb1d}\x{fb1f}-\x{fb28}\x{fb2a}-\x{fb36}\x{fb38}-\x{fb3c}\x{fb3e}\x{fb40}\x{fb41}\x{fb43}\x{fb44}\x{fb46}-\x{fbb1}\x{fbd3}-\x{fd3d}\x{fd50}-\x{fd8f}\x{fd92}-\x{fdc7}\x{fdf0}-\x{fdfb}\x{fe70}-\x{fe74}\x{fe76}-\x{fefc}\x{ff21}-\x{ff3a}\x{ff41}-\x{ff5a}\x{ff66}-\x{ffbe}\x{ffc2}-\x{ffc7}\x{ffca}-\x{ffcf}\x{ffd2}-\x{ffd7}\x{ffda}-\x{ffdc}][$A-Z\_a-z\xaa\xb5\xba\xc0-\xd6\xd8-\xf6\xf8-\x{02c1}\x{02c6}-\x{02d1}\x{02e0}-\x{02e4}\x{02ec}\x{02ee}\x{0370}-\x{0374}\x{0376}\x{0377}\x{037a}-\x{037d}\x{0386}\x{0388}-\x{038a}\x{038c}\x{038e}-\x{03a1}\x{03a3}-\x{03f5}\x{03f7}-\x{0481}\x{048a}-\x{0527}\x{0531}-\x{0556}\x{0559}\x{0561}-\x{0587}\x{05d0}-\x{05ea}\x{05f0}-\x{05f2}\x{0620}-\x{064a}\x{066e}\x{066f}\x{0671}-\x{06d3}\x{06d5}\x{06e5}\x{06e6}\x{06ee}\x{06ef}\x{06fa}-\x{06fc}\x{06ff}\x{0710}\x{0712}-\x{072f}\x{074d}-\x{07a5}\x{07b1}\x{07ca}-\x{07ea}\x{07f4}\x{07f5}\x{07fa}\x{0800}-\x{0815}\x{081a}\x{0824}\x{0828}\x{0840}-\x{0858}\x{08a0}\x{08a2}-\x{08ac}\x{0904}-\x{0939}\x{093d}\x{0950}\x{0958}-\x{0961}\x{0971}-\x{0977}\x{0979}-\x{097f}\x{0985}-\x{098c}\x{098f}\x{0990}\x{0993}-\x{09a8}\x{09aa}-\x{09b0}\x{09b2}\x{09b6}-\x{09b9}\x{09bd}\x{09ce}\x{09dc}\x{09dd}\x{09df}-\x{09e1}\x{09f0}\x{09f1}\x{0a05}-\x{0a0a}\x{0a0f}\x{0a10}\x{0a13}-\x{0a28}\x{0a2a}-\x{0a30}\x{0a32}\x{0a33}\x{0a35}\x{0a36}\x{0a38}\x{0a39}\x{0a59}-\x{0a5c}\x{0a5e}\x{0a72}-\x{0a74}\x{0a85}-\x{0a8d}\x{0a8f}-\x{0a91}\x{0a93}-\x{0aa8}\x{0aaa}-\x{0ab0}\x{0ab2}\x{0ab3}\x{0ab5}-\x{0ab9}\x{0abd}\x{0ad0}\x{0ae0}\x{0ae1}\x{0b05}-\x{0b0c}\x{0b0f}\x{0b10}\x{0b13}-\x{0b28}\x{0b2a}-\x{0b30}\x{0b32}\x{0b33}\x{0b35}-\x{0b39}\x{0b3d}\x{0b5c}\x{0b5d}\x{0b5f}-\x{0b61}\x{0b71}\x{0b83}\x{0b85}-\x{0b8a}\x{0b8e}-\x{0b90}\x{0b92}-\x{0b95}\x{0b99}\x{0b9a}\x{0b9c}\x{0b9e}\x{0b9f}\x{0ba3}\x{0ba4}\x{0ba8}-\x{0baa}\x{0bae}-\x{0bb9}\x{0bd0}\x{0c05}-\x{0c0c}\x{0c0e}-\x{0c10}\x{0c12}-\x{0c28}\x{0c2a}-\x{0c33}\x{0c35}-\x{0c39}\x{0c3d}\x{0c58}\x{0c59}\x{0c60}\x{0c61}\x{0c85}-\x{0c8c}\x{0c8e}-\x{0c90}\x{0c92}-\x{0ca8}\x{0caa}-\x{0cb3}\x{0cb5}-\x{0cb9}\x{0cbd}\x{0cde}\x{0ce0}\x{0ce1}\x{0cf1}\x{0cf2}\x{0d05}-\x{0d0c}\x{0d0e}-\x{0d10}\x{0d12}-\x{0d3a}\x{0d3d}\x{0d4e}\x{0d60}\x{0d61}\x{0d7a}-\x{0d7f}\x{0d85}-\x{0d96}\x{0d9a}-\x{0db1}\x{0db3}-\x{0dbb}\x{0dbd}\x{0dc0}-\x{0dc6}\x{0e01}-\x{0e30}\x{0e32}\x{0e33}\x{0e40}-\x{0e46}\x{0e81}\x{0e82}\x{0e84}\x{0e87}\x{0e88}\x{0e8a}\x{0e8d}\x{0e94}-\x{0e97}\x{0e99}-\x{0e9f}\x{0ea1}-\x{0ea3}\x{0ea5}\x{0ea7}\x{0eaa}\x{0eab}\x{0ead}-\x{0eb0}\x{0eb2}\x{0eb3}\x{0ebd}\x{0ec0}-\x{0ec4}\x{0ec6}\x{0edc}-\x{0edf}\x{0f00}\x{0f40}-\x{0f47}\x{0f49}-\x{0f6c}\x{0f88}-\x{0f8c}\x{1000}-\x{102a}\x{103f}\x{1050}-\x{1055}\x{105a}-\x{105d}\x{1061}\x{1065}\x{1066}\x{106e}-\x{1070}\x{1075}-\x{1081}\x{108e}\x{10a0}-\x{10c5}\x{10c7}\x{10cd}\x{10d0}-\x{10fa}\x{10fc}-\x{1248}\x{124a}-\x{124d}\x{1250}-\x{1256}\x{1258}\x{125a}-\x{125d}\x{1260}-\x{1288}\x{128a}-\x{128d}\x{1290}-\x{12b0}\x{12b2}-\x{12b5}\x{12b8}-\x{12be}\x{12c0}\x{12c2}-\x{12c5}\x{12c8}-\x{12d6}\x{12d8}-\x{1310}\x{1312}-\x{1315}\x{1318}-\x{135a}\x{1380}-\x{138f}\x{13a0}-\x{13f4}\x{1401}-\x{166c}\x{166f}-\x{167f}\x{1681}-\x{169a}\x{16a0}-\x{16ea}\x{16ee}-\x{16f0}\x{1700}-\x{170c}\x{170e}-\x{1711}\x{1720}-\x{1731}\x{1740}-\x{1751}\x{1760}-\x{176c}\x{176e}-\x{1770}\x{1780}-\x{17b3}\x{17d7}\x{17dc}\x{1820}-\x{1877}\x{1880}-\x{18a8}\x{18aa}\x{18b0}-\x{18f5}\x{1900}-\x{191c}\x{1950}-\x{196d}\x{1970}-\x{1974}\x{1980}-\x{19ab}\x{19c1}-\x{19c7}\x{1a00}-\x{1a16}\x{1a20}-\x{1a54}\x{1aa7}\x{1b05}-\x{1b33}\x{1b45}-\x{1b4b}\x{1b83}-\x{1ba0}\x{1bae}\x{1baf}\x{1bba}-\x{1be5}\x{1c00}-\x{1c23}\x{1c4d}-\x{1c4f}\x{1c5a}-\x{1c7d}\x{1ce9}-\x{1cec}\x{1cee}-\x{1cf1}\x{1cf5}\x{1cf6}\x{1d00}-\x{1dbf}\x{1e00}-\x{1f15}\x{1f18}-\x{1f1d}\x{1f20}-\x{1f45}\x{1f48}-\x{1f4d}\x{1f50}-\x{1f57}\x{1f59}\x{1f5b}\x{1f5d}\x{1f5f}-\x{1f7d}\x{1f80}-\x{1fb4}\x{1fb6}-\x{1fbc}\x{1fbe}\x{1fc2}-\x{1fc4}\x{1fc6}-\x{1fcc}\x{1fd0}-\x{1fd3}\x{1fd6}-\x{1fdb}\x{1fe0}-\x{1fec}\x{1ff2}-\x{1ff4}\x{1ff6}-\x{1ffc}\x{2071}\x{207f}\x{2090}-\x{209c}\x{2102}\x{2107}\x{210a}-\x{2113}\x{2115}\x{2119}-\x{211d}\x{2124}\x{2126}\x{2128}\x{212a}-\x{212d}\x{212f}-\x{2139}\x{213c}-\x{213f}\x{2145}-\x{2149}\x{214e}\x{2160}-\x{2188}\x{2c00}-\x{2c2e}\x{2c30}-\x{2c5e}\x{2c60}-\x{2ce4}\x{2ceb}-\x{2cee}\x{2cf2}\x{2cf3}\x{2d00}-\x{2d25}\x{2d27}\x{2d2d}\x{2d30}-\x{2d67}\x{2d6f}\x{2d80}-\x{2d96}\x{2da0}-\x{2da6}\x{2da8}-\x{2dae}\x{2db0}-\x{2db6}\x{2db8}-\x{2dbe}\x{2dc0}-\x{2dc6}\x{2dc8}-\x{2dce}\x{2dd0}-\x{2dd6}\x{2dd8}-\x{2dde}\x{2e2f}\x{3005}-\x{3007}\x{3021}-\x{3029}\x{3031}-\x{3035}\x{3038}-\x{303c}\x{3041}-\x{3096}\x{309d}-\x{309f}\x{30a1}-\x{30fa}\x{30fc}-\x{30ff}\x{3105}-\x{312d}\x{3131}-\x{318e}\x{31a0}-\x{31ba}\x{31f0}-\x{31ff}\x{3400}-\x{4db5}\x{4e00}-\x{9fcc}\x{a000}-\x{a48c}\x{a4d0}-\x{a4fd}\x{a500}-\x{a60c}\x{a610}-\x{a61f}\x{a62a}\x{a62b}\x{a640}-\x{a66e}\x{a67f}-\x{a697}\x{a6a0}-\x{a6ef}\x{a717}-\x{a71f}\x{a722}-\x{a788}\x{a78b}-\x{a78e}\x{a790}-\x{a793}\x{a7a0}-\x{a7aa}\x{a7f8}-\x{a801}\x{a803}-\x{a805}\x{a807}-\x{a80a}\x{a80c}-\x{a822}\x{a840}-\x{a873}\x{a882}-\x{a8b3}\x{a8f2}-\x{a8f7}\x{a8fb}\x{a90a}-\x{a925}\x{a930}-\x{a946}\x{a960}-\x{a97c}\x{a984}-\x{a9b2}\x{a9cf}\x{aa00}-\x{aa28}\x{aa40}-\x{aa42}\x{aa44}-\x{aa4b}\x{aa60}-\x{aa76}\x{aa7a}\x{aa80}-\x{aaaf}\x{aab1}\x{aab5}\x{aab6}\x{aab9}-\x{aabd}\x{aac0}\x{aac2}\x{aadb}-\x{aadd}\x{aae0}-\x{aaea}\x{aaf2}-\x{aaf4}\x{ab01}-\x{ab06}\x{ab09}-\x{ab0e}\x{ab11}-\x{ab16}\x{ab20}-\x{ab26}\x{ab28}-\x{ab2e}\x{abc0}-\x{abe2}\x{ac00}-\x{d7a3}\x{d7b0}-\x{d7c6}\x{d7cb}-\x{d7fb}\x{f900}-\x{fa6d}\x{fa70}-\x{fad9}\x{fb00}-\x{fb06}\x{fb13}-\x{fb17}\x{fb1d}\x{fb1f}-\x{fb28}\x{fb2a}-\x{fb36}\x{fb38}-\x{fb3c}\x{fb3e}\x{fb40}\x{fb41}\x{fb43}\x{fb44}\x{fb46}-\x{fbb1}\x{fbd3}-\x{fd3d}\x{fd50}-\x{fd8f}\x{fd92}-\x{fdc7}\x{fdf0}-\x{fdfb}\x{fe70}-\x{fe74}\x{fe76}-\x{fefc}\x{ff21}-\x{ff3a}\x{ff41}-\x{ff5a}\x{ff66}-\x{ffbe}\x{ffc2}-\x{ffc7}\x{ffca}-\x{ffcf}\x{ffd2}-\x{ffd7}\x{ffda}-\x{ffdc}0-9\x{0300}-\x{036f}\x{0483}-\x{0487}\x{0591}-\x{05bd}\x{05bf}\x{05c1}\x{05c2}\x{05c4}\x{05c5}\x{05c7}\x{0610}-\x{061a}\x{064b}-\x{0669}\x{0670}\x{06d6}-\x{06dc}\x{06df}-\x{06e4}\x{06e7}\x{06e8}\x{06ea}-\x{06ed}\x{06f0}-\x{06f9}\x{0711}\x{0730}-\x{074a}\x{07a6}-\x{07b0}\x{07c0}-\x{07c9}\x{07eb}-\x{07f3}\x{0816}-\x{0819}\x{081b}-\x{0823}\x{0825}-\x{0827}\x{0829}-\x{082d}\x{0859}-\x{085b}\x{08e4}-\x{08fe}\x{0900}-\x{0903}\x{093a}-\x{093c}\x{093e}-\x{094f}\x{0951}-\x{0957}\x{0962}\x{0963}\x{0966}-\x{096f}\x{0981}-\x{0983}\x{09bc}\x{09be}-\x{09c4}\x{09c7}\x{09c8}\x{09cb}-\x{09cd}\x{09d7}\x{09e2}\x{09e3}\x{09e6}-\x{09ef}\x{0a01}-\x{0a03}\x{0a3c}\x{0a3e}-\x{0a42}\x{0a47}\x{0a48}\x{0a4b}-\x{0a4d}\x{0a51}\x{0a66}-\x{0a71}\x{0a75}\x{0a81}-\x{0a83}\x{0abc}\x{0abe}-\x{0ac5}\x{0ac7}-\x{0ac9}\x{0acb}-\x{0acd}\x{0ae2}\x{0ae3}\x{0ae6}-\x{0aef}\x{0b01}-\x{0b03}\x{0b3c}\x{0b3e}-\x{0b44}\x{0b47}\x{0b48}\x{0b4b}-\x{0b4d}\x{0b56}\x{0b57}\x{0b62}\x{0b63}\x{0b66}-\x{0b6f}\x{0b82}\x{0bbe}-\x{0bc2}\x{0bc6}-\x{0bc8}\x{0bca}-\x{0bcd}\x{0bd7}\x{0be6}-\x{0bef}\x{0c01}-\x{0c03}\x{0c3e}-\x{0c44}\x{0c46}-\x{0c48}\x{0c4a}-\x{0c4d}\x{0c55}\x{0c56}\x{0c62}\x{0c63}\x{0c66}-\x{0c6f}\x{0c82}\x{0c83}\x{0cbc}\x{0cbe}-\x{0cc4}\x{0cc6}-\x{0cc8}\x{0cca}-\x{0ccd}\x{0cd5}\x{0cd6}\x{0ce2}\x{0ce3}\x{0ce6}-\x{0cef}\x{0d02}\x{0d03}\x{0d3e}-\x{0d44}\x{0d46}-\x{0d48}\x{0d4a}-\x{0d4d}\x{0d57}\x{0d62}\x{0d63}\x{0d66}-\x{0d6f}\x{0d82}\x{0d83}\x{0dca}\x{0dcf}-\x{0dd4}\x{0dd6}\x{0dd8}-\x{0ddf}\x{0df2}\x{0df3}\x{0e31}\x{0e34}-\x{0e3a}\x{0e47}-\x{0e4e}\x{0e50}-\x{0e59}\x{0eb1}\x{0eb4}-\x{0eb9}\x{0ebb}\x{0ebc}\x{0ec8}-\x{0ecd}\x{0ed0}-\x{0ed9}\x{0f18}\x{0f19}\x{0f20}-\x{0f29}\x{0f35}\x{0f37}\x{0f39}\x{0f3e}\x{0f3f}\x{0f71}-\x{0f84}\x{0f86}\x{0f87}\x{0f8d}-\x{0f97}\x{0f99}-\x{0fbc}\x{0fc6}\x{102b}-\x{103e}\x{1040}-\x{1049}\x{1056}-\x{1059}\x{105e}-\x{1060}\x{1062}-\x{1064}\x{1067}-\x{106d}\x{1071}-\x{1074}\x{1082}-\x{108d}\x{108f}-\x{109d}\x{135d}-\x{135f}\x{1712}-\x{1714}\x{1732}-\x{1734}\x{1752}\x{1753}\x{1772}\x{1773}\x{17b4}-\x{17d3}\x{17dd}\x{17e0}-\x{17e9}\x{180b}-\x{180d}\x{1810}-\x{1819}\x{18a9}\x{1920}-\x{192b}\x{1930}-\x{193b}\x{1946}-\x{194f}\x{19b0}-\x{19c0}\x{19c8}\x{19c9}\x{19d0}-\x{19d9}\x{1a17}-\x{1a1b}\x{1a55}-\x{1a5e}\x{1a60}-\x{1a7c}\x{1a7f}-\x{1a89}\x{1a90}-\x{1a99}\x{1b00}-\x{1b04}\x{1b34}-\x{1b44}\x{1b50}-\x{1b59}\x{1b6b}-\x{1b73}\x{1b80}-\x{1b82}\x{1ba1}-\x{1bad}\x{1bb0}-\x{1bb9}\x{1be6}-\x{1bf3}\x{1c24}-\x{1c37}\x{1c40}-\x{1c49}\x{1c50}-\x{1c59}\x{1cd0}-\x{1cd2}\x{1cd4}-\x{1ce8}\x{1ced}\x{1cf2}-\x{1cf4}\x{1dc0}-\x{1de6}\x{1dfc}-\x{1dff}\x{200c}\x{200d}\x{203f}\x{2040}\x{2054}\x{20d0}-\x{20dc}\x{20e1}\x{20e5}-\x{20f0}\x{2cef}-\x{2cf1}\x{2d7f}\x{2de0}-\x{2dff}\x{302a}-\x{302f}\x{3099}\x{309a}\x{a620}-\x{a629}\x{a66f}\x{a674}-\x{a67d}\x{a69f}\x{a6f0}\x{a6f1}\x{a802}\x{a806}\x{a80b}\x{a823}-\x{a827}\x{a880}\x{a881}\x{a8b4}-\x{a8c4}\x{a8d0}-\x{a8d9}\x{a8e0}-\x{a8f1}\x{a900}-\x{a909}\x{a926}-\x{a92d}\x{a947}-\x{a953}\x{a980}-\x{a983}\x{a9b3}-\x{a9c0}\x{a9d0}-\x{a9d9}\x{aa29}-\x{aa36}\x{aa43}\x{aa4c}\x{aa4d}\x{aa50}-\x{aa59}\x{aa7b}\x{aab0}\x{aab2}-\x{aab4}\x{aab7}\x{aab8}\x{aabe}\x{aabf}\x{aac1}\x{aaeb}-\x{aaef}\x{aaf5}\x{aaf6}\x{abe3}-\x{abea}\x{abec}\x{abed}\x{abf0}-\x{abf9}\x{fb1e}\x{fe00}-\x{fe0f}\x{fe20}-\x{fe26}\x{fe33}\x{fe34}\x{fe4d}-\x{fe4f}\x{ff10}-\x{ff19}\x{ff3f}]*\b';
26
+
27
+	/**
28
+	 * Full list of JavaScript reserved words.
29
+	 * Will be loaded from /data/js/keywords_reserved.txt.
30
+	 *
31
+	 * @see https://mathiasbynens.be/notes/reserved-keywords
32
+	 *
33
+	 * @var string[]
34
+	 */
35
+	protected $keywordsReserved = array();
36
+
37
+	/**
38
+	 * List of JavaScript reserved words that accept a <variable, value, ...>
39
+	 * after them. Some end of lines are not the end of a statement, like with
40
+	 * these keywords.
41
+	 *
42
+	 * E.g.: we shouldn't insert a ; after this else
43
+	 * else
44
+	 *     console.log('this is quite fine')
45
+	 *
46
+	 * Will be loaded from /data/js/keywords_before.txt
47
+	 *
48
+	 * @var string[]
49
+	 */
50
+	protected $keywordsBefore = array();
51
+
52
+	/**
53
+	 * List of JavaScript reserved words that accept a <variable, value, ...>
54
+	 * before them. Some end of lines are not the end of a statement, like when
55
+	 * continued by one of these keywords on the newline.
56
+	 *
57
+	 * E.g.: we shouldn't insert a ; before this instanceof
58
+	 * variable
59
+	 *     instanceof String
60
+	 *
61
+	 * Will be loaded from /data/js/keywords_after.txt
62
+	 *
63
+	 * @var string[]
64
+	 */
65
+	protected $keywordsAfter = array();
66
+
67
+	/**
68
+	 * List of all JavaScript operators.
69
+	 *
70
+	 * Will be loaded from /data/js/operators.txt
71
+	 *
72
+	 * @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Expressions_and_Operators
73
+	 *
74
+	 * @var string[]
75
+	 */
76
+	protected $operators = array();
77
+
78
+	/**
79
+	 * List of JavaScript operators that accept a <variable, value, ...> after
80
+	 * them. Some end of lines are not the end of a statement, like with these
81
+	 * operators.
82
+	 *
83
+	 * Note: Most operators are fine, we've only removed !, ++ and --.
84
+	 * There can't be a newline separating ! and whatever it is negating.
85
+	 * ++ & -- have to be joined with the value they're in-/decrementing.
86
+	 *
87
+	 * Will be loaded from /data/js/operators_before.txt
88
+	 *
89
+	 * @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Expressions_and_Operators
90
+	 *
91
+	 * @var string[]
92
+	 */
93
+	protected $operatorsBefore = array();
94
+
95
+	/**
96
+	 * List of JavaScript operators that accept a <variable, value, ...> before
97
+	 * them. Some end of lines are not the end of a statement, like when
98
+	 * continued by one of these operators on the newline.
99
+	 *
100
+	 * Note: Most operators are fine, we've only removed ), ], ++ and --.
101
+	 * ++ & -- have to be joined with the value they're in-/decrementing.
102
+	 * ) & ] are "special" in that they have lots or usecases. () for example
103
+	 * is used for function calls, for grouping, in if () and for (), ...
104
+	 *
105
+	 * Will be loaded from /data/js/operators_after.txt
106
+	 *
107
+	 * @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Expressions_and_Operators
108
+	 *
109
+	 * @var string[]
110
+	 */
111
+	protected $operatorsAfter = array();
112
+
113
+	/**
114
+	 * {@inheritdoc}
115
+	 */
116
+	public function __construct()
117
+	{
118
+		call_user_func_array(array('parent', '__construct'), func_get_args());
119
+
120
+		$dataDir = __DIR__.'/../data/js/';
121
+		$options = FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES;
122
+		$this->keywordsReserved = file($dataDir.'keywords_reserved.txt', $options);
123
+		$this->keywordsBefore = file($dataDir.'keywords_before.txt', $options);
124
+		$this->keywordsAfter = file($dataDir.'keywords_after.txt', $options);
125
+		$this->operators = file($dataDir.'operators.txt', $options);
126
+		$this->operatorsBefore = file($dataDir.'operators_before.txt', $options);
127
+		$this->operatorsAfter = file($dataDir.'operators_after.txt', $options);
128
+	}
129
+
130
+	/**
131
+	 * Minify the data.
132
+	 * Perform JS optimizations.
133
+	 *
134
+	 * @param string[optional] $path Path to write the data to
135
+	 *
136
+	 * @return string The minified data
137
+	 */
138
+	public function execute($path = null)
139
+	{
140
+		$content = '';
141
+
142
+		// loop files
143
+		foreach ($this->data as $source => $js) {
144
+			/*
145 145
              * Combine js: separating the scripts by a ;
146 146
              * I'm also adding a newline: it will be eaten when whitespace is
147 147
              * stripped, but we need to make sure we're not just appending
@@ -149,10 +149,10 @@  discard block
 block discarded – undo
149 149
              * singe-line comment on the last line (in which case it would also
150 150
              * be seen as part of that comment)
151 151
              */
152
-            $content .= $js."\n;";
153
-        }
152
+			$content .= $js."\n;";
153
+		}
154 154
 
155
-        /*
155
+		/*
156 156
          * Let's first take out strings, comments and regular expressions.
157 157
          * All of these can contain JS code-like characters, and we should make
158 158
          * sure any further magic ignores anything inside of these.
@@ -163,164 +163,164 @@  discard block
 block discarded – undo
163 163
          * Comments will be removed altogether, strings and regular expressions
164 164
          * will be replaced by placeholder text, which we'll restore later.
165 165
          */
166
-        $this->extractStrings('\'"`');
167
-        $this->stripComments();
168
-        $this->extractRegex();
169
-        $content = $this->replace($content);
166
+		$this->extractStrings('\'"`');
167
+		$this->stripComments();
168
+		$this->extractRegex();
169
+		$content = $this->replace($content);
170 170
 
171
-        $content = $this->propertyNotation($content);
172
-        $content = $this->shortenBools($content);
173
-        $content = $this->stripWhitespace($content);
171
+		$content = $this->propertyNotation($content);
172
+		$content = $this->shortenBools($content);
173
+		$content = $this->stripWhitespace($content);
174 174
 
175
-        /*
175
+		/*
176 176
          * Earlier, we extracted strings & regular expressions and replaced them
177 177
          * with placeholder text. This will restore them.
178 178
          */
179
-        $content = $this->restoreExtractedData($content);
180
-
181
-        return $content;
182
-    }
183
-
184
-    /**
185
-     * Strip comments from source code.
186
-     */
187
-    protected function stripComments()
188
-    {
189
-        // single-line comments
190
-        $this->registerPattern('/\/\/.*$/m', '');
191
-
192
-        // multi-line comments
193
-        $this->registerPattern('/\/\*.*?\*\//s', '');
194
-    }
195
-
196
-    /**
197
-     * JS can have /-delimited regular expressions, like: /ab+c/.match(string).
198
-     *
199
-     * The content inside the regex can contain characters that may be confused
200
-     * for JS code: e.g. it could contain whitespace it needs to match & we
201
-     * don't want to strip whitespace in there.
202
-     *
203
-     * The regex can be pretty simple: we don't have to care about comments,
204
-     * (which also use slashes) because stripComments() will have stripped those
205
-     * already.
206
-     *
207
-     * This method will replace all string content with simple REGEX#
208
-     * placeholder text, so we've rid all regular expressions from characters
209
-     * that may be misinterpreted. Original regex content will be saved in
210
-     * $this->extracted and after doing all other minifying, we can restore the
211
-     * original content via restoreRegex()
212
-     */
213
-    protected function extractRegex()
214
-    {
215
-        // PHP only supports $this inside anonymous functions since 5.4
216
-        $minifier = $this;
217
-        $callback = function ($match) use ($minifier) {
218
-            $count = count($minifier->extracted);
219
-            $placeholder = '/'.$count.'/';
220
-            $minifier->extracted[$placeholder] = $match[0];
221
-
222
-            return $placeholder;
223
-        };
224
-
225
-        $pattern = '\/.+?(?<!\\\\)(\\\\\\\\)*\/[gimy]*(?![0-9a-zA-Z\/])';
226
-
227
-        // a regular expression can only be followed by a few operators or some
228
-        // of the RegExp methods (a `\` followed by a variable or value is
229
-        // likely part of a division, not a regex)
230
-        $after = '[\.,;\)\}]';
231
-        $methods = '\.(exec|test|match|search|replace|split)\(';
232
-        $this->registerPattern('/'.$pattern.'(?=\s*('.$after.'|'.$methods.'))/', $callback);
233
-
234
-        // 1 more edge case: a regex can be followed by a lot more operators or
235
-        // keywords if there's a newline (ASI) in between, where the operator
236
-        // actually starts a new statement
237
-        // (https://github.com/matthiasmullie/minify/issues/56)
238
-        $operators = $this->getOperatorsForRegex($this->operatorsBefore, '/');
239
-        $operators += $this->getOperatorsForRegex($this->keywordsReserved, '/');
240
-        $this->registerPattern('/'.$pattern.'\s*\n(?=\s*('.implode('|', $operators).'))/', $callback);
241
-    }
242
-
243
-    /**
244
-     * Strip whitespace.
245
-     *
246
-     * We won't strip *all* whitespace, but as much as possible. The thing that
247
-     * we'll preserve are newlines we're unsure about.
248
-     * JavaScript doesn't require statements to be terminated with a semicolon.
249
-     * It will automatically fix missing semicolons with ASI (automatic semi-
250
-     * colon insertion) at the end of line causing errors (without semicolon.)
251
-     *
252
-     * Because it's sometimes hard to tell if a newline is part of a statement
253
-     * that should be terminated or not, we'll just leave some of them alone.
254
-     *
255
-     * @param string $content The content to strip the whitespace for
256
-     *
257
-     * @return string
258
-     */
259
-    protected function stripWhitespace($content)
260
-    {
261
-        // uniform line endings, make them all line feed
262
-        $content = str_replace(array("\r\n", "\r"), "\n", $content);
263
-
264
-        // collapse all non-line feed whitespace into a single space
265
-        $content = preg_replace('/[^\S\n]+/', ' ', $content);
266
-
267
-        // strip leading & trailing whitespace
268
-        $content = str_replace(array(" \n", "\n "), "\n", $content);
269
-
270
-        // collapse consecutive line feeds into just 1
271
-        $content = preg_replace('/\n+/', "\n", $content);
272
-
273
-        $operatorsBefore = $this->getOperatorsForRegex($this->operatorsBefore, '/');
274
-        $operatorsAfter = $this->getOperatorsForRegex($this->operatorsAfter, '/');
275
-        $operators = $this->getOperatorsForRegex($this->operators, '/');
276
-        $keywordsBefore = $this->getKeywordsForRegex($this->keywordsBefore, '/');
277
-        $keywordsAfter = $this->getKeywordsForRegex($this->keywordsAfter, '/');
278
-
279
-        // strip whitespace that ends in (or next line begin with) an operator
280
-        // that allows statements to be broken up over multiple lines
281
-        unset($operatorsBefore['+'], $operatorsBefore['-'], $operatorsAfter['+'], $operatorsAfter['-']);
282
-        $content = preg_replace(
283
-            array(
284
-                '/('.implode('|', $operatorsBefore).')\s+/',
285
-                '/\s+('.implode('|', $operatorsAfter).')/',
286
-            ), '\\1', $content
287
-        );
288
-
289
-        // make sure + and - can't be mistaken for, or joined into ++ and --
290
-        $content = preg_replace(
291
-            array(
292
-                '/(?<![\+\-])\s*([\+\-])(?![\+\-])/',
293
-                '/(?<![\+\-])([\+\-])\s*(?![\+\-])/',
294
-            ), '\\1', $content
295
-        );
296
-
297
-        // collapse whitespace around reserved words into single space
298
-        $content = preg_replace('/(^|[;\}\s])\K('.implode('|', $keywordsBefore).')\s+/', '\\2 ', $content);
299
-        $content = preg_replace('/\s+('.implode('|', $keywordsAfter).')(?=([;\{\s]|$))/', ' \\1', $content);
300
-
301
-        /*
179
+		$content = $this->restoreExtractedData($content);
180
+
181
+		return $content;
182
+	}
183
+
184
+	/**
185
+	 * Strip comments from source code.
186
+	 */
187
+	protected function stripComments()
188
+	{
189
+		// single-line comments
190
+		$this->registerPattern('/\/\/.*$/m', '');
191
+
192
+		// multi-line comments
193
+		$this->registerPattern('/\/\*.*?\*\//s', '');
194
+	}
195
+
196
+	/**
197
+	 * JS can have /-delimited regular expressions, like: /ab+c/.match(string).
198
+	 *
199
+	 * The content inside the regex can contain characters that may be confused
200
+	 * for JS code: e.g. it could contain whitespace it needs to match & we
201
+	 * don't want to strip whitespace in there.
202
+	 *
203
+	 * The regex can be pretty simple: we don't have to care about comments,
204
+	 * (which also use slashes) because stripComments() will have stripped those
205
+	 * already.
206
+	 *
207
+	 * This method will replace all string content with simple REGEX#
208
+	 * placeholder text, so we've rid all regular expressions from characters
209
+	 * that may be misinterpreted. Original regex content will be saved in
210
+	 * $this->extracted and after doing all other minifying, we can restore the
211
+	 * original content via restoreRegex()
212
+	 */
213
+	protected function extractRegex()
214
+	{
215
+		// PHP only supports $this inside anonymous functions since 5.4
216
+		$minifier = $this;
217
+		$callback = function ($match) use ($minifier) {
218
+			$count = count($minifier->extracted);
219
+			$placeholder = '/'.$count.'/';
220
+			$minifier->extracted[$placeholder] = $match[0];
221
+
222
+			return $placeholder;
223
+		};
224
+
225
+		$pattern = '\/.+?(?<!\\\\)(\\\\\\\\)*\/[gimy]*(?![0-9a-zA-Z\/])';
226
+
227
+		// a regular expression can only be followed by a few operators or some
228
+		// of the RegExp methods (a `\` followed by a variable or value is
229
+		// likely part of a division, not a regex)
230
+		$after = '[\.,;\)\}]';
231
+		$methods = '\.(exec|test|match|search|replace|split)\(';
232
+		$this->registerPattern('/'.$pattern.'(?=\s*('.$after.'|'.$methods.'))/', $callback);
233
+
234
+		// 1 more edge case: a regex can be followed by a lot more operators or
235
+		// keywords if there's a newline (ASI) in between, where the operator
236
+		// actually starts a new statement
237
+		// (https://github.com/matthiasmullie/minify/issues/56)
238
+		$operators = $this->getOperatorsForRegex($this->operatorsBefore, '/');
239
+		$operators += $this->getOperatorsForRegex($this->keywordsReserved, '/');
240
+		$this->registerPattern('/'.$pattern.'\s*\n(?=\s*('.implode('|', $operators).'))/', $callback);
241
+	}
242
+
243
+	/**
244
+	 * Strip whitespace.
245
+	 *
246
+	 * We won't strip *all* whitespace, but as much as possible. The thing that
247
+	 * we'll preserve are newlines we're unsure about.
248
+	 * JavaScript doesn't require statements to be terminated with a semicolon.
249
+	 * It will automatically fix missing semicolons with ASI (automatic semi-
250
+	 * colon insertion) at the end of line causing errors (without semicolon.)
251
+	 *
252
+	 * Because it's sometimes hard to tell if a newline is part of a statement
253
+	 * that should be terminated or not, we'll just leave some of them alone.
254
+	 *
255
+	 * @param string $content The content to strip the whitespace for
256
+	 *
257
+	 * @return string
258
+	 */
259
+	protected function stripWhitespace($content)
260
+	{
261
+		// uniform line endings, make them all line feed
262
+		$content = str_replace(array("\r\n", "\r"), "\n", $content);
263
+
264
+		// collapse all non-line feed whitespace into a single space
265
+		$content = preg_replace('/[^\S\n]+/', ' ', $content);
266
+
267
+		// strip leading & trailing whitespace
268
+		$content = str_replace(array(" \n", "\n "), "\n", $content);
269
+
270
+		// collapse consecutive line feeds into just 1
271
+		$content = preg_replace('/\n+/', "\n", $content);
272
+
273
+		$operatorsBefore = $this->getOperatorsForRegex($this->operatorsBefore, '/');
274
+		$operatorsAfter = $this->getOperatorsForRegex($this->operatorsAfter, '/');
275
+		$operators = $this->getOperatorsForRegex($this->operators, '/');
276
+		$keywordsBefore = $this->getKeywordsForRegex($this->keywordsBefore, '/');
277
+		$keywordsAfter = $this->getKeywordsForRegex($this->keywordsAfter, '/');
278
+
279
+		// strip whitespace that ends in (or next line begin with) an operator
280
+		// that allows statements to be broken up over multiple lines
281
+		unset($operatorsBefore['+'], $operatorsBefore['-'], $operatorsAfter['+'], $operatorsAfter['-']);
282
+		$content = preg_replace(
283
+			array(
284
+				'/('.implode('|', $operatorsBefore).')\s+/',
285
+				'/\s+('.implode('|', $operatorsAfter).')/',
286
+			), '\\1', $content
287
+		);
288
+
289
+		// make sure + and - can't be mistaken for, or joined into ++ and --
290
+		$content = preg_replace(
291
+			array(
292
+				'/(?<![\+\-])\s*([\+\-])(?![\+\-])/',
293
+				'/(?<![\+\-])([\+\-])\s*(?![\+\-])/',
294
+			), '\\1', $content
295
+		);
296
+
297
+		// collapse whitespace around reserved words into single space
298
+		$content = preg_replace('/(^|[;\}\s])\K('.implode('|', $keywordsBefore).')\s+/', '\\2 ', $content);
299
+		$content = preg_replace('/\s+('.implode('|', $keywordsAfter).')(?=([;\{\s]|$))/', ' \\1', $content);
300
+
301
+		/*
302 302
          * We didn't strip whitespace after a couple of operators because they
303 303
          * could be used in different contexts and we can't be sure it's ok to
304 304
          * strip the newlines. However, we can safely strip any non-line feed
305 305
          * whitespace that follows them.
306 306
          */
307
-        $operatorsDiffBefore = array_diff($operators, $operatorsBefore);
308
-        $operatorsDiffAfter = array_diff($operators, $operatorsAfter);
309
-        $content = preg_replace('/('.implode('|', $operatorsDiffBefore).')[^\S\n]+/', '\\1', $content);
310
-        $content = preg_replace('/[^\S\n]+('.implode('|', $operatorsDiffAfter).')/', '\\1', $content);
307
+		$operatorsDiffBefore = array_diff($operators, $operatorsBefore);
308
+		$operatorsDiffAfter = array_diff($operators, $operatorsAfter);
309
+		$content = preg_replace('/('.implode('|', $operatorsDiffBefore).')[^\S\n]+/', '\\1', $content);
310
+		$content = preg_replace('/[^\S\n]+('.implode('|', $operatorsDiffAfter).')/', '\\1', $content);
311 311
 
312
-        /*
312
+		/*
313 313
          * Get rid of double semicolons, except where they can be used like:
314 314
          * "for(v=1,_=b;;)", "for(v=1;;v++)" or "for(;;ja||(ja=true))".
315 315
          * I'll safeguard these double semicolons inside for-loops by
316 316
          * temporarily replacing them with an invalid condition: they won't have
317 317
          * a double semicolon and will be easy to spot to restore afterwards.
318 318
          */
319
-        $content = preg_replace('/\bfor\(([^;]*);;([^;]*)\)/', 'for(\\1;-;\\2)', $content);
320
-        $content = preg_replace('/;+/', ';', $content);
321
-        $content = preg_replace('/\bfor\(([^;]*);-;([^;]*)\)/', 'for(\\1;;\\2)', $content);
319
+		$content = preg_replace('/\bfor\(([^;]*);;([^;]*)\)/', 'for(\\1;-;\\2)', $content);
320
+		$content = preg_replace('/;+/', ';', $content);
321
+		$content = preg_replace('/\bfor\(([^;]*);-;([^;]*)\)/', 'for(\\1;;\\2)', $content);
322 322
 
323
-        /*
323
+		/*
324 324
          * Next, we'll be removing all semicolons where ASI kicks in.
325 325
          * for-loops however, can have an empty body (ending in only a
326 326
          * semicolon), like: `for(i=1;i<3;i++);`
@@ -330,9 +330,9 @@  discard block
 block discarded – undo
330 330
          * I'm going to double that semicolon (if any) so after the next line,
331 331
          * which strips semicolons here & there, we're still left with this one.
332 332
          */
333
-        $content = preg_replace('/(for\([^;]*;[^;]*;[^;\{]*\));(\}|$)/s', '\\1;;\\2', $content);
333
+		$content = preg_replace('/(for\([^;]*;[^;]*;[^;\{]*\));(\}|$)/s', '\\1;;\\2', $content);
334 334
 
335
-        /*
335
+		/*
336 336
          * We also can't strip empty else-statements. Even though they're
337 337
          * useless and probably shouldn't be in the code in the first place, we
338 338
          * shouldn't be stripping the `;` that follows it as it breaks the code.
@@ -340,114 +340,114 @@  discard block
 block discarded – undo
340 340
          *
341 341
          * @see https://github.com/matthiasmullie/minify/issues/91
342 342
          */
343
-        $content = preg_replace('/else;/s', '', $content);
343
+		$content = preg_replace('/else;/s', '', $content);
344 344
 
345
-        /*
345
+		/*
346 346
          * We also don't really want to terminate statements followed by closing
347 347
          * curly braces (which we've ignored completely up until now) or end-of-
348 348
          * script: ASI will kick in here & we're all about minifying.
349 349
          * Semicolons at beginning of the file don't make any sense either.
350 350
          */
351
-        $content = preg_replace('/;(\}|$)/s', '\\1', $content);
352
-        $content = ltrim($content, ';');
353
-
354
-        // get rid of remaining whitespace af beginning/end
355
-        return trim($content);
356
-    }
357
-
358
-    /**
359
-     * We'll strip whitespace around certain operators with regular expressions.
360
-     * This will prepare the given array by escaping all characters.
361
-     *
362
-     * @param string[] $operators
363
-     * @param string   $delimiter
364
-     *
365
-     * @return string[]
366
-     */
367
-    protected function getOperatorsForRegex(array $operators, $delimiter = '/')
368
-    {
369
-        // escape operators for use in regex
370
-        $delimiter = array_fill(0, count($operators), $delimiter);
371
-        $escaped = array_map('preg_quote', $operators, $delimiter);
372
-
373
-        $operators = array_combine($operators, $escaped);
374
-
375
-        // ignore + & - for now, they'll get special treatment
376
-        unset($operators['+'], $operators['-']);
377
-
378
-        // dot can not just immediately follow a number; it can be confused for
379
-        // decimal point, or calling a method on it, e.g. 42 .toString()
380
-        $operators['.'] = '(?<![0-9]\s)\.';
381
-
382
-        // don't confuse = with other assignment shortcuts (e.g. +=)
383
-        $chars = preg_quote('+-*\=<>%&|');
384
-        $operators['='] = '(?<!['.$chars.'])\=';
385
-
386
-        return $operators;
387
-    }
388
-
389
-    /**
390
-     * We'll strip whitespace around certain keywords with regular expressions.
391
-     * This will prepare the given array by escaping all characters.
392
-     *
393
-     * @param string[] $keywords
394
-     * @param string   $delimiter
395
-     *
396
-     * @return string[]
397
-     */
398
-    protected function getKeywordsForRegex(array $keywords, $delimiter = '/')
399
-    {
400
-        // escape keywords for use in regex
401
-        $delimiter = array_fill(0, count($keywords), $delimiter);
402
-        $escaped = array_map('preg_quote', $keywords, $delimiter);
403
-
404
-        // add word boundaries
405
-        array_walk($keywords, function ($value) {
406
-            return '\b'.$value.'\b';
407
-        });
408
-
409
-        $keywords = array_combine($keywords, $escaped);
410
-
411
-        return $keywords;
412
-    }
413
-
414
-    /**
415
-     * Replaces all occurrences of array['key'] by array.key.
416
-     *
417
-     * @param string $content
418
-     *
419
-     * @return string
420
-     */
421
-    protected function propertyNotation($content)
422
-    {
423
-        // PHP only supports $this inside anonymous functions since 5.4
424
-        $minifier = $this;
425
-        $keywords = $this->keywordsReserved;
426
-        $callback = function ($match) use ($minifier, $keywords) {
427
-            $property = trim($minifier->extracted[$match[1]], '\'"');
428
-
429
-            /*
351
+		$content = preg_replace('/;(\}|$)/s', '\\1', $content);
352
+		$content = ltrim($content, ';');
353
+
354
+		// get rid of remaining whitespace af beginning/end
355
+		return trim($content);
356
+	}
357
+
358
+	/**
359
+	 * We'll strip whitespace around certain operators with regular expressions.
360
+	 * This will prepare the given array by escaping all characters.
361
+	 *
362
+	 * @param string[] $operators
363
+	 * @param string   $delimiter
364
+	 *
365
+	 * @return string[]
366
+	 */
367
+	protected function getOperatorsForRegex(array $operators, $delimiter = '/')
368
+	{
369
+		// escape operators for use in regex
370
+		$delimiter = array_fill(0, count($operators), $delimiter);
371
+		$escaped = array_map('preg_quote', $operators, $delimiter);
372
+
373
+		$operators = array_combine($operators, $escaped);
374
+
375
+		// ignore + & - for now, they'll get special treatment
376
+		unset($operators['+'], $operators['-']);
377
+
378
+		// dot can not just immediately follow a number; it can be confused for
379
+		// decimal point, or calling a method on it, e.g. 42 .toString()
380
+		$operators['.'] = '(?<![0-9]\s)\.';
381
+
382
+		// don't confuse = with other assignment shortcuts (e.g. +=)
383
+		$chars = preg_quote('+-*\=<>%&|');
384
+		$operators['='] = '(?<!['.$chars.'])\=';
385
+
386
+		return $operators;
387
+	}
388
+
389
+	/**
390
+	 * We'll strip whitespace around certain keywords with regular expressions.
391
+	 * This will prepare the given array by escaping all characters.
392
+	 *
393
+	 * @param string[] $keywords
394
+	 * @param string   $delimiter
395
+	 *
396
+	 * @return string[]
397
+	 */
398
+	protected function getKeywordsForRegex(array $keywords, $delimiter = '/')
399
+	{
400
+		// escape keywords for use in regex
401
+		$delimiter = array_fill(0, count($keywords), $delimiter);
402
+		$escaped = array_map('preg_quote', $keywords, $delimiter);
403
+
404
+		// add word boundaries
405
+		array_walk($keywords, function ($value) {
406
+			return '\b'.$value.'\b';
407
+		});
408
+
409
+		$keywords = array_combine($keywords, $escaped);
410
+
411
+		return $keywords;
412
+	}
413
+
414
+	/**
415
+	 * Replaces all occurrences of array['key'] by array.key.
416
+	 *
417
+	 * @param string $content
418
+	 *
419
+	 * @return string
420
+	 */
421
+	protected function propertyNotation($content)
422
+	{
423
+		// PHP only supports $this inside anonymous functions since 5.4
424
+		$minifier = $this;
425
+		$keywords = $this->keywordsReserved;
426
+		$callback = function ($match) use ($minifier, $keywords) {
427
+			$property = trim($minifier->extracted[$match[1]], '\'"');
428
+
429
+			/*
430 430
              * Check if the property is a reserved keyword. In this context (as
431 431
              * property of an object literal/array) it shouldn't matter, but IE8
432 432
              * freaks out with "Expected identifier".
433 433
              */
434
-            if (in_array($property, $keywords)) {
435
-                return $match[0];
436
-            }
434
+			if (in_array($property, $keywords)) {
435
+				return $match[0];
436
+			}
437 437
 
438
-            /*
438
+			/*
439 439
              * See if the property is in a variable-like format (e.g.
440 440
              * array['key-here'] can't be replaced by array.key-here since '-'
441 441
              * is not a valid character there.
442 442
              */
443
-            if (!preg_match('/^'.$minifier::REGEX_VARIABLE.'$/u', $property)) {
444
-                return $match[0];
445
-            }
443
+			if (!preg_match('/^'.$minifier::REGEX_VARIABLE.'$/u', $property)) {
444
+				return $match[0];
445
+			}
446 446
 
447
-            return '.'.$property;
448
-        };
447
+			return '.'.$property;
448
+		};
449 449
 
450
-        /*
450
+		/*
451 451
          * Figure out if previous character is a variable name (of the array
452 452
          * we want to use property notation on) - this is to make sure
453 453
          * standalone ['value'] arrays aren't confused for keys-of-an-array.
@@ -455,61 +455,61 @@  discard block
 block discarded – undo
455 455
          * regex implementation doesn't allow unfixed-length look-behind
456 456
          * assertions.
457 457
          */
458
-        preg_match('/(\[[^\]]+\])[^\]]*$/', static::REGEX_VARIABLE, $previousChar);
459
-        $previousChar = $previousChar[1];
458
+		preg_match('/(\[[^\]]+\])[^\]]*$/', static::REGEX_VARIABLE, $previousChar);
459
+		$previousChar = $previousChar[1];
460 460
 
461
-        /*
461
+		/*
462 462
          * Make sure word preceding the ['value'] is not a keyword, e.g.
463 463
          * return['x']. Because -again- PHP's regex implementation doesn't allow
464 464
          * unfixed-length look-behind assertions, I'm just going to do a lot of
465 465
          * separate look-behind assertions, one for each keyword.
466 466
          */
467
-        $keywords = $this->getKeywordsForRegex($keywords);
468
-        $keywords = '(?<!'.implode(')(?<!', $keywords).')';
469
-
470
-        return preg_replace_callback('/(?<='.$previousChar.'|\])'.$keywords.'\[\s*(([\'"])[0-9]+\\2)\s*\]/u', $callback, $content);
471
-    }
472
-
473
-    /**
474
-     * Replaces true & false by !0 and !1.
475
-     *
476
-     * @param string $content
477
-     *
478
-     * @return string
479
-     */
480
-    protected function shortenBools($content)
481
-    {
482
-        $content = preg_replace('/\btrue\b(?!:)/', '!0', $content);
483
-        $content = preg_replace('/\bfalse\b(?!:)/', '!1', $content);
484
-
485
-        // for(;;) is exactly the same as while(true)
486
-        $content = preg_replace('/\bwhile\(!0\){/', 'for(;;){', $content);
487
-
488
-        // now make sure we didn't turn any do ... while(true) into do ... for(;;)
489
-        preg_match_all('/\bdo\b/', $content, $dos, PREG_OFFSET_CAPTURE | PREG_SET_ORDER);
490
-
491
-        // go backward to make sure positional offsets aren't altered when $content changes
492
-        $dos = array_reverse($dos);
493
-        foreach ($dos as $do) {
494
-            $offsetDo = $do[0][1];
495
-
496
-            // find all `while` (now `for`) following `do`: one of those must be
497
-            // associated with the `do` and be turned back into `while`
498
-            preg_match_all('/\bfor\(;;\)/', $content, $whiles, PREG_OFFSET_CAPTURE | PREG_SET_ORDER, $offsetDo);
499
-            foreach ($whiles as $while) {
500
-                $offsetWhile = $while[0][1];
501
-
502
-                $open = substr_count($content, '{', $offsetDo, $offsetWhile - $offsetDo);
503
-                $close = substr_count($content, '}', $offsetDo, $offsetWhile - $offsetDo);
504
-                if ($open === $close) {
505
-                    // only restore `while` if amount of `{` and `}` are the same;
506
-                    // otherwise, that `for` isn't associated with this `do`
507
-                    $content = substr_replace($content, 'while(!0)', $offsetWhile, strlen('for(;;)'));
508
-                    break;
509
-                }
510
-            }
511
-        }
512
-
513
-        return $content;
514
-    }
467
+		$keywords = $this->getKeywordsForRegex($keywords);
468
+		$keywords = '(?<!'.implode(')(?<!', $keywords).')';
469
+
470
+		return preg_replace_callback('/(?<='.$previousChar.'|\])'.$keywords.'\[\s*(([\'"])[0-9]+\\2)\s*\]/u', $callback, $content);
471
+	}
472
+
473
+	/**
474
+	 * Replaces true & false by !0 and !1.
475
+	 *
476
+	 * @param string $content
477
+	 *
478
+	 * @return string
479
+	 */
480
+	protected function shortenBools($content)
481
+	{
482
+		$content = preg_replace('/\btrue\b(?!:)/', '!0', $content);
483
+		$content = preg_replace('/\bfalse\b(?!:)/', '!1', $content);
484
+
485
+		// for(;;) is exactly the same as while(true)
486
+		$content = preg_replace('/\bwhile\(!0\){/', 'for(;;){', $content);
487
+
488
+		// now make sure we didn't turn any do ... while(true) into do ... for(;;)
489
+		preg_match_all('/\bdo\b/', $content, $dos, PREG_OFFSET_CAPTURE | PREG_SET_ORDER);
490
+
491
+		// go backward to make sure positional offsets aren't altered when $content changes
492
+		$dos = array_reverse($dos);
493
+		foreach ($dos as $do) {
494
+			$offsetDo = $do[0][1];
495
+
496
+			// find all `while` (now `for`) following `do`: one of those must be
497
+			// associated with the `do` and be turned back into `while`
498
+			preg_match_all('/\bfor\(;;\)/', $content, $whiles, PREG_OFFSET_CAPTURE | PREG_SET_ORDER, $offsetDo);
499
+			foreach ($whiles as $while) {
500
+				$offsetWhile = $while[0][1];
501
+
502
+				$open = substr_count($content, '{', $offsetDo, $offsetWhile - $offsetDo);
503
+				$close = substr_count($content, '}', $offsetDo, $offsetWhile - $offsetDo);
504
+				if ($open === $close) {
505
+					// only restore `while` if amount of `{` and `}` are the same;
506
+					// otherwise, that `for` isn't associated with this `do`
507
+					$content = substr_replace($content, 'while(!0)', $offsetWhile, strlen('for(;;)'));
508
+					break;
509
+				}
510
+			}
511
+		}
512
+
513
+		return $content;
514
+	}
515 515
 }
Please login to merge, or discard this patch.
Spacing   +26 added lines, -26 removed lines patch added patch discarded remove patch
@@ -117,14 +117,14 @@  discard block
 block discarded – undo
117 117
     {
118 118
         call_user_func_array(array('parent', '__construct'), func_get_args());
119 119
 
120
-        $dataDir = __DIR__.'/../data/js/';
120
+        $dataDir = __DIR__ . '/../data/js/';
121 121
         $options = FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES;
122
-        $this->keywordsReserved = file($dataDir.'keywords_reserved.txt', $options);
123
-        $this->keywordsBefore = file($dataDir.'keywords_before.txt', $options);
124
-        $this->keywordsAfter = file($dataDir.'keywords_after.txt', $options);
125
-        $this->operators = file($dataDir.'operators.txt', $options);
126
-        $this->operatorsBefore = file($dataDir.'operators_before.txt', $options);
127
-        $this->operatorsAfter = file($dataDir.'operators_after.txt', $options);
122
+        $this->keywordsReserved = file($dataDir . 'keywords_reserved.txt', $options);
123
+        $this->keywordsBefore = file($dataDir . 'keywords_before.txt', $options);
124
+        $this->keywordsAfter = file($dataDir . 'keywords_after.txt', $options);
125
+        $this->operators = file($dataDir . 'operators.txt', $options);
126
+        $this->operatorsBefore = file($dataDir . 'operators_before.txt', $options);
127
+        $this->operatorsAfter = file($dataDir . 'operators_after.txt', $options);
128 128
     }
129 129
 
130 130
     /**
@@ -149,7 +149,7 @@  discard block
 block discarded – undo
149 149
              * singe-line comment on the last line (in which case it would also
150 150
              * be seen as part of that comment)
151 151
              */
152
-            $content .= $js."\n;";
152
+            $content .= $js . "\n;";
153 153
         }
154 154
 
155 155
         /*
@@ -214,9 +214,9 @@  discard block
 block discarded – undo
214 214
     {
215 215
         // PHP only supports $this inside anonymous functions since 5.4
216 216
         $minifier = $this;
217
-        $callback = function ($match) use ($minifier) {
217
+        $callback = function($match) use ($minifier) {
218 218
             $count = count($minifier->extracted);
219
-            $placeholder = '/'.$count.'/';
219
+            $placeholder = '/' . $count . '/';
220 220
             $minifier->extracted[$placeholder] = $match[0];
221 221
 
222 222
             return $placeholder;
@@ -229,7 +229,7 @@  discard block
 block discarded – undo
229 229
         // likely part of a division, not a regex)
230 230
         $after = '[\.,;\)\}]';
231 231
         $methods = '\.(exec|test|match|search|replace|split)\(';
232
-        $this->registerPattern('/'.$pattern.'(?=\s*('.$after.'|'.$methods.'))/', $callback);
232
+        $this->registerPattern('/' . $pattern . '(?=\s*(' . $after . '|' . $methods . '))/', $callback);
233 233
 
234 234
         // 1 more edge case: a regex can be followed by a lot more operators or
235 235
         // keywords if there's a newline (ASI) in between, where the operator
@@ -237,7 +237,7 @@  discard block
 block discarded – undo
237 237
         // (https://github.com/matthiasmullie/minify/issues/56)
238 238
         $operators = $this->getOperatorsForRegex($this->operatorsBefore, '/');
239 239
         $operators += $this->getOperatorsForRegex($this->keywordsReserved, '/');
240
-        $this->registerPattern('/'.$pattern.'\s*\n(?=\s*('.implode('|', $operators).'))/', $callback);
240
+        $this->registerPattern('/' . $pattern . '\s*\n(?=\s*(' . implode('|', $operators) . '))/', $callback);
241 241
     }
242 242
 
243 243
     /**
@@ -281,8 +281,8 @@  discard block
 block discarded – undo
281 281
         unset($operatorsBefore['+'], $operatorsBefore['-'], $operatorsAfter['+'], $operatorsAfter['-']);
282 282
         $content = preg_replace(
283 283
             array(
284
-                '/('.implode('|', $operatorsBefore).')\s+/',
285
-                '/\s+('.implode('|', $operatorsAfter).')/',
284
+                '/(' . implode('|', $operatorsBefore) . ')\s+/',
285
+                '/\s+(' . implode('|', $operatorsAfter) . ')/',
286 286
             ), '\\1', $content
287 287
         );
288 288
 
@@ -295,8 +295,8 @@  discard block
 block discarded – undo
295 295
         );
296 296
 
297 297
         // collapse whitespace around reserved words into single space
298
-        $content = preg_replace('/(^|[;\}\s])\K('.implode('|', $keywordsBefore).')\s+/', '\\2 ', $content);
299
-        $content = preg_replace('/\s+('.implode('|', $keywordsAfter).')(?=([;\{\s]|$))/', ' \\1', $content);
298
+        $content = preg_replace('/(^|[;\}\s])\K(' . implode('|', $keywordsBefore) . ')\s+/', '\\2 ', $content);
299
+        $content = preg_replace('/\s+(' . implode('|', $keywordsAfter) . ')(?=([;\{\s]|$))/', ' \\1', $content);
300 300
 
301 301
         /*
302 302
          * We didn't strip whitespace after a couple of operators because they
@@ -306,8 +306,8 @@  discard block
 block discarded – undo
306 306
          */
307 307
         $operatorsDiffBefore = array_diff($operators, $operatorsBefore);
308 308
         $operatorsDiffAfter = array_diff($operators, $operatorsAfter);
309
-        $content = preg_replace('/('.implode('|', $operatorsDiffBefore).')[^\S\n]+/', '\\1', $content);
310
-        $content = preg_replace('/[^\S\n]+('.implode('|', $operatorsDiffAfter).')/', '\\1', $content);
309
+        $content = preg_replace('/(' . implode('|', $operatorsDiffBefore) . ')[^\S\n]+/', '\\1', $content);
310
+        $content = preg_replace('/[^\S\n]+(' . implode('|', $operatorsDiffAfter) . ')/', '\\1', $content);
311 311
 
312 312
         /*
313 313
          * Get rid of double semicolons, except where they can be used like:
@@ -381,7 +381,7 @@  discard block
 block discarded – undo
381 381
 
382 382
         // don't confuse = with other assignment shortcuts (e.g. +=)
383 383
         $chars = preg_quote('+-*\=<>%&|');
384
-        $operators['='] = '(?<!['.$chars.'])\=';
384
+        $operators['='] = '(?<![' . $chars . '])\=';
385 385
 
386 386
         return $operators;
387 387
     }
@@ -402,8 +402,8 @@  discard block
 block discarded – undo
402 402
         $escaped = array_map('preg_quote', $keywords, $delimiter);
403 403
 
404 404
         // add word boundaries
405
-        array_walk($keywords, function ($value) {
406
-            return '\b'.$value.'\b';
405
+        array_walk($keywords, function($value) {
406
+            return '\b' . $value . '\b';
407 407
         });
408 408
 
409 409
         $keywords = array_combine($keywords, $escaped);
@@ -423,7 +423,7 @@  discard block
 block discarded – undo
423 423
         // PHP only supports $this inside anonymous functions since 5.4
424 424
         $minifier = $this;
425 425
         $keywords = $this->keywordsReserved;
426
-        $callback = function ($match) use ($minifier, $keywords) {
426
+        $callback = function($match) use ($minifier, $keywords) {
427 427
             $property = trim($minifier->extracted[$match[1]], '\'"');
428 428
 
429 429
             /*
@@ -440,11 +440,11 @@  discard block
 block discarded – undo
440 440
              * array['key-here'] can't be replaced by array.key-here since '-'
441 441
              * is not a valid character there.
442 442
              */
443
-            if (!preg_match('/^'.$minifier::REGEX_VARIABLE.'$/u', $property)) {
443
+            if (!preg_match('/^' . $minifier::REGEX_VARIABLE . '$/u', $property)) {
444 444
                 return $match[0];
445 445
             }
446 446
 
447
-            return '.'.$property;
447
+            return '.' . $property;
448 448
         };
449 449
 
450 450
         /*
@@ -465,9 +465,9 @@  discard block
 block discarded – undo
465 465
          * separate look-behind assertions, one for each keyword.
466 466
          */
467 467
         $keywords = $this->getKeywordsForRegex($keywords);
468
-        $keywords = '(?<!'.implode(')(?<!', $keywords).')';
468
+        $keywords = '(?<!' . implode(')(?<!', $keywords) . ')';
469 469
 
470
-        return preg_replace_callback('/(?<='.$previousChar.'|\])'.$keywords.'\[\s*(([\'"])[0-9]+\\2)\s*\]/u', $callback, $content);
470
+        return preg_replace_callback('/(?<=' . $previousChar . '|\])' . $keywords . '\[\s*(([\'"])[0-9]+\\2)\s*\]/u', $callback, $content);
471 471
     }
472 472
 
473 473
     /**
Please login to merge, or discard this patch.
Sources/minify/src/Minify.php 1 patch
Indentation   +392 added lines, -392 removed lines patch added patch discarded remove patch
@@ -16,335 +16,335 @@  discard block
 block discarded – undo
16 16
  */
17 17
 abstract class Minify
18 18
 {
19
-    /**
20
-     * The data to be minified.
21
-     *
22
-     * @var string[]
23
-     */
24
-    protected $data = array();
25
-
26
-    /**
27
-     * Array of patterns to match.
28
-     *
29
-     * @var string[]
30
-     */
31
-    protected $patterns = array();
32
-
33
-    /**
34
-     * This array will hold content of strings and regular expressions that have
35
-     * been extracted from the JS source code, so we can reliably match "code",
36
-     * without having to worry about potential "code-like" characters inside.
37
-     *
38
-     * @var string[]
39
-     */
40
-    public $extracted = array();
41
-
42
-    /**
43
-     * Init the minify class - optionally, code may be passed along already.
44
-     */
45
-    public function __construct(/* $data = null, ... */)
46
-    {
47
-        // it's possible to add the source through the constructor as well ;)
48
-        if (func_num_args()) {
49
-            call_user_func_array(array($this, 'add'), func_get_args());
50
-        }
51
-    }
52
-
53
-    /**
54
-     * Add a file or straight-up code to be minified.
55
-     *
56
-     * @param string|string[] $data
57
-     */
58
-    public function add($data /* $data = null, ... */)
59
-    {
60
-        // bogus "usage" of parameter $data: scrutinizer warns this variable is
61
-        // not used (we're using func_get_args instead to support overloading),
62
-        // but it still needs to be defined because it makes no sense to have
63
-        // this function without argument :)
64
-        $args = array($data) + func_get_args();
65
-
66
-        // this method can be overloaded
67
-        foreach ($args as $data) {
68
-            if (is_array($data)) {
69
-                call_user_func_array(array($this, 'add'), $data);
70
-                continue;
71
-            }
72
-
73
-            // redefine var
74
-            $data = (string) $data;
75
-
76
-            // load data
77
-            $value = $this->load($data);
78
-            $key = ($data != $value) ? $data : count($this->data);
79
-
80
-            // replace CR linefeeds etc.
81
-            // @see https://github.com/matthiasmullie/minify/pull/139
82
-            $value = str_replace(array("\r\n", "\r"), "\n", $value);
83
-
84
-            // store data
85
-            $this->data[$key] = $value;
86
-        }
87
-    }
88
-
89
-    /**
90
-     * Minify the data & (optionally) saves it to a file.
91
-     *
92
-     * @param string[optional] $path Path to write the data to
93
-     *
94
-     * @return string The minified data
95
-     */
96
-    public function minify($path = null)
97
-    {
98
-        $content = $this->execute($path);
99
-
100
-        // save to path
101
-        if ($path !== null) {
102
-            $this->save($content, $path);
103
-        }
104
-
105
-        return $content;
106
-    }
107
-
108
-    /**
109
-     * Minify & gzip the data & (optionally) saves it to a file.
110
-     *
111
-     * @param string[optional] $path  Path to write the data to
112
-     * @param int[optional]    $level Compression level, from 0 to 9
113
-     *
114
-     * @return string The minified & gzipped data
115
-     */
116
-    public function gzip($path = null, $level = 9)
117
-    {
118
-        $content = $this->execute($path);
119
-        $content = gzencode($content, $level, FORCE_GZIP);
120
-
121
-        // save to path
122
-        if ($path !== null) {
123
-            $this->save($content, $path);
124
-        }
125
-
126
-        return $content;
127
-    }
128
-
129
-    /**
130
-     * Minify the data & write it to a CacheItemInterface object.
131
-     *
132
-     * @param CacheItemInterface $item Cache item to write the data to
133
-     *
134
-     * @return CacheItemInterface Cache item with the minifier data
135
-     */
136
-    public function cache(CacheItemInterface $item)
137
-    {
138
-        $content = $this->execute();
139
-        $item->set($content);
140
-
141
-        return $item;
142
-    }
143
-
144
-    /**
145
-     * Minify the data.
146
-     *
147
-     * @param string[optional] $path Path to write the data to
148
-     *
149
-     * @return string The minified data
150
-     */
151
-    abstract public function execute($path = null);
152
-
153
-    /**
154
-     * Load data.
155
-     *
156
-     * @param string $data Either a path to a file or the content itself
157
-     *
158
-     * @return string
159
-     */
160
-    protected function load($data)
161
-    {
162
-        // check if the data is a file
163
-        if ($this->canImportFile($data)) {
164
-            $data = file_get_contents($data);
165
-
166
-            // strip BOM, if any
167
-            if (substr($data, 0, 3) == "\xef\xbb\xbf") {
168
-                $data = substr($data, 3);
169
-            }
170
-        }
171
-
172
-        return $data;
173
-    }
174
-
175
-    /**
176
-     * Save to file.
177
-     *
178
-     * @param string $content The minified data
179
-     * @param string $path    The path to save the minified data to
180
-     *
181
-     * @throws IOException
182
-     */
183
-    protected function save($content, $path)
184
-    {
185
-        $handler = $this->openFileForWriting($path);
186
-
187
-        $this->writeToFile($handler, $content);
188
-
189
-        @fclose($handler);
190
-    }
191
-
192
-    /**
193
-     * Register a pattern to execute against the source content.
194
-     *
195
-     * @param string          $pattern     PCRE pattern
196
-     * @param string|callable $replacement Replacement value for matched pattern
197
-     */
198
-    protected function registerPattern($pattern, $replacement = '')
199
-    {
200
-        // study the pattern, we'll execute it more than once
201
-        $pattern .= 'S';
202
-
203
-        $this->patterns[] = array($pattern, $replacement);
204
-    }
205
-
206
-    /**
207
-     * We can't "just" run some regular expressions against JavaScript: it's a
208
-     * complex language. E.g. having an occurrence of // xyz would be a comment,
209
-     * unless it's used within a string. Of you could have something that looks
210
-     * like a 'string', but inside a comment.
211
-     * The only way to accurately replace these pieces is to traverse the JS one
212
-     * character at a time and try to find whatever starts first.
213
-     *
214
-     * @param string $content The content to replace patterns in
215
-     *
216
-     * @return string The (manipulated) content
217
-     */
218
-    protected function replace($content)
219
-    {
220
-        $processed = '';
221
-        $positions = array_fill(0, count($this->patterns), -1);
222
-        $matches = array();
223
-
224
-        while ($content) {
225
-            // find first match for all patterns
226
-            foreach ($this->patterns as $i => $pattern) {
227
-                list($pattern, $replacement) = $pattern;
228
-
229
-                // no need to re-run matches that are still in the part of the
230
-                // content that hasn't been processed
231
-                if ($positions[$i] >= 0) {
232
-                    continue;
233
-                }
234
-
235
-                $match = null;
236
-                if (preg_match($pattern, $content, $match)) {
237
-                    $matches[$i] = $match;
238
-
239
-                    // we'll store the match position as well; that way, we
240
-                    // don't have to redo all preg_matches after changing only
241
-                    // the first (we'll still know where those others are)
242
-                    $positions[$i] = strpos($content, $match[0]);
243
-                } else {
244
-                    // if the pattern couldn't be matched, there's no point in
245
-                    // executing it again in later runs on this same content;
246
-                    // ignore this one until we reach end of content
247
-                    unset($matches[$i]);
248
-                    $positions[$i] = strlen($content);
249
-                }
250
-            }
251
-
252
-            // no more matches to find: everything's been processed, break out
253
-            if (!$matches) {
254
-                $processed .= $content;
255
-                break;
256
-            }
257
-
258
-            // see which of the patterns actually found the first thing (we'll
259
-            // only want to execute that one, since we're unsure if what the
260
-            // other found was not inside what the first found)
261
-            $discardLength = min($positions);
262
-            $firstPattern = array_search($discardLength, $positions);
263
-            $match = $matches[$firstPattern][0];
264
-
265
-            // execute the pattern that matches earliest in the content string
266
-            list($pattern, $replacement) = $this->patterns[$firstPattern];
267
-            $replacement = $this->replacePattern($pattern, $replacement, $content);
268
-
269
-            // figure out which part of the string was unmatched; that's the
270
-            // part we'll execute the patterns on again next
271
-            $content = substr($content, $discardLength);
272
-            $unmatched = (string) substr($content, strpos($content, $match) + strlen($match));
273
-
274
-            // move the replaced part to $processed and prepare $content to
275
-            // again match batch of patterns against
276
-            $processed .= substr($replacement, 0, strlen($replacement) - strlen($unmatched));
277
-            $content = $unmatched;
278
-
279
-            // first match has been replaced & that content is to be left alone,
280
-            // the next matches will start after this replacement, so we should
281
-            // fix their offsets
282
-            foreach ($positions as $i => $position) {
283
-                $positions[$i] -= $discardLength + strlen($match);
284
-            }
285
-        }
286
-
287
-        return $processed;
288
-    }
289
-
290
-    /**
291
-     * This is where a pattern is matched against $content and the matches
292
-     * are replaced by their respective value.
293
-     * This function will be called plenty of times, where $content will always
294
-     * move up 1 character.
295
-     *
296
-     * @param string          $pattern     Pattern to match
297
-     * @param string|callable $replacement Replacement value
298
-     * @param string          $content     Content to match pattern against
299
-     *
300
-     * @return string
301
-     */
302
-    protected function replacePattern($pattern, $replacement, $content)
303
-    {
304
-        if (is_callable($replacement)) {
305
-            return preg_replace_callback($pattern, $replacement, $content, 1, $count);
306
-        } else {
307
-            return preg_replace($pattern, $replacement, $content, 1, $count);
308
-        }
309
-    }
310
-
311
-    /**
312
-     * Strings are a pattern we need to match, in order to ignore potential
313
-     * code-like content inside them, but we just want all of the string
314
-     * content to remain untouched.
315
-     *
316
-     * This method will replace all string content with simple STRING#
317
-     * placeholder text, so we've rid all strings from characters that may be
318
-     * misinterpreted. Original string content will be saved in $this->extracted
319
-     * and after doing all other minifying, we can restore the original content
320
-     * via restoreStrings().
321
-     *
322
-     * @param string[optional] $chars
323
-     */
324
-    protected function extractStrings($chars = '\'"')
325
-    {
326
-        // PHP only supports $this inside anonymous functions since 5.4
327
-        $minifier = $this;
328
-        $callback = function ($match) use ($minifier) {
329
-            // check the second index here, because the first always contains a quote
330
-            if ($match[2] === '') {
331
-                /*
19
+	/**
20
+	 * The data to be minified.
21
+	 *
22
+	 * @var string[]
23
+	 */
24
+	protected $data = array();
25
+
26
+	/**
27
+	 * Array of patterns to match.
28
+	 *
29
+	 * @var string[]
30
+	 */
31
+	protected $patterns = array();
32
+
33
+	/**
34
+	 * This array will hold content of strings and regular expressions that have
35
+	 * been extracted from the JS source code, so we can reliably match "code",
36
+	 * without having to worry about potential "code-like" characters inside.
37
+	 *
38
+	 * @var string[]
39
+	 */
40
+	public $extracted = array();
41
+
42
+	/**
43
+	 * Init the minify class - optionally, code may be passed along already.
44
+	 */
45
+	public function __construct(/* $data = null, ... */)
46
+	{
47
+		// it's possible to add the source through the constructor as well ;)
48
+		if (func_num_args()) {
49
+			call_user_func_array(array($this, 'add'), func_get_args());
50
+		}
51
+	}
52
+
53
+	/**
54
+	 * Add a file or straight-up code to be minified.
55
+	 *
56
+	 * @param string|string[] $data
57
+	 */
58
+	public function add($data /* $data = null, ... */)
59
+	{
60
+		// bogus "usage" of parameter $data: scrutinizer warns this variable is
61
+		// not used (we're using func_get_args instead to support overloading),
62
+		// but it still needs to be defined because it makes no sense to have
63
+		// this function without argument :)
64
+		$args = array($data) + func_get_args();
65
+
66
+		// this method can be overloaded
67
+		foreach ($args as $data) {
68
+			if (is_array($data)) {
69
+				call_user_func_array(array($this, 'add'), $data);
70
+				continue;
71
+			}
72
+
73
+			// redefine var
74
+			$data = (string) $data;
75
+
76
+			// load data
77
+			$value = $this->load($data);
78
+			$key = ($data != $value) ? $data : count($this->data);
79
+
80
+			// replace CR linefeeds etc.
81
+			// @see https://github.com/matthiasmullie/minify/pull/139
82
+			$value = str_replace(array("\r\n", "\r"), "\n", $value);
83
+
84
+			// store data
85
+			$this->data[$key] = $value;
86
+		}
87
+	}
88
+
89
+	/**
90
+	 * Minify the data & (optionally) saves it to a file.
91
+	 *
92
+	 * @param string[optional] $path Path to write the data to
93
+	 *
94
+	 * @return string The minified data
95
+	 */
96
+	public function minify($path = null)
97
+	{
98
+		$content = $this->execute($path);
99
+
100
+		// save to path
101
+		if ($path !== null) {
102
+			$this->save($content, $path);
103
+		}
104
+
105
+		return $content;
106
+	}
107
+
108
+	/**
109
+	 * Minify & gzip the data & (optionally) saves it to a file.
110
+	 *
111
+	 * @param string[optional] $path  Path to write the data to
112
+	 * @param int[optional]    $level Compression level, from 0 to 9
113
+	 *
114
+	 * @return string The minified & gzipped data
115
+	 */
116
+	public function gzip($path = null, $level = 9)
117
+	{
118
+		$content = $this->execute($path);
119
+		$content = gzencode($content, $level, FORCE_GZIP);
120
+
121
+		// save to path
122
+		if ($path !== null) {
123
+			$this->save($content, $path);
124
+		}
125
+
126
+		return $content;
127
+	}
128
+
129
+	/**
130
+	 * Minify the data & write it to a CacheItemInterface object.
131
+	 *
132
+	 * @param CacheItemInterface $item Cache item to write the data to
133
+	 *
134
+	 * @return CacheItemInterface Cache item with the minifier data
135
+	 */
136
+	public function cache(CacheItemInterface $item)
137
+	{
138
+		$content = $this->execute();
139
+		$item->set($content);
140
+
141
+		return $item;
142
+	}
143
+
144
+	/**
145
+	 * Minify the data.
146
+	 *
147
+	 * @param string[optional] $path Path to write the data to
148
+	 *
149
+	 * @return string The minified data
150
+	 */
151
+	abstract public function execute($path = null);
152
+
153
+	/**
154
+	 * Load data.
155
+	 *
156
+	 * @param string $data Either a path to a file or the content itself
157
+	 *
158
+	 * @return string
159
+	 */
160
+	protected function load($data)
161
+	{
162
+		// check if the data is a file
163
+		if ($this->canImportFile($data)) {
164
+			$data = file_get_contents($data);
165
+
166
+			// strip BOM, if any
167
+			if (substr($data, 0, 3) == "\xef\xbb\xbf") {
168
+				$data = substr($data, 3);
169
+			}
170
+		}
171
+
172
+		return $data;
173
+	}
174
+
175
+	/**
176
+	 * Save to file.
177
+	 *
178
+	 * @param string $content The minified data
179
+	 * @param string $path    The path to save the minified data to
180
+	 *
181
+	 * @throws IOException
182
+	 */
183
+	protected function save($content, $path)
184
+	{
185
+		$handler = $this->openFileForWriting($path);
186
+
187
+		$this->writeToFile($handler, $content);
188
+
189
+		@fclose($handler);
190
+	}
191
+
192
+	/**
193
+	 * Register a pattern to execute against the source content.
194
+	 *
195
+	 * @param string          $pattern     PCRE pattern
196
+	 * @param string|callable $replacement Replacement value for matched pattern
197
+	 */
198
+	protected function registerPattern($pattern, $replacement = '')
199
+	{
200
+		// study the pattern, we'll execute it more than once
201
+		$pattern .= 'S';
202
+
203
+		$this->patterns[] = array($pattern, $replacement);
204
+	}
205
+
206
+	/**
207
+	 * We can't "just" run some regular expressions against JavaScript: it's a
208
+	 * complex language. E.g. having an occurrence of // xyz would be a comment,
209
+	 * unless it's used within a string. Of you could have something that looks
210
+	 * like a 'string', but inside a comment.
211
+	 * The only way to accurately replace these pieces is to traverse the JS one
212
+	 * character at a time and try to find whatever starts first.
213
+	 *
214
+	 * @param string $content The content to replace patterns in
215
+	 *
216
+	 * @return string The (manipulated) content
217
+	 */
218
+	protected function replace($content)
219
+	{
220
+		$processed = '';
221
+		$positions = array_fill(0, count($this->patterns), -1);
222
+		$matches = array();
223
+
224
+		while ($content) {
225
+			// find first match for all patterns
226
+			foreach ($this->patterns as $i => $pattern) {
227
+				list($pattern, $replacement) = $pattern;
228
+
229
+				// no need to re-run matches that are still in the part of the
230
+				// content that hasn't been processed
231
+				if ($positions[$i] >= 0) {
232
+					continue;
233
+				}
234
+
235
+				$match = null;
236
+				if (preg_match($pattern, $content, $match)) {
237
+					$matches[$i] = $match;
238
+
239
+					// we'll store the match position as well; that way, we
240
+					// don't have to redo all preg_matches after changing only
241
+					// the first (we'll still know where those others are)
242
+					$positions[$i] = strpos($content, $match[0]);
243
+				} else {
244
+					// if the pattern couldn't be matched, there's no point in
245
+					// executing it again in later runs on this same content;
246
+					// ignore this one until we reach end of content
247
+					unset($matches[$i]);
248
+					$positions[$i] = strlen($content);
249
+				}
250
+			}
251
+
252
+			// no more matches to find: everything's been processed, break out
253
+			if (!$matches) {
254
+				$processed .= $content;
255
+				break;
256
+			}
257
+
258
+			// see which of the patterns actually found the first thing (we'll
259
+			// only want to execute that one, since we're unsure if what the
260
+			// other found was not inside what the first found)
261
+			$discardLength = min($positions);
262
+			$firstPattern = array_search($discardLength, $positions);
263
+			$match = $matches[$firstPattern][0];
264
+
265
+			// execute the pattern that matches earliest in the content string
266
+			list($pattern, $replacement) = $this->patterns[$firstPattern];
267
+			$replacement = $this->replacePattern($pattern, $replacement, $content);
268
+
269
+			// figure out which part of the string was unmatched; that's the
270
+			// part we'll execute the patterns on again next
271
+			$content = substr($content, $discardLength);
272
+			$unmatched = (string) substr($content, strpos($content, $match) + strlen($match));
273
+
274
+			// move the replaced part to $processed and prepare $content to
275
+			// again match batch of patterns against
276
+			$processed .= substr($replacement, 0, strlen($replacement) - strlen($unmatched));
277
+			$content = $unmatched;
278
+
279
+			// first match has been replaced & that content is to be left alone,
280
+			// the next matches will start after this replacement, so we should
281
+			// fix their offsets
282
+			foreach ($positions as $i => $position) {
283
+				$positions[$i] -= $discardLength + strlen($match);
284
+			}
285
+		}
286
+
287
+		return $processed;
288
+	}
289
+
290
+	/**
291
+	 * This is where a pattern is matched against $content and the matches
292
+	 * are replaced by their respective value.
293
+	 * This function will be called plenty of times, where $content will always
294
+	 * move up 1 character.
295
+	 *
296
+	 * @param string          $pattern     Pattern to match
297
+	 * @param string|callable $replacement Replacement value
298
+	 * @param string          $content     Content to match pattern against
299
+	 *
300
+	 * @return string
301
+	 */
302
+	protected function replacePattern($pattern, $replacement, $content)
303
+	{
304
+		if (is_callable($replacement)) {
305
+			return preg_replace_callback($pattern, $replacement, $content, 1, $count);
306
+		} else {
307
+			return preg_replace($pattern, $replacement, $content, 1, $count);
308
+		}
309
+	}
310
+
311
+	/**
312
+	 * Strings are a pattern we need to match, in order to ignore potential
313
+	 * code-like content inside them, but we just want all of the string
314
+	 * content to remain untouched.
315
+	 *
316
+	 * This method will replace all string content with simple STRING#
317
+	 * placeholder text, so we've rid all strings from characters that may be
318
+	 * misinterpreted. Original string content will be saved in $this->extracted
319
+	 * and after doing all other minifying, we can restore the original content
320
+	 * via restoreStrings().
321
+	 *
322
+	 * @param string[optional] $chars
323
+	 */
324
+	protected function extractStrings($chars = '\'"')
325
+	{
326
+		// PHP only supports $this inside anonymous functions since 5.4
327
+		$minifier = $this;
328
+		$callback = function ($match) use ($minifier) {
329
+			// check the second index here, because the first always contains a quote
330
+			if ($match[2] === '') {
331
+				/*
332 332
                  * Empty strings need no placeholder; they can't be confused for
333 333
                  * anything else anyway.
334 334
                  * But we still needed to match them, for the extraction routine
335 335
                  * to skip over this particular string.
336 336
                  */
337
-                return $match[0];
338
-            }
337
+				return $match[0];
338
+			}
339 339
 
340
-            $count = count($minifier->extracted);
341
-            $placeholder = $match[1].$count.$match[1];
342
-            $minifier->extracted[$placeholder] = $match[1].$match[2].$match[1];
340
+			$count = count($minifier->extracted);
341
+			$placeholder = $match[1].$count.$match[1];
342
+			$minifier->extracted[$placeholder] = $match[1].$match[2].$match[1];
343 343
 
344
-            return $placeholder;
345
-        };
344
+			return $placeholder;
345
+		};
346 346
 
347
-        /*
347
+		/*
348 348
          * The \\ messiness explained:
349 349
          * * Don't count ' or " as end-of-string if it's escaped (has backslash
350 350
          * in front of it)
@@ -356,75 +356,75 @@  discard block
 block discarded – undo
356 356
          * considered as escape-char (times 2) and to get it in the regex,
357 357
          * escaped (times 2)
358 358
          */
359
-        $this->registerPattern('/(['.$chars.'])(.*?(?<!\\\\)(\\\\\\\\)*+)\\1/s', $callback);
360
-    }
361
-
362
-    /**
363
-     * This method will restore all extracted data (strings, regexes) that were
364
-     * replaced with placeholder text in extract*(). The original content was
365
-     * saved in $this->extracted.
366
-     *
367
-     * @param string $content
368
-     *
369
-     * @return string
370
-     */
371
-    protected function restoreExtractedData($content)
372
-    {
373
-        if (!$this->extracted) {
374
-            // nothing was extracted, nothing to restore
375
-            return $content;
376
-        }
377
-
378
-        $content = strtr($content, $this->extracted);
379
-
380
-        $this->extracted = array();
381
-
382
-        return $content;
383
-    }
384
-
385
-    /**
386
-     * Check if the path is a regular file and can be read.
387
-     *
388
-     * @param string $path
389
-     *
390
-     * @return bool
391
-     */
392
-    protected function canImportFile($path)
393
-    {
394
-        return strlen($path) < PHP_MAXPATHLEN && @is_file($path) && is_readable($path);
395
-    }
396
-
397
-    /**
398
-     * Attempts to open file specified by $path for writing.
399
-     *
400
-     * @param string $path The path to the file
401
-     *
402
-     * @return resource Specifier for the target file
403
-     *
404
-     * @throws IOException
405
-     */
406
-    protected function openFileForWriting($path)
407
-    {
408
-        if (($handler = @fopen($path, 'w')) === false) {
409
-            throw new IOException('The file "'.$path.'" could not be opened for writing. Check if PHP has enough permissions.');
410
-        }
411
-
412
-        return $handler;
413
-    }
414
-
415
-    /**
416
-     * Attempts to write $content to the file specified by $handler. $path is used for printing exceptions.
417
-     *
418
-     * @param resource $handler The resource to write to
419
-     * @param string   $content The content to write
420
-     * @param string   $path    The path to the file (for exception printing only)
421
-     *
422
-     * @throws IOException
423
-     */
424
-    protected function writeToFile($handler, $content, $path = '')
425
-    {
426
-        if (($result = @fwrite($handler, $content)) === false || ($result < strlen($content))) {
427
-            throw new IOException('The file "'.$path.'" could not be written to. Check your disk space and file permissions.');
428
-        }
429
-    }
359
+		$this->registerPattern('/(['.$chars.'])(.*?(?<!\\\\)(\\\\\\\\)*+)\\1/s', $callback);
360
+	}
361
+
362
+	/**
363
+	 * This method will restore all extracted data (strings, regexes) that were
364
+	 * replaced with placeholder text in extract*(). The original content was
365
+	 * saved in $this->extracted.
366
+	 *
367
+	 * @param string $content
368
+	 *
369
+	 * @return string
370
+	 */
371
+	protected function restoreExtractedData($content)
372
+	{
373
+		if (!$this->extracted) {
374
+			// nothing was extracted, nothing to restore
375
+			return $content;
376
+		}
377
+
378
+		$content = strtr($content, $this->extracted);
379
+
380
+		$this->extracted = array();
381
+
382
+		return $content;
383
+	}
384
+
385
+	/**
386
+	 * Check if the path is a regular file and can be read.
387
+	 *
388
+	 * @param string $path
389
+	 *
390
+	 * @return bool
391
+	 */
392
+	protected function canImportFile($path)
393
+	{
394
+		return strlen($path) < PHP_MAXPATHLEN && @is_file($path) && is_readable($path);
395
+	}
396
+
397
+	/**
398
+	 * Attempts to open file specified by $path for writing.
399
+	 *
400
+	 * @param string $path The path to the file
401
+	 *
402
+	 * @return resource Specifier for the target file
403
+	 *
404
+	 * @throws IOException
405
+	 */
406
+	protected function openFileForWriting($path)
407
+	{
408
+		if (($handler = @fopen($path, 'w')) === false) {
409
+			throw new IOException('The file "'.$path.'" could not be opened for writing. Check if PHP has enough permissions.');
410
+		}
411
+
412
+		return $handler;
413
+	}
414
+
415
+	/**
416
+	 * Attempts to write $content to the file specified by $handler. $path is used for printing exceptions.
417
+	 *
418
+	 * @param resource $handler The resource to write to
419
+	 * @param string   $content The content to write
420
+	 * @param string   $path    The path to the file (for exception printing only)
421
+	 *
422
+	 * @throws IOException
423
+	 */
424
+	protected function writeToFile($handler, $content, $path = '')
425
+	{
426
+		if (($result = @fwrite($handler, $content)) === false || ($result < strlen($content))) {
427
+			throw new IOException('The file "'.$path.'" could not be written to. Check your disk space and file permissions.');
428
+		}
429
+	}
430 430
 }
Please login to merge, or discard this patch.
Sources/Subs.php 1 patch
Spacing   +116 added lines, -116 removed lines patch added patch discarded remove patch
@@ -1097,7 +1097,7 @@  discard block
 block discarded – undo
1097 1097
 					'height' => array('optional' => true, 'match' => '(\d+)'),
1098 1098
 				),
1099 1099
 				'content' => '$1',
1100
-				'validate' => function (&$tag, &$data, $disabled, $params) use ($modSettings, $context, $sourcedir, $txt)
1100
+				'validate' => function(&$tag, &$data, $disabled, $params) use ($modSettings, $context, $sourcedir, $txt)
1101 1101
 				{
1102 1102
 					$returnContext = '';
1103 1103
 
@@ -1132,7 +1132,7 @@  discard block
 block discarded – undo
1132 1132
 						}
1133 1133
 
1134 1134
 						if ($currentAttachment['thumbnail']['has_thumb'] && empty($params['{width}']) && empty($params['{height}']))
1135
-							$returnContext .= '<a href="'. $currentAttachment['href']. ';image" id="link_'. $currentAttachment['id']. '" onclick="'. $currentAttachment['thumbnail']['javascript']. '"><img src="'. $currentAttachment['thumbnail']['href']. '"' . $alt . $title . ' id="thumb_'. $currentAttachment['id']. '"></a>';
1135
+							$returnContext .= '<a href="' . $currentAttachment['href'] . ';image" id="link_' . $currentAttachment['id'] . '" onclick="' . $currentAttachment['thumbnail']['javascript'] . '"><img src="' . $currentAttachment['thumbnail']['href'] . '"' . $alt . $title . ' id="thumb_' . $currentAttachment['id'] . '"></a>';
1136 1136
 						else
1137 1137
 							$returnContext .= '<img src="' . $currentAttachment['href'] . ';image"' . $alt . $title . $width . $height . '/>';
1138 1138
 					}
@@ -1161,7 +1161,7 @@  discard block
 block discarded – undo
1161 1161
 				'type' => 'unparsed_content',
1162 1162
 				'content' => '<div class="codeheader"><span class="code floatleft">' . $txt['code'] . '</span> <a class="codeoperation smf_select_text">' . $txt['code_select'] . '</a></div><code class="bbc_code">$1</code>',
1163 1163
 				// @todo Maybe this can be simplified?
1164
-				'validate' => isset($disabled['code']) ? null : function (&$tag, &$data, $disabled) use ($context)
1164
+				'validate' => isset($disabled['code']) ? null : function(&$tag, &$data, $disabled) use ($context)
1165 1165
 				{
1166 1166
 					if (!isset($disabled['code']))
1167 1167
 					{
@@ -1198,7 +1198,7 @@  discard block
 block discarded – undo
1198 1198
 				'type' => 'unparsed_equals_content',
1199 1199
 				'content' => '<div class="codeheader"><span class="code floatleft">' . $txt['code'] . '</span> ($2) <a class="codeoperation smf_select_text">' . $txt['code_select'] . '</a></div><code class="bbc_code">$1</code>',
1200 1200
 				// @todo Maybe this can be simplified?
1201
-				'validate' => isset($disabled['code']) ? null : function (&$tag, &$data, $disabled) use ($context)
1201
+				'validate' => isset($disabled['code']) ? null : function(&$tag, &$data, $disabled) use ($context)
1202 1202
 				{
1203 1203
 					if (!isset($disabled['code']))
1204 1204
 					{
@@ -1242,7 +1242,7 @@  discard block
 block discarded – undo
1242 1242
 				'type' => 'unparsed_content',
1243 1243
 				'content' => '<a href="mailto:$1" class="bbc_email">$1</a>',
1244 1244
 				// @todo Should this respect guest_hideContacts?
1245
-				'validate' => function (&$tag, &$data, $disabled)
1245
+				'validate' => function(&$tag, &$data, $disabled)
1246 1246
 				{
1247 1247
 					$data = strtr($data, array('<br>' => ''));
1248 1248
 				},
@@ -1261,7 +1261,7 @@  discard block
 block discarded – undo
1261 1261
 				'type' => 'unparsed_commas_content',
1262 1262
 				'test' => '\d+,\d+\]',
1263 1263
 				'content' => '<embed type="application/x-shockwave-flash" src="$1" width="$2" height="$3" play="true" loop="true" quality="high" AllowScriptAccess="never">',
1264
-				'validate' => function (&$tag, &$data, $disabled)
1264
+				'validate' => function(&$tag, &$data, $disabled)
1265 1265
 				{
1266 1266
 					if (isset($disabled['url']))
1267 1267
 						$tag['content'] = '$1';
@@ -1306,7 +1306,7 @@  discard block
 block discarded – undo
1306 1306
 					'height' => array('optional' => true, 'value' => ' height="$1"', 'match' => '(\d+)'),
1307 1307
 				),
1308 1308
 				'content' => '<img src="$1" alt="{alt}" title="{title}"{width}{height} class="bbc_img resized">',
1309
-				'validate' => function (&$tag, &$data, $disabled)
1309
+				'validate' => function(&$tag, &$data, $disabled)
1310 1310
 				{
1311 1311
 					global $image_proxy_enabled, $image_proxy_secret, $boardurl;
1312 1312
 
@@ -1329,7 +1329,7 @@  discard block
 block discarded – undo
1329 1329
 				'tag' => 'img',
1330 1330
 				'type' => 'unparsed_content',
1331 1331
 				'content' => '<img src="$1" alt="" class="bbc_img">',
1332
-				'validate' => function (&$tag, &$data, $disabled)
1332
+				'validate' => function(&$tag, &$data, $disabled)
1333 1333
 				{
1334 1334
 					global $image_proxy_enabled, $image_proxy_secret, $boardurl;
1335 1335
 
@@ -1352,7 +1352,7 @@  discard block
 block discarded – undo
1352 1352
 				'tag' => 'iurl',
1353 1353
 				'type' => 'unparsed_content',
1354 1354
 				'content' => '<a href="$1" class="bbc_link">$1</a>',
1355
-				'validate' => function (&$tag, &$data, $disabled)
1355
+				'validate' => function(&$tag, &$data, $disabled)
1356 1356
 				{
1357 1357
 					$data = strtr($data, array('<br>' => ''));
1358 1358
 					$scheme = parse_url($data, PHP_URL_SCHEME);
@@ -1366,7 +1366,7 @@  discard block
 block discarded – undo
1366 1366
 				'quoted' => 'optional',
1367 1367
 				'before' => '<a href="$1" class="bbc_link">',
1368 1368
 				'after' => '</a>',
1369
-				'validate' => function (&$tag, &$data, $disabled)
1369
+				'validate' => function(&$tag, &$data, $disabled)
1370 1370
 				{
1371 1371
 					if (substr($data, 0, 1) == '#')
1372 1372
 						$data = '#post_' . substr($data, 1);
@@ -1446,7 +1446,7 @@  discard block
 block discarded – undo
1446 1446
 				'tag' => 'php',
1447 1447
 				'type' => 'unparsed_content',
1448 1448
 				'content' => '<span class="phpcode">$1</span>',
1449
-				'validate' => isset($disabled['php']) ? null : function (&$tag, &$data, $disabled)
1449
+				'validate' => isset($disabled['php']) ? null : function(&$tag, &$data, $disabled)
1450 1450
 				{
1451 1451
 					if (!isset($disabled['php']))
1452 1452
 					{
@@ -1544,7 +1544,7 @@  discard block
 block discarded – undo
1544 1544
 				'test' => '[1-7]\]',
1545 1545
 				'before' => '<span style="font-size: $1;" class="bbc_size">',
1546 1546
 				'after' => '</span>',
1547
-				'validate' => function (&$tag, &$data, $disabled)
1547
+				'validate' => function(&$tag, &$data, $disabled)
1548 1548
 				{
1549 1549
 					$sizes = array(1 => 0.7, 2 => 1.0, 3 => 1.35, 4 => 1.45, 5 => 2.0, 6 => 2.65, 7 => 3.95);
1550 1550
 					$data = $sizes[$data] . 'em';
@@ -1582,7 +1582,7 @@  discard block
 block discarded – undo
1582 1582
 				'tag' => 'time',
1583 1583
 				'type' => 'unparsed_content',
1584 1584
 				'content' => '$1',
1585
-				'validate' => function (&$tag, &$data, $disabled)
1585
+				'validate' => function(&$tag, &$data, $disabled)
1586 1586
 				{
1587 1587
 					if (is_numeric($data))
1588 1588
 						$data = timeformat($data);
@@ -1610,7 +1610,7 @@  discard block
 block discarded – undo
1610 1610
 				'tag' => 'url',
1611 1611
 				'type' => 'unparsed_content',
1612 1612
 				'content' => '<a href="$1" class="bbc_link" target="_blank">$1</a>',
1613
-				'validate' => function (&$tag, &$data, $disabled)
1613
+				'validate' => function(&$tag, &$data, $disabled)
1614 1614
 				{
1615 1615
 					$data = strtr($data, array('<br>' => ''));
1616 1616
 					$scheme = parse_url($data, PHP_URL_SCHEME);
@@ -1624,7 +1624,7 @@  discard block
 block discarded – undo
1624 1624
 				'quoted' => 'optional',
1625 1625
 				'before' => '<a href="$1" class="bbc_link" target="_blank">',
1626 1626
 				'after' => '</a>',
1627
-				'validate' => function (&$tag, &$data, $disabled)
1627
+				'validate' => function(&$tag, &$data, $disabled)
1628 1628
 				{
1629 1629
 					$scheme = parse_url($data, PHP_URL_SCHEME);
1630 1630
 					if (empty($scheme))
@@ -1650,7 +1650,7 @@  discard block
 block discarded – undo
1650 1650
 		{
1651 1651
 			if (isset($temp_bbc))
1652 1652
 				$bbc_codes = $temp_bbc;
1653
-			usort($codes, function ($a, $b) {
1653
+			usort($codes, function($a, $b) {
1654 1654
 				return strcmp($a['tag'], $b['tag']);
1655 1655
 			});
1656 1656
 			return $codes;
@@ -1888,7 +1888,7 @@  discard block
 block discarded – undo
1888 1888
 										# a run of Unicode domain name characters and a dot
1889 1889
 										[\p{L}\p{M}\p{N}\-.:@]+\.
1890 1890
 										# and then a TLD valid in the DNS or the reserved "local" TLD
1891
-										(?:'. $modSettings['tld_regex'] .'|local)
1891
+										(?:'. $modSettings['tld_regex'] . '|local)
1892 1892
 									)
1893 1893
 									# followed by a non-domain character or end of line
1894 1894
 									(?=[^\p{L}\p{N}\-.]|$)
@@ -1956,7 +1956,7 @@  discard block
 block discarded – undo
1956 1956
 						)?
1957 1957
 						';
1958 1958
 
1959
-						$data = preg_replace_callback('~' . $url_regex . '~xi' . ($context['utf8'] ? 'u' : ''), function ($matches) {
1959
+						$data = preg_replace_callback('~' . $url_regex . '~xi' . ($context['utf8'] ? 'u' : ''), function($matches) {
1960 1960
 							$url = array_shift($matches);
1961 1961
 
1962 1962
 							$scheme = parse_url($url, PHP_URL_SCHEME);
@@ -2685,7 +2685,7 @@  discard block
 block discarded – undo
2685 2685
 		for ($i = 0, $n = count($smileysfrom); $i < $n; $i++)
2686 2686
 		{
2687 2687
 			$specialChars = $smcFunc['htmlspecialchars']($smileysfrom[$i], ENT_QUOTES);
2688
-			$smileyCode = '<img src="' . $smileys_path . $smileysto[$i] . '" alt="' . strtr($specialChars, array(':' => '&#58;', '(' => '&#40;', ')' => '&#41;', '$' => '&#36;', '[' => '&#091;')). '" title="' . strtr($smcFunc['htmlspecialchars']($smileysdescs[$i]), array(':' => '&#58;', '(' => '&#40;', ')' => '&#41;', '$' => '&#36;', '[' => '&#091;')) . '" class="smiley">';
2688
+			$smileyCode = '<img src="' . $smileys_path . $smileysto[$i] . '" alt="' . strtr($specialChars, array(':' => '&#58;', '(' => '&#40;', ')' => '&#41;', '$' => '&#36;', '[' => '&#091;')) . '" title="' . strtr($smcFunc['htmlspecialchars']($smileysdescs[$i]), array(':' => '&#58;', '(' => '&#40;', ')' => '&#41;', '$' => '&#36;', '[' => '&#091;')) . '" class="smiley">';
2689 2689
 
2690 2690
 			$smileyPregReplacements[$smileysfrom[$i]] = $smileyCode;
2691 2691
 
@@ -2702,7 +2702,7 @@  discard block
 block discarded – undo
2702 2702
 
2703 2703
 	// Replace away!
2704 2704
 	$message = preg_replace_callback($smileyPregSearch,
2705
-		function ($matches) use ($smileyPregReplacements)
2705
+		function($matches) use ($smileyPregReplacements)
2706 2706
 		{
2707 2707
 			return $smileyPregReplacements[$matches[1]];
2708 2708
 		}, $message);
@@ -2768,13 +2768,13 @@  discard block
 block discarded – undo
2768 2768
 	{
2769 2769
 		if (defined('SID') && SID != '')
2770 2770
 			$setLocation = preg_replace_callback('~^' . preg_quote($scripturl, '/') . '\?(?:' . SID . '(?:;|&|&amp;))((?:board|topic)=[^#]+?)(#[^"]*?)?$~',
2771
-				function ($m) use ($scripturl)
2771
+				function($m) use ($scripturl)
2772 2772
 				{
2773
-					return $scripturl . '/' . strtr("$m[1]", '&;=', '//,') . '.html?' . SID. (isset($m[2]) ? "$m[2]" : "");
2773
+					return $scripturl . '/' . strtr("$m[1]", '&;=', '//,') . '.html?' . SID . (isset($m[2]) ? "$m[2]" : "");
2774 2774
 				}, $setLocation);
2775 2775
 		else
2776 2776
 			$setLocation = preg_replace_callback('~^' . preg_quote($scripturl, '/') . '\?((?:board|topic)=[^#"]+?)(#[^"]*?)?$~',
2777
-				function ($m) use ($scripturl)
2777
+				function($m) use ($scripturl)
2778 2778
 				{
2779 2779
 					return $scripturl . '/' . strtr("$m[1]", '&;=', '//,') . '.html' . (isset($m[2]) ? "$m[2]" : "");
2780 2780
 				}, $setLocation);
@@ -3097,7 +3097,7 @@  discard block
 block discarded – undo
3097 3097
 
3098 3098
 	// Add a generic "Are you sure?" confirmation message.
3099 3099
 	addInlineJavaScript('
3100
-	var smf_you_sure =' . JavaScriptEscape($txt['quickmod_confirm']) .';');
3100
+	var smf_you_sure =' . JavaScriptEscape($txt['quickmod_confirm']) . ';');
3101 3101
 
3102 3102
 	// Now add the capping code for avatars.
3103 3103
 	if (!empty($modSettings['avatar_max_width_external']) && !empty($modSettings['avatar_max_height_external']) && !empty($modSettings['avatar_action_too_large']) && $modSettings['avatar_action_too_large'] == 'option_css_resize')
@@ -3458,7 +3458,7 @@  discard block
 block discarded – undo
3458 3458
 
3459 3459
 		else
3460 3460
 			echo '
3461
-	<script src="', $settings['theme_url'] ,'/scripts/minified', ($do_deferred ? '_deferred' : '') ,'.js', $minSeed ,'"></script>';
3461
+	<script src="', $settings['theme_url'], '/scripts/minified', ($do_deferred ? '_deferred' : ''), '.js', $minSeed, '"></script>';
3462 3462
 	}
3463 3463
 
3464 3464
 	// Inline JavaScript - Actually useful some times!
@@ -3536,14 +3536,14 @@  discard block
 block discarded – undo
3536 3536
 
3537 3537
 		else
3538 3538
 			echo '
3539
-	<link rel="stylesheet" href="', $settings['theme_url'] ,'/css/minified.css', $minSeed ,'">';
3539
+	<link rel="stylesheet" href="', $settings['theme_url'], '/css/minified.css', $minSeed, '">';
3540 3540
 	}
3541 3541
 
3542 3542
 	// Print the rest after the minified files.
3543 3543
 	if (!empty($normal))
3544 3544
 		foreach ($normal as $nf)
3545 3545
 			echo '
3546
-	<link rel="stylesheet" href="', $nf ,'">';
3546
+	<link rel="stylesheet" href="', $nf, '">';
3547 3547
 
3548 3548
 	if ($db_show_debug === true)
3549 3549
 	{
@@ -3559,7 +3559,7 @@  discard block
 block discarded – undo
3559 3559
 	<style>';
3560 3560
 
3561 3561
 		foreach ($context['css_header'] as $css)
3562
-			echo $css .'
3562
+			echo $css . '
3563 3563
 	';
3564 3564
 
3565 3565
 		echo'
@@ -3588,27 +3588,27 @@  discard block
 block discarded – undo
3588 3588
 		return false;
3589 3589
 
3590 3590
 	// Did we already did this?
3591
-	$toCache = cache_get_data('minimized_'. $settings['theme_id'] .'_'. $type, 86400);
3591
+	$toCache = cache_get_data('minimized_' . $settings['theme_id'] . '_' . $type, 86400);
3592 3592
 
3593 3593
 	// Already done?
3594 3594
 	if (!empty($toCache))
3595 3595
 		return true;
3596 3596
 
3597 3597
 	// No namespaces, sorry!
3598
-	$classType = 'MatthiasMullie\\Minify\\'. strtoupper($type);
3598
+	$classType = 'MatthiasMullie\\Minify\\' . strtoupper($type);
3599 3599
 
3600 3600
 	// Temp path.
3601
-	$cTempPath = $settings['theme_dir'] .'/'. ($type == 'css' ? 'css' : 'scripts') .'/';
3601
+	$cTempPath = $settings['theme_dir'] . '/' . ($type == 'css' ? 'css' : 'scripts') . '/';
3602 3602
 
3603 3603
 	// What kind of file are we going to create?
3604
-	$toCreate = $cTempPath .'minified'. ($do_deferred ? '_deferred' : '') .'.'. $type;
3604
+	$toCreate = $cTempPath . 'minified' . ($do_deferred ? '_deferred' : '') . '.' . $type;
3605 3605
 
3606 3606
 	// File has to exists, if it isn't try to create it.
3607 3607
 	if ((!file_exists($toCreate) && @fopen($toCreate, 'w') === false) || !smf_chmod($toCreate))
3608 3608
 	{
3609 3609
 		loadLanguage('Errors');
3610 3610
 		log_error(sprintf($txt['file_not_created'], $toCreate), 'general');
3611
-		cache_put_data('minimized_'. $settings['theme_id'] .'_'. $type, null);
3611
+		cache_put_data('minimized_' . $settings['theme_id'] . '_' . $type, null);
3612 3612
 
3613 3613
 		// The process failed so roll back to print each individual file.
3614 3614
 		return $data;
@@ -3643,14 +3643,14 @@  discard block
 block discarded – undo
3643 3643
 	{
3644 3644
 		loadLanguage('Errors');
3645 3645
 		log_error(sprintf($txt['file_not_created'], $toCreate), 'general');
3646
-		cache_put_data('minimized_'. $settings['theme_id'] .'_'. $type, null);
3646
+		cache_put_data('minimized_' . $settings['theme_id'] . '_' . $type, null);
3647 3647
 
3648 3648
 		// The process failed so roll back to print each individual file.
3649 3649
 		return $data;
3650 3650
 	}
3651 3651
 
3652 3652
 	// And create a long lived cache entry.
3653
-	cache_put_data('minimized_'. $settings['theme_id'] .'_'. $type, $toCreate, 86400);
3653
+	cache_put_data('minimized_' . $settings['theme_id'] . '_' . $type, $toCreate, 86400);
3654 3654
 
3655 3655
 	return true;
3656 3656
 }
@@ -3707,7 +3707,7 @@  discard block
 block discarded – undo
3707 3707
 	else
3708 3708
 		$path = $modSettings['attachmentUploadDir'];
3709 3709
 
3710
-	return $path . '/' . $attachment_id . '_' . $file_hash .'.dat';
3710
+	return $path . '/' . $attachment_id . '_' . $file_hash . '.dat';
3711 3711
 }
3712 3712
 
3713 3713
 /**
@@ -3751,10 +3751,10 @@  discard block
 block discarded – undo
3751 3751
 		$valid_low = isValidIP($ip_parts[0]);
3752 3752
 		$valid_high = isValidIP($ip_parts[1]);
3753 3753
 		$count = 0;
3754
-		$mode = (preg_match('/:/',$ip_parts[0]) > 0 ? ':' : '.');
3754
+		$mode = (preg_match('/:/', $ip_parts[0]) > 0 ? ':' : '.');
3755 3755
 		$max = ($mode == ':' ? 'ffff' : '255');
3756 3756
 		$min = 0;
3757
-		if(!$valid_low)
3757
+		if (!$valid_low)
3758 3758
 		{
3759 3759
 			$ip_parts[0] = preg_replace('/\*/', '0', $ip_parts[0]);
3760 3760
 			$valid_low = isValidIP($ip_parts[0]);
@@ -3768,7 +3768,7 @@  discard block
 block discarded – undo
3768 3768
 		}
3769 3769
 
3770 3770
 		$count = 0;
3771
-		if(!$valid_high)
3771
+		if (!$valid_high)
3772 3772
 		{
3773 3773
 			$ip_parts[1] = preg_replace('/\*/', $max, $ip_parts[1]);
3774 3774
 			$valid_high = isValidIP($ip_parts[1]);
@@ -3781,7 +3781,7 @@  discard block
 block discarded – undo
3781 3781
 			}
3782 3782
 		}
3783 3783
 
3784
-		if($valid_high && $valid_low)
3784
+		if ($valid_high && $valid_low)
3785 3785
 		{
3786 3786
 			$ip_array['low'] = $ip_parts[0];
3787 3787
 			$ip_array['high'] = $ip_parts[1];
@@ -3963,7 +3963,7 @@  discard block
 block discarded – undo
3963 3963
 		addInlineJavaScript('
3964 3964
 	var user_menus = new smc_PopupMenu();
3965 3965
 	user_menus.add("profile", "' . $scripturl . '?action=profile;area=popup");
3966
-	user_menus.add("alerts", "' . $scripturl . '?action=profile;area=alerts_popup;u='. $context['user']['id'] .'");', true);
3966
+	user_menus.add("alerts", "' . $scripturl . '?action=profile;area=alerts_popup;u=' . $context['user']['id'] . '");', true);
3967 3967
 		if ($context['allow_pm'])
3968 3968
 			addInlineJavaScript('
3969 3969
 	user_menus.add("pm", "' . $scripturl . '?action=pm;sa=popup");', true);
@@ -4588,7 +4588,7 @@  discard block
 block discarded – undo
4588 4588
 		// No? try a fallback to $sourcedir
4589 4589
 		else
4590 4590
 		{
4591
-			$absPath = $sourcedir .'/'. $file;
4591
+			$absPath = $sourcedir . '/' . $file;
4592 4592
 
4593 4593
 			if (file_exists($absPath))
4594 4594
 				require_once($absPath);
@@ -4669,15 +4669,15 @@  discard block
 block discarded – undo
4669 4669
 
4670 4670
 	// UTF-8 occurences of MS special characters
4671 4671
 	$findchars_utf8 = array(
4672
-		"\xe2\80\x9a",	// single low-9 quotation mark
4673
-		"\xe2\80\x9e",	// double low-9 quotation mark
4674
-		"\xe2\80\xa6",	// horizontal ellipsis
4675
-		"\xe2\x80\x98",	// left single curly quote
4676
-		"\xe2\x80\x99",	// right single curly quote
4677
-		"\xe2\x80\x9c",	// left double curly quote
4678
-		"\xe2\x80\x9d",	// right double curly quote
4679
-		"\xe2\x80\x93",	// en dash
4680
-		"\xe2\x80\x94",	// em dash
4672
+		"\xe2\80\x9a", // single low-9 quotation mark
4673
+		"\xe2\80\x9e", // double low-9 quotation mark
4674
+		"\xe2\80\xa6", // horizontal ellipsis
4675
+		"\xe2\x80\x98", // left single curly quote
4676
+		"\xe2\x80\x99", // right single curly quote
4677
+		"\xe2\x80\x9c", // left double curly quote
4678
+		"\xe2\x80\x9d", // right double curly quote
4679
+		"\xe2\x80\x93", // en dash
4680
+		"\xe2\x80\x94", // em dash
4681 4681
 	);
4682 4682
 
4683 4683
 	// windows 1252 / iso equivalents
@@ -4695,15 +4695,15 @@  discard block
 block discarded – undo
4695 4695
 
4696 4696
 	// safe replacements
4697 4697
 	$replacechars = array(
4698
-		',',	// &sbquo;
4699
-		',,',	// &bdquo;
4700
-		'...',	// &hellip;
4701
-		"'",	// &lsquo;
4702
-		"'",	// &rsquo;
4703
-		'"',	// &ldquo;
4704
-		'"',	// &rdquo;
4705
-		'-',	// &ndash;
4706
-		'--',	// &mdash;
4698
+		',', // &sbquo;
4699
+		',,', // &bdquo;
4700
+		'...', // &hellip;
4701
+		"'", // &lsquo;
4702
+		"'", // &rsquo;
4703
+		'"', // &ldquo;
4704
+		'"', // &rdquo;
4705
+		'-', // &ndash;
4706
+		'--', // &mdash;
4707 4707
 	);
4708 4708
 
4709 4709
 	if ($context['utf8'])
@@ -5066,7 +5066,7 @@  discard block
 block discarded – undo
5066 5066
  */
5067 5067
 function inet_dtop($bin)
5068 5068
 {
5069
-	if(empty($bin))
5069
+	if (empty($bin))
5070 5070
 		return '';
5071 5071
 
5072 5072
 	global $db_type;
@@ -5097,28 +5097,28 @@  discard block
 block discarded – undo
5097 5097
  */
5098 5098
 function _safe_serialize($value)
5099 5099
 {
5100
-	if(is_null($value))
5100
+	if (is_null($value))
5101 5101
 		return 'N;';
5102 5102
 
5103
-	if(is_bool($value))
5104
-		return 'b:'. (int) $value .';';
5103
+	if (is_bool($value))
5104
+		return 'b:' . (int) $value . ';';
5105 5105
 
5106
-	if(is_int($value))
5107
-		return 'i:'. $value .';';
5106
+	if (is_int($value))
5107
+		return 'i:' . $value . ';';
5108 5108
 
5109
-	if(is_float($value))
5110
-		return 'd:'. str_replace(',', '.', $value) .';';
5109
+	if (is_float($value))
5110
+		return 'd:' . str_replace(',', '.', $value) . ';';
5111 5111
 
5112
-	if(is_string($value))
5113
-		return 's:'. strlen($value) .':"'. $value .'";';
5112
+	if (is_string($value))
5113
+		return 's:' . strlen($value) . ':"' . $value . '";';
5114 5114
 
5115
-	if(is_array($value))
5115
+	if (is_array($value))
5116 5116
 	{
5117 5117
 		$out = '';
5118
-		foreach($value as $k => $v)
5118
+		foreach ($value as $k => $v)
5119 5119
 			$out .= _safe_serialize($k) . _safe_serialize($v);
5120 5120
 
5121
-		return 'a:'. count($value) .':{'. $out .'}';
5121
+		return 'a:' . count($value) . ':{' . $out . '}';
5122 5122
 	}
5123 5123
 
5124 5124
 	// safe_serialize cannot serialize resources or objects.
@@ -5160,7 +5160,7 @@  discard block
 block discarded – undo
5160 5160
 function _safe_unserialize($str)
5161 5161
 {
5162 5162
 	// Input  is not a string.
5163
-	if(empty($str) || !is_string($str))
5163
+	if (empty($str) || !is_string($str))
5164 5164
 		return false;
5165 5165
 
5166 5166
 	$stack = array();
@@ -5174,40 +5174,40 @@  discard block
 block discarded – undo
5174 5174
 	 *   3 - in array, expecting value or another array
5175 5175
 	 */
5176 5176
 	$state = 0;
5177
-	while($state != 1)
5177
+	while ($state != 1)
5178 5178
 	{
5179 5179
 		$type = isset($str[0]) ? $str[0] : '';
5180
-		if($type == '}')
5180
+		if ($type == '}')
5181 5181
 			$str = substr($str, 1);
5182 5182
 
5183
-		else if($type == 'N' && $str[1] == ';')
5183
+		else if ($type == 'N' && $str[1] == ';')
5184 5184
 		{
5185 5185
 			$value = null;
5186 5186
 			$str = substr($str, 2);
5187 5187
 		}
5188
-		else if($type == 'b' && preg_match('/^b:([01]);/', $str, $matches))
5188
+		else if ($type == 'b' && preg_match('/^b:([01]);/', $str, $matches))
5189 5189
 		{
5190 5190
 			$value = $matches[1] == '1' ? true : false;
5191 5191
 			$str = substr($str, 4);
5192 5192
 		}
5193
-		else if($type == 'i' && preg_match('/^i:(-?[0-9]+);(.*)/s', $str, $matches))
5193
+		else if ($type == 'i' && preg_match('/^i:(-?[0-9]+);(.*)/s', $str, $matches))
5194 5194
 		{
5195
-			$value = (int)$matches[1];
5195
+			$value = (int) $matches[1];
5196 5196
 			$str = $matches[2];
5197 5197
 		}
5198
-		else if($type == 'd' && preg_match('/^d:(-?[0-9]+\.?[0-9]*(E[+-][0-9]+)?);(.*)/s', $str, $matches))
5198
+		else if ($type == 'd' && preg_match('/^d:(-?[0-9]+\.?[0-9]*(E[+-][0-9]+)?);(.*)/s', $str, $matches))
5199 5199
 		{
5200
-			$value = (float)$matches[1];
5200
+			$value = (float) $matches[1];
5201 5201
 			$str = $matches[3];
5202 5202
 		}
5203
-		else if($type == 's' && preg_match('/^s:([0-9]+):"(.*)/s', $str, $matches) && substr($matches[2], (int)$matches[1], 2) == '";')
5203
+		else if ($type == 's' && preg_match('/^s:([0-9]+):"(.*)/s', $str, $matches) && substr($matches[2], (int) $matches[1], 2) == '";')
5204 5204
 		{
5205
-			$value = substr($matches[2], 0, (int)$matches[1]);
5206
-			$str = substr($matches[2], (int)$matches[1] + 2);
5205
+			$value = substr($matches[2], 0, (int) $matches[1]);
5206
+			$str = substr($matches[2], (int) $matches[1] + 2);
5207 5207
 		}
5208
-		else if($type == 'a' && preg_match('/^a:([0-9]+):{(.*)/s', $str, $matches))
5208
+		else if ($type == 'a' && preg_match('/^a:([0-9]+):{(.*)/s', $str, $matches))
5209 5209
 		{
5210
-			$expectedLength = (int)$matches[1];
5210
+			$expectedLength = (int) $matches[1];
5211 5211
 			$str = $matches[2];
5212 5212
 		}
5213 5213
 
@@ -5215,10 +5215,10 @@  discard block
 block discarded – undo
5215 5215
 		else
5216 5216
 			return false;
5217 5217
 
5218
-		switch($state)
5218
+		switch ($state)
5219 5219
 		{
5220 5220
 			case 3: // In array, expecting value or another array.
5221
-				if($type == 'a')
5221
+				if ($type == 'a')
5222 5222
 				{
5223 5223
 					$stack[] = &$list;
5224 5224
 					$list[$key] = array();
@@ -5227,7 +5227,7 @@  discard block
 block discarded – undo
5227 5227
 					$state = 2;
5228 5228
 					break;
5229 5229
 				}
5230
-				if($type != '}')
5230
+				if ($type != '}')
5231 5231
 				{
5232 5232
 					$list[$key] = $value;
5233 5233
 					$state = 2;
@@ -5238,29 +5238,29 @@  discard block
 block discarded – undo
5238 5238
 				return false;
5239 5239
 
5240 5240
 			case 2: // in array, expecting end of array or a key
5241
-				if($type == '}')
5241
+				if ($type == '}')
5242 5242
 				{
5243 5243
 					// Array size is less than expected.
5244
-					if(count($list) < end($expected))
5244
+					if (count($list) < end($expected))
5245 5245
 						return false;
5246 5246
 
5247 5247
 					unset($list);
5248
-					$list = &$stack[count($stack)-1];
5248
+					$list = &$stack[count($stack) - 1];
5249 5249
 					array_pop($stack);
5250 5250
 
5251 5251
 					// Go to terminal state if we're at the end of the root array.
5252 5252
 					array_pop($expected);
5253 5253
 
5254
-					if(count($expected) == 0)
5254
+					if (count($expected) == 0)
5255 5255
 						$state = 1;
5256 5256
 
5257 5257
 					break;
5258 5258
 				}
5259 5259
 
5260
-				if($type == 'i' || $type == 's')
5260
+				if ($type == 'i' || $type == 's')
5261 5261
 				{
5262 5262
 					// Array size exceeds expected length.
5263
-					if(count($list) >= end($expected))
5263
+					if (count($list) >= end($expected))
5264 5264
 						return false;
5265 5265
 
5266 5266
 					$key = $value;
@@ -5273,7 +5273,7 @@  discard block
 block discarded – undo
5273 5273
 
5274 5274
 			// Expecting array or value.
5275 5275
 			case 0:
5276
-				if($type == 'a')
5276
+				if ($type == 'a')
5277 5277
 				{
5278 5278
 					$data = array();
5279 5279
 					$list = &$data;
@@ -5282,7 +5282,7 @@  discard block
 block discarded – undo
5282 5282
 					break;
5283 5283
 				}
5284 5284
 
5285
-				if($type != '}')
5285
+				if ($type != '}')
5286 5286
 				{
5287 5287
 					$data = $value;
5288 5288
 					$state = 1;
@@ -5295,7 +5295,7 @@  discard block
 block discarded – undo
5295 5295
 	}
5296 5296
 
5297 5297
 	// Trailing data in input.
5298
-	if(!empty($str))
5298
+	if (!empty($str))
5299 5299
 		return false;
5300 5300
 
5301 5301
 	return $data;
@@ -5349,7 +5349,7 @@  discard block
 block discarded – undo
5349 5349
 	// Set different modes.
5350 5350
 	$chmodValues = $isDir ? array(0750, 0755, 0775, 0777) : array(0644, 0664, 0666);
5351 5351
 
5352
-	foreach($chmodValues as $val)
5352
+	foreach ($chmodValues as $val)
5353 5353
 	{
5354 5354
 		// If it's writable, break out of the loop.
5355 5355
 		if (is_writable($file))
@@ -5384,13 +5384,13 @@  discard block
 block discarded – undo
5384 5384
 	$returnArray = @json_decode($json, $returnAsArray);
5385 5385
 
5386 5386
 	// PHP 5.3 so no json_last_error_msg()
5387
-	switch(json_last_error())
5387
+	switch (json_last_error())
5388 5388
 	{
5389 5389
 		case JSON_ERROR_NONE:
5390 5390
 			$jsonError = false;
5391 5391
 			break;
5392 5392
 		case JSON_ERROR_DEPTH:
5393
-			$jsonError =  'JSON_ERROR_DEPTH';
5393
+			$jsonError = 'JSON_ERROR_DEPTH';
5394 5394
 			break;
5395 5395
 		case JSON_ERROR_STATE_MISMATCH:
5396 5396
 			$jsonError = 'JSON_ERROR_STATE_MISMATCH';
@@ -5418,10 +5418,10 @@  discard block
 block discarded – undo
5418 5418
 		loadLanguage('Errors');
5419 5419
 
5420 5420
 		if (!empty($jsonDebug))
5421
-			log_error($txt['json_'. $jsonError], 'critical', $jsonDebug['file'], $jsonDebug['line']);
5421
+			log_error($txt['json_' . $jsonError], 'critical', $jsonDebug['file'], $jsonDebug['line']);
5422 5422
 
5423 5423
 		else
5424
-			log_error($txt['json_'. $jsonError], 'critical');
5424
+			log_error($txt['json_' . $jsonError], 'critical');
5425 5425
 
5426 5426
 		// Everyone expects an array.
5427 5427
 		return array();
@@ -5525,7 +5525,7 @@  discard block
 block discarded – undo
5525 5525
 		});
5526 5526
 
5527 5527
 		// Convert Punycode to Unicode
5528
-		$tlds = array_map(function ($input) {
5528
+		$tlds = array_map(function($input) {
5529 5529
 			$prefix = 'xn--';
5530 5530
 			$safe_char = 0xFFFC;
5531 5531
 			$base = 36;
@@ -5541,7 +5541,7 @@  discard block
 block discarded – undo
5541 5541
 
5542 5542
 			foreach ($enco_parts as $encoded)
5543 5543
 			{
5544
-				if (strpos($encoded,$prefix) !== 0 || strlen(trim(str_replace($prefix,'',$encoded))) == 0)
5544
+				if (strpos($encoded, $prefix) !== 0 || strlen(trim(str_replace($prefix, '', $encoded))) == 0)
5545 5545
 				{
5546 5546
 					$output_parts[] = $encoded;
5547 5547
 					continue;
@@ -5552,7 +5552,7 @@  discard block
 block discarded – undo
5552 5552
 				$idx = 0;
5553 5553
 				$char = 0x80;
5554 5554
 				$decoded = array();
5555
-				$output='';
5555
+				$output = '';
5556 5556
 				$delim_pos = strrpos($encoded, '-');
5557 5557
 
5558 5558
 				if ($delim_pos > strlen($prefix))
@@ -5568,7 +5568,7 @@  discard block
 block discarded – undo
5568 5568
 
5569 5569
 				for ($enco_idx = $delim_pos ? ($delim_pos + 1) : 0; $enco_idx < $enco_len; ++$deco_len)
5570 5570
 				{
5571
-					for ($old_idx = $idx, $w = 1, $k = $base; 1 ; $k += $base)
5571
+					for ($old_idx = $idx, $w = 1, $k = $base; 1; $k += $base)
5572 5572
 					{
5573 5573
 						$cp = ord($encoded{$enco_idx++});
5574 5574
 						$digit = ($cp - 48 < 10) ? $cp - 22 : (($cp - 65 < 26) ? $cp - 65 : (($cp - 97 < 26) ? $cp - 97 : $base));
@@ -5609,15 +5609,15 @@  discard block
 block discarded – undo
5609 5609
 
5610 5610
 					// 2 bytes
5611 5611
 					elseif ($v < (1 << 11))
5612
-						$output .= chr(192+($v >> 6)) . chr(128+($v & 63));
5612
+						$output .= chr(192 + ($v >> 6)) . chr(128 + ($v & 63));
5613 5613
 
5614 5614
 					// 3 bytes
5615 5615
 					elseif ($v < (1 << 16))
5616
-						$output .= chr(224+($v >> 12)) . chr(128+(($v >> 6) & 63)) . chr(128+($v & 63));
5616
+						$output .= chr(224 + ($v >> 12)) . chr(128 + (($v >> 6) & 63)) . chr(128 + ($v & 63));
5617 5617
 
5618 5618
 					// 4 bytes
5619 5619
 					elseif ($v < (1 << 21))
5620
-						$output .= chr(240+($v >> 18)) . chr(128+(($v >> 12) & 63)) . chr(128+(($v >> 6) & 63)) . chr(128+($v & 63));
5620
+						$output .= chr(240 + ($v >> 18)) . chr(128 + (($v >> 12) & 63)) . chr(128 + (($v >> 6) & 63)) . chr(128 + ($v & 63));
5621 5621
 
5622 5622
 					//  'Conversion from UCS-4 to UTF-8 failed: malformed input at byte '.$k
5623 5623
 					else
@@ -5724,7 +5724,7 @@  discard block
 block discarded – undo
5724 5724
 	}
5725 5725
 
5726 5726
 	// This recursive function creates the index array from the strings
5727
-	$add_string_to_index = function ($string, $index) use (&$strlen, &$substr, &$add_string_to_index)
5727
+	$add_string_to_index = function($string, $index) use (&$strlen, &$substr, &$add_string_to_index)
5728 5728
 	{
5729 5729
 		static $depth = 0;
5730 5730
 		$depth++;
@@ -5751,7 +5751,7 @@  discard block
 block discarded – undo
5751 5751
 	};
5752 5752
 
5753 5753
 	// This recursive function turns the index array into a regular expression
5754
-	$index_to_regex = function (&$index, $delim) use (&$strlen, &$index_to_regex)
5754
+	$index_to_regex = function(&$index, $delim) use (&$strlen, &$index_to_regex)
5755 5755
 	{
5756 5756
 		static $depth = 0;
5757 5757
 		$depth++;
@@ -5775,11 +5775,11 @@  discard block
 block discarded – undo
5775 5775
 
5776 5776
 				if (count(array_keys($value)) == 1)
5777 5777
 				{
5778
-					$new_key_array = explode('(?'.'>', $sub_regex);
5778
+					$new_key_array = explode('(?' . '>', $sub_regex);
5779 5779
 					$new_key .= $new_key_array[0];
5780 5780
 				}
5781 5781
 				else
5782
-					$sub_regex = '(?'.'>' . $sub_regex . ')';
5782
+					$sub_regex = '(?' . '>' . $sub_regex . ')';
5783 5783
 			}
5784 5784
 
5785 5785
 			if ($depth > 1)
@@ -5819,7 +5819,7 @@  discard block
 block discarded – undo
5819 5819
 		$index = $add_string_to_index($string, $index);
5820 5820
 
5821 5821
 	while (!empty($index))
5822
-		$regexes[] = '(?'.'>' . $index_to_regex($index, $delim) . ')';
5822
+		$regexes[] = '(?' . '>' . $index_to_regex($index, $delim) . ')';
5823 5823
 
5824 5824
 	// Restore PHP's internal character encoding to whatever it was originally
5825 5825
 	if (!empty($current_encoding))
Please login to merge, or discard this patch.