Bladeren bron

setup route indexing commands and basic resolver

Olivier Massot 4 jaren geleden
bovenliggende
commit
e3ca61abcc

+ 103 - 0
ot_admin/Classes/Command/UpdateRoutingIndexCommand.php

@@ -0,0 +1,103 @@
+<?php
+
+namespace Opentalent\OtAdmin\Command;
+
+
+use Opentalent\OtAdmin\Controller\SiteController;
+use Symfony\Component\Console\Command\Command;
+use Symfony\Component\Console\Input\InputArgument;
+use Symfony\Component\Console\Input\InputInterface;
+use Symfony\Component\Console\Input\InputOption;
+use Symfony\Component\Console\Output\OutputInterface;
+use Symfony\Component\Console\Style\SymfonyStyle;
+use TYPO3\CMS\Core\Database\ConnectionPool;
+use TYPO3\CMS\Core\Utility\GeneralUtility;
+use TYPO3\CMS\Extbase\Object\ObjectManager;
+
+/**
+ * This CLI command updates the routing index for the given website
+ *
+ * @package Opentalent\OtAdmin\Command
+ */
+class UpdateRoutingIndexCommand extends Command
+{
+    /**
+     * -- This method is expected by Typo3, do not rename ou remove --
+     *
+     * Allows to configure the command.
+     * Allows to add a description, a help text, and / or define arguments.
+     *
+     */
+    protected function configure()
+    {
+        $this
+            ->setName("ot:site:index")
+            ->setDescription("Update the routes index for the given website(s)")
+            ->setHelp("This CLI command updates the routing index for the given website")
+            ->addOption(
+                'all',
+                null,
+                InputOption::VALUE_NONE,
+                "Update all of the organization websites"
+            )
+            ->addArgument(
+                'organization-id',
+                InputArgument::OPTIONAL,
+                "The organization's id in the opentalent DB"
+            );
+    }
+
+    /**
+     * -- This method is expected by Typo3, do not rename ou remove --
+     *
+     * @param InputInterface $input
+     * @param OutputInterface $output
+     * @throws \Exception
+     */
+    protected function execute(InputInterface $input, OutputInterface $output)
+    {
+        $org_id = $input->getArgument('organization-id');
+        $all = $input->getOption('all');
+
+        if ($all && $org_id) {
+            throw new \InvalidArgumentException("You can not pass both an organization id and the --all option");
+        }
+        if (!$all && !$org_id) {
+            throw new \InvalidArgumentException("You shall either pass an organization id or use the --all option");
+        }
+
+        $io = new SymfonyStyle($input, $output);
+
+        $siteController = GeneralUtility::makeInstance(ObjectManager::class)->get(SiteController::class);
+
+        if ($all) {
+            $connectionPool = GeneralUtility::makeInstance(ConnectionPool::class);
+            $queryBuilder = $connectionPool->getQueryBuilderForTable('pages');
+            $sites = $queryBuilder
+                ->select('tx_opentalent_structure_id')
+                ->from('pages')
+                ->where('is_siteroot=1')
+                ->andWhere($queryBuilder->expr()->gt('tx_opentalent_structure_id', 0))
+                ->execute()
+                ->fetchAll();
+
+            $io->progressStart(count($sites));
+
+            foreach ($sites as $site) {
+                $org_id = $site['tx_opentalent_structure_id'];
+                try {
+                    $siteController->updateRoutingIndexAction($org_id);
+                } catch (\Throwable $e) {
+                    $io->error('Organization Id: ' . $org_id . ' - ' . $e->getMessage());
+                }
+                $io->progressAdvance(1);
+            }
+            $io->progressFinish();
+
+            $io->success(sprintf("The routing index has all been fully updated"));
+        } else {
+            $rootUid = $siteController->updateRoutingIndexAction($org_id);
+            $io->success(sprintf("The website with root uid " . $rootUid . " routing index has been updated"));
+        }
+    }
+}

+ 17 - 1
ot_admin/Classes/Controller/SiteController.php

