1
0
Fork 0
mirror of synced 2024-05-21 05:02:37 +12:00

Merge branch '0.7.x' of github.com:appwrite/appwrite into dev

This commit is contained in:
Eldad Fux 2021-02-27 17:39:48 +02:00
commit 64ca27e342
14 changed files with 212 additions and 551 deletions

View file

@ -162,8 +162,6 @@ Appwrite's current structure is a combination of both [Monolithic](https://en.wi
│ ├── Extend
│ ├── Network
│ ├── OpenSSL
│ ├── Resize
│ ├── Storage
│ ├── Task
│ ├── Template
│ ├── URL

View file

@ -1,28 +1,28 @@
<?php
use Utopia\App;
use Utopia\Exception;
use Utopia\Validator\Boolean;
use Utopia\Validator\Text;
use Utopia\Validator\WhiteList;
use Utopia\Validator\Range;
use Utopia\Validator\URL;
use Utopia\Cache\Cache;
use Utopia\Cache\Adapter\Filesystem;
use Appwrite\Resize\Resize;
use Appwrite\URL\URL as URLParse;
use Appwrite\Utopia\Response;
use Utopia\Config\Config;
use Utopia\Validator\HexColor;
use chillerlan\QRCode\QRCode;
use chillerlan\QRCode\QROptions;
use Utopia\App;
use Utopia\Cache\Adapter\Filesystem;
use Utopia\Cache\Cache;
use Utopia\Config\Config;
use Utopia\Exception;
use Utopia\Image\Image;
use Utopia\Validator\Boolean;
use Utopia\Validator\HexColor;
use Utopia\Validator\Range;
use Utopia\Validator\Text;
use Utopia\Validator\URL;
use Utopia\Validator\WhiteList;
$avatarCallback = function ($type, $code, $width, $height, $quality, $response) {
/** @var Appwrite\Utopia\Response $response */
$code = \strtolower($code);
$type = \strtolower($type);
$set = Config::getParam('avatar-'.$type, []);
$set = Config::getParam('avatar-' . $type, []);
if (empty($set)) {
throw new Exception('Avatar set not found', 404);
@ -37,17 +37,17 @@ $avatarCallback = function ($type, $code, $width, $height, $quality, $response)
}
$output = 'png';
$date = \date('D, d M Y H:i:s', \time() + (60 * 60 * 24 * 45)).' GMT'; // 45 days cache
$key = \md5('/v1/avatars/:type/:code-'.$code.$width.$height.$quality.$output);
$date = \date('D, d M Y H:i:s', \time() + (60 * 60 * 24 * 45)) . ' GMT'; // 45 days cache
$key = \md5('/v1/avatars/:type/:code-' . $code . $width . $height . $quality . $output);
$path = $set[$code];
$type = 'png';
if (!\is_readable($path)) {
throw new Exception('File not readable in '.$path, 500);
throw new Exception('File not readable in ' . $path, 500);
}
$cache = new Cache(new Filesystem(APP_STORAGE_CACHE.'/app-0')); // Limit file number or size
$data = $cache->load($key, 60 * 60 * 24 * 30 * 3 /* 3 months */);
$cache = new Cache(new Filesystem(APP_STORAGE_CACHE . '/app-0')); // Limit file number or size
$data = $cache->load($key, 60 * 60 * 24 * 30 * 3/* 3 months */);
if ($data) {
//$output = (empty($output)) ? $type : $output;
@ -60,24 +60,23 @@ $avatarCallback = function ($type, $code, $width, $height, $quality, $response)
;
}
$resize = new Resize(\file_get_contents($path));
$image = new Image(\file_get_contents($path));
$resize->crop((int) $width, (int) $height);
$image->crop((int) $width, (int) $height);
$output = (empty($output)) ? $type : $output;
$data = $resize->output($output, $quality);
$data = $image->output($output, $quality);
$cache->save($key, $data);
$response
->setContentType('image/png')
->addHeader('Expires', $date)
->addHeader('X-Appwrite-Cache', 'miss')
->send($data, null);
;
unset($resize);
unset($image);
};
App::get('/v1/avatars/credit-cards/:code')
@ -91,7 +90,7 @@ App::get('/v1/avatars/credit-cards/:code')
->label('sdk.description', '/docs/references/avatars/get-credit-card.md')
->label('sdk.response.code', Response::STATUS_CODE_OK)
->label('sdk.response.type', Response::CONTENT_TYPE_IMAGE_PNG)
->param('code', '', new WhiteList(\array_keys(Config::getParam('avatar-credit-cards'))), 'Credit Card Code. Possible values: '.\implode(', ', \array_keys(Config::getParam('avatar-credit-cards'))).'.')
->param('code', '', new WhiteList(\array_keys(Config::getParam('avatar-credit-cards'))), 'Credit Card Code. Possible values: ' . \implode(', ', \array_keys(Config::getParam('avatar-credit-cards'))) . '.')
->param('width', 100, new Range(0, 2000), 'Image width. Pass an integer between 0 to 2000. Defaults to 100.', true)
->param('height', 100, new Range(0, 2000), 'Image height. Pass an integer between 0 to 2000. Defaults to 100.', true)
->param('quality', 100, new Range(0, 100), 'Image quality. Pass an integer between 0 to 100. Defaults to 100.', true)
@ -160,11 +159,11 @@ App::get('/v1/avatars/image')
$quality = 80;
$output = 'png';
$date = \date('D, d M Y H:i:s', \time() + (60 * 60 * 24 * 45)).' GMT'; // 45 days cache
$key = \md5('/v2/avatars/images-'.$url.'-'.$width.'/'.$height.'/'.$quality);
$date = \date('D, d M Y H:i:s', \time() + (60 * 60 * 24 * 45)) . ' GMT'; // 45 days cache
$key = \md5('/v2/avatars/images-' . $url . '-' . $width . '/' . $height . '/' . $quality);
$type = 'png';
$cache = new Cache(new Filesystem(APP_STORAGE_CACHE.'/app-0')); // Limit file number or size
$data = $cache->load($key, 60 * 60 * 24 * 7 /* 1 week */);
$cache = new Cache(new Filesystem(APP_STORAGE_CACHE . '/app-0')); // Limit file number or size
$data = $cache->load($key, 60 * 60 * 24 * 7/* 1 week */);
if ($data) {
return $response
@ -186,17 +185,17 @@ App::get('/v1/avatars/image')
}
try {
$resize = new Resize($fetch);
} catch (\Exception $exception) {
$image = new Image($fetch);
} catch (\Exception$exception) {
throw new Exception('Unable to parse image', 500);
}
$resize->crop((int) $width, (int) $height);
$image->crop((int) $width, (int) $height);
$output = (empty($output)) ? $type : $output;
$data = $resize->output($output, $quality);
$data = $image->output($output, $quality);
$cache->save($key, $data);
$response
@ -206,7 +205,7 @@ App::get('/v1/avatars/image')
->send($data);
;
unset($resize);
unset($image);
});
App::get('/v1/avatars/favicon')
@ -229,11 +228,11 @@ App::get('/v1/avatars/favicon')
$height = 56;
$quality = 80;
$output = 'png';
$date = \date('D, d M Y H:i:s', \time() + (60 * 60 * 24 * 45)).' GMT'; // 45 days cache
$key = \md5('/v2/avatars/favicon-'.$url);
$date = \date('D, d M Y H:i:s', \time() + (60 * 60 * 24 * 45)) . ' GMT'; // 45 days cache
$key = \md5('/v2/avatars/favicon-' . $url);
$type = 'png';
$cache = new Cache(new Filesystem(APP_STORAGE_CACHE.'/app-0')); // Limit file number or size
$data = $cache->load($key, 60 * 60 * 24 * 30 * 3 /* 3 months */);
$cache = new Cache(new Filesystem(APP_STORAGE_CACHE . '/app-0')); // Limit file number or size
$data = $cache->load($key, 60 * 60 * 24 * 30 * 3/* 3 months */);
if ($data) {
return $response
@ -316,7 +315,7 @@ App::get('/v1/avatars/favicon')
if (empty($outputHref) || empty($outputExt)) {
$default = \parse_url($url);
$outputHref = $default['scheme'].'://'.$default['host'].'/favicon.ico';
$outputHref = $default['scheme'] . '://' . $default['host'] . '/favicon.ico';
$outputExt = 'ico';
}
@ -343,13 +342,13 @@ App::get('/v1/avatars/favicon')
throw new Exception('Icon not found', 404);
}
$resize = new Resize($fetch);
$image = new Image($fetch);
$resize->crop((int) $width, (int) $height);
$image->crop((int) $width, (int) $height);
$output = (empty($output)) ? $type : $output;
$data = $resize->output($output, $quality);
$data = $image->output($output, $quality);
$cache->save($key, $data);
@ -359,7 +358,7 @@ App::get('/v1/avatars/favicon')
->addHeader('X-Appwrite-Cache', 'miss')
->send($data);
unset($resize);
unset($image);
});
App::get('/v1/avatars/qr')
@ -394,14 +393,14 @@ App::get('/v1/avatars/qr')
$response->addHeader('Content-Disposition', 'attachment; filename="qr.png"');
}
$resize = new Resize($qrcode->render($text));
$image = new Image($qrcode->render($text));
$resize->crop((int) $size, (int) $size);
$image->crop((int) $size, (int) $size);
$response
->addHeader('Expires', \date('D, d M Y H:i:s', \time() + (60 * 60 * 24 * 45)).' GMT') // 45 days cache
->addHeader('Expires', \date('D, d M Y H:i:s', \time() + (60 * 60 * 24 * 45)) . ' GMT') // 45 days cache
->setContentType('image/png')
->send($resize->output('png', 9))
->send($image->output('png', 9))
;
});
@ -437,10 +436,10 @@ App::get('/v1/avatars/initials')
['color' => '#610038', 'background' => '#f5d1e6'], // PINK
['color' => '#386100', 'background' => '#dcf1bd'], // LIME
['color' => '#615800', 'background' => '#f1ecba'], // YELLOW
['color' => '#610008', 'background' => '#f6d2d5'] // RED
['color' => '#610008', 'background' => '#f6d2d5'], // RED
];
$rand = \rand(0, \count($themes)-1);
$rand = \rand(0, \count($themes) - 1);
$name = (!empty($name)) ? $name : $user->getAttribute('name', $user->getAttribute('email', ''));
$words = \explode(' ', \strtoupper($name));
@ -457,23 +456,23 @@ App::get('/v1/avatars/initials')
}
$length = \count($words);
$rand = \substr($code,-1);
$background = (!empty($background)) ? '#'.$background : $themes[$rand]['background'];
$color = (!empty($color)) ? '#'.$color : $themes[$rand]['color'];
$rand = \substr($code, -1);
$background = (!empty($background)) ? '#' . $background : $themes[$rand]['background'];
$color = (!empty($color)) ? '#' . $color : $themes[$rand]['color'];
$image = new \Imagick();
$draw = new \ImagickDraw();
$fontSize = \min($width, $height) / 2;
$draw->setFont(__DIR__."/../../../public/fonts/poppins-v9-latin-500.ttf");
$image->setFont(__DIR__."/../../../public/fonts/poppins-v9-latin-500.ttf");
$draw->setFont(__DIR__ . "/../../../public/fonts/poppins-v9-latin-500.ttf");
$image->setFont(__DIR__ . "/../../../public/fonts/poppins-v9-latin-500.ttf");
$draw->setFillColor(new \ImagickPixel($color));
$draw->setFontSize($fontSize);
$draw->setTextAlignment(\Imagick::ALIGN_CENTER);
$draw->annotation($width / 1.97, ($height / 2) + ($fontSize / 3), $initials);
$image->newImage($width, $height, $background);
$image->setImageFormat("png");
$image->drawImage($draw);
@ -481,7 +480,7 @@ App::get('/v1/avatars/initials')
//$image->setImageCompressionQuality(9 - round(($quality / 100) * 9));
$response
->addHeader('Expires', \date('D, d M Y H:i:s', \time() + (60 * 60 * 24 * 45)).' GMT') // 45 days cache
->addHeader('Expires', \date('D, d M Y H:i:s', \time() + (60 * 60 * 24 * 45)) . ' GMT') // 45 days cache
->setContentType('image/png')
->send($image->getImageBlob())
;

