em->getRepository(Visit::class); return new VisitsStats( $visitsRepo->countNonOrphanVisits(VisitsCountFiltering::withApiKey($apiKey)), $visitsRepo->countOrphanVisits(new VisitsCountFiltering()), ); } /** * @return Visit[]|Paginator * @throws ShortUrlNotFoundException */ public function visitsForShortUrl( ShortUrlIdentifier $identifier, VisitsParams $params, ?ApiKey $apiKey = null, ): Paginator { /** @var ShortUrlRepositoryInterface $repo */ $repo = $this->em->getRepository(ShortUrl::class); if (! $repo->shortCodeIsInUse($identifier, $apiKey?->spec())) { throw ShortUrlNotFoundException::fromNotFound($identifier); } /** @var VisitRepositoryInterface $repo */ $repo = $this->em->getRepository(Visit::class); return $this->createPaginator( new ShortUrlVisitsPaginatorAdapter($repo, $identifier, $params, $apiKey), $params, ); } /** * @return Visit[]|Paginator * @throws TagNotFoundException */ public function visitsForTag(string $tag, VisitsParams $params, ?ApiKey $apiKey = null): Paginator { /** @var TagRepository $tagRepo */ $tagRepo = $this->em->getRepository(Tag::class); if (! $tagRepo->tagExists($tag, $apiKey)) { throw TagNotFoundException::fromTag($tag); } /** @var VisitRepositoryInterface $repo */ $repo = $this->em->getRepository(Visit::class); return $this->createPaginator(new TagVisitsPaginatorAdapter($repo, $tag, $params, $apiKey), $params); } /** * @return Visit[]|Paginator * @throws DomainNotFoundException */ public function visitsForDomain(string $domain, VisitsParams $params, ?ApiKey $apiKey = null): Paginator { /** @var DomainRepository $domainRepo */ $domainRepo = $this->em->getRepository(Domain::class); if ($domain !== 'DEFAULT' && ! $domainRepo->domainExists($domain, $apiKey)) { throw DomainNotFoundException::fromAuthority($domain); } /** @var VisitRepositoryInterface $repo */ $repo = $this->em->getRepository(Visit::class); return $this->createPaginator(new DomainVisitsPaginatorAdapter($repo, $domain, $params, $apiKey), $params); } /** * @return Visit[]|Paginator */ public function orphanVisits(VisitsParams $params): Paginator { /** @var VisitRepositoryInterface $repo */ $repo = $this->em->getRepository(Visit::class); return $this->createPaginator(new OrphanVisitsPaginatorAdapter($repo, $params), $params); } public function nonOrphanVisits(VisitsParams $params, ?ApiKey $apiKey = null): Paginator { /** @var VisitRepositoryInterface $repo */ $repo = $this->em->getRepository(Visit::class); return $this->createPaginator(new NonOrphanVisitsPaginatorAdapter($repo, $params, $apiKey), $params); } private function createPaginator(AdapterInterface $adapter, VisitsParams $params): Paginator { $paginator = new Paginator($adapter); $paginator->setMaxPerPage($params->itemsPerPage) ->setCurrentPage($params->page); return $paginator; } }