From ece79240a25c94c2d079716771f85628fa2fe015 Mon Sep 17 00:00:00 2001 From: gggeek Date: Wed, 3 Apr 2019 16:30:12 +0000 Subject: [PATCH] introduce dedicated exceptions for matchers --- .../InvalidMatchConditionsException.php | 7 +++ .../InvalidMatchResultsNumberException.php | 7 +++ .../InvalidSortConditionsException.php | 7 +++ API/KeyMatcherInterface.php | 3 +- API/MatcherInterface.php | 4 +- API/SortingMatcherInterface.php | 6 ++- Command/GenerateCommand.php | 14 +----- Core/Matcher/AbstractMatcher.php | 35 ++++++++++--- Core/Matcher/ContentMatcher.php | 3 +- Core/Matcher/ContentVersionMatcher.php | 14 +++--- Core/Matcher/LocationMatcher.php | 8 +-- Core/Matcher/QueryBasedMatcher.php | 49 +++++++++++-------- Core/Matcher/ReferenceMatcher.php | 5 +- Core/Matcher/TagMatcher.php | 3 +- 14 files changed, 109 insertions(+), 56 deletions(-) create mode 100644 API/Exception/InvalidMatchConditionsException.php create mode 100644 API/Exception/InvalidMatchResultsNumberException.php create mode 100644 API/Exception/InvalidSortConditionsException.php diff --git a/API/Exception/InvalidMatchConditionsException.php b/API/Exception/InvalidMatchConditionsException.php new file mode 100644 index 0000000..c10d55c --- /dev/null +++ b/API/Exception/InvalidMatchConditionsException.php @@ -0,0 +1,7 @@ +addOption('match-except', null, InputOption::VALUE_NONE, 'Used to match all entities except the ones satisfying the match-value condition', null) ->addOption('lang', 'l', InputOption::VALUE_REQUIRED, 'The language of the migration (eng-GB, ger-DE, ...). If null, the default language of the current siteaccess is used') ->addOption('dbserver', null, InputOption::VALUE_REQUIRED, 'The type of the database server the sql migration is for, when type=db (mysql, postgresql, ...)', 'mysql') - ->addOption('role', null, InputOption::VALUE_REQUIRED, 'Deprecated: The role identifier (or id) that you would like to update, for type=role', null) ->addOption('admin-login', 'a', InputOption::VALUE_REQUIRED, "Login of admin account used whenever elevated privileges are needed (user id 14 used by default)") ->addArgument('bundle', InputArgument::REQUIRED, 'The bundle to generate the migration definition file in. eg.: AcmeMigrationBundle') ->addArgument('name', InputArgument::OPTIONAL, 'The migration name (will be prefixed with current date)', null) @@ -52,7 +51,7 @@ For SQL type migration you can optionally specify the database server type the m php ezpublish/console kaliop:migration:generate --format=sql bundleName -For role/content/content_type migrations you need to specify the entity that you want to generate the migration for: +For role/content/content_type/language/object_state/section migrations you need to specify the entity that you want to generate the migration for: php ezpublish/console kaliop:migration:generate --type=content --match-type=content_id --match-value=10,14 bundleName @@ -85,23 +84,12 @@ EOT $name = $input->getArgument('name'); $fileType = $input->getOption('format'); $migrationType = $input->getOption('type'); - $role = $input->getOption('role'); $matchType = $input->getOption('match-type'); $matchValue = $input->getOption('match-value'); $matchExcept = $input->getOption('match-except'); $mode = $input->getOption('mode'); $dbServer = $input->getOption('dbserver'); - if ($role != '') { - $output->writeln('The "role" option is deprecated since version 3.2 and will be removed in 4.0. Use "type=role", "match-type=identifier" and "match-value" instead.'); - $migrationType = 'role'; - $matchType = 'identifier'; - $matchValue = $role; - if ($mode == '') { - $mode = 'update'; - } - } - if ($bundleName == $this->thisBundle) { throw new \InvalidArgumentException("It is not allowed to create migrations in bundle '$bundleName'"); } diff --git a/Core/Matcher/AbstractMatcher.php b/Core/Matcher/AbstractMatcher.php index c3fc4ab..5b9cdf8 100644 --- a/Core/Matcher/AbstractMatcher.php +++ b/Core/Matcher/AbstractMatcher.php @@ -3,6 +3,8 @@ namespace Kaliop\eZMigrationBundle\Core\Matcher; use Kaliop\eZMigrationBundle\API\MatcherInterface; +use Kaliop\eZMigrationBundle\API\Exception\InvalidMatchResultsNumberException; +use Kaliop\eZMigrationBundle\API\Exception\InvalidMatchConditionsException; abstract class AbstractMatcher implements MatcherInterface { @@ -15,29 +17,38 @@ abstract class AbstractMatcher implements MatcherInterface /** @var int $minConditions the minimum number of conditions we allow to match on for a single match request. It could be replaced with an array of mandatory conditions, really... */ protected $minConditions = 1; + /** + * @param array $conditions + * @throws InvalidMatchConditionsException + */ protected function validateConditions(array $conditions) { if ($this->minConditions > 0 && count($conditions) < $this->minConditions) { - throw new \Exception($this->returns . ' can not be matched because the matching conditions are empty'); + throw new InvalidMatchConditionsException($this->returns . ' can not be matched because the matching conditions are empty'); } if ($this->maxConditions > 0 && count($conditions) > $this->maxConditions) { - throw new \Exception($this->returns . " can not be matched because multiple matching conditions are specified. Only {$this->maxConditions} condition(s) are supported"); + throw new InvalidMatchConditionsException($this->returns . " can not be matched because multiple matching conditions are specified. Only {$this->maxConditions} condition(s) are supported"); } foreach ($conditions as $key => $value) { if (!in_array((string)$key, $this->allowedConditions)) { - throw new \Exception($this->returns . " can not be matched because matching condition '$key' is not supported. Supported conditions are: " . + throw new InvalidMatchConditionsException($this->returns . " can not be matched because matching condition '$key' is not supported. Supported conditions are: " . implode(', ', $this->allowedConditions)); } } } + /** + * @param $conditionsArray + * @return array|\ArrayObject + * @throws InvalidMatchConditionsException + */ protected function matchAnd($conditionsArray) { /// @todo introduce proper re-validation of all child conditions if (!is_array($conditionsArray) || !count($conditionsArray)) { - throw new \Exception($this->returns . " can not be matched because no matching conditions found for 'and' clause."); + throw new InvalidMatchConditionsException($this->returns . " can not be matched because no matching conditions found for 'and' clause."); } $class = null; @@ -61,11 +72,16 @@ abstract class AbstractMatcher implements MatcherInterface return $results; } + /** + * @param $conditionsArray + * @return array + * @throws InvalidMatchConditionsException + */ protected function matchOr($conditionsArray) { /// @todo introduce proper re-validation of all child conditions if (!is_array($conditionsArray) || !count($conditionsArray)) { - throw new \Exception($this->returns . " can not be matched because no matching conditions found for 'or' clause."); + throw new InvalidMatchConditionsException($this->returns . " can not be matched because no matching conditions found for 'or' clause."); } $class = null; @@ -86,12 +102,18 @@ abstract class AbstractMatcher implements MatcherInterface return $results; } + /** + * @param array $conditions + * @return mixed + * @throws InvalidMatchConditionsException + * @throws InvalidMatchResultsNumberException + */ public function matchOne(array $conditions) { $results = $this->match($conditions); $count = count($results); if ($count !== 1) { - throw new \Exception("Found $count " . $this->returns . " when expected exactly only one to match the conditions"); + throw new InvalidMatchResultsNumberException("Found $count " . $this->returns . " when expected exactly only one to match the conditions"); } return reset($results); } @@ -99,6 +121,7 @@ abstract class AbstractMatcher implements MatcherInterface /** * @param array $conditions * @return array|\ArrayObject the keys must be a unique identifier of the matched entities + * @throws \Kaliop\eZMigrationBundle\API\Exception\InvalidMatchConditionsException */ abstract public function match(array $conditions); } diff --git a/Core/Matcher/ContentMatcher.php b/Core/Matcher/ContentMatcher.php index f1a485a..8094e42 100644 --- a/Core/Matcher/ContentMatcher.php +++ b/Core/Matcher/ContentMatcher.php @@ -6,6 +6,7 @@ use eZ\Publish\API\Repository\Values\Content\Content; use eZ\Publish\API\Repository\Values\Content\Query; use Kaliop\eZMigrationBundle\API\Collection\ContentCollection; use Kaliop\eZMigrationBundle\API\SortingMatcherInterface; +use Kaliop\eZMigrationBundle\API\Exception\InvalidMatchResultsNumberException; class ContentMatcher extends QueryBasedMatcher implements SortingMatcherInterface { @@ -45,7 +46,7 @@ class ContentMatcher extends QueryBasedMatcher implements SortingMatcherInterfac $results = $this->match($conditions, $sort, $offset, 2); $count = count($results); if ($count !== 1) { - throw new \Exception("Found $count " . $this->returns . " when expected exactly only one to match the conditions"); + throw new InvalidMatchResultsNumberException("Found $count " . $this->returns . " when expected exactly only one to match the conditions"); } return reset($results); } diff --git a/Core/Matcher/ContentVersionMatcher.php b/Core/Matcher/ContentVersionMatcher.php index f5a00e3..78022a7 100644 --- a/Core/Matcher/ContentVersionMatcher.php +++ b/Core/Matcher/ContentVersionMatcher.php @@ -5,9 +5,10 @@ namespace Kaliop\eZMigrationBundle\Core\Matcher; use eZ\Publish\API\Repository\Repository; use eZ\Publish\API\Repository\Values\Content\Content; use \eZ\Publish\API\Repository\Values\Content\VersionInfo; -use eZ\Publish\Core\Base\Exceptions\NotFoundException; use Kaliop\eZMigrationBundle\API\MatcherInterface; use Kaliop\eZMigrationBundle\API\Collection\VersionInfoCollection; +use Kaliop\eZMigrationBundle\API\Exception\InvalidMatchResultsNumberException; +use Kaliop\eZMigrationBundle\API\Exception\InvalidMatchConditionsException; class ContentVersionMatcher extends RepositoryMatcher implements MatcherInterface { @@ -67,7 +68,7 @@ class ContentVersionMatcher extends RepositoryMatcher implements MatcherInterfac $results = $this->match($contentConditions, $versionConditions, $sort, $offset, 2); $count = count($results); if ($count !== 1) { - throw new \Exception("Found $count " . $this->returns . " when expected exactly only one to match the conditions"); + throw new InvalidMatchResultsNumberException("Found $count " . $this->returns . " when expected exactly only one to match the conditions"); } return reset($results); } @@ -114,13 +115,14 @@ class ContentVersionMatcher extends RepositoryMatcher implements MatcherInterfac { /// @todo introduce proper re-validation of all child conditions if (!is_array($conditionsArray) || !count($conditionsArray)) { - throw new \Exception($this->returns . " can not be matched because no matching conditions found for 'and' clause."); + throw new InvalidMatchConditionsException($this->returns . " can not be matched because no matching conditions found for 'and' clause."); } if (is_null($content)) { - throw new \Exception($this->returns . " can not be matched because there was no content to match for 'and' clause."); + throw new InvalidMatchConditionsException($this->returns . " can not be matched because there was no content to match for 'and' clause."); } + $results = array(); foreach ($conditionsArray as $conditions) { $out = $this->matchContentVersions($conditions, $content); if (!isset($results)) { @@ -137,11 +139,11 @@ class ContentVersionMatcher extends RepositoryMatcher implements MatcherInterfac { /// @todo introduce proper re-validation of all child conditions if (!is_array($conditionsArray) || !count($conditionsArray)) { - throw new \Exception($this->returns . " can not be matched because no matching conditions found for 'or' clause."); + throw new InvalidMatchConditionsException($this->returns . " can not be matched because no matching conditions found for 'or' clause."); } if (is_null($content)) { - throw new \Exception($this->returns . " can not be matched because there was no content to match for 'or' clause."); + throw new InvalidMatchConditionsException($this->returns . " can not be matched because there was no content to match for 'or' clause."); } $results = array(); diff --git a/Core/Matcher/LocationMatcher.php b/Core/Matcher/LocationMatcher.php index 67a7db3..a69d71e 100644 --- a/Core/Matcher/LocationMatcher.php +++ b/Core/Matcher/LocationMatcher.php @@ -7,6 +7,8 @@ use eZ\Publish\API\Repository\Values\Content\LocationQuery; use eZ\Publish\API\Repository\Values\Content\Location; use Kaliop\eZMigrationBundle\API\Collection\LocationCollection; use Kaliop\eZMigrationBundle\API\SortingMatcherInterface; +use Kaliop\eZMigrationBundle\API\Exception\InvalidMatchResultsNumberException; +use Kaliop\eZMigrationBundle\API\Exception\InvalidMatchConditionsException; class LocationMatcher extends QueryBasedMatcher implements SortingMatcherInterface { @@ -47,7 +49,7 @@ class LocationMatcher extends QueryBasedMatcher implements SortingMatcherInterfa $results = $this->match($conditions, $sort, $offset, 2); $count = count($results); if ($count !== 1) { - throw new \Exception("Found $count " . $this->returns . " when expected exactly only one to match the conditions"); + throw new InvalidMatchResultsNumberException("Found $count " . $this->returns . " when expected exactly only one to match the conditions"); } return reset($results); } @@ -108,7 +110,7 @@ class LocationMatcher extends QueryBasedMatcher implements SortingMatcherInterfa $match = reset($values); $operator = key($values); if (!isset(self::$operatorsMap[$operator])) { - throw new \Exception("Can not use '$operator' as comparison operator for depth"); + throw new InvalidMatchConditionsException("Can not use '$operator' as comparison operator for depth"); } return new Query\Criterion\Location\Depth(self::$operatorsMap[$operator], $match); @@ -126,7 +128,7 @@ class LocationMatcher extends QueryBasedMatcher implements SortingMatcherInterfa $match = reset($values); $operator = key($values); if (!isset(self::$operatorsMap[$operator])) { - throw new \Exception("Can not use '$operator' as comparison operator for depth"); + throw new InvalidMatchConditionsException("Can not use '$operator' as comparison operator for depth"); } return new Query\Criterion\Location\Priority(self::$operatorsMap[$operator], $match); } diff --git a/Core/Matcher/QueryBasedMatcher.php b/Core/Matcher/QueryBasedMatcher.php index 91a1975..870687c 100644 --- a/Core/Matcher/QueryBasedMatcher.php +++ b/Core/Matcher/QueryBasedMatcher.php @@ -4,9 +4,11 @@ namespace Kaliop\eZMigrationBundle\Core\Matcher; use eZ\Publish\API\Repository\Values\Content\Query; use eZ\Publish\API\Repository\Values\Content\Query\SortClause; +use eZ\Publish\API\Repository\Values\Content\Query\Criterion\Operator; use eZ\Publish\API\Repository\Repository; use Kaliop\eZMigrationBundle\API\KeyMatcherInterface; -use eZ\Publish\API\Repository\Values\Content\Query\Criterion\Operator; +use Kaliop\eZMigrationBundle\API\Exception\InvalidSortConditionsException; +use Kaliop\eZMigrationBundle\API\Exception\InvalidMatchConditionsException; /** * @todo extend to allow matching by modifier, language code, content_type_group_id @@ -97,7 +99,7 @@ abstract class QueryBasedMatcher extends RepositoryMatcher * @param $key * @param $values * @return mixed should it be \eZ\Publish\API\Repository\Values\Content\Query\CriterionInterface ? - * @throws \Exception for unsupported keys + * @throws InvalidMatchConditionsException for unsupported keys */ protected function getQueryCriterion($key, $values) { @@ -125,7 +127,7 @@ abstract class QueryBasedMatcher extends RepositoryMatcher $match = reset($spec); $operator = key($spec); if (!isset(self::$operatorsMap[$operator])) { - throw new \Exception("Can not use '$operator' as comparison operator for attributes"); + throw new InvalidMatchConditionsException("Can not use '$operator' as comparison operator for attributes"); } return new Query\Criterion\Field($attribute, self::$operatorsMap[$operator], $match); @@ -141,7 +143,7 @@ abstract class QueryBasedMatcher extends RepositoryMatcher $match = reset($values); $operator = key($values); if (!isset(self::$operatorsMap[$operator])) { - throw new \Exception("Can not use '$operator' as comparison operator for dates"); + throw new InvalidMatchConditionsException("Can not use '$operator' as comparison operator for dates"); } return new Query\Criterion\DateMetadata(Query\Criterion\DateMetadata::CREATED, self::$operatorsMap[$operator], $match); @@ -160,7 +162,7 @@ abstract class QueryBasedMatcher extends RepositoryMatcher $match = reset($values); $operator = key($values); if (!isset(self::$operatorsMap[$operator])) { - throw new \Exception("Can not use '$operator' as comparison operator for dates"); + throw new InvalidMatchConditionsException("Can not use '$operator' as comparison operator for dates"); } return new Query\Criterion\DateMetadata(Query\Criterion\DateMetadata::MODIFIED, self::$operatorsMap[$operator], $match); @@ -235,11 +237,16 @@ abstract class QueryBasedMatcher extends RepositoryMatcher return new Query\Criterion\LogicalNot($subCriterion); default: - throw new \Exception($this->returns . " can not be matched because matching condition '$key' is not supported. Supported conditions are: " . + throw new InvalidMatchConditionsException($this->returns . " can not be matched because matching condition '$key' is not supported. Supported conditions are: " . implode(', ', $this->allowedConditions)); } } + /** + * @param array $sortDefinition + * @return array + * @throws InvalidSortConditionsException + */ protected function getSortClauses(array $sortDefinition) { $out = array(); @@ -250,7 +257,7 @@ abstract class QueryBasedMatcher extends RepositoryMatcher $sortItem = array('sort_field' => $sortItem); } if (!is_array($sortItem) || !isset($sortItem['sort_field'])) { - throw new \Exception("Missing sort_field element in sorting definition"); + throw new InvalidSortConditionsException("Missing sort_field element in sorting definition"); } if (!isset($sortItem['sort_order'])) { // we have to pick a default ;-) @@ -260,48 +267,48 @@ abstract class QueryBasedMatcher extends RepositoryMatcher $direction = $this->hash2SortOrder($sortItem['sort_order']); switch($sortItem['sort_field']) { - case SELF::SORT_CONTENT_ID: + case self::SORT_CONTENT_ID: $out[] = new SortClause\ContentId($direction); break; - case SELF::SORT_CONTENT_NAME: + case self::SORT_CONTENT_NAME: $out[] = new SortClause\ContentName($direction); break; - case SELF::SORT_DATE_MODIFIED: + case self::SORT_DATE_MODIFIED: $out[] = new SortClause\DateModified($direction); break; - case SELF::SORT_DATE_PUBLISHED: + case self::SORT_DATE_PUBLISHED: $out[] = new SortClause\DatePublished($direction); break; /// @todo - //case SELF::SORT_FIELD: + //case self::SORT_FIELD: // $out[] = new SortClause\Field($direction); // break; - case SELF::SORT_LOCATION_DEPTH: + case self::SORT_LOCATION_DEPTH: $out[] = new SortClause\Location\Depth($direction); break; - case SELF::SORT_LOCATION_ID: + case self::SORT_LOCATION_ID: $out[] = new SortClause\Location\Id($direction); break; - case SELF::SORT_LOCATION_ISMAIN: + case self::SORT_LOCATION_ISMAIN: $out[] = new SortClause\Location\IsMainLocation($direction); break; - case SELF::SORT_LOCATION_PATH: + case self::SORT_LOCATION_PATH: $out[] = new SortClause\Location\Path($direction); break; - case SELF::SORT_LOCATION_PRIORITY: + case self::SORT_LOCATION_PRIORITY: $out[] = new SortClause\Location\Priority($direction); break; - case SELF::SORT_LOCATION_VISIBILITY: + case self::SORT_LOCATION_VISIBILITY: $out[] = new SortClause\Location\Visibility($direction); break; - case SELF::SORT_SECTION_IDENTIFIER: + case self::SORT_SECTION_IDENTIFIER: $out[] = new SortClause\SectionIdentifier($direction); break; - case SELF::SORT_SECTION_NAME: + case self::SORT_SECTION_NAME: $out[] = new SortClause\SectionName($direction); break; default: - throw new \Exception("Sort field '{$sortItem['sort_field']}' not implemented"); + throw new InvalidSortConditionsException("Sort field '{$sortItem['sort_field']}' not implemented"); } } diff --git a/Core/Matcher/ReferenceMatcher.php b/Core/Matcher/ReferenceMatcher.php index b43ed4e..24f2ff5 100644 --- a/Core/Matcher/ReferenceMatcher.php +++ b/Core/Matcher/ReferenceMatcher.php @@ -2,9 +2,10 @@ namespace Kaliop\eZMigrationBundle\Core\Matcher; -use eZ\Publish\API\Repository\Values\Content\Query\Criterion\Operator; use Symfony\Component\Validator\Validator\ValidatorInterface; +use eZ\Publish\API\Repository\Values\Content\Query\Criterion\Operator; use Kaliop\eZMigrationBundle\API\ReferenceResolverInterface; +use Kaliop\eZMigrationBundle\API\Exception\InvalidMatchConditionsException; /** * We abuse a bit the 'matcher' framework to set up a 'constraint' matcher which is used to tell whether a reference @@ -129,7 +130,7 @@ class ReferenceMatcher extends AbstractMatcher protected function getConstraint($constraint, $targetValue) { if (!isset(self::$operatorsMap[$constraint])) { - throw new \Exception("Matching condition '$constraint' is not supported. Supported conditions are: " . + throw new InvalidMatchConditionsException("Matching condition '$constraint' is not supported. Supported conditions are: " . implode(', ', array_keys(self::$operatorsMap)) ); } diff --git a/Core/Matcher/TagMatcher.php b/Core/Matcher/TagMatcher.php index ec8839d..613c022 100644 --- a/Core/Matcher/TagMatcher.php +++ b/Core/Matcher/TagMatcher.php @@ -4,6 +4,7 @@ namespace Kaliop\eZMigrationBundle\Core\Matcher; use Kaliop\eZMigrationBundle\API\Collection\TagCollection; use Kaliop\eZMigrationBundle\API\KeyMatcherInterface; +use Kaliop\eZMigrationBundle\API\Exception\InvalidMatchConditionsException; /** * @todo when matching by keyword, allow to pick the desired language @@ -97,7 +98,7 @@ class TagMatcher extends AbstractMatcher implements KeyMatcherInterface return array(self::MATCH_TAG_ID => $key); } - throw new \Exception("Tag matcher can not uniquely identify the type of key used to match: " . $key); + throw new InvalidMatchConditionsException("Tag matcher can not uniquely identify the type of key used to match: " . $key); } /**