Skip to content

Commit

Permalink
Merge pull request #32 from tinify/transcoding
Browse files Browse the repository at this point in the history
Image transcoding
  • Loading branch information
rkoopmans authored Sep 26, 2022
2 parents 6ba7c59 + 2165f0b commit fe42293
Show file tree
Hide file tree
Showing 7 changed files with 126 additions and 22 deletions.
5 changes: 5 additions & 0 deletions CHANGES.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
## 1.6.0
* Support to run the unittests on newer versions of PHP (5.5 +)
* Add API methods for converting/transcoding and transformation
* Add helper function for returning the compressed file extension

## 1.5.2
* Fail early if version of curl/openssl is too old.

Expand Down
2 changes: 1 addition & 1 deletion lib/Tinify.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

namespace Tinify;

const VERSION = "1.5.2";
const VERSION = "1.6.0";

class Tinify {
private static $key = NULL;
Expand Down
8 changes: 8 additions & 0 deletions lib/Tinify/ResultMeta.php
Original file line number Diff line number Diff line change
Expand Up @@ -20,4 +20,12 @@ public function height() {
public function location() {
return isset($this->meta["location"]) ? $this->meta["location"] : null;
}

public function extension() {
if (isset($this->meta["content-type"])) {
$parts = explode("/", $this->meta["content-type"]);
return end($parts);
}
return null;
}
}
10 changes: 10 additions & 0 deletions lib/Tinify/Source.php
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,16 @@ public function store($options) {
return new Result($response->headers, $response->body);
}

public function convert($options) {
$commands = array_merge($this->commands, array("convert" => $options));
return new self($this->url, $commands);
}

public function transform($options) {
$commands = array_merge($this->commands, array("transform" => $options));
return new self($this->url, $commands);
}

public function result() {
$response = Tinify::getClient()->request("get", $this->url, $this->commands);
return new Result($response->headers, $response->body);
Expand Down
10 changes: 10 additions & 0 deletions test/TinifyResultTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -32,4 +32,14 @@ public function testWithMetaAndDataToBufferShouldReturnImageData() {
$result = new Tinify\Result(array(), "image data");
$this->assertSame("image data", $result->toBuffer());
}

public function testWithMetadataReturnsExtension() {
$result = new Tinify\Result(array("content-type" => "image/png"), "image data");
$this->assertSame($result->extension(), "png");
}

public function testWithoutMetadataReturnsExtensionAsNull() {
$result = new Tinify\ResultMeta(array(), "image data");
$this->assertSame($result->extension(), null);
}
}
102 changes: 81 additions & 21 deletions test/TinifySourceTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ public function testWithInvalidApiKeyFromUrlShouldThrowAccountException() {
Tinify\Source::fromUrl("http://example.com/test.jpg");
}

public function testWithValidApiKeyFromFileShouldReturnSource() {
public function testFromFileShouldReturnSource() {
Tinify\setKey("valid");

CurlMock::register("https://api.tinify.com/shrink", array(
Expand All @@ -46,7 +46,7 @@ public function testWithValidApiKeyFromFileShouldReturnSource() {
$this->assertInstanceOf("Tinify\Source", Tinify\Source::fromFile(DUMMY_FILE_LOCATION));
}

public function testWithValidApiKeyFromFileShouldReturnSourceWithData() {
public function testFromFileShouldReturnSourceWithData() {
Tinify\setKey("valid");

CurlMock::register("https://api.tinify.com/shrink", array(
Expand All @@ -60,7 +60,7 @@ public function testWithValidApiKeyFromFileShouldReturnSourceWithData() {
$this->assertSame("compressed file", Tinify\Source::fromFile(DUMMY_FILE_LOCATION)->toBuffer());
}

public function testWithValidApiKeyFromBufferShouldReturnSource() {
public function testFromBufferShouldReturnSource() {
Tinify\setKey("valid");

CurlMock::register("https://api.tinify.com/shrink", array(
Expand All @@ -70,7 +70,7 @@ public function testWithValidApiKeyFromBufferShouldReturnSource() {
$this->assertInstanceOf("Tinify\Source", Tinify\Source::fromBuffer("png file"));
}

public function testWithValidApiKeyFromBufferShouldReturnSourceWithData() {
public function testFromBufferShouldReturnSourceWithData() {
Tinify\setKey("valid");

CurlMock::register("https://api.tinify.com/shrink", array(
Expand All @@ -84,17 +84,17 @@ public function testWithValidApiKeyFromBufferShouldReturnSourceWithData() {
$this->assertSame("compressed file", Tinify\Source::fromBuffer("png file")->toBuffer());
}

public function testWithValidApiKeyFromUrlShouldReturnSource() {
public function testFromUrlShouldReturnSource() {
Tinify\setKey("valid");

CurlMock::register("https://api.tinify.com/shrink", array(
"status" => 201, "headers" => array("Location" => "https://api.tinify.com/some/location")
));

$this->assertInstanceOf("Tinify\Source", Tinify\Source::fromUrl("http://example.com/testWithValidApiKey.jpg"));
$this->assertInstanceOf("Tinify\Source", Tinify\Source::fromUrl("http://example.com/test.jpg"));
}

public function testWithValidApiKeyFromUrlShouldReturnSourceWithData() {
public function testFromUrlShouldReturnSourceWithData() {
Tinify\setKey("valid");

CurlMock::register("https://api.tinify.com/shrink", array(
Expand All @@ -105,10 +105,10 @@ public function testWithValidApiKeyFromUrlShouldReturnSourceWithData() {
"status" => 200, "body" => "compressed file"
));

$this->assertSame("compressed file", Tinify\Source::fromUrl("http://example.com/testWithValidApiKey.jpg")->toBuffer());
$this->assertSame("compressed file", Tinify\Source::fromUrl("http://example.com/test.jpg")->toBuffer());
}

public function testWithValidApiKeyFromUrlShouldThrowExceptionIfRequestIsNotOK() {
public function testFromUrlShouldThrowExceptionIfRequestIsNotOK() {
Tinify\setKey("valid");

CurlMock::register("https://api.tinify.com/shrink", array(
Expand All @@ -119,7 +119,7 @@ public function testWithValidApiKeyFromUrlShouldThrowExceptionIfRequestIsNotOK()
Tinify\Source::fromUrl("file://wrong");
}

public function testWithValidApiKeyResultShouldReturnResult() {
public function testResultShouldReturnResult() {
Tinify\setKey("valid");

CurlMock::register("https://api.tinify.com/shrink", array(
Expand All @@ -134,7 +134,7 @@ public function testWithValidApiKeyResultShouldReturnResult() {
$this->assertInstanceOf("Tinify\Result", Tinify\Source::fromBuffer("png file")->result());
}

public function testWithValidApiKeyPreserveShouldReturnSource() {
public function testPreserveShouldReturnSource() {
Tinify\setKey("valid");

CurlMock::register("https://api.tinify.com/shrink", array(
Expand All @@ -149,7 +149,7 @@ public function testWithValidApiKeyPreserveShouldReturnSource() {
$this->assertSame("png file", CurlMock::last(CURLOPT_POSTFIELDS));
}

public function testWithValidApiKeyPreserveShouldReturnSourceWithData() {
public function testPreserveShouldReturnSourceWithData() {
Tinify\setKey("valid");

CurlMock::register("https://api.tinify.com/shrink", array(
Expand All @@ -164,7 +164,7 @@ public function testWithValidApiKeyPreserveShouldReturnSourceWithData() {
$this->assertSame("{\"preserve\":[\"copyright\",\"location\"]}", CurlMock::last(CURLOPT_POSTFIELDS));
}

public function testWithValidApiKeyPreserveShouldReturnSourceWithDataForArray() {
public function testPreserveShouldReturnSourceWithDataForArray() {
Tinify\setKey("valid");

CurlMock::register("https://api.tinify.com/shrink", array(
Expand All @@ -179,7 +179,7 @@ public function testWithValidApiKeyPreserveShouldReturnSourceWithDataForArray()
$this->assertSame("{\"preserve\":[\"copyright\",\"location\"]}", CurlMock::last(CURLOPT_POSTFIELDS));
}

public function testWithValidApiKeyPreserveShouldIncludeOtherOptionsIfSet() {
public function testPreserveShouldIncludeOtherOptionsIfSet() {
Tinify\setKey("valid");

CurlMock::register("https://api.tinify.com/shrink", array(
Expand All @@ -196,7 +196,7 @@ public function testWithValidApiKeyPreserveShouldIncludeOtherOptionsIfSet() {
$this->assertSame("{\"resize\":{\"width\":400},\"preserve\":[\"copyright\",\"location\"]}", CurlMock::last(CURLOPT_POSTFIELDS));
}

public function testWithValidApiKeyResizeShouldReturnSource() {
public function testResizeShouldReturnSource() {
Tinify\setKey("valid");

CurlMock::register("https://api.tinify.com/shrink", array(
Expand All @@ -211,7 +211,7 @@ public function testWithValidApiKeyResizeShouldReturnSource() {
$this->assertSame("png file", CurlMock::last(CURLOPT_POSTFIELDS));
}

public function testWithValidApiKeyResizeShouldReturnSourceWithData() {
public function testResizeShouldReturnSourceWithData() {
Tinify\setKey("valid");

CurlMock::register("https://api.tinify.com/shrink", array(
Expand All @@ -226,7 +226,67 @@ public function testWithValidApiKeyResizeShouldReturnSourceWithData() {
$this->assertSame("{\"resize\":{\"width\":400}}", CurlMock::last(CURLOPT_POSTFIELDS));
}

public function testWithValidApiKeyStoreShouldReturnResultMeta() {
public function testConvertShouldReturnSource() {
Tinify\setKey("valid");

CurlMock::register("https://api.tinify.com/shrink", array(
"status" => 201, "headers" => array("Location" => "https://api.tinify.com/some/location")
));

CurlMock::register("https://api.tinify.com/some/location", array(
"status" => 200, "body" => "Convertd file"
));

$this->assertInstanceOf("Tinify\Source", Tinify\Source::fromBuffer("png file")->Convert(array("type" =>"image/webp")));
$this->assertSame("png file", CurlMock::last(CURLOPT_POSTFIELDS));
}

public function testConvertShouldReturnSourceWithData() {
Tinify\setKey("valid");

CurlMock::register("https://api.tinify.com/shrink", array(
"status" => 201, "headers" => array("Location" => "https://api.tinify.com/some/location")
));

CurlMock::register("https://api.tinify.com/some/location", array(
"status" => 200, "body" => "Convertd file"
));

$this->assertSame("Convertd file", Tinify\Source::fromBuffer("png file")->convert(array("type" => "image/webp"))->toBuffer());
$this->assertSame("{\"convert\":{\"type\":\"image\/webp\"}}", CurlMock::last(CURLOPT_POSTFIELDS));
}

public function testTransformShouldReturnSource() {
Tinify\setKey("valid");

CurlMock::register("https://api.tinify.com/shrink", array(
"status" => 201, "headers" => array("Location" => "https://api.tinify.com/some/location")
));

CurlMock::register("https://api.tinify.com/some/location", array(
"status" => 200, "body" => "transformed file"
));

$this->assertInstanceOf("Tinify\Source", Tinify\Source::fromBuffer("png file")->transform(array("background" => "black")));
$this->assertSame("png file", CurlMock::last(CURLOPT_POSTFIELDS));
}

public function testTransformShouldReturnSourceWithData() {
Tinify\setKey("valid");

CurlMock::register("https://api.tinify.com/shrink", array(
"status" => 201, "headers" => array("Location" => "https://api.tinify.com/some/location")
));

CurlMock::register("https://api.tinify.com/some/location", array(
"status" => 200, "body" => "transformd file"
));

$this->assertSame("transformd file", Tinify\Source::fromBuffer("png file")->transform(array("background" => "black"))->toBuffer());
$this->assertSame("{\"transform\":{\"background\":\"black\"}}", CurlMock::last(CURLOPT_POSTFIELDS));
}

public function testStoreShouldReturnResultMeta() {
Tinify\setKey("valid");

CurlMock::register("https://api.tinify.com/shrink", array(
Expand All @@ -243,7 +303,7 @@ public function testWithValidApiKeyStoreShouldReturnResultMeta() {
$this->assertSame("{\"store\":{\"service\":\"s3\",\"aws_secret_access_key\":\"abcde\"}}", CurlMock::last(CURLOPT_POSTFIELDS));
}

public function testWithValidApiKeyStoreShouldReturnResultMetaWithLocation() {
public function testStoreShouldReturnResultMetaWithLocation() {
Tinify\setKey("valid");

CurlMock::register("https://api.tinify.com/shrink", array(
Expand All @@ -263,7 +323,7 @@ public function testWithValidApiKeyStoreShouldReturnResultMetaWithLocation() {
$this->assertSame("{\"store\":{\"service\":\"s3\"}}", CurlMock::last(CURLOPT_POSTFIELDS));
}

public function testWithValidApiKeyStoreShouldIncludeOtherOptionsIfSet() {
public function testStoreShouldIncludeOtherOptionsIfSet() {
Tinify\setKey("valid");

CurlMock::register("https://api.tinify.com/shrink", array(
Expand All @@ -280,7 +340,7 @@ public function testWithValidApiKeyStoreShouldIncludeOtherOptionsIfSet() {
$this->assertSame("{\"resize\":{\"width\":300},\"store\":{\"service\":\"s3\",\"aws_secret_access_key\":\"abcde\"}}", CurlMock::last(CURLOPT_POSTFIELDS));
}

public function testWithValidApiKeyToBufferShouldReturnImageData() {
public function testToBufferShouldReturnImageData() {
Tinify\setKey("valid");

CurlMock::register("https://api.tinify.com/shrink", array(
Expand All @@ -293,7 +353,7 @@ public function testWithValidApiKeyToBufferShouldReturnImageData() {
$this->assertSame("compressed file", Tinify\Source::fromBuffer("png file")->toBuffer());
}

public function testWithValidApiKeyToFileShouldStoreImageData() {
public function testToFileShouldStoreImageData() {
Tinify\setKey("valid");

CurlMock::register("https://api.tinify.com/shrink", array(
Expand Down
11 changes: 11 additions & 0 deletions test/integration.php
Original file line number Diff line number Diff line change
Expand Up @@ -77,4 +77,15 @@ public function testShouldPreserveMetadata() {
$this->assertStringContainsString("\0\0\0\x89", $contents);
$this->assertStringContainsString("Copyright Voormedia", $contents);
}

public function testShouldConvert() {
$path = tempnam(sys_get_temp_dir(), "tinify-php");
self::$optimized->convert(array("type" => ["image/webp"]))->toFile($path);

$size = filesize($path);
$contents = fread(fopen($path, "rb"), $size);

$this->assertEquals(substr($contents, 0, 4), "RIFF");
$this->assertEquals(substr($contents, 8, 4), "WEBP");
}
}

0 comments on commit fe42293

Please sign in to comment.