image refactoring and svg support

This commit is contained in:
Yuri Kuznetsov
2021-07-21 13:50:19 +03:00
parent 7066098957
commit 438daf82b4
5 changed files with 150 additions and 75 deletions
+2 -2
View File
@@ -107,13 +107,13 @@ class Avatar extends Image implements Di\MetadataAware
$size = 'small';
}
if (empty($this->imageSizes[$size])) {
if (empty($this->getSizes()[$size])) {
$this->renderBlank($response);
return;
}
$width = $this->imageSizes[$size][0];
$width = $this->getSizes()[$size][0];
$response
->setHeader('Cache-Control', 'max-age=360000, must-revalidate')
+34 -29
View File
@@ -43,34 +43,13 @@ use Espo\Core\{
FileStorage\Manager as FileStorageManager,
Utils\File\Manager as FileManager,
Utils\Config,
Utils\Metadata,
};
use Espo\Entities\Attachment;
class Image implements EntryPoint
{
protected $allowedFileTypes = [
'image/jpeg',
'image/png',
'image/gif',
'image/webp',
];
protected $imageSizes = [
'xxx-small' => [18, 18],
'xx-small' => [32, 32],
'x-small' => [64, 64],
'small' => [128, 128],
'medium' => [256, 256],
'large' => [512, 512],
'x-large' => [864, 864],
'xx-large' => [1024, 1024],
];
protected $fixOrientationFileTypeList = [
'image/jpeg',
];
protected $allowedRelatedTypeList = null;
protected $allowedFieldList = null;
@@ -85,18 +64,22 @@ class Image implements EntryPoint
protected $config;
private $metadata;
public function __construct(
FileStorageManager $fileStorageManager,
Acl $acl,
EntityManager $entityManager,
FileManager $fileManager,
Config $config
Config $config,
Metadata $metadata
) {
$this->fileStorageManager = $fileStorageManager;
$this->acl = $acl;
$this->entityManager = $entityManager;
$this->fileManager = $fileManager;
$this->config = $config;
$this->metadata = $metadata;
}
public function run(Request $request, Response $response): void
@@ -125,8 +108,8 @@ class Image implements EntryPoint
$fileType = $attachment->get('type');
if (!in_array($fileType, $this->allowedFileTypes)) {
throw new Error();
if (!in_array($fileType, $this->getAllowedFileTypeList())) {
throw new Forbidden("Not allowed file type '{$fileType}'.");
}
if ($this->allowedRelatedTypeList) {
@@ -141,7 +124,9 @@ class Image implements EntryPoint
}
}
if ($size) {
$toResize = $size && in_array($fileType, $this->getResizableFileTypeList());
if ($toResize) {
$fileName = $size . '-' . $attachment->get('name');
$contents = $this->getThumbContents($attachment, $size);
@@ -173,7 +158,7 @@ class Image implements EntryPoint
protected function getThumbContents(Attachment $attachment, string $size): string
{
if (!array_key_exists($size, $this->imageSizes)) {
if (!array_key_exists($size, $this->getSizes())) {
throw new Error("Bad size.");
}
@@ -242,7 +227,7 @@ class Image implements EntryPoint
list($originalWidth, $originalHeight) = getimagesize($filePath);
list($width, $height) = $this->imageSizes[$size];
list($width, $height) = $this->getSizes()[$size];
if ($originalWidth <= $width && $originalHeight <= $height) {
$targetWidth = $originalWidth;
@@ -323,7 +308,7 @@ class Image implements EntryPoint
break;
}
if (in_array($fileType, $this->fixOrientationFileTypeList)) {
if (in_array($fileType, $this->getFixOrientationFileTypeList())) {
$targetImage = $this->fixOrientation($targetImage, $filePath);
}
@@ -353,4 +338,24 @@ class Image implements EntryPoint
return $targetImage;
}
private function getAllowedFileTypeList(): array
{
return $this->metadata->get(['app', 'image', 'allowedFileTypeList']) ?? [];
}
private function getResizableFileTypeList(): array
{
return $this->metadata->get(['app', 'image', 'resizableFileTypeList']) ?? [];
}
private function getFixOrientationFileTypeList(): array
{
return $this->metadata->get(['app', 'image', 'fixOrientationFileTypeList']) ?? [];
}
protected function getSizes(): array
{
return $this->metadata->get(['app', 'image', 'sizes']) ?? [];
}
}
@@ -0,0 +1,35 @@
{
"allowedFileTypeList": [
"image/jpeg",
"image/png",
"image/gif",
"image/webp",
"image/svg+xml"
],
"resizableFileTypeList": [
"image/jpeg",
"image/png",
"image/gif",
"image/webp"
],
"fixOrientationFileTypeList": [
"image/jpeg"
],
"previewFileTypeList": [
"image/jpeg",
"image/png",
"image/gif",
"image/webp",
"image/svg+xml"
],
"sizes": {
"xxx-small": [18, 18],
"xx-small": [32, 32],
"x-small": [64, 64],
"small": [128, 128],
"medium": [256, 256],
"large": [512, 512],
"x-large": [864, 864],
"xx-large": [1024, 1024]
}
}
+36 -21
View File
@@ -52,13 +52,6 @@ define('views/fields/attachment-multiple', 'views/fields/base', function (Dep) {
showPreviews: true,
previewTypeList: [
'image/jpeg',
'image/png',
'image/gif',
'image/webp',
],
accept: null,
validations: ['ready', 'required'],
@@ -175,7 +168,8 @@ define('views/fields/attachment-multiple', 'views/fields/base', function (Dep) {
this.previewSize = this.options.previewSize || this.params.previewSize || this.previewSize;
var self = this;
this.previewTypeList = this.getMetadata().get(['app', 'image', 'previewFileTypeList']) || [];
this.imageSizes = this.getMetadata().get(['app', 'image', 'sizes']) || {};
this.nameHash = _.clone(this.model.get(this.nameHashName)) || {};
@@ -358,13 +352,21 @@ define('views/fields/attachment-multiple', 'views/fields/base', function (Dep) {
name = Handlebars.Utils.escapeExpression(name);
id = Handlebars.Utils.escapeExpression(id);
var preview = name;
if (~this.previewTypeList.indexOf(type)) {
preview = '<img src="' + this.getImageUrl(id, 'small') + '" title="' + name + '">';
if (!~this.previewTypeList.indexOf(type)) {
return name;
}
return preview;
let html = $('<img>')
.attr('src', this.getImageUrl(id, 'small'))
.attr('title', name)
.css({
maxWidth: (this.imageSizes[this.previewSize] || {})[0],
maxHeight: (this.imageSizes[this.previewSize] || {})[1],
})
.get(0)
.outerHTML;
return html;
},
addAttachmentBox: function (name, type, id) {
@@ -609,22 +611,35 @@ define('views/fields/attachment-multiple', 'views/fields/base', function (Dep) {
return true;
}
return false
return false;
},
getDetailPreview: function (name, type, id) {
name = Handlebars.Utils.escapeExpression(name);
id = Handlebars.Utils.escapeExpression(id);
var preview = name;
if (this.isTypeIsImage(type)) {
preview = '<a data-action="showImagePreview" data-id="' + id + '" href="' +
this.getImageUrl(id) + '"><img src="'+
this.getImageUrl(id, this.previewSize)+'" class="image-preview"></a>';
if (!this.isTypeIsImage(type)) {
return name;
}
return preview;
let html = $('<a>')
.attr('data-action', 'showImagePreview')
.attr('data-id', id)
.attr('title', name)
.attr('href', this.getImageUrl(id))
.append(
$('<img>')
.attr('src', this.getImageUrl(id, this.previewSize))
.addClass('image-preview')
.css({
maxWidth: (this.imageSizes[this.previewSize] || {})[0],
maxHeight: (this.imageSizes[this.previewSize] || {})[1],
})
)
.get(0)
.outerHTML;
return html;
},
getValueForDisplay: function () {
+43 -23
View File
@@ -44,13 +44,6 @@ define('views/fields/file', 'views/fields/link', function (Dep) {
accept: false,
previewTypeList: [
'image/jpeg',
'image/png',
'image/gif',
'image/webp',
],
defaultType: false,
previewSize: 'small',
@@ -168,6 +161,9 @@ define('views/fields/file', 'views/fields/link', function (Dep) {
this.previewSize = this.options.previewSize || this.params.previewSize || this.previewSize;
this.previewTypeList = this.getMetadata().get(['app', 'image', 'previewFileTypeList']) || [];
this.imageSizes = this.getMetadata().get(['app', 'image', 'sizes']) || {};
var sourceDefs = this.getMetadata().get(['clientDefs', 'Attachment', 'sourceDefs']) || {};
this.sourceList = Espo.Utils.clone(this.params.sourceList || []);
@@ -298,7 +294,7 @@ define('views/fields/file', 'views/fields/link', function (Dep) {
return name;
}
var previewSize = this.previewSize;
let previewSize = this.previewSize;
if (this.isListMode()) {
previewSize = 'small';
@@ -310,35 +306,59 @@ define('views/fields/file', 'views/fields/link', function (Dep) {
id = Handlebars.Utils.escapeExpression(id);
var src = this.getBasePath() + '?entryPoint=image&size=' + previewSize + '&id=' + id;
let src = this.getBasePath() + '?entryPoint=image&size=' + previewSize + '&id=' + id;
var img = '<img src="' + src + '" class="image-preview">';
let $img = $('<img>')
.attr('src', src)
.addClass('image-preview')
.css({
maxWidth: (this.imageSizes[this.previewSize] || {})[0],
maxHeight: (this.imageSizes[this.previewSize] || {})[1],
});
if (this.mode === 'listLink') {
var link = '#' + this.model.entityType + '/view/' + this.model.id;
let link = '#' + this.model.entityType + '/view/' + this.model.id;
return '<a href="'+link+'">' + img + '</a>';
let html = $('<a>')
.attr('href', link)
.append($img)
.get(0)
.outerHTML;
return html;
}
var preview = '' +
'<a data-action="showImagePreview" data-id="' + id + '" href="' + this.getImageUrl(id) + '">' +
img +
'</a>';
let html = $('<a>')
.attr('data-action', 'showImagePreview')
.attr('data-id', id)
.attr('title', name)
.attr('href', this.getImageUrl(id))
.append($img)
.get(0)
.outerHTML;
return preview;
return html;
},
getEditPreview: function (name, type, id) {
name = Handlebars.Utils.escapeExpression(name);
id = Handlebars.Utils.escapeExpression(id);
var preview = name;
if (~this.previewTypeList.indexOf(type)) {
preview = '<img src="' + this.getImageUrl(id, 'small') + '" title="' + name + '">';
if (!~this.previewTypeList.indexOf(type)) {
return null;
}
return preview;
let html = $('<img>')
.attr('src', this.getImageUrl(id, 'small'))
.attr('title', name)
.css({
maxWidth: (this.imageSizes[this.previewSize] || {})[0],
maxHeight: (this.imageSizes[this.previewSize] || {})[1],
})
.get(0)
.outerHTML;
return html;
},
getValueForDisplay: function () {
@@ -549,7 +569,7 @@ define('views/fields/file', 'views/fields/link', function (Dep) {
var $att = $('<div>')
.append(removeLink)
.append(
.append(
$('<span class="preview">' + preview + '</span>')
.addClass('gray-box')
);