email template placeholders

This commit is contained in:
Yuri Kuznetsov
2023-11-07 19:20:07 +02:00
parent 72a218fca0
commit 6d1d38c4af
12 changed files with 350 additions and 26 deletions

19
.idea/jsonSchemas.xml generated
View File

@@ -550,6 +550,25 @@
</SchemaInfo>
</value>
</entry>
<entry key="metadata/app/emailTemplate">
<value>
<SchemaInfo>
<option name="generatedName" value="New Schema" />
<option name="name" value="metadata/app/emailTemplate" />
<option name="relativePathToSchema" value="schema/metadata/app/emailTemplate.json" />
<option name="schemaVersion" value="JSON Schema version 7" />
<option name="patterns">
<list>
<Item>
<option name="pattern" value="true" />
<option name="path" value="*/Resources/metadata/app/emailTemplate.json" />
<option name="mappingKind" value="Pattern" />
</Item>
</list>
</option>
</SchemaInfo>
</value>
</entry>
<entry key="metadata/app/entityManagerParams">
<value>
<SchemaInfo>

View File

@@ -256,6 +256,12 @@
],
"url": "./schema/metadata/app/defaultDashboardOptions.json"
},
{
"fileMatch": [
"*/Resources/metadata/app/emailTemplate.json"
],
"url": "./schema/metadata/app/emailTemplate.json"
},
{
"fileMatch": [
"*/Resources/metadata/app/entityManagerParams.json"

View File

@@ -0,0 +1,16 @@
{
"placeholders": {
"today": {
"className": "Espo\\Tools\\EmailTemplate\\Placeholders\\Today",
"order": 0
},
"now": {
"className": "Espo\\Tools\\EmailTemplate\\Placeholders\\Now",
"order": 1
},
"currentYear": {
"className": "Espo\\Tools\\EmailTemplate\\Placeholders\\CurrentYear",
"order": 2
}
}
}

View File

@@ -31,6 +31,6 @@
"filterList": [
"actual"
],
"placeholderList": ["today", "now", "currentYear", "optOutUrl", "optOutLink"],
"placeholderList": ["optOutUrl", "optOutLink"],
"iconClass": "fas fa-envelope-square"
}

View File

@@ -0,0 +1,35 @@
<?php
/************************************************************************
* This file is part of EspoCRM.
*
* EspoCRM - Open Source CRM application.
* Copyright (C) 2014-2023 Yurii Kuznietsov, Taras Machyshyn, Oleksii Avramenko
* Website: https://www.espocrm.com
*
* EspoCRM is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* EspoCRM is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with EspoCRM. If not, see http://www.gnu.org/licenses/.
*
* 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 General Public License version 3.
*
* In accordance with Section 7(b) of the GNU General Public License version 3,
* these Appropriate Legal Notices must retain the display of the "EspoCRM" word.
************************************************************************/
namespace Espo\Tools\EmailTemplate;
interface Placeholder
{
public function get(Data $data): string;
}

View File

@@ -0,0 +1,60 @@
<?php
/************************************************************************
* This file is part of EspoCRM.
*
* EspoCRM - Open Source CRM application.
* Copyright (C) 2014-2023 Yurii Kuznietsov, Taras Machyshyn, Oleksii Avramenko
* Website: https://www.espocrm.com
*
* EspoCRM is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* EspoCRM is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with EspoCRM. If not, see http://www.gnu.org/licenses/.
*
* 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 General Public License version 3.
*
* In accordance with Section 7(b) of the GNU General Public License version 3,
* these Appropriate Legal Notices must retain the display of the "EspoCRM" word.
************************************************************************/
namespace Espo\Tools\EmailTemplate\Placeholders;
use DateTime;
use DateTimezone;
use Espo\Core\Utils\Config;
use Espo\Tools\EmailTemplate\Data;
use Espo\Tools\EmailTemplate\Placeholder;
use Exception;
use RuntimeException;
/**
* @noinspection PhpUnused
*/
class CurrentYear implements Placeholder
{
public function __construct(
private Config $config
) {}
public function get(Data $data): string
{
try {
$now = new DateTime('now', new DateTimezone($this->config->get('timeZone')));
}
catch (Exception $e) {
throw new RuntimeException($e->getMessage());
}
return $now->format('Y');
}
}

View File

@@ -0,0 +1,49 @@
<?php
/************************************************************************
* This file is part of EspoCRM.
*
* EspoCRM - Open Source CRM application.
* Copyright (C) 2014-2023 Yurii Kuznietsov, Taras Machyshyn, Oleksii Avramenko
* Website: https://www.espocrm.com
*
* EspoCRM is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* EspoCRM is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with EspoCRM. If not, see http://www.gnu.org/licenses/.
*
* 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 General Public License version 3.
*
* In accordance with Section 7(b) of the GNU General Public License version 3,
* these Appropriate Legal Notices must retain the display of the "EspoCRM" word.
************************************************************************/
namespace Espo\Tools\EmailTemplate\Placeholders;
use Espo\Core\Utils\DateTime;
use Espo\Tools\EmailTemplate\Data;
use Espo\Tools\EmailTemplate\Placeholder;
/**
* @noinspection PhpUnused
*/
class Now implements Placeholder
{
public function __construct(
private DateTime $dateTime
) {}
public function get(Data $data): string
{
return $this->dateTime->getNowString();
}
}

View File

@@ -0,0 +1,49 @@
<?php
/************************************************************************
* This file is part of EspoCRM.
*
* EspoCRM - Open Source CRM application.
* Copyright (C) 2014-2023 Yurii Kuznietsov, Taras Machyshyn, Oleksii Avramenko
* Website: https://www.espocrm.com
*
* EspoCRM is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* EspoCRM is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with EspoCRM. If not, see http://www.gnu.org/licenses/.
*
* 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 General Public License version 3.
*
* In accordance with Section 7(b) of the GNU General Public License version 3,
* these Appropriate Legal Notices must retain the display of the "EspoCRM" word.
************************************************************************/
namespace Espo\Tools\EmailTemplate\Placeholders;
use Espo\Core\Utils\DateTime;
use Espo\Tools\EmailTemplate\Data;
use Espo\Tools\EmailTemplate\Placeholder;
/**
* @noinspection PhpUnused
*/
class Today implements Placeholder
{
public function __construct(
private DateTime $dateTime
) {}
public function get(Data $data): string
{
return $this->dateTime->getTodayString();
}
}

View File

@@ -0,0 +1,68 @@
<?php
/************************************************************************
* This file is part of EspoCRM.
*
* EspoCRM - Open Source CRM application.
* Copyright (C) 2014-2023 Yurii Kuznietsov, Taras Machyshyn, Oleksii Avramenko
* Website: https://www.espocrm.com
*
* EspoCRM is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* EspoCRM is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with EspoCRM. If not, see http://www.gnu.org/licenses/.
*
* 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 General Public License version 3.
*
* In accordance with Section 7(b) of the GNU General Public License version 3,
* these Appropriate Legal Notices must retain the display of the "EspoCRM" word.
************************************************************************/
namespace Espo\Tools\EmailTemplate;
use Espo\Core\InjectableFactory;
use Espo\Core\Utils\Metadata;
class PlaceholdersProvider
{
public function __construct(
private Metadata $metadata,
private InjectableFactory $injectableFactory
) {}
/**
* @return array{string, Placeholder}[]
*/
public function get(): array
{
$defs = $this->metadata->get("app.emailTemplate.placeholders") ?? [];
/** @var string[] $list */
$list = array_keys($defs);
usort($list, function ($a, $b) use ($defs) {
$o1 = $defs[$a]['order'] ?? 0;
$o2 = $defs[$b]['order'] ?? 0;
return $o1 - $o2;
});
return array_map(function ($name) use ($defs) {
/** @var class-string<Placeholder> $className */
$className = $defs[$name]['className'];
$placeholder = $this->injectableFactory->create($className);
return [$name, $placeholder];
}, $list);
}
}

View File

@@ -43,7 +43,6 @@ use Espo\Core\Entities\Person;
use Espo\Core\Htmlizer\HtmlizerFactory as HtmlizerFactory;
use Espo\Core\Htmlizer\Htmlizer;
use Espo\Core\Acl\GlobalRestriction;
use Espo\Core\Utils\DateTime as DateTimeUtil;
use Espo\Entities\EmailTemplate;
use Espo\Entities\User;
use Espo\Entities\Attachment;
@@ -51,9 +50,6 @@ use Espo\Entities\EmailAddress;
use Espo\Repositories\EmailAddress as EmailAddressRepository;
use Exception;
use DateTime;
use DateTimezone;
use RuntimeException;
class Processor
{
@@ -68,7 +64,7 @@ class Processor
private FileStorageManager $fileStorageManager,
private User $user,
private HtmlizerFactory $htmlizerFactory,
private DateTimeUtil $dateTime
private PlaceholdersProvider $placeholdersProvider
) {}
public function process(EmailTemplate $template, Params $params, Data $data): Result
@@ -223,23 +219,11 @@ class Processor
);
}
/** @noinspection PhpUnusedParameterInspection */
private function processPlaceholders(string $text, Data $data): string
{
try {
$now = new DateTime('now', new DateTimezone($this->config->get('timeZone')));
}
catch (Exception $e) {
throw new RuntimeException($e->getMessage());
}
foreach ($this->placeholdersProvider->get() as [$key, $placeholder]) {
$value = $placeholder->get($data);
$replaceData = [
'today' => $this->dateTime->getTodayString(),
'now' => $this->dateTime->getNowString(),
'currentYear' => $now->format('Y'),
];
foreach ($replaceData as $key => $value) {
$text = str_replace('{' . $key . '}', $value, $text);
}

View File

@@ -33,7 +33,19 @@ define('views/email-template/record/panels/information', ['views/record/panels/s
templateContent: '{{{infoText}}}',
data: function () {
let placeholderList = this.getMetadata().get(['clientDefs', 'EmailTemplate', 'placeholderList']) || [];
const list2 = this.getMetadata().get(['clientDefs', 'EmailTemplate', 'placeholderList']) || [];
const defs = this.getMetadata().get('app.emailTemplate.placeholders') || {};
const list1 = Object.keys(defs)
.sort((a, b) => {
const o1 = defs[a].order || 0;
const o2 = defs[b].order || 0;
return o1 - o2;
});
const placeholderList = [...list1, ...list2];
if (!placeholderList.length) {
return {
@@ -41,9 +53,9 @@ define('views/email-template/record/panels/information', ['views/record/panels/s
};
}
let $header = $('<h4>').text(this.translate('Available placeholders', 'labels', 'EmailTemplate') + ':');
const $header = $('<h4>').text(this.translate('Available placeholders', 'labels', 'EmailTemplate') + ':');
let $liList = placeholderList.map(item => {
const $liList = placeholderList.map(item => {
return $('<li>').append(
$('<code>').text('{' + item + '}'),
' &#8211; ',
@@ -51,11 +63,11 @@ define('views/email-template/record/panels/information', ['views/record/panels/s
)
});
let $ul = $('<ul>').append($liList);
const $ul = $('<ul>').append($liList);
let $text = $('<span>')
const $text = $('<span>')
.addClass('complex-text')
.append($header, $ul)
.append($header, $ul);
return {
infoText: $text[0].outerHTML,

View File

@@ -0,0 +1,26 @@
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "https://www.espocrm.com/schema/metadata/app/emailTemplates.json",
"title": "app/databasePlatforms",
"description": "Email template definitions.",
"type": "object",
"properties": {
"placeholders": {
"description": "Placeholders.",
"additionalProperties": {
"description": "A placeholder.",
"type": "object",
"properties": {
"className": {
"type": "string",
"description": "A class. Should implement Espo\\Tools\\EmailTemplate\\Placeholder."
},
"order": {
"type": "integer",
"description": "An order position."
}
}
}
}
}
}