From ed439905f55e756b1c4a7bc37750d5884ddb15b6 Mon Sep 17 00:00:00 2001
From: Jonas Leder <jonas@jonasled.de>
Date: Mon, 28 Nov 2022 10:23:18 +0100
Subject: [PATCH] implement pagination for history

---
 composer.json                        |   1 +
 composer.lock                        | 258 ++++++++++++++++++++++++++-
 config/bundles.php                   |   1 +
 config/packages/knp_paginator.yaml   |   3 +
 config/packages/translation.yaml     |  13 ++
 src/Controller/HistoryController.php |  22 ++-
 symfony.lock                         |  16 ++
 templates/pages/history.html.twig    |   7 +-
 translations/.gitignore              |   0
 9 files changed, 311 insertions(+), 10 deletions(-)
 create mode 100644 config/packages/knp_paginator.yaml
 create mode 100644 config/packages/translation.yaml
 create mode 100644 translations/.gitignore

diff --git a/composer.json b/composer.json
index f83c7eb..8cd92b2 100644
--- a/composer.json
+++ b/composer.json
@@ -10,6 +10,7 @@
         "doctrine/doctrine-bundle": "^2.7",
         "doctrine/doctrine-migrations-bundle": "^3.2",
         "doctrine/orm": "^2.13",
+        "knplabs/knp-paginator-bundle": "^6.0",
         "scheb/2fa-bundle": "^6.3",
         "scheb/2fa-google-authenticator": "^6.3",
         "symfony/console": "6.1.*",
diff --git a/composer.lock b/composer.lock
index 51ea395..57e2ae3 100644
--- a/composer.lock
+++ b/composer.lock
@@ -4,7 +4,7 @@
         "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
         "This file is @generated automatically"
     ],
-    "content-hash": "82615f0b7f2f0e427cc6532cf5a57cf9",
+    "content-hash": "5203af63acc967dbd6bca06908fb1220",
     "packages": [
         {
             "name": "doctrine/annotations",
@@ -1458,6 +1458,166 @@
             ],
             "time": "2022-10-17T19:48:16+00:00"
         },
