diff --git a/mailpoet/lib/Automation/Integrations/MailPoet/Analytics/Controller/OverviewStatisticsController.php b/mailpoet/lib/Automation/Integrations/MailPoet/Analytics/Controller/OverviewStatisticsController.php index 0d75b3eb50..c24504a19f 100644 --- a/mailpoet/lib/Automation/Integrations/MailPoet/Analytics/Controller/OverviewStatisticsController.php +++ b/mailpoet/lib/Automation/Integrations/MailPoet/Analytics/Controller/OverviewStatisticsController.php @@ -5,7 +5,7 @@ namespace MailPoet\Automation\Integrations\MailPoet\Analytics\Controller; use MailPoet\Automation\Engine\Data\Automation; use MailPoet\Automation\Engine\Data\Step; use MailPoet\Automation\Integrations\MailPoet\Actions\SendEmailAction; -use MailPoet\Automation\Integrations\MailPoet\Analytics\Entities\Query; +use MailPoet\Automation\Integrations\MailPoet\Analytics\Entities\QueryWithCompare; use MailPoet\Entities\StatisticsClickEntity; use MailPoet\Entities\StatisticsOpenEntity; use MailPoet\Newsletter\NewslettersRepository; @@ -33,7 +33,7 @@ class OverviewStatisticsController { $this->newsletterUrl = $newsletterUrl; } - public function getStatisticsForAutomation(Automation $automation, Query $query): array { + public function getStatisticsForAutomation(Automation $automation, QueryWithCompare $query): array { $emails = $this->getEmailsFromAutomation($automation); $data = [ 'sent' => ['current' => 0, 'previous' => 0], @@ -57,8 +57,8 @@ class OverviewStatisticsController { $currentStatistics = $this->newsletterStatisticsRepository->getBatchStatistics( $emails, - $query->getPrimaryAfter(), - $query->getPrimaryBefore(), + $query->getAfter(), + $query->getBefore(), $requiredData ); foreach ($currentStatistics as $newsletterId => $statistic) { @@ -83,8 +83,8 @@ class OverviewStatisticsController { $previousStatistics = $this->newsletterStatisticsRepository->getBatchStatistics( $emails, - $query->getSecondaryAfter(), - $query->getSecondaryBefore(), + $query->getCompareWithAfter(), + $query->getCompareWithBefore(), $requiredData ); diff --git a/mailpoet/lib/Automation/Integrations/MailPoet/Analytics/Endpoints/OverviewEndpoint.php b/mailpoet/lib/Automation/Integrations/MailPoet/Analytics/Endpoints/OverviewEndpoint.php index 9c6884347a..d898af2d12 100644 --- a/mailpoet/lib/Automation/Integrations/MailPoet/Analytics/Endpoints/OverviewEndpoint.php +++ b/mailpoet/lib/Automation/Integrations/MailPoet/Analytics/Endpoints/OverviewEndpoint.php @@ -8,7 +8,7 @@ use MailPoet\Automation\Engine\API\Endpoint; use MailPoet\Automation\Engine\Exceptions\NotFoundException; use MailPoet\Automation\Engine\Storage\AutomationStorage; use MailPoet\Automation\Integrations\MailPoet\Analytics\Controller\OverviewStatisticsController; -use MailPoet\Automation\Integrations\MailPoet\Analytics\Entities\Query; +use MailPoet\Automation\Integrations\MailPoet\Analytics\Entities\QueryWithCompare; use MailPoet\Validator\Builder; class OverviewEndpoint extends Endpoint { @@ -32,7 +32,7 @@ class OverviewEndpoint extends Endpoint { if (!$automation) { throw new NotFoundException(__('Automation not found', 'mailpoet')); } - $query = Query::fromRequest($request); + $query = QueryWithCompare::fromRequest($request); $result = $this->overviewStatisticsController->getStatisticsForAutomation($automation, $query); return new Response($result); @@ -41,22 +41,7 @@ class OverviewEndpoint extends Endpoint { public static function getRequestSchema(): array { return [ 'id' => Builder::integer()->required(), - 'query' => Builder::object( - [ - 'primary' => Builder::object( - [ - 'after' => Builder::string()->formatDateTime()->required(), - 'before' => Builder::string()->formatDateTime()->required(), - ] - ), - 'secondary' => Builder::object( - [ - 'after' => Builder::string()->formatDateTime()->required(), - 'before' => Builder::string()->formatDateTime()->required(), - ] - ), - ] - ), + 'query' => QueryWithCompare::getRequestSchema(), ]; } } diff --git a/mailpoet/lib/Automation/Integrations/MailPoet/Analytics/Entities/Query.php b/mailpoet/lib/Automation/Integrations/MailPoet/Analytics/Entities/Query.php index 98f4ad3e5e..fb2bc685a2 100644 --- a/mailpoet/lib/Automation/Integrations/MailPoet/Analytics/Entities/Query.php +++ b/mailpoet/lib/Automation/Integrations/MailPoet/Analytics/Entities/Query.php @@ -4,6 +4,8 @@ namespace MailPoet\Automation\Integrations\MailPoet\Analytics\Entities; use MailPoet\API\REST\Request; use MailPoet\Automation\Engine\Exceptions\UnexpectedValueException; +use MailPoet\Validator\Builder; +use MailPoet\Validator\Schema; class Query { @@ -13,68 +15,110 @@ class Query { /** @var \DateTimeImmutable */ private $primaryBefore; - /** @var \DateTimeImmutable */ - private $secondaryAfter; + /** @var int */ + private $limit; - /** @var \DateTimeImmutable */ - private $secondaryBefore; + /** @var string */ + private $orderBy; + + /** @var string */ + private $orderDirection; + + /** @var int */ + private $page; public function __construct( \DateTimeImmutable $primaryAfter, \DateTimeImmutable $primaryBefore, - \DateTimeImmutable $secondaryAfter, - \DateTimeImmutable $secondaryBefore + int $limit = 25, + string $orderBy = '', + string $orderDirection = 'asc', + int $page = 1 ) { $this->primaryAfter = $primaryAfter; $this->primaryBefore = $primaryBefore; - $this->secondaryAfter = $secondaryAfter; - $this->secondaryBefore = $secondaryBefore; + $this->limit = $limit; + $this->orderBy = $orderBy; + $this->orderDirection = $orderDirection; + $this->page = $page; } - public function getPrimaryAfter(): \DateTimeImmutable { + public function getAfter(): \DateTimeImmutable { return $this->primaryAfter; } - public function getPrimaryBefore(): \DateTimeImmutable { + public function getBefore(): \DateTimeImmutable { return $this->primaryBefore; } - public function getSecondaryAfter(): \DateTimeImmutable { - return $this->secondaryAfter; + public function getLimit(): int { + return $this->limit; } - public function getSecondaryBefore(): \DateTimeImmutable { - return $this->secondaryBefore; + public function getOrderBy(): string { + return $this->orderBy; } - public static function fromRequest(Request $request): self { + public function getOrderDirection(): string { + return $this->orderDirection; + } + public function getPage(): int { + return $this->page; + } + + /** + * @param Request $request + * @return Query + * @throws UnexpectedValueException + */ + public static function fromRequest(Request $request) { $query = $request->getParam('query'); if (!is_array($query)) { throw new UnexpectedValueException('Invalid query parameters'); } $primary = $query['primary'] ?? null; - $secondary = $query['secondary'] ?? null; - if (!is_array($primary) || !is_array($secondary)) { + if (!is_array($primary)) { throw new UnexpectedValueException('Invalid query parameters'); } $primaryAfter = $primary['after'] ?? null; $primaryBefore = $primary['before'] ?? null; - $secondaryAfter = $secondary['after'] ?? null; - $secondaryBefore = $secondary['before'] ?? null; if ( !is_string($primaryAfter) || - !is_string($primaryBefore) || - !is_string($secondaryAfter) || - !is_string($secondaryBefore) + !is_string($primaryBefore) ) { throw new UnexpectedValueException('Invalid query parameters'); } + + $limit = $query['limit'] ?? 25; + $orderBy = $query['order_by'] ?? ''; + $orderDirection = isset($query['order']) && strtolower($query['order']) === 'asc' ? 'asc' : 'desc'; + $page = $query['page'] ?? 1; + return new self( new \DateTimeImmutable($primaryAfter), new \DateTimeImmutable($primaryBefore), - new \DateTimeImmutable($secondaryAfter), - new \DateTimeImmutable($secondaryBefore) + $limit, + $orderBy, + $orderDirection, + $page + ); + } + + public static function getRequestSchema(): Schema { + return Builder::object( + [ + 'primary' => Builder::object( + [ + 'after' => Builder::string()->formatDateTime()->required(), + 'before' => Builder::string()->formatDateTime()->required(), + ] + ), + 'limit' => Builder::integer()->minimum(1)->maximum(100), + 'order_by' => Builder::string(), + 'order' => Builder::string(), + 'page' => Builder::integer()->minimum(1), + ] ); } } diff --git a/mailpoet/lib/Automation/Integrations/MailPoet/Analytics/Entities/QueryWithCompare.php b/mailpoet/lib/Automation/Integrations/MailPoet/Analytics/Entities/QueryWithCompare.php new file mode 100644 index 0000000000..268d2d663e --- /dev/null +++ b/mailpoet/lib/Automation/Integrations/MailPoet/Analytics/Entities/QueryWithCompare.php @@ -0,0 +1,109 @@ +secondaryAfter = $secondaryAfter; + $this->secondaryBefore = $secondaryBefore; + } + + public function getCompareWithAfter(): \DateTimeImmutable { + return $this->secondaryAfter; + } + + public function getCompareWithBefore(): \DateTimeImmutable { + return $this->secondaryBefore; + } + + /** + * @param Request $request + * @return QueryWithCompare + * @throws UnexpectedValueException + */ + public static function fromRequest(Request $request) { + + $query = $request->getParam('query'); + if (!is_array($query)) { + throw new UnexpectedValueException('Invalid query parameters'); + } + $primary = $query['primary'] ?? null; + $secondary = $query['secondary'] ?? null; + if (!is_array($primary) || !is_array($secondary)) { + throw new UnexpectedValueException('Invalid query parameters'); + } + $primaryAfter = $primary['after'] ?? null; + $primaryBefore = $primary['before'] ?? null; + $secondaryAfter = $secondary['after'] ?? null; + $secondaryBefore = $secondary['before'] ?? null; + if ( + !is_string($primaryAfter) || + !is_string($primaryBefore) || + !is_string($secondaryAfter) || + !is_string($secondaryBefore) + ) { + throw new UnexpectedValueException('Invalid query parameters'); + } + + $limit = $query['limit'] ?? 25; + $orderBy = $query['orderBy'] ?? ''; + $orderDirection = $query['orderDirection'] ?? 'asc'; + $page = $query['page'] ?? 0; + + return new self( + new \DateTimeImmutable($primaryAfter), + new \DateTimeImmutable($primaryBefore), + new \DateTimeImmutable($secondaryAfter), + new \DateTimeImmutable($secondaryBefore), + $limit, + $orderBy, + $orderDirection, + $page + ); + } + + public static function getRequestSchema(): Schema { + return Builder::object( + [ + 'primary' => Builder::object( + [ + 'after' => Builder::string()->formatDateTime()->required(), + 'before' => Builder::string()->formatDateTime()->required(), + ] + ), + 'secondary' => Builder::object( + [ + 'after' => Builder::string()->formatDateTime()->required(), + 'before' => Builder::string()->formatDateTime()->required(), + ] + ), + 'limit' => Builder::integer()->minimum(1)->maximum(100), + 'orderBy' => Builder::string(), + 'orderDirection' => Builder::string(), + 'page' => Builder::integer()->minimum(1), + ] + ); + } +}