@@ -13,6 +13,7 @@ use Opentalent\OtCore\Domain\Model\Organization;
 use Opentalent\OtCore\Domain\Repository\OrganizationRepository;
 use Opentalent\OtCore\Domain\Repository\OrganizationRepository;
 use Opentalent\OtCore\Exception\ApiRequestException;
 use Opentalent\OtCore\Exception\ApiRequestException;
 use Opentalent\OtCore\Utility\FileUtility;
 use Opentalent\OtCore\Utility\FileUtility;
+use Opentalent\OtRouter\Routing\Indexer;
 use PDO;
 use PDO;
 use Symfony\Component\Yaml\Yaml;
 use Symfony\Component\Yaml\Yaml;
 use TYPO3\CMS\Core\Cache\Exception\NoSuchCacheException;
 use TYPO3\CMS\Core\Cache\Exception\NoSuchCacheException;
@@ -691,7 +692,8 @@ class SiteController extends ActionController
             }
             }
 
 
             // ## Reset the routing index
             // ## Reset the routing index
-            // TODO: complete
+            $routingIndexer = GeneralUtility::makeInstance(ObjectManager::class)->get(Indexer::class);
+            $routingIndexer->indexRoutesForWebsite($rootUid);
 
 
             // Try to commit the result
             // Try to commit the result
             $commitSuccess = $this->connectionPool->getConnectionByName('Default')->commit();
             $commitSuccess = $this->connectionPool->getConnectionByName('Default')->commit();
@@ -1683,6 +1685,20 @@ class SiteController extends ActionController
         }
         }
     }
     }
 
 
