From c304e18810d3664d025174eec57f4e5fa0fc9372 Mon Sep 17 00:00:00 2001 From: Sherwin H Date: Tue, 27 Aug 2019 14:34:04 -0700 Subject: [PATCH 01/10] feat: add srcset generation function --- src/Imgix/UrlBuilder.php | 60 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 60 insertions(+) diff --git a/src/Imgix/UrlBuilder.php b/src/Imgix/UrlBuilder.php index 8489dc3..f4d30a2 100644 --- a/src/Imgix/UrlBuilder.php +++ b/src/Imgix/UrlBuilder.php @@ -57,4 +57,64 @@ public function createURL($path, $params=array()) { return $uh->getURL(); } + + public function createSrcSet($path, $params=array()) { + $width = array_key_exists('w', $params) ? $params['w'] : NULL; + $height = array_key_exists('h', $params) ? $params['h'] : NULL; + $aspectRatio = array_key_exists('ar', $params) ? $params['ar'] : NULL; + + if (($width) || ($height && $aspectRatio)) { + return $this->createDPRSrcSet($path, $params); + } + else { + return $this->createSrcSetPairs($path, $params); + } + } + + private function createDPRSrcSet($path, $params) { + $srcset = ""; + $targetRatios = array(1, 2, 3, 4, 5); + $url = $this->createURL($path, $params); + + $size = count($targetRatios); + for($i = 0; $i < $size; $i++) { + $currentRatio = $targetRatios[$i]; + $srcset .= $url." ".$currentRatio."x,\n"; + } + + return substr($srcset, 0, strlen($srcset)-2); + } + + private function createSrcSetPairs($path, $params) { + $srcset = ""; + $currentWidth = NULL; + $currentParams = NULL; + $targetWidths = $this->targetWidths(); + + $size = count($targetWidths); + for($i = 0; $i < $size; $i++) { + $currentWidth = $targetWidths[$i]; + $currentParams = $params; + $currentParams['w'] = $currentWidth; + $srcset .= $this->createURL($path, $currentParams) . " " . $currentWidth . "w,\n"; + } + + return substr($srcset, 0, strlen($srcset)-2); + } + + private function targetWidths() { + $resolutions = array(); + $prev = 100; + $INCREMENT_PERCENTAGE = 8; + $MAX_SIZE = 8192; + + + while ($prev <= $MAX_SIZE) { + array_push($resolutions, 2 * round($prev / 2)); + $prev *= 1 + ($INCREMENT_PERCENTAGE / 100) * 2; + } + + array_push($resolutions, $MAX_SIZE); + return $resolutions; + } } From 3857ef43140eb0113c0d1bd1f360b3c67f89222e Mon Sep 17 00:00:00 2001 From: Sherwin H Date: Tue, 27 Aug 2019 21:40:47 -0700 Subject: [PATCH 02/10] style: spacing; separate rounding to helper function --- src/Imgix/UrlBuilder.php | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/Imgix/UrlBuilder.php b/src/Imgix/UrlBuilder.php index f4d30a2..600aef0 100644 --- a/src/Imgix/UrlBuilder.php +++ b/src/Imgix/UrlBuilder.php @@ -77,7 +77,7 @@ private function createDPRSrcSet($path, $params) { $url = $this->createURL($path, $params); $size = count($targetRatios); - for($i = 0; $i < $size; $i++) { + for ($i = 0; $i < $size; $i++) { $currentRatio = $targetRatios[$i]; $srcset .= $url." ".$currentRatio."x,\n"; } @@ -92,7 +92,7 @@ private function createSrcSetPairs($path, $params) { $targetWidths = $this->targetWidths(); $size = count($targetWidths); - for($i = 0; $i < $size; $i++) { + for ($i = 0; $i < $size; $i++) { $currentWidth = $targetWidths[$i]; $currentParams = $params; $currentParams['w'] = $currentWidth; @@ -108,9 +108,12 @@ private function targetWidths() { $INCREMENT_PERCENTAGE = 8; $MAX_SIZE = 8192; + $ensureEven = function($n) { + return 2 * round($n / 2); + }; while ($prev <= $MAX_SIZE) { - array_push($resolutions, 2 * round($prev / 2)); + array_push($resolutions, $ensureEven($prev)); $prev *= 1 + ($INCREMENT_PERCENTAGE / 100) * 2; } From fc84c0a06a182b30a6f664087c6bd448689e9e22 Mon Sep 17 00:00:00 2001 From: Sherwin H Date: Tue, 27 Aug 2019 21:41:13 -0700 Subject: [PATCH 03/10] test: add srcset tests --- tests/Imgix/Tests/UrlBuilderTest.php | 255 +++++++++++++++++++++++++++ 1 file changed, 255 insertions(+) diff --git a/tests/Imgix/Tests/UrlBuilderTest.php b/tests/Imgix/Tests/UrlBuilderTest.php index 9901279..9422061 100644 --- a/tests/Imgix/Tests/UrlBuilderTest.php +++ b/tests/Imgix/Tests/UrlBuilderTest.php @@ -139,5 +139,260 @@ public function test_invalid_domain_append_dash() { $builder = new UrlBuilder("demos.imgix.net-", true, "", false); } + + private function srcsetBuilder($params=array()) { + $builder = new UrlBuilder("demos.imgix.net", true, "my-key", false); + return $builder->createSrcSet("bridge.png", $params); + } + + // parse the width as an int, eg "100w" => 100 + private function parseWidth($width) { + return (int)substr($width, 0, strlen($width)-1); + } + + public function testNoParametersGeneratesSrcsetPairs() { + $srcset = $this->srcsetBuilder(); + $expectedNumberOfPairs = 31; + $this->assertEquals($expectedNumberOfPairs, count(explode(",", $srcset))); + } + + public function testSrcsetPairValues() { + $srcset = $this->srcsetBuilder(); + $index = 0; + // array of expected resolutions generated by srcset + $resolutions = array(100, 116, 134, 156, 182, 210, 244, 282, + 328, 380, 442, 512, 594, 688, 798, 926, + 1074, 1246, 1446, 1678, 1946, 2258, 2618, + 3038, 3524, 4088, 4742, 5500, 6380, 7400, 8192); + $srclist = explode(",", $srcset); + $matches = array(); + + foreach ($srclist as $src) { + $width = explode(" ", $src)[1]; + + // extract width int values + preg_match("/\d+/", $width, $matches); + $this->assertEquals($resolutions[$index], $matches[0]); + $index ++; + } + } + + public function testGivenWidthSrcsetIsDPR() { + $srcset = $this->srcsetBuilder(array("w"=>300)); + $devicePixelRatio = 1; + $srclist = explode(",", $srcset); + + foreach ($srclist as $src) { + $generatedRatio = explode(" ", $src)[1]; + $dprStr = $devicePixelRatio . "x"; + $this->assertEquals($dprStr, $generatedRatio); + $devicePixelRatio += 1; + } + } + + public function testGivenWidthSignsURLs() { + $srcset = $this->srcsetBuilder(array("w"=>300)); + $expectedSignature = "65bff01b598e97ddeb1f39a56930ec30"; + $srclist = explode(",", $srcset); + + foreach ($srclist as $src) { + $url = explode(" ", $src)[0]; + $this->assertStringContainsString("s=", $url); + + // extract the sign parameter + $generatedSignature = substr($url, strrpos($url, "s=")+2); + $this->assertEquals($expectedSignature, $generatedSignature); + } + } + + public function testGivenHeightSrcsetGeneratesPairs() { + $srcset = $this->srcsetBuilder(array("h"=>300)); + $expectedNumberOfPairs = 31; + $this->assertEquals($expectedNumberOfPairs, count(explode(",", $srcset))); + } + + public function testGivenHeightRespectsParameter() { + $srcset = $this->srcsetBuilder(array("h"=>300)); + $srclist = explode(",", $srcset); + + foreach ($srclist as $src) { + $this->assertStringContainsString("h=300", $src); + } + } + + public function testGivenHeightSrcsetPairsWithinBounds() { + $srcset = $this->srcsetBuilder(array("h"=>300)); + $srclist = explode(",", $srcset); + + $minParsed = explode(" ", $srclist[0])[1]; + $maxParsed = explode(" ", $srclist[count($srclist)-1])[1]; + $min = $this->parseWidth($minParsed); + $max = $this->parseWidth($maxParsed); + + $this->assertGreaterThanOrEqual(100, $min); + $this->assertLessThanOrEqual(8192, $max); + } + + public function testGivenHeightSrcsetIteratesEighteenPercent() { + $incrementAllowed = .18; + $srcset = $this->srcsetBuilder(array("h"=>300)); + $srclist = explode(",", $srcset); + + $widths = array_map(function ($src) { + return $this->parseWidth(explode(" ", $src)[1]); + }, $srclist); + + $prev = $widths[0]; + $size = count($widths); + for ($i = 1; $i < $size; $i++) { + $width = $widths[$i]; + $this->assertLessThan((1 + $incrementAllowed), ($width / $prev)); + $prev = $width; + } + } + + public function testGivenHeightSrcsetSignsUrls() { + $srcset = $this->srcsetBuilder(array("h"=>300)); + $srclist = explode(",", $srcset); + + $srcs = array_map(function ($src) { + return explode(" ", $src)[0]; + }, $srclist); + + foreach ($srcs as $src) { + $this->assertStringContainsString("s=", $src); + + // parse out query params + $params = substr($src, strrpos($src, "?")); + $params = substr($params, 0, strrpos($params, "s=")-1); + + // parse out sign parameter + $generatedSignature = substr($src, strrpos($src, "s=")+2); + + $signatureBase = "my-key" . "/bridge.png" . $params; + $expectSignature = md5($signatureBase); + + $this->assertEquals($expectSignature, $generatedSignature); + } + } + + public function testGivenWidthAndHeightSrcsetIsDPR() { + $srcset = $this->srcsetBuilder(array("w"=>300, "h"=>"400")); + $devicePixelRatio = 1; + $srclist = explode(",", $srcset); + + foreach ($srclist as $src) { + $generatedRatio = explode(" ", $src)[1]; + $dprStr = $devicePixelRatio . "x"; + $this->assertEquals($dprStr, $generatedRatio); + $devicePixelRatio += 1; + } + } + + public function testGivenWidthAndHeightSignsURLs() { + $srcset = $this->srcsetBuilder(array("w"=>300, "h"=>"400")); + $expectedSignature = "27e4d1ec19ed834a3d8b7ec89dda0e20"; + $srclist = explode(",", $srcset); + + foreach ($srclist as $src) { + $url = explode(" ", $src)[0]; + $this->assertStringContainsString("s=", $url); + + // extract the sign parameter + $generatedSignature = substr($url, strrpos($url, "s=")+2); + $this->assertEquals($expectedSignature, $generatedSignature); + } + } + + public function testGivenAspectRatioSrcsetGeneratesPairs() { + $srcset = $this->srcsetBuilder(array("ar"=>"3:2")); + $expectedNumberOfPairs = 31; + $this->assertEquals($expectedNumberOfPairs, count(explode(",", $srcset))); + } + + public function testGivenAspectRatioSrcsetPairsWithinBounds() { + $srcset = $this->srcsetBuilder(array("ar"=>"3:2")); + $srclist = explode(",", $srcset); + + $minParsed = explode(" ", $srclist[0])[1]; + $maxParsed = explode(" ", $srclist[count($srclist)-1])[1]; + $min = $this->parseWidth($minParsed); + $max = $this->parseWidth($maxParsed); + + $this->assertGreaterThanOrEqual(100, $min); + $this->assertLessThanOrEqual(8192, $max); + } + + public function testGivenAspectRatioSrcsetIteratesEighteenPercent() { + $incrementAllowed = .18; + $srcset = $this->srcsetBuilder(array("ar"=>"3:2")); + $srclist = explode(",", $srcset); + + $widths = array_map(function ($src) { + return $this->parseWidth(explode(" ", $src)[1]); + }, $srclist); + + $prev = $widths[0]; + $size = count($widths); + for ($i = 1; $i < $size; $i++) { + $width = $widths[$i]; + $this->assertLessThan((1 + $incrementAllowed), ($width / $prev)); + $prev = $width; + } + } + + public function testGivenAspectRatioSrcsetSignsUrls() { + $srcset = $this->srcsetBuilder(array("ar"=>"3:2")); + $srclist = explode(",", $srcset); + + $srcs = array_map(function ($src) { + return explode(" ", $src)[0]; + }, $srclist); + + foreach ($srcs as $src) { + $this->assertStringContainsString("s=", $src); + + // parse out query params + $params = substr($src, strrpos($src, "?")); + $params = substr($params, 0, strrpos($params, "s=")-1); + + // parse out sign parameter + $generatedSignature = substr($src, strrpos($src, "s=")+2); + + $signatureBase = "my-key" . "/bridge.png" . $params; + $expectSignature = md5($signatureBase); + + $this->assertEquals($expectSignature, $generatedSignature); + } + } + + public function testGivenAspectRatioAndHeightSrcsetIsDPR() { + $srcset = $this->srcsetBuilder(array("h"=>400,"ar"=>"3:2")); + $devicePixelRatio = 1; + $srclist = explode(",", $srcset); + + foreach ($srclist as $src) { + $generatedRatio = explode(" ", $src)[1]; + $dprStr = $devicePixelRatio . "x"; + $this->assertEquals($dprStr, $generatedRatio); + $devicePixelRatio += 1; + } + } + + public function testGivenAspectRatioAndHeightSignsURLs() { + $srcset = $this->srcsetBuilder(array("h"=>400,"ar"=>"3:2")); + $expectedSignature = "96e491fd2b81c3306545a6d88ccbe7eb"; + $srclist = explode(",", $srcset); + + foreach ($srclist as $src) { + $url = explode(" ", $src)[0]; + $this->assertStringContainsString("s=", $url); + + // extract the sign parameter + $generatedSignature = substr($url, strrpos($url, "s=")+2); + $this->assertEquals($expectedSignature, $generatedSignature); + } + } + } ?> From 2d514dc5824ba92d9cb03ebda5993715f9bc0170 Mon Sep 17 00:00:00 2001 From: Sherwin H Date: Wed, 28 Aug 2019 11:17:18 -0700 Subject: [PATCH 04/10] test: replace assertStringContainsString with phpunit backwards compatible function --- tests/Imgix/Tests/UrlBuilderTest.php | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/tests/Imgix/Tests/UrlBuilderTest.php b/tests/Imgix/Tests/UrlBuilderTest.php index 9422061..2313869 100644 --- a/tests/Imgix/Tests/UrlBuilderTest.php +++ b/tests/Imgix/Tests/UrlBuilderTest.php @@ -197,7 +197,7 @@ public function testGivenWidthSignsURLs() { foreach ($srclist as $src) { $url = explode(" ", $src)[0]; - $this->assertStringContainsString("s=", $url); + $this->assertRegExp("/s=/", $url); // extract the sign parameter $generatedSignature = substr($url, strrpos($url, "s=")+2); @@ -216,7 +216,7 @@ public function testGivenHeightRespectsParameter() { $srclist = explode(",", $srcset); foreach ($srclist as $src) { - $this->assertStringContainsString("h=300", $src); + $this->assertRegExp("/h=300/", $src); } } @@ -260,7 +260,7 @@ public function testGivenHeightSrcsetSignsUrls() { }, $srclist); foreach ($srcs as $src) { - $this->assertStringContainsString("s=", $src); + $this->assertRegExp("/s=/", $src); // parse out query params $params = substr($src, strrpos($src, "?")); @@ -296,7 +296,7 @@ public function testGivenWidthAndHeightSignsURLs() { foreach ($srclist as $src) { $url = explode(" ", $src)[0]; - $this->assertStringContainsString("s=", $url); + $this->assertRegExp("/s=/", $url); // extract the sign parameter $generatedSignature = substr($url, strrpos($url, "s=")+2); @@ -350,7 +350,7 @@ public function testGivenAspectRatioSrcsetSignsUrls() { }, $srclist); foreach ($srcs as $src) { - $this->assertStringContainsString("s=", $src); + $this->assertRegExp("/s=/", $src); // parse out query params $params = substr($src, strrpos($src, "?")); @@ -386,7 +386,7 @@ public function testGivenAspectRatioAndHeightSignsURLs() { foreach ($srclist as $src) { $url = explode(" ", $src)[0]; - $this->assertStringContainsString("s=", $url); + $this->assertRegExp("/s=/", $url); // extract the sign parameter $generatedSignature = substr($url, strrpos($url, "s=")+2); From 11c9e63c9922553f90349a1b2c426c68131aa78a Mon Sep 17 00:00:00 2001 From: Sherwin H Date: Wed, 28 Aug 2019 12:59:07 -0700 Subject: [PATCH 05/10] docs: add documentation for srcset generation --- README.md | 39 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) diff --git a/README.md b/README.md index 2a597b5..76efe88 100644 --- a/README.md +++ b/README.md @@ -81,3 +81,42 @@ echo $builder->createURL("bridge.png", $params); // Prints out: // http://demos.imgix.net/bridge.png?h=100&w=100&s=bb8f3a2ab832e35997456823272103a4 ``` + +## Srcset Generation + +The imgix library allows for generation of custom `srcset` attributes, which can be invoked through `createSrcSet()`. By default, the `srcset` generated will allow for responsive size switching by building a list of image-width mappings. + +```php +$builder = new UrlBuilder("demos.imgix.net", true, "my-key", false); +$builder->createSrcSet("bridge.png"); +``` + +Will produce the following attribute value, which can then be served to the client: + +```html +https://demos.imgix.net/bridge.png?w=100&s=ac331d314510e3039a33aa1a7ebc23ee 100w, +https://demos.imgix.net/bridge.png?w=116&s=aac0667a00791c8c8801a2fef134e78a 116w, +https://demos.imgix.net/bridge.png?w=134&s=2fcd42d984155efe26cc1e36e16b2897 134w, + ... +https://demos.imgix.net/bridge.png?w=7400&s=6a6cbe01416dc4e0c65d1a2f87b868ac 7400w, +https://demos.imgix.net/bridge.png?w=8192&s=9e6b0a94e81e929ad71829fcccf4d2d8 8192w +``` + +In cases where enough information is provided about an image's dimensions, `createSrcSet()` will instead build a `srcset` that will allow for an image to be served at different resolutions. The parameters taken into consideration when determining if an image is fixed-width are `w`, `h`, and `ar`. By invoking `createSrcSet()` with either a width **or** the height and aspect ratio (along with `fit=crop`, typically) provided, a different `srcset` will be generated for a fixed-size image instead. + +```php +$builder = new UrlBuilder("demos.imgix.net", true, "my-key", false); +$builder->createSrcSet("bridge.png", array("h"=>800, "ar"=>"3:2", "fit"=>"crop")); +``` + +Will produce the following attribute value: + +```html +https://demos.imgix.net/bridge.png?ar=3%3A2&dpr=1&fit=crop&h=800&s=39eb37ad41acf7170343aa463424ae49 1x, +https://demos.imgix.net/bridge.png?ar=3%3A2&dpr=2&fit=crop&h=800&s=a8ab13a2c7a17b91db42cb86e45f7c9d 2x, +https://demos.imgix.net/bridge.png?ar=3%3A2&dpr=3&fit=crop&h=800&s=8fefe5daf312f04fb6912a101afbf704 3x, +https://demos.imgix.net/bridge.png?ar=3%3A2&dpr=4&fit=crop&h=800&s=74a6167d6ef8ba410109feda814b9ac0 4x, +https://demos.imgix.net/bridge.png?ar=3%3A2&dpr=5&fit=crop&h=800&s=4449b7f44ba7d6d0527a16d9a10b6e39 5x +``` + +For more information to better understand `srcset`, we highly recommend [Eric Portis' "Srcset and sizes" article](https://ericportis.com/posts/2014/srcset-sizes/) which goes into depth about the subject. From 6e7751a58af4430e6961dbacf7b45fff8b883238 Mon Sep 17 00:00:00 2001 From: Sherwin H Date: Wed, 28 Aug 2019 13:12:58 -0700 Subject: [PATCH 06/10] fix: add dpr as a parameter when generated a fixed-width srcset --- src/Imgix/UrlBuilder.php | 6 ++- tests/Imgix/Tests/UrlBuilderTest.php | 57 ++++++++++++++++++++++------ 2 files changed, 49 insertions(+), 14 deletions(-) diff --git a/src/Imgix/UrlBuilder.php b/src/Imgix/UrlBuilder.php index 600aef0..1ce6d0b 100644 --- a/src/Imgix/UrlBuilder.php +++ b/src/Imgix/UrlBuilder.php @@ -74,12 +74,14 @@ public function createSrcSet($path, $params=array()) { private function createDPRSrcSet($path, $params) { $srcset = ""; $targetRatios = array(1, 2, 3, 4, 5); - $url = $this->createURL($path, $params); $size = count($targetRatios); for ($i = 0; $i < $size; $i++) { $currentRatio = $targetRatios[$i]; - $srcset .= $url." ".$currentRatio."x,\n"; + $currentParams = $params; + $dpr_value = array("dpr"=>($i+1)); + $currentParams += $dpr_value; + $srcset .= $this->createURL($path, $currentParams) . " " . $currentRatio . "x,\n"; } return substr($srcset, 0, strlen($srcset)-2); diff --git a/tests/Imgix/Tests/UrlBuilderTest.php b/tests/Imgix/Tests/UrlBuilderTest.php index 2313869..b288bc3 100644 --- a/tests/Imgix/Tests/UrlBuilderTest.php +++ b/tests/Imgix/Tests/UrlBuilderTest.php @@ -183,25 +183,36 @@ public function testGivenWidthSrcsetIsDPR() { $srclist = explode(",", $srcset); foreach ($srclist as $src) { - $generatedRatio = explode(" ", $src)[1]; + list($generatedURL, $generatedRatio) = explode(" ", $src); + $dprStr = $devicePixelRatio . "x"; $this->assertEquals($dprStr, $generatedRatio); + + $this->assertRegExp("/dpr=".$devicePixelRatio."/", $generatedURL); + $devicePixelRatio += 1; } } public function testGivenWidthSignsURLs() { $srcset = $this->srcsetBuilder(array("w"=>300)); - $expectedSignature = "65bff01b598e97ddeb1f39a56930ec30"; $srclist = explode(",", $srcset); foreach ($srclist as $src) { $url = explode(" ", $src)[0]; $this->assertRegExp("/s=/", $url); - // extract the sign parameter + // parse out query params + $params = substr($url, strrpos($url, "?")); + $params = substr($params, 0, strrpos($params, "s=")-1); + + // parse out sign parameter $generatedSignature = substr($url, strrpos($url, "s=")+2); - $this->assertEquals($expectedSignature, $generatedSignature); + + $signatureBase = "my-key" . "/bridge.png" . $params; + $expectSignature = md5($signatureBase); + + $this->assertEquals($expectSignature, $generatedSignature); } } @@ -282,25 +293,36 @@ public function testGivenWidthAndHeightSrcsetIsDPR() { $srclist = explode(",", $srcset); foreach ($srclist as $src) { - $generatedRatio = explode(" ", $src)[1]; + list($generatedURL, $generatedRatio) = explode(" ", $src); + $dprStr = $devicePixelRatio . "x"; $this->assertEquals($dprStr, $generatedRatio); + + $this->assertRegExp("/dpr=".$devicePixelRatio."/", $generatedURL); + $devicePixelRatio += 1; } } public function testGivenWidthAndHeightSignsURLs() { $srcset = $this->srcsetBuilder(array("w"=>300, "h"=>"400")); - $expectedSignature = "27e4d1ec19ed834a3d8b7ec89dda0e20"; $srclist = explode(",", $srcset); foreach ($srclist as $src) { $url = explode(" ", $src)[0]; $this->assertRegExp("/s=/", $url); + + // parse out query params + $params = substr($url, strrpos($url, "?")); + $params = substr($params, 0, strrpos($params, "s=")-1); - // extract the sign parameter + // parse out sign parameter $generatedSignature = substr($url, strrpos($url, "s=")+2); - $this->assertEquals($expectedSignature, $generatedSignature); + + $signatureBase = "my-key" . "/bridge.png" . $params; + $expectSignature = md5($signatureBase); + + $this->assertEquals($expectSignature, $generatedSignature); } } @@ -372,25 +394,36 @@ public function testGivenAspectRatioAndHeightSrcsetIsDPR() { $srclist = explode(",", $srcset); foreach ($srclist as $src) { - $generatedRatio = explode(" ", $src)[1]; + list($generatedURL, $generatedRatio) = explode(" ", $src); + $dprStr = $devicePixelRatio . "x"; $this->assertEquals($dprStr, $generatedRatio); + + $this->assertRegExp("/dpr=".$devicePixelRatio."/", $generatedURL); + $devicePixelRatio += 1; } } public function testGivenAspectRatioAndHeightSignsURLs() { $srcset = $this->srcsetBuilder(array("h"=>400,"ar"=>"3:2")); - $expectedSignature = "96e491fd2b81c3306545a6d88ccbe7eb"; $srclist = explode(",", $srcset); foreach ($srclist as $src) { $url = explode(" ", $src)[0]; $this->assertRegExp("/s=/", $url); + + // parse out query params + $params = substr($url, strrpos($url, "?")); + $params = substr($params, 0, strrpos($params, "s=")-1); - // extract the sign parameter + // parse out sign parameter $generatedSignature = substr($url, strrpos($url, "s=")+2); - $this->assertEquals($expectedSignature, $generatedSignature); + + $signatureBase = "my-key" . "/bridge.png" . $params; + $expectSignature = md5($signatureBase); + + $this->assertEquals($expectSignature, $generatedSignature); } } From 715b48b0ce1c115f5ccd4f5c770776d23766a840 Mon Sep 17 00:00:00 2001 From: Sherwin H Date: Wed, 28 Aug 2019 13:19:55 -0700 Subject: [PATCH 07/10] add dpr parameter in a different way, overwrites user-passed dpr --- src/Imgix/UrlBuilder.php | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/Imgix/UrlBuilder.php b/src/Imgix/UrlBuilder.php index 1ce6d0b..0619c33 100644 --- a/src/Imgix/UrlBuilder.php +++ b/src/Imgix/UrlBuilder.php @@ -79,8 +79,7 @@ private function createDPRSrcSet($path, $params) { for ($i = 0; $i < $size; $i++) { $currentRatio = $targetRatios[$i]; $currentParams = $params; - $dpr_value = array("dpr"=>($i+1)); - $currentParams += $dpr_value; + $currentParams['dpr'] = $i+1; $srcset .= $this->createURL($path, $currentParams) . " " . $currentRatio . "x,\n"; } From 777af4da516f5008cbc08fc29445e3ca9261e030 Mon Sep 17 00:00:00 2001 From: Sherwin H Date: Thu, 29 Aug 2019 15:21:10 -0700 Subject: [PATCH 08/10] address PR feedback --- src/Imgix/UrlBuilder.php | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/src/Imgix/UrlBuilder.php b/src/Imgix/UrlBuilder.php index 0619c33..10547f4 100644 --- a/src/Imgix/UrlBuilder.php +++ b/src/Imgix/UrlBuilder.php @@ -9,6 +9,9 @@ class UrlBuilder { private $useHttps; private $signKey; + private const TARGETRATIOS = array(1, 2, 3, 4, 5); + private $targetWidths; + public function __construct($domain, $useHttps = false, $signKey = "", $includeLibraryParam = true) { if (!is_string($domain)) { @@ -21,6 +24,7 @@ public function __construct($domain, $useHttps = false, $signKey = "", $includeL $this->useHttps = $useHttps; $this->signKey = $signKey; $this->includeLibraryParam = $includeLibraryParam; + $this->targetWidths = $this->targetWidths(); } private function validateDomain($domain) { @@ -73,34 +77,32 @@ public function createSrcSet($path, $params=array()) { private function createDPRSrcSet($path, $params) { $srcset = ""; - $targetRatios = array(1, 2, 3, 4, 5); - $size = count($targetRatios); + $size = count(self::TARGETRATIOS); for ($i = 0; $i < $size; $i++) { - $currentRatio = $targetRatios[$i]; + $currentRatio = self::TARGETRATIOS[$i]; $currentParams = $params; $currentParams['dpr'] = $i+1; $srcset .= $this->createURL($path, $currentParams) . " " . $currentRatio . "x,\n"; } - return substr($srcset, 0, strlen($srcset)-2); + return substr($srcset, 0, strlen($srcset) - 2); } private function createSrcSetPairs($path, $params) { $srcset = ""; $currentWidth = NULL; $currentParams = NULL; - $targetWidths = $this->targetWidths(); - $size = count($targetWidths); + $size = count($this->targetWidths); for ($i = 0; $i < $size; $i++) { - $currentWidth = $targetWidths[$i]; + $currentWidth = $this->targetWidths[$i]; $currentParams = $params; $currentParams['w'] = $currentWidth; $srcset .= $this->createURL($path, $currentParams) . " " . $currentWidth . "w,\n"; } - return substr($srcset, 0, strlen($srcset)-2); + return substr($srcset, 0, strlen($srcset) - 2); } private function targetWidths() { From bf5ae680d93facd90b8b4bfbe5f04532d595804b Mon Sep 17 00:00:00 2001 From: Sherwin H Date: Thu, 29 Aug 2019 15:29:55 -0700 Subject: [PATCH 09/10] remove const visibility modifier as it is not supported in all php versions --- src/Imgix/UrlBuilder.php | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/Imgix/UrlBuilder.php b/src/Imgix/UrlBuilder.php index 10547f4..99b9396 100644 --- a/src/Imgix/UrlBuilder.php +++ b/src/Imgix/UrlBuilder.php @@ -9,7 +9,10 @@ class UrlBuilder { private $useHttps; private $signKey; - private const TARGETRATIOS = array(1, 2, 3, 4, 5); + // define class constants + // should be private; but visibility modifiers are not supported php version <7.1 + const TARGETRATIOS = array(1, 2, 3, 4, 5); + // constants cannot be dynamically assigned; keeping as a class variable instead private $targetWidths; public function __construct($domain, $useHttps = false, $signKey = "", $includeLibraryParam = true) { From 4d5b349e9da7cee67789a8fe850bb73b457b791d Mon Sep 17 00:00:00 2001 From: Sherwin H Date: Thu, 29 Aug 2019 16:10:38 -0700 Subject: [PATCH 10/10] docs: add to example --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 76efe88..9a952bb 100644 --- a/README.md +++ b/README.md @@ -88,7 +88,7 @@ The imgix library allows for generation of custom `srcset` attributes, which can ```php $builder = new UrlBuilder("demos.imgix.net", true, "my-key", false); -$builder->createSrcSet("bridge.png"); +echo $builder->createSrcSet("bridge.png"); ``` Will produce the following attribute value, which can then be served to the client: @@ -106,7 +106,7 @@ In cases where enough information is provided about an image's dimensions, `crea ```php $builder = new UrlBuilder("demos.imgix.net", true, "my-key", false); -$builder->createSrcSet("bridge.png", array("h"=>800, "ar"=>"3:2", "fit"=>"crop")); +echo $builder->createSrcSet("bridge.png", array("h"=>800, "ar"=>"3:2", "fit"=>"crop")); ``` Will produce the following attribute value: