[TASK] Fluidification of installed services report 61/50061/5
authorMichael Oehlhof <typo3@oehlhof.de>
Wed, 28 Sep 2016 22:09:07 +0000 (00:09 +0200)
committerChristian Kuhn <lolli@schwarzbu.ch>
Sat, 29 Oct 2016 11:44:01 +0000 (13:44 +0200)
Resolves: #78088
Releases: master
Change-Id: I975361c525c22c5fbc2b6e7ced4f0a4e5ac8d514
Reviewed-on: https://review.typo3.org/50061
Tested-by: TYPO3com <no-reply@typo3.com>
Reviewed-by: Joerg Boesche <typo3@joergboesche.de>
Tested-by: Joerg Boesche <typo3@joergboesche.de>
Reviewed-by: Christian Kuhn <lolli@schwarzbu.ch>
Tested-by: Christian Kuhn <lolli@schwarzbu.ch>
typo3/sysext/sv/Classes/Report/ServicesListReport.php
typo3/sysext/sv/Resources/Private/Templates/ServicesListReport.html [new file with mode: 0644]
typo3/sysext/sv/Tests/Unit/Report/ServicesListReportTest.php [new file with mode: 0644]

index e331713..7f0e620 100644 (file)
@@ -18,6 +18,7 @@ use TYPO3\CMS\Core\Exception;
 use TYPO3\CMS\Core\Utility\CommandUtility;
 use TYPO3\CMS\Core\Utility\ExtensionManagementUtility;
 use TYPO3\CMS\Core\Utility\GeneralUtility;
+use TYPO3\CMS\Fluid\View\StandaloneView;
 use TYPO3\CMS\Reports\Controller\ReportController;
 use TYPO3\CMS\Reports\ReportInterface;
 
@@ -52,158 +53,108 @@ class ServicesListReport implements ReportInterface
      */
     public function getReport()
     {
-        $content = '';
-        $content .= $this->renderHelp();
-        $content .= $this->renderServicesList();
-        $content .= $this->renderExecutablesSearchPathList();
-        return $content;
-    }
+        // Rendering of the output via fluid
+        $view = GeneralUtility::makeInstance(StandaloneView::class);
+        $view->setTemplatePathAndFilename(GeneralUtility::getFileAbsFileName(
+            'EXT:sv/Resources/Private/Templates/ServicesListReport.html'
+        ));
 
-    /**
-     * Renders the help comments at the top of the module.
-     *
-     * @return string The help content for this module.
-     */
-    protected function renderHelp()
-    {
-        $help = '<p class="lead">' . $this->getLanguageService()->getLL('report_explanation') . '</p>';
-        $help .= '<p class="help">' . $this->getLanguageService()->getLL('externals_explanation') . '</p>';
-        return $help;
+        $view->assignMultiple([
+            'servicesList' => $this->getServicesList(),
+            'searchPaths' => $this->getExecutablesSearchPathList()
+        ]);
+
+        return $view->render();
     }
 
     /**
      * This method assembles a list of all installed services
      *
-     * @return string HTML to display
+     * @return array with data to display
      */
-    protected function renderServicesList()
+    protected function getServicesList()
     {
-        $servicesList = '';
+        $servicesList = [];
         $services = $this->getInstalledServices();
         foreach ($services as $serviceType => $installedServices) {
-            $servicesList .= $this->renderServiceTypeList($serviceType, $installedServices);
+            $servicesList[] = $this->getServiceTypeList($serviceType, $installedServices);
         }
         return $servicesList;
     }
 
     /**
-     * Renders the services list for a single service type.
+     * Get the services list for a single service type.
      *
      * @param string $serviceType The service type to render the installed services list for
      * @param array $services List of services for the given type
-     * @return string Service list as HTML for one service type
+     * @return array Service list as array for one service type
      */