+    /**
+     * Update the routing index for the given website
+     *
+     * @param int $organizationId
+     * @throws NoSuchWebsiteException
+     */
+    public function updateRoutingIndexAction(int $organizationId)
+    {
+        $rootUid = $this->findRootUidFor($organizationId);
+
+        $routingIndexer = GeneralUtility::makeInstance(ObjectManager::class)->get(Indexer::class);
+        $routingIndexer->indexRoutesForWebsite($rootUid);
+    }
+
     /**
     /**
      * Retrieve the Organization object from the repository and then,
      * Retrieve the Organization object from the repository and then,
      * from the Opentalent API
      * from the Opentalent API

+ 28 - 1
ot_admin/Classes/Http/ApiController.php

@@ -298,7 +298,6 @@ class ApiController implements LoggerAwareInterface
         );
         );
     }
     }
 
 
-
     /**
     /**
      * -- Target of the route 'site_resetperms' --
      * -- Target of the route 'site_resetperms' --
      * >> Requires a query param named 'organization-id' (int)
      * >> Requires a query param named 'organization-id' (int)
@@ -327,6 +326,34 @@ class ApiController implements LoggerAwareInterface
         );
         );
     }
     }
 
 
+    /**
+     * -- Target of the route 'site_reindex' --
+     * >> Requires a query param named 'organization-id' (int)
+     *
+     * Update the routing index for the given website
+     *
+     * @param ServerRequest $request
+     * @return JsonResponse
+     * @throws \Exception
+     */
+    public function updateRoutingIndexAction(ServerRequest $request): JsonResponse
+    {
+        $this->assertIpAllowed();
+
+        $organizationId = $this->getOrganizationId($request);
+
+        $controller = GeneralUtility::makeInstance(ObjectManager::class)->get(SiteController::class);
+        $rootUid = $controller->updateRoutingIndexAction($organizationId);
+
+        return new JsonResponse(
+            [
+                'organization_id' => $organizationId,
+                'msg' => "The website with root uid " . $rootUid . " routing index has been updated",
+                'root_uid' => $rootUid
+            ]
+        );
+    }
+
     /**
     /**
      * -- Target of the route 'site_status' --
      * -- Target of the route 'site_status' --
      * >> Requires a query param named 'organization-id' (int)
      * >> Requires a query param named 'organization-id' (int)

+ 5 - 0
ot_admin/Configuration/Backend/Routes.php

@@ -42,6 +42,11 @@ return [
         'target' => ApiController::class . '::resetBeUserPermsAction',
         'target' => ApiController::class . '::resetBeUserPermsAction',
         'access' => 'public'
         'access' => 'public'
     ],
     ],
+    'site_index' => [
+        'path' => '/otadmin/site/index',
+        'target' => ApiController::class . '::updateRoutingIndexAction',
+        'access' => 'public'
+    ],
     'site_status' => [
     'site_status' => [
         'path' => '/otadmin/site/status',
         'path' => '/otadmin/site/status',
         'target' => ApiController::class . '::getSiteStatusAction',
         'target' => ApiController::class . '::getSiteStatusAction',

+ 3 - 0
ot_admin/Configuration/Commands.php

@@ -31,6 +31,9 @@ return [
     'ot:site:reset-perms' => [
     'ot:site:reset-perms' => [
         'class' => Opentalent\OtAdmin\Command\ResetBeUserPermsCommand::class
         'class' => Opentalent\OtAdmin\Command\ResetBeUserPermsCommand::class
     ],
     ],
+    'ot:site:index' => [
+        'class' => Opentalent\OtAdmin\Command\UpdateRoutingIndexCommand::class
+    ],
     'ot:site:status' => [
     'ot:site:status' => [
         'class' => Opentalent\OtAdmin\Command\GetSiteStatusCommand::class
         'class' => Opentalent\OtAdmin\Command\GetSiteStatusCommand::class
     ],
     ],

+ 6 - 0
ot_admin/Configuration/Services.yaml

@@ -43,6 +43,12 @@ services:
         command: 'ot:site:reset-perms'
         command: 'ot:site:reset-perms'
         schedulable: true
         schedulable: true
 
 
+  Opentalent\OtAdmin\Command\UpdateRoutingIndexCommand:
+    tags:
+      - name: 'ot:site:index'
+        command: 'ot:site:index'
+        schedulable: true
+
   Opentalent\OtAdmin\Command\GetSiteStatusCommand:
   Opentalent\OtAdmin\Command\GetSiteStatusCommand:
     tags:
     tags:
       - name: 'ot:site:status'
       - name: 'ot:site:status'

+ 3 - 1
ot_admin/Readme.md

@@ -9,7 +9,9 @@ This extension provides commands available by the API, CLI, or a dedicated admin
 | Vendor | Opentalent |
 | Vendor | Opentalent |
 | Nom | OtAdmin |
 | Nom | OtAdmin |
 
 
-> Warning: this extension depends on the ot_templating extension
+**IMPORTANT**:
+
+* Cette extension dépend de l'extension OtRouter
 
 
 ## CLI
 ## CLI
 
 

+ 0 - 2
ot_core/Readme.md

@@ -15,8 +15,6 @@ Cette extension fournit de nombreuses classes et ressources communes aux autres
 
 
 * Cette extension ne doit dépendre d'aucune autre pour fonctionner, c'est à dire que son fonctionnement ne doit 
 * Cette extension ne doit dépendre d'aucune autre pour fonctionner, c'est à dire que son fonctionnement ne doit 
 pas être modifié si aucune autre extension n'est installée
 pas être modifié si aucune autre extension n'est installée
-* Cette extension est aussi la seule dont les autres extensions doivent pouvoir dépendre
-
 
 
 ### Pour lancer les tests unitaires:
 ### Pour lancer les tests unitaires:
 
 

+ 0 - 58
ot_router/Classes/Indexer/RoutingIndexer.php

@@ -1,58 +0,0 @@
-<?php
-
-namespace Opentalent\OtRouter\Controller;
-
-use Opentalent\OtCore\Domain\Repository\OrganizationRepository;
-use Opentalent\OtCore\Page\OtPageRepository;
-use TYPO3\CMS\Core\Database\ConnectionPool;
-
-/**
- * Provides methods to index the Typo3 pages and populate the routing db table
- *
- * @package Opentalent\OtRouter\Controller
- */
-class RoutingIndexer
-{
-    const INDEX_TABLENAME = 'tx_opentalent_router';
-
-    /**
-     * @var ConnectionPool
-     */
-    private ConnectionPool $connectionPool;
-
-    public function injectConnectionPool(ConnectionPool $connectionPool)
-    {
-        $this->connectionPool = $connectionPool;
-    }
-
-    /**
-     * @var OtPageRepository
-     */
-    protected OtPageRepository $otPageRepository;
-
-    public function injectOtPageRepository(OtPageRepository $otPageRepository) {
-        $this->otPageRepository = $otPageRepository;
-    }
-
-    protected OrganizationRepository $organizationRepository;
-
-    public function injectOrganizationRepository(OrganizationRepository $organizationRepository) {
-        $this->organizationRepository = $organizationRepository;
-    }
-
-    /**
-     * Clear then repopulate the whole index
-     */
-    public function indexAllRoutes() {
-
-    }
-
-    /**
-     * Clear and recreate the index entry for the target website organization
-     *
-     * @param int $organizationId
-     */
-    public function indexRoutesFor(int $organizationId) {
-
-    }
-}

