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 )) {
2022-07-27 02:24:32 +12:00
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 )) {
2022-07-27 02:24:32 +12:00
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' )) {
2022-07-27 02:24:32 +12:00
throw new Exception ( Exception :: GENERAL_SERVER_ERROR , 'Imagick extension is missing' );
2019-05-09 18:54:39 +12:00
}
2019-09-07 05:10:41 +12:00
$output = 'png' ;
2020-06-27 17:36:22 +12:00
$path = $set [ $code ];
2019-09-07 05:10:41 +12:00
$type = 'png' ;
2019-05-09 18:54:39 +12:00
2020-06-20 23:20:49 +12:00
if ( ! \is_readable ( $path )) {
2022-07-27 02:24:32 +12:00
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
2022-07-29 03:24:18 +12:00
-> 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 )
2022-07-29 03:24:18 +12:00
;
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' )
2020-05-25 15:36:10 +12:00
-> 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' ])
2019-07-10 08:20: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/image' )
2021-04-16 19:22:17 +12:00
-> label ( 'sdk.auth' , [ APP_AUTH_TYPE_SESSION , APP_AUTH_TYPE_KEY , APP_AUTH_TYPE_JWT ])
2019-07-10 08:20:39 +12:00
-> 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' ;
2022-07-24 05:42:42 +12:00
2020-06-30 09:43:34 +12:00
if ( ! \extension_loaded ( 'imagick' )) {
2022-07-27 02:24:32 +12:00
throw new Exception ( Exception :: GENERAL_SERVER_ERROR , 'Imagick extension is missing' );
2020-06-30 09:43:34 +12:00
}
2019-07-10 08:20:39 +12:00
2020-06-30 09:43:34 +12:00
$fetch = @ \file_get_contents ( $url , false );
2019-07-10 08:20:39 +12:00
2020-06-30 09:43:34 +12:00
if ( ! $fetch ) {
2022-07-27 02:24:32 +12:00
throw new Exception ( Exception :: AVATAR_IMAGE_NOT_FOUND );
2020-06-30 09:43:34 +12:00
}
2019-07-10 08:20:39 +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 ) {
2022-07-27 02:24:32 +12:00
throw new Exception ( Exception :: GENERAL_SERVER_ERROR , 'Unable to parse image' );
2020-06-30 09:43:34 +12:00
}
2019-07-10 08:20:39 +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
2022-07-29 03:24:18 +12:00
-> 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 )
2022-07-29 03:24:18 +12:00
;
2021-02-20 02:59:46 +13:00
unset ( $image );
2020-12-27 03:59:15 +13:00
});
2019-07-10 08:20:39 +12: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' )) {
2022-07-27 02:24:32 +12:00
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 ) {
2022-07-27 02:24:32 +12:00
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 ));
2022-11-10 00:45:15 +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 ;
}
2019-07-07 07:43:45 +12:00
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 ) {
2022-07-27 02:24:32 +12:00
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
2022-07-29 03:24:18 +12:00
-> 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 )
2022-07-29 03:24:18 +12:00
;
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-21 23:56:42 +12:00
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 ([
2021-01-10 13:07:58 +13:00
'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 ))
2022-07-29 03:24:18 +12:00
;
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)
2022-09-05 21:24:56 +12:00
[ '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 ();
2022-09-05 21:24:56 +12:00
$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
2022-09-05 21:24:56 +12: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
2022-09-05 21:24:56 +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
2022-09-05 21:24:56 +12: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 " );
2022-09-05 21:24:56 +12:00
$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 ())
2022-07-29 03:24:18 +12:00
;
2020-12-27 03:59:15 +13:00
});