. * * The interactive user interfaces in modified source and object code versions * of this program must display Appropriate Legal Notices, as required under * Section 5 of the GNU Affero General Public License version 3. * * In accordance with Section 7(b) of the GNU Affero General Public License version 3, * these Appropriate Legal Notices must retain the display of the "EspoCRM" word. ************************************************************************/ namespace Espo\EntryPoints; use Espo\Core\Exceptions\BadRequest; use Espo\Core\Exceptions\Error; use Espo\Core\Api\Request; use Espo\Core\Api\Response; use Espo\Core\Exceptions\ForbiddenSilent; use Espo\Core\Exceptions\NotFound; use Espo\Core\Exceptions\NotFoundSilent; use Espo\Core\Utils\SystemUser; use Espo\Entities\User; use LasseRafn\InitialAvatarGenerator\InitialAvatar; /** * @noinspection PhpUnused */ class Avatar extends Image { protected string $systemColor = '#a4b5bd'; /** @var string[] */ protected $colorList = [ '#6fa8d6', '#edc555', '#d4729b', '#8093BD', '#7cc4a4', '#8a7cc2', '#de6666', '#ABE3A1', '#E8AF64', ]; private function getColor(User $user): string { if ($user->getUserName() === SystemUser::NAME) { return $this->metadata->get(['app', 'avatars', 'systemColor']) ?? $this->systemColor; } $hash = $user->getId(); $length = strlen($hash); $sum = 0; for ($i = 0; $i < $length; $i++) { $sum += ord($hash[$i]); } $x = $sum % 128 + 1; $colorList = $this->metadata->get(['app', 'avatars', 'colorList']) ?? $this->colorList; if ($x === 128) { $x--; } $index = intval($x * count($colorList) / 128); return $colorList[$index]; } /** * @throws BadRequest * @throws Error * @throws NotFoundSilent * @throws ForbiddenSilent * @throws NotFound */ public function run(Request $request, Response $response): void { $userId = $request->getQueryParam('id'); $size = $request->getQueryParam('size') ?? 'small'; if (!$userId) { throw new BadRequest(); } $user = $this->entityManager->getRDBRepositoryByClass(User::class)->getById( $userId); if (!$user) { $this->renderBlank($response); return; } if ($user->getAvatarId()) { $this->show($response, $user->getAvatarId(), $size, true); return; } $sizes = $this->getSizes()[$size]; if (empty($sizes)) { $this->renderBlank($response); return; } $width = $sizes[0]; $color = $this->getColor($user); $image = (new InitialAvatar()) ->name($user->getName() ?? $user->getUserName() ?? $userId) ->width($width) ->height($width) ->color('#FFF') ->background($color) ->fontSize() ->generate(); $response ->setHeader('Cache-Control', 'max-age=360000, must-revalidate') ->setHeader('Content-Type', 'image/png'); $response->writeBody($image->stream('png', 100)); } /** * @throws Error */ private function renderBlank(Response $response): void { ob_start(); $img = imagecreatetruecolor(14, 14); if ($img === false) { throw new Error(); } imagesavealpha($img, true); $color = imagecolorallocatealpha($img, 127, 127, 127, 127); if ($color === false) { throw new Error(); } imagefill($img, 0, 0, $color); imagepng($img); imagecolordeallocate($img, $color); $contents = ob_get_contents(); if ($contents === false) { throw new Error(); } ob_end_clean(); imagedestroy($img); $response ->setHeader('Content-Type', 'image/png') ->writeBody($contents); } }