From 9b40368e45a07196b4da0001149a4b6b7f461957 Mon Sep 17 00:00:00 2001 From: Alan Gabriel Bem Date: Fri, 12 Mar 2021 12:04:25 +0100 Subject: [PATCH] search for subscription using criteria --- src/Domain/Event/Subscription/Criteria.php | 24 ++++++ .../Subscription/Criteria/AndCriteria.php | 38 +++++++++ .../Criteria/CompletedCriteria.php | 28 ++++++ .../Subscription/Criteria/NotCriteria.php | 36 ++++++++ .../Subscription/Criteria/OrCriteria.php | 38 +++++++++ .../Criteria/TypeEqualsToCriteria.php | 59 +++++++++++++ .../Event/Subscription/Criteria/Visitor.php | 28 ++++++ src/Domain/Event/Subscription/Repository.php | 2 +- .../Event/Subscription/Repository/Filter.php | 85 ------------------- src/Infrastructure/Event/Subscription/DAO.php | 2 +- .../Subscription/DAO/DbalPostgresDAO.php | 36 ++------ 11 files changed, 261 insertions(+), 115 deletions(-) create mode 100644 src/Domain/Event/Subscription/Criteria.php create mode 100644 src/Domain/Event/Subscription/Criteria/AndCriteria.php create mode 100644 src/Domain/Event/Subscription/Criteria/CompletedCriteria.php create mode 100644 src/Domain/Event/Subscription/Criteria/NotCriteria.php create mode 100644 src/Domain/Event/Subscription/Criteria/OrCriteria.php create mode 100644 src/Domain/Event/Subscription/Criteria/TypeEqualsToCriteria.php create mode 100644 src/Domain/Event/Subscription/Criteria/Visitor.php delete mode 100644 src/Domain/Event/Subscription/Repository/Filter.php diff --git a/src/Domain/Event/Subscription/Criteria.php b/src/Domain/Event/Subscription/Criteria.php new file mode 100644 index 00000000..f0b383c2 --- /dev/null +++ b/src/Domain/Event/Subscription/Criteria.php @@ -0,0 +1,24 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +declare(strict_types=1); + +namespace Streak\Domain\Event\Subscription; + +use Streak\Domain\Event\Subscription\Criteria\Visitor; + +/** + * @author Alan Gabriel Bem + */ +interface Criteria +{ + public function accept(Visitor $visitor); +} diff --git a/src/Domain/Event/Subscription/Criteria/AndCriteria.php b/src/Domain/Event/Subscription/Criteria/AndCriteria.php new file mode 100644 index 00000000..31ff0fbf --- /dev/null +++ b/src/Domain/Event/Subscription/Criteria/AndCriteria.php @@ -0,0 +1,38 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +declare(strict_types=1); + +namespace Streak\Domain\Event\Subscription\Criteria; + +use Streak\Domain\Event\Subscription\Criteria; + +/** + * @author Alan Gabriel Bem + */ +class AndCriteria implements Criteria +{ + private $criteria; + + public function __construct(Criteria... $criteria) + { + $this->criteria = $criteria; + } + + public function accept(Visitor $visitor) + { + foreach ($this->criteria as $criterion) { + $criterion->accept($visitor); + } + + $visitor->visitAnd($this); + } +} diff --git a/src/Domain/Event/Subscription/Criteria/CompletedCriteria.php b/src/Domain/Event/Subscription/Criteria/CompletedCriteria.php new file mode 100644 index 00000000..9544a574 --- /dev/null +++ b/src/Domain/Event/Subscription/Criteria/CompletedCriteria.php @@ -0,0 +1,28 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +declare(strict_types=1); + +namespace Streak\Domain\Event\Subscription\Criteria; + +use Streak\Domain\Event\Subscription\Criteria; + +/** + * @author Alan Gabriel Bem + */ +class CompletedCriteria implements Criteria +{ + public function accept(Visitor $visitor) + { + + } + +} diff --git a/src/Domain/Event/Subscription/Criteria/NotCriteria.php b/src/Domain/Event/Subscription/Criteria/NotCriteria.php new file mode 100644 index 00000000..cec9134c --- /dev/null +++ b/src/Domain/Event/Subscription/Criteria/NotCriteria.php @@ -0,0 +1,36 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +declare(strict_types=1); + +namespace Streak\Domain\Event\Subscription\Criteria; + +use Streak\Domain\Event\Subscription\Criteria; + +/** + * @author Alan Gabriel Bem + */ +class NotCriteria implements Criteria +{ + private $criteria; + + public function __construct(Criteria $criteria) + { + $this->criteria = $criteria; + } + + public function accept(Visitor $visitor) + { + $this->criteria->accept($visitor); + + $visitor->visitNot($this); + } +} diff --git a/src/Domain/Event/Subscription/Criteria/OrCriteria.php b/src/Domain/Event/Subscription/Criteria/OrCriteria.php new file mode 100644 index 00000000..d6e8f187 --- /dev/null +++ b/src/Domain/Event/Subscription/Criteria/OrCriteria.php @@ -0,0 +1,38 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +declare(strict_types=1); + +namespace Streak\Domain\Event\Subscription\Criteria; + +use Streak\Domain\Event\Subscription\Criteria; + +/** + * @author Alan Gabriel Bem + */ +class OrCriteria implements Criteria +{ + private $criteria; + + public function __construct(Criteria... $criteria) + { + $this->criteria = $criteria; + } + + public function accept(Visitor $visitor) + { + foreach ($this->criteria as $criterion) { + $criterion->accept($visitor); + } + + $visitor->visitOr($this); + } +} diff --git a/src/Domain/Event/Subscription/Criteria/TypeEqualsToCriteria.php b/src/Domain/Event/Subscription/Criteria/TypeEqualsToCriteria.php new file mode 100644 index 00000000..a9d48ad9 --- /dev/null +++ b/src/Domain/Event/Subscription/Criteria/TypeEqualsToCriteria.php @@ -0,0 +1,59 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +declare(strict_types=1); + +namespace Streak\Domain\Event\Subscription\Criteria; + +use Streak\Domain\Event\Listener; +use Streak\Domain\Event\Subscription\Criteria; + +/** + * @author Alan Gabriel Bem + */ +class TypeEqualsToCriteria implements Criteria +{ + private $type; + + public function __construct(string $type) + { + $this->validate($type); + + $this->type = $type; + } + + public function type() : string + { + return $this->type; + } + + public function accept(Visitor $visitor) + { + $visitor->visitTypeEqualsTo($this); + } + + private function validate(string $type) : void + { + try { + $reflection = new \ReflectionClass($type); + } catch (\ReflectionException $exception) { + throw new \InvalidArgumentException( + sprintf('Given argument "%s" is not a type of "%s"', $type, Listener\Id::class) + ); + } + + if (false === $reflection->implementsInterface(Listener\Id::class)) { + throw new \InvalidArgumentException( + sprintf('Given argument "%s" is not a type of "%s"', $type, Listener\Id::class) + ); + } + } +} diff --git a/src/Domain/Event/Subscription/Criteria/Visitor.php b/src/Domain/Event/Subscription/Criteria/Visitor.php new file mode 100644 index 00000000..d8e50a52 --- /dev/null +++ b/src/Domain/Event/Subscription/Criteria/Visitor.php @@ -0,0 +1,28 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +declare(strict_types=1); + +namespace Streak\Domain\Event\Subscription\Criteria; + +/** + * @author Alan Gabriel Bem + */ +interface Visitor +{ + public function visitAnd(AndCriteria $criteria); + + public function visitOr(OrCriteria $criteria); + + public function visitNot(NotCriteria $criteria); + + public function visitTypeEqualsTo(TypeEqualsToCriteria $criteria); +} diff --git a/src/Domain/Event/Subscription/Repository.php b/src/Domain/Event/Subscription/Repository.php index fadfb0a2..8cefc11e 100644 --- a/src/Domain/Event/Subscription/Repository.php +++ b/src/Domain/Event/Subscription/Repository.php @@ -39,5 +39,5 @@ public function add(Event\Subscription $subscription) : void; /** * @return iterable|Event\Subscription[] */ - public function all(?Repository\Filter $filter = null) : iterable; + public function all(Criteria $criteria) : iterable; } diff --git a/src/Domain/Event/Subscription/Repository/Filter.php b/src/Domain/Event/Subscription/Repository/Filter.php deleted file mode 100644 index 7aaeb40f..00000000 --- a/src/Domain/Event/Subscription/Repository/Filter.php +++ /dev/null @@ -1,85 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -declare(strict_types=1); - -namespace Streak\Domain\Event\Subscription\Repository; - -/** - * @author Alan Gabriel Bem - */ -final class Filter -{ - private $subscriptionTypes = []; - private $areCompletedSubscriptionsIgnored = true; - - public function __construct() - { - } - - public static function nothing() : Filter - { - return new self(); - } - - public function filterSubscriptionTypes(string ...$types) : Filter - { - $filter = new self(); - $filter->subscriptionTypes = $this->subscriptionTypes; - $filter->areCompletedSubscriptionsIgnored = $this->areCompletedSubscriptionsIgnored; - - foreach ($types as $type) { - if (true === in_array($type, $filter->subscriptionTypes, true)) { - continue; - } - $filter->subscriptionTypes[] = $type; - } - - return $filter; - } - - public function doNotFilterProducerTypes() : Filter - { - $filter = new self(); - $filter->subscriptionTypes = []; - $filter->areCompletedSubscriptionsIgnored = $this->areCompletedSubscriptionsIgnored; - - return $filter; - } - - public function subscriptionTypes() : array - { - return $this->subscriptionTypes; - } - - public function ignoreCompletedSubscriptions() : Filter - { - $filter = new self(); - $filter->subscriptionTypes = $this->subscriptionTypes; - $filter->areCompletedSubscriptionsIgnored = true; - - return $filter; - } - - public function doNotIgnoreCompletedSubscriptions() : Filter - { - $filter = new self(); - $filter->subscriptionTypes = $this->subscriptionTypes; - $filter->areCompletedSubscriptionsIgnored = false; - - return $filter; - } - - public function areCompletedSubscriptionsIgnored() : bool - { - return $this->areCompletedSubscriptionsIgnored; - } -} diff --git a/src/Infrastructure/Event/Subscription/DAO.php b/src/Infrastructure/Event/Subscription/DAO.php index 079d3560..cb3750a3 100644 --- a/src/Infrastructure/Event/Subscription/DAO.php +++ b/src/Infrastructure/Event/Subscription/DAO.php @@ -32,5 +32,5 @@ public function exists(Listener\Id $id) : bool; * * @return DAO\Subscription[] */ - public function all(array $types = [], ?bool $completed = null) : iterable; + public function all(Subscription\Criteria $criteria) : iterable; } diff --git a/src/Infrastructure/Event/Subscription/DAO/DbalPostgresDAO.php b/src/Infrastructure/Event/Subscription/DAO/DbalPostgresDAO.php index 96777cac..f54b9dc8 100644 --- a/src/Infrastructure/Event/Subscription/DAO/DbalPostgresDAO.php +++ b/src/Infrastructure/Event/Subscription/DAO/DbalPostgresDAO.php @@ -386,38 +386,18 @@ private function doExists(Listener\Id $id) : bool /** * @throws \Doctrine\DBAL\DBALException */ - private function doAll(array $types, ?bool $completed) : \Generator + private function doAll(Subscription\Criteria $criteria) : \Generator { - $sql = 'SELECT subscription_type, subscription_id, subscription_version, state, started_by, started_at, last_processed_event, last_event_processed_at, completed, paused_at FROM subscriptions'; - $where = []; - $parameters = []; - - if ($types) { - $sub = []; - foreach ($types as $key => $type) { - $sub[] = " (subscription_type = :subscription_type_$key) "; - $parameters["subscription_type_$key"] = $type; - } - $where[] = '('.implode(' OR ', $sub).')'; - } - - if (true === $completed) { - $where[] = ' completed IS TRUE '; - } - if (false === $completed) { - $where[] = ' completed IS FALSE '; - } - - $where = implode(' AND ', $where); + $builder = $this->connection->createQueryBuilder(); - if ($where) { - $sql = "$sql WHERE $where "; - } + $visitor = new DbalVisitor($builder); + $criteria->accept($visitor); - $sql .= ' ORDER BY id'; + $builder->select(['subscription_type', 'subscription_id', 'subscription_version', 'state', 'started_by', 'started_at', 'last_processed_event', 'last_event_processed_at', 'completed', 'paused_at']); + $builder->from('subscriptions'); + $builder->orderBy('id', 'ASC'); - $statement = $this->connection->prepare($sql); - $statement->execute($parameters); + $statement = $builder->execute(); while ($row = $statement->fetch(\PDO::FETCH_ASSOC)) { $subscription = $this->fromRow($row);