From 4a47ba8cf673f59bb7999ae24554d698aeee1aba Mon Sep 17 00:00:00 2001 From: Constantine Karnaukhov Date: Sun, 27 Sep 2020 00:50:24 +0400 Subject: [PATCH] refactor(bridge): rename Adapter namespace to Bridge --- CHANGELOG.md | 5 + composer.json | 2 +- phpstan.neon.dist | 3 + phpunit.xml.dist | 3 + .../DoctrineCollectionsCriteriaConverter.php | 48 ++---- ...DoctrineCollectionsExpressionConverter.php | 139 ++--------------- .../SpiralPagination/PaginableCriteria.php | 95 ++---------- .../DoctrineCollectionsCriteriaConverter.php | 48 ++++++ ...DoctrineCollectionsExpressionConverter.php | 142 ++++++++++++++++++ .../SpiralPagination/PaginableCriteria.php | 99 ++++++++++++ src/Criteria.php | 2 +- ...ctrineCollectionsCriteriaConverterTest.php | 2 +- .../PaginableCriteriaTest.php | 2 +- 13 files changed, 334 insertions(+), 256 deletions(-) create mode 100755 src/Bridge/DoctrineCollections/DoctrineCollectionsCriteriaConverter.php create mode 100755 src/Bridge/DoctrineCollections/DoctrineCollectionsExpressionConverter.php create mode 100755 src/Bridge/SpiralPagination/PaginableCriteria.php rename tests/{Adapter => Bridge}/DoctrineCollections/DoctrineCollectionsCriteriaConverterTest.php (98%) rename tests/{Adapter => Bridge}/SpiralPagination/PaginableCriteriaTest.php (97%) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4408282..6ec1537 100755 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -22,6 +22,11 @@ Updates should follow the [Keep a CHANGELOG](http://keepachangelog.com/) princip - Nothing --> +## [1.1.0] - 2020-09-27 +### Deprecated +- Namespace `spaceonfire\Criteria\Adapter` renamed to `spaceonfire\Criteria\Bridge`. + Class aliases provided for backwards compatibility, but will be removed in next major release. + ## [1.0.0] - 2020-05-27 ### Added - First stable release diff --git a/composer.json b/composer.json index 58f4f6b..8aefeba 100755 --- a/composer.json +++ b/composer.json @@ -51,7 +51,7 @@ }, "extra": { "branch-alias": { - "dev-master": "1.0-dev" + "dev-master": "1.1-dev" } }, "config": { diff --git a/phpstan.neon.dist b/phpstan.neon.dist index 2577c0b..664a46e 100755 --- a/phpstan.neon.dist +++ b/phpstan.neon.dist @@ -19,3 +19,6 @@ parameters: - src/Expression/ExpressionFactory.php - src/Expression/AbstractExpressionDecorator.php - '/^Method (.*) should return static\((.*)\) but returns (.*)\.$/' + - + message: '/^If condition is always false\.$/' + path: src/Adapter/* diff --git a/phpunit.xml.dist b/phpunit.xml.dist index 0015c1e..ddb0e91 100755 --- a/phpunit.xml.dist +++ b/phpunit.xml.dist @@ -17,6 +17,9 @@ src/ + + src/Adapter/ + diff --git a/src/Adapter/DoctrineCollections/DoctrineCollectionsCriteriaConverter.php b/src/Adapter/DoctrineCollections/DoctrineCollectionsCriteriaConverter.php index ade76f8..67bd896 100755 --- a/src/Adapter/DoctrineCollections/DoctrineCollectionsCriteriaConverter.php +++ b/src/Adapter/DoctrineCollections/DoctrineCollectionsCriteriaConverter.php @@ -4,45 +4,19 @@ namespace spaceonfire\Criteria\Adapter\DoctrineCollections; -use Doctrine\Common\Collections\Criteria as DoctrineCriteria; -use spaceonfire\Criteria\Criteria; -use spaceonfire\Criteria\CriteriaInterface; +use function class_alias; -class DoctrineCollectionsCriteriaConverter -{ +class_alias( + \spaceonfire\Criteria\Bridge\DoctrineCollections\DoctrineCollectionsCriteriaConverter::class, + __NAMESPACE__ . '\DoctrineCollectionsCriteriaConverter' +); + +if (false) { /** - * Converts Doctrine criteria to spaceonfire criteria - * @param DoctrineCriteria $doctrineCriteria - * @param string $comparisonMethod - * @return CriteriaInterface + * @deprecated Will be dropped in next major release. + * Use \spaceonfire\Criteria\Bridge\DoctrineCollections\DoctrineCollectionsCriteriaConverter instead. */ - public function convert( - DoctrineCriteria $doctrineCriteria, - string $comparisonMethod = 'property' - ): CriteriaInterface { - $criteria = new Criteria(); - - if (null !== $doctrineExpression = $doctrineCriteria->getWhereExpression()) { - $expression = (new DoctrineCollectionsExpressionConverter($comparisonMethod)) - ->dispatch($doctrineExpression); - - $criteria->where($expression); - } - - $orderBy = array_map(static function (string $ordering): int { - return $ordering === DoctrineCriteria::ASC ? SORT_ASC : SORT_DESC; - }, $doctrineCriteria->getOrderings()); - - $criteria->orderBy($orderBy); - - if (null !== $offset = $doctrineCriteria->getFirstResult()) { - $criteria->offset($offset); - } - - if (null !== $limit = $doctrineCriteria->getMaxResults()) { - $criteria->limit($limit); - } - - return $criteria; + class DoctrineCollectionsCriteriaConverter extends \spaceonfire\Criteria\Bridge\DoctrineCollections\DoctrineCollectionsCriteriaConverter + { } } diff --git a/src/Adapter/DoctrineCollections/DoctrineCollectionsExpressionConverter.php b/src/Adapter/DoctrineCollections/DoctrineCollectionsExpressionConverter.php index b29deb1..64b51d9 100755 --- a/src/Adapter/DoctrineCollections/DoctrineCollectionsExpressionConverter.php +++ b/src/Adapter/DoctrineCollections/DoctrineCollectionsExpressionConverter.php @@ -4,139 +4,20 @@ namespace spaceonfire\Criteria\Adapter\DoctrineCollections; -use Doctrine\Common\Collections\Expr\Comparison; -use Doctrine\Common\Collections\Expr\CompositeExpression; -use Doctrine\Common\Collections\Expr\ExpressionVisitor; -use Doctrine\Common\Collections\Expr\Value; -use InvalidArgumentException; -use spaceonfire\Criteria\Criteria; -use spaceonfire\Criteria\Expression\ExpressionFactory; -use Webmozart\Assert\Assert; -use Webmozart\Expression\Expression; +use function class_alias; -/** - * Converts Expressions from Doctrine collections to webmozart expressions - * @package spaceonfire\Criteria\Adapter\DoctrineCollections - */ -class DoctrineCollectionsExpressionConverter extends ExpressionVisitor -{ - /** - * @var string - */ - private $comparisonMethod; - - /** - * DoctrineCollectionsExpressionConverter constructor. - * @param string $comparisonMethod `property` or `key` - */ - public function __construct(string $comparisonMethod = 'property') - { - Assert::oneOf($comparisonMethod, ['property', 'key']); - $this->comparisonMethod = $comparisonMethod; - } - - private function getExpressionFactory(): ExpressionFactory - { - return Criteria::expr(); - } - - /** - * @inheritDoc - * @return Expression - */ - public function walkCompositeExpression(CompositeExpression $expr): Expression - { - $expressionList = []; - foreach ($expr->getExpressionList() as $child) { - $expressionList[] = $this->dispatch($child); - } - - switch ($expr->getType()) { - case CompositeExpression::TYPE_AND: - return $this->getExpressionFactory()->andX($expressionList); - - case CompositeExpression::TYPE_OR: - return $this->getExpressionFactory()->orX($expressionList); - - default: - throw new InvalidArgumentException(sprintf( - 'Unknown composite expression type: "%s"', - $expr->getType() - )); - } - } - - /** - * @inheritDoc - * @return Expression - */ - public function walkComparison(Comparison $comparison): Expression - { - $field = $comparison->getField(); - $value = $this->walkValue($comparison->getValue()); - - switch ($comparison->getOperator()) { - case Comparison::EQ: - case Comparison::IS: - $innerExpression = $this->getExpressionFactory()->same($value); - break; - - case Comparison::NEQ: - $innerExpression = $this->getExpressionFactory()->notSame($value); - break; - - case Comparison::IN: - $innerExpression = $this->getExpressionFactory()->in($value); - break; - - case Comparison::NIN: - $innerExpression = $this->getExpressionFactory()->not($this->getExpressionFactory()->in($value)); - break; - - case Comparison::CONTAINS: - $innerExpression = $this->getExpressionFactory()->contains($value); - break; - - case Comparison::STARTS_WITH: - $innerExpression = $this->getExpressionFactory()->startsWith($value); - break; - - case Comparison::ENDS_WITH: - $innerExpression = $this->getExpressionFactory()->endsWith($value); - break; - - case Comparison::LT: - $innerExpression = $this->getExpressionFactory()->lessThan($value); - break; - - case Comparison::LTE: - $innerExpression = $this->getExpressionFactory()->lessThanEqual($value); - break; - - case Comparison::GT: - $innerExpression = $this->getExpressionFactory()->greaterThan($value); - break; - - case Comparison::GTE: - $innerExpression = $this->getExpressionFactory()->greaterThanEqual($value); - break; - } - - if (!isset($innerExpression)) { - throw new InvalidArgumentException(sprintf( - 'Unknown comparison operator: "%s"', - $comparison->getOperator() - )); - } - - return $this->getExpressionFactory()->{$this->comparisonMethod}($field, $innerExpression); - } +class_alias( + \spaceonfire\Criteria\Bridge\DoctrineCollections\DoctrineCollectionsExpressionConverter::class, + __NAMESPACE__ . '\DoctrineCollectionsExpressionConverter' +); +if (false) { /** - * @inheritDoc + * Converts Expressions from Doctrine collections to webmozart expressions + * @deprecated Will be dropped in next major release. + * Use \spaceonfire\Criteria\Bridge\DoctrineCollections\DoctrineCollectionsExpressionConverter instead. */ - public function walkValue(Value $value) + class DoctrineCollectionsExpressionConverter extends \spaceonfire\Criteria\Bridge\DoctrineCollections\DoctrineCollectionsExpressionConverter { - return $value->getValue(); } } diff --git a/src/Adapter/SpiralPagination/PaginableCriteria.php b/src/Adapter/SpiralPagination/PaginableCriteria.php index 75920a0..fab9a56 100755 --- a/src/Adapter/SpiralPagination/PaginableCriteria.php +++ b/src/Adapter/SpiralPagination/PaginableCriteria.php @@ -4,96 +4,19 @@ namespace spaceonfire\Criteria\Adapter\SpiralPagination; -use spaceonfire\Criteria\AbstractCriteriaDecorator; -use spaceonfire\Criteria\Criteria; -use spaceonfire\Criteria\CriteriaInterface; -use Spiral\Pagination\PaginableInterface; -use Spiral\Pagination\Paginator; -use Spiral\Pagination\PaginatorInterface; -use Webmozart\Assert\Assert; +use function class_alias; -class PaginableCriteria extends AbstractCriteriaDecorator implements PaginableInterface -{ - /** - * @var PaginatorInterface|Paginator|null - */ - private $paginator; - - /** - * PaginableCriteria constructor. - * @param CriteriaInterface|null $criteria original criteria to proxy - * @param PaginatorInterface|null $paginator - */ - public function __construct(?CriteriaInterface $criteria = null, ?PaginatorInterface $paginator = null) - { - parent::__construct($criteria ?? new Criteria()); - - if ($paginator !== null) { - $this->paginator = $paginator; - $paginator->paginate($this); - } else { - $this->resetPaginator(); - } - } - - /** - * Getter for `paginator` property - * @return PaginatorInterface|Paginator - */ - public function getPaginator(): PaginatorInterface - { - Assert::notNull($this->paginator); - return $this->paginator; - } - - /** - * @return PaginatorInterface|Paginator - */ - private function makePaginator(): PaginatorInterface - { - $paginator = $this->paginator ?? new Paginator(); - - Assert::isInstanceOf($paginator, Paginator::class); - - $limit = $this->getLimit() ?? 25; - $tmpCount = $limit + $this->getOffset(); - $page = (int)($this->getOffset() / $limit) + 1; - - return $paginator->withCount(max($tmpCount, $paginator->count()))->withLimit($limit)->withPage($page); - } - - private function resetPaginator(): void - { - $this->paginator = $this->makePaginator(); - } - - /** - * @inheritDoc - */ - public function limit(?int $limit): CriteriaInterface - { - parent::limit($limit); - $this->resetPaginator(); - return $this; - } - - /** - * @inheritDoc - */ - public function offset(?int $offset): CriteriaInterface - { - parent::offset($offset); - $this->resetPaginator(); - return $this; - } +class_alias( + \spaceonfire\Criteria\Bridge\SpiralPagination\PaginableCriteria::class, + __NAMESPACE__ . '\PaginableCriteria' +); +if (false) { /** - * Clone criteria + * @deprecated Will be dropped in next major release. + * Use \spaceonfire\Criteria\Bridge\SpiralPagination\PaginableCriteria instead. */ - public function __clone() + class PaginableCriteria extends \spaceonfire\Criteria\Bridge\SpiralPagination\PaginableCriteria { - if ($this->paginator !== null) { - $this->paginator = clone $this->paginator; - } } } diff --git a/src/Bridge/DoctrineCollections/DoctrineCollectionsCriteriaConverter.php b/src/Bridge/DoctrineCollections/DoctrineCollectionsCriteriaConverter.php new file mode 100755 index 0000000..904f67a --- /dev/null +++ b/src/Bridge/DoctrineCollections/DoctrineCollectionsCriteriaConverter.php @@ -0,0 +1,48 @@ +getWhereExpression()) { + $expression = (new DoctrineCollectionsExpressionConverter($comparisonMethod)) + ->dispatch($doctrineExpression); + + $criteria->where($expression); + } + + $orderBy = array_map(static function (string $ordering): int { + return $ordering === DoctrineCriteria::ASC ? SORT_ASC : SORT_DESC; + }, $doctrineCriteria->getOrderings()); + + $criteria->orderBy($orderBy); + + if (null !== $offset = $doctrineCriteria->getFirstResult()) { + $criteria->offset($offset); + } + + if (null !== $limit = $doctrineCriteria->getMaxResults()) { + $criteria->limit($limit); + } + + return $criteria; + } +} diff --git a/src/Bridge/DoctrineCollections/DoctrineCollectionsExpressionConverter.php b/src/Bridge/DoctrineCollections/DoctrineCollectionsExpressionConverter.php new file mode 100755 index 0000000..cacbbe1 --- /dev/null +++ b/src/Bridge/DoctrineCollections/DoctrineCollectionsExpressionConverter.php @@ -0,0 +1,142 @@ +comparisonMethod = $comparisonMethod; + } + + private function getExpressionFactory(): ExpressionFactory + { + return Criteria::expr(); + } + + /** + * @inheritDoc + * @return Expression + */ + public function walkCompositeExpression(CompositeExpression $expr): Expression + { + $expressionList = []; + foreach ($expr->getExpressionList() as $child) { + $expressionList[] = $this->dispatch($child); + } + + switch ($expr->getType()) { + case CompositeExpression::TYPE_AND: + return $this->getExpressionFactory()->andX($expressionList); + + case CompositeExpression::TYPE_OR: + return $this->getExpressionFactory()->orX($expressionList); + + default: + throw new InvalidArgumentException(sprintf( + 'Unknown composite expression type: "%s"', + $expr->getType() + )); + } + } + + /** + * @inheritDoc + * @return Expression + */ + public function walkComparison(Comparison $comparison): Expression + { + $field = $comparison->getField(); + $value = $this->walkValue($comparison->getValue()); + + switch ($comparison->getOperator()) { + case Comparison::EQ: + case Comparison::IS: + $innerExpression = $this->getExpressionFactory()->same($value); + break; + + case Comparison::NEQ: + $innerExpression = $this->getExpressionFactory()->notSame($value); + break; + + case Comparison::IN: + $innerExpression = $this->getExpressionFactory()->in($value); + break; + + case Comparison::NIN: + $innerExpression = $this->getExpressionFactory()->not($this->getExpressionFactory()->in($value)); + break; + + case Comparison::CONTAINS: + $innerExpression = $this->getExpressionFactory()->contains($value); + break; + + case Comparison::STARTS_WITH: + $innerExpression = $this->getExpressionFactory()->startsWith($value); + break; + + case Comparison::ENDS_WITH: + $innerExpression = $this->getExpressionFactory()->endsWith($value); + break; + + case Comparison::LT: + $innerExpression = $this->getExpressionFactory()->lessThan($value); + break; + + case Comparison::LTE: + $innerExpression = $this->getExpressionFactory()->lessThanEqual($value); + break; + + case Comparison::GT: + $innerExpression = $this->getExpressionFactory()->greaterThan($value); + break; + + case Comparison::GTE: + $innerExpression = $this->getExpressionFactory()->greaterThanEqual($value); + break; + } + + if (!isset($innerExpression)) { + throw new InvalidArgumentException(sprintf( + 'Unknown comparison operator: "%s"', + $comparison->getOperator() + )); + } + + return $this->getExpressionFactory()->{$this->comparisonMethod}($field, $innerExpression); + } + + /** + * @inheritDoc + */ + public function walkValue(Value $value) + { + return $value->getValue(); + } +} diff --git a/src/Bridge/SpiralPagination/PaginableCriteria.php b/src/Bridge/SpiralPagination/PaginableCriteria.php new file mode 100755 index 0000000..6852560 --- /dev/null +++ b/src/Bridge/SpiralPagination/PaginableCriteria.php @@ -0,0 +1,99 @@ +paginator = $paginator; + $paginator->paginate($this); + } else { + $this->resetPaginator(); + } + } + + /** + * Getter for `paginator` property + * @return PaginatorInterface|Paginator + */ + public function getPaginator(): PaginatorInterface + { + Assert::notNull($this->paginator); + return $this->paginator; + } + + /** + * @return PaginatorInterface|Paginator + */ + private function makePaginator(): PaginatorInterface + { + $paginator = $this->paginator ?? new Paginator(); + + Assert::isInstanceOf($paginator, Paginator::class); + + $limit = $this->getLimit() ?? 25; + $tmpCount = $limit + $this->getOffset(); + $page = (int)($this->getOffset() / $limit) + 1; + + return $paginator->withCount(max($tmpCount, $paginator->count()))->withLimit($limit)->withPage($page); + } + + private function resetPaginator(): void + { + $this->paginator = $this->makePaginator(); + } + + /** + * @inheritDoc + */ + public function limit(?int $limit): CriteriaInterface + { + parent::limit($limit); + $this->resetPaginator(); + return $this; + } + + /** + * @inheritDoc + */ + public function offset(?int $offset): CriteriaInterface + { + parent::offset($offset); + $this->resetPaginator(); + return $this; + } + + /** + * Clone criteria + */ + public function __clone() + { + if ($this->paginator !== null) { + $this->paginator = clone $this->paginator; + } + } +} diff --git a/src/Criteria.php b/src/Criteria.php index 2d90863..64df6b9 100755 --- a/src/Criteria.php +++ b/src/Criteria.php @@ -37,7 +37,7 @@ class Criteria implements CriteriaInterface /** * Criteria constructor. - * @param Expression $where + * @param Expression|null $where * @param array $orderBy * @param int|null $offset * @param int|null $limit diff --git a/tests/Adapter/DoctrineCollections/DoctrineCollectionsCriteriaConverterTest.php b/tests/Bridge/DoctrineCollections/DoctrineCollectionsCriteriaConverterTest.php similarity index 98% rename from tests/Adapter/DoctrineCollections/DoctrineCollectionsCriteriaConverterTest.php rename to tests/Bridge/DoctrineCollections/DoctrineCollectionsCriteriaConverterTest.php index 489037f..44f002c 100755 --- a/tests/Adapter/DoctrineCollections/DoctrineCollectionsCriteriaConverterTest.php +++ b/tests/Bridge/DoctrineCollections/DoctrineCollectionsCriteriaConverterTest.php @@ -2,7 +2,7 @@ declare(strict_types=1); -namespace spaceonfire\Criteria\Adapter\DoctrineCollections; +namespace spaceonfire\Criteria\Bridge\DoctrineCollections; use Doctrine\Common\Collections\Criteria as DoctrineCriteria; use Doctrine\Common\Collections\Expr\CompositeExpression; diff --git a/tests/Adapter/SpiralPagination/PaginableCriteriaTest.php b/tests/Bridge/SpiralPagination/PaginableCriteriaTest.php similarity index 97% rename from tests/Adapter/SpiralPagination/PaginableCriteriaTest.php rename to tests/Bridge/SpiralPagination/PaginableCriteriaTest.php index 706c829..cb65b8f 100755 --- a/tests/Adapter/SpiralPagination/PaginableCriteriaTest.php +++ b/tests/Bridge/SpiralPagination/PaginableCriteriaTest.php @@ -2,7 +2,7 @@ declare(strict_types=1); -namespace spaceonfire\Criteria\Adapter\SpiralPagination; +namespace spaceonfire\Criteria\Bridge\SpiralPagination; use spaceonfire\Criteria\AbstractCriteriaTest; use spaceonfire\Criteria\CriteriaInterface;