From ce6b73c88a2d538114cd0641be7f28aab1db31c0 Mon Sep 17 00:00:00 2001 From: Klimov Paul Date: Sun, 26 May 2013 14:53:41 +0300 Subject: [PATCH 1/6] Method "AssetController::adjustCssUrl()" has been created as blank --- .../yii/console/controllers/AssetController.php | 17 +++++++ .../console/controllers/AssetControllerTest.php | 54 ++++++++++++++++++++++ 2 files changed, 71 insertions(+) diff --git a/framework/yii/console/controllers/AssetController.php b/framework/yii/console/controllers/AssetController.php index ca7896c..852b892 100644 --- a/framework/yii/console/controllers/AssetController.php +++ b/framework/yii/console/controllers/AssetController.php @@ -528,6 +528,23 @@ EOD } /** + * Adjusts CSS content allowing URL references pointing to the original resources. + * @param string $cssContent source CSS content. + * @param string $inputFilePath input CSS file name. + * @param string $outputFilePath output CSS file name. + * @return string adjusted CSS content. + */ + protected function adjustCssUrl($cssContent, $inputFilePath, $outputFilePath) + { + $callback = function($matches) use ($inputFilePath, $outputFilePath) { + return $matches[0]; + }; + $cssContent = preg_replace_callback('/[\w\-]:\s*url\("(.*)"\)+/is', $callback, $cssContent); + + return $cssContent; + } + + /** * Creates template of configuration file for [[actionCompress]]. * @param string $configFile output file name. */ diff --git a/tests/unit/framework/console/controllers/AssetControllerTest.php b/tests/unit/framework/console/controllers/AssetControllerTest.php index d792c9e..4983568 100644 --- a/tests/unit/framework/console/controllers/AssetControllerTest.php +++ b/tests/unit/framework/console/controllers/AssetControllerTest.php @@ -169,6 +169,23 @@ class AssetControllerTest extends TestCase } } + /** + * Invokes the asset controller method even if it is protected. + * @param string $methodName name of the method to be invoked. + * @param array $args method arguments. + * @return mixed method invoke result. + */ + protected function invokeAssetControllerMethod($methodName, array $args = array()) + { + $controller = $this->createAssetController(); + $controllerClassReflection = new ReflectionClass(get_class($controller)); + $methodReflection = $controllerClassReflection->getMethod($methodName); + $methodReflection->setAccessible(true); + $result = $methodReflection->invokeArgs($controller, $args); + $methodReflection->setAccessible(false); + return $result; + } + // Tests : public function testActionTemplate() @@ -237,4 +254,41 @@ class AssetControllerTest extends TestCase $this->assertContains($content, $compressedJsFileContent, "Source of '{$name}' is missing in combined file!"); } } + + /** + * Data provider for [[testAdjustCssUrl()]]. + * @return array test data. + */ + public function adjustCssUrlDataProvider() + { + return array( + array( + '.test-class {background-image: url("test.png");}', + '/test/base/path/assets/input', + '/test/base/path/assets/output', + '.test-class {background-image: url("../input/test.png");}', + ), + array( + '.test-class {background-image: url("../img/test.png");}', + '/test/base/path/assets/input', + '/test/base/path/assets/output', + '.test-class {background-image: url("../input/img/test.png");}', + ), + ); + } + + /** + * @dataProvider adjustCssUrlDataProvider + * + * @param $cssContent + * @param $inputFilePath + * @param $outputFilePath + * @param $expectedCssContent + */ + public function testAdjustCssUrl($cssContent, $inputFilePath, $outputFilePath, $expectedCssContent) + { + $adjustedCssContent = $this->invokeAssetControllerMethod('adjustCssUrl', array($cssContent, $inputFilePath, $outputFilePath)); + + $this->assertEquals($expectedCssContent, $adjustedCssContent, 'Unable to adjust CSS correctly!'); + } } From fbc8e265ad81b6b6542aa7b93c189210c1d2cdb7 Mon Sep 17 00:00:00 2001 From: Klimov Paul Date: Sun, 26 May 2013 18:55:12 +0300 Subject: [PATCH 2/6] Method "AssetController::adjustCssUrl()" has been implemented in basic. --- .../yii/console/controllers/AssetController.php | 27 +++++++++++++++++++--- 1 file changed, 24 insertions(+), 3 deletions(-) diff --git a/framework/yii/console/controllers/AssetController.php b/framework/yii/console/controllers/AssetController.php index 852b892..71709e8 100644 --- a/framework/yii/console/controllers/AssetController.php +++ b/framework/yii/console/controllers/AssetController.php @@ -536,10 +536,31 @@ EOD */ protected function adjustCssUrl($cssContent, $inputFilePath, $outputFilePath) { - $callback = function($matches) use ($inputFilePath, $outputFilePath) { - return $matches[0]; + $sharedPath = ''; + for ($i = 0; $i < strlen($inputFilePath); $i++) { + if (!isset($outputFilePath[$i])) { + break; + } + if ($inputFilePath[$i] == $outputFilePath[$i]) { + $sharedPath .= $inputFilePath[$i]; + } + } + $inputFileRelativePath = trim(str_replace($sharedPath, '', $inputFilePath), '/'); + $outputFileRelativePath = trim(str_replace($sharedPath, '', $outputFilePath), '/'); + $inputFileRelativePathParts = explode('/', $inputFileRelativePath); + $outputFileRelativePathParts = explode('/', $outputFileRelativePath); + + $callback = function($matches) use ($inputFileRelativePathParts, $outputFileRelativePathParts) { + $fullMatch = $matches[0]; + $inputUrl = $matches[1]; + + $urlPrefix = str_repeat('../', count($outputFileRelativePathParts)); + $urlPrefix .= implode('/', $inputFileRelativePathParts); + + $outputUrl = $urlPrefix . '/' . $inputUrl; + return str_replace($inputUrl, $outputUrl, $fullMatch); }; - $cssContent = preg_replace_callback('/[\w\-]:\s*url\("(.*)"\)+/is', $callback, $cssContent); + $cssContent = preg_replace_callback('/[\w\-]:\s*url\("([^"]*)"\)+/is', $callback, $cssContent); return $cssContent; } From 265a6f1c39653ed8ceb743296b5023cf496fb68e Mon Sep 17 00:00:00 2001 From: Klimov Paul Date: Sun, 26 May 2013 20:47:34 +0300 Subject: [PATCH 3/6] Relative path composing at "AssetController::adjustCssUrl()" has been complete. --- .../yii/console/controllers/AssetController.php | 37 ++++++++++++++++------ .../console/controllers/AssetControllerTest.php | 20 +++++++++--- 2 files changed, 44 insertions(+), 13 deletions(-) diff --git a/framework/yii/console/controllers/AssetController.php b/framework/yii/console/controllers/AssetController.php index 71709e8..249938f 100644 --- a/framework/yii/console/controllers/AssetController.php +++ b/framework/yii/console/controllers/AssetController.php @@ -536,15 +536,20 @@ EOD */ protected function adjustCssUrl($cssContent, $inputFilePath, $outputFilePath) { - $sharedPath = ''; - for ($i = 0; $i < strlen($inputFilePath); $i++) { - if (!isset($outputFilePath[$i])) { + $sharedPathParts = array(); + $inputFilePathParts = explode('/', $inputFilePath); + $inputFilePathPartsCount = count($inputFilePathParts); + $outputFilePathParts = explode('/', $outputFilePath); + $outputFilePathPartsCount = count($outputFilePathParts); + for ($i =0; $i < $inputFilePathPartsCount && $i < $outputFilePathPartsCount; $i++) { + if ($inputFilePathParts[$i] == $outputFilePathParts[$i]) { + $sharedPathParts[] = $inputFilePathParts[$i]; + } else { break; } - if ($inputFilePath[$i] == $outputFilePath[$i]) { - $sharedPath .= $inputFilePath[$i]; - } } + $sharedPath = implode('/', $sharedPathParts); + $inputFileRelativePath = trim(str_replace($sharedPath, '', $inputFilePath), '/'); $outputFileRelativePath = trim(str_replace($sharedPath, '', $outputFilePath), '/'); $inputFileRelativePathParts = explode('/', $inputFileRelativePath); @@ -554,12 +559,26 @@ EOD $fullMatch = $matches[0]; $inputUrl = $matches[1]; - $urlPrefix = str_repeat('../', count($outputFileRelativePathParts)); - $urlPrefix .= implode('/', $inputFileRelativePathParts); + $outputUrlParts = array_fill(0, count($outputFileRelativePathParts), '..'); + $outputUrlParts = array_merge($outputUrlParts, $inputFileRelativePathParts); + + if (strpos($inputUrl, '/') !== false) { + $inputUrlParts = explode('/', $inputUrl); + foreach ($inputUrlParts as $key => $inputUrlPart) { + if ($inputUrlPart == '..') { + array_pop($outputUrlParts); + unset($inputUrlParts[$key]); + } + } + $outputUrlParts[] = implode('/', $inputUrlParts); + } else { + $outputUrlParts[] = $inputUrl; + } + $outputUrl = implode('/', $outputUrlParts); - $outputUrl = $urlPrefix . '/' . $inputUrl; return str_replace($inputUrl, $outputUrl, $fullMatch); }; + $cssContent = preg_replace_callback('/[\w\-]:\s*url\("([^"]*)"\)+/is', $callback, $cssContent); return $cssContent; diff --git a/tests/unit/framework/console/controllers/AssetControllerTest.php b/tests/unit/framework/console/controllers/AssetControllerTest.php index 4983568..4f25fe6 100644 --- a/tests/unit/framework/console/controllers/AssetControllerTest.php +++ b/tests/unit/framework/console/controllers/AssetControllerTest.php @@ -263,16 +263,28 @@ class AssetControllerTest extends TestCase { return array( array( - '.test-class {background-image: url("test.png");}', + '.published-same-dir-class {background-image: url("published_same_dir.png");}', '/test/base/path/assets/input', '/test/base/path/assets/output', - '.test-class {background-image: url("../input/test.png");}', + '.published-same-dir-class {background-image: url("../input/published_same_dir.png");}', ), array( - '.test-class {background-image: url("../img/test.png");}', + '.published-relative-dir-class {background-image: url("../img/published_relative_dir.png");}', '/test/base/path/assets/input', '/test/base/path/assets/output', - '.test-class {background-image: url("../input/img/test.png");}', + '.published-relative-dir-class {background-image: url("../img/published_relative_dir.png");}', + ), + array( + '.static-same-dir-class {background-image: url("static_same_dir.png");}', + '/test/base/path/css', + '/test/base/path/assets/output', + '.static-same-dir-class {background-image: url("../../css/static_same_dir.png");}', + ), + array( + '.static-relative-dir-class {background-image: url("../img/static_relative_dir.png");}', + '/test/base/path/css', + '/test/base/path/assets/output', + '.static-relative-dir-class {background-image: url("../../img/static_relative_dir.png");}', ), ); } From b6ec6085fe84a218ae101609a02b93cbdd76eb19 Mon Sep 17 00:00:00 2001 From: Klimov Paul Date: Sun, 26 May 2013 20:59:03 +0300 Subject: [PATCH 4/6] Method "AssetController::adjustCssUrl()" has been complete. --- framework/yii/console/controllers/AssetController.php | 2 +- .../framework/console/controllers/AssetControllerTest.php | 12 ++++++------ 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/framework/yii/console/controllers/AssetController.php b/framework/yii/console/controllers/AssetController.php index 249938f..1bd8e10 100644 --- a/framework/yii/console/controllers/AssetController.php +++ b/framework/yii/console/controllers/AssetController.php @@ -579,7 +579,7 @@ EOD return str_replace($inputUrl, $outputUrl, $fullMatch); }; - $cssContent = preg_replace_callback('/[\w\-]:\s*url\("([^"]*)"\)+/is', $callback, $cssContent); + $cssContent = preg_replace_callback('/url\(["\']?([^"]*)["\']?\)/is', $callback, $cssContent); return $cssContent; } diff --git a/tests/unit/framework/console/controllers/AssetControllerTest.php b/tests/unit/framework/console/controllers/AssetControllerTest.php index 4f25fe6..a76a942 100644 --- a/tests/unit/framework/console/controllers/AssetControllerTest.php +++ b/tests/unit/framework/console/controllers/AssetControllerTest.php @@ -263,22 +263,22 @@ class AssetControllerTest extends TestCase { return array( array( - '.published-same-dir-class {background-image: url("published_same_dir.png");}', + '.published-same-dir-class {background-image: url(published_same_dir.png);}', '/test/base/path/assets/input', '/test/base/path/assets/output', - '.published-same-dir-class {background-image: url("../input/published_same_dir.png");}', + '.published-same-dir-class {background-image: url(../input/published_same_dir.png);}', ), array( - '.published-relative-dir-class {background-image: url("../img/published_relative_dir.png");}', + '.published-relative-dir-class {background-image: url(../img/published_relative_dir.png);}', '/test/base/path/assets/input', '/test/base/path/assets/output', - '.published-relative-dir-class {background-image: url("../img/published_relative_dir.png");}', + '.published-relative-dir-class {background-image: url(../img/published_relative_dir.png);}', ), array( - '.static-same-dir-class {background-image: url("static_same_dir.png");}', + '.static-same-dir-class {background-image: url(\'static_same_dir.png\');}', '/test/base/path/css', '/test/base/path/assets/output', - '.static-same-dir-class {background-image: url("../../css/static_same_dir.png");}', + '.static-same-dir-class {background-image: url(\'../../css/static_same_dir.png\');}', ), array( '.static-relative-dir-class {background-image: url("../img/static_relative_dir.png");}', From 2635b4775efaf514ee1e7ace7071ae6c29f596ec Mon Sep 17 00:00:00 2001 From: Klimov Paul Date: Sun, 26 May 2013 21:01:18 +0300 Subject: [PATCH 5/6] Method "AssetController::adjustCssUrl()" has been applied to compress process. --- framework/yii/console/controllers/AssetController.php | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/framework/yii/console/controllers/AssetController.php b/framework/yii/console/controllers/AssetController.php index 1bd8e10..98c67a5 100644 --- a/framework/yii/console/controllers/AssetController.php +++ b/framework/yii/console/controllers/AssetController.php @@ -517,11 +517,10 @@ EOD */ public function combineCssFiles($inputFiles, $outputFile) { - // todo: adjust url() references in CSS files $content = ''; foreach ($inputFiles as $file) { $content .= "/*** BEGIN FILE: $file ***/\n" - . file_get_contents($file) + . $this->adjustCssUrl(file_get_contents($file), dirname($file), dirname($outputFile)) . "/*** END FILE: $file ***/\n"; } file_put_contents($outputFile, $content); From f65d1398a55094578f8dadfdfe4ce46c2ccfdb22 Mon Sep 17 00:00:00 2001 From: Klimov Paul Date: Sun, 26 May 2013 21:05:53 +0300 Subject: [PATCH 6/6] Added skipping for absolute URLs at "AssetController::adjustCssUrl()". --- framework/yii/console/controllers/AssetController.php | 4 ++++ .../framework/console/controllers/AssetControllerTest.php | 12 ++++++++++++ 2 files changed, 16 insertions(+) diff --git a/framework/yii/console/controllers/AssetController.php b/framework/yii/console/controllers/AssetController.php index 98c67a5..8e3de29 100644 --- a/framework/yii/console/controllers/AssetController.php +++ b/framework/yii/console/controllers/AssetController.php @@ -558,6 +558,10 @@ EOD $fullMatch = $matches[0]; $inputUrl = $matches[1]; + if (preg_match('/https?:\/\//is', $inputUrl)) { + return $fullMatch; + } + $outputUrlParts = array_fill(0, count($outputFileRelativePathParts), '..'); $outputUrlParts = array_merge($outputUrlParts, $inputFileRelativePathParts); diff --git a/tests/unit/framework/console/controllers/AssetControllerTest.php b/tests/unit/framework/console/controllers/AssetControllerTest.php index a76a942..db6d2a7 100644 --- a/tests/unit/framework/console/controllers/AssetControllerTest.php +++ b/tests/unit/framework/console/controllers/AssetControllerTest.php @@ -286,6 +286,18 @@ class AssetControllerTest extends TestCase '/test/base/path/assets/output', '.static-relative-dir-class {background-image: url("../../img/static_relative_dir.png");}', ), + array( + '.absolute-url-class {background-image: url(http://domain.com/img/image.gif);}', + '/test/base/path/assets/input', + '/test/base/path/assets/output', + '.absolute-url-class {background-image: url(http://domain.com/img/image.gif);}', + ), + array( + '.absolute-url-secure-class {background-image: url(https://secure.domain.com/img/image.gif);}', + '/test/base/path/assets/input', + '/test/base/path/assets/output', + '.absolute-url-secure-class {background-image: url(https://secure.domain.com/img/image.gif);}', + ), ); }