+ 9 - 2
ot_router/Classes/Middleware/Router.php

@@ -1,11 +1,13 @@
 <?php
 <?php
 namespace Opentalent\OtRouter\Middleware;
 namespace Opentalent\OtRouter\Middleware;
 
 
+use Opentalent\OtRouter\Routing\Resolver;
 use Psr\Http\Message\ResponseInterface;
 use Psr\Http\Message\ResponseInterface;
 use Psr\Http\Message\ServerRequestInterface;
 use Psr\Http\Message\ServerRequestInterface;
 use Psr\Http\Server\MiddlewareInterface;
 use Psr\Http\Server\MiddlewareInterface;
 use Psr\Http\Server\RequestHandlerInterface;
 use Psr\Http\Server\RequestHandlerInterface;
-use TYPO3\CMS\Core\Http\RedirectResponse;
+use TYPO3\CMS\Core\Utility\GeneralUtility;
+use TYPO3\CMS\Extbase\Object\ObjectManager;
 
 
 /**
 /**
  * Hooks into the frontend request and use the index table to resolve a page uid
  * Hooks into the frontend request and use the index table to resolve a page uid
@@ -24,7 +26,12 @@ class Router implements MiddlewareInterface
     {
     {
         $uri = $request->getUri();
         $uri = $request->getUri();
 
 
-        
+        $resolver = GeneralUtility::makeInstance(ObjectManager::class)->get(Resolver::class);
+
+        $pageUid = $resolver->getPageUid(
+            $uri->getHost(),
+            $uri->getPath(),
+        );
 
 
         // just pass the plate to the next middleware...
         // just pass the plate to the next middleware...
         return $handler->handle($request);
         return $handler->handle($request);

+ 106 - 0
ot_router/Classes/Routing/Indexer.php

@@ -0,0 +1,106 @@
+<?php
+
+namespace Opentalent\OtRouter\Routing;
+
+use Opentalent\OtCore\Page\OtPageRepository;
+use Opentalent\OtRouter\Utility\RouteNormalizer;
+use TYPO3\CMS\Core\Database\ConnectionPool;
+
+/**
+ * Provides methods to index the Typo3 pages and populate the routing db table
+ *
+ * @package Opentalent\OtRouter\Routing
+ */
+class Indexer
+{
+    const INDEX_TABLENAME = 'tx_opentalent_router';
+
+    /**
+     * @var ConnectionPool
+     */
+    private ConnectionPool $connectionPool;
+
+    public function injectConnectionPool(ConnectionPool $connectionPool)
+    {
+        $this->connectionPool = $connectionPool;
+    }
+
+    /**
+     * @var OtPageRepository
+     */
+    protected OtPageRepository $otPageRepository;
+
+    public function injectOtPageRepository(OtPageRepository $otPageRepository) {
+        $this->otPageRepository = $otPageRepository;
+    }
+
+    /**
+     * Clear then repopulate the whole index
+     */
+    public function indexAllRoutes() {
+        $queryBuilder = $this->connectionPool->getQueryBuilderForTable('pages');
+        $rootPages = $queryBuilder
+            ->select('uid')
+            ->from('pages')
+            ->where($queryBuilder->expr()->eq('is_siteroot', 1))
+            ->execute()
+            ->fetchAll();
+
+        foreach ($rootPages as $rootPage) {
+            $this->indexRoutesForWebsite($rootPage);
+        }
+    }
+
+    /**
+     * Clear and recreate the index entry for the target website
+     *
+     * @param int $rootUid
+     */
+    public function indexRoutesForWebsite(int $rootUid) {
+        foreach ($this->otPageRepository->getAllSitePages($rootUid) as $page) {
+            $this->registerIndexEntry(
+                $page['uid'],
+                $page['tx_opentalent_structure_domain'],
+                $page['slug'],
+                $rootUid
+            );
+        }
+    }
+
+    public function indexRouteForPage(int $pageUid) {
+        $page = $this->otPageRepository->getPage($pageUid);
+        $rootPage = $this->otPageRepository->getRootPageFor($pageUid);
+
+        $this->registerIndexEntry(
+            $page['uid'],
+            $page['tx_opentalent_structure_domain'],
+            $page['slug'],
+            $rootPage['uid']
+        );
+    }
+
+    private function registerIndexEntry(int $pageUid,
+                                      string $domain,
+                                      string $slug,
+                                      ?int $rootUid = null) {
+        $queryBuilder = $this->connectionPool->getQueryBuilderForTable(self::INDEX_TABLENAME);
+        $queryBuilder
+            ->delete(self::INDEX_TABLENAME)
+            ->where($queryBuilder->expr()->eq('page_uid', $pageUid))
+            ->execute();
+
+        $entry = [
+            'domain' => RouteNormalizer::normalizeDomain($domain),
+            'root_uid' => $rootUid,
+            'slug' => RouteNormalizer::normalizeSlug($slug),
+            'page_uid' => $pageUid,
+            'last_update' => date('Y-m-d H:i:s')
+        ];
+
+        $queryBuilder = $this->connectionPool->getQueryBuilderForTable(self::INDEX_TABLENAME);
+        $queryBuilder
+            ->insert(self::INDEX_TABLENAME)
+            ->values($entry)
+            ->execute();
+    }
+}

