diff --git a/lib/RoadizCoreBundle/migrations/Version20230615122615.php b/lib/RoadizCoreBundle/migrations/Version20230615122615.php new file mode 100644 index 00000000..abed8b48 --- /dev/null +++ b/lib/RoadizCoreBundle/migrations/Version20230615122615.php @@ -0,0 +1,38 @@ +addSql('ALTER TABLE redirections ADD use_count INT DEFAULT 0 NOT NULL'); + $this->addSql('CREATE INDEX redirection_use_count ON redirections (use_count)'); + } + + public function down(Schema $schema): void + { + // this down() migration is auto-generated, please modify it to your needs + $this->addSql('DROP INDEX redirection_use_count ON redirections'); + $this->addSql('ALTER TABLE redirections DROP use_count'); + } + + public function isTransactional(): bool + { + return false; + } +} diff --git a/lib/RoadizCoreBundle/src/Controller/RedirectionController.php b/lib/RoadizCoreBundle/src/Controller/RedirectionController.php index 90d1c8ec..bef839fc 100644 --- a/lib/RoadizCoreBundle/src/Controller/RedirectionController.php +++ b/lib/RoadizCoreBundle/src/Controller/RedirectionController.php @@ -4,6 +4,7 @@ namespace RZ\Roadiz\CoreBundle\Controller; +use Doctrine\Persistence\ManagerRegistry; use RZ\Roadiz\CoreBundle\Entity\Redirection; use Symfony\Cmf\Component\Routing\RouteObjectInterface; use Symfony\Component\HttpFoundation\RedirectResponse; @@ -15,13 +16,12 @@ final class RedirectionController { private UrlGeneratorInterface $urlGenerator; + private ManagerRegistry $managerRegistry; - /** - * @param UrlGeneratorInterface $urlGenerator - */ - public function __construct(UrlGeneratorInterface $urlGenerator) + public function __construct(UrlGeneratorInterface $urlGenerator, ManagerRegistry $managerRegistry) { $this->urlGenerator = $urlGenerator; + $this->managerRegistry = $managerRegistry; } /** @@ -32,6 +32,9 @@ public function __construct(UrlGeneratorInterface $urlGenerator) public function redirectAction(Request $request, Redirection $redirection): RedirectResponse { if (null !== $redirection->getRedirectNodeSource()) { + $redirection->incrementUseCount(); + $this->managerRegistry->getManagerForClass(Redirection::class)->flush(); + return new RedirectResponse( $this->urlGenerator->generate( RouteObjectInterface::OBJECT_BASED_ROUTE_NAME, @@ -45,6 +48,8 @@ public function redirectAction(Request $request, Redirection $redirection): Redi null !== $redirection->getRedirectUri() && strlen($redirection->getRedirectUri()) > 0 ) { + $redirection->incrementUseCount(); + $this->managerRegistry->getManagerForClass(Redirection::class)->flush(); return new RedirectResponse($redirection->getRedirectUri(), $redirection->getType()); } diff --git a/lib/RoadizCoreBundle/src/Entity/Redirection.php b/lib/RoadizCoreBundle/src/Entity/Redirection.php index 2428d2e9..239c53d4 100644 --- a/lib/RoadizCoreBundle/src/Entity/Redirection.php +++ b/lib/RoadizCoreBundle/src/Entity/Redirection.php @@ -18,25 +18,24 @@ ORM\Entity(repositoryClass: RedirectionRepository::class), ORM\Table(name: "redirections"), ORM\HasLifecycleCallbacks, - UniqueEntity(fields: ["query"]) + UniqueEntity(fields: ["query"]), + ORM\Index(columns: ["use_count"], name: 'redirection_use_count') ] class Redirection extends AbstractDateTimed { - /** - * @var string - */ #[ORM\Column(type: 'string', length: 255, unique: true)] #[Assert\NotBlank] #[Assert\Length(max: 255)] private string $query = ""; - /** - * @var string|null - */ #[ORM\Column(name: 'redirectUri', type: 'text', length: 2048, nullable: true)] #[Assert\Length(max: 2048)] private ?string $redirectUri = null; + #[ORM\Column(name: 'use_count', type: 'integer', nullable: false, options: ['default' => 0])] + #[Assert\Length(max: 2048)] + private int $useCount = 0; + /** * @var NodesSources|null */ @@ -59,12 +58,12 @@ public function getQuery(): string } /** - * @param string $query + * @param string|null $query * @return Redirection */ - public function setQuery($query): Redirection + public function setQuery(?string $query): Redirection { - $this->query = $query; + $this->query = $query ?? ''; return $this; } @@ -80,7 +79,7 @@ public function getRedirectUri(): ?string * @param string|null $redirectUri * @return Redirection */ - public function setRedirectUri($redirectUri): Redirection + public function setRedirectUri(?string $redirectUri): Redirection { $this->redirectUri = $redirectUri; return $this; @@ -140,4 +139,18 @@ public function __construct() $this->type = Response::HTTP_MOVED_PERMANENTLY; $this->initAbstractDateTimed(); } + + /** + * @return int + */ + public function getUseCount(): int + { + return $this->useCount; + } + + public function incrementUseCount(): self + { + $this->useCount++; + return $this; + } } diff --git a/lib/RoadizCoreBundle/src/Routing/RedirectableUrlMatcher.php b/lib/RoadizCoreBundle/src/Routing/RedirectableUrlMatcher.php index a686e08c..b6f3c486 100644 --- a/lib/RoadizCoreBundle/src/Routing/RedirectableUrlMatcher.php +++ b/lib/RoadizCoreBundle/src/Routing/RedirectableUrlMatcher.php @@ -18,7 +18,7 @@ final class RedirectableUrlMatcher extends BaseMatcher * * @return array An array of parameters */ - public function redirect($path, $route, $scheme = null): array + public function redirect(string $path, string $route, ?string $scheme = null): array { return [ '_controller' => RedirectionController::class . '::redirectToRouteAction', diff --git a/lib/RoadizCoreBundle/src/Routing/RedirectionMatcher.php b/lib/RoadizCoreBundle/src/Routing/RedirectionMatcher.php index 3579b0e1..919224eb 100644 --- a/lib/RoadizCoreBundle/src/Routing/RedirectionMatcher.php +++ b/lib/RoadizCoreBundle/src/Routing/RedirectionMatcher.php @@ -46,7 +46,7 @@ public function __construct( /** * {@inheritdoc} */ - public function match($pathinfo): array + public function match(string $pathinfo): array { $this->stopwatch->start('findRedirection'); $decodedUrl = rawurldecode($pathinfo); diff --git a/lib/Rozier/src/Resources/translations/messages.xlf b/lib/Rozier/src/Resources/translations/messages.xlf index 9a0b1cf2..17584989 100644 --- a/lib/Rozier/src/Resources/translations/messages.xlf +++ b/lib/Rozier/src/Resources/translations/messages.xlf @@ -1177,6 +1177,7 @@ redirection.typeRedirection field which stands for HTTP code: 301 or 302 redirection.moved_permanentlyRedirection type description for 301 Moved Permanently redirection.moved_temporarilyRedirection type description for 302 Moved Temporarily + redirection.use_countRedirection usage count login_imageGlobal parameter to customize login screen background image publishedAtField label for node-source publication date and time. publishableField label for node-type publishable status. diff --git a/lib/Rozier/src/Resources/views/redirections/list.html.twig b/lib/Rozier/src/Resources/views/redirections/list.html.twig index b652e218..d4ad6b79 100644 --- a/lib/Rozier/src/Resources/views/redirections/list.html.twig +++ b/lib/Rozier/src/Resources/views/redirections/list.html.twig @@ -42,6 +42,13 @@ } only %} {% trans %}redirection.type{% endtrans %} + + {% trans %}redirection.use_count{% endtrans %} + {% include '@RoadizRozier/includes/column_ordering.html.twig' with { + 'field': 'useCount', + 'filters': filters, + } only %} + {% trans %}actions{% endtrans %} @@ -66,6 +73,7 @@ {% endif %} {{ item.typeAsString|trans }} + {{ item.useCount }} {% apply spaceless %}