View file

@ -18,7 +18,7 @@ use Utopia\Storage\Validator\File;
use Utopia\Storage\Validator\FileSize;
use Utopia\Storage\Validator\Upload;
use Utopia\Storage\Compression\Algorithms\GZIP;
use Appwrite\Resize\Resize;
use Utopia\Image\Image;
use Appwrite\OpenSSL\OpenSSL;
use Appwrite\Utopia\Response;
use Utopia\Config\Config;
@ -332,17 +332,17 @@ App::get('/v1/storage/files/:fileId/preview')
$source = $compressor->decompress($source);
}
$resize = new Resize($source);
$image = new Image($source);
$resize->crop((int) $width, (int) $height);
$image->crop((int) $width, (int) $height);
if (!empty($background)) {
$resize->setBackground('#'.$background);
$image->setBackground('#'.$background);
}
$output = (empty($output)) ? $type : $output;
$data = $resize->output($output, $quality);
$data = $image->output($output, $quality);
$cache->save($key, $data);
@ -353,7 +353,7 @@ App::get('/v1/storage/files/:fileId/preview')
->send($data)
;
unset($resize);
unset($image);
});
App::get('/v1/storage/files/:fileId/download')

View file

@ -47,7 +47,8 @@
"utopia-php/domains": "0.2.*",
"utopia-php/swoole": "0.2.*",
"utopia-php/system": "0.4.*",
"utopia-php/storage": "0.2.*",
"utopia-php/storage": "0.4.*",
"utopia-php/image": "0.1.*",
"resque/php-resque": "1.3.6",
"matomo/device-detector": "4.1.0",

