This commit is contained in:
Yuri Kuznetsov
2024-03-15 14:54:02 +02:00
parent 9e60ea2209
commit 3ef24bb5ad
9 changed files with 419 additions and 103 deletions
+5
View File
@@ -267,6 +267,11 @@ class User extends Person
return $value; return $value;
} }
public function getAvatarId(): ?string
{
return $this->get('avatarId');
}
/** /**
* @return ?string * @return ?string
*/ */
+38 -38
View File
@@ -36,33 +36,39 @@ use Espo\Core\Api\Response;
use Espo\Core\Exceptions\ForbiddenSilent; use Espo\Core\Exceptions\ForbiddenSilent;
use Espo\Core\Exceptions\NotFound; use Espo\Core\Exceptions\NotFound;
use Espo\Core\Exceptions\NotFoundSilent; use Espo\Core\Exceptions\NotFoundSilent;
use Espo\Core\Utils\SystemUser; use Espo\Core\Utils\SystemUser;
use Espo\Entities\User; use Espo\Entities\User;
use Identicon\Identicon;
use LasseRafn\InitialAvatarGenerator\InitialAvatar;
/**
* @noinspection PhpUnused
*/
class Avatar extends Image class Avatar extends Image
{ {
protected string $systemColor = '#a4b5bd'; protected string $systemColor = '#a4b5bd';
/** @var array<int, string|array{int, int, int}> */ /** @var string[] */
protected $colorList = [ protected $colorList = [
[111, 168, 214], '#6fa8d6',
[237, 197, 85], '#edc555',
[212, 114, 155], '#d4729b',
'#8093BD', '#8093BD',
[124, 196, 164], '#7cc4a4',
[138, 124, 194], '#8a7cc2',
[222, 102, 102], '#de6666',
'#ABE3A1', '#ABE3A1',
'#E8AF64', '#E8AF64',
]; ];
/** private function getColor(User $user): string
* @return string|array{int, int, int}
*/
private function getColor(string $hash)
{ {
if ($user->getUserName() === SystemUser::NAME) {
return $this->metadata->get(['app', 'avatars', 'systemColor']) ?? $this->systemColor;
}
$hash = $user->getId();
$length = strlen($hash); $length = strlen($hash);
$sum = 0; $sum = 0;
@@ -94,14 +100,13 @@ class Avatar extends Image
public function run(Request $request, Response $response): void public function run(Request $request, Response $response): void
{ {
$userId = $request->getQueryParam('id'); $userId = $request->getQueryParam('id');
$size = $request->getQueryParam('size') ?? null; $size = $request->getQueryParam('size') ?? 'small';
if (!$userId) { if (!$userId) {
throw new BadRequest(); throw new BadRequest();
} }
/** @var ?User $user */ $user = $this->entityManager->getRDBRepositoryByClass(User::class)->getById( $userId);
$user = $this->entityManager->getEntityById(User::ENTITY_TYPE, $userId);
if (!$user) { if (!$user) {
$this->renderBlank($response); $this->renderBlank($response);
@@ -109,43 +114,38 @@ class Avatar extends Image
return; return;
} }
$id = $user->get('avatarId'); if ($user->getAvatarId()) {
$this->show($response, $user->getAvatarId(), $size, true);
if ($id) {
$this->show($response, $id, $size, true);
return; return;
} }
$identicon = new Identicon(); $sizes = $this->getSizes()[$size];
if (!$size) { if (empty($sizes)) {
$size = 'small';
}
if (empty($this->getSizes()[$size])) {
$this->renderBlank($response); $this->renderBlank($response);
return; return;
} }
$width = $this->getSizes()[$size][0]; $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()
//->preferBold()
->generate();
$response $response
->setHeader('Cache-Control', 'max-age=360000, must-revalidate') ->setHeader('Cache-Control', 'max-age=360000, must-revalidate')
->setHeader('Content-Type', 'image/png'); ->setHeader('Content-Type', 'image/png');
$hash = $userId; $response->writeBody($image->stream('png', 100));
$color = $this->getColor($userId);
if ($user->getUserName() === SystemUser::NAME) {
$color = $this->metadata->get(['app', 'avatars', 'systemColor']) ?? $this->systemColor;
}
$imgContent = $identicon->getImageData($hash, $width, $color);
$response->writeBody($imgContent);
} }
/** /**
@@ -49,7 +49,7 @@ define('crm:views/meeting/fields/users', ['crm:views/meeting/fields/attendees'],
}, },
getIconHtml: function (id) { getIconHtml: function (id) {
let iconHtml = this.getHelper().getAvatarHtml(id, 'small', 14, 'avatar-link'); let iconHtml = this.getHelper().getAvatarHtml(id, 'small', 16, 'avatar-link');
if (iconHtml) { if (iconHtml) {
iconHtml += ' '; iconHtml += ' ';
+1 -1
View File
@@ -54,7 +54,7 @@ class AssignedUsersFieldView extends LinkMultipleFieldView {
let html = super.getDetailLinkHtml(id); let html = super.getDetailLinkHtml(id);
let avatarHtml = this.isDetailMode() ? let avatarHtml = this.isDetailMode() ?
this.getHelper().getAvatarHtml(id, 'small', 14, 'avatar-link') : ''; this.getHelper().getAvatarHtml(id, 'small', 16, 'avatar-link') : '';
if (!avatarHtml) { if (!avatarHtml) {
return html; return html;
+1 -1
View File
@@ -45,7 +45,7 @@ class UserWithAvatarFieldView extends UserFieldView {
} }
getAvatarHtml() { getAvatarHtml() {
return this.getHelper().getAvatarHtml(this.model.get(this.idName), 'small', 14, 'avatar-link'); return this.getHelper().getAvatarHtml(this.model.get(this.idName), 'small', 16, 'avatar-link');
} }
} }
+1 -1
View File
@@ -43,7 +43,7 @@ define('views/user/fields/name', ['views/fields/person-name'], function (Dep) {
}, },
getAvatarHtml: function () { getAvatarHtml: function () {
return this.getHelper().getAvatarHtml(this.model.id, 'small', 16, 'avatar-link'); return this.getHelper().getAvatarHtml(this.model.id, 'small', 18, 'avatar-link');
}, },
}); });
}); });
+2 -2
View File
@@ -27,7 +27,6 @@
"laminas/laminas-servicemanager": "^3.22", "laminas/laminas-servicemanager": "^3.22",
"laminas/laminas-crypt": "^3.11", "laminas/laminas-crypt": "^3.11",
"monolog/monolog": "~3.5", "monolog/monolog": "~3.5",
"yzalis/identicon": "~2.0.0",
"zordius/lightncandy": "dev-espo#v1.2.5e", "zordius/lightncandy": "dev-espo#v1.2.5e",
"composer/semver": "^3", "composer/semver": "^3",
"spatie/async": "1.5.6", "spatie/async": "1.5.6",
@@ -51,7 +50,8 @@
"brick/phonenumber": "^0.5.0", "brick/phonenumber": "^0.5.0",
"picqer/php-barcode-generator": "^2.4", "picqer/php-barcode-generator": "^2.4",
"chillerlan/php-qrcode": "^4.3", "chillerlan/php-qrcode": "^4.3",
"ext-ctype": "*" "ext-ctype": "*",
"lasserafn/php-initial-avatar-generator": "^4.3"
}, },
"require-dev": { "require-dev": {
"phpunit/phpunit": "^9.5", "phpunit/phpunit": "^9.5",
Generated
+369 -58
View File
@@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically" "This file is @generated automatically"
], ],
"content-hash": "fe1e7604c6062d93a4d4ae62abcc73f6", "content-hash": "a98b5f556eaf6120fad8b36c44d060bf",
"packages": [ "packages": [
{ {
"name": "async-aws/core", "name": "async-aws/core",
@@ -1335,6 +1335,90 @@
], ],
"time": "2023-04-17T16:00:37+00:00" "time": "2023-04-17T16:00:37+00:00"
}, },
{
"name": "intervention/image",
"version": "2.7.2",
"source": {
"type": "git",
"url": "https://github.com/Intervention/image.git",
"reference": "04be355f8d6734c826045d02a1079ad658322dad"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/Intervention/image/zipball/04be355f8d6734c826045d02a1079ad658322dad",
"reference": "04be355f8d6734c826045d02a1079ad658322dad",
"shasum": ""
},
"require": {
"ext-fileinfo": "*",
"guzzlehttp/psr7": "~1.1 || ^2.0",
"php": ">=5.4.0"
},
"require-dev": {
"mockery/mockery": "~0.9.2",
"phpunit/phpunit": "^4.8 || ^5.7 || ^7.5.15"
},
"suggest": {
"ext-gd": "to use GD library based image processing.",
"ext-imagick": "to use Imagick based image processing.",
"intervention/imagecache": "Caching extension for the Intervention Image library"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "2.4-dev"
},
"laravel": {
"providers": [
"Intervention\\Image\\ImageServiceProvider"
],
"aliases": {
"Image": "Intervention\\Image\\Facades\\Image"
}
}
},
"autoload": {
"psr-4": {
"Intervention\\Image\\": "src/Intervention/Image"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Oliver Vogel",
"email": "oliver@intervention.io",
"homepage": "https://intervention.io/"
}
],
"description": "Image handling and manipulation library with support for Laravel integration",
"homepage": "http://image.intervention.io/",
"keywords": [
"gd",
"image",
"imagick",
"laravel",
"thumbnail",
"watermark"
],
"support": {
"issues": "https://github.com/Intervention/image/issues",
"source": "https://github.com/Intervention/image/tree/2.7.2"
},
"funding": [
{
"url": "https://paypal.me/interventionio",
"type": "custom"
},
{
"url": "https://github.com/Intervention",
"type": "github"
}
],
"time": "2022-05-21T17:30:32+00:00"
},
{ {
"name": "johngrogg/ics-parser", "name": "johngrogg/ics-parser",
"version": "v3.0.0", "version": "v3.0.0",
@@ -2082,6 +2166,167 @@
}, },
"time": "2022-09-08T13:45:54+00:00" "time": "2022-09-08T13:45:54+00:00"
}, },
{
"name": "lasserafn/php-initial-avatar-generator",
"version": "4.3",
"source": {
"type": "git",
"url": "https://github.com/LasseRafn/php-initial-avatar-generator.git",
"reference": "ffe43d8df3f18646d7b23011272cce2d71400e1f"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/LasseRafn/php-initial-avatar-generator/zipball/ffe43d8df3f18646d7b23011272cce2d71400e1f",
"reference": "ffe43d8df3f18646d7b23011272cce2d71400e1f",
"shasum": ""
},
"require": {
"ext-json": "*",
"intervention/image": "^2.3",
"lasserafn/php-initials": "^3.0",
"lasserafn/php-string-script-language": "^0.4",
"meyfa/php-svg": "^0.9.0",
"overtrue/pinyin": "^4.0",
"php": "^7.0|^7.1|^7.2|^7.3|^7.4|^8.0|^8.1|^8.2"
},
"require-dev": {
"phpunit/phpunit": "^8.5"
},
"type": "library",
"autoload": {
"psr-4": {
"LasseRafn\\InitialAvatarGenerator\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Lasse Rafn",
"email": "lasserafn@gmail.com"
}
],
"description": "A package to generate avatars with initials for PHP",
"keywords": [
"Initials",
"avatar",
"image",
"svg"
],
"support": {
"issues": "https://github.com/LasseRafn/php-initial-avatar-generator/issues",
"source": "https://github.com/LasseRafn/php-initial-avatar-generator/tree/4.3"
},
"funding": [
{
"url": "https://opencollective.com/ui-avatars",
"type": "open_collective"
}
],
"time": "2023-07-26T19:17:56+00:00"
},
{
"name": "lasserafn/php-initials",
"version": "3.1",
"source": {
"type": "git",
"url": "https://github.com/LasseRafn/php-initials.git",
"reference": "d287e1542687390eb68de779949bc0adc49e2d52"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/LasseRafn/php-initials/zipball/d287e1542687390eb68de779949bc0adc49e2d52",
"reference": "d287e1542687390eb68de779949bc0adc49e2d52",
"shasum": ""
},
"require": {
"php": "^5.6|^7.0|^7.1|^8.0"
},
"require-dev": {
"phpunit/phpunit": "^5.7",
"satooshi/php-coveralls": "^1.0"
},
"type": "library",
"autoload": {
"psr-4": {
"LasseRafn\\Initials\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Lasse Rafn",
"email": "lasserafn@gmail.com"
}
],
"description": "A package to generate initials in PHP",
"keywords": [
"Initials",
"php"
],
"support": {
"issues": "https://github.com/LasseRafn/php-initials/issues",
"source": "https://github.com/LasseRafn/php-initials/tree/3.1"
},
"time": "2020-12-24T12:25:51+00:00"
},
{
"name": "lasserafn/php-string-script-language",
"version": "0.4",
"source": {
"type": "git",
"url": "https://github.com/LasseRafn/php-string-script-language.git",
"reference": "cab5612d4382067de855fcecc7c09108dca77fb5"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/LasseRafn/php-string-script-language/zipball/cab5612d4382067de855fcecc7c09108dca77fb5",
"reference": "cab5612d4382067de855fcecc7c09108dca77fb5",
"shasum": ""
},
"require": {
"php": "^5.6|^7.0|^7.1|^8.0|^8.1|^8.2"
},
"require-dev": {
"doctrine/instantiator": "1.0.5",
"phpunit/phpunit": "^5.6",
"phpunit/phpunit-mock-objects": "3.2.4",
"satooshi/php-coveralls": "^1.0",
"sebastian/exporter": "^1.2"
},
"type": "library",
"autoload": {
"psr-4": {
"LasseRafn\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Lasse Rafn",
"email": "lasserafn@gmail.com"
}
],
"description": "Detect language/encoding of a string in PHP",
"keywords": [
"language",
"php",
"string"
],
"support": {
"issues": "https://github.com/LasseRafn/php-string-script-language/issues",
"source": "https://github.com/LasseRafn/php-string-script-language/tree/0.4"
},
"time": "2023-07-26T07:23:39+00:00"
},
{ {
"name": "league/flysystem", "name": "league/flysystem",
"version": "2.1.1", "version": "2.1.1",
@@ -2611,6 +2856,56 @@
}, },
"time": "2023-05-10T11:58:31+00:00" "time": "2023-05-10T11:58:31+00:00"
}, },
{
"name": "meyfa/php-svg",
"version": "v0.9.1",
"source": {
"type": "git",
"url": "https://github.com/meyfa/php-svg.git",
"reference": "34401edef1f724898f468f71b85505fbcc8351bb"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/meyfa/php-svg/zipball/34401edef1f724898f468f71b85505fbcc8351bb",
"reference": "34401edef1f724898f468f71b85505fbcc8351bb",
"shasum": ""
},
"require": {
"ext-gd": "*",
"ext-simplexml": "*",
"php": ">=5.3.3"
},
"require-dev": {
"meyfa/phpunit-assert-gd": "^1.1",
"phpunit/phpunit": "^4.8"
},
"type": "library",
"autoload": {
"psr-4": {
"SVG\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Fabian Meyer",
"homepage": "http://meyfa.net"
}
],
"description": "Read, edit, write, and render SVG files with PHP",
"homepage": "https://github.com/meyfa/php-svg",
"keywords": [
"svg"
],
"support": {
"issues": "https://github.com/meyfa/php-svg/issues",
"source": "https://github.com/meyfa/php-svg/tree/v0.9.1"
},
"time": "2019-07-30T18:41:25+00:00"
},
{ {
"name": "michelf/php-markdown", "name": "michelf/php-markdown",
"version": "1.9.0", "version": "1.9.0",
@@ -3070,6 +3365,79 @@
], ],
"time": "2023-11-22T15:34:18+00:00" "time": "2023-11-22T15:34:18+00:00"
}, },
{
"name": "overtrue/pinyin",
"version": "4.1.0",
"source": {
"type": "git",
"url": "https://github.com/overtrue/pinyin.git",
"reference": "4d0fb4f27f0c79e81c9489e0c0ae4a4f8837eae7"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/overtrue/pinyin/zipball/4d0fb4f27f0c79e81c9489e0c0ae4a4f8837eae7",
"reference": "4d0fb4f27f0c79e81c9489e0c0ae4a4f8837eae7",
"shasum": ""
},
"require": {
"php": ">=7.1"
},
"require-dev": {
"brainmaestro/composer-git-hooks": "^2.7",
"friendsofphp/php-cs-fixer": "^2.16",
"phpunit/phpunit": "~8.0"
},
"type": "library",
"extra": {
"hooks": {
"pre-commit": [
"composer test",
"composer fix-style"
],
"pre-push": [
"composer test",
"composer check-style"
]
}
},
"autoload": {
"files": [
"src/const.php"
],
"psr-4": {
"Overtrue\\Pinyin\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "overtrue",
"email": "anzhengchao@gmail.com",
"homepage": "http://github.com/overtrue"
}
],
"description": "Chinese to pinyin translator.",
"homepage": "https://github.com/overtrue/pinyin",
"keywords": [
"Chinese",
"Pinyin",
"cn2pinyin"
],
"support": {
"issues": "https://github.com/overtrue/pinyin/issues",
"source": "https://github.com/overtrue/pinyin/tree/4.1.0"
},
"funding": [
{
"url": "https://github.com/overtrue",
"type": "github"
}
],
"time": "2023-04-27T10:17:12+00:00"
},
{ {
"name": "paragonie/constant_time_encoding", "name": "paragonie/constant_time_encoding",
"version": "v2.6.3", "version": "v2.6.3",
@@ -6299,63 +6667,6 @@
}, },
"time": "2022-06-03T18:03:27+00:00" "time": "2022-06-03T18:03:27+00:00"
}, },
{
"name": "yzalis/identicon",
"version": "2.0.0",
"source": {
"type": "git",
"url": "https://github.com/yzalis/Identicon.git",
"reference": "ff5ed090129cab9bfa2a322857d4a01d107aa0ae"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/yzalis/Identicon/zipball/ff5ed090129cab9bfa2a322857d4a01d107aa0ae",
"reference": "ff5ed090129cab9bfa2a322857d4a01d107aa0ae",
"shasum": ""
},
"require": {
"php": ">=5.5.0"
},
"require-dev": {
"ext-imagick": "*",
"fzaninotto/faker": "^1.2.0",
"phpunit/phpunit": "^4.0 || ^5.0"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.2-dev"
}
},
"autoload": {
"psr-4": {
"Identicon\\": "src/Identicon/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Benjamin Laugueux",
"email": "benjamin@yzalis.com"
}
],
"description": "Create awesome unique avatar.",
"homepage": "http://identicon-php.org",
"keywords": [
"avatar",
"identicon",
"image"
],
"support": {
"issues": "https://github.com/yzalis/Identicon/issues",
"source": "https://github.com/yzalis/Identicon/tree/master"
},
"abandoned": true,
"time": "2019-10-14T09:30:57+00:00"
},
{ {
"name": "zbateson/mail-mime-parser", "name": "zbateson/mail-mime-parser",
"version": "1.3.1", "version": "1.3.1",
+1 -1
View File
@@ -1987,7 +1987,7 @@ td > span.color-icon {
} }
img.avatar { img.avatar {
border-radius: var(--border-radius-small); border-radius: 50%;
} }
img.avatar.avatar-link { img.avatar.avatar-link {