Completed
Pull Request — release-2.1 (#4089)
by Sebastiaan
08:14
created
Sources/tasks/MsgReport-Notify.php 1 patch
Indentation   +1 added lines, -1 removed lines patch added patch discarded remove patch
@@ -19,7 +19,7 @@
 block discarded – undo
19 19
 class MsgReport_Notify_Background extends SMF_BackgroundTask
20 20
 {
21 21
 	/**
22
-     * This executes the task - loads up the information, puts the email in the queue and inserts alerts as needed.
22
+	 * This executes the task - loads up the information, puts the email in the queue and inserts alerts as needed.
23 23
 	 * @return bool Always returns true.
24 24
 	 */
25 25
 	public function execute()
Please login to merge, or discard this patch.
Sources/tasks/UpdateTldRegex.php 1 patch
Indentation   +4 added lines, -4 removed lines patch added patch discarded remove patch
@@ -18,10 +18,10 @@
 block discarded – undo
18 18
  */
19 19
 class Update_TLD_Regex extends SMF_BackgroundTask
20 20
 {
21
-    /**
22
-     * This executes the task. It just calls set_tld_regex() in Subs.php
23
-     * @return bool Always returns true
24
-     */
21
+	/**
22
+	 * This executes the task. It just calls set_tld_regex() in Subs.php
23
+	 * @return bool Always returns true
24
+	 */
25 25
 	public function execute()
26 26
  	{
27 27
 		global $sourcedir;
Please login to merge, or discard this patch.
Sources/tasks/MemberReportReply-Notify.php 1 patch
Indentation   +1 added lines, -1 removed lines patch added patch discarded remove patch
@@ -20,7 +20,7 @@
 block discarded – undo
20 20
 class MemberReportReply_Notify_Background extends SMF_BackgroundTask
21 21
 {
22 22
 	/**
23
-     * This executes the task - loads up the information, puts the email in the queue and inserts alerts as needed.
23
+	 * This executes the task - loads up the information, puts the email in the queue and inserts alerts as needed.
24 24
 	 * @return bool Always returns true.
25 25
 	 */
26 26
 	public function execute()
Please login to merge, or discard this patch.
Sources/tasks/ApproveReply-Notify.php 1 patch
Indentation   +1 added lines, -1 removed lines patch added patch discarded remove patch
@@ -18,7 +18,7 @@
 block discarded – undo
18 18
 class ApproveReply_Notify_Background extends SMF_BackgroundTask
19 19
 {
20 20
 	/**
21
-     * This executes the task - loads up the information, puts the email in the queue and inserts alerts.
21
+	 * This executes the task - loads up the information, puts the email in the queue and inserts alerts.
22 22
 	 * @return bool Always returns true.
23 23
 	 */
24 24
 	public function execute()
Please login to merge, or discard this patch.
Sources/tasks/GroupReq-Notify.php 1 patch
Indentation   +1 added lines, -1 removed lines patch added patch discarded remove patch
@@ -20,7 +20,7 @@
 block discarded – undo
20 20
 class GroupReq_Notify_Background extends SMF_BackgroundTask
21 21
 {
22 22
 	/**
23
-     * This executes the task - loads up the information, puts the email in the queue and inserts any alerts as needed.
23
+	 * This executes the task - loads up the information, puts the email in the queue and inserts any alerts as needed.
24 24
 	 * @return bool Always returns true.
25 25
 	 */
26 26
 	public function execute()
Please login to merge, or discard this patch.
Sources/ManageBans.php 1 patch
Indentation   +3 added lines, -3 removed lines patch added patch discarded remove patch
@@ -784,7 +784,7 @@  discard block
 block discarded – undo
784 784
 		)
785 785
 	);
786 786
 	while ($row = $smcFunc['db_fetch_assoc']($request))
787
-	    $error_ips[] = inet_dtop($row['ip']);
787
+		$error_ips[] = inet_dtop($row['ip']);
788 788
 	$smcFunc['db_free_result']($request);
789 789
 
790 790
 	return $error_ips;
@@ -2168,9 +2168,9 @@  discard block
 block discarded – undo
2168 2168
 
2169 2169
 	if ($low == '255.255.255.255') return 'unknown';
2170 2170
 	if ($low == $high)
2171
-	    return $low;
2171
+		return $low;
2172 2172
 	else
2173
-	    return $low . '-' . $high;
2173
+		return $low . '-' . $high;
2174 2174
 }
2175 2175
 
2176 2176
 /**
Please login to merge, or discard this patch.
Sources/Who.php 1 patch
Indentation   +1 added lines, -1 removed lines patch added patch discarded remove patch
@@ -673,7 +673,7 @@
 block discarded – undo
673 673
 						'Nikola "Dzonny" Novaković',
674 674
 						// Localizers
675 675
 						'Dr. Deejay',
676
-                        			'd3vcho',
676
+									'd3vcho',
677 677
 						// Former Localizers
678 678
 						'Relyana',
679 679
 					),
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 1 patch
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.