235
composer.lock generated
View file

@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
"content-hash": "01173c3bd9d5d01922432165ebcf1ce2",
"content-hash": "4f58de92fb64af44d915387895472881",
"packages": [
{
"name": "adhocore/jwt",
@ -1691,6 +1691,59 @@
},
"time": "2020-12-26T12:02:39+00:00"
},
{
"name": "utopia-php/image",
"version": "0.1.0",
"source": {
"type": "git",
"url": "https://github.com/utopia-php/image.git",
"reference": "66e38db211b1d6fe93de09d82606641e0f996e42"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/utopia-php/image/zipball/66e38db211b1d6fe93de09d82606641e0f996e42",
"reference": "66e38db211b1d6fe93de09d82606641e0f996e42",
"shasum": ""
},
"require": {
"chillerlan/php-qrcode": "4.3.0",
"ext-imagick": "*",
"php": ">=7.4"
},
"require-dev": {
"phpunit/phpunit": "^9.3",
"vimeo/psalm": "4.0.1"
},
"type": "library",
"autoload": {
"psr-4": {
"Utopia\\Image\\": "src/Image"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Eldad Fux",
"email": "eldad@appwrite.io"
}
],
"description": "A simple Image manipulation library",
"keywords": [
"framework",
"image",
"php",
"upf",
"utopia"
],
"support": {
"issues": "https://github.com/utopia-php/image/issues",
"source": "https://github.com/utopia-php/image/tree/0.1.0"
},
"time": "2021-02-19T05:09:46+00:00"
},
{
"name": "utopia-php/locale",
"version": "0.3.3",
@ -1849,16 +1902,16 @@
},
{
"name": "utopia-php/storage",
"version": "0.2.0",
"version": "0.4.1",
"source": {
"type": "git",
"url": "https://github.com/utopia-php/storage.git",
"reference": "27bfd663c9b2a17ac0911522a87f42bee834df95"
"reference": "86f749f2d79268528732e560f77dde0155e162ca"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/utopia-php/storage/zipball/27bfd663c9b2a17ac0911522a87f42bee834df95",
"reference": "27bfd663c9b2a17ac0911522a87f42bee834df95",
"url": "https://api.github.com/repos/utopia-php/storage/zipball/86f749f2d79268528732e560f77dde0155e162ca",
"reference": "86f749f2d79268528732e560f77dde0155e162ca",
"shasum": ""
},
"require": {
@ -1895,9 +1948,9 @@
],
"support": {
"issues": "https://github.com/utopia-php/storage/issues",
"source": "https://github.com/utopia-php/storage/tree/0.2.0"
"source": "https://github.com/utopia-php/storage/tree/0.4.1"
},
"time": "2021-01-27T12:21:27+00:00"
"time": "2021-02-19T05:04:44+00:00"
},
{
"name": "utopia-php/swoole",
@ -2653,12 +2706,12 @@
"source": {
"type": "git",
"url": "https://github.com/felixfbecker/php-language-server-protocol.git",
"reference": "85e83cacd2ed573238678c6875f8f0d7ec699541"
"reference": "9d846d1f5cf101deee7a61c8ba7caa0a975cd730"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/felixfbecker/php-language-server-protocol/zipball/85e83cacd2ed573238678c6875f8f0d7ec699541",
"reference": "85e83cacd2ed573238678c6875f8f0d7ec699541",
"url": "https://api.github.com/repos/felixfbecker/php-language-server-protocol/zipball/9d846d1f5cf101deee7a61c8ba7caa0a975cd730",
"reference": "9d846d1f5cf101deee7a61c8ba7caa0a975cd730",
"shasum": ""
},
"require": {
@ -2700,9 +2753,9 @@
],
"support": {
"issues": "https://github.com/felixfbecker/php-language-server-protocol/issues",
"source": "https://github.com/felixfbecker/php-language-server-protocol/tree/v1.5.0"
"source": "https://github.com/felixfbecker/php-language-server-protocol/tree/1.5.1"
},
"time": "2020-10-23T13:55:30+00:00"
"time": "2021-02-22T14:02:09+00:00"
},
{
"name": "matthiasmullie/minify",
@ -3117,16 +3170,16 @@
},
{
"name": "phar-io/version",
"version": "3.0.4",
"version": "3.1.0",
"source": {
"type": "git",
"url": "https://github.com/phar-io/version.git",
"reference": "e4782611070e50613683d2b9a57730e9a3ba5451"
"reference": "bae7c545bef187884426f042434e561ab1ddb182"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/phar-io/version/zipball/e4782611070e50613683d2b9a57730e9a3ba5451",
"reference": "e4782611070e50613683d2b9a57730e9a3ba5451",
"url": "https://api.github.com/repos/phar-io/version/zipball/bae7c545bef187884426f042434e561ab1ddb182",
"reference": "bae7c545bef187884426f042434e561ab1ddb182",
"shasum": ""
},
"require": {
@ -3162,9 +3215,9 @@
"description": "Library for handling version information and constraints",
"support": {
"issues": "https://github.com/phar-io/version/issues",
"source": "https://github.com/phar-io/version/tree/3.0.4"
"source": "https://github.com/phar-io/version/tree/3.1.0"
},
"time": "2020-12-13T23:18:30+00:00"
"time": "2021-02-23T14:00:09+00:00"
},
{
"name": "phpdocumentor/reflection-common",
@ -3477,12 +3530,12 @@
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/php-file-iterator.git",
"reference": "499be26d3f45b1d12b4903a772ea22f858a48eb3"
"reference": "dae425925709122f7584cadeeb838edcaa491bb1"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/499be26d3f45b1d12b4903a772ea22f858a48eb3",
"reference": "499be26d3f45b1d12b4903a772ea22f858a48eb3",
"url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/dae425925709122f7584cadeeb838edcaa491bb1",
"reference": "dae425925709122f7584cadeeb838edcaa491bb1",
"shasum": ""
},
"require": {
@ -3530,7 +3583,7 @@
"type": "github"
}
],
"time": "2021-02-21T06:39:05+00:00"
"time": "2021-02-23T15:48:43+00:00"
},
{
"name": "phpunit/php-invoker",
@ -3538,12 +3591,12 @@
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/php-invoker.git",
"reference": "e17a1cc6f8ab1ba4f4ff654019b9d7d9f017267c"
"reference": "5ad9e5f5d6ee1a837e1d50bab1017e0daf423b40"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/php-invoker/zipball/e17a1cc6f8ab1ba4f4ff654019b9d7d9f017267c",
"reference": "e17a1cc6f8ab1ba4f4ff654019b9d7d9f017267c",
"url": "https://api.github.com/repos/sebastianbergmann/php-invoker/zipball/5ad9e5f5d6ee1a837e1d50bab1017e0daf423b40",
"reference": "5ad9e5f5d6ee1a837e1d50bab1017e0daf423b40",
"shasum": ""
},
"require": {
@ -3594,7 +3647,7 @@
"type": "github"
}
],
"time": "2021-02-21T06:39:14+00:00"
"time": "2021-02-23T15:48:51+00:00"
},
{
"name": "phpunit/php-text-template",
@ -3602,12 +3655,12 @@
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/php-text-template.git",
"reference": "8de0286bd8c4988bc20fbd7c246d1662e5c2efe2"
"reference": "4ec5a2ac79a19b35d0cf83cce30604f77743067a"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/php-text-template/zipball/8de0286bd8c4988bc20fbd7c246d1662e5c2efe2",
"reference": "8de0286bd8c4988bc20fbd7c246d1662e5c2efe2",
"url": "https://api.github.com/repos/sebastianbergmann/php-text-template/zipball/4ec5a2ac79a19b35d0cf83cce30604f77743067a",
"reference": "4ec5a2ac79a19b35d0cf83cce30604f77743067a",
"shasum": ""
},
"require": {
@ -3654,7 +3707,7 @@
"type": "github"
}
],
"time": "2021-02-21T06:39:47+00:00"
"time": "2021-02-23T15:49:24+00:00"
},
{
"name": "phpunit/php-timer",
@ -3662,12 +3715,12 @@
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/php-timer.git",
"reference": "bb859edc295be92317a9161ddb0d5cae03c4e164"
"reference": "705821b0927b5e69e9e016c84de68dc6195c71b9"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/bb859edc295be92317a9161ddb0d5cae03c4e164",
"reference": "bb859edc295be92317a9161ddb0d5cae03c4e164",
"url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/705821b0927b5e69e9e016c84de68dc6195c71b9",
"reference": "705821b0927b5e69e9e016c84de68dc6195c71b9",
"shasum": ""
},
"require": {
@ -3714,7 +3767,7 @@
"type": "github"
}
],
"time": "2021-02-21T06:39:22+00:00"
"time": "2021-02-23T15:48:59+00:00"
},
{
"name": "phpunit/phpunit",
@ -3879,12 +3932,12 @@
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/cli-parser.git",
"reference": "83a4f03a3fce4f613fa2662aa7357246c7bb6860"
"reference": "3a42d843af4d27ca1155e1d926881af162733655"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/cli-parser/zipball/83a4f03a3fce4f613fa2662aa7357246c7bb6860",
"reference": "83a4f03a3fce4f613fa2662aa7357246c7bb6860",
"url": "https://api.github.com/repos/sebastianbergmann/cli-parser/zipball/3a42d843af4d27ca1155e1d926881af162733655",
"reference": "3a42d843af4d27ca1155e1d926881af162733655",
"shasum": ""
},
"require": {
@ -3928,7 +3981,7 @@
"type": "github"
}
],
"time": "2021-02-21T06:40:12+00:00"
"time": "2021-02-23T15:49:50+00:00"
},
{
"name": "sebastian/code-unit",
@ -3992,12 +4045,12 @@
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/code-unit-reverse-lookup.git",
"reference": "b0e1cc9a057295d75ec7c03e6e89094fa0787ca4"
"reference": "5f5db0b35f586eb5bca0581a10bb42dd56575986"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/code-unit-reverse-lookup/zipball/b0e1cc9a057295d75ec7c03e6e89094fa0787ca4",
"reference": "b0e1cc9a057295d75ec7c03e6e89094fa0787ca4",
"url": "https://api.github.com/repos/sebastianbergmann/code-unit-reverse-lookup/zipball/5f5db0b35f586eb5bca0581a10bb42dd56575986",
"reference": "5f5db0b35f586eb5bca0581a10bb42dd56575986",
"shasum": ""
},
"require": {
@ -4040,7 +4093,7 @@
"type": "github"
}
],
"time": "2021-02-21T06:37:59+00:00"
"time": "2021-02-23T15:47:39+00:00"
},
{
"name": "sebastian/comparator",
@ -4048,12 +4101,12 @@
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/comparator.git",
"reference": "56f15c16d786947d3fbb9df2788ae14049d34286"
"reference": "dbc5fb421f242a5749845dc8dd0dc8cde2979dd9"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/56f15c16d786947d3fbb9df2788ae14049d34286",
"reference": "56f15c16d786947d3fbb9df2788ae14049d34286",
"url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/dbc5fb421f242a5749845dc8dd0dc8cde2979dd9",
"reference": "dbc5fb421f242a5749845dc8dd0dc8cde2979dd9",
"shasum": ""
},
"require": {
@ -4115,7 +4168,7 @@
"type": "github"
}
],
"time": "2021-02-21T06:38:07+00:00"
"time": "2021-02-23T15:47:47+00:00"
},
{
"name": "sebastian/complexity",
@ -4180,12 +4233,12 @@
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/diff.git",
"reference": "33d65ae1c50be986bfbddd876d23ea3042bc2b5f"
"reference": "93e6aa13f3dc5f8327e7fb9756e9655fc4c23e90"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/33d65ae1c50be986bfbddd876d23ea3042bc2b5f",
"reference": "33d65ae1c50be986bfbddd876d23ea3042bc2b5f",
"url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/93e6aa13f3dc5f8327e7fb9756e9655fc4c23e90",
"reference": "93e6aa13f3dc5f8327e7fb9756e9655fc4c23e90",
"shasum": ""
},
"require": {
@ -4239,7 +4292,7 @@
"type": "github"
}
],
"time": "2021-02-21T06:38:16+00:00"
"time": "2021-02-23T15:47:55+00:00"
},
{
"name": "sebastian/environment",
@ -4247,12 +4300,12 @@
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/environment.git",
"reference": "d5a0fb77ea34154ab24cc9ada037e9f2b5715842"
"reference": "6e1743b808be9cfd33a716583ccb94b7d4d32e94"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/d5a0fb77ea34154ab24cc9ada037e9f2b5715842",
"reference": "d5a0fb77ea34154ab24cc9ada037e9f2b5715842",
"url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/6e1743b808be9cfd33a716583ccb94b7d4d32e94",
"reference": "6e1743b808be9cfd33a716583ccb94b7d4d32e94",
"shasum": ""
},
"require": {
@ -4303,7 +4356,7 @@
"type": "github"
}
],
"time": "2021-02-21T06:38:24+00:00"
"time": "2021-02-23T15:48:03+00:00"
},
{
"name": "sebastian/exporter",
@ -4311,12 +4364,12 @@
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/exporter.git",
"reference": "36878bc8e65b75bdd37fe65ed6939e6374164b06"
"reference": "eca7281ab29075df68b113a37a83be616b629b12"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/36878bc8e65b75bdd37fe65ed6939e6374164b06",
"reference": "36878bc8e65b75bdd37fe65ed6939e6374164b06",
"url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/eca7281ab29075df68b113a37a83be616b629b12",
"reference": "eca7281ab29075df68b113a37a83be616b629b12",
"shasum": ""
},
"require": {
@ -4381,7 +4434,7 @@
"type": "github"
}
],
"time": "2021-02-21T06:38:32+00:00"
"time": "2021-02-23T15:48:12+00:00"
},
{
"name": "sebastian/global-state",
@ -4389,12 +4442,12 @@
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/global-state.git",
"reference": "48eacca30bf0ee1f7b4ba27ddbf5a448d5eae9b9"
"reference": "0ac702e6d13725242edb9b294c5d20b92fcfb8b4"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/48eacca30bf0ee1f7b4ba27ddbf5a448d5eae9b9",
"reference": "48eacca30bf0ee1f7b4ba27ddbf5a448d5eae9b9",
"url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/0ac702e6d13725242edb9b294c5d20b92fcfb8b4",
"reference": "0ac702e6d13725242edb9b294c5d20b92fcfb8b4",
"shasum": ""
},
"require": {
@ -4446,7 +4499,7 @@
"type": "github"
}
],
"time": "2021-02-21T06:38:40+00:00"
"time": "2021-02-23T15:48:19+00:00"
},
{
"name": "sebastian/lines-of-code",
@ -4511,12 +4564,12 @@
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/object-enumerator.git",
"reference": "00ebe4f5fb5fbc4e7ab57545f70c0ef61392f527"
"reference": "8cc80b4bda00a4c5997c3fc597a34872f3a1007d"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/object-enumerator/zipball/00ebe4f5fb5fbc4e7ab57545f70c0ef61392f527",
"reference": "00ebe4f5fb5fbc4e7ab57545f70c0ef61392f527",
"url": "https://api.github.com/repos/sebastianbergmann/object-enumerator/zipball/8cc80b4bda00a4c5997c3fc597a34872f3a1007d",
"reference": "8cc80b4bda00a4c5997c3fc597a34872f3a1007d",
"shasum": ""
},
"require": {
@ -4561,7 +4614,7 @@
"type": "github"
}
],
"time": "2021-02-21T06:38:48+00:00"
"time": "2021-02-23T15:48:28+00:00"
},
{
"name": "sebastian/object-reflector",
@ -4569,12 +4622,12 @@
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/object-reflector.git",
"reference": "13af24fcef1a0857804d8f1896e95af4f01c37f0"
"reference": "1d33587c2c3e636936f895e103a9e82dd8102a8e"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/object-reflector/zipball/13af24fcef1a0857804d8f1896e95af4f01c37f0",
"reference": "13af24fcef1a0857804d8f1896e95af4f01c37f0",
"url": "https://api.github.com/repos/sebastianbergmann/object-reflector/zipball/1d33587c2c3e636936f895e103a9e82dd8102a8e",
"reference": "1d33587c2c3e636936f895e103a9e82dd8102a8e",
"shasum": ""
},
"require": {
@ -4617,7 +4670,7 @@
"type": "github"
}
],
"time": "2021-02-21T06:38:56+00:00"
"time": "2021-02-23T15:48:35+00:00"
},
{
"name": "sebastian/recursion-context",
@ -4625,12 +4678,12 @@
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/recursion-context.git",
"reference": "43746c15374dba48c7c81f8e993b21888c943a83"
"reference": "43f58a51e8f853aadb228ba818d2be388af7237b"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/43746c15374dba48c7c81f8e993b21888c943a83",
"reference": "43746c15374dba48c7c81f8e993b21888c943a83",
"url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/43f58a51e8f853aadb228ba818d2be388af7237b",
"reference": "43f58a51e8f853aadb228ba818d2be388af7237b",
"shasum": ""
},
"require": {
@ -4681,7 +4734,7 @@
"type": "github"
}
],
"time": "2021-02-21T06:39:30+00:00"
"time": "2021-02-23T15:49:08+00:00"
},
{
"name": "sebastian/resource-operations",
@ -4745,12 +4798,12 @@
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/type.git",
"reference": "819c8e7fba19e9c2137b238040b906f1586cc7cc"
"reference": "557863473c1de00e165a288d5b547f1f83652e7e"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/type/zipball/819c8e7fba19e9c2137b238040b906f1586cc7cc",
"reference": "819c8e7fba19e9c2137b238040b906f1586cc7cc",
"url": "https://api.github.com/repos/sebastianbergmann/type/zipball/557863473c1de00e165a288d5b547f1f83652e7e",
"reference": "557863473c1de00e165a288d5b547f1f83652e7e",
"shasum": ""
},
"require": {
@ -4794,7 +4847,7 @@
"type": "github"
}
],
"time": "2021-02-21T06:39:38+00:00"
"time": "2021-02-23T15:49:16+00:00"
},
{
"name": "sebastian/version",
@ -4893,12 +4946,12 @@
"source": {
"type": "git",
"url": "https://github.com/symfony/console.git",
"reference": "539148499aaafa5058d534582f61ce2a66480987"
"reference": "c08d7d0d458eceb62996d81d3be8d9fbf5564ec4"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/console/zipball/539148499aaafa5058d534582f61ce2a66480987",
"reference": "539148499aaafa5058d534582f61ce2a66480987",
"url": "https://api.github.com/repos/symfony/console/zipball/c08d7d0d458eceb62996d81d3be8d9fbf5564ec4",
"reference": "c08d7d0d458eceb62996d81d3be8d9fbf5564ec4",
"shasum": ""
},
"require": {
@ -4983,7 +5036,7 @@
"type": "tidelift"
}
],
"time": "2021-02-18T11:02:40+00:00"
"time": "2021-02-23T10:10:15+00:00"
},
{
"name": "symfony/polyfill-intl-grapheme",
@ -5403,12 +5456,12 @@
"source": {
"type": "git",
"url": "https://github.com/symfony/service-contracts.git",
"reference": "bf99754c6182a126968b1c2709d18548489f27eb"
"reference": "e830e6ceebd6377b019e4c9a523d6f2c27007e4a"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/service-contracts/zipball/bf99754c6182a126968b1c2709d18548489f27eb",
"reference": "bf99754c6182a126968b1c2709d18548489f27eb",
"url": "https://api.github.com/repos/symfony/service-contracts/zipball/e830e6ceebd6377b019e4c9a523d6f2c27007e4a",
"reference": "e830e6ceebd6377b019e4c9a523d6f2c27007e4a",
"shasum": ""
},
"require": {
@ -5422,7 +5475,7 @@
"type": "library",
"extra": {
"branch-alias": {
"dev-main": "2.3-dev"
"dev-main": "2.4-dev"
},
"thanks": {
"name": "symfony/contracts",
@ -5475,7 +5528,7 @@
"type": "tidelift"
}
],
"time": "2021-01-27T16:27:53+00:00"
"time": "2021-02-25T16:38:04+00:00"
},
{
"name": "symfony/string",
@ -5617,12 +5670,12 @@
"source": {
"type": "git",
"url": "https://github.com/twigphp/Twig.git",
"reference": "429f90a02d3bd4a06787ac9bc48c56c4320b58a0"
"reference": "728c611e8643a5dd44839ffa791e21763b04a694"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/twigphp/Twig/zipball/429f90a02d3bd4a06787ac9bc48c56c4320b58a0",
"reference": "429f90a02d3bd4a06787ac9bc48c56c4320b58a0",
"url": "https://api.github.com/repos/twigphp/Twig/zipball/728c611e8643a5dd44839ffa791e21763b04a694",
"reference": "728c611e8643a5dd44839ffa791e21763b04a694",
"shasum": ""
},
"require": {
@ -5688,7 +5741,7 @@
"type": "tidelift"
}
],
"time": "2021-02-08T09:50:07+00:00"
"time": "2021-02-22T11:56:05+00:00"
},
{
"name": "vimeo/psalm",

View file

@ -1,220 +0,0 @@
<?php
namespace Appwrite\Resize;
use Exception;
use Imagick;
class Resize
{
private $image;
private $width;
private $height;
/**
* @param string $data
*
* @throws Exception
*/
public function __construct($data)
{
$this->image = new Imagick();
$this->image->readImageBlob($data);
$this->width = $this->image->getImageWidth();
$this->height = $this->image->getImageHeight();
}
/**
* @param int $width
* @param int $height
*
* @return Resize
*
* @throws \Throwable
*/
public function crop(int $width, int $height)
{
$originalAspect = $this->width / $this->height;
if (empty($width)) {
$width = $height * $originalAspect;
}
if (empty($height)) {
$height = $width / $originalAspect;
}
if (empty($height) && empty($width)) {
$height = $this->height;
$width = $this->width;
}
if ($this->image->getImageFormat() == 'GIF') {
$this->image = $this->image->coalesceImages();
foreach ($this->image as $frame) {
$frame->cropThumbnailImage($width, $height);
}
$this->image->deconstructImages();
} else {
$this->image->cropThumbnailImage($width, $height);
}
return $this;
}
/**
* @param $color
*
* @return Resize
*
* @throws \Throwable
*/
public function setBackground($color)
{
$this->image->setImageBackgroundColor($color);
$this->image = $this->image->mergeImageLayers(Imagick::LAYERMETHOD_FLATTEN);
return $this;
}
/**
* Output.
*
* Prints manipulated image.
*
* @param string $type
* @param int $quality
*
* @return string
*
* @throws Exception
*/
public function output(string $type, int $quality = 75)
{
return $this->save(null, $type, $quality);
}
/**
* @param string $path
* @param $type
* @param int $quality
*
* @return string
*
* @throws Exception
*/
public function save(string $path = null, string $type = '', int $quality = 75)
{
// Create directory with write permissions
if (null !== $path && !\file_exists(\dirname($path))) {
if (!@\mkdir(\dirname($path), 0755, true)) {
throw new Exception('Can\'t create directory '.\dirname($path));
}
}
switch ($type) {
case 'jpg':
case 'jpeg':
$this->image->setImageCompressionQuality($quality);
$this->image->setImageFormat('jpg');
break;
case 'gif':
$this->image->setImageFormat('gif');
break;
case 'webp':
try {
$this->image->setImageFormat('webp');
} catch (\Throwable $th) {
$signature = $this->image->getImageSignature();
$temp = '/tmp/temp-'.$signature.'.'.\strtolower($this->image->getImageFormat());
$output = '/tmp/output-'.$signature.'.webp';
// save temp
$this->image->writeImages($temp, true);
// convert temp
\exec("cwebp -quiet -metadata none -q $quality $temp -o $output");
$data = \file_get_contents($output);
//load webp
if (empty($path)) {
return $data;
} else {
\file_put_contents($path, $data, LOCK_EX);
}
$this->image->clear();
$this->image->destroy();
//delete webp
\unlink($output);
\unlink($temp);
return;
}
break;
case 'png':
/* Scale quality from 0-100 to 0-9 */
$scaleQuality = \round(($quality / 100) * 9);
/* Invert quality setting as 0 is best, not 9 */
$invertScaleQuality = 9 - $scaleQuality;
$this->image->setImageCompressionQuality($invertScaleQuality);
$this->image->setImageFormat('png');
break;
default:
throw new Exception('Invalid output type given');
break;
}
if (empty($path)) {
return $this->image->getImagesBlob();
} else {
$this->image->writeImages($path, true);
}
$this->image->clear();
$this->image->destroy();
}
/**
* @param int $newHeight
*
* @return int
*/
protected function getSizeByFixedHeight(int $newHeight):int
{
$ratio = $this->width / $this->height;
$newWidth = $newHeight * $ratio;
return $newWidth;
}
/**
* @param int $newWidth
*
* @return int
*/
protected function getSizeByFixedWidth(int $newWidth):int
{
$ratio = $this->height / $this->width;
$newHeight = $newWidth * $ratio;
return $newHeight;
}
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 799 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 596 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 31 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 23 KiB

View file

@ -1,170 +0,0 @@
<?php
namespace Appwrite\Tests;
use Appwrite\Resize\Resize;
use PHPUnit\Framework\TestCase;
class ResizeTest extends TestCase
{
public function setUp(): void
{
}
public function tearDown(): void
{
}
public function testCrop100x100()
{
$resize = new Resize(\file_get_contents(__DIR__ . '/../../resources/disk-a/kitten-1.jpg'));
$target = __DIR__.'/100x100.jpg';
$resize->crop(100, 100);
$resize->save($target, 'jpg', 100);
$this->assertEquals(\is_readable($target), true);
$this->assertNotEmpty(\md5(\file_get_contents($target)));
$image = new \Imagick($target);
$this->assertEquals(100, $image->getImageWidth());
$this->assertEquals(100, $image->getImageHeight());
$this->assertEquals('JPEG', $image->getImageFormat());
\unlink($target);
}
public function testCrop100x400()
{
$resize = new Resize(\file_get_contents(__DIR__ . '/../../resources/disk-a/kitten-1.jpg'));
$target = __DIR__.'/100x400.jpg';
$resize->crop(100, 400);
$resize->save($target, 'jpg', 100);
$this->assertEquals(\is_readable($target), true);
$this->assertNotEmpty(\md5(\file_get_contents($target)));
$image = new \Imagick($target);
$this->assertEquals(100, $image->getImageWidth());
$this->assertEquals(400, $image->getImageHeight());
$this->assertEquals('JPEG', $image->getImageFormat());
\unlink($target);
}
public function testCrop400x100()
{
$resize = new Resize(\file_get_contents(__DIR__ . '/../../resources/disk-a/kitten-1.jpg'));
$target = __DIR__.'/400x100.jpg';
$resize->crop(400, 100);
$resize->save($target, 'jpg', 100);
$this->assertEquals(\is_readable($target), true);
$this->assertNotEmpty(\md5(\file_get_contents($target)));
$image = new \Imagick($target);
$this->assertEquals(400, $image->getImageWidth());
$this->assertEquals(100, $image->getImageHeight());
$this->assertEquals('JPEG', $image->getImageFormat());
\unlink($target);
}
public function testCrop100x100WEBP()
{
$resize = new Resize(\file_get_contents(__DIR__ . '/../../resources/disk-a/kitten-1.jpg'));
$target = __DIR__.'/100x100.webp';
$original = __DIR__.'/../../resources/resize/100x100.webp';
$resize->crop(100, 100);
$resize->save($target, 'webp', 100);
$this->assertEquals(\is_readable($target), true);
$this->assertNotEmpty(\md5(\file_get_contents($target)));
$image = new \Imagick($target);
$this->assertEquals(100, $image->getImageWidth());
$this->assertEquals(100, $image->getImageHeight());
$this->assertTrue(in_array($image->getImageFormat(), ['PAM', 'WEBP']));
\unlink($target);
}
public function testCrop100x100PNG()
{
$resize = new Resize(\file_get_contents(__DIR__ . '/../../resources/disk-a/kitten-1.jpg'));
$target = __DIR__.'/100x100.png';
$original = __DIR__.'/../../resources/resize/100x100.png';
$resize->crop(100, 100);
$resize->save($target, 'png', 100);
$this->assertEquals(\is_readable($target), true);
$this->assertGreaterThan(15000, \filesize($target));
$this->assertLessThan(30000, \filesize($target));
$this->assertEquals(\mime_content_type($target), \mime_content_type($original));
$this->assertNotEmpty(\md5(\file_get_contents($target)));
$image = new \Imagick($target);
$this->assertEquals(100, $image->getImageWidth());
$this->assertEquals(100, $image->getImageHeight());
$this->assertEquals('PNG', $image->getImageFormat());
\unlink($target);
}
public function testCrop100x100PNGQuality30()
{
$resize = new Resize(\file_get_contents(__DIR__ . '/../../resources/disk-a/kitten-1.jpg'));
$target = __DIR__.'/100x100-q30.jpg';
$original = __DIR__.'/../../resources/resize/100x100-q30.jpg';
$resize->crop(100, 100);
$resize->save($target, 'jpg', 10);
$this->assertEquals(\is_readable($target), true);
$this->assertGreaterThan(500, \filesize($target));
$this->assertLessThan(2000, \filesize($target));
$this->assertEquals(\mime_content_type($target), \mime_content_type($original));
$this->assertNotEmpty(\md5(\file_get_contents($target)));
$image = new \Imagick($target);
$this->assertEquals(100, $image->getImageWidth());
$this->assertEquals(100, $image->getImageHeight());
$this->assertEquals('JPEG', $image->getImageFormat());
\unlink($target);
}
public function testCrop100x100GIF()
{
$resize = new Resize(\file_get_contents(__DIR__ . '/../../resources/disk-a/kitten-3.gif'));
$target = __DIR__.'/100x100.gif';
$original = __DIR__.'/../../resources/resize/100x100.gif';
$resize->crop(100, 100);
$resize->save($target, 'gif', 100);
$this->assertEquals(\is_readable($target), true);
$this->assertGreaterThan(400000, \filesize($target));
$this->assertLessThan(800000, \filesize($target));
$this->assertEquals(\mime_content_type($target), \mime_content_type($original));
$this->assertNotEmpty(\md5(\file_get_contents($target)));
$image = new \Imagick($target);
$this->assertEquals(100, $image->getImageWidth());
$this->assertEquals(100, $image->getImageHeight());
$this->assertEquals('GIF', $image->getImageFormat());
\unlink($target);
}
}