From f7e7bc43e35036dac4df60295aadb6b5e044b572 Mon Sep 17 00:00:00 2001 From: Yuri Kuznetsov Date: Fri, 3 Jan 2020 12:52:06 +0200 Subject: [PATCH] settings: person name format --- application/Espo/Core/Entities/Person.php | 18 ++--- .../Espo/Core/Loaders/EntityManager.php | 9 ++- application/Espo/Core/ORM/EntityManager.php | 17 +++- application/Espo/Core/ORM/Helper.php | 80 +++++++++++++++++++ .../Espo/Core/Utils/Database/Orm/Base.php | 38 +++++---- .../Core/Utils/Database/Orm/Converter.php | 10 +-- .../Core/Utils/Database/Orm/Fields/Base.php | 1 + .../Utils/Database/Orm/Fields/PersonName.php | 11 ++- .../Utils/Database/Orm/RelationManager.php | 7 +- application/Espo/Core/defaults/config.php | 1 + .../Espo/Resources/i18n/en_US/Settings.json | 5 ++ .../Resources/layouts/Settings/settings.json | 3 +- .../metadata/app/containerServices.json | 4 + .../metadata/entityDefs/Settings.json | 4 + application/Espo/Services/Settings.php | 6 +- .../templates/fields/person-name/detail.tpl | 6 +- .../fields/person-name/edit-last-first.tpl | 13 +++ client/src/views/fields/person-name.js | 56 ++++++++++++- 18 files changed, 238 insertions(+), 51 deletions(-) create mode 100644 application/Espo/Core/ORM/Helper.php create mode 100644 client/res/templates/fields/person-name/edit-last-first.tpl diff --git a/application/Espo/Core/Entities/Person.php b/application/Espo/Core/Entities/Person.php index 5ff0dee7a2..7127a56e55 100644 --- a/application/Espo/Core/Entities/Person.php +++ b/application/Espo/Core/Entities/Person.php @@ -35,23 +35,17 @@ class Person extends \Espo\Core\ORM\Entity { $this->setValue('lastName', $value); - $firstName = $this->get('firstName'); - if (empty($firstName)) { - $this->setValue('name', $value); - } else { - $this->setValue('name', $firstName . ' ' . $value); - } + $name = $this->getEntityManager()->getHelper()->formatPersonName($this, 'name'); + + $this->setValue('name', $name); } public function _setFirstName($value) { $this->setValue('firstName', $value); - $lastName = $this->get('lastName'); - if (empty($lastName)) { - $this->setValue('name', $value); - } else { - $this->setValue('name', $value . ' ' . $lastName); - } + $name = $this->getEntityManager()->getHelper()->formatPersonName($this, 'name'); + + $this->setValue('name', $name); } } diff --git a/application/Espo/Core/Loaders/EntityManager.php b/application/Espo/Core/Loaders/EntityManager.php index e1dd23e57a..cedb1182d8 100644 --- a/application/Espo/Core/Loaders/EntityManager.php +++ b/application/Espo/Core/Loaders/EntityManager.php @@ -35,7 +35,7 @@ class EntityManager extends Base { $config = $this->getContainer()->get('config'); - $params = array( + $params = [ 'host' => $config->get('database.host'), 'port' => $config->get('database.port'), 'dbname' => $config->get('database.dbname'), @@ -50,15 +50,16 @@ class EntityManager extends Base 'sslCert' => $config->get('database.sslCert'), 'sslKey' => $config->get('database.sslKey'), 'sslCAPath' => $config->get('database.sslCAPath'), - 'sslCipher' => $config->get('database.sslCipher') - ); + 'sslCipher' => $config->get('database.sslCipher'), + ]; $entityManager = new \Espo\Core\ORM\EntityManager($params); + $entityManager->setEspoMetadata($this->getContainer()->get('metadata')); $entityManager->setHookManager($this->getContainer()->get('hookManager')); + $entityManager->setHelper($this->getContainer()->get('entityManagerHelper')); $entityManager->setContainer($this->getContainer()); return $entityManager; } } - diff --git a/application/Espo/Core/ORM/EntityManager.php b/application/Espo/Core/ORM/EntityManager.php index 29f58836bc..fa8ea2d97b 100644 --- a/application/Espo/Core/ORM/EntityManager.php +++ b/application/Espo/Core/ORM/EntityManager.php @@ -41,9 +41,11 @@ class EntityManager extends \Espo\ORM\EntityManager protected $container; - private $repositoryClassNameHash = array(); + private $repositoryClassNameHash = []; - private $entityClassNameHash = array(); + private $entityClassNameHash = []; + + private $helper; public function setContainer(\Espo\Core\Container $container) { @@ -108,5 +110,14 @@ class EntityManager extends \Espo\ORM\EntityManager } return $this->entityClassNameHash[$name]; } -} + public function setHelper(Helper $helper) + { + $this->helper = $helper; + } + + public function getHelper() + { + return $this->helper; + } +} diff --git a/application/Espo/Core/ORM/Helper.php b/application/Espo/Core/ORM/Helper.php new file mode 100644 index 0000000000..f5e25ba252 --- /dev/null +++ b/application/Espo/Core/ORM/Helper.php @@ -0,0 +1,80 @@ +config = $config; + } + + public function formatPersonName(Entity $entity, string $field) + { + $format = $this->config->get('personNameFormat'); + + $first = $entity->get('first' . ucfirst($field)); + $last = $entity->get('last' . ucfirst($field)); + + switch ($format) { + case 'lastFirst': + if (!$first && !$last) { + return null; + } + if (!$first) { + return $last; + } + if (!$last) { + return $first; + } + return $last . ' ' . $first; + + default: + if (!$first && !$last) { + return null; + } + if (!$first) { + return $last; + } + if (!$last) { + return $first; + } + return $first . ' ' . $last; + } + + return null; + } +} diff --git a/application/Espo/Core/Utils/Database/Orm/Base.php b/application/Espo/Core/Utils/Database/Orm/Base.php index 18e55df6e7..c24ac95eef 100644 --- a/application/Espo/Core/Utils/Database/Orm/Base.php +++ b/application/Espo/Core/Utils/Database/Orm/Base.php @@ -30,6 +30,7 @@ namespace Espo\Core\Utils\Database\Orm; use Espo\Core\Utils\Util; +use Espo\Core\Utils\Config; class Base { @@ -43,11 +44,14 @@ class Base private $entityDefs; - public function __construct(\Espo\Core\Utils\Metadata $metadata, array $ormEntityDefs, array $entityDefs) + protected $config; + + public function __construct(\Espo\Core\Utils\Metadata $metadata, array $ormEntityDefs, array $entityDefs, Config $config) { $this->metadata = $metadata; $this->ormEntityDefs = $ormEntityDefs; $this->entityDefs = $entityDefs; + $this->config = $config; } protected function getMetadata() @@ -216,20 +220,28 @@ class Base return $returns; } - /** - * Get Foreign field - * - * @param string $name - * @param string $entityName - * @return string - */ - protected function getForeignField($name, $entityName) + protected function getForeignField(string $name, string $entityType) { - $foreignField = $this->getMetadata()->get('entityDefs.'.$entityName.'.fields.'.$name); + $foreignField = $this->getMetadata()->get(['entityDefs', $entityType, 'fields', $name]); if ($foreignField['type'] != 'varchar') { if ($foreignField['type'] == 'personName') { - return array('first' . ucfirst($name), ' ', 'last' . ucfirst($name)); + $personNameFormat = $this->config->get('personNameFormat'); + + switch ($personNameFormat) { + case 'lastFirst': + return [ + 'last' . ucfirst($name), + ' ', + 'first' . ucfirst($name), + ]; + } + + return [ + 'first' . ucfirst($name), + ' ', + 'last' . ucfirst($name), + ]; } } @@ -238,9 +250,6 @@ class Base /** * Set a value for all elements of array. So, in result all elements will have the same values - * - * @param string $value - * @param array $array */ protected function setArrayValue($inputValue, array $array) { @@ -250,5 +259,4 @@ class Base return $array; } - } diff --git a/application/Espo/Core/Utils/Database/Orm/Converter.php b/application/Espo/Core/Utils/Database/Orm/Converter.php index b15e79faf6..0e887a0e90 100644 --- a/application/Espo/Core/Utils/Database/Orm/Converter.php +++ b/application/Espo/Core/Utils/Database/Orm/Converter.php @@ -116,7 +116,7 @@ class Converter $this->fileManager = $fileManager; //need to featue with ormHooks. Ex. isFollowed field $this->config = $config; - $this->relationManager = new RelationManager($this->metadata); + $this->relationManager = new RelationManager($this->metadata, $config); $this->metadataHelper = new \Espo\Core\Utils\Metadata\Helper($this->metadata); $this->databaseHelper = new \Espo\Core\Utils\Database\Helper($this->config); @@ -346,12 +346,8 @@ class Converter /** * Correct fields definitions based on \Espo\Custom\Core\Utils\Database\Orm\Fields - * - * @param array $ormMetadata - * - * @return array */ - protected function correctFields($entityName, array $ormMetadata) + protected function correctFields($entityName, array $ormMetadata) : array { $entityDefs = $this->getEntityDefs(); @@ -367,7 +363,7 @@ class Converter } if (class_exists($className) && method_exists($className, 'load')) { - $helperClass = new $className($this->metadata, $ormMetadata, $entityDefs); + $helperClass = new $className($this->metadata, $ormMetadata, $entityDefs, $this->config); $fieldResult = $helperClass->process($fieldName, $entityName); if (isset($fieldResult['unset'])) { $ormMetadata = Util::unsetInArray($ormMetadata, $fieldResult['unset']); diff --git a/application/Espo/Core/Utils/Database/Orm/Fields/Base.php b/application/Espo/Core/Utils/Database/Orm/Fields/Base.php index 279b53dd23..90fa336484 100644 --- a/application/Espo/Core/Utils/Database/Orm/Fields/Base.php +++ b/application/Espo/Core/Utils/Database/Orm/Fields/Base.php @@ -28,6 +28,7 @@ ************************************************************************/ namespace Espo\Core\Utils\Database\Orm\Fields; + class Base extends \Espo\Core\Utils\Database\Orm\Base { /** diff --git a/application/Espo/Core/Utils/Database/Orm/Fields/PersonName.php b/application/Espo/Core/Utils/Database/Orm/Fields/PersonName.php index 40a1eb3ab1..d1facca2d4 100644 --- a/application/Espo/Core/Utils/Database/Orm/Fields/PersonName.php +++ b/application/Espo/Core/Utils/Database/Orm/Fields/PersonName.php @@ -35,7 +35,16 @@ class PersonName extends Base { protected function load($fieldName, $entityName) { - $subList = ['first' . ucfirst($fieldName), ' ', 'last' . ucfirst($fieldName)]; + $format = $this->config->get('personNameFormat'); + + switch ($format) { + case 'lastFirst': + $subList = ['last' . ucfirst($fieldName), ' ', 'first' . ucfirst($fieldName)]; + break; + + default: + $subList = ['first' . ucfirst($fieldName), ' ', 'last' . ucfirst($fieldName)]; + } $tableName = Util::toUnderScore($entityName); diff --git a/application/Espo/Core/Utils/Database/Orm/RelationManager.php b/application/Espo/Core/Utils/Database/Orm/RelationManager.php index 2f07c6a08e..87ec02cf5e 100644 --- a/application/Espo/Core/Utils/Database/Orm/RelationManager.php +++ b/application/Espo/Core/Utils/Database/Orm/RelationManager.php @@ -30,14 +30,17 @@ namespace Espo\Core\Utils\Database\Orm; use Espo\Core\Utils\Util; +use Espo\Core\Utils\Metadata; +use Espo\Core\Utils\Config; class RelationManager { private $metadata; - public function __construct(\Espo\Core\Utils\Metadata $metadata) + public function __construct(Metadata $metadata, Config $config) { $this->metadata = $metadata; + $this->config = $config; } protected function getMetadata() @@ -132,7 +135,7 @@ class RelationManager } if (isset($className) && $className !== false) { - $helperClass = new $className($this->metadata, $ormMetadata, $entityDefs); + $helperClass = new $className($this->metadata, $ormMetadata, $entityDefs, $this->config); return $helperClass->process($linkName, $entityName, $foreignLink['name'], $foreignEntityName); } //END: relationDefs defined in separate file diff --git a/application/Espo/Core/defaults/config.php b/application/Espo/Core/defaults/config.php index 33f2d5bb43..cfd1c3d013 100644 --- a/application/Espo/Core/defaults/config.php +++ b/application/Espo/Core/defaults/config.php @@ -179,5 +179,6 @@ return [ 'emailForceUseExternalClient' => false, 'useWebSocket' => false, 'auth2FAMethodList' => ['Totp'], + 'personNameFormat' => 'firstLast', 'isInstalled' => false, ]; diff --git a/application/Espo/Resources/i18n/en_US/Settings.json b/application/Espo/Resources/i18n/en_US/Settings.json index 7fb4edfa74..d1385fcde2 100644 --- a/application/Espo/Resources/i18n/en_US/Settings.json +++ b/application/Espo/Resources/i18n/en_US/Settings.json @@ -83,6 +83,7 @@ "siteUrl": "Site URL", "addressPreview": "Address Preview", "addressFormat": "Address Format", + "personNameFormat": "Person Name Format", "notificationSoundsDisabled": "Disable Notification Sounds", "applicationName": "Application Name", "calendarEntityList": "Calendar Entity List", @@ -138,6 +139,10 @@ "1": "10 USD", "2": "$10" }, + "personNameFormat": { + "firstLast": "First Last", + "lastFirst": "Last First" + }, "streamEmailNotificationsTypeList": { "Post": "Posts", "Status": "Status updates", diff --git a/application/Espo/Resources/layouts/Settings/settings.json b/application/Espo/Resources/layouts/Settings/settings.json index d87b396c3d..9102e20dd6 100644 --- a/application/Espo/Resources/layouts/Settings/settings.json +++ b/application/Espo/Resources/layouts/Settings/settings.json @@ -27,7 +27,8 @@ [{"name": "language"}, {"name": "timeZone"}], [{"name": "dateFormat"}, {"name": "weekStart"}], [{"name": "timeFormat"}, {"name": "thousandSeparator"}], - [{"name": "fiscalYearShift"}, {"name": "decimalMark"}], + [{"name": "fiscalYearShift"}, {"name": "decimalMark"}], + [{"name": "personNameFormat"}, false], [{"name": "addressFormat"}, {"name": "addressPreview"}], [{"name": "addressCountryList"}, {"name": "addressCityList"}], [{"name": "addressStateList"}, false] diff --git a/application/Espo/Resources/metadata/app/containerServices.json b/application/Espo/Resources/metadata/app/containerServices.json index 7499f843c2..32079dd0cd 100644 --- a/application/Espo/Resources/metadata/app/containerServices.json +++ b/application/Espo/Resources/metadata/app/containerServices.json @@ -2,5 +2,9 @@ "clientManager": { "className": "\\Espo\\Core\\Utils\\ClientManager", "dependencyList": ["config", "themeManager", "metadata"] + }, + "entityManagerHelper": { + "className": "\\Espo\\Core\\ORM\\Helper", + "dependencyList": ["config"] } } \ No newline at end of file diff --git a/application/Espo/Resources/metadata/entityDefs/Settings.json b/application/Espo/Resources/metadata/entityDefs/Settings.json index af635db5f7..fda348bdac 100644 --- a/application/Espo/Resources/metadata/entityDefs/Settings.json +++ b/application/Espo/Resources/metadata/entityDefs/Settings.json @@ -453,6 +453,10 @@ "readOnly": true, "view": "views/settings/fields/address-preview" }, + "personNameFormat": { + "type": "enum", + "options": ["firstLast", "lastFirst"] + }, "currencyFormat": { "type": "enumInt", "options": [1, 2] diff --git a/application/Espo/Services/Settings.php b/application/Espo/Services/Settings.php index e3927c1e12..516ed48aca 100644 --- a/application/Espo/Services/Settings.php +++ b/application/Espo/Services/Settings.php @@ -197,8 +197,6 @@ class Settings extends \Espo\Core\Services\Base if ( (isset($data->useCache) && $data->useCache !== $this->getConfig()->get('useCache')) - || - (isset($data->aclStrictMode) && $data->aclStrictMode !== $this->getConfig()->get('aclStrictMode')) ) { $this->getContainer()->get('dataManager')->clearCache(); } @@ -211,6 +209,10 @@ class Settings extends \Espo\Core\Services\Base throw new Error('Cannot save settings'); } + if (isset($data->personNameFormat)) { + $this->getContainer()->get('dataManager')->clearCache(); + } + if (isset($data->defaultCurrency) || isset($data->baseCurrency) || isset($data->currencyRates)) { $this->getContainer()->get('dataManager')->rebuildDatabase([]); } diff --git a/client/res/templates/fields/person-name/detail.tpl b/client/res/templates/fields/person-name/detail.tpl index 702ccf1880..c7fc8bc67c 100644 --- a/client/res/templates/fields/person-name/detail.tpl +++ b/client/res/templates/fields/person-name/detail.tpl @@ -1,3 +1,5 @@ -{{#if isNotEmpty}}{{translateOption salutationValue field='salutationName' scope=scope}} {{firstValue}} {{lastValue}}{{else}} +{{#if isNotEmpty}}{{formattedValue}} +{{else}} {{#if valueIsSet}}{{{translate 'None'}}}{{else}}...{{/if}} -{{/if}} \ No newline at end of file +{{/if}} + diff --git a/client/res/templates/fields/person-name/edit-last-first.tpl b/client/res/templates/fields/person-name/edit-last-first.tpl new file mode 100644 index 0000000000..621e2d600c --- /dev/null +++ b/client/res/templates/fields/person-name/edit-last-first.tpl @@ -0,0 +1,13 @@ +
+
+ +
+
+ +
+
+ +
+
diff --git a/client/src/views/fields/person-name.js b/client/src/views/fields/person-name.js index 1f594bfe35..dddf32ad62 100644 --- a/client/src/views/fields/person-name.js +++ b/client/src/views/fields/person-name.js @@ -26,7 +26,7 @@ * these Appropriate Legal Notices must retain the display of the "EspoCRM" word. ************************************************************************/ -Espo.define('views/fields/person-name', 'views/fields/varchar', function (Dep) { +define('views/fields/person-name', 'views/fields/varchar', function (Dep) { return Dep.extend({ @@ -36,6 +36,8 @@ Espo.define('views/fields/person-name', 'views/fields/varchar', function (Dep) { editTemplate: 'fields/person-name/edit', + editTemplateLastFirst: 'fields/person-name/edit-last-first', + data: function () { var data = Dep.prototype.data.call(this); data.ucName = Espo.Utils.upperCaseFirst(this.name); @@ -53,6 +55,11 @@ Espo.define('views/fields/person-name', 'views/fields/varchar', function (Dep) { } else if (this.mode === 'list' || this.mode === 'listLink') { data.isNotEmpty = !!data.firstValue || !!data.lastValue; } + + if (data.isNotEmpty && this.mode == 'detail' || this.mode == 'list' || this.mode === 'listLink') { + data.formattedValue = this.getFormattedValue(); + } + return data; }, @@ -83,6 +90,51 @@ Espo.define('views/fields/person-name', 'views/fields/varchar', function (Dep) { } }, + getFormattedValue: function () { + var salutation = this.model.get(this.salutationField); + var first = this.model.get(this.firstField); + var last = this.model.get(this.lastField); + + if (salutation) { + salutation = this.getLanguage().translateOption(salutation, 'salutationName', this.model.entityType); + } + + var value = ''; + + var format = this.getFormat(); + + switch (format) { + case 'lastFirst': + if (salutation) value += salutation; + if (last) value += ' ' + last; + if (first) value += ' ' + first; + break; + + default: + if (salutation) value += salutation; + if (first) value += ' ' + first; + if (last) value += ' ' + last; + } + + value = value.trim(); + + return value; + }, + + _getTemplateName: function () { + if (this.mode == 'edit') { + var prop = 'editTemplate' + Espo.Utils.upperCaseFirst(this.getFormat().toString()); + if (prop in this) { + return this[prop]; + } + } + return Dep.prototype._getTemplateName.call(this); + }, + + getFormat: function () { + return this.getConfig().get('personNameFormat') || 'firstLast'; + }, + validateRequired: function () { var isRequired = this.isRequired(); @@ -124,6 +176,6 @@ Espo.define('views/fields/person-name', 'views/fields/varchar', function (Dep) { data[this.firstField] = this.$first.val().trim(); data[this.lastField] = this.$last.val().trim(); return data; - } + }, }); });