em = $em; $this->eventDispatcher = $eventDispatcher; $this->anonymizeRemoteAddr = $anonymizeRemoteAddr; } public function track(ShortUrl $shortUrl, Visitor $visitor): void { $visit = Visit::forValidShortUrl($shortUrl, $visitor, $this->anonymizeRemoteAddr); $this->em->persist($visit); $this->em->flush(); $this->eventDispatcher->dispatch(new ShortUrlVisited($visit->getId(), $visitor->getRemoteAddress())); } /** * @return Visit[]|Paginator * @throws ShortUrlNotFoundException */ public function info(ShortUrlIdentifier $identifier, VisitsParams $params, ?ApiKey $apiKey = null): Paginator { $spec = $apiKey !== null ? $apiKey->spec() : null; /** @var ShortUrlRepositoryInterface $repo */ $repo = $this->em->getRepository(ShortUrl::class); if (! $repo->shortCodeIsInUse($identifier->shortCode(), $identifier->domain(), $spec)) { throw ShortUrlNotFoundException::fromNotFound($identifier); } /** @var VisitRepositoryInterface $repo */ $repo = $this->em->getRepository(Visit::class); $paginator = new Paginator(new VisitsPaginatorAdapter($repo, $identifier, $params, $spec)); $paginator->setMaxPerPage($params->getItemsPerPage()) ->setCurrentPage($params->getPage()); return $paginator; } /** * @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); $paginator = new Paginator(new VisitsForTagPaginatorAdapter($repo, $tag, $params, $apiKey)); $paginator->setMaxPerPage($params->getItemsPerPage()) ->setCurrentPage($params->getPage()); return $paginator; } }