+ 0 - 3
ot_router/Readme.md

@@ -8,9 +8,6 @@ Bypass the builtin Typo3 routing with dedicated router adapted to a large amount
 | Vendor | Opentalent |
 | Vendor | Opentalent |
 | Nom | OtRouter |
 | Nom | OtRouter |
 
 
-> **IMPORTANT**: This extension only aims to improve performances. **If disabled, it shall not 
-> cause anything else than performances losses**. We need to be able to disable it anytime without other consequences.
-
 Cette extension implémente un système de routing basé sur un index des pages sous forme de table additionnelle dans la
 Cette extension implémente un système de routing basé sur un index des pages sous forme de table additionnelle dans la
 base de données.
 base de données.
 
 

+ 4 - 4
ot_router/composer.json

@@ -13,16 +13,16 @@
     },
     },
     "autoload": {
     "autoload": {
         "psr-4": {
         "psr-4": {
-            "Opentalent\\OtOptimizer\\": "Classes"
+            "Opentalent\\OtRouter\\": "Classes"
         }
         }
     },
     },
     "autoload-dev": {
     "autoload-dev": {
         "psr-4": {
         "psr-4": {
-            "Opentalent\\OtOptimizer\\Tests\\": "Tests"
+            "Opentalent\\OtRouter\\Tests\\": "Tests"
         }
         }
     },
     },
     "replace": {
     "replace": {
-        "ot_optimizer": "self.version",
-        "typo3-ter/ot-optimizer": "self.version"
+        "ot_router": "self.version",
+        "typo3-ter/ot-router": "self.version"
     }
     }
 }
 }

+ 2 - 2
ot_router/ext_tables.sql

@@ -4,12 +4,12 @@
 # Table structure for table 'tx_opentalent_router'
 # Table structure for table 'tx_opentalent_router'
 #
 #
 CREATE TABLE tx_opentalent_router (
 CREATE TABLE tx_opentalent_router (
-    uid INT UNSIGNED NOT NULL,
+    uid INT UNSIGNED NOT NULL AUTO_INCREMENT,
     domain VARCHAR(2048) NOT NULL,
     domain VARCHAR(2048) NOT NULL,
     root_uid INT UNSIGNED NOT NULL,
     root_uid INT UNSIGNED NOT NULL,
-    structure_id INT UNSIGNED NOT NULL,
     slug VARCHAR(2048) NOT NULL,
     slug VARCHAR(2048) NOT NULL,
     page_uid INT UNSIGNED NOT NULL,
     page_uid INT UNSIGNED NOT NULL,
     last_update DATETIME NOT NULL,
     last_update DATETIME NOT NULL,
     PRIMARY KEY (uid)
     PRIMARY KEY (uid)
 );
 );
+