From 33f0a3072d03ab92ac16373514cf9bde367678b1 Mon Sep 17 00:00:00 2001 From: Benn Oshrin Date: Tue, 27 Dec 2022 13:56:33 -0500 Subject: [PATCH] Require lowercase (CO-2477) and unique (CO-2440) matchgrid table names --- app/resources/locales/en_US/default.po | 3 + app/src/Model/Table/MatchgridsTable.php | 78 ++++++++++++++++++++++++- 2 files changed, 78 insertions(+), 3 deletions(-) diff --git a/app/resources/locales/en_US/default.po b/app/resources/locales/en_US/default.po index 2ff6a6af..4a6ba8e4 100644 --- a/app/resources/locales/en_US/default.po +++ b/app/resources/locales/en_US/default.po @@ -288,6 +288,9 @@ msgstr "When this value is selected, {0} cannot be empty" msgid "match.er.input.invalid" msgstr "Invalid character found" +msgid "match.er.mg.inuse" +msgstr "A Matchgrid with table name {0} already exists" + msgid "match.er.mg.notfound" msgstr "Matchgrid table not found, was the Matchgrid built? ({0})" diff --git a/app/src/Model/Table/MatchgridsTable.php b/app/src/Model/Table/MatchgridsTable.php index 1b5700b2..9911a4ad 100644 --- a/app/src/Model/Table/MatchgridsTable.php +++ b/app/src/Model/Table/MatchgridsTable.php @@ -29,9 +29,11 @@ namespace App\Model\Table; -use Cake\ORM\Query; -use Cake\ORM\Table; -use Cake\Validation\Validator; +use \Cake\Event\EventInterface; +use \Cake\ORM\Query; +use \Cake\ORM\RulesChecker; +use \Cake\ORM\Table; +use \Cake\Validation\Validator; use \App\Lib\Enum\ConfidenceModeEnum; use \App\Lib\Enum\StatusEnum; @@ -94,6 +96,24 @@ public function initialize(array $config): void { $this->setAllowLookupPrimaryLink(['build', 'manage', 'configure', 'pending', 'reconcile']); } + + /** + * Actions to perform before validation. + * + * @since @COmanage Match v1.1.0 + * @param EventInterface $event Event + * @param ArrayObject $data Data + * @param ArrayObject $options Options + */ + + public function beforeMarshal(EventInterface $event, \ArrayObject $data, \ArrayObject $options) { + // We convert the table name to lowercase to avoid problems with database + // queries due to capital letters (see CO-2477) + + if(isset($data['table_name'])) { + $data['table_name'] = mb_strtolower($data['table_name']); + } + } /** * Build the specified Matchgrid. @@ -113,6 +133,27 @@ public function build(int $id) { return true; } + /** + * Define business rules. + * + * @since COmanage Match v1.1.0 + * @param RulesChecker $rules RulesChecker object + * @return RulesChecker + */ + + public function buildRules(RulesChecker $rules): RulesChecker { + // Two Matchgrids cannot have the same name. Since the name is used + // to generate the matchgrid table name, and tablenames are usually + // treated as case insensitive, we perform a case insensitive check + // (and so can't use isUnique()). + + $rules->add([$this, 'ruleIsUnique'], + 'isUnique', + ['errorField' => 'table_name']); + + return $rules; + } + /** * Calculate the Matchgrid ID associated with the requested object ID. * @@ -162,6 +203,37 @@ public function getMatchgridConfig($id) { ]]); } + /** + * Application Rule to determine if the current entity is uniquely named + * (case insensitive). + * + * @param Entity $entity Entity to be validated + * @param array $options Application rule options + * + * @return bool|string true if the Rule check passes, false otherwise + * @since COmanage Match v1.1.0 + */ + + public function ruleIsUnique($entity, array $options): bool|string { + // We don't want to perform the uniqueness check on an update where + // the table name is not changed + + if(!$entity->id || $entity->isDirty('table_name')) { + $c = $this->find('all', [ + 'conditions' => [ + 'LOWER(Matchgrids.table_name)' => strtolower($entity->table_name) + ] + ]) + ->count(); + + if($c > 0) { + return __('match.er.mg.inuse', [$entity->table_name]); + } + } + + return true; + } + /** * Set validation rules. *