+        {
+            "name": "knplabs/knp-components",
+            "version": "v4.0.1",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/KnpLabs/knp-components.git",
+                "reference": "fc88b7073f98c2a73b5d8391bb5f1b4dfedd33fd"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/KnpLabs/knp-components/zipball/fc88b7073f98c2a73b5d8391bb5f1b4dfedd33fd",
+                "reference": "fc88b7073f98c2a73b5d8391bb5f1b4dfedd33fd",
+                "shasum": ""
+            },
+            "require": {
+                "php": "^8.0",
+                "symfony/event-dispatcher-contracts": "^3.0"
+            },
+            "conflict": {
+                "doctrine/dbal": "<2.10"
+            },
+            "require-dev": {
+                "doctrine/mongodb-odm": "^2.4",
+                "doctrine/orm": "^2.12",
+                "doctrine/phpcr-odm": "^1.6",
+                "ext-pdo_sqlite": "*",
+                "jackalope/jackalope-doctrine-dbal": "^1.8",
+                "phpunit/phpunit": "^9.5",
+                "propel/propel1": "^1.7",
+                "ruflin/elastica": "^7.0",
+                "solarium/solarium": "^6.0",
+                "symfony/http-foundation": "^5.4 || ^6.0",
+                "symfony/http-kernel": "^5.4 || ^6.0",
+                "symfony/property-access": "^5.4 || ^6.0"
+            },
+            "suggest": {
+                "doctrine/common": "to allow usage pagination with Doctrine ArrayCollection",
+                "doctrine/mongodb-odm": "to allow usage pagination with Doctrine ODM MongoDB",
+                "doctrine/orm": "to allow usage pagination with Doctrine ORM",
+                "doctrine/phpcr-odm": "to allow usage pagination with Doctrine ODM PHPCR",
+                "propel/propel1": "to allow usage pagination with Propel ORM",
+                "ruflin/elastica": "to allow usage pagination with ElasticSearch Client",
+                "solarium/solarium": "to allow usage pagination with Solarium Client",
+                "symfony/http-foundation": "to retrieve arguments from Request",
+                "symfony/property-access": "to allow sorting arrays"
+            },
+            "type": "library",
+            "extra": {
+                "branch-alias": {
+                    "dev-master": "4.x-dev"
+                }
+            },
+            "autoload": {
+                "psr-4": {
+                    "Knp\\Component\\": "src/Knp/Component"
+                }
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "MIT"
+            ],
+            "authors": [
+                {
+                    "name": "KnpLabs Team",
+                    "homepage": "https://knplabs.com"
+                },
+                {
+                    "name": "Symfony Community",
+                    "homepage": "https://github.com/KnpLabs/knp-components/contributors"
+                }
+            ],
+            "description": "Knplabs component library",
+            "homepage": "http://github.com/KnpLabs/knp-components",
+            "keywords": [
+                "components",
+                "knp",
+                "knplabs",
+                "pager",
+                "paginator"
+            ],
+            "support": {
+                "issues": "https://github.com/KnpLabs/knp-components/issues",
+                "source": "https://github.com/KnpLabs/knp-components/tree/v4.0.1"
+            },
+            "time": "2022-10-01T07:31:54+00:00"
+        },
+        {
+            "name": "knplabs/knp-paginator-bundle",
+            "version": "v6.0.0",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/KnpLabs/KnpPaginatorBundle.git",
+                "reference": "2f9f36654de838556987d0e90eabe48b5e49e136"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/KnpLabs/KnpPaginatorBundle/zipball/2f9f36654de838556987d0e90eabe48b5e49e136",
+                "reference": "2f9f36654de838556987d0e90eabe48b5e49e136",
+                "shasum": ""
+            },
+            "require": {
+                "knplabs/knp-components": "^4.0",
+                "php": "^8.0",
+                "symfony/config": "^6.0",
+                "symfony/dependency-injection": "^6.0",
+                "symfony/event-dispatcher": "^6.0",
+                "symfony/http-foundation": "^6.0",
+                "symfony/http-kernel": "^6.0",
+                "symfony/routing": "^6.0",
+                "symfony/translation": "^6.0",
+                "twig/twig": "^3.0"
+            },
+            "require-dev": {
+                "phpstan/phpstan": "^1.8",
+                "phpunit/phpunit": "^9.5",
+                "symfony/expression-language": "^6.0",
+                "symfony/templating": "^6.0"
+            },
+            "type": "symfony-bundle",
+            "extra": {
+                "branch-alias": {
+                    "dev-master": "5.x-dev"
+                }
+            },
+            "autoload": {
+                "psr-4": {
+                    "Knp\\Bundle\\PaginatorBundle\\": "src"
+                }
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "MIT"
+            ],
+            "authors": [
+                {
+                    "name": "KnpLabs Team",
+                    "homepage": "http://knplabs.com"
+                },
+                {
+                    "name": "Symfony Community",
+                    "homepage": "http://github.com/KnpLabs/KnpPaginatorBundle/contributors"
+                }
+            ],
+            "description": "Paginator bundle for Symfony to automate pagination and simplify sorting and other features",
+            "homepage": "http://github.com/KnpLabs/KnpPaginatorBundle",
+            "keywords": [
+                "bundle",
+                "knp",
+                "knplabs",
+                "pager",
+                "pagination",
+                "paginator",
+                "symfony"
+            ],
+            "support": {
+                "issues": "https://github.com/KnpLabs/KnpPaginatorBundle/issues",
+                "source": "https://github.com/KnpLabs/KnpPaginatorBundle/tree/v6.0.0"
+            },
+            "time": "2022-11-01T15:37:33+00:00"
+        },
         {
             "name": "laminas/laminas-code",
             "version": "4.7.1",
@@ -5023,6 +5183,102 @@
             ],
             "time": "2022-10-10T09:34:31+00:00"
         },
