1
0
Fork 0
mirror of synced 2024-07-01 20:50:49 +12:00
appwrite/app/controllers/api/avatars.php

426 lines
18 KiB
PHP
Raw Normal View History

2019-05-09 18:54:39 +12:00
<?php
2022-05-03 06:06:12 +12:00
use Appwrite\Extend\Exception;
use Appwrite\Network\Validator\URL;
2021-02-20 02:59:46 +13:00
use Appwrite\URL\URL as URLParse;
use Appwrite\Utopia\Response;
use chillerlan\QRCode\QRCode;
use chillerlan\QRCode\QROptions;
2020-06-29 05:31:21 +12:00
use Utopia\App;
2021-02-20 02:59:46 +13:00
use Utopia\Config\Config;
2022-05-03 06:06:12 +12:00
use Utopia\Database\Document;
2021-02-20 02:59:46 +13:00
use Utopia\Image\Image;
2020-06-22 00:18:00 +12:00
use Utopia\Validator\Boolean;
2021-02-20 02:59:46 +13:00
use Utopia\Validator\HexColor;
2019-05-09 18:54:39 +12:00
use Utopia\Validator\Range;
2021-02-20 02:59:46 +13:00
use Utopia\Validator\Text;
use Utopia\Validator\WhiteList;
2019-05-09 18:54:39 +12:00
2022-07-08 02:51:22 +12:00
$avatarCallback = function (string $type, string $code, int $width, int $height, int $quality, Response $response) {
2020-06-30 09:43:34 +12:00
2020-06-20 23:20:49 +12:00
$code = \strtolower($code);
$type = \strtolower($type);
2021-02-20 02:59:46 +13:00
$set = Config::getParam('avatar-' . $type, []);
2019-05-09 18:54:39 +12:00
2020-06-27 17:36:22 +12:00
if (empty($set)) {
throw new Exception(Exception::AVATAR_SET_NOT_FOUND);
2019-05-09 18:54:39 +12:00
}
2020-06-27 17:36:22 +12:00
if (!\array_key_exists($code, $set)) {
throw new Exception(Exception::AVATAR_NOT_FOUND);
2019-05-09 18:54:39 +12:00
}
2020-06-20 23:20:49 +12:00
if (!\extension_loaded('imagick')) {
throw new Exception(Exception::GENERAL_SERVER_ERROR, 'Imagick extension is missing');
2019-05-09 18:54:39 +12:00
}
$output = 'png';
2020-06-27 17:36:22 +12:00
$path = $set[$code];
$type = 'png';
2019-05-09 18:54:39 +12:00
2020-06-20 23:20:49 +12:00
if (!\is_readable($path)) {
throw new Exception(Exception::GENERAL_SERVER_ERROR, 'File not readable in ' . $path);
2019-05-09 18:54:39 +12:00
}
2021-02-20 02:59:46 +13:00
$image = new Image(\file_get_contents($path));
$image->crop((int) $width, (int) $height);
2019-05-09 18:54:39 +12:00
$output = (empty($output)) ? $type : $output;
2021-02-20 02:59:46 +13:00
$data = $image->output($output, $quality);
2022-07-24 21:49:51 +12:00
$response
->addHeader('Expires', \date('D, d M Y H:i:s', \time() + 60 * 60 * 24 * 30) . ' GMT')
2022-07-24 21:49:51 +12:00
->setContentType('image/png')
2022-08-15 03:01:34 +12:00
->file($data)
;
2021-02-20 02:59:46 +13:00
unset($image);
2019-05-09 18:54:39 +12:00
};
2020-06-29 05:31:21 +12:00
App::get('/v1/avatars/credit-cards/:code')
2019-05-09 18:54:39 +12:00
->desc('Get Credit Card Icon')
2022-07-24 19:05:24 +12:00
->groups(['api', 'avatars'])
2019-05-09 18:54:39 +12:00
->label('scope', 'avatars.read')
2022-08-17 21:25:47 +12:00
->label('cache', true)
2022-08-16 01:55:11 +12:00
->label('cache.resource', 'avatar/credit-card')
2021-04-16 19:22:17 +12:00
->label('sdk.auth', [APP_AUTH_TYPE_SESSION, APP_AUTH_TYPE_KEY, APP_AUTH_TYPE_JWT])
2019-05-09 18:54:39 +12:00
->label('sdk.namespace', 'avatars')
->label('sdk.method', 'getCreditCard')
2020-05-18 16:26:28 +12:00
->label('sdk.methodType', 'location')
2019-10-09 21:31:51 +13:00
->label('sdk.description', '/docs/references/avatars/get-credit-card.md')
2020-11-12 10:02:24 +13:00
->label('sdk.response.code', Response::STATUS_CODE_OK)
2020-11-12 11:02:02 +13:00
->label('sdk.response.type', Response::CONTENT_TYPE_IMAGE_PNG)
2021-02-20 02:59:46 +13:00
->param('code', '', new WhiteList(\array_keys(Config::getParam('avatar-credit-cards'))), 'Credit Card Code. Possible values: ' . \implode(', ', \array_keys(Config::getParam('avatar-credit-cards'))) . '.')
2022-04-20 20:27:28 +12:00
->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)
2020-09-11 02:40:14 +12:00
->param('quality', 100, new Range(0, 100), 'Image quality. Pass an integer between 0 to 100. Defaults to 100.', true)
2020-12-27 03:59:15 +13:00
->inject('response')
2022-07-08 02:51:22 +12:00
->action(fn (string $code, int $width, int $height, int $quality, Response $response) => $avatarCallback('credit-cards', $code, $width, $height, $quality, $response));
2019-05-09 18:54:39 +12:00
2020-06-29 05:31:21 +12:00
App::get('/v1/avatars/browsers/:code')
2019-05-09 18:54:39 +12:00
->desc('Get Browser Icon')
2022-07-24 19:05:24 +12:00
->groups(['api', 'avatars'])
2019-05-09 18:54:39 +12:00
->label('scope', 'avatars.read')
2022-08-17 21:25:47 +12:00
->label('cache', true)
2022-08-16 01:55:11 +12:00
->label('cache.resource', 'avatar/browser')
2021-04-16 19:22:17 +12:00
->label('sdk.auth', [APP_AUTH_TYPE_SESSION, APP_AUTH_TYPE_KEY, APP_AUTH_TYPE_JWT])
2019-05-09 18:54:39 +12:00
->label('sdk.namespace', 'avatars')
->label('sdk.method', 'getBrowser')
->label('sdk.methodType', 'location')
2019-10-08 20:09:35 +13:00
->label('sdk.description', '/docs/references/avatars/get-browser.md')
2020-11-12 10:02:24 +13:00
->label('sdk.response.code', Response::STATUS_CODE_OK)
2020-11-12 11:02:02 +13:00
->label('sdk.response.type', Response::CONTENT_TYPE_IMAGE_PNG)
2020-09-11 02:40:14 +12:00
->param('code', '', new WhiteList(\array_keys(Config::getParam('avatar-browsers'))), 'Browser Code.')
2022-04-20 20:27:28 +12:00
->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)
2020-09-11 02:40:14 +12:00
->param('quality', 100, new Range(0, 100), 'Image quality. Pass an integer between 0 to 100. Defaults to 100.', true)
2020-12-27 03:59:15 +13:00
->inject('response')
2022-07-08 02:51:22 +12:00
->action(fn (string $code, int $width, int $height, int $quality, Response $response) => $avatarCallback('browsers', $code, $width, $height, $quality, $response));
2019-05-09 18:54:39 +12:00
2020-06-29 05:31:21 +12:00
App::get('/v1/avatars/flags/:code')
2019-05-09 18:54:39 +12:00
->desc('Get Country Flag')
2022-07-24 19:05:24 +12:00
->groups(['api', 'avatars'])
2019-05-09 18:54:39 +12:00
->label('scope', 'avatars.read')
2022-08-17 21:25:47 +12:00
->label('cache', true)
2022-08-16 01:55:11 +12:00
->label('cache.resource', 'avatar/flag')
2021-04-16 19:22:17 +12:00
->label('sdk.auth', [APP_AUTH_TYPE_SESSION, APP_AUTH_TYPE_KEY, APP_AUTH_TYPE_JWT])
2019-05-09 18:54:39 +12:00
->label('sdk.namespace', 'avatars')
->label('sdk.method', 'getFlag')
2020-05-18 16:26:28 +12:00
->label('sdk.methodType', 'location')
2019-10-08 20:09:35 +13:00
->label('sdk.description', '/docs/references/avatars/get-flag.md')
2020-11-12 10:02:24 +13:00
->label('sdk.response.code', Response::STATUS_CODE_OK)
2020-11-12 11:02:02 +13:00
->label('sdk.response.type', Response::CONTENT_TYPE_IMAGE_PNG)
2020-09-11 02:40:14 +12:00
->param('code', '', new WhiteList(\array_keys(Config::getParam('avatar-flags'))), 'Country Code. ISO Alpha-2 country code format.')
2022-04-20 20:31:12 +12:00
->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)
2020-09-11 02:40:14 +12:00
->param('quality', 100, new Range(0, 100), 'Image quality. Pass an integer between 0 to 100. Defaults to 100.', true)
2020-12-27 03:59:15 +13:00
->inject('response')
2022-07-08 02:51:22 +12:00
->action(fn (string $code, int $width, int $height, int $quality, Response $response) => $avatarCallback('flags', $code, $width, $height, $quality, $response));
2019-05-09 18:54:39 +12:00
2020-06-29 05:31:21 +12:00
App::get('/v1/avatars/image')
2019-08-24 02:16:25 +12:00
->desc('Get Image from URL')
2020-06-26 06:32:12 +12:00
->groups(['api', 'avatars'])
->label('scope', 'avatars.read')
2022-08-17 21:25:47 +12:00
->label('cache', true)
2022-08-16 01:55:11 +12:00
->label('cache.resource', 'avatar/image')
2021-04-16 19:22:17 +12:00
->label('sdk.auth', [APP_AUTH_TYPE_SESSION, APP_AUTH_TYPE_KEY, APP_AUTH_TYPE_JWT])
->label('sdk.namespace', 'avatars')
->label('sdk.method', 'getImage')
2020-05-18 16:26:28 +12:00
->label('sdk.methodType', 'location')
2019-10-08 20:09:35 +13:00
->label('sdk.description', '/docs/references/avatars/get-image.md')
2020-11-12 10:02:24 +13:00
->label('sdk.response.code', Response::STATUS_CODE_OK)
2020-11-12 11:02:02 +13:00
->label('sdk.response.type', Response::CONTENT_TYPE_IMAGE)
2022-02-17 04:16:37 +13:00
->param('url', '', new URL(['http', 'https']), 'Image URL which you want to crop.')
2022-04-20 20:31:12 +12:00
->param('width', 400, new Range(0, 2000), 'Resize preview image width, Pass an integer between 0 to 2000. Defaults to 400.', true)
->param('height', 400, new Range(0, 2000), 'Resize preview image height, Pass an integer between 0 to 2000. Defaults to 400.', true)
2020-12-27 03:59:15 +13:00
->inject('response')
2022-07-08 02:51:22 +12:00
->action(function (string $url, int $width, int $height, Response $response) {
2020-06-30 09:43:34 +12:00
$quality = 80;
$output = 'png';
$type = 'png';
2020-06-30 09:43:34 +12:00
if (!\extension_loaded('imagick')) {
throw new Exception(Exception::GENERAL_SERVER_ERROR, 'Imagick extension is missing');
2020-06-30 09:43:34 +12:00
}
2020-06-30 09:43:34 +12:00
$fetch = @\file_get_contents($url, false);
2020-06-30 09:43:34 +12:00
if (!$fetch) {
throw new Exception(Exception::AVATAR_IMAGE_NOT_FOUND);
2020-06-30 09:43:34 +12:00
}
2020-06-30 09:43:34 +12:00
try {
2021-02-20 02:59:46 +13:00
$image = new Image($fetch);
2022-05-09 03:10:56 +12:00
} catch (\Exception $exception) {
throw new Exception(Exception::GENERAL_SERVER_ERROR, 'Unable to parse image');
2020-06-30 09:43:34 +12:00
}
2021-02-20 02:59:46 +13:00
$image->crop((int) $width, (int) $height);
2020-06-30 09:43:34 +12:00
$output = (empty($output)) ? $type : $output;
2021-02-20 02:59:46 +13:00
$data = $image->output($output, $quality);
2022-07-24 21:49:51 +12:00
$response
->addHeader('Expires', \date('D, d M Y H:i:s', \time() + 60 * 60 * 24 * 30) . ' GMT')
2022-07-24 21:49:51 +12:00
->setContentType('image/png')
2022-08-15 03:01:34 +12:00
->file($data)
;
2021-02-20 02:59:46 +13:00
unset($image);
2020-12-27 03:59:15 +13:00
});
2020-06-29 05:31:21 +12:00
App::get('/v1/avatars/favicon')
2019-05-09 18:54:39 +12:00
->desc('Get Favicon')
2022-07-24 19:05:24 +12:00
->groups(['api', 'avatars'])
2019-05-09 18:54:39 +12:00
->label('scope', 'avatars.read')
2022-08-17 21:25:47 +12:00
->label('cache', true)
2022-08-16 01:55:11 +12:00
->label('cache.resource', 'avatar/favicon')
2021-04-16 19:22:17 +12:00
->label('sdk.auth', [APP_AUTH_TYPE_SESSION, APP_AUTH_TYPE_KEY, APP_AUTH_TYPE_JWT])
2019-05-09 18:54:39 +12:00
->label('sdk.namespace', 'avatars')
->label('sdk.method', 'getFavicon')
2020-05-18 16:26:28 +12:00
->label('sdk.methodType', 'location')
2019-10-08 20:09:35 +13:00
->label('sdk.description', '/docs/references/avatars/get-favicon.md')
2020-11-12 10:02:24 +13:00
->label('sdk.response.code', Response::STATUS_CODE_OK)
2020-11-12 11:02:02 +13:00
->label('sdk.response.type', Response::CONTENT_TYPE_IMAGE)
2022-02-17 04:16:37 +13:00
->param('url', '', new URL(['http', 'https']), 'Website URL which you want to fetch the favicon from.')
2020-12-27 03:59:15 +13:00
->inject('response')
2022-07-08 02:51:22 +12:00
->action(function (string $url, Response $response) {
2020-06-30 09:43:34 +12:00
$width = 56;
$height = 56;
$quality = 80;
$output = 'png';
$type = 'png';
2019-05-09 18:54:39 +12:00
2020-06-30 09:43:34 +12:00
if (!\extension_loaded('imagick')) {
throw new Exception(Exception::GENERAL_SERVER_ERROR, 'Imagick extension is missing');
2020-06-30 09:43:34 +12:00
}
2019-05-09 18:54:39 +12:00
2020-06-30 09:43:34 +12:00
$curl = \curl_init();
2019-05-09 18:54:39 +12:00
2020-06-30 09:43:34 +12:00
\curl_setopt_array($curl, [
CURLOPT_RETURNTRANSFER => 1,
CURLOPT_FOLLOWLOCATION => true,
CURLOPT_MAXREDIRS => 3,
CURLOPT_URL => $url,
2022-05-09 03:10:56 +12:00
CURLOPT_USERAGENT => \sprintf(
APP_USERAGENT,
2020-06-30 23:09:28 +12:00
App::getEnv('_APP_VERSION', 'UNKNOWN'),
2020-06-30 09:43:34 +12:00
App::getEnv('_APP_SYSTEM_SECURITY_EMAIL_ADDRESS', APP_EMAIL_SECURITY)
),
]);
2019-05-09 18:54:39 +12:00
2020-06-30 09:43:34 +12:00
$html = \curl_exec($curl);
2019-05-09 18:54:39 +12:00
2020-06-30 09:43:34 +12:00
\curl_close($curl);
2019-05-09 18:54:39 +12:00
2020-06-30 09:43:34 +12:00
if (!$html) {
throw new Exception(Exception::AVATAR_REMOTE_URL_FAILED);
2020-06-30 09:43:34 +12:00
}
2019-05-09 18:54:39 +12:00
2020-06-30 09:43:34 +12:00
$doc = new DOMDocument();
$doc->strictErrorChecking = false;
@$doc->loadHTML($html);
$links = $doc->getElementsByTagName('link');
$outputHref = '';
$outputExt = '';
$space = 0;
foreach ($links as $link) { /* @var $link DOMElement */
$href = $link->getAttribute('href');
$rel = $link->getAttribute('rel');
$sizes = $link->getAttribute('sizes');
$absolute = URLParse::unparse(\array_merge(\parse_url($url), \parse_url($href)));
switch (\strtolower($rel)) {
case 'icon':
case 'shortcut icon':
//case 'apple-touch-icon':
$ext = \pathinfo(\parse_url($absolute, PHP_URL_PATH), PATHINFO_EXTENSION);
switch ($ext) {
case 'ico':
case 'png':
case 'jpg':
case 'jpeg':
$size = \explode('x', \strtolower($sizes));
2020-10-15 10:34:57 +13:00
$sizeWidth = (int) $size[0] ?? 0;
$sizeHeight = (int) $size[1] ?? 0;
2020-06-30 09:43:34 +12:00
if (($sizeWidth * $sizeHeight) >= $space) {
$space = $sizeWidth * $sizeHeight;
$outputHref = $absolute;
$outputExt = $ext;
}
break;
}
2020-06-30 09:43:34 +12:00
break;
2019-05-09 18:54:39 +12:00
}
2020-06-30 09:43:34 +12:00
}
2019-05-09 18:54:39 +12:00
2020-06-30 09:43:34 +12:00
if (empty($outputHref) || empty($outputExt)) {
$default = \parse_url($url);
2019-05-09 18:54:39 +12:00
2021-02-20 02:59:46 +13:00
$outputHref = $default['scheme'] . '://' . $default['host'] . '/favicon.ico';
2020-06-30 09:43:34 +12:00
$outputExt = 'ico';
}
2019-05-09 18:54:39 +12:00
2020-06-30 09:43:34 +12:00
if ('ico' == $outputExt) { // Skip crop, Imagick isn\'t supporting icon files
$data = @\file_get_contents($outputHref, false);
2019-05-09 18:54:39 +12:00
2020-06-30 09:43:34 +12:00
if (empty($data) || (\mb_substr($data, 0, 5) === '<html') || \mb_substr($data, 0, 5) === '<!doc') {
2022-08-14 18:56:12 +12:00
throw new Exception(Exception::AVATAR_ICON_NOT_FOUND, 'Favicon not found');
2019-05-09 18:54:39 +12:00
}
2022-07-27 00:50:33 +12:00
$response
2022-07-31 06:55:36 +12:00
->addHeader('Expires', \date('D, d M Y H:i:s', \time() + 60 * 60 * 24 * 30) . ' GMT')
2022-07-27 00:50:33 +12:00
->setContentType('image/x-icon')
2022-08-17 21:25:47 +12:00
->file($data)
2022-07-27 00:50:33 +12:00
;
2020-06-30 09:43:34 +12:00
}
2019-05-09 18:54:39 +12:00
2020-06-30 09:43:34 +12:00
$fetch = @\file_get_contents($outputHref, false);
2019-05-09 18:54:39 +12:00
2020-06-30 09:43:34 +12:00
if (!$fetch) {
throw new Exception(Exception::AVATAR_ICON_NOT_FOUND);
2020-06-30 09:43:34 +12:00
}
2019-05-09 18:54:39 +12:00
2021-02-20 02:59:46 +13:00
$image = new Image($fetch);
$image->crop((int) $width, (int) $height);
2020-06-30 09:43:34 +12:00
$output = (empty($output)) ? $type : $output;
2021-02-20 02:59:46 +13:00
$data = $image->output($output, $quality);
2020-06-30 09:43:34 +12:00
2022-07-24 21:49:51 +12:00
$response
->addHeader('Expires', \date('D, d M Y H:i:s', \time() + 60 * 60 * 24 * 30) . ' GMT')
2022-07-24 21:49:51 +12:00
->setContentType('image/png')
2022-08-15 03:01:34 +12:00
->file($data)
;
2021-02-20 02:59:46 +13:00
unset($image);
2020-12-27 03:59:15 +13:00
});
2019-05-09 18:54:39 +12:00
2020-06-29 05:31:21 +12:00
App::get('/v1/avatars/qr')
2019-11-28 06:24:36 +13:00
->desc('Get QR Code')
2020-06-26 06:32:12 +12:00
->groups(['api', 'avatars'])
2019-05-09 18:54:39 +12:00
->label('scope', 'avatars.read')
2021-04-16 19:22:17 +12:00
->label('sdk.auth', [APP_AUTH_TYPE_SESSION, APP_AUTH_TYPE_KEY, APP_AUTH_TYPE_JWT])
2019-05-09 18:54:39 +12:00
->label('sdk.namespace', 'avatars')
->label('sdk.method', 'getQR')
2020-05-18 16:26:28 +12:00
->label('sdk.methodType', 'location')
2019-10-08 20:09:35 +13:00
->label('sdk.description', '/docs/references/avatars/get-qr.md')
2020-11-12 10:02:24 +13:00
->label('sdk.response.code', Response::STATUS_CODE_OK)
2020-11-12 11:02:02 +13:00
->label('sdk.response.type', Response::CONTENT_TYPE_IMAGE_PNG)
2020-09-11 02:40:14 +12:00
->param('text', '', new Text(512), 'Plain text to be converted to QR code image.')
2022-04-12 23:36:03 +12:00
->param('size', 400, new Range(1, 1000), 'QR code size. Pass an integer between 1 to 1000. Defaults to 400.', true)
2020-09-11 02:40:14 +12:00
->param('margin', 1, new Range(0, 10), 'Margin from edge. Pass an integer between 0 to 10. Defaults to 1.', true)
->param('download', false, new Boolean(true), 'Return resulting image with \'Content-Disposition: attachment \' headers for the browser to start downloading it. Pass 0 for no header, or 1 for otherwise. Default value is set to 0.', true)
2020-12-27 03:59:15 +13:00
->inject('response')
2022-05-09 03:10:56 +12:00
->action(function (string $text, int $size, int $margin, bool $download, Response $response) {
2020-06-30 09:43:34 +12:00
$download = ($download === '1' || $download === 'true' || $download === 1 || $download === true);
2020-10-27 13:12:35 +13:00
$options = new QROptions([
'addQuietzone' => true,
'quietzoneSize' => $margin,
'outputType' => QRCode::OUTPUT_IMAGICK,
2020-10-23 07:50:57 +13:00
]);
2020-10-27 13:12:35 +13:00
$qrcode = new QRCode($options);
2019-05-09 18:54:39 +12:00
2020-06-30 09:43:34 +12:00
if ($download) {
$response->addHeader('Content-Disposition', 'attachment; filename="qr.png"');
2020-06-10 07:48:26 +12:00
}
2020-06-30 09:43:34 +12:00
2021-02-20 02:59:46 +13:00
$image = new Image($qrcode->render($text));
$image->crop((int) $size, (int) $size);
2021-01-10 13:17:44 +13:00
2020-06-30 09:43:34 +12:00
$response
2022-07-27 00:50:33 +12:00
->addHeader('Expires', \date('D, d M Y H:i:s', \time() + (60 * 60 * 24 * 45)) . ' GMT') // 45 days cache
2020-06-30 09:43:34 +12:00
->setContentType('image/png')
2022-08-18 02:57:56 +12:00
->send($image->output('png', 9))
;
2020-12-27 03:59:15 +13:00
});
2020-06-10 07:48:26 +12:00
2020-06-29 05:31:21 +12:00
App::get('/v1/avatars/initials')
2020-06-10 07:48:26 +12:00
->desc('Get User Initials')
2020-06-26 06:32:12 +12:00
->groups(['api', 'avatars'])
2020-06-10 07:48:26 +12:00
->label('scope', 'avatars.read')
2022-08-17 21:25:47 +12:00
->label('cache', true)
2022-08-16 01:55:11 +12:00
->label('cache.resource', 'avatar/initials')
2021-04-16 19:22:17 +12:00
->label('sdk.auth', [APP_AUTH_TYPE_SESSION, APP_AUTH_TYPE_KEY, APP_AUTH_TYPE_JWT])
2020-06-10 07:48:26 +12:00
->label('sdk.namespace', 'avatars')
->label('sdk.method', 'getInitials')
->label('sdk.methodType', 'location')
->label('sdk.description', '/docs/references/avatars/get-initials.md')
2020-11-12 10:02:24 +13:00
->label('sdk.response.code', Response::STATUS_CODE_OK)
2020-11-12 11:02:02 +13:00
->label('sdk.response.type', Response::CONTENT_TYPE_IMAGE_PNG)
2020-09-11 02:40:14 +12:00
->param('name', '', new Text(128), 'Full Name. When empty, current user name or email will be used. Max length: 128 chars.', true)
2022-04-20 20:27:28 +12:00
->param('width', 500, new Range(0, 2000), 'Image width. Pass an integer between 0 to 2000. Defaults to 100.', true)
->param('height', 500, new Range(0, 2000), 'Image height. Pass an integer between 0 to 2000. Defaults to 100.', true)
2020-09-11 02:40:14 +12:00
->param('background', '', new HexColor(), 'Changes background color. By default a random color will be picked and stay will persistent to the given name.', true)
2020-12-27 03:59:15 +13:00
->inject('response')
->inject('user')
2022-09-05 21:36:01 +12:00
->action(function (string $name, int $width, int $height, string $background, Response $response, Document $user) {
2020-06-30 09:43:34 +12:00
$themes = [
2022-09-09 23:09:04 +12:00
['background' => '#FFA1CE'], // Default (Pink)
['background' => '#FDC584'], // Orange
['background' => '#94DBD1'], // Green
['background' => '#A1C4FF'], // Blue
['background' => '#FFA1CE'], // Pink
['background' => '#CBB1FC'] // Purple
2020-06-30 09:43:34 +12:00
];
$name = (!empty($name)) ? $name : $user->getAttribute('name', $user->getAttribute('email', ''));
$words = \explode(' ', \strtoupper($name));
2021-07-26 00:13:49 +12:00
// if there is no space, try to split by `_` underscore
2022-05-09 03:10:56 +12:00
$words = (count($words) == 1) ? \explode('_', \strtoupper($name)) : $words;
2020-06-30 09:43:34 +12:00
$initials = null;
$code = 0;
foreach ($words as $key => $w) {
2020-10-15 10:34:57 +13:00
$initials .= $w[0] ?? '';
2020-06-30 09:43:34 +12:00
$code += (isset($w[0])) ? \ord($w[0]) : 0;
if ($key == 1) {
break;
2020-06-10 07:48:26 +12:00
}
2020-06-30 09:43:34 +12:00
}
2020-06-10 07:48:26 +12:00
2021-02-20 02:59:46 +13:00
$rand = \substr($code, -1);
2022-09-05 21:36:01 +12:00
// Wrap rand value to avoid out of range
$rand = ($rand > \count($themes) - 1) ? $rand % \count($themes) : $rand;
2021-02-20 02:59:46 +13:00
$background = (!empty($background)) ? '#' . $background : $themes[$rand]['background'];
2020-06-30 09:43:34 +12:00
$image = new \Imagick();
$punch = new \Imagick();
2020-06-30 09:43:34 +12:00
$draw = new \ImagickDraw();
$fontSize = \min($width, $height) / 2;
2021-02-20 02:59:46 +13:00
$punch->newImage($width, $height, 'transparent');
2021-02-20 02:59:46 +13:00
$draw->setFont(__DIR__ . "/../../../public/fonts/poppins-v9-latin-500.ttf");
$image->setFont(__DIR__ . "/../../../public/fonts/poppins-v9-latin-500.ttf");
2020-06-30 09:43:34 +12:00
$draw->setFillColor(new ImagickPixel('black'));
2020-06-30 09:43:34 +12:00
$draw->setFontSize($fontSize);
2021-02-20 02:59:46 +13:00
2020-06-30 09:43:34 +12:00
$draw->setTextAlignment(\Imagick::ALIGN_CENTER);
$draw->annotation($width / 1.97, ($height / 2) + ($fontSize / 3), $initials);
2021-02-20 02:59:46 +13:00
$punch->drawImage($draw);
$punch->negateImage(true, Imagick::CHANNEL_ALPHA);
2020-06-30 09:43:34 +12:00
$image->newImage($width, $height, $background);
$image->setImageFormat("png");
$image->compositeImage($punch, Imagick::COMPOSITE_COPYOPACITY, 0, 0);
2020-06-30 09:43:34 +12:00
//$image->setImageCompressionQuality(9 - round(($quality / 100) * 9));
2020-06-10 07:48:26 +12:00
2020-06-30 09:43:34 +12:00
$response
2021-02-20 02:59:46 +13:00
->addHeader('Expires', \date('D, d M Y H:i:s', \time() + (60 * 60 * 24 * 45)) . ' GMT') // 45 days cache
2020-06-30 09:43:34 +12:00
->setContentType('image/png')
2022-08-15 03:01:34 +12:00
->file($image->getImageBlob())
;
2020-12-27 03:59:15 +13:00
});