Pārlūkot izejas kodu

various improvements

Olivier Massot 2 gadi atpakaļ
vecāks
revīzija
66e719d561

+ 27 - 6
ot_admin/Classes/Command/ScanCommand.php

@@ -8,6 +8,8 @@ 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 Twig\Environment;
+use Twig\Loader\FilesystemLoader;
 use TYPO3\CMS\Core\Utility\GeneralUtility;
 use TYPO3\CMS\Extbase\Object\ObjectManager;
 
@@ -28,10 +30,15 @@ class ScanCommand extends Command
     protected function configure()
     {
         $this
-            ->setName("ot:scan")
+            ->setName("ot:site:scan")
             ->setDescription("Scan the typo3 DB")
             ->setHelp("This CLI command performs a full scan on the Typo3 db.")
             ->addOption(
+                'deep',
+                'd',
+            InputOption::VALUE_NONE,
+            'Performs a deeper scan, with more control operations'
+            )->addOption(
                 'report',
                 'r',
                 InputOption::VALUE_OPTIONAL,
@@ -49,11 +56,13 @@ class ScanCommand extends Command
      */
     protected function execute(InputInterface $input, OutputInterface $output)
     {
+        $deep = $input->getOption('deep');
+
         $io = new SymfonyStyle($input, $output);
 
         // instanciate twig loader
-        $loader = new \Twig\Loader\FilesystemLoader(dirname(__FILE__) . '/../../templates');
-        $twig = new \Twig\Environment($loader);
+        $loader = new FilesystemLoader(__DIR__ . '/../../templates');
+        $twig = new Environment($loader);
 
         // evaluate the report path
         $report_path = $input->getOption('report');
@@ -61,21 +70,33 @@ class ScanCommand extends Command
             $report_path = getcwd() . '/scan_report.html';
         } else {
             $info = pathinfo($report_path);
-            if ($info['extension'] != 'html') {
+            if ($info['extension'] !== 'html') {
                 $report_path .= '.html';
             }
         }
 
         // perform the scan
         $scanController = GeneralUtility::makeInstance(ObjectManager::class)->get(ScanController::class);
-        $scan = $scanController->scanAllAction(true);
+
+        $progressBar = $io->createProgressBar();
+        $progressBar->display();
+
+        $scan = $scanController->scanAllAction(
+            $deep,
+            function ($i, $total) use ($progressBar) {
+                $progressBar->setProgress($i);
+                if ($total !== $progressBar->getMaxSteps()) {
+                    $progressBar->setMaxSteps($total);
+                }
+            }
+        );
 
         // render the twig template
         $template = $twig->load('scan_report.twig');
 
         $html_report = $template->render(['scan' => $scan]);
 
-        $f = fopen($report_path, 'w+');
+        $f = fopen($report_path, 'wb+');
         try {
             fwrite($f, $html_report);
             $io->success(sprintf("Report file was created at: " . $report_path));

+ 11 - 1
ot_admin/Classes/Controller/ScanController.php

@@ -19,9 +19,10 @@ class ScanController extends ActionController
      *
      * @param bool $fullScan If true, a 'warnings' entry will be added to the result of each site status,
      *                        and a full scan of the website pages will be performed.
+     * @param callable|null $progressCallback Expects a function that takes 2 parameters : the current step, and the max
      * @return ScanReport
      */
-    public function scanAllAction(bool $fullScan = false): ScanReport
+    public function scanAllAction(bool $fullScan = false, ?callable $progressCallback = null): ScanReport
     {
         $organizationRepository = GeneralUtility::makeInstance(ObjectManager::class)->get(OrganizationRepository::class);
         $siteController = GeneralUtility::makeInstance(ObjectManager::class)->get(SiteController::class);
@@ -29,10 +30,19 @@ class ScanController extends ActionController
         $report = new ScanReport();
 
         $organizationsCollection = $organizationRepository->getAll();
+        $i = 0;
+        $total = count($organizationsCollection->getMembers());
+
         foreach ($organizationsCollection->getMembers() as $organization) {
+            $i++;
+
             $status = $siteController->getSiteStatusAction($organization->getId(), $fullScan);
 
             $report->setResultFor($organization->getId(), $status);
+
+            if ($progressCallback !== null) {
+                $progressCallback($i, $total);
+            }
         }
 
         return $report;

+ 3 - 0
ot_admin/Classes/Controller/SiteController.php

@@ -1310,6 +1310,7 @@ class SiteController extends ActionController
      *   - STATUS_EXISTING_DELETED
      *   - STATUS_EXISTING_HIDDEN
      *   - STATUS_EXISTING_WITH_WARNINGS
+     *   - STATUS_EXISTING_WITH_CRITICAL_ERRORS
      *
      * @param int $organizationId the organization's id whom site cache should be cleared
      * @param bool $fullScan If true, a 'warnings' entry will be added to the result, and a full scan of
@@ -1327,6 +1328,8 @@ class SiteController extends ActionController
             $siteInfos = $this->getSiteInfosAction($organizationId);
         } catch (NoSuchWebsiteException $e) {
             return new SiteStatus($organizationId, SiteStatus::STATUS_NO_SUCH_WEBSITE);
+        } catch(\Throwable $e) {
+            return new SiteStatus($organizationId, SiteStatus::STATUS_EXISTING_WITH_CRITICAL_ERRORS);
         }
 
         if ($siteInfos->isDeleted()) {

+ 2 - 0
ot_admin/Classes/Domain/Entity/SiteStatus.php

@@ -14,6 +14,7 @@ class SiteStatus
     const STATUS_EXISTING_DELETED = 2;
     const STATUS_EXISTING_HIDDEN = 3;
     const STATUS_EXISTING_WITH_WARNINGS = 4;
+    const STATUS_EXISTING_WITH_CRITICAL_ERRORS = 1;
 
     const STATUSES = [
         self::STATUS_UNKNOWN => 'Unknown',
@@ -22,6 +23,7 @@ class SiteStatus
         self::STATUS_EXISTING_DELETED => 'Existing, deleted',
         self::STATUS_EXISTING_HIDDEN => 'Existing, hidden',
         self::STATUS_EXISTING_WITH_WARNINGS => 'Existing with warnings',
+        self::STATUS_EXISTING_WITH_CRITICAL_ERRORS => 'Existing with critical error(s)',
     ];
 
     /**

+ 1 - 1
ot_admin/Configuration/Commands.php

@@ -40,7 +40,7 @@ return [
     'ot:redirection:remove' => [
         'class' => Opentalent\OtAdmin\Command\RemoveRedirectionCommand::class
     ],
-    'ot:scan' => [
+    'ot:site:scan' => [
         'class' => Opentalent\OtAdmin\Command\ScanCommand::class
     ],
     'ot:regen-config-files' => [

+ 2 - 2
ot_admin/Configuration/Services.yaml

@@ -69,6 +69,6 @@ services:
 
   Opentalent\OtAdmin\Command\ScanCommand:
     tags:
-      - name: 'ot:scan'
-        command: 'ot:scan'
+      - name: 'ot:site:scan'
+        command: 'ot:site:scan'
         schedulable: true

+ 8 - 7
ot_core/Classes/Domain/Repository/BaseApiRepository.php

@@ -13,9 +13,9 @@ use TYPO3\CMS\Core\Utility\GeneralUtility;
  */
 abstract class BaseApiRepository
 {
-    const URI_TRAILING_PART = '';
-    const HYDRA_TYPE = '';
-    const DEFAULT_ITEMS_PER_PAGE = 8;
+    protected const URI_TRAILING_PART = '';
+    protected const HYDRA_TYPE = '';
+    protected const DEFAULT_ITEMS_PER_PAGE = 8;
 
     protected $apiService;
 
@@ -30,7 +30,8 @@ abstract class BaseApiRepository
      * [FOR TESTS ONLY]
      * @param OpentalentApiService $apiService
      */
-    protected function injectOpentalentApiService(OpentalentApiService $apiService) {
+    protected function injectOpentalentApiService(OpentalentApiService $apiService): void
+    {
         $this->apiService = $apiService;
     }
 
@@ -40,7 +41,7 @@ abstract class BaseApiRepository
      * @param array $record
      * @return object
      */
-    abstract protected function memberToObject(array $record);
+    abstract protected function memberToObject(array $record): ?object;
 
     /**
      * Send a request to the API and
@@ -51,7 +52,7 @@ abstract class BaseApiRepository
      * @return object
      * @throws ApiRequestException
      */
-    protected function getApiFirstRecord($params = [], ?string $forceUri = null)
+    protected function getApiFirstRecord(array $params = [], ?string $forceUri = null): object
     {
         $params['page'] = '1';
         $params['totalItems'] = '1';
@@ -89,7 +90,7 @@ abstract class BaseApiRepository
         if (is_array($body['hydra:member'])) {
             foreach ($body['hydra:member'] as $record) {
                 $instance = $this->memberToObject($record);
-                if ($instance != null) {
+                if ($instance !== null) {
                     $members[] = $instance;
                 }
             }

+ 1 - 1
ot_core/Classes/Domain/Repository/DonorRepository.php

@@ -51,7 +51,7 @@ class DonorRepository extends BaseApiRepository
      * @param $record
      * @return Donor|null
      */
-    protected function memberToObject(array $record) {
+    protected function memberToObject(array $record): ?Donor {
         if ($record['@type'] != $this::HYDRA_TYPE) {
             return null;
         }

+ 1 - 1
ot_core/Classes/Domain/Repository/EventRepository.php

@@ -152,7 +152,7 @@ class EventRepository extends BaseApiRepository
      * @return Event|null
      * @throws Exception
      */
-    protected function memberToObject(array $record) {
+    protected function memberToObject(array $record): ?Event {
         if ($record['@type'] != $this::HYDRA_TYPE) {
             return null;
         }

+ 1 - 1
ot_core/Classes/Domain/Repository/FederationStructureRepository.php

@@ -44,7 +44,7 @@ class FederationStructureRepository extends BaseApiRepository
      * @param array $record
      * @return FederationStructure|null
      */
-    protected function memberToObject(array $record) {
+    protected function memberToObject(array $record): ?FederationStructure {
         if ($record['@type'] != $this::HYDRA_TYPE) {
             return null;
         }

+ 1 - 1
ot_core/Classes/Domain/Repository/MemberRepository.php

@@ -35,7 +35,7 @@ class MemberRepository extends BaseApiRepository
      * @return Member|null
      * @throws \Exception
      */
-    protected function memberToObject(array $record) {
+    protected function memberToObject(array $record): ?Member {
         if ($record['@type'] != $this::HYDRA_TYPE) {
             return null;
         }

+ 11 - 11
ot_core/Classes/Domain/Repository/OrganizationRepository.php

@@ -2,14 +2,13 @@
 
 namespace Opentalent\OtCore\Domain\Repository;
 
-use GuzzleHttp\Exception\GuzzleException;
 use Opentalent\OtCore\Domain\Model\Organization;
 use Opentalent\OtCore\Exception\ApiRequestException;
 
 class OrganizationRepository extends BaseApiRepository
 {
-    const URI_TRAILING_PART = '/api/public/organizations';
-    const HYDRA_TYPE = 'PortailOrganization';
+    protected const URI_TRAILING_PART = '/api/public/organizations';
+    protected const HYDRA_TYPE = 'PortailOrganization';
 
     /**
      * Get the organization by Id
@@ -18,12 +17,12 @@ class OrganizationRepository extends BaseApiRepository
      * @return object
      * @throws ApiRequestException
      */
-    public function findById($id): object
+    public function findById(int $id): object
     {
         $params = [];
         $params['filter[where][id]'] = $id;
         $organization = $this->getApiFirstRecord($params);
-        if ($organization == null) {
+        if ($organization === null) {
             throw new ApiRequestException('Organization with id ' . $id . ' does not exist');
         }
         return $organization;
@@ -37,12 +36,12 @@ class OrganizationRepository extends BaseApiRepository
      * @throws \Exception
      * @throws ApiRequestException
      */
-    public function findByName($name): object
+    public function findByName(string $name): object
     {
         $params = [];
         $params['filter[where][name]'] = $name;
         $organization = $this->getApiFirstRecord($params);
-        if($organization == null) {
+        if($organization === null) {
             throw new ApiRequestException('Organization with name "' . $name . '" does not exist');
         }
         return $organization;
@@ -57,7 +56,7 @@ class OrganizationRepository extends BaseApiRepository
      * @return ApiPagedCollection
      * @throws ApiRequestException
      */
-    public function findChildrenById(int $id, $searchParams = [], $page = 1): ApiPagedCollection
+    public function findChildrenById(int $id, array $searchParams = [], int $page = 1): ApiPagedCollection
     {
         $params = [];
         $params['parentId'] = $id;
@@ -86,11 +85,12 @@ class OrganizationRepository extends BaseApiRepository
     /**
      * Returns an Organization object from an Api record
      *
-     * @param $record
+     * @param array $record
      * @return Organization|null
      */
-    protected function memberToObject(array $record) {
-        if ($record['@type'] != $this::HYDRA_TYPE) {
+    protected function memberToObject(array $record): ?Organization
+    {
+        if ($record['@type'] !== $this::HYDRA_TYPE) {
             return null;
         }
 

+ 1 - 1
ot_core/Tests/Unit/Domain/Repository/BaseApiRepositoryTest.php

@@ -13,7 +13,7 @@ use Opentalent\OtCore\Exception\ApiRequestException;
  */
 class ConcreteBaseApiRepository extends BaseApiRepository {
     protected function memberToObject(array $member) { return $member; }
-    public function getApiFirstRecord($params = [], $forceUri = null) { return parent::getApiFirstRecord($params, $forceUri); }
+    public function getApiFirstRecord(array $params = [], $forceUri = null) { return parent::getApiFirstRecord($params, $forceUri); }
     public function getApiRecords($params = [], $forceUri = null): ApiPagedCollection { return parent::getApiRecords($params, $forceUri); }
 }
 

+ 0 - 3
ot_templating/Resources/Private/Partials/Modern/Header.html

@@ -4,9 +4,6 @@
 
 <f:comment><!--<f:render partial="Modern/Preloader" />--></f:comment>
 
-<f:comment><!-- Render the matomo integration code --></f:comment>
-<f:comment><!--<f:render partial="Classic/Matomo" />--></f:comment>
-
 <header id="header" class="header default fullWidth">
 
     <f:comment><!-- Render the no-script warning box defined in partial/NoScriptWarning.html--></f:comment>