From 09e792dda7ef2c04b1ea533578035a33122493ae Mon Sep 17 00:00:00 2001
From: Jonas Leder <jonas@jonasled.de>
Date: Mon, 30 Jan 2023 19:24:58 +0100
Subject: [PATCH] add table with redirects

---
 migrations/Version20230130182242.php          | 31 ++++++++
 .../Admin/RedirectCrudController.php          | 25 +++++++
 src/Controller/PageController.php             | 29 ++++++--
 src/Entity/Redirect.php                       | 65 ++++++++++++++++
 src/Repository/RedirectRepository.php         | 74 +++++++++++++++++++
 5 files changed, 217 insertions(+), 7 deletions(-)
 create mode 100644 migrations/Version20230130182242.php
 create mode 100644 src/Controller/Admin/RedirectCrudController.php
 create mode 100644 src/Entity/Redirect.php
 create mode 100644 src/Repository/RedirectRepository.php

diff --git a/migrations/Version20230130182242.php b/migrations/Version20230130182242.php
new file mode 100644
index 00000000..cf74863d
--- /dev/null
+++ b/migrations/Version20230130182242.php
@@ -0,0 +1,31 @@
+<?php
+
+declare(strict_types=1);
+
+namespace DoctrineMigrations;
+
+use Doctrine\DBAL\Schema\Schema;
+use Doctrine\Migrations\AbstractMigration;
+
+/**
+ * Auto-generated Migration: Please modify to your needs!
+ */
+final class Version20230130182242 extends AbstractMigration
+{
+    public function getDescription(): string
+    {
+        return '';
+    }
+
+    public function up(Schema $schema): void
+    {
+        // this up() migration is auto-generated, please modify it to your needs
+        $this->addSql('CREATE TABLE redirect (id INT AUTO_INCREMENT NOT NULL, name VARCHAR(255) NOT NULL, redirect_url VARCHAR(255) NOT NULL, is_s3_file TINYINT(1) NOT NULL, PRIMARY KEY(id)) DEFAULT CHARACTER SET utf8mb4 COLLATE `utf8mb4_unicode_ci` ENGINE = InnoDB');
+    }
+
+    public function down(Schema $schema): void
+    {
+        // this down() migration is auto-generated, please modify it to your needs
+        $this->addSql('DROP TABLE redirect');
+    }
+}
diff --git a/src/Controller/Admin/RedirectCrudController.php b/src/Controller/Admin/RedirectCrudController.php
new file mode 100644
index 00000000..3b9f0e4a
--- /dev/null
+++ b/src/Controller/Admin/RedirectCrudController.php
@@ -0,0 +1,25 @@
+<?php
+
+namespace App\Controller\Admin;
+
+use App\Entity\Redirect;
+use EasyCorp\Bundle\EasyAdminBundle\Controller\AbstractCrudController;
+
+class RedirectCrudController extends AbstractCrudController
+{
+    public static function getEntityFqcn(): string
+    {
+        return Redirect::class;
+    }
+
+    /*
+    public function configureFields(string $pageName): iterable
+    {
+        return [
+            IdField::new('id'),
+            TextField::new('title'),
+            TextEditorField::new('description'),
+        ];
+    }
+    */
+}
diff --git a/src/Controller/PageController.php b/src/Controller/PageController.php
index c2a80953..86b70e7a 100644
--- a/src/Controller/PageController.php
+++ b/src/Controller/PageController.php
@@ -5,8 +5,10 @@ namespace App\Controller;
 use App\Entity\Comment;
 use App\Repository\CommentRepository;
 use App\Repository\PageRepository;
+use App\Repository\RedirectRepository;
 use App\Service\CaptchaService;
 use App\Service\PlaceholderService;
+use App\Service\S3Service;
 use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
 use Symfony\Component\HttpFoundation\RedirectResponse;
 use Symfony\Component\HttpFoundation\Request;
@@ -30,21 +32,34 @@ class PageController extends AbstractController
         Request $request,
         PageRepository $pageRepository,
         CaptchaService $captchaService,
-        PlaceholderService $placeholderService
+        PlaceholderService $placeholderService,
+        RedirectRepository $redirectRepository,
+        S3Service $s3Service
     ): Response {
 
         $page = $pageRepository->getPageFromURL($request->getPathInfo());
-        if (!$page) {
-            return $this->render('pages/error404.html.twig')->setStatusCode(404);
-        }
-        $page = $placeholderService->replacePlaceholderInPage($page);
-        return $this->render('pages/page.html.twig', [
+        if ($page) {
+            $page = $placeholderService->replacePlaceholderInPage($page);
+            return $this->render('pages/page.html.twig', [
             'page' => $page,
             'captcha' => $captchaService->getInlineCaptcha(),
             'name' => '',
             'email' => '',
             'comment' => ''
-        ]);
+            ]);
+        }
+
+        $redirect = $redirectRepository->getRedirectFromURL($request->getPathInfo());
+        if ($redirect) {
+            $url = $redirect->getRedirectURL();
+            if ($redirect->isIsS3File()) {
+                $url = $s3Service->generateSignedUrl('download/' . $url);
+            }
+            return new RedirectResponse($url);
+        }
+
+
+        return $this->render('pages/error404.html.twig')->setStatusCode(404);
     }
 
     #[Route('/{all}', requirements: ['all' => '.*'], methods: ['POST'], priority: -1)]
