From 237d83d3cbc48975c5cfee6c7329b1203e10a3bd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Elan=20Ruusam=C3=A4e?= Date: Wed, 3 Feb 2016 09:08:31 +0200 Subject: [PATCH 01/31] add jshrink thin wrapper --- composer.json | 3 ++- lib/Minify/JS/JShrink.php | 47 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 49 insertions(+), 1 deletion(-) create mode 100644 lib/Minify/JS/JShrink.php diff --git a/composer.json b/composer.json index 7842db1..6f0e5c1 100644 --- a/composer.json +++ b/composer.json @@ -32,7 +32,8 @@ "require-dev": { "leafo/lessphp": "~0.4.0", "meenie/javascript-packer": "~1.1", - "phpunit/phpunit": "4.8.*" + "phpunit/phpunit": "4.8.*", + "tedivm/jshrink": "~1.1.0" }, "suggest": { "leafo/lessphp": "LESS support", diff --git a/lib/Minify/JS/JShrink.php b/lib/Minify/JS/JShrink.php new file mode 100644 index 0000000..d5dcf8c --- /dev/null +++ b/lib/Minify/JS/JShrink.php @@ -0,0 +1,47 @@ + + * @link https://github.com/tedious/JShrink + * + */ +class JShrink +{ + /** + * Contains the default options for minification. This array is merged with + * the one passed in by the user to create the request specific set of + * options (stored in the $options attribute). + * + * @var string[] + */ + protected static $defaultOptions = array('flaggedComments' => true); + + /** + * Takes a string containing javascript and removes unneeded characters in + * order to shrink the code without altering it's functionality. + * + * @param string $js The raw javascript to be minified + * @param array $options Various runtime options in an associative array + * + * @see JShrink\Minifier::minify() + * @return string + */ + public static function minify($js, array $options = array()) + { + $options = array_merge( + self::$defaultOptions, + $options + ); + return \JShrink\Minifier::minify($js, $options); + } +} From 2045731d6054eeb01a57b5fa7e8ed54782325471 Mon Sep 17 00:00:00 2001 From: Steve Clay Date: Wed, 18 May 2016 17:01:59 -0400 Subject: [PATCH 02/31] Improve Minify_Lines algorithm and add tests Fixes #531 Fixes #534 --- lib/Minify/Lines.php | 110 ++++++++++++++---- min_extras/tools/minifyTextarea.php | 2 +- tests/MinifyLinesTest.php | 32 +++-- tests/_test_files/lines/basic.in.js | 66 +++++++++++ .../lines_output.js => lines/basic.out.js} | 24 ++-- .../lines_bugs.js => lines/misc.in.js} | 24 ++-- tests/_test_files/lines/misc.out.js | 18 +++ tests/_test_files/lines/url.in.js | 13 +++ tests/_test_files/lines/url.out.js | 17 +++ 9 files changed, 247 insertions(+), 59 deletions(-) create mode 100644 tests/_test_files/lines/basic.in.js rename tests/_test_files/{minify/lines_output.js => lines/basic.out.js} (93%) rename tests/_test_files/{minify/lines_bugs.js => lines/misc.in.js} (53%) create mode 100644 tests/_test_files/lines/misc.out.js create mode 100644 tests/_test_files/lines/url.in.js create mode 100644 tests/_test_files/lines/url.out.js diff --git a/lib/Minify/Lines.php b/lib/Minify/Lines.php index e046c59..1aa2f95 100644 --- a/lib/Minify/Lines.php +++ b/lib/Minify/Lines.php @@ -41,11 +41,6 @@ class Minify_Lines { : ''; $content = str_replace("\r\n", "\n", $content); - // Hackily rewrite strings with XPath expressions that are - // likely to throw off our dumb parser (for Prototype 1.6.1). - $content = str_replace('"/*"', '"/"+"*"', $content); - $content = preg_replace('@([\'"])(\\.?//?)\\*@', '$1$2$1+$1*', $content); - $lines = explode("\n", $content); $numLines = count($lines); // determine left padding @@ -89,33 +84,43 @@ class Minify_Lines { * * @param string $line current line of code * - * @param bool $inComment was the parser in a comment at the - * beginning of the line? + * @param bool $inComment was the parser in a C-style comment at the + * beginning of the previous line? * * @return bool */ private static function _eolInComment($line, $inComment) { - // crude way to avoid things like // */ - $line = preg_replace('~//.*?(\\*/|/\\*).*~', '', $line); - while (strlen($line)) { - $search = $inComment - ? '*/' - : '/*'; - $pos = strpos($line, $search); - if (false === $pos) { - return $inComment; - } else { - if ($pos == 0 - || ($inComment - ? substr($line, $pos, 3) - : substr($line, $pos-1, 3)) != '*/*') - { - $inComment = ! $inComment; + if ($inComment) { + // only "*/" can end the comment + $index = self::_find($line, '*/'); + if ($index === false) { + return true; } - $line = substr($line, $pos + 2); + + // stop comment and keep walking line + $inComment = false; + @$line = (string)substr($line, $index + 2); + continue; } + + // look for "//" and "/*" + $single = self::_find($line, '//'); + $multi = self::_find($line, '/*'); + if ($multi === false) { + return false; + } + + if ($single === false || $multi < $single) { + // start comment and keep walking line + $inComment = true; + @$line = (string)substr($line, $multi + 2); + continue; + } + + // a single-line comment preceeded it + return false; } return $inComment; @@ -137,8 +142,63 @@ class Minify_Lines { */ private static function _addNote($line, $note, $inComment, $padTo) { - return $inComment + $line = $inComment ? '/* ' . str_pad($note, $padTo, ' ', STR_PAD_RIGHT) . ' *| ' . $line : '/* ' . str_pad($note, $padTo, ' ', STR_PAD_RIGHT) . ' */ ' . $line; + return rtrim($line); + } + + /** + * Find a token trying to avoid false positives + * + * @param string $str String containing the token + * @param string $token Token being checked + * @return bool + */ + private static function _find($str, $token) { + switch ($token) { + case '//': + $fakes = array( + '://' => 1, + '"//' => 1, + '\'//' => 1, + '".//' => 2, + '\'.//' => 2, + ); + break; + case '/*': + $fakes = array( + '"/*' => 1, + '\'/*' => 1, + '"//*' => 2, + '\'//*' => 2, + '".//*' => 3, + '\'.//*' => 3, + '*/*' => 1, + '\\/*' => 1, + ); + break; + default: + $fakes = array(); + } + + $index = strpos($str, $token); + $offset = 0; + + while ($index !== false) { + foreach ($fakes as $fake => $skip) { + $check = substr($str, $index - $skip, strlen($fake)); + if ($check === $fake) { + // move offset and scan again + $offset += $index + strlen($token); + $index = strpos($str, $token, $offset); + break; + } + } + // legitimate find + return $index; + } + + return $index; } } diff --git a/min_extras/tools/minifyTextarea.php b/min_extras/tools/minifyTextarea.php index fbdfcef..a5b5926 100644 --- a/min_extras/tools/minifyTextarea.php +++ b/min_extras/tools/minifyTextarea.php @@ -55,7 +55,7 @@ if ($env->post('method') === 'Minify and serve') { } $tpl = array(); -$tpl['classes'] = array('Minify_HTML', 'JSMin\\JSMin', 'Minify_CSS'); +$tpl['classes'] = array('Minify_HTML', 'JSMin\\JSMin', 'Minify_CSS', 'Minify_Lines'); if (in_array($env->post('method'), $tpl['classes'])) { diff --git a/tests/MinifyLinesTest.php b/tests/MinifyLinesTest.php index 6e93434..87f27c5 100644 --- a/tests/MinifyLinesTest.php +++ b/tests/MinifyLinesTest.php @@ -4,8 +4,6 @@ class MinifyLinesTest extends TestCase { public function test_lines() { - $exp = file_get_contents(self::$test_files . "/minify/lines_output.js"); - $env = new Minify_Env(array( 'server' => array( 'DOCUMENT_ROOT' => dirname(__DIR__), @@ -15,15 +13,27 @@ class MinifyLinesTest extends TestCase $controller = new Minify_Controller_Files($env, $sourceFactory); $minify = new Minify(new Minify_Cache_Null()); - $ret = $minify->serve($controller, array( - 'debug' => true - ,'quiet' => true - ,'encodeOutput' => false - ,'files' => array( - self::$test_files . "/js/before.js" - ) - )); + $files = glob(self::$test_files . "/lines/*.in.js"); - $this->assertEquals($exp, $ret['content']); + // uncomment to debug one + //$files = array(self::$test_files . "/lines/basic.in.js"); + + foreach ($files as $file) { + $ret = $minify->serve($controller, array( + 'debug' => true, + 'quiet' => true, + 'encodeOutput' => false, + 'files' => array($file), + )); + + $outFile = str_replace('.in.js', '.out.js', $file); + + $exp = file_get_contents($outFile); + + // uncomment to set up expected output + //file_put_contents($outFile, $ret['content']); + + $this->assertEquals($exp, $ret['content'], "Did not match: " . basename($outFile)); + } } } diff --git a/tests/_test_files/lines/basic.in.js b/tests/_test_files/lines/basic.in.js new file mode 100644 index 0000000..4158b3c --- /dev/null +++ b/tests/_test_files/lines/basic.in.js @@ -0,0 +1,66 @@ +/*! is.js + + (c) 2001 Douglas Crockford + 2001 June 3 +*/ + +// is + +// The -is- object is used to identify the browser. Every browser edition +// identifies itself, but there is no standard way of doing it, and some of +// the identification is deceptive. This is because the authors of web +// browsers are liars. For example, Microsoft's IE browsers claim to be +// Mozilla 4. Netscape 6 claims to be version 5. + +var is = { + ie: navigator.appName == 'Microsoft Internet Explorer', + java: navigator.javaEnabled(), + ns: navigator.appName == 'Netscape', + ua: navigator.userAgent.toLowerCase(), + version: parseFloat(navigator.appVersion.substr(21)) || + parseFloat(navigator.appVersion), + win: navigator.platform == 'Win32' +} +/*!* + * preserve this comment, too + */ +is.mac = is.ua.indexOf('mac') >= 0; +if (is.ua.indexOf('opera') >= 0) { + is.ie = is.ns = false; + is.opera = true; +} +if (is.ua.indexOf('gecko') >= 0) { + is.ie = is.ns = false; + is.gecko = true; +} + +/*@cc_on + /*@if (@_win32) + if (is.ie && is.win) + document.write("PASS: IE/win honored conditional comment.
"); + @else @*/ + if (is.ie && is.win) + document.write("FAIL: IE/win did not honor multi-line conditional comment.
"); + else + document.write("PASS: Non-IE/win browser ignores multi-line conditional comment.
"); + /*@end +@*/ + +var recognizesCondComm = true; +//@cc_on/* +recognizesCondComm = false; +//@cc_on*/ + +if ((is.ie && is.win) == recognizesCondComm) + document.write("PASS: IE/win honored single-line conditional comment.
"); +else + document.write("FAIL: Non-IE/win browser did not ignore single-line conditional comment.
"); + +// hello +//@cc_on/* +// world +//@cc_on*/ +//@cc_on/* +'hello'; +/*!* preserved */ +/*!* preserved */ \ No newline at end of file diff --git a/tests/_test_files/minify/lines_output.js b/tests/_test_files/lines/basic.out.js similarity index 93% rename from tests/_test_files/minify/lines_output.js rename to tests/_test_files/lines/basic.out.js index 5565867..ad0d845 100644 --- a/tests/_test_files/minify/lines_output.js +++ b/tests/_test_files/lines/basic.out.js @@ -1,20 +1,20 @@ -/* before.js */ +/* basic.in.js */ /* 1 */ /*! is.js -/* 2 *| +/* 2 *| /* 3 *| (c) 2001 Douglas Crockford /* 4 *| 2001 June 3 /* 5 *| */ -/* 6 */ +/* 6 */ /* 7 */ // is -/* 8 */ +/* 8 */ /* 9 */ // The -is- object is used to identify the browser. Every browser edition /* 10 */ // identifies itself, but there is no standard way of doing it, and some of /* 11 */ // the identification is deceptive. This is because the authors of web /* 12 */ // browsers are liars. For example, Microsoft's IE browsers claim to be /* 13 */ // Mozilla 4. Netscape 6 claims to be version 5. -/* 14 */ +/* 14 */ /* 15 */ var is = { /* 16 */ ie: navigator.appName == 'Microsoft Internet Explorer', /* 17 */ java: navigator.javaEnabled(), @@ -36,7 +36,7 @@ /* 33 */ is.ie = is.ns = false; /* 34 */ is.gecko = true; /* 35 */ } -/* 36 */ +/* 36 */ /* 37 */ /*@cc_on /* 38 *| /*@if (@_win32) /* 39 *| if (is.ie && is.win) @@ -44,24 +44,24 @@ /* 41 *| @else @*/ /* 42 */ if (is.ie && is.win) /* 43 */ document.write("FAIL: IE/win did not honor multi-line conditional comment.
"); -/* 44 */ else +/* 44 */ else /* 45 */ document.write("PASS: Non-IE/win browser ignores multi-line conditional comment.
"); /* 46 */ /*@end /* 47 *| @*/ -/* 48 */ +/* 48 */ /* 49 */ var recognizesCondComm = true; /* 50 */ //@cc_on/* -/* before.js */ +/* basic.in.js */ /* 51 */ recognizesCondComm = false; /* 52 */ //@cc_on*/ -/* 53 */ +/* 53 */ /* 54 */ if ((is.ie && is.win) == recognizesCondComm) /* 55 */ document.write("PASS: IE/win honored single-line conditional comment.
"); -/* 56 */ else +/* 56 */ else /* 57 */ document.write("FAIL: Non-IE/win browser did not ignore single-line conditional comment.
"); -/* 58 */ +/* 58 */ /* 59 */ // hello /* 60 */ //@cc_on/* /* 61 */ // world diff --git a/tests/_test_files/minify/lines_bugs.js b/tests/_test_files/lines/misc.in.js similarity index 53% rename from tests/_test_files/minify/lines_bugs.js rename to tests/_test_files/lines/misc.in.js index cf56b58..6ac5d6d 100644 --- a/tests/_test_files/minify/lines_bugs.js +++ b/tests/_test_files/lines/misc.in.js @@ -1,10 +1,14 @@ -// sections from Prototype 1.6.1 -var xpath = ".//*[local-name()='ul' or local-name()='UL']" + - "//*[local-name()='li' or local-name()='LI']"; -this.matcher = ['.//*']; -xpath = { - descendant: "//*", - child: "/*", - f: 0 -}; -document._getElementsByXPath('.//*' + cond, element); \ No newline at end of file +// sections from Prototype 1.6.1 +var xpath = ".//*[local-name()='ul' or local-name()='UL']" + + "//*[local-name()='li' or local-name()='LI']"; +this.matcher = ['.//*']; +xpath = { + descendant: "//*", + child: "/*", + f: 0 +}; +document._getElementsByXPath('.//*' + cond, element); + +// from angular 1.4.8 +var URL_REGEXP = /^[a-z][a-z\d.+-]*:\/*(?:[^:@]+(?::[^@]+)?@)?(?:[^\s:/?#]+|\[[a-f\d:]+\])(?::\d+)?(?:\/[^?#]*)?(?:\?[^#]*)?(?:#.*)?$/i; + diff --git a/tests/_test_files/lines/misc.out.js b/tests/_test_files/lines/misc.out.js new file mode 100644 index 0000000..b888683 --- /dev/null +++ b/tests/_test_files/lines/misc.out.js @@ -0,0 +1,18 @@ + +/* misc.in.js */ + +/* 1 */ // sections from Prototype 1.6.1 +/* 2 */ var xpath = ".//*[local-name()='ul' or local-name()='UL']" + +/* 3 */ "//*[local-name()='li' or local-name()='LI']"; +/* 4 */ this.matcher = ['.//*']; +/* 5 */ xpath = { +/* 6 */ descendant: "//*", +/* 7 */ child: "/*", +/* 8 */ f: 0 +/* 9 */ }; +/* 10 */ document._getElementsByXPath('.//*' + cond, element); +/* 11 */ +/* 12 */ // from angular 1.4.8 +/* 13 */ var URL_REGEXP = /^[a-z][a-z\d.+-]*:\/*(?:[^:@]+(?::[^@]+)?@)?(?:[^\s:/?#]+|\[[a-f\d:]+\])(?::\d+)?(?:\/[^?#]*)?(?:\?[^#]*)?(?:#.*)?$/i; +/* 14 */ +/* 15 */ diff --git a/tests/_test_files/lines/url.in.js b/tests/_test_files/lines/url.in.js new file mode 100644 index 0000000..eb5d779 --- /dev/null +++ b/tests/_test_files/lines/url.in.js @@ -0,0 +1,13 @@ +foo; /* http://example.com */ +bar; + +foo; /* + http://example.com */ +bar; + +foo = "http://example.com"; /* hello */ +bar; + +foo = "http://example.com"; /* +hello */ +bar; diff --git a/tests/_test_files/lines/url.out.js b/tests/_test_files/lines/url.out.js new file mode 100644 index 0000000..dc43a7c --- /dev/null +++ b/tests/_test_files/lines/url.out.js @@ -0,0 +1,17 @@ + +/* url.in.js */ + +/* 1 */ foo; /* http://example.com */ +/* 2 */ bar; +/* 3 */ +/* 4 */ foo; /* +/* 5 *| http://example.com */ +/* 6 */ bar; +/* 7 */ +/* 8 */ foo = "http://example.com"; /* hello */ +/* 9 */ bar; +/* 10 */ +/* 11 */ foo = "http://example.com"; /* +/* 12 *| hello */ +/* 13 */ bar; +/* 14 */ From 42b18c1e2a5b5a0d47a53c8178f38522521b1b74 Mon Sep 17 00:00:00 2001 From: Steve Clay Date: Wed, 8 Jun 2016 19:00:35 -0400 Subject: [PATCH 03/31] Sync JSMin with mrclay/jsmin-php --- min/lib/JSMin.php | 53 +++++++++++--------- min_unit_tests/_test_files/js/regexes.min.js | 5 +- 2 files changed, 32 insertions(+), 26 deletions(-) diff --git a/min/lib/JSMin.php b/min/lib/JSMin.php index 9840d8b..c90a23d 100644 --- a/min/lib/JSMin.php +++ b/min/lib/JSMin.php @@ -108,6 +108,11 @@ class JSMin { $mbIntEnc = mb_internal_encoding(); mb_internal_encoding('8bit'); } + + if (isset($this->input[0]) && $this->input[0] === "\xef") { + $this->input = substr($this->input, 3); + } + $this->input = str_replace("\r\n", "\n", $this->input); $this->inputLength = strlen($this->input); @@ -271,37 +276,39 @@ class JSMin { protected function isRegexpLiteral() { if (false !== strpos("(,=:[!&|?+-~*{;", $this->a)) { - // we obviously aren't dividing + // we can't divide after these tokens return true; } - // we have to check for a preceding keyword, and we don't need to pattern - // match over the whole output. - $recentOutput = substr($this->output, -10); - - // check if return/typeof directly precede a pattern without a space - foreach (array('return', 'typeof') as $keyword) { - if ($this->a !== substr($keyword, -1)) { - // certainly wasn't keyword - continue; - } - if (preg_match("~(^|[\\s\\S])" . substr($keyword, 0, -1) . "$~", $recentOutput, $m)) { - if ($m[1] === '' || !$this->isAlphaNum($m[1])) { - return true; - } + // check if first non-ws token is "/" (see starts-regex.js) + $length = strlen($this->output); + if ($this->a === ' ' || $this->a === "\n") { + if ($length < 2) { // weird edge case + return true; } } - // check all keywords - if ($this->a === ' ' || $this->a === "\n") { - if (preg_match('~(^|[\\s\\S])(?:case|else|in|return|typeof)$~', $recentOutput, $m)) { - if ($m[1] === '' || !$this->isAlphaNum($m[1])) { - return true; - } - } + // if the "/" follows a keyword, it must be a regexp, otherwise it's best to assume division + + $subject = $this->output . trim($this->a); + if (!preg_match('/(?:case|else|in|return|typeof)$/', $subject, $m)) { + // not a keyword + return false; } - return false; + // can't be sure it's a keyword yet (see not-regexp.js) + $charBeforeKeyword = substr($subject, 0 - strlen($m[0]) - 1, 1); + if ($this->isAlphaNum($charBeforeKeyword)) { + // this is really an identifier ending in a keyword, e.g. "xreturn" + return false; + } + + // it's a regexp. Remove unneeded whitespace after keyword + if ($this->a === ' ' || $this->a === "\n") { + $this->a = ''; + } + + return true; } /** diff --git a/min_unit_tests/_test_files/js/regexes.min.js b/min_unit_tests/_test_files/js/regexes.min.js index d3c80a6..d7d5b4e 100644 --- a/min_unit_tests/_test_files/js/regexes.min.js +++ b/min_unit_tests/_test_files/js/regexes.min.js @@ -1,3 +1,2 @@ -function testIssue74(){return /'/;} -!function(s){return /^[£$€?.]/.test(s);}();typeof -/ ' /;x=/ [/] /;1/foo;(2)/foo;function(){return/foo/};function(){return typeof/foo/}; \ No newline at end of file +function testIssue74(){return/'/;} +!function(s){return/^[£$€?.]/.test(s);}();typeof/ ' /;x=/ [/] /;1/foo;(2)/foo;function(){return/foo/};function(){return typeof/foo/}; \ No newline at end of file From 60b89dcc0d5dd9dc811beb6165e1b5226b04a9eb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Elan=20Ruusam=C3=A4e?= Date: Tue, 20 Sep 2016 23:36:24 +0300 Subject: [PATCH 04/31] disable server info by default again mistakenly enabled in 9370e96 --- server-info.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/server-info.php b/server-info.php index 20b1312..c829f9b 100644 --- a/server-info.php +++ b/server-info.php @@ -5,7 +5,7 @@ * * Change to true to expose this info. */ -$enabled = true; +$enabled = false; /////////////////////// From 9ca1bc9e74754f03edf0faf0d91b1af721f97119 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Elan=20Ruusam=C3=A4e?= Date: Wed, 12 Oct 2016 16:34:39 +0300 Subject: [PATCH 05/31] add checkAllowDirs to sourceFactoryOptions needed to be able to specify the option via config --- lib/Minify/App.php | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/lib/Minify/App.php b/lib/Minify/App.php index d39a639..f4ce31c 100644 --- a/lib/Minify/App.php +++ b/lib/Minify/App.php @@ -3,7 +3,6 @@ namespace Minify; use Props\Container; -use Psr\Log\LoggerInterface; /** * @property \Minify_CacheInterface $cache @@ -104,12 +103,14 @@ class App extends Container { if (empty($config->documentRoot)) { return $app->env->getDocRoot(); } + return $app->env->normalizePath($config->documentRoot); }; $this->env = function (App $app) { $config = $app->config; $envArgs = empty($config->envArgs) ? array() : $config->envArgs; + return new \Minify_Env($envArgs); }; @@ -117,6 +118,7 @@ class App extends Container { $format = "%channel%.%level_name%: %message% %context% %extra%"; $handler = new \Monolog\Handler\ErrorLogHandler(); $handler->setFormatter(new \Monolog\Formatter\LineFormatter($format)); + return $handler; }; @@ -142,11 +144,13 @@ class App extends Container { if ($value === true || $value instanceof \FirePHP) { $logger->pushHandler($app->errorLogHandler); $logger->pushHandler(new \Monolog\Handler\FirePHPHandler()); + return $logger; } if ($value instanceof \Monolog\Handler\HandlerInterface) { $logger->pushHandler($value); + return $logger; } @@ -154,6 +158,7 @@ class App extends Container { if (is_object($value) && is_callable(array($value, 'log'))) { $handler = new \Minify\Logger\LegacyHandler($value); $logger->pushHandler($handler); + return $logger; } @@ -232,6 +237,10 @@ class App extends Container { $ret['allowDirs'] = $serveOptions['minApp']['allowDirs']; } + if (isset($serveOptions['checkAllowDirs'])) { + $ret['checkAllowDirs'] = $serveOptions['checkAllowDirs']; + } + if (is_numeric($app->config->uploaderHoursBehind)) { $ret['uploaderHoursBehind'] = $app->config->uploaderHoursBehind; } @@ -258,6 +267,7 @@ class App extends Container { */ private function typeOf($var) { $type = gettype($var); + return $type === 'object' ? get_class($var) : $type; } } From fdc69a369e28e477d98c92b7692570435b6df740 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Elan=20Ruusam=C3=A4e?= Date: Wed, 12 Oct 2016 16:32:11 +0300 Subject: [PATCH 06/31] add scss support via leafo/scssphp --- composer.json | 1 + lib/Minify/ScssCssSource.php | 169 ++++++++++++++++++++++++++++++++++ lib/Minify/Source/Factory.php | 10 +- 3 files changed, 177 insertions(+), 3 deletions(-) create mode 100644 lib/Minify/ScssCssSource.php diff --git a/composer.json b/composer.json index f7e6c2e..04c54ee 100644 --- a/composer.json +++ b/composer.json @@ -34,6 +34,7 @@ }, "require-dev": { "leafo/lessphp": "~0.4.0", + "leafo/scssphp": "^0.6.6", "meenie/javascript-packer": "~1.1", "phpunit/phpunit": "4.8.*", "tedivm/jshrink": "~1.1.0" diff --git a/lib/Minify/ScssCssSource.php b/lib/Minify/ScssCssSource.php new file mode 100644 index 0000000..cf40bc1 --- /dev/null +++ b/lib/Minify/ScssCssSource.php @@ -0,0 +1,169 @@ +cache = $cache; + } + + /** + * Get last modified of all parsed files + * + * @return int + */ + public function getLastModified() + { + $cache = $this->getCache(); + + return $cache['updated']; + } + + /** + * Get content + * + * @return string + */ + public function getContent() + { + $cache = $this->getCache(); + + return $cache['content']; + } + + /** + * Make a unique cache id for for this source. + * + * @param string $prefix + * + * @return string + */ + private function getCacheId($prefix = 'minify') + { + $md5 = md5($this->filepath); + + return "{$prefix}_scss_{$md5}"; + } + + /** + * Get SCSS cache object + * + * Runs the compilation if needed + * + * Implements Leafo\ScssPhp\Server logic because we need to get parsed files without parsing actual content + * + * @return array + */ + private function getCache() + { + // cache for single run + // so that getLastModified and getContent in single request do not add additional cache roundtrips (i.e memcache) + if (isset($this->parsed)) { + return $this->parsed; + } + + // check from cache first + $cache = null; + $cacheId = $this->getCacheId(); + if ($this->cache->isValid($cacheId, 0)) { + if ($cache = $this->cache->fetch($cacheId)) { + $cache = unserialize($cache); + } + } + + $input = $cache ? $cache : $this->filepath; + + if ($this->cacheIsStale($cache)) { + $cache = $this->compile($this->filepath); + } + + if (!is_array($input) || $cache['updated'] > $input['updated']) { + $this->cache->store($cacheId, serialize($cache)); + } + + return $this->parsed = $cache; + } + + /** + * Determine whether .scss file needs to be re-compiled. + * + * @param array $cache Cache object + * + * @return boolean True if compile required. + */ + public function cacheIsStale($cache) + { + if (!$cache) { + return true; + } + + $updated = $cache['updated']; + foreach ($cache['files'] as $import => $mtime) { + $filemtime = filemtime($import); + + if ($filemtime !== $mtime || $filemtime > $updated) { + return true; + } + } + + return false; + } + + /** + * Compile .scss file + * + * @param string $filename Input path (.scss) + * + * @see Server::compile() + * @return array meta data result of the compile + */ + private function compile($filename) + { + $start = microtime(true); + $scss = new Compiler(); + $css = $scss->compile(file_get_contents($filename), $filename); + $elapsed = round((microtime(true) - $start), 4); + + $v = Version::VERSION; + $ts = date('r', $start); + $css = "/* compiled by scssphp $v on $ts (${elapsed}s) */\n\n" . $css; + + $imports = $scss->getParsedFiles(); + + $updated = 0; + foreach ($imports as $mtime) { + $updated = max($updated, $mtime); + } + + return array( + 'elapsed' => $elapsed, // statistic, can be dropped + 'updated' => $updated, + 'content' => $css, + 'files' => $imports, + ); + } +} diff --git a/lib/Minify/Source/Factory.php b/lib/Minify/Source/Factory.php index 7033179..71d7f08 100644 --- a/lib/Minify/Source/Factory.php +++ b/lib/Minify/Source/Factory.php @@ -67,9 +67,13 @@ class Minify_Source_Factory { throw new InvalidArgumentException("fileChecker option is not callable"); } - $this->setHandler('~\.less$~i', function ($spec) use ($cache) { - return new Minify_LessCssSource($spec, $cache); - }); + $this->setHandler('~\.less$~i', function ($spec) use ($cache) { + return new Minify_LessCssSource($spec, $cache); + }); + + $this->setHandler('~\.scss~i', function ($spec) use ($cache) { + return new Minify_ScssCssSource($spec, $cache); + }); $this->setHandler('~\.(js|css)$~i', function ($spec) { return new Minify_Source($spec); From b5a0ed3e3a989964e0b255870d5a9af18c2035fe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Elan=20Ruusam=C3=A4e?= Date: Wed, 12 Oct 2016 16:52:58 +0300 Subject: [PATCH 07/31] ci: bump php version so deps could be installed on travis for php 5.3 --- .travis.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.travis.yml b/.travis.yml index e1a2519..bb067ae 100644 --- a/.travis.yml +++ b/.travis.yml @@ -23,6 +23,8 @@ cache: - vendor install: + # set low version, so deps can be installed on 5.3 + - composer config platform.php 5.4 - composer update --no-interaction --prefer-source script: From ae1fdf4a30608e111454d2f99d7243b213116dc2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Elan=20Ruusam=C3=A4e?= Date: Thu, 13 Oct 2016 12:18:52 +0300 Subject: [PATCH 08/31] use lower scssphp version for php 5.3 compatibility the functionality we are using is present --- .travis.yml | 2 -- composer.json | 2 +- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/.travis.yml b/.travis.yml index bb067ae..e1a2519 100644 --- a/.travis.yml +++ b/.travis.yml @@ -23,8 +23,6 @@ cache: - vendor install: - # set low version, so deps can be installed on 5.3 - - composer config platform.php 5.4 - composer update --no-interaction --prefer-source script: diff --git a/composer.json b/composer.json index 04c54ee..478bb6b 100644 --- a/composer.json +++ b/composer.json @@ -34,7 +34,7 @@ }, "require-dev": { "leafo/lessphp": "~0.4.0", - "leafo/scssphp": "^0.6.6", + "leafo/scssphp": "^0.3.0", "meenie/javascript-packer": "~1.1", "phpunit/phpunit": "4.8.*", "tedivm/jshrink": "~1.1.0" From 3014900cd4e4089a82d8db0eaa6de78724ca70c8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Elan=20Ruusam=C3=A4e?= Date: Thu, 13 Oct 2016 12:20:50 +0300 Subject: [PATCH 09/31] add base directory of input file to import path this is needed for @import to be able to resolve included files --- lib/Minify/ScssCssSource.php | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/lib/Minify/ScssCssSource.php b/lib/Minify/ScssCssSource.php index cf40bc1..7da4a23 100644 --- a/lib/Minify/ScssCssSource.php +++ b/lib/Minify/ScssCssSource.php @@ -145,7 +145,13 @@ class Minify_ScssCssSource extends Minify_Source { { $start = microtime(true); $scss = new Compiler(); - $css = $scss->compile(file_get_contents($filename), $filename); + + // set import path directory the input filename resides + // otherwise @import statements will not find the files + // and will treat the @import line as css import + $scss->setImportPaths(dirname($filename)); + + $css = $scss->compile(file_get_contents($filename), $filename); $elapsed = round((microtime(true) - $start), 4); $v = Version::VERSION; From 2bd69ca5b1138a6561945789abb4d03af2701127 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Elan=20Ruusam=C3=A4e?= Date: Thu, 13 Oct 2016 12:21:09 +0300 Subject: [PATCH 10/31] test scssphp functionality tested cache dependencies --- tests/ScssSourceTest.php | 40 +++++++++++++++++++ tests/_test_files/_included.scss | 8 ++++ tests/_test_files/htmlHelper_groupsConfig.php | 4 ++ tests/_test_files/main.scss | 29 ++++++++++++++ 4 files changed, 81 insertions(+) create mode 100644 tests/ScssSourceTest.php create mode 100644 tests/_test_files/_included.scss create mode 100644 tests/_test_files/main.scss diff --git a/tests/ScssSourceTest.php b/tests/ScssSourceTest.php new file mode 100644 index 0000000..a1581ef --- /dev/null +++ b/tests/ScssSourceTest.php @@ -0,0 +1,40 @@ +realDocRoot = $_SERVER['DOCUMENT_ROOT']; + $_SERVER['DOCUMENT_ROOT'] = self::$document_root; + } + + /** + * @link https://github.com/mrclay/minify/issues/500 + */ + public function testTimestamp() + { + $baseDir = self::$test_files; + + $mainLess = "$baseDir/main.scss"; + $includedLess = "$baseDir/_included.scss"; + + // touch timestamp with 1s difference + touch($mainLess); + sleep(1); + touch($includedLess); + + $mtime1 = filemtime($mainLess); + var_dump($mtime1); + $mtime2 = filemtime($includedLess); + var_dump($mtime2); + + $max = max($mtime1, $mtime2); + + $options = array( + 'groupsConfigFile' => "$baseDir/htmlHelper_groupsConfig.php", + ); + $res = Minify_HTML_Helper::getUri('scss', $options); + + $this->assertEquals("/min/g=scss&{$max}", $res); + } +} \ No newline at end of file diff --git a/tests/_test_files/_included.scss b/tests/_test_files/_included.scss new file mode 100644 index 0000000..df8d371 --- /dev/null +++ b/tests/_test_files/_included.scss @@ -0,0 +1,8 @@ +/* lesstest2.scss */ + + +a.included { + color: $primary-color; + font-size: 13px; + text-decoration: none; +} diff --git a/tests/_test_files/htmlHelper_groupsConfig.php b/tests/_test_files/htmlHelper_groupsConfig.php index cf67275..cbf8a9d 100644 --- a/tests/_test_files/htmlHelper_groupsConfig.php +++ b/tests/_test_files/htmlHelper_groupsConfig.php @@ -9,4 +9,8 @@ return array( 'less' => array( '//_test_files/main.less', ), + + 'scss' => array( + '//_test_files/main.scss', + ), ); diff --git a/tests/_test_files/main.scss b/tests/_test_files/main.scss new file mode 100644 index 0000000..80bc0ea --- /dev/null +++ b/tests/_test_files/main.scss @@ -0,0 +1,29 @@ +/*! preserving comment */ + +// Variable +$primary-color: hotpink; + +// Mixin +@mixin border-radius($radius) { + -webkit-border-radius: $radius; + -moz-border-radius: $radius; + border-radius: $radius; +} + +.my-element { + color: $primary-color; + width: 100%; + overflow: hidden; +} + +.my-other-element { + @include border-radius(6px); +} + +/* import include -> */ +@import "_included"; +/* <- import included */ + +/* + a normal comment. +*/ \ No newline at end of file From 78d5921f911ea19d4f863cb0ed75976c055dc49f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Elan=20Ruusam=C3=A4e?= Date: Thu, 13 Oct 2016 12:37:08 +0300 Subject: [PATCH 11/31] lessphp: use updated timestamp from cache no need to calculate the timestamp ourselves each time the calculated value already present in cache object --- lib/Minify/LessCssSource.php | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/lib/Minify/LessCssSource.php b/lib/Minify/LessCssSource.php index e5a4314..1e3fa1b 100644 --- a/lib/Minify/LessCssSource.php +++ b/lib/Minify/LessCssSource.php @@ -30,13 +30,7 @@ class Minify_LessCssSource extends Minify_Source { public function getLastModified() { $cache = $this->getCache(); - $lastModified = 0; - foreach ($cache['files'] as $mtime) { - $lastModified = max($lastModified, $mtime); - - } - - return $lastModified; + return $cache['updated']; } /** From 72dd4db37a9ff2bcbf83075f34243d8ac2c2bf0d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Elan=20Ruusam=C3=A4e?= Date: Thu, 13 Oct 2016 12:50:27 +0300 Subject: [PATCH 12/31] calculate lastmodified to be maximum accurate the time() may be incorrect if there's slight delay between file modify and cache write. but as file modify is what is important, rely on that. also needed to use different cache file because the format change. --- lib/Minify/LessCssSource.php | 21 +++++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/lib/Minify/LessCssSource.php b/lib/Minify/LessCssSource.php index 1e3fa1b..249f9dc 100644 --- a/lib/Minify/LessCssSource.php +++ b/lib/Minify/LessCssSource.php @@ -30,7 +30,7 @@ class Minify_LessCssSource extends Minify_Source { public function getLastModified() { $cache = $this->getCache(); - return $cache['updated']; + return $cache['lastModified']; } /** @@ -70,12 +70,29 @@ class Minify_LessCssSource extends Minify_Source { $cache = $less->cachedCompile($input); if (!is_array($input) || $cache['updated'] > $input['updated']) { + $cache['lastModified'] = $this->getMaxLastModified($cache); $this->cache->store($cacheId, serialize($cache)); } return $this->parsed = $cache; } + /** + * Calculate maximum last modified of all files, + * as the 'updated' timestamp in cache is not the same as file last modified timestamp: + * @link https://github.com/leafo/lessphp/blob/v0.4.0/lessc.inc.php#L1904 + * @return int + */ + private function getMaxLastModified($cache) + { + $lastModified = 0; + foreach ($cache['files'] as $mtime) { + $lastModified = max($lastModified, $mtime); + } + + return $lastModified; + } + /** * Make a unique cache id for for this source. * @@ -86,7 +103,7 @@ class Minify_LessCssSource extends Minify_Source { private function getCacheId($prefix = 'minify') { $md5 = md5($this->filepath); - return "{$prefix}_less_{$md5}"; + return "{$prefix}_less2_{$md5}"; } /** From 035183b2b8a2d6453960fa9cba85b7ae86fa4fdb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Elan=20Ruusam=C3=A4e?= Date: Thu, 13 Oct 2016 14:40:21 +0300 Subject: [PATCH 13/31] cacheIsStale is not public --- lib/Minify/ScssCssSource.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/Minify/ScssCssSource.php b/lib/Minify/ScssCssSource.php index 7da4a23..038a03f 100644 --- a/lib/Minify/ScssCssSource.php +++ b/lib/Minify/ScssCssSource.php @@ -115,7 +115,7 @@ class Minify_ScssCssSource extends Minify_Source { * * @return boolean True if compile required. */ - public function cacheIsStale($cache) + private function cacheIsStale($cache) { if (!$cache) { return true; From 0cc631c5a98b37447a1bd7fc0bca80c5ed05d04c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Elan=20Ruusam=C3=A4e?= Date: Sun, 16 Oct 2016 16:44:58 +0300 Subject: [PATCH 14/31] php-cs fixes 1) Minify.php (return) 2) Minify/Env.php (return) 3) Minify/JS/JShrink.php (return) 4) Minify/HTML/Helper.php (return) 5) Minify/Logger/LegacyHandler.php (unused_use) 6) Minify/Lines.php (return) 7) Minify/Controller/Files.php (unused_use) 8) Minify/ControllerInterface.php (unused_use) 9) Minify/Cache/File.php (return) --- lib/Minify.php | 3 +++ lib/Minify/Cache/File.php | 2 ++ lib/Minify/Controller/Files.php | 1 - lib/Minify/ControllerInterface.php | 1 - lib/Minify/Env.php | 1 + lib/Minify/HTML/Helper.php | 2 ++ lib/Minify/JS/JShrink.php | 1 + lib/Minify/Lines.php | 1 + lib/Minify/Logger/LegacyHandler.php | 1 - 9 files changed, 10 insertions(+), 3 deletions(-) diff --git a/lib/Minify.php b/lib/Minify.php index ba5ac4d..eb3061e 100644 --- a/lib/Minify.php +++ b/lib/Minify.php @@ -497,6 +497,7 @@ class Minify { $content = substr($content, 3); } $content = str_replace("\r\n", "\n", $content); + return trim($content); } @@ -721,6 +722,7 @@ class Minify { $this->logger && $this->logger->warning('ContentType mismatch'); $this->sources = array(); + return $options; } @@ -734,6 +736,7 @@ class Minify { $this->logger && $this->logger->warning('ContentType mismatch'); $this->sources = array(); + return $options; } } diff --git a/lib/Minify/Cache/File.php b/lib/Minify/Cache/File.php index cb3a082..4a4f33b 100644 --- a/lib/Minify/Cache/File.php +++ b/lib/Minify/Cache/File.php @@ -64,6 +64,7 @@ class Minify_Cache_File implements Minify_CacheInterface { if ($data !== $this->fetch($id)) { @unlink($file); $this->logger->warning("Minify_Cache_File: Post-write read failed for '$file'"); + return false; } @@ -160,6 +161,7 @@ class Minify_Cache_File implements Minify_CacheInterface { public static function tmp() { trigger_error(__METHOD__ . ' is deprecated in Minfy 3.0', E_USER_DEPRECATED); + return sys_get_temp_dir(); } diff --git a/lib/Minify/Controller/Files.php b/lib/Minify/Controller/Files.php index da22bd3..db67d33 100644 --- a/lib/Minify/Controller/Files.php +++ b/lib/Minify/Controller/Files.php @@ -4,7 +4,6 @@ * @package Minify */ -use Psr\Log\LoggerInterface; use Monolog\Logger; /** diff --git a/lib/Minify/ControllerInterface.php b/lib/Minify/ControllerInterface.php index ebd71a4..ddefd75 100644 --- a/lib/Minify/ControllerInterface.php +++ b/lib/Minify/ControllerInterface.php @@ -1,6 +1,5 @@ Date: Sun, 16 Oct 2016 16:46:43 +0300 Subject: [PATCH 15/31] phpcs: enable psr2 --- .php_cs | 3 ++- lib/HTTP/ConditionalGet.php | 6 ++++-- lib/HTTP/Encoder.php | 12 +++++------- lib/Minify.php | 16 ++++++++-------- lib/Minify/App.php | 9 ++++++--- lib/Minify/Build.php | 8 +++++--- lib/Minify/CSS.php | 3 ++- lib/Minify/CSS/Compressor.php | 6 ++++-- lib/Minify/CSS/UriRewriter.php | 9 ++++++--- lib/Minify/CSSmin.php | 3 ++- lib/Minify/Cache/APC.php | 3 ++- lib/Minify/Cache/File.php | 5 +++-- lib/Minify/Cache/Memcache.php | 7 ++++--- lib/Minify/Cache/Null.php | 3 ++- lib/Minify/Cache/WinCache.php | 10 +++++----- lib/Minify/Cache/XCache.php | 3 ++- lib/Minify/Cache/ZendPlatform.php | 3 ++- lib/Minify/CacheInterface.php | 3 ++- lib/Minify/CommentPreserver.php | 3 ++- lib/Minify/Controller/Base.php | 3 ++- lib/Minify/Controller/Files.php | 6 ++++-- lib/Minify/Controller/Groups.php | 6 ++++-- lib/Minify/Controller/MinApp.php | 6 ++++-- lib/Minify/Controller/Page.php | 6 ++++-- lib/Minify/ControllerInterface.php | 3 ++- lib/Minify/DebugDetector.php | 3 ++- lib/Minify/Env.php | 3 ++- lib/Minify/HTML.php | 6 ++++-- lib/Minify/HTML/Helper.php | 9 ++++++--- lib/Minify/ImportProcessor.php | 19 +++++++++++-------- lib/Minify/JS/ClosureCompiler.php | 7 +++++-- lib/Minify/LessCssSource.php | 21 ++++++++++++++------- lib/Minify/Lines.php | 6 ++++-- lib/Minify/Packer.php | 3 ++- lib/Minify/ScssCssSource.php | 11 ++++++----- lib/Minify/ServeConfiguration.php | 3 ++- lib/Minify/Source.php | 16 +++++++++------- lib/Minify/Source/Factory.php | 3 ++- lib/Minify/Source/FactoryException.php | 4 +++- lib/Minify/SourceInterface.php | 3 ++- lib/Minify/SourceSet.php | 3 ++- lib/Minify/YUICompressor.php | 13 +++++++------ lib/MrClay/Cli.php | 3 ++- lib/MrClay/Cli/Arg.php | 3 ++- 44 files changed, 175 insertions(+), 109 deletions(-) diff --git a/.php_cs b/.php_cs index ddae094..8f25773 100644 --- a/.php_cs +++ b/.php_cs @@ -5,7 +5,7 @@ $finder = Symfony\CS\Finder\DefaultFinder::create() ; return Symfony\CS\Config\Config::create() - ->level(Symfony\CS\FixerInterface::NONE_LEVEL) + ->level(Symfony\CS\FixerInterface::PSR2_LEVEL) ->setUsingCache(true) ->fixers(array( 'linefeed', @@ -21,6 +21,7 @@ return Symfony\CS\Config\Config::create() 'controls_spaces', 'elseif', '-eof_ending', + '-method_argument_space', )) ->finder($finder) ; diff --git a/lib/HTTP/ConditionalGet.php b/lib/HTTP/ConditionalGet.php index 72d11c8..0f251ee 100644 --- a/lib/HTTP/ConditionalGet.php +++ b/lib/HTTP/ConditionalGet.php @@ -60,7 +60,8 @@ * @subpackage HTTP * @author Stephen Clay */ -class HTTP_ConditionalGet { +class HTTP_ConditionalGet +{ /** * Does the client have a valid copy of the requested resource? @@ -340,7 +341,8 @@ class HTTP_ConditionalGet { * * @return string */ - protected function normalizeEtag($etag) { + protected function normalizeEtag($etag) + { $etag = trim($etag); return $this->_stripEtag diff --git a/lib/HTTP/Encoder.php b/lib/HTTP/Encoder.php index 6e236ee..3bd788c 100644 --- a/lib/HTTP/Encoder.php +++ b/lib/HTTP/Encoder.php @@ -43,7 +43,8 @@ * @subpackage HTTP * @author Stephen Clay */ -class HTTP_Encoder { +class HTTP_Encoder +{ /** * Should the encoder allow HTTP encoding to IE6? @@ -97,8 +98,7 @@ class HTTP_Encoder { $this->_headers['Content-Type'] = $spec['type']; } if (isset($spec['method']) - && in_array($spec['method'], array('gzip', 'deflate', 'compress', ''))) - { + && in_array($spec['method'], array('gzip', 'deflate', 'compress', ''))) { $this->_encodeMethod = array($spec['method'], $spec['method']); } else { $this->_encodeMethod = self::getAcceptedEncoding(); @@ -192,8 +192,7 @@ class HTTP_Encoder { // @link http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html if (! isset($_SERVER['HTTP_ACCEPT_ENCODING']) - || self::isBuggyIe()) - { + || self::isBuggyIe()) { return array('', ''); } $ae = $_SERVER['HTTP_ACCEPT_ENCODING']; @@ -259,8 +258,7 @@ class HTTP_Encoder { } if ('' === $this->_encodeMethod[0] || ($compressionLevel == 0) - || !extension_loaded('zlib')) - { + || !extension_loaded('zlib')) { return false; } if ($this->_encodeMethod[0] === 'deflate') { diff --git a/lib/Minify.php b/lib/Minify.php index eb3061e..f6a532b 100644 --- a/lib/Minify.php +++ b/lib/Minify.php @@ -24,7 +24,8 @@ use Psr\Log\LoggerInterface; * @license http://opensource.org/licenses/bsd-license.php New BSD License * @link https://github.com/mrclay/minify */ -class Minify { +class Minify +{ /** * API version @@ -87,7 +88,8 @@ class Minify { * @param Minify_CacheInterface $cache * @param LoggerInterface $logger */ - public function __construct(Minify_CacheInterface $cache, LoggerInterface $logger = null) { + public function __construct(Minify_CacheInterface $cache, LoggerInterface $logger = null) + { $this->cache = $cache; $this->logger = $logger; } @@ -492,7 +494,8 @@ class Minify { * @param string $content * @return string */ - public static function nullMinifier($content) { + public static function nullMinifier($content) + { if (isset($content[0]) && $content[0] === "\xef") { $content = substr($content, 3); } @@ -506,7 +509,7 @@ class Minify { */ protected function setupUriRewrites() { - foreach($this->sources as $key => $source) { + foreach ($this->sources as $key => $source) { $file = $this->env->normalizePath($source->getFilePath()); $minifyOptions = $source->getMinifierOptions(); @@ -594,8 +597,7 @@ class Minify { || $type === self::TYPE_CSS // yes, to process CSS individually (avoiding PCRE bugs/limits) || $minifier !== $lastMinifier // yes, minifier changed || $options !== $lastOptions) // yes, options changed - ) - { + ) { // minify previous sources with last settings $imploded = implode($implodeSeparator, $groupToProcessTogether); $groupToProcessTogether = array(); @@ -718,7 +720,6 @@ class Minify { if (!empty($options['contentType'])) { // just verify sources have null content type or match the options if ($sourceType !== null && $sourceType !== $options['contentType']) { - $this->logger && $this->logger->warning('ContentType mismatch'); $this->sources = array(); @@ -732,7 +733,6 @@ class Minify { if ($type === null) { $type = $sourceType; } elseif ($sourceType !== $type) { - $this->logger && $this->logger->warning('ContentType mismatch'); $this->sources = array(); diff --git a/lib/Minify/App.php b/lib/Minify/App.php index f4ce31c..ecab7ef 100644 --- a/lib/Minify/App.php +++ b/lib/Minify/App.php @@ -21,7 +21,8 @@ use Props\Container; * @property \Minify_Source_Factory $sourceFactory * @property array $sourceFactoryOptions */ -class App extends Container { +class App extends Container +{ /** * Constructor @@ -249,7 +250,8 @@ class App extends Container { }; } - public function runServer() { + public function runServer() + { if (!$this->env->get('f') && $this->env->get('g') === null) { // no spec given $msg = '

No "f" or "g" parameters were detected.

'; @@ -265,7 +267,8 @@ class App extends Container { * @param mixed $var * @return string */ - private function typeOf($var) { + private function typeOf($var) + { $type = gettype($var); return $type === 'object' ? get_class($var) : $type; diff --git a/lib/Minify/Build.php b/lib/Minify/Build.php index e4428e0..dcfd8e2 100644 --- a/lib/Minify/Build.php +++ b/lib/Minify/Build.php @@ -34,7 +34,8 @@ * @package Minify * @author Stephen Clay */ -class Minify_Build { +class Minify_Build +{ /** * Last modification time of all files in the build @@ -67,7 +68,8 @@ class Minify_Build { * append the timestamp to the URI. * @return string */ - public function uri($uri, $forceAmpersand = false) { + public function uri($uri, $forceAmpersand = false) + { $sep = ($forceAmpersand || strpos($uri, '?') !== false) ? self::$ampersand : '?'; @@ -75,7 +77,7 @@ class Minify_Build { return "{$uri}{$sep}{$this->lastModified}"; } - /** + /** * Create a build object * * @param array $sources array of Minify_Source objects and/or file paths diff --git a/lib/Minify/CSS.php b/lib/Minify/CSS.php index da389ea..bc3a3ad 100644 --- a/lib/Minify/CSS.php +++ b/lib/Minify/CSS.php @@ -16,7 +16,8 @@ * * @deprecated Use Minify_CSSmin */ -class Minify_CSS { +class Minify_CSS +{ /** * Minify a CSS string diff --git a/lib/Minify/CSS/Compressor.php b/lib/Minify/CSS/Compressor.php index aa9f81f..5fba844 100644 --- a/lib/Minify/CSS/Compressor.php +++ b/lib/Minify/CSS/Compressor.php @@ -26,7 +26,8 @@ * * @deprecated Use CSSmin (tubalmartin/cssmin) */ -class Minify_CSS_Compressor { +class Minify_CSS_Compressor +{ /** * Minify a CSS string @@ -61,7 +62,8 @@ class Minify_CSS_Compressor { * * @param array $options (currently ignored) */ - private function __construct($options) { + private function __construct($options) + { $this->_options = $options; } diff --git a/lib/Minify/CSS/UriRewriter.php b/lib/Minify/CSS/UriRewriter.php index 93bf321..4fe7b46 100644 --- a/lib/Minify/CSS/UriRewriter.php +++ b/lib/Minify/CSS/UriRewriter.php @@ -10,7 +10,8 @@ * @package Minify * @author Stephen Clay */ -class Minify_CSS_UriRewriter { +class Minify_CSS_UriRewriter +{ /** * rewrite() and rewriteRelative() append debugging information here @@ -326,7 +327,8 @@ class Minify_CSS_UriRewriter { * @param string $css * @return string */ - private static function _owlifySvgPaths($css) { + private static function _owlifySvgPaths($css) + { return preg_replace('~\b((?:clip-path|mask|-webkit-mask)\s*\:\s*)url(\(\s*#\w+\s*\))~', '$1owl$2', $css); } @@ -338,7 +340,8 @@ class Minify_CSS_UriRewriter { * @param string $css * @return string */ - private static function _unOwlify($css) { + private static function _unOwlify($css) + { return preg_replace('~\b((?:clip-path|mask|-webkit-mask)\s*\:\s*)owl~', '$1url', $css); } } diff --git a/lib/Minify/CSSmin.php b/lib/Minify/CSSmin.php index 8c3a64f..ad5cdbf 100644 --- a/lib/Minify/CSSmin.php +++ b/lib/Minify/CSSmin.php @@ -12,7 +12,8 @@ * @package Minify * @author Stephen Clay */ -class Minify_CSSmin { +class Minify_CSSmin +{ /** * Minify a CSS string diff --git a/lib/Minify/Cache/APC.php b/lib/Minify/Cache/APC.php index 2e65501..94c2871 100644 --- a/lib/Minify/Cache/APC.php +++ b/lib/Minify/Cache/APC.php @@ -14,7 +14,8 @@ * @package Minify * @author Chris Edwards **/ -class Minify_Cache_APC implements Minify_CacheInterface { +class Minify_Cache_APC implements Minify_CacheInterface +{ /** * Create a Minify_Cache_APC object, to be passed to diff --git a/lib/Minify/Cache/File.php b/lib/Minify/Cache/File.php index 4a4f33b..eeba305 100644 --- a/lib/Minify/Cache/File.php +++ b/lib/Minify/Cache/File.php @@ -6,7 +6,8 @@ use Psr\Log\LoggerInterface; -class Minify_Cache_File implements Minify_CacheInterface { +class Minify_Cache_File implements Minify_CacheInterface +{ /** * @var string @@ -117,7 +118,7 @@ class Minify_Cache_File implements Minify_CacheInterface { } } - /** + /** * Fetch the cached content * * @param string $id cache id (e.g. a filename) diff --git a/lib/Minify/Cache/Memcache.php b/lib/Minify/Cache/Memcache.php index ad6c480..180b607 100644 --- a/lib/Minify/Cache/Memcache.php +++ b/lib/Minify/Cache/Memcache.php @@ -17,7 +17,8 @@ * } * **/ -class Minify_Cache_Memcache implements Minify_CacheInterface { +class Minify_Cache_Memcache implements Minify_CacheInterface +{ /** * Create a Minify_Cache_Memcache object, to be passed to @@ -92,7 +93,7 @@ class Minify_Cache_Memcache implements Minify_CacheInterface { : ''; } - /** + /** * Fetch the cached content * * @param string $id cache id @@ -114,7 +115,7 @@ class Minify_Cache_Memcache implements Minify_CacheInterface { private $_data = null; private $_id = null; - /** + /** * Fetch data and timestamp from memcache, store in instance * * @param string $id diff --git a/lib/Minify/Cache/Null.php b/lib/Minify/Cache/Null.php index 38c77c7..4f654a6 100644 --- a/lib/Minify/Cache/Null.php +++ b/lib/Minify/Cache/Null.php @@ -8,7 +8,8 @@ * * @package Minify */ -class Minify_Cache_Null implements Minify_CacheInterface { +class Minify_Cache_Null implements Minify_CacheInterface +{ /** * Write data to cache. * diff --git a/lib/Minify/Cache/WinCache.php b/lib/Minify/Cache/WinCache.php index 4097500..26132bf 100644 --- a/lib/Minify/Cache/WinCache.php +++ b/lib/Minify/Cache/WinCache.php @@ -99,12 +99,12 @@ class Minify_Cache_WinCache implements Minify_CacheInterface return $this->_fetch($id) ? $this->_data : ''; } - private $_exp = NULL; + private $_exp = null; // cache of most recently fetched id - private $_lm = NULL; - private $_data = NULL; - private $_id = NULL; + private $_lm = null; + private $_data = null; + private $_id = null; /** * Fetch data and timestamp from WinCache, store in instance @@ -121,7 +121,7 @@ class Minify_Cache_WinCache implements Minify_CacheInterface $suc = false; $ret = wincache_ucache_get($id, $suc); if (!$suc) { - $this->_id = NULL; + $this->_id = null; return false; } diff --git a/lib/Minify/Cache/XCache.php b/lib/Minify/Cache/XCache.php index 4edd261..a5585bb 100644 --- a/lib/Minify/Cache/XCache.php +++ b/lib/Minify/Cache/XCache.php @@ -17,7 +17,8 @@ * @package Minify * @author Elan Ruusamäe **/ -class Minify_Cache_XCache implements Minify_CacheInterface { +class Minify_Cache_XCache implements Minify_CacheInterface +{ /** * Create a Minify_Cache_XCache object, to be passed to diff --git a/lib/Minify/Cache/ZendPlatform.php b/lib/Minify/Cache/ZendPlatform.php index 9e5d248..b1f6d22 100644 --- a/lib/Minify/Cache/ZendPlatform.php +++ b/lib/Minify/Cache/ZendPlatform.php @@ -16,7 +16,8 @@ * @package Minify * @author Patrick van Dissel */ -class Minify_Cache_ZendPlatform implements Minify_CacheInterface { +class Minify_Cache_ZendPlatform implements Minify_CacheInterface +{ /** * Create a Minify_Cache_ZendPlatform object, to be passed to diff --git a/lib/Minify/CacheInterface.php b/lib/Minify/CacheInterface.php index 56b79b8..1b891b1 100644 --- a/lib/Minify/CacheInterface.php +++ b/lib/Minify/CacheInterface.php @@ -9,7 +9,8 @@ * * @package Minify */ -interface Minify_CacheInterface { +interface Minify_CacheInterface +{ /** * Write data to cache. * diff --git a/lib/Minify/CommentPreserver.php b/lib/Minify/CommentPreserver.php index 00db9ff..f295839 100644 --- a/lib/Minify/CommentPreserver.php +++ b/lib/Minify/CommentPreserver.php @@ -10,7 +10,8 @@ * @package Minify * @author Stephen Clay */ -class Minify_CommentPreserver { +class Minify_CommentPreserver +{ /** * String to be prepended to each preserved comment diff --git a/lib/Minify/Controller/Base.php b/lib/Minify/Controller/Base.php index e95e6e9..54a60c9 100644 --- a/lib/Minify/Controller/Base.php +++ b/lib/Minify/Controller/Base.php @@ -15,7 +15,8 @@ use Monolog\Logger; * @package Minify * @author Stephen Clay */ -abstract class Minify_Controller_Base implements Minify_ControllerInterface { +abstract class Minify_Controller_Base implements Minify_ControllerInterface +{ /** * @var Minify_Env diff --git a/lib/Minify/Controller/Files.php b/lib/Minify/Controller/Files.php index db67d33..85a76d0 100644 --- a/lib/Minify/Controller/Files.php +++ b/lib/Minify/Controller/Files.php @@ -28,7 +28,8 @@ use Monolog\Logger; * @package Minify * @author Stephen Clay */ -class Minify_Controller_Files extends Minify_Controller_Base { +class Minify_Controller_Files extends Minify_Controller_Base +{ /** * Set up file sources @@ -40,7 +41,8 @@ class Minify_Controller_Files extends Minify_Controller_Base { * * 'files': (required) array of complete file paths, or a single path */ - public function createConfiguration(array $options) { + public function createConfiguration(array $options) + { // strip controller options $files = $options['files']; diff --git a/lib/Minify/Controller/Groups.php b/lib/Minify/Controller/Groups.php index 5c415e0..a115a00 100644 --- a/lib/Minify/Controller/Groups.php +++ b/lib/Minify/Controller/Groups.php @@ -23,7 +23,8 @@ * @package Minify * @author Stephen Clay */ -class Minify_Controller_Groups extends Minify_Controller_Files { +class Minify_Controller_Groups extends Minify_Controller_Files +{ /** * Set up groups of files as sources @@ -35,7 +36,8 @@ class Minify_Controller_Groups extends Minify_Controller_Files { * * @return array Minify options */ - public function createConfiguration(array $options) { + public function createConfiguration(array $options) + { // strip controller options $groups = $options['groups']; unset($options['groups']); diff --git a/lib/Minify/Controller/MinApp.php b/lib/Minify/Controller/MinApp.php index 80a05c5..b09ac81 100644 --- a/lib/Minify/Controller/MinApp.php +++ b/lib/Minify/Controller/MinApp.php @@ -10,7 +10,8 @@ * @package Minify * @author Stephen Clay */ -class Minify_Controller_MinApp extends Minify_Controller_Base { +class Minify_Controller_MinApp extends Minify_Controller_Base +{ /** * Set up groups of files as sources @@ -19,7 +20,8 @@ class Minify_Controller_MinApp extends Minify_Controller_Base { * * @return array Minify options */ - public function createConfiguration(array $options) { + public function createConfiguration(array $options) + { // PHP insecure by default: realpath() and other FS functions can't handle null bytes. $get = $this->env->get(); foreach (array('g', 'b', 'f') as $key) { diff --git a/lib/Minify/Controller/Page.php b/lib/Minify/Controller/Page.php index 8120479..36d9714 100644 --- a/lib/Minify/Controller/Page.php +++ b/lib/Minify/Controller/Page.php @@ -11,7 +11,8 @@ * @package Minify * @author Stephen Clay */ -class Minify_Controller_Page extends Minify_Controller_Base { +class Minify_Controller_Page extends Minify_Controller_Base +{ /** * Set up source of HTML content @@ -31,7 +32,8 @@ class Minify_Controller_Page extends Minify_Controller_Base { * 'minifyAll': should all CSS and Javascript blocks be individually * minified? (default false) */ - public function createConfiguration(array $options) { + public function createConfiguration(array $options) + { if (isset($options['file'])) { $sourceSpec = array( 'filepath' => $options['file'] diff --git a/lib/Minify/ControllerInterface.php b/lib/Minify/ControllerInterface.php index ddefd75..35b4de3 100644 --- a/lib/Minify/ControllerInterface.php +++ b/lib/Minify/ControllerInterface.php @@ -1,7 +1,8 @@ */ -class Minify_DebugDetector { +class Minify_DebugDetector +{ public static function shouldDebugRequest(Minify_Env $env) { if ($env->get('debug') !== null) { diff --git a/lib/Minify/Env.php b/lib/Minify/Env.php index decb718..d8274e5 100644 --- a/lib/Minify/Env.php +++ b/lib/Minify/Env.php @@ -1,6 +1,7 @@ */ -class Minify_HTML { +class Minify_HTML +{ /** * @var boolean */ @@ -40,7 +41,8 @@ class Minify_HTML { * * @return string */ - public static function minify($html, $options = array()) { + public static function minify($html, $options = array()) + { $min = new self($html, $options); return $min->process(); diff --git a/lib/Minify/HTML/Helper.php b/lib/Minify/HTML/Helper.php index f07e5d9..498d3c7 100644 --- a/lib/Minify/HTML/Helper.php +++ b/lib/Minify/HTML/Helper.php @@ -10,7 +10,8 @@ * @package Minify * @author Stephen Clay */ -class Minify_HTML_Helper { +class Minify_HTML_Helper +{ public $rewriteWorks = true; public $minAppUri = '/min'; public $groupsConfigFile = ''; @@ -190,7 +191,8 @@ class Minify_HTML_Helper { * @param int $pos index to check * @return mixed a common char or '' if any do not match */ - protected static function _getCommonCharAtPos($arr, $pos) { + protected static function _getCommonCharAtPos($arr, $pos) + { if (!isset($arr[0][$pos])) { return ''; } @@ -215,7 +217,8 @@ class Minify_HTML_Helper { * @param string $minRoot root-relative URI of the "min" application * @return string */ - protected static function _getShortestUri($paths, $minRoot = '/min/') { + protected static function _getShortestUri($paths, $minRoot = '/min/') + { $pos = 0; $base = ''; while (true) { diff --git a/lib/Minify/ImportProcessor.php b/lib/Minify/ImportProcessor.php index 715a9bf..1ed707b 100644 --- a/lib/Minify/ImportProcessor.php +++ b/lib/Minify/ImportProcessor.php @@ -18,8 +18,8 @@ * @author Stephen Clay * @author Simon Schick */ -class Minify_ImportProcessor { - +class Minify_ImportProcessor +{ public static $filesIncluded = array(); public static function process($file) @@ -173,8 +173,7 @@ class Minify_ImportProcessor { $arFrom = explode($ps, rtrim($realFrom, $ps)); $arTo = explode($ps, rtrim($realTo, $ps)); - while (count($arFrom) && count($arTo) && ($arFrom[0] == $arTo[0])) - { + while (count($arFrom) && count($arTo) && ($arFrom[0] == $arTo[0])) { array_shift($arFrom); array_shift($arTo); } @@ -191,18 +190,21 @@ class Minify_ImportProcessor { private function truepath($path) { // whether $path is unix or not - $unipath = strlen($path) == 0 || $path{0} != '/'; + $unipath = strlen($path) == 0 || $path{0} + != '/'; // attempts to detect if path is relative in which case, add cwd - if (strpos($path, ':') === false && $unipath) + if (strpos($path, ':') === false && $unipath) { $path = $this->_currentDir . DIRECTORY_SEPARATOR . $path; + } // resolve path parts (single dot, double dot and double delimiters) $path = str_replace(array('/', '\\'), DIRECTORY_SEPARATOR, $path); $parts = array_filter(explode(DIRECTORY_SEPARATOR, $path), 'strlen'); $absolutes = array(); foreach ($parts as $part) { - if ('.' == $part) + if ('.' == $part) { continue; + } if ('..' == $part) { array_pop($absolutes); } else { @@ -211,8 +213,9 @@ class Minify_ImportProcessor { } $path = implode(DIRECTORY_SEPARATOR, $absolutes); // resolve any symlinks - if (file_exists($path) && linkinfo($path) > 0) + if (file_exists($path) && linkinfo($path) > 0) { $path = readlink($path); + } // put initial separator that could have been lost $path = !$unipath ? '/' . $path : $path; diff --git a/lib/Minify/JS/ClosureCompiler.php b/lib/Minify/JS/ClosureCompiler.php index ade3c2f..20381a2 100644 --- a/lib/Minify/JS/ClosureCompiler.php +++ b/lib/Minify/JS/ClosureCompiler.php @@ -13,7 +13,8 @@ * * @todo can use a stream wrapper to unit test this? */ -class Minify_JS_ClosureCompiler { +class Minify_JS_ClosureCompiler +{ /** * @var string The option key for the maximum POST byte size @@ -228,4 +229,6 @@ class Minify_JS_ClosureCompiler { } } -class Minify_JS_ClosureCompiler_Exception extends Exception {} +class Minify_JS_ClosureCompiler_Exception extends Exception +{ +} diff --git a/lib/Minify/LessCssSource.php b/lib/Minify/LessCssSource.php index 249f9dc..8fa2e63 100644 --- a/lib/Minify/LessCssSource.php +++ b/lib/Minify/LessCssSource.php @@ -1,6 +1,7 @@ cache = $cache; @@ -27,7 +29,8 @@ class Minify_LessCssSource extends Minify_Source { * * @return int */ - public function getLastModified() { + public function getLastModified() + { $cache = $this->getCache(); return $cache['lastModified']; @@ -38,7 +41,8 @@ class Minify_LessCssSource extends Minify_Source { * * @return string */ - public function getContent() { + public function getContent() + { $cache = $this->getCache(); return $cache['compiled']; @@ -49,7 +53,8 @@ class Minify_LessCssSource extends Minify_Source { * * @return array */ - private function getCache() { + private function getCache() + { // cache for single run // so that getLastModified and getContent in single request do not add additional cache roundtrips (i.e memcache) if (isset($this->parsed)) { @@ -100,7 +105,8 @@ class Minify_LessCssSource extends Minify_Source { * * @return string */ - private function getCacheId($prefix = 'minify') { + private function getCacheId($prefix = 'minify') + { $md5 = md5($this->filepath); return "{$prefix}_less2_{$md5}"; @@ -111,7 +117,8 @@ class Minify_LessCssSource extends Minify_Source { * * @return lessc */ - private function getCompiler() { + private function getCompiler() + { $less = new lessc(); // do not spend CPU time letting less doing minify $less->setPreserveComments(true); diff --git a/lib/Minify/Lines.php b/lib/Minify/Lines.php index 92bc4a4..db85d85 100644 --- a/lib/Minify/Lines.php +++ b/lib/Minify/Lines.php @@ -11,7 +11,8 @@ * @author Stephen Clay * @author Adam Pedersen (Issue 55 fix) */ -class Minify_Lines { +class Minify_Lines +{ /** * Add line numbers in C-style comments @@ -156,7 +157,8 @@ class Minify_Lines { * @param string $token Token being checked * @return bool */ - private static function _find($str, $token) { + private static function _find($str, $token) + { switch ($token) { case '//': $fakes = array( diff --git a/lib/Minify/Packer.php b/lib/Minify/Packer.php index f6fbcd8..7ddca79 100644 --- a/lib/Minify/Packer.php +++ b/lib/Minify/Packer.php @@ -19,7 +19,8 @@ * * @package Minify */ -class Minify_Packer { +class Minify_Packer +{ public static function minify($code, $options = array()) { // @todo: set encoding options based on $options :) diff --git a/lib/Minify/ScssCssSource.php b/lib/Minify/ScssCssSource.php index 038a03f..9aa58f0 100644 --- a/lib/Minify/ScssCssSource.php +++ b/lib/Minify/ScssCssSource.php @@ -8,7 +8,8 @@ use Leafo\ScssPhp\Version; * * @link https://github.com/leafo/scssphp/ */ -class Minify_ScssCssSource extends Minify_Source { +class Minify_ScssCssSource extends Minify_Source +{ /** * @var Minify_CacheInterface */ @@ -146,12 +147,12 @@ class Minify_ScssCssSource extends Minify_Source { $start = microtime(true); $scss = new Compiler(); - // set import path directory the input filename resides - // otherwise @import statements will not find the files + // set import path directory the input filename resides + // otherwise @import statements will not find the files // and will treat the @import line as css import - $scss->setImportPaths(dirname($filename)); + $scss->setImportPaths(dirname($filename)); - $css = $scss->compile(file_get_contents($filename), $filename); + $css = $scss->compile(file_get_contents($filename), $filename); $elapsed = round((microtime(true) - $start), 4); $v = Version::VERSION; diff --git a/lib/Minify/ServeConfiguration.php b/lib/Minify/ServeConfiguration.php index a2938a1..12d9d2f 100644 --- a/lib/Minify/ServeConfiguration.php +++ b/lib/Minify/ServeConfiguration.php @@ -9,7 +9,8 @@ * * @package Minify */ -class Minify_ServeConfiguration { +class Minify_ServeConfiguration +{ /** * @var Minify_SourceInterface[] diff --git a/lib/Minify/Source.php b/lib/Minify/Source.php index b44107e..39597a6 100644 --- a/lib/Minify/Source.php +++ b/lib/Minify/Source.php @@ -13,7 +13,8 @@ * @package Minify * @author Stephen Clay */ -class Minify_Source implements Minify_SourceInterface { +class Minify_Source implements Minify_SourceInterface +{ /** * @var int time of last modification @@ -70,13 +71,13 @@ class Minify_Source implements Minify_SourceInterface { if (isset($spec['filepath'])) { $ext = pathinfo($spec['filepath'], PATHINFO_EXTENSION); switch ($ext) { - case 'js' : $this->contentType = Minify::TYPE_JS; + case 'js': $this->contentType = Minify::TYPE_JS; break; - case 'less' : // fallthrough - case 'css' : $this->contentType = Minify::TYPE_CSS; + case 'less': // fallthrough + case 'css': $this->contentType = Minify::TYPE_CSS; break; - case 'htm' : // fallthrough - case 'html' : $this->contentType = Minify::TYPE_HTML; + case 'htm': // fallthrough + case 'html': $this->contentType = Minify::TYPE_HTML; break; } $this->filepath = $spec['filepath']; @@ -203,7 +204,8 @@ class Minify_Source implements Minify_SourceInterface { /** * {@inheritdoc} */ - public function setupUriRewrites() { + public function setupUriRewrites() + { if ($this->filepath && !isset($this->minifyOptions['currentDir']) && !isset($this->minifyOptions['prependRelativePath']) diff --git a/lib/Minify/Source/Factory.php b/lib/Minify/Source/Factory.php index 71d7f08..f36d1b2 100644 --- a/lib/Minify/Source/Factory.php +++ b/lib/Minify/Source/Factory.php @@ -1,6 +1,7 @@ */ -class Minify_YUICompressor { +class Minify_YUICompressor +{ /** * Filepath of the YUI Compressor jar file. This must be set before @@ -112,15 +113,15 @@ class Minify_YUICompressor { ,'nomunge' => false ,'preserve-semi' => false ,'disable-optimizations' => false - ,'stack-size' => '' + ,'stack-size' => '' ) ,$userOptions ); $cmd = self::$javaExecutable - . (!empty($o['stack-size']) - ? ' -Xss' . $o['stack-size'] - : '') - . ' -jar ' . escapeshellarg(self::$jarFile) + . (!empty($o['stack-size']) + ? ' -Xss' . $o['stack-size'] + : '') + . ' -jar ' . escapeshellarg(self::$jarFile) . " --type {$type}" . (preg_match('/^[\\da-zA-Z0-9\\-]+$/', $o['charset']) ? " --charset {$o['charset']}" diff --git a/lib/MrClay/Cli.php b/lib/MrClay/Cli.php index f382c82..e9ef3b3 100644 --- a/lib/MrClay/Cli.php +++ b/lib/MrClay/Cli.php @@ -18,7 +18,8 @@ use InvalidArgumentException; * @author Steve Clay * @license http://www.opensource.org/licenses/mit-license.php MIT License */ -class Cli { +class Cli +{ /** * @var array validation errors diff --git a/lib/MrClay/Cli/Arg.php b/lib/MrClay/Cli/Arg.php index 9c8b0e3..b7a46e9 100644 --- a/lib/MrClay/Cli/Arg.php +++ b/lib/MrClay/Cli/Arg.php @@ -43,7 +43,8 @@ use BadMethodCallException; * @author Steve Clay * @license http://www.opensource.org/licenses/mit-license.php MIT License */ -class Arg { +class Arg +{ /** * @return array */ From 16c811cd93b74c0dc8d7a543cea9f02020224d88 Mon Sep 17 00:00:00 2001 From: Steve Clay Date: Sun, 16 Oct 2016 15:13:38 -0400 Subject: [PATCH 16/31] Big style cleanup --- lib/Minify.php | 10 ++--- lib/Minify/App.php | 5 ++- lib/Minify/Build.php | 4 +- lib/Minify/CSS.php | 25 +++++------- lib/Minify/CSS/Compressor.php | 61 +++++++++++++++------------- lib/Minify/CSS/UriRewriter.php | 56 ++++++++++++++------------ lib/Minify/Cache/APC.php | 18 ++++----- lib/Minify/Cache/File.php | 46 +++++++++++---------- lib/Minify/Cache/Memcache.php | 18 ++++----- lib/Minify/Cache/WinCache.php | 8 +++- lib/Minify/Cache/XCache.php | 18 ++++----- lib/Minify/Cache/ZendPlatform.php | 18 +++------ lib/Minify/CommentPreserver.php | 21 ++++------ lib/Minify/Controller/Groups.php | 14 ++++--- lib/Minify/Controller/MinApp.php | 67 ++++++++++++++++--------------- lib/Minify/Controller/Page.php | 8 ++-- lib/Minify/DebugDetector.php | 1 + lib/Minify/Env.php | 14 +++---- lib/Minify/HTML/Helper.php | 7 +--- lib/Minify/ImportProcessor.php | 34 ++++++---------- lib/Minify/Lines.php | 30 +++++++------- lib/Minify/Source.php | 14 +++---- lib/Minify/YUICompressor.php | 26 ++++++------ 23 files changed, 257 insertions(+), 266 deletions(-) diff --git a/lib/Minify.php b/lib/Minify.php index f6a532b..c42e60e 100644 --- a/lib/Minify.php +++ b/lib/Minify.php @@ -274,7 +274,8 @@ class Minify // depending on what the client accepts, $contentEncoding may be // 'x-gzip' while our internal encodeMethod is 'gzip'. Calling // getAcceptedEncoding(false, false) leaves out compress and deflate as options. - list($this->options['encodeMethod'], $contentEncoding) = HTTP_Encoder::getAcceptedEncoding(false, false); + $list = HTTP_Encoder::getAcceptedEncoding(false, false); + list($this->options['encodeMethod'], $contentEncoding) = $list; $sendVary = ! HTTP_Encoder::isBuggyIe(); } } else { @@ -515,8 +516,8 @@ class Minify if ($file && !isset($minifyOptions['currentDir']) - && !isset($minifyOptions['prependRelativePath']) - ) { + && !isset($minifyOptions['prependRelativePath'])) { + $minifyOptions['currentDir'] = dirname($file); $source->setMinifierOptions($minifyOptions); } @@ -596,8 +597,7 @@ class Minify ! $source // yes, we ran out of sources || $type === self::TYPE_CSS // yes, to process CSS individually (avoiding PCRE bugs/limits) || $minifier !== $lastMinifier // yes, minifier changed - || $options !== $lastOptions) // yes, options changed - ) { + || $options !== $lastOptions)) { // yes, options changed // minify previous sources with last settings $imploded = implode($implodeSeparator, $groupToProcessTogether); $groupToProcessTogether = array(); diff --git a/lib/Minify/App.php b/lib/Minify/App.php index ecab7ef..840f364 100644 --- a/lib/Minify/App.php +++ b/lib/Minify/App.php @@ -64,9 +64,10 @@ class App extends Container $propNames = array_keys(get_object_vars($config)); - $varNames = array_map(function ($name) { + $prefixer = function ($name) { return "min_$name"; - }, $propNames); + }; + $varNames = array_map($prefixer, $propNames); $vars = compact($varNames); diff --git a/lib/Minify/Build.php b/lib/Minify/Build.php index dcfd8e2..bf9b487 100644 --- a/lib/Minify/Build.php +++ b/lib/Minify/Build.php @@ -70,9 +70,7 @@ class Minify_Build */ public function uri($uri, $forceAmpersand = false) { - $sep = ($forceAmpersand || strpos($uri, '?') !== false) - ? self::$ampersand - : '?'; + $sep = ($forceAmpersand || strpos($uri, '?') !== false) ? self::$ampersand : '?'; return "{$uri}{$sep}{$this->lastModified}"; } diff --git a/lib/Minify/CSS.php b/lib/Minify/CSS.php index bc3a3ad..c311f2e 100644 --- a/lib/Minify/CSS.php +++ b/lib/Minify/CSS.php @@ -71,32 +71,27 @@ class Minify_CSS if ($options['removeCharsets']) { $css = preg_replace('/@charset[^;]+;\\s*/', '', $css); } + if ($options['compress']) { if (! $options['preserveComments']) { $css = Minify_CSS_Compressor::process($css, $options); } else { - $css = Minify_CommentPreserver::process( - $css - ,array('Minify_CSS_Compressor', 'process') - ,array($options) - ); + $processor = array('Minify_CSS_Compressor', 'process'); + $css = Minify_CommentPreserver::process($css, $processor, array($options)); } } + if (! $options['currentDir'] && ! $options['prependRelativePath']) { return $css; } + if ($options['currentDir']) { - return Minify_CSS_UriRewriter::rewrite( - $css - ,$options['currentDir'] - ,$options['docRoot'] - ,$options['symlinks'] - ); + $currentDir = $options['currentDir']; + $docRoot = $options['docRoot']; + $symlinks = $options['symlinks']; + return Minify_CSS_UriRewriter::rewrite($css, $currentDir, $docRoot, $symlinks); } else { - return Minify_CSS_UriRewriter::prepend( - $css - ,$options['prependRelativePath'] - ); + return Minify_CSS_UriRewriter::prepend($css, $options['prependRelativePath']); } } } diff --git a/lib/Minify/CSS/Compressor.php b/lib/Minify/CSS/Compressor.php index 5fba844..ee3c7d6 100644 --- a/lib/Minify/CSS/Compressor.php +++ b/lib/Minify/CSS/Compressor.php @@ -88,8 +88,8 @@ class Minify_CSS_Compressor $css = preg_replace('@:\\s*/\\*\\s*\\*/@', ':/*keep*/', $css); // apply callback to all valid comments (and strip out surrounding ws - $css = preg_replace_callback('@\\s*/\\*([\\s\\S]*?)\\*/\\s*@' - ,array($this, '_commentCB'), $css); + $pattern = '@\\s*/\\*([\\s\\S]*?)\\*/\\s*@'; + $css = preg_replace_callback($pattern, array($this, '_commentCB'), $css); // remove ws around { } and last semicolon in declaration block $css = preg_replace('/\\s*{\\s*/', '{', $css); @@ -99,16 +99,17 @@ class Minify_CSS_Compressor $css = preg_replace('/\\s*;\\s*/', ';', $css); // remove ws around urls - $css = preg_replace('/ + $pattern = '/ url\\( # url( \\s* ([^\\)]+?) # 1 = the URL (really just a bunch of non right parenthesis) \\s* \\) # ) - /x', 'url($1)', $css); + /x'; + $css = preg_replace($pattern, 'url($1)', $css); // remove ws between rules and colons - $css = preg_replace('/ + $pattern = '/ \\s* ([{;]) # 1 = beginning of block or rule separator \\s* @@ -117,10 +118,11 @@ class Minify_CSS_Compressor : \\s* (\\b|[#\'"-]) # 3 = first character of a value - /x', '$1$2:$3', $css); + /x'; + $css = preg_replace($pattern, '$1$2:$3', $css); // remove ws in selectors - $css = preg_replace_callback('/ + $pattern = '/ (?: # non-capture \\s* [^~>+,\\s]+ # selector part @@ -130,16 +132,16 @@ class Minify_CSS_Compressor \\s* [^~>+,\\s]+ # selector part { # open declaration block - /x' - ,array($this, '_selectorsCB'), $css); + /x'; + $css = preg_replace_callback($pattern, array($this, '_selectorsCB'), $css); // minimize hex colors - $css = preg_replace('/([^=])#([a-f\\d])\\2([a-f\\d])\\3([a-f\\d])\\4([\\s;\\}])/i' - , '$1#$2$3$4$5', $css); + $pattern = '/([^=])#([a-f\\d])\\2([a-f\\d])\\3([a-f\\d])\\4([\\s;\\}])/i'; + $css = preg_replace($pattern, '$1#$2$3$4$5', $css); // remove spaces between font families - $css = preg_replace_callback('/font-family:([^;}]+)([;}])/' - ,array($this, '_fontFamilyCB'), $css); + $pattern = '/font-family:([^;}]+)([;}])/'; + $css = preg_replace_callback($pattern, array($this, '_fontFamilyCB'), $css); $css = preg_replace('/@import\\s+url/', '@import url', $css); @@ -147,14 +149,15 @@ class Minify_CSS_Compressor $css = preg_replace('/[ \\t]*\\n+\\s*/', "\n", $css); // separate common descendent selectors w/ newlines (to limit line lengths) - $css = preg_replace('/([\\w#\\.\\*]+)\\s+([\\w#\\.\\*]+){/', "$1\n$2{", $css); + $pattern = '/([\\w#\\.\\*]+)\\s+([\\w#\\.\\*]+){/'; + $css = preg_replace($pattern, "$1\n$2{", $css); // Use newline after 1st numeric value (to limit line lengths). - $css = preg_replace('/ + $pattern = '/ ((?:padding|margin|border|outline):\\d+(?:px|em)?) # 1 = prop : 1st numeric value \\s+ - /x' - ,"$1\n", $css); + /x'; + $css = preg_replace($pattern, "$1\n", $css); // prevent triggering IE6 bug: http://www.crankygeek.com/ie6pebug/ $css = preg_replace('/:first-l(etter|ine)\\{/', ':first-l$1 {', $css); @@ -191,52 +194,54 @@ class Minify_CSS_Compressor if ($m === 'keep') { return '/**/'; } + if ($m === '" "') { // component of http://tantek.com/CSS/Examples/midpass.html return '/*" "*/'; } + if (preg_match('@";\\}\\s*\\}/\\*\\s+@', $m)) { // component of http://tantek.com/CSS/Examples/midpass.html return '/*";}}/* */'; } + if ($this->_inHack) { // inversion: feeding only to one browser - if (preg_match('@ + $pattern = '@ ^/ # comment started like /*/ \\s* (\\S[\\s\\S]+?) # has at least some non-ws content \\s* /\\* # ends like /*/ or /**/ - @x', $m, $n)) { + @x'; + if (preg_match($pattern, $m, $n)) { // end hack mode after this comment, but preserve the hack and comment content $this->_inHack = false; - return "/*/{$n[1]}/**/"; } } + if (substr($m, -1) === '\\') { // comment ends like \*/ // begin hack mode and preserve hack $this->_inHack = true; - return '/*\\*/'; } + if ($m !== '' && $m[0] === '/') { // comment looks like /*/ foo */ // begin hack mode and preserve hack $this->_inHack = true; - return '/*/*/'; } + if ($this->_inHack) { // a regular comment ends hack mode but should be preserved $this->_inHack = false; - return '/**/'; } + // Issue 107: if there's any surrounding whitespace, it may be important, so // replace the comment with a single space - return $hasSurroundingWs // remove all other comments - ? ' ' - : ''; + return $hasSurroundingWs ? ' ' : ''; // remove all other comments } /** @@ -249,8 +254,10 @@ class Minify_CSS_Compressor protected function _fontFamilyCB($m) { // Issue 210: must not eliminate WS between words in unquoted families - $pieces = preg_split('/(\'[^\']+\'|"[^"]+")/', $m[1], null, PREG_SPLIT_DELIM_CAPTURE | PREG_SPLIT_NO_EMPTY); + $flags = PREG_SPLIT_DELIM_CAPTURE | PREG_SPLIT_NO_EMPTY; + $pieces = preg_split('/(\'[^\']+\'|"[^"]+")/', $m[1], null, $flags); $out = 'font-family:'; + while (null !== ($piece = array_shift($pieces))) { if ($piece[0] !== '"' && $piece[0] !== "'") { $piece = preg_replace('/\\s+/', ' ', $piece); diff --git a/lib/Minify/CSS/UriRewriter.php b/lib/Minify/CSS/UriRewriter.php index 4fe7b46..248875c 100644 --- a/lib/Minify/CSS/UriRewriter.php +++ b/lib/Minify/CSS/UriRewriter.php @@ -52,10 +52,10 @@ class Minify_CSS_UriRewriter // normalize symlinks in order to map to link foreach ($symlinks as $link => $target) { - $link = ($link === '//') - ? self::$_docRoot - : str_replace('//', self::$_docRoot . '/', $link); + + $link = ($link === '//') ? self::$_docRoot : str_replace('//', self::$_docRoot . '/', $link); $link = strtr($link, '/', DIRECTORY_SEPARATOR); + self::$_symlinks[$link] = self::_realpath($target); } @@ -71,10 +71,11 @@ class Minify_CSS_UriRewriter $css = self::_owlifySvgPaths($css); // rewrite - $css = preg_replace_callback('/@import\\s+([\'"])(.*?)[\'"]/' - ,array(self::$className, '_processUriCB'), $css); - $css = preg_replace_callback('/url\\(\\s*([\'"](.*?)[\'"]|[^\\)\\s]+)\\s*\\)/' - ,array(self::$className, '_processUriCB'), $css); + $pattern = '/@import\\s+([\'"])(.*?)[\'"]/'; + $css = preg_replace_callback($pattern, array(self::$className, '_processUriCB'), $css); + + $pattern = '/url\\(\\s*([\'"](.*?)[\'"]|[^\\)\\s]+)\\s*\\)/'; + $css = preg_replace_callback($pattern, array(self::$className, '_processUriCB'), $css); $css = self::_unOwlify($css); @@ -99,10 +100,11 @@ class Minify_CSS_UriRewriter $css = self::_owlifySvgPaths($css); // append - $css = preg_replace_callback('/@import\\s+([\'"])(.*?)[\'"]/' - ,array(self::$className, '_processUriCB'), $css); - $css = preg_replace_callback('/url\\(\\s*([\'"](.*?)[\'"]|[^\\)\\s]+)\\s*\\)/' - ,array(self::$className, '_processUriCB'), $css); + $pattern = '/@import\\s+([\'"])(.*?)[\'"]/'; + $css = preg_replace_callback($pattern, array(self::$className, '_processUriCB'), $css); + + $pattern = '/url\\(\\s*([\'"](.*?)[\'"]|[^\\)\\s]+)\\s*\\)/'; + $css = preg_replace_callback($pattern, array(self::$className, '_processUriCB'), $css); $css = self::_unOwlify($css); @@ -152,8 +154,8 @@ class Minify_CSS_UriRewriter public static function rewriteRelative($uri, $realCurrentDir, $realDocRoot, $symlinks = array()) { // prepend path with current dir separator (OS-independent) - $path = strtr($realCurrentDir, '/', DIRECTORY_SEPARATOR) - . DIRECTORY_SEPARATOR . strtr($uri, '/', DIRECTORY_SEPARATOR); + $path = strtr($realCurrentDir, '/', DIRECTORY_SEPARATOR); + $path .= DIRECTORY_SEPARATOR . strtr($uri, '/', DIRECTORY_SEPARATOR); self::$debugText .= "file-relative URI : {$uri}\n" . "path prepended : {$path}\n"; @@ -263,13 +265,14 @@ class Minify_CSS_UriRewriter */ private static function _trimUrls($css) { - return preg_replace('/ + $pattern = '/ url\\( # url( \\s* ([^\\)]+?) # 1 = URI (assuming does not contain ")") \\s* \\) # ) - /x', 'url($1)', $css); + /x'; + return preg_replace($pattern, 'url($1)', $css); } /** @@ -287,12 +290,9 @@ class Minify_CSS_UriRewriter $uri = $m[2]; } else { // $m[1] is either quoted or not - $quoteChar = ($m[1][0] === "'" || $m[1][0] === '"') - ? $m[1][0] - : ''; - $uri = ($quoteChar === '') - ? $m[1] - : substr($m[1], 1, strlen($m[1]) - 2); + $quoteChar = ($m[1][0] === "'" || $m[1][0] === '"') ? $m[1][0] : ''; + + $uri = ($quoteChar === '') ? $m[1] : substr($m[1], 1, strlen($m[1]) - 2); } // if not root/scheme relative and not starts with scheme if (!preg_match('~^(/|[a-z]+\:)~', $uri)) { @@ -313,9 +313,11 @@ class Minify_CSS_UriRewriter } } - return $isImport - ? "@import {$quoteChar}{$uri}{$quoteChar}" - : "url({$quoteChar}{$uri}{$quoteChar})"; + if ($isImport) { + return "@import {$quoteChar}{$uri}{$quoteChar}"; + } else { + return "url({$quoteChar}{$uri}{$quoteChar})"; + } } /** @@ -329,7 +331,8 @@ class Minify_CSS_UriRewriter */ private static function _owlifySvgPaths($css) { - return preg_replace('~\b((?:clip-path|mask|-webkit-mask)\s*\:\s*)url(\(\s*#\w+\s*\))~', '$1owl$2', $css); + $pattern = '~\b((?:clip-path|mask|-webkit-mask)\s*\:\s*)url(\(\s*#\w+\s*\))~'; + return preg_replace($pattern, '$1owl$2', $css); } /** @@ -342,6 +345,7 @@ class Minify_CSS_UriRewriter */ private static function _unOwlify($css) { - return preg_replace('~\b((?:clip-path|mask|-webkit-mask)\s*\:\s*)owl~', '$1url', $css); + $pattern = '~\b((?:clip-path|mask|-webkit-mask)\s*\:\s*)owl~'; + return preg_replace($pattern, '$1url', $css); } } diff --git a/lib/Minify/Cache/APC.php b/lib/Minify/Cache/APC.php index 94c2871..479938d 100644 --- a/lib/Minify/Cache/APC.php +++ b/lib/Minify/Cache/APC.php @@ -59,9 +59,11 @@ class Minify_Cache_APC implements Minify_CacheInterface return false; } - return (function_exists('mb_strlen') && ((int)ini_get('mbstring.func_overload') & 2)) - ? mb_strlen($this->_data, '8bit') - : strlen($this->_data); + if (function_exists('mb_strlen') && ((int)ini_get('mbstring.func_overload') & 2)) { + return mb_strlen($this->_data, '8bit'); + } else { + return strlen($this->_data);; + } } /** @@ -85,9 +87,7 @@ class Minify_Cache_APC implements Minify_CacheInterface */ public function display($id) { - echo $this->_fetch($id) - ? $this->_data - : ''; + echo $this->_fetch($id) ? $this->_data : ''; } /** @@ -99,9 +99,7 @@ class Minify_Cache_APC implements Minify_CacheInterface */ public function fetch($id) { - return $this->_fetch($id) - ? $this->_data - : ''; + return $this->_fetch($id) ? $this->_data : ''; } private $_exp = null; @@ -126,9 +124,9 @@ class Minify_Cache_APC implements Minify_CacheInterface $ret = apc_fetch($id); if (false === $ret) { $this->_id = null; - return false; } + list($this->_lm, $this->_data) = explode('|', $ret, 2); $this->_id = $id; diff --git a/lib/Minify/Cache/File.php b/lib/Minify/Cache/File.php index eeba305..7f57472 100644 --- a/lib/Minify/Cache/File.php +++ b/lib/Minify/Cache/File.php @@ -54,13 +54,13 @@ class Minify_Cache_File implements Minify_CacheInterface */ public function store($id, $data) { - $flag = $this->locking - ? LOCK_EX - : null; + $flag = $this->locking ? LOCK_EX : null; $file = $this->path . '/' . $id; + if (! @file_put_contents($file, $data, $flag)) { $this->logger->warning("Minify_Cache_File: Write failed to '$file'"); } + // write control if ($data !== $this->fetch($id)) { @unlink($file); @@ -107,15 +107,16 @@ class Minify_Cache_File implements Minify_CacheInterface */ public function display($id) { - if ($this->locking) { - $fp = fopen($this->path . '/' . $id, 'rb'); - flock($fp, LOCK_SH); - fpassthru($fp); - flock($fp, LOCK_UN); - fclose($fp); - } else { + if (!$this->locking) { readfile($this->path . '/' . $id); + return; } + + $fp = fopen($this->path . '/' . $id, 'rb'); + flock($fp, LOCK_SH); + fpassthru($fp); + flock($fp, LOCK_UN); + fclose($fp); } /** @@ -127,20 +128,21 @@ class Minify_Cache_File implements Minify_CacheInterface */ public function fetch($id) { - if ($this->locking) { - $fp = fopen($this->path . '/' . $id, 'rb'); - if (!$fp) { - return false; - } - flock($fp, LOCK_SH); - $ret = stream_get_contents($fp); - flock($fp, LOCK_UN); - fclose($fp); - - return $ret; - } else { + if (!$this->locking) { return file_get_contents($this->path . '/' . $id); } + + $fp = fopen($this->path . '/' . $id, 'rb'); + if (!$fp) { + return false; + } + + flock($fp, LOCK_SH); + $ret = stream_get_contents($fp); + flock($fp, LOCK_UN); + fclose($fp); + + return $ret; } /** diff --git a/lib/Minify/Cache/Memcache.php b/lib/Minify/Cache/Memcache.php index 180b607..d70dd07 100644 --- a/lib/Minify/Cache/Memcache.php +++ b/lib/Minify/Cache/Memcache.php @@ -62,9 +62,11 @@ class Minify_Cache_Memcache implements Minify_CacheInterface return false; } - return (function_exists('mb_strlen') && ((int)ini_get('mbstring.func_overload') & 2)) - ? mb_strlen($this->_data, '8bit') - : strlen($this->_data); + if (function_exists('mb_strlen') && ((int)ini_get('mbstring.func_overload') & 2)) { + return mb_strlen($this->_data, '8bit'); + } else { + return strlen($this->_data); + } } /** @@ -88,9 +90,7 @@ class Minify_Cache_Memcache implements Minify_CacheInterface */ public function display($id) { - echo $this->_fetch($id) - ? $this->_data - : ''; + echo $this->_fetch($id) ? $this->_data : ''; } /** @@ -102,9 +102,7 @@ class Minify_Cache_Memcache implements Minify_CacheInterface */ public function fetch($id) { - return $this->_fetch($id) - ? $this->_data - : ''; + return $this->_fetch($id) ? $this->_data : ''; } private $_mc = null; @@ -127,12 +125,14 @@ class Minify_Cache_Memcache implements Minify_CacheInterface if ($this->_id === $id) { return true; } + $ret = $this->_mc->get($id); if (false === $ret) { $this->_id = null; return false; } + list($this->_lm, $this->_data) = explode('|', $ret, 2); $this->_id = $id; diff --git a/lib/Minify/Cache/WinCache.php b/lib/Minify/Cache/WinCache.php index 26132bf..46e285a 100644 --- a/lib/Minify/Cache/WinCache.php +++ b/lib/Minify/Cache/WinCache.php @@ -60,7 +60,11 @@ class Minify_Cache_WinCache implements Minify_CacheInterface return false; } - return (function_exists('mb_strlen') && ((int) ini_get('mbstring.func_overload') & 2)) ? mb_strlen($this->_data, '8bit') : strlen($this->_data); + if (function_exists('mb_strlen') && ((int) ini_get('mbstring.func_overload') & 2)) { + return mb_strlen($this->_data, '8bit'); + } else { + return strlen($this->_data); + } } /** @@ -118,6 +122,7 @@ class Minify_Cache_WinCache implements Minify_CacheInterface if ($this->_id === $id) { return true; } + $suc = false; $ret = wincache_ucache_get($id, $suc); if (!$suc) { @@ -125,6 +130,7 @@ class Minify_Cache_WinCache implements Minify_CacheInterface return false; } + list($this->_lm, $this->_data) = explode('|', $ret, 2); $this->_id = $id; diff --git a/lib/Minify/Cache/XCache.php b/lib/Minify/Cache/XCache.php index a5585bb..f293cb3 100644 --- a/lib/Minify/Cache/XCache.php +++ b/lib/Minify/Cache/XCache.php @@ -56,9 +56,11 @@ class Minify_Cache_XCache implements Minify_CacheInterface return false; } - return (function_exists('mb_strlen') && ((int)ini_get('mbstring.func_overload') & 2)) - ? mb_strlen($this->_data, '8bit') - : strlen($this->_data); + if (function_exists('mb_strlen') && ((int)ini_get('mbstring.func_overload') & 2)) { + return mb_strlen($this->_data, '8bit'); + } else { + return strlen($this->_data); + } } /** @@ -80,9 +82,7 @@ class Minify_Cache_XCache implements Minify_CacheInterface */ public function display($id) { - echo $this->_fetch($id) - ? $this->_data - : ''; + echo $this->_fetch($id) ? $this->_data : ''; } /** @@ -93,9 +93,7 @@ class Minify_Cache_XCache implements Minify_CacheInterface */ public function fetch($id) { - return $this->_fetch($id) - ? $this->_data - : ''; + return $this->_fetch($id) ? $this->_data : ''; } private $_exp = null; @@ -116,12 +114,14 @@ class Minify_Cache_XCache implements Minify_CacheInterface if ($this->_id === $id) { return true; } + $ret = xcache_get($id); if (false === $ret) { $this->_id = null; return false; } + list($this->_lm, $this->_data) = explode('|', $ret, 2); $this->_id = $id; diff --git a/lib/Minify/Cache/ZendPlatform.php b/lib/Minify/Cache/ZendPlatform.php index b1f6d22..76e9920 100644 --- a/lib/Minify/Cache/ZendPlatform.php +++ b/lib/Minify/Cache/ZendPlatform.php @@ -55,9 +55,7 @@ class Minify_Cache_ZendPlatform implements Minify_CacheInterface */ public function getSize($id) { - return $this->_fetch($id) - ? strlen($this->_data) - : false; + return $this->_fetch($id) ? strlen($this->_data) : false; } /** @@ -71,9 +69,7 @@ class Minify_Cache_ZendPlatform implements Minify_CacheInterface */ public function isValid($id, $srcMtime) { - $ret = ($this->_fetch($id) && ($this->_lm >= $srcMtime)); - - return $ret; + return ($this->_fetch($id) && ($this->_lm >= $srcMtime)); } /** @@ -83,9 +79,7 @@ class Minify_Cache_ZendPlatform implements Minify_CacheInterface */ public function display($id) { - echo $this->_fetch($id) - ? $this->_data - : ''; + echo $this->_fetch($id) ? $this->_data : ''; } /** @@ -97,9 +91,7 @@ class Minify_Cache_ZendPlatform implements Minify_CacheInterface */ public function fetch($id) { - return $this->_fetch($id) - ? $this->_data - : ''; + return $this->_fetch($id) ? $this->_data : ''; } private $_exp = null; @@ -121,12 +113,14 @@ class Minify_Cache_ZendPlatform implements Minify_CacheInterface if ($this->_id === $id) { return true; } + $ret = output_cache_get($id, $this->_exp); if (false === $ret) { $this->_id = null; return false; } + list($this->_lm, $this->_data) = explode('|', $ret, 2); $this->_id = $id; diff --git a/lib/Minify/CommentPreserver.php b/lib/Minify/CommentPreserver.php index f295839..6bdb6f3 100644 --- a/lib/Minify/CommentPreserver.php +++ b/lib/Minify/CommentPreserver.php @@ -72,21 +72,16 @@ class Minify_CommentPreserver */ private static function _nextComment($in) { - if ( - false === ($start = strpos($in, '/*!')) - || false === ($end = strpos($in, '*/', $start + 3)) - ) { + if (false === ($start = strpos($in, '/*!')) || false === ($end = strpos($in, '*/', $start + 3))) { return array($in, false, false); } - $ret = array( - substr($in, 0, $start) - ,self::$prepend . '/*!' . substr($in, $start + 3, $end - $start - 1) . self::$append - ); - $endChars = (strlen($in) - $end - 2); - $ret[] = (0 === $endChars) - ? '' - : substr($in, -$endChars); - return $ret; + $beforeComment = substr($in, 0, $start); + $comment = self::$prepend . '/*!' . substr($in, $start + 3, $end - $start - 1) . self::$append; + + $endChars = (strlen($in) - $end - 2); + $afterComment = (0 === $endChars) ? '' : substr($in, -$endChars); + + return array($beforeComment, $comment, $afterComment); } } diff --git a/lib/Minify/Controller/Groups.php b/lib/Minify/Controller/Groups.php index a115a00..8938288 100644 --- a/lib/Minify/Controller/Groups.php +++ b/lib/Minify/Controller/Groups.php @@ -45,12 +45,14 @@ class Minify_Controller_Groups extends Minify_Controller_Files $server = $this->env->server(); // mod_fcgid places PATH_INFO in ORIG_PATH_INFO - $pathInfo = isset($server['ORIG_PATH_INFO']) - ? substr($server['ORIG_PATH_INFO'], 1) - : (isset($server['PATH_INFO']) - ? substr($server['PATH_INFO'], 1) - : false - ); + if (isset($server['ORIG_PATH_INFO'])) { + $pathInfo = substr($server['ORIG_PATH_INFO'], 1); + } elseif (isset($server['PATH_INFO'])) { + $pathInfo = substr($server['PATH_INFO'], 1) + } else { + $pathInfo = false; + } + if (false === $pathInfo || ! isset($groups[$pathInfo])) { // no PATH_INFO or not a valid group $this->logger->info("Missing PATH_INFO or no group set for \"$pathInfo\""); diff --git a/lib/Minify/Controller/MinApp.php b/lib/Minify/Controller/MinApp.php index b09ac81..7606982 100644 --- a/lib/Minify/Controller/MinApp.php +++ b/lib/Minify/Controller/MinApp.php @@ -31,14 +31,14 @@ class Minify_Controller_MinApp extends Minify_Controller_Base } // filter controller options - $localOptions = array_merge( - array( - 'groupsOnly' => false, - 'groups' => array(), - 'symlinks' => array(), - ) - ,(isset($options['minApp']) ? $options['minApp'] : array()) + $defaults = array( + 'groupsOnly' => false, + 'groups' => array(), + 'symlinks' => array(), ); + $minApp = isset($options['minApp']) ? $options['minApp'] : array(); + $localOptions = array_merge($defaults, $minApp); + unset($options['minApp']); // normalize $symlinks in order to map to target @@ -53,7 +53,7 @@ class Minify_Controller_MinApp extends Minify_Controller_Base $sources = array(); $selectionId = ''; - $firstMissingResource = null; + $firstMissing = null; if (isset($get['g'])) { // add group(s) @@ -83,12 +83,12 @@ class Minify_Controller_MinApp extends Minify_Controller_Base $sources[] = $source; } catch (Minify_Source_FactoryException $e) { $this->logger->error($e->getMessage()); - if (null === $firstMissingResource) { - $firstMissingResource = basename($file); + if (null === $firstMissing) { + $firstMissing = basename($file); continue; } else { - $secondMissingResource = basename($file); - $this->logger->info("More than one file was missing: '$firstMissingResource', '$secondMissingResource'"); + $secondMissing = basename($file); + $this->logger->info("More than one file was missing: '$firstMissing', '$secondMissing'"); return new Minify_ServeConfiguration($options); } @@ -100,18 +100,18 @@ class Minify_Controller_MinApp extends Minify_Controller_Base // try user files // The following restrictions are to limit the URLs that minify will // respond to. - if (// verify at least one file, files are single comma separated, - // and are all same extension - ! preg_match('/^[^,]+\\.(css|less|js)(?:,[^,]+\\.\\1)*$/', $get['f'], $m) - // no "//" - || strpos($get['f'], '//') !== false - // no "\" - || strpos($get['f'], '\\') !== false - ) { + + // verify at least one file, files are single comma separated, and are all same extension + $validPattern = preg_match('/^[^,]+\\.(css|less|js)(?:,[^,]+\\.\\1)*$/', $get['f'], $m); + $hasComment = strpos($get['f'], '//') !== false; + $hasEscape = strpos($get['f'], '\\') !== false; + + if (!$validPattern || $hasComment || $hasEscape) { $this->logger->info("GET param 'f' was invalid"); return new Minify_ServeConfiguration($options); } + $ext = ".{$m[1]}"; $files = explode(',', $get['f']); if ($files != array_unique($files)) { @@ -119,11 +119,14 @@ class Minify_Controller_MinApp extends Minify_Controller_Base return new Minify_ServeConfiguration($options); } + if (isset($get['b'])) { // check for validity - if (preg_match('@^[^/]+(?:/[^/]+)*$@', $get['b']) - && false === strpos($get['b'], '..') - && $get['b'] !== '.') { + $isValidBase = preg_match('@^[^/]+(?:/[^/]+)*$@', $get['b']); + $hasDots = false !== strpos($get['b'], '..'); + $isDot = $get['b'] === '.'; + + if ($isValidBase && !$hasDots && !$isDot) { // valid base $base = "/{$get['b']}/"; } else { @@ -154,12 +157,12 @@ class Minify_Controller_MinApp extends Minify_Controller_Base $basenames[] = basename($path, $ext); } catch (Minify_Source_FactoryException $e) { $this->logger->error($e->getMessage()); - if (null === $firstMissingResource) { - $firstMissingResource = $uri; + if (null === $firstMissing) { + $firstMissing = $uri; continue; } else { - $secondMissingResource = $uri; - $this->logger->info("More than one file was missing: '$firstMissingResource', '$secondMissingResource`'"); + $secondMissing = $uri; + $this->logger->info("More than one file was missing: '$firstMissing', '$secondMissing`'"); return new Minify_ServeConfiguration($options); } @@ -177,14 +180,14 @@ class Minify_Controller_MinApp extends Minify_Controller_Base return new Minify_ServeConfiguration($options); } - if (null !== $firstMissingResource) { + if (null !== $firstMissing) { array_unshift($sources, new Minify_Source(array( - 'id' => 'missingFile' + 'id' => 'missingFile', // should not cause cache invalidation - ,'lastModified' => 0 + 'lastModified' => 0, // due to caching, filename is unreliable. - ,'content' => "/* Minify: at least one missing file. See " . Minify::URL_DEBUG . " */\n" - ,'minifier' => 'Minify::nullMinifier' + 'content' => "/* Minify: at least one missing file. See " . Minify::URL_DEBUG . " */\n", + 'minifier' => 'Minify::nullMinifier', ))); } diff --git a/lib/Minify/Controller/Page.php b/lib/Minify/Controller/Page.php index 36d9714..7001fe0 100644 --- a/lib/Minify/Controller/Page.php +++ b/lib/Minify/Controller/Page.php @@ -42,8 +42,8 @@ class Minify_Controller_Page extends Minify_Controller_Base } else { // strip controller options $sourceSpec = array( - 'content' => $options['content'] - ,'id' => $options['id'] + 'content' => $options['content'], + 'id' => $options['id'], ); $f = $options['id']; unset($options['content'], $options['id']); @@ -54,8 +54,8 @@ class Minify_Controller_Page extends Minify_Controller_Base if (isset($options['minifyAll'])) { // this will be the 2nd argument passed to Minify_HTML::minify() $sourceSpec['minifyOptions'] = array( - 'cssMinifier' => array('Minify_CSSmin', 'minify') - ,'jsMinifier' => array('JSMin\\JSMin', 'minify') + 'cssMinifier' => array('Minify_CSSmin', 'minify'), + 'jsMinifier' => array('JSMin\\JSMin', 'minify'), ); unset($options['minifyAll']); } diff --git a/lib/Minify/DebugDetector.php b/lib/Minify/DebugDetector.php index 10b19a7..19d03d0 100644 --- a/lib/Minify/DebugDetector.php +++ b/lib/Minify/DebugDetector.php @@ -13,6 +13,7 @@ class Minify_DebugDetector if ($env->get('debug') !== null) { return true; } + $cookieValue = $env->cookie('minifyDebug'); if ($cookieValue) { foreach (preg_split('/\\s+/', $cookieValue) as $debugUri) { diff --git a/lib/Minify/Env.php b/lib/Minify/Env.php index d8274e5..25490bc 100644 --- a/lib/Minify/Env.php +++ b/lib/Minify/Env.php @@ -34,6 +34,7 @@ class Minify_Env } else { $this->server['DOCUMENT_ROOT'] = rtrim($this->server['DOCUMENT_ROOT'], '/\\'); } + $this->server['DOCUMENT_ROOT'] = $this->normalizePath($this->server['DOCUMENT_ROOT']); $this->get = $options['get']; $this->post = $options['post']; @@ -46,9 +47,7 @@ class Minify_Env return $this->server; } - return isset($this->server[$key]) - ? $this->server[$key] - : null; + return isset($this->server[$key]) ? $this->server[$key] : null; } public function cookie($key = null, $default = null) @@ -93,6 +92,7 @@ class Minify_Env if ($realpath) { $path = $realpath; } + $path = str_replace('\\', '/', $path); $path = rtrim($path, '/'); if (substr($path, 1, 1) === ':') { @@ -118,11 +118,9 @@ class Minify_Env if (isset($server['SERVER_SOFTWARE']) && 0 !== strpos($server['SERVER_SOFTWARE'], 'Microsoft-IIS/')) { throw new InvalidArgumentException('DOCUMENT_ROOT is not provided and could not be computed'); } - $docRoot = substr( - $server['SCRIPT_FILENAME'] - ,0 - ,strlen($server['SCRIPT_FILENAME']) - strlen($server['SCRIPT_NAME']) - ); + + $substrLength = strlen($server['SCRIPT_FILENAME']) - strlen($server['SCRIPT_NAME']); + $docRoot = substr($server['SCRIPT_FILENAME'], 0, $substrLength); return rtrim($docRoot, '\\'); } diff --git a/lib/Minify/HTML/Helper.php b/lib/Minify/HTML/Helper.php index 498d3c7..bfded8b 100644 --- a/lib/Minify/HTML/Helper.php +++ b/lib/Minify/HTML/Helper.php @@ -99,8 +99,7 @@ class Minify_HTML_Helper foreach ($files as $k => $file) { if (0 === strpos($file, '//')) { $file = substr($file, 2); - } elseif (0 === strpos($file, '/') - || 1 === strpos($file, ':\\')) { + } elseif (0 === strpos($file, '/') || 1 === strpos($file, ':\\')) { $file = substr($file, strlen(self::app()->env->getDocRoot()) + 1); } $file = strtr($file, '\\', '/'); @@ -243,9 +242,7 @@ class Minify_HTML_Helper $base = substr($base, 0, strlen($base) - 1); $bUri = $minRoot . 'b=' . $base . '&f=' . implode(',', $basedPaths); - $uri = strlen($uri) < strlen($bUri) - ? $uri - : $bUri; + $uri = strlen($uri) < strlen($bUri) ? $uri : $bUri; } return $uri; diff --git a/lib/Minify/ImportProcessor.php b/lib/Minify/ImportProcessor.php index 1ed707b..09ec64c 100644 --- a/lib/Minify/ImportProcessor.php +++ b/lib/Minify/ImportProcessor.php @@ -57,8 +57,7 @@ class Minify_ImportProcessor $file = realpath($file); if (! $file || in_array($file, self::$filesIncluded) - || false === ($content = @file_get_contents($file)) - ) { + || false === ($content = @file_get_contents($file))) { // file missing, already included, or failed read return ''; } @@ -73,8 +72,7 @@ class Minify_ImportProcessor $content = str_replace("\r\n", "\n", $content); // process @imports - $content = preg_replace_callback( - '/ + $pattern = '/ @import\\s+ (?:url\\(\\s*)? # maybe url( [\'"]? # maybe quote @@ -83,19 +81,14 @@ class Minify_ImportProcessor (?:\\s*\\))? # maybe ) ([a-zA-Z,\\s]*)? # 2 = media list ; # end token - /x' - ,array($this, '_importCB') - ,$content - ); + /x'; + $content = preg_replace_callback($pattern, array($this, '_importCB'), $content); // You only need to rework the import-path if the script is imported if (self::$_isCss && $is_imported) { // rewrite remaining relative URIs - $content = preg_replace_callback( - '/url\\(\\s*([^\\)\\s]+)\\s*\\)/' - ,array($this, '_urlCB') - ,$content - ); + $pattern = '/url\\(\\s*([^\\)\\s]+)\\s*\\)/'; + $content = preg_replace_callback($pattern, array($this, '_urlCB'), $content); } return $this->_importedContent . $content; @@ -139,12 +132,10 @@ class Minify_ImportProcessor private function _urlCB($m) { // $m[1] is either quoted or not - $quote = ($m[1][0] === "'" || $m[1][0] === '"') - ? $m[1][0] - : ''; - $url = ($quote === '') - ? $m[1] - : substr($m[1], 1, strlen($m[1]) - 2); + $quote = ($m[1][0] === "'" || $m[1][0] === '"') ? $m[1][0] : ''; + + $url = ($quote === '') ? $m[1] : substr($m[1], 1, strlen($m[1]) - 2); + if ('/' !== $url[0]) { if (strpos($url, '//') > 0) { // probably starts with protocol, do not alter @@ -190,8 +181,8 @@ class Minify_ImportProcessor private function truepath($path) { // whether $path is unix or not - $unipath = strlen($path) == 0 || $path{0} - != '/'; + $unipath = (strlen($path) == 0) || ($path{0} != '/'); + // attempts to detect if path is relative in which case, add cwd if (strpos($path, ':') === false && $unipath) { $path = $this->_currentDir . DIRECTORY_SEPARATOR . $path; @@ -211,6 +202,7 @@ class Minify_ImportProcessor $absolutes[] = $part; } } + $path = implode(DIRECTORY_SEPARATOR, $absolutes); // resolve any symlinks if (file_exists($path) && linkinfo($path) > 0) { diff --git a/lib/Minify/Lines.php b/lib/Minify/Lines.php index db85d85..499a9cc 100644 --- a/lib/Minify/Lines.php +++ b/lib/Minify/Lines.php @@ -37,9 +37,7 @@ class Minify_Lines */ public static function minify($content, $options = array()) { - $id = (isset($options['id']) && $options['id']) - ? $options['id'] - : ''; + $id = (isset($options['id']) && $options['id']) ? $options['id'] : ''; $content = str_replace("\r\n", "\n", $content); $lines = explode("\n", $content); @@ -49,6 +47,7 @@ class Minify_Lines $inComment = false; $i = 0; $newLines = array(); + while (null !== ($line = array_shift($lines))) { if (('' !== $id) && (0 == $i % 50)) { if ($inComment) { @@ -57,24 +56,25 @@ class Minify_Lines array_push($newLines, '', "/* {$id} */", ''); } } + ++$i; $newLines[] = self::_addNote($line, $i, $inComment, $padTo); $inComment = self::_eolInComment($line, $inComment); } + $content = implode("\n", $newLines) . "\n"; // check for desired URI rewriting if (isset($options['currentDir'])) { Minify_CSS_UriRewriter::$debugText = ''; - $content = Minify_CSS_UriRewriter::rewrite( - $content - ,$options['currentDir'] - ,isset($options['docRoot']) ? $options['docRoot'] : $_SERVER['DOCUMENT_ROOT'] - ,isset($options['symlinks']) ? $options['symlinks'] : array() - ); + $docRoot = isset($options['docRoot']) ? $options['docRoot'] : $_SERVER['DOCUMENT_ROOT']; + $symlinks = isset($options['symlinks']) ? $options['symlinks'] : array(); + + $content = Minify_CSS_UriRewriter::rewrite($content, $options['currentDir'], $docRoot, $symlinks); + $content = "/* Minify_CSS_UriRewriter::\$debugText\n\n" - . Minify_CSS_UriRewriter::$debugText . "*/\n" - . $content; + . Minify_CSS_UriRewriter::$debugText . "*/\n" + . $content; } return $content; @@ -143,9 +143,11 @@ class Minify_Lines */ private static function _addNote($line, $note, $inComment, $padTo) { - $line = $inComment - ? '/* ' . str_pad($note, $padTo, ' ', STR_PAD_RIGHT) . ' *| ' . $line - : '/* ' . str_pad($note, $padTo, ' ', STR_PAD_RIGHT) . ' */ ' . $line; + if ($inComment) { + $line = '/* ' . str_pad($note, $padTo, ' ', STR_PAD_RIGHT) . ' *| ' . $line; + } else { + $line = '/* ' . str_pad($note, $padTo, ' ', STR_PAD_RIGHT) . ' */ ' . $line; + } return rtrim($line); } diff --git a/lib/Minify/Source.php b/lib/Minify/Source.php index 39597a6..a4fc4d7 100644 --- a/lib/Minify/Source.php +++ b/lib/Minify/Source.php @@ -72,13 +72,13 @@ class Minify_Source implements Minify_SourceInterface $ext = pathinfo($spec['filepath'], PATHINFO_EXTENSION); switch ($ext) { case 'js': $this->contentType = Minify::TYPE_JS; - break; + break; case 'less': // fallthrough case 'css': $this->contentType = Minify::TYPE_CSS; - break; + break; case 'htm': // fallthrough case 'html': $this->contentType = Minify::TYPE_HTML; - break; + break; } $this->filepath = $spec['filepath']; $this->id = $spec['filepath']; @@ -97,9 +97,7 @@ class Minify_Source implements Minify_SourceInterface } else { $this->getContentFunc = $spec['getContentFunc']; } - $this->lastModified = isset($spec['lastModified']) - ? $spec['lastModified'] - : time(); + $this->lastModified = isset($spec['lastModified']) ? $spec['lastModified'] : time(); } if (isset($spec['contentType'])) { $this->contentType = $spec['contentType']; @@ -208,8 +206,8 @@ class Minify_Source implements Minify_SourceInterface { if ($this->filepath && !isset($this->minifyOptions['currentDir']) - && !isset($this->minifyOptions['prependRelativePath']) - ) { + && !isset($this->minifyOptions['prependRelativePath'])) { + $this->minifyOptions['currentDir'] = dirname($this->filepath); } } diff --git a/lib/Minify/YUICompressor.php b/lib/Minify/YUICompressor.php index 1614893..4c3c53b 100644 --- a/lib/Minify/YUICompressor.php +++ b/lib/Minify/YUICompressor.php @@ -93,6 +93,7 @@ class Minify_YUICompressor if (! ($tmpFile = tempnam(self::$tempDir, 'yuic_'))) { throw new Exception('Minify_YUICompressor : could not create temp file in "'.self::$tempDir.'".'); } + file_put_contents($tmpFile, $content); exec(self::_getCmd($options, $type, $tmpFile), $output, $result_code); unlink($tmpFile); @@ -105,22 +106,19 @@ class Minify_YUICompressor private static function _getCmd($userOptions, $type, $tmpFile) { - $o = array_merge( - array( - 'charset' => '' - ,'line-break' => 5000 - ,'type' => $type - ,'nomunge' => false - ,'preserve-semi' => false - ,'disable-optimizations' => false - ,'stack-size' => '' - ) - ,$userOptions + $defaults = array( + 'charset' => '', + 'line-break' => 5000, + 'type' => $type, + 'nomunge' => false, + 'preserve-semi' => false, + 'disable-optimizations' => false, + 'stack-size' => '', ); + $o = array_merge($defaults, $userOptions); + $cmd = self::$javaExecutable - . (!empty($o['stack-size']) - ? ' -Xss' . $o['stack-size'] - : '') + . (!empty($o['stack-size']) ? ' -Xss' . $o['stack-size'] : '') . ' -jar ' . escapeshellarg(self::$jarFile) . " --type {$type}" . (preg_match('/^[\\da-zA-Z0-9\\-]+$/', $o['charset']) From 74042c87adea3f2f0700e896d508635a72ec14ac Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Elan=20Ruusam=C3=A4e?= Date: Mon, 17 Oct 2016 14:22:30 +0300 Subject: [PATCH 17/31] allow .scss via f= param. #549 --- lib/Minify/Controller/MinApp.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/Minify/Controller/MinApp.php b/lib/Minify/Controller/MinApp.php index 7606982..e8440fe 100644 --- a/lib/Minify/Controller/MinApp.php +++ b/lib/Minify/Controller/MinApp.php @@ -102,7 +102,7 @@ class Minify_Controller_MinApp extends Minify_Controller_Base // respond to. // verify at least one file, files are single comma separated, and are all same extension - $validPattern = preg_match('/^[^,]+\\.(css|less|js)(?:,[^,]+\\.\\1)*$/', $get['f'], $m); + $validPattern = preg_match('/^[^,]+\\.(css|less|scss|js)(?:,[^,]+\\.\\1)*$/', $get['f'], $m); $hasComment = strpos($get['f'], '//') !== false; $hasEscape = strpos($get['f'], '\\') !== false; From b31ddbf4c100e4f93616760b9c7e948250a02f61 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Elan=20Ruusam=C3=A4e?= Date: Mon, 17 Oct 2016 15:14:56 +0300 Subject: [PATCH 18/31] add missing .scss to css type map. #549 --- lib/Minify/Source.php | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/Minify/Source.php b/lib/Minify/Source.php index a4fc4d7..1769d6e 100644 --- a/lib/Minify/Source.php +++ b/lib/Minify/Source.php @@ -74,6 +74,7 @@ class Minify_Source implements Minify_SourceInterface case 'js': $this->contentType = Minify::TYPE_JS; break; case 'less': // fallthrough + case 'scss': // fallthrough case 'css': $this->contentType = Minify::TYPE_CSS; break; case 'htm': // fallthrough From b8c79ac8d456fd4a1651977d6672ee47a7f6ebf7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Elan=20Ruusam=C3=A4e?= Date: Wed, 2 Nov 2016 15:53:10 +0200 Subject: [PATCH 19/31] Minify: add details to ContentType mismatch errors --- lib/Minify.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/Minify.php b/lib/Minify.php index c42e60e..7741931 100644 --- a/lib/Minify.php +++ b/lib/Minify.php @@ -720,7 +720,7 @@ class Minify if (!empty($options['contentType'])) { // just verify sources have null content type or match the options if ($sourceType !== null && $sourceType !== $options['contentType']) { - $this->logger && $this->logger->warning('ContentType mismatch'); + $this->logger && $this->logger->warning("ContentType mismatch: '{$sourceType}' != '{$options['contentType']}'"); $this->sources = array(); @@ -733,7 +733,7 @@ class Minify if ($type === null) { $type = $sourceType; } elseif ($sourceType !== $type) { - $this->logger && $this->logger->warning('ContentType mismatch'); + $this->logger && $this->logger->warning("ContentType mismatch: '{$sourceType}' != '{$type}'"); $this->sources = array(); From 8949df33ddf631eec09a1757bbda865b9d64610f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Elan=20Ruusam=C3=A4e?= Date: Tue, 6 Dec 2016 14:46:46 +0200 Subject: [PATCH 20/31] add testcase for js minify that produces $jscomp polyfills with recent closure compiler default input language has changed from ES3 to ES6 produces $jscomp polyfills --- tests/MinifyClosureCompilerTest.php | 12 +++++++++++- tests/TestCase.php | 19 +++++++++++++++++++ tests/_test_files/js/jscomp.polyfill.js | 7 +++++++ tests/_test_files/js/jscomp.polyfill.min.js | 1 + 4 files changed, 38 insertions(+), 1 deletion(-) create mode 100644 tests/_test_files/js/jscomp.polyfill.js create mode 100644 tests/_test_files/js/jscomp.polyfill.min.js diff --git a/tests/MinifyClosureCompilerTest.php b/tests/MinifyClosureCompilerTest.php index ea93eea..13c88d0 100644 --- a/tests/MinifyClosureCompilerTest.php +++ b/tests/MinifyClosureCompilerTest.php @@ -80,12 +80,22 @@ class MinifyClosureCompilerTest extends TestCase { $this->assertHasJar(); - $src = file_get_contents(self::$test_files . '/bug-513.js'); + $src = $this->getDataFile('bug-513.js'); $minExpected = 'var a=4;'; $minOutput = Minify_ClosureCompiler::minify($src); $this->assertSame($minExpected, $minOutput, 'advanced optimizations'); } + public function testOptions() + { + $this->assertHasJar(); + + $src = $this->getDataFile('js/jscomp.polyfill.js'); + $exp = $this->getDataFile('js/jscomp.polyfill.min.js'); + $res = Minify_ClosureCompiler::minify($src); + $this->assertSame($exp, $res); + } + protected function assertHasJar() { $this->assertNotEmpty(Minify_ClosureCompiler::$jarFile); diff --git a/tests/TestCase.php b/tests/TestCase.php index a871461..f763412 100644 --- a/tests/TestCase.php +++ b/tests/TestCase.php @@ -47,4 +47,23 @@ class TestCase extends PHPUnit_Framework_TestCase $this->assertSame($data, $displayed, "$id display"); $this->assertEquals($data, $cache->fetch($id), "$id fetch"); } + + /** + * Read data file, assert that it exists and is not empty. + * As a side effect calls trim() to fight against different Editors that insert or strip final newline. + * + * @param string $filename + * @return string + */ + protected function getDataFile($filename) + { + $path = self::$test_files . '/' . $filename; + $this->assertFileExists($path); + $contents = file_get_contents($path); + $this->assertNotEmpty($contents); + $contents = trim($contents); + $this->assertNotEmpty($contents); + + return $contents; + } } \ No newline at end of file diff --git a/tests/_test_files/js/jscomp.polyfill.js b/tests/_test_files/js/jscomp.polyfill.js new file mode 100644 index 0000000..f1da735 --- /dev/null +++ b/tests/_test_files/js/jscomp.polyfill.js @@ -0,0 +1,7 @@ +(function() { + /** + * @type {string} + */ + var $array = jQuery.find('#div'); + print($array.find('a')); +})(); \ No newline at end of file diff --git a/tests/_test_files/js/jscomp.polyfill.min.js b/tests/_test_files/js/jscomp.polyfill.min.js new file mode 100644 index 0000000..6146151 --- /dev/null +++ b/tests/_test_files/js/jscomp.polyfill.min.js @@ -0,0 +1 @@ +(function(){var a=jQuery.find("#div");print(a.find("a"))})(); \ No newline at end of file From 6a330d9091a16ca62fcd38a70e6e64bceccb3314 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Elan=20Ruusam=C3=A4e?= Date: Tue, 6 Dec 2016 16:59:36 +0200 Subject: [PATCH 21/31] pass any option to closure compiler --- lib/Minify/ClosureCompiler.php | 40 ++++++++++++----------------- tests/MinifyClosureCompilerTest.php | 2 +- 2 files changed, 18 insertions(+), 24 deletions(-) diff --git a/lib/Minify/ClosureCompiler.php b/lib/Minify/ClosureCompiler.php index 487cafe..26cbc67 100644 --- a/lib/Minify/ClosureCompiler.php +++ b/lib/Minify/ClosureCompiler.php @@ -24,19 +24,12 @@ * * * - * @todo unit tests, $options docs - * @todo more options support (or should just passthru them all?) - * * @package Minify * @author Stephen Clay * @author Elan Ruusamäe */ class Minify_ClosureCompiler { - const OPTION_CHARSET = 'charset'; - const OPTION_COMPILATION_LEVEL = 'compilation_level'; - const OPTION_WARNING_LEVEL = 'warning_level'; - public static $isDebug = false; /** @@ -61,6 +54,17 @@ class Minify_ClosureCompiler */ public static $javaExecutable = 'java'; + /** + * Default command line options passed to closure-compiler + * + * @var array + */ + public static $defaultOptions = array( + 'charset' => 'utf-8', + 'compilation_level' => 'SIMPLE_OPTIMIZATIONS', + 'warning_level' => 'QUIET', + ); + /** * Minify a Javascript string * @@ -137,7 +141,8 @@ class Minify_ClosureCompiler $this->checkJar(self::$jarFile); $server = array( self::$javaExecutable, - '-jar', escapeshellarg(self::$jarFile) + '-jar', + escapeshellarg(self::$jarFile) ); return $server; @@ -151,24 +156,13 @@ class Minify_ClosureCompiler { $args = array(); - $o = array_merge( - array( - self::OPTION_CHARSET => 'utf-8', - self::OPTION_COMPILATION_LEVEL => 'SIMPLE_OPTIMIZATIONS', - self::OPTION_WARNING_LEVEL => 'QUIET', - ), + $options = array_merge( + static::$defaultOptions, $userOptions ); - $charsetOption = $o[self::OPTION_CHARSET]; - if (preg_match('/^[\\da-zA-Z0-9\\-]+$/', $charsetOption)) { - $args[] = "--charset {$charsetOption}"; - } - - foreach (array(self::OPTION_COMPILATION_LEVEL, self::OPTION_WARNING_LEVEL) as $opt) { - if ($o[$opt]) { - $args[] = "--{$opt} " . escapeshellarg($o[$opt]); - } + foreach ($options as $key => $value) { + $args[] = "--{$key} " . escapeshellarg($value); } return $args; diff --git a/tests/MinifyClosureCompilerTest.php b/tests/MinifyClosureCompilerTest.php index 13c88d0..15a1d5f 100644 --- a/tests/MinifyClosureCompilerTest.php +++ b/tests/MinifyClosureCompilerTest.php @@ -63,7 +63,7 @@ class MinifyClosureCompilerTest extends TestCase $src = "function unused() {};"; $minExpected = ''; $options = array( - Minify_ClosureCompiler::OPTION_COMPILATION_LEVEL => 'ADVANCED_OPTIMIZATIONS' + 'compilation_level' => 'ADVANCED_OPTIMIZATIONS' ); $minOutput = Minify_ClosureCompiler::minify($src, $options); $this->assertSame($minExpected, $minOutput, 'advanced optimizations'); From 8fe915f4864674e90f20343452c63c9bfdafdd7e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Elan=20Ruusam=C3=A4e?= Date: Tue, 6 Dec 2016 17:00:58 +0200 Subject: [PATCH 22/31] test $jscomp polyfill output --- tests/MinifyClosureCompilerTest.php | 18 ++++++++++++++++-- tests/_test_files/js/jscomp.polyfilled.min.js | 3 +++ 2 files changed, 19 insertions(+), 2 deletions(-) create mode 100644 tests/_test_files/js/jscomp.polyfilled.min.js diff --git a/tests/MinifyClosureCompilerTest.php b/tests/MinifyClosureCompilerTest.php index 15a1d5f..84dc1e3 100644 --- a/tests/MinifyClosureCompilerTest.php +++ b/tests/MinifyClosureCompilerTest.php @@ -86,13 +86,27 @@ class MinifyClosureCompilerTest extends TestCase $this->assertSame($minExpected, $minOutput, 'advanced optimizations'); } - public function testOptions() + /** + * Test that language_in parameter has effect. + */ + public function testLanguageOptions() { $this->assertHasJar(); $src = $this->getDataFile('js/jscomp.polyfill.js'); $exp = $this->getDataFile('js/jscomp.polyfill.min.js'); - $res = Minify_ClosureCompiler::minify($src); + $options = array( + 'language_in' => 'ECMASCRIPT3', + ); + + $res = Minify_ClosureCompiler::minify($src, $options); + $this->assertSame($exp, $res); + + $options = array( + 'language_in' => 'ECMASCRIPT6', + ); + $exp = $this->getDataFile('js/jscomp.polyfilled.min.js'); + $res = Minify_ClosureCompiler::minify($src, $options); $this->assertSame($exp, $res); } diff --git a/tests/_test_files/js/jscomp.polyfilled.min.js b/tests/_test_files/js/jscomp.polyfilled.min.js new file mode 100644 index 0000000..faa4d04 --- /dev/null +++ b/tests/_test_files/js/jscomp.polyfilled.min.js @@ -0,0 +1,3 @@ +var $jscomp={scope:{},findInternal:function(a,c,b){a instanceof String&&(a=String(a));for(var d=a.length,e=0;e Date: Tue, 6 Dec 2016 17:02:26 +0200 Subject: [PATCH 23/31] remove var_dump debug from test output --- tests/LessSourceTest.php | 2 -- tests/ScssSourceTest.php | 2 -- 2 files changed, 4 deletions(-) diff --git a/tests/LessSourceTest.php b/tests/LessSourceTest.php index f61045c..a2b5158 100644 --- a/tests/LessSourceTest.php +++ b/tests/LessSourceTest.php @@ -24,9 +24,7 @@ class LessSourceTest extends TestCase touch($includedLess); $mtime1 = filemtime($mainLess); - var_dump($mtime1); $mtime2 = filemtime($includedLess); - var_dump($mtime2); $max = max($mtime1, $mtime2); diff --git a/tests/ScssSourceTest.php b/tests/ScssSourceTest.php index a1581ef..c37ca36 100644 --- a/tests/ScssSourceTest.php +++ b/tests/ScssSourceTest.php @@ -24,9 +24,7 @@ class ScssSourceTest extends TestCase touch($includedLess); $mtime1 = filemtime($mainLess); - var_dump($mtime1); $mtime2 = filemtime($includedLess); - var_dump($mtime2); $max = max($mtime1, $mtime2); From 005dc26e2226f59a59eb4be402f554cd95bf3d1f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Elan=20Ruusam=C3=A4e?= Date: Tue, 6 Dec 2016 17:04:34 +0200 Subject: [PATCH 24/31] tests: skip rather than fail if nailgun.jar is missing --- tests/MinifyNailgunClosureCompilerTest.php | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/tests/MinifyNailgunClosureCompilerTest.php b/tests/MinifyNailgunClosureCompilerTest.php index caeeb70..572ed5f 100644 --- a/tests/MinifyNailgunClosureCompilerTest.php +++ b/tests/MinifyNailgunClosureCompilerTest.php @@ -20,7 +20,7 @@ class MinifyNailgunClosureCompilerTest extends TestCase /** * Test minimisation with the minimum necessary settings */ - public function test2() + public function test1() { $this->assertHasJar(); $src = " @@ -40,8 +40,10 @@ class MinifyNailgunClosureCompilerTest extends TestCase protected function assertHasJar() { $this->assertNotEmpty(Minify_ClosureCompiler::$jarFile); + $this->assertNotEmpty(Minify_NailgunClosureCompiler::$ngJarFile); try { $this->assertFileExists(Minify_ClosureCompiler::$jarFile, "Have closure compiler compiler.jar"); + $this->assertFileExists(Minify_NailgunClosureCompiler::$ngJarFile, "Have nailgun.jar"); } catch (Exception $e) { $this->markTestSkipped($e->getMessage()); } From 56d55abc013950abb2d05c303ecd44ac6600774c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Elan=20Ruusam=C3=A4e?= Date: Tue, 6 Dec 2016 17:08:58 +0200 Subject: [PATCH 25/31] travis: install closure compiler --- .gitignore | 1 + .travis.yml | 6 ++++++ 2 files changed, 7 insertions(+) diff --git a/.gitignore b/.gitignore index ca2c1a9..f3f3bdf 100644 --- a/.gitignore +++ b/.gitignore @@ -8,3 +8,4 @@ /composer.lock /vendor /.php_cs.cache +/tests/compiler.jar diff --git a/.travis.yml b/.travis.yml index e1a2519..06b5093 100644 --- a/.travis.yml +++ b/.travis.yml @@ -25,6 +25,12 @@ cache: install: - composer update --no-interaction --prefer-source +before_script: + - wget -c https://dl.google.com/closure-compiler/compiler-latest.zip -O vendor/compiler-latest.zip + - unzip -fd vendor/closure-compiler vendor/compiler-latest.zip + - ln -sfn ../$(echo vendor/closure-compiler/closure-compiler-*.jar) tests/compiler.jar + - java -jar tests/compiler.jar --version + script: - composer validate - phpunit From 6fc0648a0d3ca1648c7af946425152d95ac5633c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Elan=20Ruusam=C3=A4e?= Date: Tue, 6 Dec 2016 17:16:37 +0200 Subject: [PATCH 26/31] phpunit: verbose output of run summary --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 06b5093..359e8e2 100644 --- a/.travis.yml +++ b/.travis.yml @@ -33,6 +33,6 @@ before_script: script: - composer validate - - phpunit + - phpunit --verbose # vim:ts=2:sw=2:et From 625bc5ac0ac501cd1d33107a436c0014d3cd0e94 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Elan=20Ruusam=C3=A4e?= Date: Tue, 6 Dec 2016 20:38:17 +0200 Subject: [PATCH 27/31] fix unzip overwrite. refs 56d55ab --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 359e8e2..2659d19 100644 --- a/.travis.yml +++ b/.travis.yml @@ -27,7 +27,7 @@ install: before_script: - wget -c https://dl.google.com/closure-compiler/compiler-latest.zip -O vendor/compiler-latest.zip - - unzip -fd vendor/closure-compiler vendor/compiler-latest.zip + - unzip -od vendor/closure-compiler vendor/compiler-latest.zip - ln -sfn ../$(echo vendor/closure-compiler/closure-compiler-*.jar) tests/compiler.jar - java -jar tests/compiler.jar --version From 1936c946e84bddf17d3f038c4ac8d00accb1f1bf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Elan=20Ruusam=C3=A4e?= Date: Thu, 8 Dec 2016 16:12:37 +0200 Subject: [PATCH 28/31] firephp/firephp-core is optional dependency --- composer.json | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/composer.json b/composer.json index 478bb6b..d0a35f7 100644 --- a/composer.json +++ b/composer.json @@ -23,16 +23,16 @@ "classmap": ["tests/TestCase.php"] }, "require": { - "php": ">=5.3.0", "ext-pcre": "*", - "firephp/firephp-core": "~0.4.0", "intervention/httpauth": "~2.0", "monolog/monolog": "~1.1", "mrclay/jsmin-php": "~2", "mrclay/props-dic": "^2.2", + "php": "^5.3.0 || ^7.0", "tubalmartin/cssmin": "~2.4.8" }, "require-dev": { + "firephp/firephp-core": "~0.4.0", "leafo/lessphp": "~0.4.0", "leafo/scssphp": "^0.3.0", "meenie/javascript-packer": "~1.1", @@ -40,6 +40,7 @@ "tedivm/jshrink": "~1.1.0" }, "suggest": { + "firephp/firephp-core": "Use FirePHP for Log messages", "leafo/lessphp": "LESS support", "meenie/javascript-packer": "Keep track of the Packer PHP port using Composer" }, From 94436b214de4b82e87a43562c2e41c6d237c4e29 Mon Sep 17 00:00:00 2001 From: Michael Wasson Date: Thu, 22 Dec 2016 08:43:05 -0500 Subject: [PATCH 29/31] correct typo - CSS -> JS --- docs/UserGuide.wiki.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/UserGuide.wiki.md b/docs/UserGuide.wiki.md index a572894..6e37e96 100644 --- a/docs/UserGuide.wiki.md +++ b/docs/UserGuide.wiki.md @@ -10,7 +10,7 @@ In other words, the "f" argument is set to the file path from root without the i To combine multiple files, separate the paths given to "f" with commas. -Let's say you have CSS files at these URLs: +Let's say you have JS files at these URLs: * http://example.com/scripts/library-1.5.js * http://example.com/scripts/site.js From 12b9096b23587720f015fa61b8a65de2cf1ba656 Mon Sep 17 00:00:00 2001 From: Steve Clay Date: Wed, 18 Jan 2017 18:48:15 -0500 Subject: [PATCH 30/31] URI rewriter passes through empty URLs Fixes #561 --- lib/Minify/CSS/UriRewriter.php | 5 +++++ tests/_test_files/css_uriRewriter/exp.css | 2 ++ tests/_test_files/css_uriRewriter/exp_prepend.css | 2 ++ tests/_test_files/css_uriRewriter/exp_prepend2.css | 2 ++ tests/_test_files/css_uriRewriter/in.css | 2 ++ 5 files changed, 13 insertions(+) diff --git a/lib/Minify/CSS/UriRewriter.php b/lib/Minify/CSS/UriRewriter.php index 248875c..acd1a2c 100644 --- a/lib/Minify/CSS/UriRewriter.php +++ b/lib/Minify/CSS/UriRewriter.php @@ -294,6 +294,11 @@ class Minify_CSS_UriRewriter $uri = ($quoteChar === '') ? $m[1] : substr($m[1], 1, strlen($m[1]) - 2); } + + if ($uri === '') { + return $m[0]; + } + // if not root/scheme relative and not starts with scheme if (!preg_match('~^(/|[a-z]+\:)~', $uri)) { // URI is file-relative: rewrite depending on options diff --git a/tests/_test_files/css_uriRewriter/exp.css b/tests/_test_files/css_uriRewriter/exp.css index 3296c26..5ce7667 100644 --- a/tests/_test_files/css_uriRewriter/exp.css +++ b/tests/_test_files/css_uriRewriter/exp.css @@ -8,6 +8,7 @@ @import url("/css/foo.css"); /* abs, should not alter */ @import url(/css2/foo.css); /* abs, should not alter */ @import url(foo:bar); /* scheme, should not alter */ +@import url(); /* empty, should not alter */ foo {clip-path:url(#c1)} /* inline clip path, should not alter */ foo {clip-path:url(/_test_files/css_uriRewriter/foo.svg#c1)} foo {mask: url(#c1)} /* should not alter */ @@ -17,5 +18,6 @@ foo {background:url('http://foo.com/css/foo.css');} /* scheme, should not alter foo {background:url("//foo.com/css/foo.css");} /* protocol relative, should not alter */ foo {background:url(foo:bar);} /* scheme, should not alter */ foo {background:url("/_test_files/css_uriRewriter/foo bar.jpg");} +foo {background:url("");} /* empty, should not alter */ @import url('/_test_files/css_uriRewriter/foo bar.css'); @import "/_test_files/css_uriRewriter/foo bar.css"; diff --git a/tests/_test_files/css_uriRewriter/exp_prepend.css b/tests/_test_files/css_uriRewriter/exp_prepend.css index bc09c44..a56103d 100644 --- a/tests/_test_files/css_uriRewriter/exp_prepend.css +++ b/tests/_test_files/css_uriRewriter/exp_prepend.css @@ -8,6 +8,7 @@ @import url("/css/foo.css"); /* abs, should not alter */ @import url(/css2/foo.css); /* abs, should not alter */ @import url(foo:bar); /* scheme, should not alter */ +@import url(); /* empty, should not alter */ foo {clip-path:url(#c1)} /* inline clip path, should not alter */ foo {clip-path:url(http://cnd.com/A/B/foo.svg#c1)} foo {mask: url(#c1)} /* should not alter */ @@ -17,5 +18,6 @@ foo {background:url('http://foo.com/css/foo.css');} /* scheme, should not alter foo {background:url("//foo.com/css/foo.css");} /* protocol relative, should not alter */ foo {background:url(foo:bar);} /* scheme, should not alter */ foo {background:url("http://cnd.com/A/B/foo bar.jpg");} +foo {background:url("");} /* empty, should not alter */ @import url('http://cnd.com/A/B/foo bar.css'); @import "http://cnd.com/A/B/foo bar.css"; diff --git a/tests/_test_files/css_uriRewriter/exp_prepend2.css b/tests/_test_files/css_uriRewriter/exp_prepend2.css index c8f7c61..f9398a5 100644 --- a/tests/_test_files/css_uriRewriter/exp_prepend2.css +++ b/tests/_test_files/css_uriRewriter/exp_prepend2.css @@ -8,6 +8,7 @@ @import url("/css/foo.css"); /* abs, should not alter */ @import url(/css2/foo.css); /* abs, should not alter */ @import url(foo:bar); /* scheme, should not alter */ +@import url(); /* empty, should not alter */ foo {clip-path:url(#c1)} /* inline clip path, should not alter */ foo {clip-path:url(//cnd.com/A/B/foo.svg#c1)} foo {mask: url(#c1)} /* should not alter */ @@ -17,5 +18,6 @@ foo {background:url('http://foo.com/css/foo.css');} /* scheme, should not alter foo {background:url("//foo.com/css/foo.css");} /* protocol relative, should not alter */ foo {background:url(foo:bar);} /* scheme, should not alter */ foo {background:url("//cnd.com/A/B/foo bar.jpg");} +foo {background:url("");} /* empty, should not alter */ @import url('//cnd.com/A/B/foo bar.css'); @import "//cnd.com/A/B/foo bar.css"; diff --git a/tests/_test_files/css_uriRewriter/in.css b/tests/_test_files/css_uriRewriter/in.css index 0200450..e5c4858 100644 --- a/tests/_test_files/css_uriRewriter/in.css +++ b/tests/_test_files/css_uriRewriter/in.css @@ -8,6 +8,7 @@ @import url("/css/foo.css"); /* abs, should not alter */ @import url(/css2/foo.css); /* abs, should not alter */ @import url(foo:bar); /* scheme, should not alter */ +@import url(); /* empty, should not alter */ foo {clip-path:url(#c1)} /* inline clip path, should not alter */ foo {clip-path:url(foo.svg#c1)} foo {mask: url( #c1 )} /* should not alter */ @@ -17,5 +18,6 @@ foo {background:url('http://foo.com/css/foo.css');} /* scheme, should not alter foo {background:url("//foo.com/css/foo.css");} /* protocol relative, should not alter */ foo {background:url(foo:bar);} /* scheme, should not alter */ foo {background:url("foo bar.jpg");} +foo {background:url("");} /* empty, should not alter */ @import url('foo bar.css'); @import "foo bar.css"; From ddf3a4e57f1172428664ae0c26a2b821e6a5d737 Mon Sep 17 00:00:00 2001 From: Steve Clay Date: Wed, 18 Jan 2017 18:39:15 -0500 Subject: [PATCH 31/31] Require later SCSS PHP for tests No longer test PHP 5.3 --- .travis.yml | 1 - composer.json | 2 +- tests/ScssSourceTest.php | 4 ++++ 3 files changed, 5 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index 2659d19..0ef27a3 100644 --- a/.travis.yml +++ b/.travis.yml @@ -6,7 +6,6 @@ php: - 5.6 - 5.5 - 5.4 - - 5.3 - hhvm matrix: diff --git a/composer.json b/composer.json index d0a35f7..84128f8 100644 --- a/composer.json +++ b/composer.json @@ -34,7 +34,7 @@ "require-dev": { "firephp/firephp-core": "~0.4.0", "leafo/lessphp": "~0.4.0", - "leafo/scssphp": "^0.3.0", + "leafo/scssphp": "~0.6.6", "meenie/javascript-packer": "~1.1", "phpunit/phpunit": "4.8.*", "tedivm/jshrink": "~1.1.0" diff --git a/tests/ScssSourceTest.php b/tests/ScssSourceTest.php index c37ca36..a8123dd 100644 --- a/tests/ScssSourceTest.php +++ b/tests/ScssSourceTest.php @@ -4,6 +4,10 @@ class ScssSourceTest extends TestCase { public function setUp() { + if (version_compare(PHP_VERSION, '5.4.0', '<')) { + $this->markTestSkipped('scssphp is not compatible with this PHP version.'); + } + $this->realDocRoot = $_SERVER['DOCUMENT_ROOT']; $_SERVER['DOCUMENT_ROOT'] = self::$document_root; }