-    protected function renderServiceTypeList($serviceType, $services)
+    protected function getServiceTypeList($serviceType, $services)
     {
         $lang = $this->getLanguageService();
-        $header = '<h3>' . sprintf($lang->getLL('service_type'), $serviceType) . '</h3>';
-        $serviceList = '
-                       <table class="table table-striped table-hover tx_sv_reportlist">
-                               <thead>
-                                       <tr>
-                                               <td style="width: 35%">' . $lang->getLL('service') . '</td>
-                                               <td>' . $lang->getLL('priority') . '</td>
-                                               <td>' . $lang->getLL('quality') . '</td>
-                                               <td style="width: 35%">' . $lang->getLL('subtypes') . '</td>
-                                               <td>' . $lang->getLL('os') . '</td>
-                                               <td>' . $lang->getLL('externals') . '</td>
-                                               <td>' . $lang->getLL('available') . '</td>
-                                       </tr>
-                               </thead>
-                       <tbody>';
+        $serviceList = [];
+        $serviceList['Type'] = sprintf($lang->getLL('service_type'), $serviceType);
 
+        $serviceList['Services'] = [];
         foreach ($services as $serviceKey => $serviceInformation) {
-            $serviceList .= $this->renderServiceRow($serviceKey, $serviceInformation);
+            $serviceList['Services'][] = $this->getServiceRow($serviceKey, $serviceInformation);
         }
 
-        $serviceList .= '
-                       </tbody>
-                       </table>
-               ';
-        return $header . $serviceList;
+        return $serviceList;
     }
 
     /**
-     * Renders a single service's row.
+     * Get data of a single service's row.
      *
      * @param string $serviceKey The service key to access the service.
      * @param array $serviceInformation registration information of the service.
-     * @return string HTML row for the service.
+     * @return array data for one row for the service.
      */
-    protected function renderServiceRow($serviceKey, $serviceInformation)
+    protected function getServiceRow($serviceKey, $serviceInformation)
     {
-        $serviceDescription = '
-                       <p class="service-header">
-                               <span class="service-title">' . $serviceInformation['title'] . '</span> (' . $serviceInformation['extKey'] . ': ' . $serviceKey . ')
-                       </p>';
-        if (!empty($serviceInformation['description'])) {
-            $serviceDescription .= '<p class="service-description">' . $serviceInformation['description'] . '</p>';
-        }
-        $serviceSubtypes = $serviceInformation['serviceSubTypes'] ? implode(', ', $serviceInformation['serviceSubTypes']) : '-';
-        $serviceOperatingSystem = $serviceInformation['os'] ?: $this->getLanguageService()->getLL('any');
-        $serviceRequiredExecutables = $serviceInformation['exec'] ?: '-';
-        $serviceAvailabilityClass = 'danger';
-        $serviceAvailable = $this->getLanguageService()->sL('LLL:EXT:lang/locallang_common.xlf:no');
+        $result = [
+            'Key' => $serviceKey,
+            'Information' => $serviceInformation,
+            'Subtypes' => $serviceInformation['serviceSubTypes'] ? implode(', ', $serviceInformation['serviceSubTypes']) : '-',
+            'OperatingSystem' => $serviceInformation['os'] ?: $this->getLanguageService()->getLL('any'),
+            'RequiredExecutables' => $serviceInformation['exec'] ?: '-',
+            'AvailabilityClass' => 'danger',
+            'Available' => $this->getLanguageService()->sL('LLL:EXT:lang/locallang_common.xlf:no'),
+        ];
+
         try {
             $serviceDetails = ExtensionManagementUtility::findServiceByKey($serviceKey);
             if ($serviceDetails['available']) {
-                $serviceAvailabilityClass = 'success';
-                $serviceAvailable = $this->getLanguageService()->sL('LLL:EXT:lang/locallang_common.xlf:yes');
+                $result['AvailabilityClass'] = 'success';
+                $result['Available'] = $this->getLanguageService()->sL('LLL:EXT:lang/locallang_common.xlf:yes');
             }
         } catch (Exception $e) {
         }
-        $serviceRow = '
-                       <tr class="service ' . $serviceAvailabilityClass . '">
-                               <td class="first-cell">' . $serviceDescription . '</td>
-                               <td class="cell">' . $serviceInformation['priority'] . '</td>
-                               <td class="cell">' . $serviceInformation['quality'] . '</td>
-                               <td class="cell">' . $serviceSubtypes . '</td>
-                               <td class="cell">' . $serviceOperatingSystem . '</td>
-                               <td class="cell">' . $serviceRequiredExecutables . '</td>
-                               <td class="last-cell">' . $serviceAvailable . '</td>
-                       </tr>';
-        return $serviceRow;
+
+        return $result;
     }
 
     /**
      * This method assembles a list of all defined executables search paths
      *
-     * @return string HTML to display
+     * @return array data to display
      */