diff --git a/src/Entity/Redirect.php b/src/Entity/Redirect.php
new file mode 100644
index 00000000..c03c4932
--- /dev/null
+++ b/src/Entity/Redirect.php
@@ -0,0 +1,65 @@
+<?php
+
+namespace App\Entity;
+
+use App\Repository\RedirectRepository;
+use Doctrine\ORM\Mapping as ORM;
+
+#[ORM\Entity(repositoryClass: RedirectRepository::class)]
+class Redirect
+{
+    #[ORM\Id]
+    #[ORM\GeneratedValue]
+    #[ORM\Column]
+    private ?int $id = null;
+
+    #[ORM\Column(length: 255)]
+    private ?string $name = null;
+
+    #[ORM\Column(length: 255)]
+    private ?string $redirectURL = null;
+
+    #[ORM\Column]
+    private ?bool $isS3File = null;
+
+    public function getId(): ?int
+    {
+        return $this->id;
+    }
+
+    public function getName(): ?string
+    {
+        return $this->name;
+    }
+
+    public function setName(string $name): self
+    {
+        $this->name = $name;
+
+        return $this;
+    }
+
+    public function getRedirectURL(): ?string
+    {
+        return $this->redirectURL;
+    }
+
+    public function setRedirectURL(string $redirectURL): self
+    {
+        $this->redirectURL = $redirectURL;
+
+        return $this;
+    }
+
+    public function isIsS3File(): ?bool
+    {
+        return $this->isS3File;
+    }
+
+    public function setIsS3File(bool $isS3File): self
+    {
+        $this->isS3File = $isS3File;
+
+        return $this;
+    }
+}
diff --git a/src/Repository/RedirectRepository.php b/src/Repository/RedirectRepository.php
new file mode 100644
index 00000000..3cfff1ba
--- /dev/null
+++ b/src/Repository/RedirectRepository.php
@@ -0,0 +1,74 @@
+<?php
+
+namespace App\Repository;
+
+use App\Entity\Redirect;
+use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
+use Doctrine\Persistence\ManagerRegistry;
+
+/**
+ * @extends ServiceEntityRepository<Redirect>
+ *
+ * @method Redirect|null find($id, $lockMode = null, $lockVersion = null)
+ * @method Redirect|null findOneBy(array $criteria, array $orderBy = null)
+ * @method Redirect[]    findAll()
+ * @method Redirect[]    findBy(array $criteria, array $orderBy = null, $limit = null, $offset = null)
+ */
+class RedirectRepository extends ServiceEntityRepository
+{
+    public function __construct(ManagerRegistry $registry)
+    {
+        parent::__construct($registry, Redirect::class);
+    }
+
+    public function save(Redirect $entity, bool $flush = false): void
+    {
+        $this->getEntityManager()->persist($entity);
+
+        if ($flush) {
+            $this->getEntityManager()->flush();
+        }
+    }
+
+    public function remove(Redirect $entity, bool $flush = false): void
+    {
+        $this->getEntityManager()->remove($entity);
+
+        if ($flush) {
+            $this->getEntityManager()->flush();
+        }
+    }
+
+    public function getRedirectFromURL(string $url): Redirect|null
+    {
+        return $this->createQueryBuilder('r')
+            ->where('r.name = :path')
+            ->setParameter('path', $url)
+            ->getQuery()
+            ->getOneOrNullResult();
+    }
+//    /**
+//     * @return Redirect[] Returns an array of Redirect objects
+//     */
+//    public function findByExampleField($value): array
+//    {
+//        return $this->createQueryBuilder('r')
+//            ->andWhere('r.exampleField = :val')
+//            ->setParameter('val', $value)
+//            ->orderBy('r.id', 'ASC')
+//            ->setMaxResults(10)
+//            ->getQuery()
+//            ->getResult()
+//        ;
+//    }
+
+//    public function findOneBySomeField($value): ?Redirect
+//    {
+//        return $this->createQueryBuilder('r')
+//            ->andWhere('r.exampleField = :val')
+//            ->setParameter('val', $value)
+//            ->getQuery()
+//            ->getOneOrNullResult()
+//        ;
+//    }
+}
-- 
GitLab