mirror of
https://github.com/shlinkio/shlink.git
synced 2024-11-27 08:18:24 +03:00
Created new action to get default visit stats
This commit is contained in:
parent
5beaab85ac
commit
1ef10f11cb
9 changed files with 129 additions and 1 deletions
|
@ -27,6 +27,7 @@ return [
|
||||||
Service\VisitsTracker::class => ConfigAbstractFactory::class,
|
Service\VisitsTracker::class => ConfigAbstractFactory::class,
|
||||||
Service\ShortUrlService::class => ConfigAbstractFactory::class,
|
Service\ShortUrlService::class => ConfigAbstractFactory::class,
|
||||||
Visit\VisitLocator::class => ConfigAbstractFactory::class,
|
Visit\VisitLocator::class => ConfigAbstractFactory::class,
|
||||||
|
Visit\VisitsStatsHelper::class => ConfigAbstractFactory::class,
|
||||||
Service\Tag\TagService::class => ConfigAbstractFactory::class,
|
Service\Tag\TagService::class => ConfigAbstractFactory::class,
|
||||||
Service\ShortUrl\DeleteShortUrlService::class => ConfigAbstractFactory::class,
|
Service\ShortUrl\DeleteShortUrlService::class => ConfigAbstractFactory::class,
|
||||||
Service\ShortUrl\ShortUrlResolver::class => ConfigAbstractFactory::class,
|
Service\ShortUrl\ShortUrlResolver::class => ConfigAbstractFactory::class,
|
||||||
|
@ -56,6 +57,7 @@ return [
|
||||||
Service\VisitsTracker::class => ['em', EventDispatcherInterface::class],
|
Service\VisitsTracker::class => ['em', EventDispatcherInterface::class],
|
||||||
Service\ShortUrlService::class => ['em', Service\ShortUrl\ShortUrlResolver::class, Util\UrlValidator::class],
|
Service\ShortUrlService::class => ['em', Service\ShortUrl\ShortUrlResolver::class, Util\UrlValidator::class],
|
||||||
Visit\VisitLocator::class => ['em'],
|
Visit\VisitLocator::class => ['em'],
|
||||||
|
Visit\VisitsStatsHelper::class => ['em'],
|
||||||
Service\Tag\TagService::class => ['em'],
|
Service\Tag\TagService::class => ['em'],
|
||||||
Service\ShortUrl\DeleteShortUrlService::class => [
|
Service\ShortUrl\DeleteShortUrlService::class => [
|
||||||
'em',
|
'em',
|
||||||
|
|
24
module/Core/src/Visit/Model/VisitsStats.php
Normal file
24
module/Core/src/Visit/Model/VisitsStats.php
Normal file
|
@ -0,0 +1,24 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace Shlinkio\Shlink\Core\Visit\Model;
|
||||||
|
|
||||||
|
use JsonSerializable;
|
||||||
|
|
||||||
|
final class VisitsStats implements JsonSerializable
|
||||||
|
{
|
||||||
|
private int $visitsCount;
|
||||||
|
|
||||||
|
public function __construct(int $visitsCount)
|
||||||
|
{
|
||||||
|
$this->visitsCount = $visitsCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function jsonSerialize(): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'visitsCount' => $this->visitsCount,
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
32
module/Core/src/Visit/VisitsStatsHelper.php
Normal file
32
module/Core/src/Visit/VisitsStatsHelper.php
Normal file
|
@ -0,0 +1,32 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace Shlinkio\Shlink\Core\Visit;
|
||||||
|
|
||||||
|
use Doctrine\ORM\EntityManagerInterface;
|
||||||
|
use Shlinkio\Shlink\Core\Entity\Visit;
|
||||||
|
use Shlinkio\Shlink\Core\Repository\VisitRepository;
|
||||||
|
use Shlinkio\Shlink\Core\Visit\Model\VisitsStats;
|
||||||
|
|
||||||
|
class VisitsStatsHelper implements VisitsStatsHelperInterface
|
||||||
|
{
|
||||||
|
private EntityManagerInterface $em;
|
||||||
|
|
||||||
|
public function __construct(EntityManagerInterface $em)
|
||||||
|
{
|
||||||
|
$this->em = $em;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getVisitsStats(): VisitsStats
|
||||||
|
{
|
||||||
|
return new VisitsStats($this->getVisitsCount());
|
||||||
|
}
|
||||||
|
|
||||||
|
private function getVisitsCount(): int
|
||||||
|
{
|
||||||
|
/** @var VisitRepository $visitsRepo */
|
||||||
|
$visitsRepo = $this->em->getRepository(Visit::class);
|
||||||
|
return $visitsRepo->count([]);
|
||||||
|
}
|
||||||
|
}
|
12
module/Core/src/Visit/VisitsStatsHelperInterface.php
Normal file
12
module/Core/src/Visit/VisitsStatsHelperInterface.php
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace Shlinkio\Shlink\Core\Visit;
|
||||||
|
|
||||||
|
use Shlinkio\Shlink\Core\Visit\Model\VisitsStats;
|
||||||
|
|
||||||
|
interface VisitsStatsHelperInterface
|
||||||
|
{
|
||||||
|
public function getVisitsStats(): VisitsStats;
|
||||||
|
}
|
|
@ -11,6 +11,7 @@ use Psr\Log\LoggerInterface;
|
||||||
use Shlinkio\Shlink\Common\Mercure\LcobucciJwtProvider;
|
use Shlinkio\Shlink\Common\Mercure\LcobucciJwtProvider;
|
||||||
use Shlinkio\Shlink\Core\Options\AppOptions;
|
use Shlinkio\Shlink\Core\Options\AppOptions;
|
||||||
use Shlinkio\Shlink\Core\Service;
|
use Shlinkio\Shlink\Core\Service;
|
||||||
|
use Shlinkio\Shlink\Core\Visit;
|
||||||
use Shlinkio\Shlink\Rest\Service\ApiKeyService;
|
use Shlinkio\Shlink\Rest\Service\ApiKeyService;
|
||||||
|
|
||||||
return [
|
return [
|
||||||
|
@ -29,6 +30,7 @@ return [
|
||||||
Action\ShortUrl\ListShortUrlsAction::class => ConfigAbstractFactory::class,
|
Action\ShortUrl\ListShortUrlsAction::class => ConfigAbstractFactory::class,
|
||||||
Action\ShortUrl\EditShortUrlTagsAction::class => ConfigAbstractFactory::class,
|
Action\ShortUrl\EditShortUrlTagsAction::class => ConfigAbstractFactory::class,
|
||||||
Action\Visit\ShortUrlVisitsAction::class => ConfigAbstractFactory::class,
|
Action\Visit\ShortUrlVisitsAction::class => ConfigAbstractFactory::class,
|
||||||
|
Action\Visit\GlobalVisitsAction::class => ConfigAbstractFactory::class,
|
||||||
Action\Tag\ListTagsAction::class => ConfigAbstractFactory::class,
|
Action\Tag\ListTagsAction::class => ConfigAbstractFactory::class,
|
||||||
Action\Tag\DeleteTagsAction::class => ConfigAbstractFactory::class,
|
Action\Tag\DeleteTagsAction::class => ConfigAbstractFactory::class,
|
||||||
Action\Tag\CreateTagsAction::class => ConfigAbstractFactory::class,
|
Action\Tag\CreateTagsAction::class => ConfigAbstractFactory::class,
|
||||||
|
@ -66,6 +68,7 @@ return [
|
||||||
'config.url_shortener.domain',
|
'config.url_shortener.domain',
|
||||||
],
|
],
|
||||||
Action\Visit\ShortUrlVisitsAction::class => [Service\VisitsTracker::class, 'Logger_Shlink'],
|
Action\Visit\ShortUrlVisitsAction::class => [Service\VisitsTracker::class, 'Logger_Shlink'],
|
||||||
|
Action\Visit\GlobalVisitsAction::class => [Visit\VisitsStatsHelper::class, 'Logger_Shlink'],
|
||||||
Action\ShortUrl\ListShortUrlsAction::class => [
|
Action\ShortUrl\ListShortUrlsAction::class => [
|
||||||
Service\ShortUrlService::class,
|
Service\ShortUrlService::class,
|
||||||
'config.url_shortener.domain',
|
'config.url_shortener.domain',
|
||||||
|
|
|
@ -27,6 +27,7 @@ return [
|
||||||
|
|
||||||
// Visits
|
// Visits
|
||||||
Action\Visit\ShortUrlVisitsAction::getRouteDef([$dropDomainMiddleware]),
|
Action\Visit\ShortUrlVisitsAction::getRouteDef([$dropDomainMiddleware]),
|
||||||
|
Action\Visit\GlobalVisitsAction::getRouteDef(),
|
||||||
|
|
||||||
// Tags
|
// Tags
|
||||||
Action\Tag\ListTagsAction::getRouteDef(),
|
Action\Tag\ListTagsAction::getRouteDef(),
|
||||||
|
|
33
module/Rest/src/Action/Visit/GlobalVisitsAction.php
Normal file
33
module/Rest/src/Action/Visit/GlobalVisitsAction.php
Normal file
|
@ -0,0 +1,33 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace Shlinkio\Shlink\Rest\Action\Visit;
|
||||||
|
|
||||||
|
use Laminas\Diactoros\Response\JsonResponse;
|
||||||
|
use Psr\Http\Message\ResponseInterface;
|
||||||
|
use Psr\Http\Message\ServerRequestInterface;
|
||||||
|
use Psr\Log\LoggerInterface;
|
||||||
|
use Shlinkio\Shlink\Core\Visit\VisitsStatsHelperInterface;
|
||||||
|
use Shlinkio\Shlink\Rest\Action\AbstractRestAction;
|
||||||
|
|
||||||
|
class GlobalVisitsAction extends AbstractRestAction
|
||||||
|
{
|
||||||
|
protected const ROUTE_PATH = '/visits';
|
||||||
|
protected const ROUTE_ALLOWED_METHODS = [self::METHOD_GET];
|
||||||
|
|
||||||
|
private VisitsStatsHelperInterface $statsHelper;
|
||||||
|
|
||||||
|
public function __construct(VisitsStatsHelperInterface $statsHelper, ?LoggerInterface $logger = null)
|
||||||
|
{
|
||||||
|
parent::__construct($logger);
|
||||||
|
$this->statsHelper = $statsHelper;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function handle(ServerRequestInterface $request): ResponseInterface
|
||||||
|
{
|
||||||
|
return new JsonResponse([
|
||||||
|
'visits' => $this->statsHelper->getVisitsStats(),
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
21
module/Rest/test-api/Action/GlobalVisitsActionTest.php
Normal file
21
module/Rest/test-api/Action/GlobalVisitsActionTest.php
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace ShlinkioApiTest\Shlink\Rest\Action;
|
||||||
|
|
||||||
|
use Shlinkio\Shlink\TestUtils\ApiTest\ApiTestCase;
|
||||||
|
|
||||||
|
class GlobalVisitsActionTest extends ApiTestCase
|
||||||
|
{
|
||||||
|
/** @test */
|
||||||
|
public function returnsExpectedVisitsStats(): void
|
||||||
|
{
|
||||||
|
$resp = $this->callApiWithKey(self::METHOD_GET, '/visits');
|
||||||
|
$payload = $this->getJsonResponsePayload($resp);
|
||||||
|
|
||||||
|
$this->assertArrayHasKey('visits', $payload);
|
||||||
|
$this->assertArrayHasKey('visitsCount', $payload['visits']);
|
||||||
|
$this->assertEquals(7, $payload['visits']['visitsCount']);
|
||||||
|
}
|
||||||
|
}
|
|
@ -11,7 +11,7 @@ use ShlinkioApiTest\Shlink\Rest\Utils\NotFoundUrlHelpersTrait;
|
||||||
use function GuzzleHttp\Psr7\build_query;
|
use function GuzzleHttp\Psr7\build_query;
|
||||||
use function sprintf;
|
use function sprintf;
|
||||||
|
|
||||||
class GetVisitsActionTest extends ApiTestCase
|
class ShortUrlVisitsActionTest extends ApiTestCase
|
||||||
{
|
{
|
||||||
use NotFoundUrlHelpersTrait;
|
use NotFoundUrlHelpersTrait;
|
||||||
|
|
Loading…
Reference in a new issue