-    protected function renderExecutablesSearchPathList()
+    protected function getExecutablesSearchPathList()
     {
-        $searchPaths = CommandUtility::getPaths(true);
-        $content = '<h3>' . $this->getLanguageService()->getLL('search_paths') . '</h3>';
-        if (empty($searchPaths)) {
-            $content .= '<p>' . $this->getLanguageService()->getLL('no_search_paths') . '</p>';
-        } else {
-            $content .= '
-                       <table class="table table-striped table-hover tx_sv_reportlist">
-                               <thead>
-                                       <tr>
-                                               <td>' . $this->getLanguageService()->getLL('path') . '</td>
-                                               <td>' . $this->getLanguageService()->getLL('valid') . '</td>
-                                       </tr>
-                               </thead>
-                               <tbody>';
-            foreach ($searchPaths as $path => $isValid) {
-                $pathAccessibleClass = 'danger';
-                $pathAccessible = $this->getLanguageService()->sL('LLL:EXT:lang/locallang_common.xlf:no');
-                if ($isValid) {
-                    $pathAccessibleClass = 'success';
-                    $pathAccessible = $this->getLanguageService()->sL('LLL:EXT:lang/locallang_common.xlf:yes');
-                }
-                $content .= '
-                                       <tr class="' . $pathAccessibleClass . '">
-                                               <td class="first-cell">' . GeneralUtility::fixWindowsFilePath($path) . '</td>
-                                               <td class="last-cell">' . $pathAccessible . '</td>
-                                       </tr>';
-            }
-            $content .= '
-                               </tbody>
-                       </table>';
+        $addInvalidSearchPaths = true;
+        $searchPaths = CommandUtility::getPaths($addInvalidSearchPaths);
+        $result = [];
+
+        foreach ($searchPaths as $path => $isValid) {
+            $searchPathData = $this->getServicePathStatus($isValid);
+            $result[] = [
+                'class' => $searchPathData['statusCSSClass'],
+                'accessible' => 'LLL:EXT:lang/locallang_common.xlf:' . $searchPathData['accessible'],
+                'path' => GeneralUtility::fixWindowsFilePath($path),
+            ];
         }
-        return $content;
+
+        return $result;
     }
 
     /**
@@ -245,8 +196,8 @@ class ServicesListReport implements ReportInterface
     {
         $result = 0;
         // If priorities are the same, test quality
-        if ($a['priority'] == $b['priority']) {
-            if ($a['quality'] != $b['quality']) {
+        if ($a['priority'] === $b['priority']) {
+            if ($a['quality'] !== $b['quality']) {
                 // Service with highest quality should come first,
                 // thus it must be marked as smaller
                 $result = $a['quality'] > $b['quality'] ? -1 : 1;
@@ -268,4 +219,24 @@ class ServicesListReport implements ReportInterface
     {
         return $GLOBALS['LANG'];
     }
+
+    /**
+     * Method to check if the service in path is available
+     * @param $isValid
+     * @return array
+     */
+    private function getServicePathStatus($isValid): array
+    {
+        $statusCSSClass = 'danger';
+        $accessible = 'no';
+
+        if ($isValid) {
+            $statusCSSClass = 'success';
+            $accessible = 'yes';
+        }
+        return [
+            'statusCSSClass' => $statusCSSClass,
+            'accessible' => $accessible
+        ];
+    }
 }