+        {
+            "name": "symfony/translation",
+            "version": "v6.1.6",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/symfony/translation.git",
+                "reference": "e6cd330e5a072518f88d65148f3f165541807494"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/symfony/translation/zipball/e6cd330e5a072518f88d65148f3f165541807494",
+                "reference": "e6cd330e5a072518f88d65148f3f165541807494",
+                "shasum": ""
+            },
+            "require": {
+                "php": ">=8.1",
+                "symfony/polyfill-mbstring": "~1.0",
+                "symfony/translation-contracts": "^2.3|^3.0"
+            },
+            "conflict": {
+                "symfony/config": "<5.4",
+                "symfony/console": "<5.4",
+                "symfony/dependency-injection": "<5.4",
+                "symfony/http-kernel": "<5.4",
+                "symfony/twig-bundle": "<5.4",
+                "symfony/yaml": "<5.4"
+            },
+            "provide": {
+                "symfony/translation-implementation": "2.3|3.0"
+            },
+            "require-dev": {
+                "psr/log": "^1|^2|^3",
+                "symfony/config": "^5.4|^6.0",
+                "symfony/console": "^5.4|^6.0",
+                "symfony/dependency-injection": "^5.4|^6.0",
+                "symfony/finder": "^5.4|^6.0",
+                "symfony/http-client-contracts": "^1.1|^2.0|^3.0",
+                "symfony/http-kernel": "^5.4|^6.0",
+                "symfony/intl": "^5.4|^6.0",
+                "symfony/polyfill-intl-icu": "^1.21",
+                "symfony/routing": "^5.4|^6.0",
+                "symfony/service-contracts": "^1.1.2|^2|^3",
+                "symfony/yaml": "^5.4|^6.0"
+            },
+            "suggest": {
+                "psr/log-implementation": "To use logging capability in translator",
+                "symfony/config": "",
+                "symfony/yaml": ""
+            },
+            "type": "library",
+            "autoload": {
+                "files": [
+                    "Resources/functions.php"
+                ],
+                "psr-4": {
+                    "Symfony\\Component\\Translation\\": ""
+                },
+                "exclude-from-classmap": [
+                    "/Tests/"
+                ]
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "MIT"
+            ],
+            "authors": [
+                {
+                    "name": "Fabien Potencier",
+                    "email": "fabien@symfony.com"
+                },
+                {
+                    "name": "Symfony Community",
+                    "homepage": "https://symfony.com/contributors"
+                }
+            ],
+            "description": "Provides tools to internationalize your application",
+            "homepage": "https://symfony.com",
+            "support": {
+                "source": "https://github.com/symfony/translation/tree/v6.1.6"
+            },
+            "funding": [
+                {
+                    "url": "https://symfony.com/sponsor",
+                    "type": "custom"
+                },
+                {
+                    "url": "https://github.com/fabpot",
+                    "type": "github"
+                },
+                {
+                    "url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
+                    "type": "tidelift"
+                }
+            ],
+            "time": "2022-10-07T08:04:03+00:00"
+        },
         {
             "name": "symfony/translation-contracts",
             "version": "v3.1.1",
diff --git a/config/bundles.php b/config/bundles.php
index 1b34c84..481bc63 100644
--- a/config/bundles.php
+++ b/config/bundles.php
@@ -13,4 +13,5 @@ return [
     Symfony\UX\TwigComponent\TwigComponentBundle::class => ['all' => true],
     Scheb\TwoFactorBundle\SchebTwoFactorBundle::class => ['all' => true],
     Symfony\UX\Turbo\TurboBundle::class => ['all' => true],
+    Knp\Bundle\PaginatorBundle\KnpPaginatorBundle::class => ['all' => true],
 ];
diff --git a/config/packages/knp_paginator.yaml b/config/packages/knp_paginator.yaml
new file mode 100644
index 0000000..fc55e78
--- /dev/null
+++ b/config/packages/knp_paginator.yaml
@@ -0,0 +1,3 @@
+knp_paginator:
+  template:
+    pagination: '@KnpPaginator/Pagination/twitter_bootstrap_v4_pagination.html.twig'
\ No newline at end of file
diff --git a/config/packages/translation.yaml b/config/packages/translation.yaml
new file mode 100644
index 0000000..abb76aa
--- /dev/null
+++ b/config/packages/translation.yaml
@@ -0,0 +1,13 @@
+framework:
+    default_locale: en
+    translator:
+        default_path: '%kernel.project_dir%/translations'
+        fallbacks:
+            - en
+#        providers:
+#            crowdin:
+#                dsn: '%env(CROWDIN_DSN)%'
+#            loco:
+#                dsn: '%env(LOCO_DSN)%'
+#            lokalise:
+#                dsn: '%env(LOKALISE_DSN)%'
diff --git a/src/Controller/HistoryController.php b/src/Controller/HistoryController.php
index 982042a..9fead5c 100644
--- a/src/Controller/HistoryController.php
+++ b/src/Controller/HistoryController.php
@@ -5,7 +5,9 @@ namespace App\Controller;
 use App\Entity\Users;
 use App\Repository\HistoryRepository;
 use App\Repository\WebResetterRepository;
+use Knp\Component\Pager\PaginatorInterface;
 use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
+use Symfony\Component\HttpFoundation\Request;
 use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException;
 use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
 use Symfony\Component\Routing\Annotation\Route;
@@ -14,32 +16,38 @@ use function Doctrine\ORM\QueryBuilder;
 class HistoryController extends AbstractController
 {
     #[Route('/history/{deviceId}', methods: ['GET'], name: 'app_history')]
-    public function getHistory(HistoryRepository $historyRepository, WebResetterRepository $webResetterRepository, string $deviceId = null) {
+    public function getHistory(HistoryRepository $historyRepository, WebResetterRepository $webResetterRepository, Request $request, PaginatorInterface $paginator, string $deviceId = null)
+    {
         /**
-         * @var Users $user;
+         * @var Users $user ;
          */
         $user = $this->getUser();
         $query = $historyRepository->createQueryBuilder('h')->orderBy('h.id', 'DESC');
 
         if ($deviceId) {
             $device = $webResetterRepository->find($deviceId);
-            if(!$device) {
+            if (!$device) {
                 throw new NotFoundHttpException();
             }
 
             if (!$device->getUsers()->contains($this->getUser()) && !$user->isAdminAccess()) {
-               throw new AccessDeniedHttpException();
+                throw new AccessDeniedHttpException();
             }
             $query->andWhere('h.device = :device')
                 ->setParameter(':device', $device);
-     } elseif(!$user->isAdminAccess())
-        {
+        } elseif (!$user->isAdminAccess()) {
             $query->andWhere($query->expr()->in('h.device', ':devices'))
                 ->setParameter('devices', $user->getWebResetter()->toArray());
         }
 
+        $pagination = $paginator->paginate(
+            $query, /* query NOT result */
+            $request->query->getInt('page', 1), /*page number*/
+            20 /*limit per page*/
+        );
+
         return $this->render('pages/history.html.twig', [
-           'history' => $query->getQuery()->execute()
+            'pagination' => $pagination
         ]);
     }
 }
\ No newline at end of file
diff --git a/symfony.lock b/symfony.lock
index f07681b..a10cecc 100644
--- a/symfony.lock
+++ b/symfony.lock
@@ -35,6 +35,9 @@
             "migrations/.gitignore"
         ]
     },
+    "knplabs/knp-paginator-bundle": {
+        "version": "v6.0.0"
+    },
     "scheb/2fa-bundle": {
         "version": "6.3",
         "recipe": {
@@ -137,6 +140,19 @@
             "config/packages/security.yaml"
         ]
     },
+    "symfony/translation": {
+        "version": "6.1",
+        "recipe": {
+            "repo": "github.com/symfony/recipes",
+            "branch": "main",
+            "version": "5.3",
+            "ref": "da64f5a2b6d96f5dc24914517c0350a5f91dee43"
+        },
+        "files": [
+            "config/packages/translation.yaml",
+            "translations/.gitignore"
+        ]
+    },
     "symfony/twig-bundle": {
         "version": "6.1",
         "recipe": {
diff --git a/templates/pages/history.html.twig b/templates/pages/history.html.twig
index 1aeaa87..1e0ba94 100644
--- a/templates/pages/history.html.twig
+++ b/templates/pages/history.html.twig
@@ -2,8 +2,11 @@
 {% block title %}History{% endblock %}
 {% block content %}
     <div class="container">
-        {% for historyElement in history %}
-            {{ component('history_accordion', {'history': historyElement}) }}
+        {% for history in pagination %}
+            {{ component('history_accordion', {'history': history}) }}
         {% endfor %}
+        <div class="navigation mt-2">
+            {{ knp_pagination_render(pagination) }}
+        </div>
     </div>
 {% endblock %}
\ No newline at end of file
diff --git a/translations/.gitignore b/translations/.gitignore
new file mode 100644
index 0000000..e69de29
-- 
GitLab