From 9f743b718aa327e796f382798652492335df059b Mon Sep 17 00:00:00 2001 From: Yuri Kuznetsov Date: Thu, 15 Feb 2024 16:20:51 +0200 Subject: [PATCH] custom prefix --- .../Espo/Controllers/EntityManager.php | 6 ++--- application/Espo/Controllers/FieldManager.php | 6 ++--- .../Espo/Resources/defaults/config.php | 1 + .../Espo/Resources/defaults/systemConfig.php | 1 + .../Tools/EntityManager/EntityManager.php | 7 +++++- .../Espo/Tools/EntityManager/NameUtil.php | 15 +++++++++++- .../Espo/Tools/FieldManager/FieldManager.php | 13 +++++++++-- .../Espo/Tools/LinkManager/LinkManager.php | 23 +++++++++++++++---- client/src/views/admin/entity-manager/edit.js | 4 ++-- .../integration/Espo/Record/SanitizeTest.php | 8 +++---- 10 files changed, 64 insertions(+), 20 deletions(-) diff --git a/application/Espo/Controllers/EntityManager.php b/application/Espo/Controllers/EntityManager.php index 58ef4e402d..a500ad9ffb 100644 --- a/application/Espo/Controllers/EntityManager.php +++ b/application/Espo/Controllers/EntityManager.php @@ -66,7 +66,7 @@ class EntityManager * @throws Error * @throws Conflict */ - public function postActionCreateEntity(Request $request): bool + public function postActionCreateEntity(Request $request): stdClass { $data = $request->getParsedBody(); @@ -142,9 +142,9 @@ class EntityManager $params['kanbanStatusIgnoreList'] = $data['kanbanStatusIgnoreList']; } - $this->entityManagerTool->create($name, $type, $params); + $name = $this->entityManagerTool->create($name, $type, $params); - return true; + return (object) ['name' => $name]; } /** diff --git a/application/Espo/Controllers/FieldManager.php b/application/Espo/Controllers/FieldManager.php index 1e49f2de68..35355d41ec 100644 --- a/application/Espo/Controllers/FieldManager.php +++ b/application/Espo/Controllers/FieldManager.php @@ -100,18 +100,18 @@ class FieldManager $fieldManagerTool = $this->fieldManagerTool; - $fieldManagerTool->create($scope, $name, get_object_vars($data)); + $name = $fieldManagerTool->create($scope, $name, get_object_vars($data)); try { $this->dataManager->rebuild([$scope]); } catch (Error $e) { - $fieldManagerTool->delete($scope, $data->name); + $fieldManagerTool->delete($scope, $name); throw new Error($e->getMessage()); } - return $fieldManagerTool->read($scope, $data->name); + return $fieldManagerTool->read($scope, $name); } /** diff --git a/application/Espo/Resources/defaults/config.php b/application/Espo/Resources/defaults/config.php index 3aaac30cd4..b09cba00a2 100644 --- a/application/Espo/Resources/defaults/config.php +++ b/application/Espo/Resources/defaults/config.php @@ -288,5 +288,6 @@ return [ 'phoneNumberPreferredCountryList' => ['us', 'de'], 'adminUpgradeDisabled' => false, 'wysiwygCodeEditorDisabled' => false, + 'customPrefixDisabled' => false, 'isInstalled' => false, ]; diff --git a/application/Espo/Resources/defaults/systemConfig.php b/application/Espo/Resources/defaults/systemConfig.php index 22325dbdf8..54deb69e67 100644 --- a/application/Espo/Resources/defaults/systemConfig.php +++ b/application/Espo/Resources/defaults/systemConfig.php @@ -205,6 +205,7 @@ return [ 'authAnotherUserDisabled', 'emailAddressEntityLookupDefaultOrder', 'phoneNumberEntityLookupDefaultOrder', + 'customPrefixDisabled', 'latestVersion', ], 'superAdminItems' => [ diff --git a/application/Espo/Tools/EntityManager/EntityManager.php b/application/Espo/Tools/EntityManager/EntityManager.php index e0e401b90c..d9689fb979 100644 --- a/application/Espo/Tools/EntityManager/EntityManager.php +++ b/application/Espo/Tools/EntityManager/EntityManager.php @@ -71,11 +71,12 @@ class EntityManager /** * @param array $params + * @return string An actual name. * @throws BadRequest * @throws Error * @throws Conflict */ - public function create(string $name, string $type, array $params = [], ?CreateParams $createParams = null): void + public function create(string $name, string $type, array $params = [], ?CreateParams $createParams = null): string { $createParams ??= new CreateParams(); @@ -97,6 +98,8 @@ class EntityManager throw new Error("Type '$type' is not creatable."); } + $name = $this->nameUtil->addCustomPrefix($name, true); + if ($this->nameUtil->nameIsBad($name)) { throw new Error("Entity name should contain only letters and numbers, " . "start with an upper case letter."); @@ -285,6 +288,8 @@ class EntityManager } $this->dataManager->rebuild(); + + return $name; } /** diff --git a/application/Espo/Tools/EntityManager/NameUtil.php b/application/Espo/Tools/EntityManager/NameUtil.php index 684a8d0664..814b606e7a 100644 --- a/application/Espo/Tools/EntityManager/NameUtil.php +++ b/application/Espo/Tools/EntityManager/NameUtil.php @@ -29,6 +29,7 @@ namespace Espo\Tools\EntityManager; +use Espo\Core\Utils\Config; use Espo\Core\Utils\Metadata; use Espo\Core\Utils\Route; use Espo\Core\Utils\Util; @@ -94,7 +95,8 @@ class NameUtil private Metadata $metadata, private ServiceFactory $serviceFactory, private EntityManager $entityManager, - private Route $routeUtil + private Route $routeUtil, + private Config $config ) {} public function nameIsBad(string $name): bool @@ -244,4 +246,15 @@ class NameUtil return false; } + + public function addCustomPrefix(string $name, bool $ucFirst = false): string + { + if ($this->config->get('customPrefixDisabled')) { + return $name; + } + + $prefix = $ucFirst ? 'C' : 'c'; + + return $prefix . ucfirst($name); + } } diff --git a/application/Espo/Tools/FieldManager/FieldManager.php b/application/Espo/Tools/FieldManager/FieldManager.php index 133ef4f4fd..98a274d1dc 100644 --- a/application/Espo/Tools/FieldManager/FieldManager.php +++ b/application/Espo/Tools/FieldManager/FieldManager.php @@ -40,6 +40,7 @@ use Espo\Core\Exceptions\Error; use Espo\Core\Utils\Metadata\Helper as MetadataHelper; use Espo\Core\Utils\Util; +use Espo\Tools\EntityManager\NameUtil; use RuntimeException; use stdClass; @@ -87,7 +88,8 @@ class FieldManager private Metadata $metadata, private Language $language, private Language $baseLanguage, - private MetadataHelper $metadataHelper + private MetadataHelper $metadataHelper, + private NameUtil $nameUtil ) {} /** @@ -113,16 +115,21 @@ class FieldManager /** * @param array $fieldDefs + * @return string An actual name. * @throws BadRequest * @throws Conflict * @throws Error */ - public function create(string $scope, string $name, array $fieldDefs): void + public function create(string $scope, string $name, array $fieldDefs): string { if (strlen($name) === 0) { throw new BadRequest("Empty field name."); } + if (!$this->isScopeCustom($scope)) { + $name = $this->nameUtil->addCustomPrefix($name); + } + if (strlen(Util::camelCaseToUnderscore($name)) > self::MAX_NAME_LENGTH) { throw Error::createWithBody( "Field name should not be longer than " . self::MAX_NAME_LENGTH . ".", @@ -199,6 +206,8 @@ class FieldManager } $this->update($scope, $name, $fieldDefs, true); + + return $name; } /** diff --git a/application/Espo/Tools/LinkManager/LinkManager.php b/application/Espo/Tools/LinkManager/LinkManager.php index 3084abeca7..9e692cdf9d 100644 --- a/application/Espo/Tools/LinkManager/LinkManager.php +++ b/application/Espo/Tools/LinkManager/LinkManager.php @@ -124,6 +124,8 @@ class LinkManager $params['relationName'] : lcfirst($entity) . $entityForeign; + $relationName = $this->nameUtil->addCustomPrefix($relationName); + if ($this->isNameTooLong($relationName)) { throw new Error("Relation name is too long."); } @@ -141,6 +143,14 @@ class LinkManager } } + if (!$this->isScopeCustom($entity)) { + $link = $this->nameUtil->addCustomPrefix($link); + } + + if (!$entityForeign || !$this->isScopeCustom($entityForeign)) { + $linkForeign = $this->nameUtil->addCustomPrefix($linkForeign); + } + $linkParams = LinkParams::createBuilder() ->setType($linkType) ->setEntityType($entity) @@ -150,6 +160,10 @@ class LinkManager ->setName($relationName) ->build(); + if (is_numeric($link[0]) || is_numeric($linkForeign[0])) { + throw new Error('Bad link name.'); + } + if ( $this->isNameTooLong($link) || $this->isNameTooLong($linkForeign) @@ -157,10 +171,6 @@ class LinkManager throw new Error("Link name is too long."); } - if (is_numeric($link[0]) || is_numeric($linkForeign[0])) { - throw new Error('Bad link name.'); - } - if (preg_match('/[^a-z]/', $link[0])) { throw new Error("Link name should start with a lower case letter."); } @@ -1089,4 +1099,9 @@ class LinkManager $this->baseLanguage->save(); } } + + private function isScopeCustom(string $scope): bool + { + return (bool) $this->metadata->get("scopes.$scope.isCustom"); + } } diff --git a/client/src/views/admin/entity-manager/edit.js b/client/src/views/admin/entity-manager/edit.js index 69a3fc6bcd..ae2fba4918 100644 --- a/client/src/views/admin/entity-manager/edit.js +++ b/client/src/views/admin/entity-manager/edit.js @@ -641,7 +641,7 @@ class EntityManagerEditView extends View { Espo.Ui.notify(this.translate('pleaseWait', 'messages')); - Espo.Ajax.postRequest(url, data).then(() => { + Espo.Ajax.postRequest(url, data).then(/** Record */response => { this.model.fetchedAttributes = this.model.getClonedAttributes(); this.scope ? @@ -685,7 +685,7 @@ class EntityManagerEditView extends View { this.getRecordView().setIsNotChanged(); if (this.isNew) { - this.getRouter().navigate('#Admin/entityManager/scope=' + name, {trigger: true}); + this.getRouter().navigate(`#Admin/entityManager/scope=${response.name}`, {trigger: true}); } }); }) diff --git a/tests/integration/Espo/Record/SanitizeTest.php b/tests/integration/Espo/Record/SanitizeTest.php index 153b1878aa..3aeef0fd93 100644 --- a/tests/integration/Espo/Record/SanitizeTest.php +++ b/tests/integration/Espo/Record/SanitizeTest.php @@ -60,7 +60,7 @@ class SanitizeTest extends BaseTestCase 'sicCode' => ' ', 'phoneNumber' => '+380 9044 433 11', 'description' => '', - 'array' => [ + 'cArray' => [ ' test ', 'hello', ], @@ -73,7 +73,7 @@ class SanitizeTest extends BaseTestCase $this->assertEquals('Test 1', $account->getName()); $this->assertEquals(null, $account->get('sicCode')); $this->assertEquals(null, $account->get('description')); - $this->assertEquals(['test', 'hello'], $account->get('array')); + $this->assertEquals(['test', 'hello'], $account->get('cArray')); /** @noinspection PhpUnhandledExceptionInspection */ /** @var Account $account */ @@ -88,11 +88,11 @@ class SanitizeTest extends BaseTestCase ], ], 'description' => 'Test', - 'array' => null, + 'cArray' => null, ], CreateParams::create()); $this->assertEquals('Test', $account->get('description')); - $this->assertEquals([], $account->get('array')); + $this->assertEquals([], $account->get('cArray')); $numbers = $account->getPhoneNumberGroup()->getNumberList(); $this->assertCount(2, $numbers);