diff --git a/typo3/sysext/sv/Resources/Private/Templates/ServicesListReport.html b/typo3/sysext/sv/Resources/Private/Templates/ServicesListReport.html
new file mode 100644 (file)
index 0000000..22774fd
--- /dev/null
@@ -0,0 +1,77 @@
+<p class="lead">
+    <f:translate key="report_explanation" extensionName="sv" />
+</p>
+<p class="help">
+    <f:translate key="externals_explanation" extensionName="sv" />
+</p>
+
+<f:for each="{servicesList}" as="serviceList">
+    <f:render section="ServiceTypeList" arguments="{serviceList: serviceList}" />
+</f:for>
+
+<h3><f:translate key="search_paths" extensionName="sv" /></h3>
+<f:if condition="{searchPaths}">
+    <f:then>
+        <table class="table table-striped table-hover tx_sv_reportlist">
+            <thead>
+                <tr>
+                    <td><f:translate key="path" extensionName="sv" /></td>
+                    <td><f:translate key="valid" extensionName="sv" /></td>
+                </tr>
+            </thead>
+            <tbody>
+                <f:for each="{searchPaths}" as="searchPath">
+                    <tr class="{searchPath.class}">
+                        <td class="first-cell">{searchPath.path}</td>
+                        <td class="last-cell"><f:translate key="{searchPath.accessible}" /></td>
+                    </tr>
+                </f:for>
+            </tbody>
+        </table>
+    </f:then>
+    <f:else>
+        <p><f:translate key="no_search_paths" extensionName="sv" /></p>
+    </f:else>
+</f:if>
+
+
+<f:section name="ServiceTypeList">
+    <h3>{serviceList.Type}</h3>
+    <table class="table table-striped table-hover tx_sv_reportlist">
+        <thead>
+            <tr>
+                <td style="width: 35%"><f:translate key="service" extensionName="sv" /></td>
+                <td><f:translate key="priority" extensionName="sv" /></td>
+                <td><f:translate key="quality" extensionName="sv" /></td>
+                <td style="width: 35%"><f:translate key="subtypes" extensionName="sv" /></td>
+                <td><f:translate key="os" extensionName="sv" /></td>
+                <td><f:translate key="externals" extensionName="sv" /></td>
+                <td><f:translate key="available" extensionName="sv" /></td>
+            </tr>
+        </thead>
+        <tbody>
+            <f:for each="{serviceList.Services}" as="service">
+                <f:render section="ServiceRow" arguments="{service: service}" />
+            </f:for>
+        </tbody>
+    </table>
+</f:section>
+
+<f:section name="ServiceRow">
+    <tr class="service {service.AvailabilityClass}">
+        <td class="first-cell">{service.Description}
+            <p class="service-header">
+                <span class="service-title">{service.Information.title}</span> ({service.Information.extKey}: {service.Key})
+            </p>
+            <f:if condition="{service.Information.description}">
+                <p class="service-description">{service.Information.description}</p>
+            </f:if>
+        </td>
+        <td class="cell">{service.Information.priority}</td>
+        <td class="cell">{service.Information.quality}</td>
+        <td class="cell">{service.Subtypes}</td>
+        <td class="cell">{service.OperatingSystem}</td>
+        <td class="cell">{service.RequiredExecutables}</td>
+        <td class="last-cell">{service.Available}</td>
+    </tr>
+</f:section>
\ No newline at end of file
diff --git a/typo3/sysext/sv/Tests/Unit/Report/ServicesListReportTest.php b/typo3/sysext/sv/Tests/Unit/Report/ServicesListReportTest.php
new file mode 100644 (file)
index 0000000..2eaa9f6
--- /dev/null
@@ -0,0 +1,105 @@
+<?php
+declare(strict_types=1);
+namespace TYPO3\sv\Tests\Unit\Report;
+
+/*
+ * This file is part of the TYPO3 CMS project.
+ *
+ * It is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License, either version 2
+ * of the License, or any later version.
+ *
+ * For the full copyright and license information, please read the
+ * LICENSE.txt file that was distributed with this source code.
+ *
+ * The TYPO3 project - inspiring people to share!
+ */
+
+use Prophecy\Argument;
+use Prophecy\Prophecy\ObjectProphecy;
+use TYPO3\CMS\Core\Tests\UnitTestCase;
+use TYPO3\CMS\Core\Utility\GeneralUtility;
+use TYPO3\CMS\Fluid\View\StandaloneView;
+use TYPO3\CMS\Lang\LanguageService;
+use TYPO3\CMS\Reports\Controller\ReportController;
+use TYPO3\CMS\Sv\Report\ServicesListReport;
+
+/**
+ * Test case for class ServicesListReport
+ */
+class ServicesListReportTest extends UnitTestCase
+{
+    /**
+     * @var ServicesListReport
+     */
+    protected $subject;
+
+    /**
+     * SetUp
+     */
+    public function setUp()
+    {
+        $GLOBALS['LANG'] = $this->languageServiceProphecy()->reveal();
+        $this->subject = new ServicesListReport(
+            $this->reportControllerProphecy()->reveal()
+        );
+    }
+
+    /**
+     * @test
+     */
+    public function getReportCollectsRelevantDataToAssignThemToTemplateForResponse()
+    {
+        $standaloneViewProphecy = $this->standaloneViewProphecy();
+
+        $this->subject->getReport();
+
+        $standaloneViewProphecy
+            ->assignMultiple(Argument::withEntry('servicesList', []))
+            ->shouldHaveBeenCalled();
+        $standaloneViewProphecy
+            ->assignMultiple(Argument::withKey('searchPaths'))
+            ->shouldHaveBeenCalled();
+    }
+
+    /**
+     * @return ObjectProphecy
+     * @internal param $templatePath
+     */
+    private function standaloneViewProphecy(): ObjectProphecy
+    {
+        $templatePath = GeneralUtility::getFileAbsFileName(
+            'EXT:sv/Resources/Private/Templates/ServicesListReport.html'
+        );
+        $standaloneViewProphecy = $this->prophesize(StandaloneView::class);
+        $standaloneViewProphecy->setTemplatePathAndFilename($templatePath)->shouldBeCalled();
+        $standaloneViewProphecy->assignMultiple(Argument::any())->willReturn($standaloneViewProphecy->reveal());
+        $standaloneViewProphecy->render()->willReturn('<p>Template output</p>');
+        GeneralUtility::addInstance(StandaloneView::class, $standaloneViewProphecy->reveal());
+
+        return $standaloneViewProphecy;
+    }
+
+    /**
+     * @return ObjectProphecy
+     */
+    private function languageServiceProphecy(): ObjectProphecy
+    {
+        $languageServiceProphecy = $this->prophesize(LanguageService::class);
+        $languageServiceProphecy
+            ->includeLLFile('EXT:sv/Resources/Private/Language/locallang.xlf')
+            ->willReturn(null)
+            ->shouldBeCalled();
+        $languageServiceProphecy->getLL(Argument::any())->willReturn('translation string');
+        return $languageServiceProphecy;
+    }
+
+    /**
+     * @return ObjectProphecy
+     */
+    private function reportControllerProphecy(): ObjectProphecy
+    {
+        $reportControllerProphecy = $this->prophesize(ReportController::class);
+        return $reportControllerProphecy;
+    }
+}