[!!!][TASK] Move service report from EXT:sv to EXT:reports 63/53163/10
authorGeorg Ringer <georg.ringer@gmail.com>
Wed, 7 Jun 2017 15:27:31 +0000 (17:27 +0200)
committerBenni Mack <benni@typo3.org>
Sat, 17 Jun 2017 20:55:58 +0000 (22:55 +0200)
Move the report as a first step to get rid of EXT:sv.

Resolves: #81536
Releases: master
Change-Id: I46e38b5c4bf8d5466e1bcc1db510b1cd660a7b38
Reviewed-on: https://review.typo3.org/53163
Reviewed-by: Anja Leichsenring <aleichsenring@ab-softlab.de>
Tested-by: Anja Leichsenring <aleichsenring@ab-softlab.de>
Tested-by: TYPO3com <no-reply@typo3.com>
Reviewed-by: Benni Mack <benni@typo3.org>
Tested-by: Benni Mack <benni@typo3.org>
15 files changed:
typo3/sysext/core/Documentation/Changelog/master/Breaking-81536-MoveOfServicesListReportFromSvToReports.rst [new file with mode: 0644]
typo3/sysext/reports/Classes/Report/ServicesListReport.php [new file with mode: 0644]
typo3/sysext/reports/Migrations/Code/ClassAliasMap.php [new file with mode: 0644]
typo3/sysext/reports/Migrations/Code/LegacyClassesForIde.php [new file with mode: 0644]
typo3/sysext/reports/Resources/Private/Language/locallang_servicereport.xlf [new file with mode: 0644]
typo3/sysext/reports/Resources/Private/Templates/ServicesListReport.html [new file with mode: 0644]
typo3/sysext/reports/Resources/Public/Images/service-reports.png [new file with mode: 0644]
typo3/sysext/reports/Tests/Unit/Report/ServicesListReportTest.php [new file with mode: 0644]
typo3/sysext/reports/ext_tables.php
typo3/sysext/sv/Classes/Report/ServicesListReport.php [deleted file]
typo3/sysext/sv/Resources/Private/Language/locallang.xlf [deleted file]
typo3/sysext/sv/Resources/Private/Templates/ServicesListReport.html [deleted file]
typo3/sysext/sv/Resources/Public/Images/service-reports.png [deleted file]
typo3/sysext/sv/Tests/Unit/Report/ServicesListReportTest.php [deleted file]
typo3/sysext/sv/ext_tables.php [deleted file]

diff --git a/typo3/sysext/core/Documentation/Changelog/master/Breaking-81536-MoveOfServicesListReportFromSvToReports.rst b/typo3/sysext/core/Documentation/Changelog/master/Breaking-81536-MoveOfServicesListReportFromSvToReports.rst
new file mode 100644 (file)
index 0000000..3310978
--- /dev/null
@@ -0,0 +1,41 @@
+.. include:: ../../Includes.txt
+
+==========================================================
+Breaking: #81536 - MoveOfServicesListReportFromSvToReports
+==========================================================
+
+See :issue:`81536`
+
+Description
+===========
+
+The service list report has been moved from EXT:sv to EXT:reports.
+
+
+Impact
+======
+
+Because of the new location the namespace of the class :php:`ServicesListReport` has been changed from :php:`TYPO3\CMS\Sv\Report` to :php:`TYPO3\CMS\Reports\Report`. Additionally the relevant language file has been moved from :file:`EXT:/sv/Resources/Private/Language/locallang.xlf` to :file:`EXT:/reports/Resources/Private/Language/serviceReport.xlf`.
+
+
+Affected Installations
+======================
+
+All installations or 3rd party extensions which directly access the used files of the report:
+
+- :php:`TYPO3\CMS\Sv\Report\ServicesListReport`
+- :file:`EXT:sv/Resources/Private/Language/locallang.xlf`
+- :file:`EXT:sv/Resources/Private/Templates/ServicesListReport.html`
+- :file:`EXT:sv/Resources/Public/Images/service-reports.png`
+
+
+Migration
+=========
+
+Use the new namespace :php:`TYPO3\CMS\Reports\Report\ServicesListReport` and the location of the files:
+
+- :file:`EXT:reports/Resources/Private/Language/serviceReport.xlf`
+- :file:`EXT:reports/Resources/Private/Templates/ServicesListReport.html`
+- :file:`EXT:reports/Resources/Public/Images/service-reports.png`
+
+.. index:: Backend
diff --git a/typo3/sysext/reports/Classes/Report/ServicesListReport.php b/typo3/sysext/reports/Classes/Report/ServicesListReport.php
new file mode 100644 (file)
index 0000000..be7cf9f
--- /dev/null
@@ -0,0 +1,238 @@
+<?php
+namespace TYPO3\CMS\Reports\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 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;
+
+/**
+ * This class provides a report displaying a list of all installed services
+ */
+class ServicesListReport implements ReportInterface
+{
+    /**
+     * @var ReportController
+     */
+    protected $reportsModule;
+
+    /**
+     * Constructor
+     *
+     * @param ReportController $reportsModule Back-reference to the calling reports module
+     */
+    public function __construct(ReportController $reportsModule)
+    {
+        $this->reportsModule = $reportsModule;
+        $this->getLanguageService()->includeLLFile('EXT:reports/Resources/Private/Language/locallang_servicereport.xlf');
+    }
+
+    /**
+     * This method renders the report
+     *
+     * @return string The status report as HTML
+     */
+    public function getReport()
+    {
+        // Rendering of the output via fluid
+        $view = GeneralUtility::makeInstance(StandaloneView::class);
+        $view->setTemplatePathAndFilename(GeneralUtility::getFileAbsFileName(
+            'EXT:reports/Resources/Private/Templates/ServicesListReport.html'
+        ));
+
+        $view->assignMultiple([
+            'servicesList' => $this->getServicesList(),
+            'searchPaths' => $this->getExecutablesSearchPathList()
+        ]);
+
+        return $view->render();
+    }
+
+    /**
+     * This method assembles a list of all installed services
+     *
+     * @return array with data to display
+     */
+    protected function getServicesList()
+    {
+        $servicesList = [];
+        $services = $this->getInstalledServices();
+        foreach ($services as $serviceType => $installedServices) {
+            $servicesList[] = $this->getServiceTypeList($serviceType, $installedServices);
+        }
+        return $servicesList;
+    }
+
+    /**
+     * 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 array Service list as array for one service type
+     */
+    protected function getServiceTypeList($serviceType, $services)
+    {
+        $lang = $this->getLanguageService();
+        $serviceList = [];
+        $serviceList['Type'] = sprintf($lang->getLL('service_type'), $serviceType);
+
+        $serviceList['Services'] = [];
+        foreach ($services as $serviceKey => $serviceInformation) {
+            $serviceList['Services'][] = $this->getServiceRow($serviceKey, $serviceInformation);
+        }
+
+        return $serviceList;
+    }
+
+    /**
+     * 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 array data for one row for the service.
+     */
+    protected function getServiceRow($serviceKey, $serviceInformation)
+    {
+        $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/Resources/Private/Language/locallang_common.xlf:no'),
+        ];
+
+        try {
+            $serviceDetails = ExtensionManagementUtility::findServiceByKey($serviceKey);
+            if ($serviceDetails['available']) {
+                $result['AvailabilityClass'] = 'success';
+                $result['Available'] = $this->getLanguageService()->sL('LLL:EXT:lang/Resources/Private/Language/locallang_common.xlf:yes');
+            }
+        } catch (Exception $e) {
+        }
+
+        return $result;
+    }
+
+    /**
+     * This method assembles a list of all defined executables search paths
+     *
+     * @return array data to display
+     */
+    protected function getExecutablesSearchPathList()
+    {
+        $searchPaths = CommandUtility::getPaths(true);
+        $result = [];
+
+        foreach ($searchPaths as $path => $isValid) {
+            $searchPathData = $this->getServicePathStatus($isValid);
+            $result[] = [
+                'class' => $searchPathData['statusCSSClass'],
+                'accessible' => 'LLL:EXT:lang/Resources/Private/Language/locallang_common.xlf:' . $searchPathData['accessible'],
+                'path' => GeneralUtility::fixWindowsFilePath($path),
+            ];
+        }
+
+        return $result;
+    }
+
+    /**
+     * This method filters the $T3_SERVICES global array to return a relevant,
+     * ordered list of installed services.
+     *
+     * Every installed service appears twice in $T3_SERVICES: once as a service key
+     * for a given service type, and once a service type all by itself
+     * The list of services to display must avoid these duplicates
+     *
+     * Furthermore, inside each service type, installed services must be
+     * ordered by priority and quality
+     *
+     * @return array List of filtered and ordered services
+     */
+    protected function getInstalledServices()
+    {
+        $filteredServices = [];
+        foreach ($GLOBALS['T3_SERVICES'] as $serviceType => $serviceList) {
+            // If the (first) key of the service list is not the same as the service type,
+            // it's a "true" service type. Keep it and sort it.
+            if (key($serviceList) !== $serviceType) {
+                uasort($serviceList, [$this, 'sortServices']);
+                $filteredServices[$serviceType] = $serviceList;
+            }
+        }
+        return $filteredServices;
+    }
+
+    /**
+     * Utility method used to sort services according to their priority and
+     * quality.
+     *
+     * @param array $a First service to compare
+     * @param array $b Second service to compare
+     * @return int 1, 0 or -1 if $a is smaller, equal or greater than $b, respectively
+     */
+    protected function sortServices(array $a, array $b)
+    {
+        $result = 0;
+        // If priorities are the same, test 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;
+            }
+        } else {
+            // Service with highest priority should come first,
+            // thus it must be marked as smaller
+            $result = $a['priority'] > $b['priority'] ? -1 : 1;
+        }
+        return $result;
+    }
+
+    /**
+     * Method to check if the service in path is available
+     * @param bool|string $isValid
+     * @return array
+     */
+    private function getServicePathStatus($isValid): array
+    {
+        $statusCSSClass = 'danger';
+        $accessible = 'no';
+
+        if ($isValid) {
+            $statusCSSClass = 'success';
+            $accessible = 'yes';
+        }
+        return [
+            'statusCSSClass' => $statusCSSClass,
+            'accessible' => $accessible
+        ];
+    }
+
+    /**
+     * Returns LanguageService
+     *
+     * @return \TYPO3\CMS\Core\Localization\LanguageService
+     */
+    protected function getLanguageService()
+    {
+        return $GLOBALS['LANG'];
+    }
+}
diff --git a/typo3/sysext/reports/Migrations/Code/ClassAliasMap.php b/typo3/sysext/reports/Migrations/Code/ClassAliasMap.php
new file mode 100644 (file)
index 0000000..8f276a0
--- /dev/null
@@ -0,0 +1,4 @@
+<?php
+return [
+    'TYPO3\\CMS\\Sv\\Report\\ServicesListReport' => \TYPO3\CMS\Reports\Report\ServicesListReport::class
+];
diff --git a/typo3/sysext/reports/Migrations/Code/LegacyClassesForIde.php b/typo3/sysext/reports/Migrations/Code/LegacyClassesForIde.php
new file mode 100644 (file)
index 0000000..48c3a6e
--- /dev/null
@@ -0,0 +1,10 @@
+<?php
+namespace {
+    die('Access denied');
+}
+
+namespace TYPO3\CMS\Sv\Report {
+    class ServicesListReport extends \TYPO3\CMS\Reports\Report\ServicesListReport
+    {
+    }
+}
diff --git a/typo3/sysext/reports/Resources/Private/Language/locallang_servicereport.xlf b/typo3/sysext/reports/Resources/Private/Language/locallang_servicereport.xlf
new file mode 100644 (file)
index 0000000..0dd4b56
--- /dev/null
@@ -0,0 +1,59 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<xliff version="1.0" xmlns:t3="http://typo3.org/schemas/xliff">
+       <file t3:id="1415814992" source-language="en" datatype="plaintext" original="messages" date="2011-10-17T20:22:37Z" product-name="sv">
+               <header/>
+               <body>
+                       <trans-unit id="report_title">
+                               <source>Installed Services</source>
+                       </trans-unit>
+                       <trans-unit id="report_description">
+                               <source>List of all installed services with information and status for each of them.</source>
+                       </trans-unit>
+                       <trans-unit id="report_explanation">
+                               <source>This report displays a list of installed services, with detailed information about each of them. The services are ordered by type, priority and quality. Unavailable services are highlighted with an error status.</source>
+                       </trans-unit>
+                       <trans-unit id="externals_explanation">
+                               <source>The "Externals" column shows which external programs a given service relies on. If such program is missing or not executable, the service will be unavailable. Search paths for executables are listed at the bottom of this report.</source>
+                       </trans-unit>
+                       <trans-unit id="service_type">
+                               <source>Service type: %s</source>
+                       </trans-unit>
+                       <trans-unit id="service">
+                               <source>Service</source>
+                       </trans-unit>
+                       <trans-unit id="priority">
+                               <source>Priority</source>
+                       </trans-unit>
+                       <trans-unit id="quality">
+                               <source>Quality</source>
+                       </trans-unit>
+                       <trans-unit id="subtypes">
+                               <source>Subtypes</source>
+                       </trans-unit>
+                       <trans-unit id="os">
+                               <source>OS</source>
+                       </trans-unit>
+                       <trans-unit id="externals">
+                               <source>Externals</source>
+                       </trans-unit>
+                       <trans-unit id="available">
+                               <source>Available</source>
+                       </trans-unit>
+                       <trans-unit id="any">
+                               <source>Any</source>
+                       </trans-unit>
+                       <trans-unit id="search_paths">
+                               <source>Configured search paths for external programs</source>
+                       </trans-unit>
+                       <trans-unit id="path">
+                               <source>Path</source>
+                       </trans-unit>
+                       <trans-unit id="valid">
+                               <source>Valid</source>
+                       </trans-unit>
+                       <trans-unit id="no_search_paths">
+                               <source>No search paths configured.</source>
+                       </trans-unit>
+               </body>
+       </file>
+</xliff>
diff --git a/typo3/sysext/reports/Resources/Private/Templates/ServicesListReport.html b/typo3/sysext/reports/Resources/Private/Templates/ServicesListReport.html
new file mode 100644 (file)
index 0000000..dcb9331
--- /dev/null
@@ -0,0 +1,77 @@
+<p class="lead">
+    <f:translate key="report_explanation" />
+</p>
+<p class="help">
+    <f:translate key="externals_explanation" />
+</p>
+
+<f:for each="{servicesList}" as="serviceList">
+    <f:render section="ServiceTypeList" arguments="{serviceList: serviceList}" />
+</f:for>
+
+<h3><f:translate key="search_paths" /></h3>
+<f:if condition="{searchPaths}">
+    <f:then>
+        <table class="table table-striped table-hover tx_sv_reportlist">
+            <thead>
+                <tr>
+                    <td><f:translate key="LLL:EXT:reports/Resources/Private/Language/locallang_servicereport.xlf:path" /></td>
+                    <td><f:translate key="LLL:EXT:reports/Resources/Private/Language/locallang_servicereport.xlf:valid" /></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="LLL:EXT:reports/Resources/Private/Language/locallang_servicereport.xlf:{searchPath.accessible}" /></td>
+                    </tr>
+                </f:for>
+            </tbody>
+        </table>
+    </f:then>
+    <f:else>
+        <p><f:translate key="LLL:EXT:reports/Resources/Private/Language/locallang_servicereport.xlf:no_search_paths" /></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" /></td>
+                <td><f:translate key="LLL:EXT:reports/Resources/Private/Language/locallang_servicereport.xlf:priority" /></td>
+                <td><f:translate key="LLL:EXT:reports/Resources/Private/Language/locallang_servicereport.xlf:quality" /></td>
+                <td style="width: 35%"><f:translate key="LLL:EXT:reports/Resources/Private/Language/locallang_servicereport.xlf:subtypes" /></td>
+                <td><f:translate key="LLL:EXT:reports/Resources/Private/Language/locallang_servicereport.xlf:os" /></td>
+                <td><f:translate key="LLL:EXT:reports/Resources/Private/Language/locallang_servicereport.xlf:externals" /></td>
+                <td><f:translate key="LLL:EXT:reports/Resources/Private/Language/locallang_servicereport.xlf:available" /></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>
diff --git a/typo3/sysext/reports/Resources/Public/Images/service-reports.png b/typo3/sysext/reports/Resources/Public/Images/service-reports.png
new file mode 100644 (file)
index 0000000..c782b5b
Binary files /dev/null and b/typo3/sysext/reports/Resources/Public/Images/service-reports.png differ
diff --git a/typo3/sysext/reports/Tests/Unit/Report/ServicesListReportTest.php b/typo3/sysext/reports/Tests/Unit/Report/ServicesListReportTest.php
new file mode 100644 (file)
index 0000000..2a8c1be
--- /dev/null
@@ -0,0 +1,104 @@
+<?php
+declare(strict_types=1);
+namespace TYPO3\Reports\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\Localization\LanguageService;
+use TYPO3\CMS\Core\Utility\GeneralUtility;
+use TYPO3\CMS\Fluid\View\StandaloneView;
+use TYPO3\CMS\Reports\Controller\ReportController;
+use TYPO3\CMS\Reports\Report\ServicesListReport;
+
+/**
+ * Test case for class ServicesListReport
+ */
+class ServicesListReportTest extends \TYPO3\TestingFramework\Core\Unit\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:reports/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:reports/Resources/Private/Language/locallang_servicereport.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;
+    }
+}
index 84aa205..09b375e 100644 (file)
@@ -32,4 +32,11 @@ if (TYPO3_MODE === 'BE') {
     $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['reports']['tx_reports']['status']['providers']['security'][] = \TYPO3\CMS\Reports\Report\Status\SecurityStatus::class;
     $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['reports']['tx_reports']['status']['providers']['configuration'][] = \TYPO3\CMS\Reports\Report\Status\ConfigurationStatus::class;
     $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['reports']['tx_reports']['status']['providers']['fal'][] = \TYPO3\CMS\Reports\Report\Status\FalStatus::class;
+
+    $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['reports']['sv']['services'] = [
+        'title' => 'LLL:EXT:reports/Resources/Private/Language/locallang_servicereport.xlf:report_title',
+        'description' => 'LLL:EXT:reports/Resources/Private/Language/locallang_servicereport.xlf:report_description',
+        'icon' => 'EXT:reports/Resources/Public/Images/service-reports.png',
+        'report' => \TYPO3\CMS\Reports\Report\ServicesListReport::class
+    ];
 }
diff --git a/typo3/sysext/sv/Classes/Report/ServicesListReport.php b/typo3/sysext/sv/Classes/Report/ServicesListReport.php
deleted file mode 100644 (file)
index e6c1e44..0000000
+++ /dev/null
@@ -1,238 +0,0 @@
-<?php
-namespace TYPO3\CMS\Sv\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 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;
-
-/**
- * This class provides a report displaying a list of all installed services
- */
-class ServicesListReport implements ReportInterface
-{
-    /**
-     * @var ReportController
-     */
-    protected $reportsModule;
-
-    /**
-     * Constructor
-     *
-     * @param ReportController $reportsModule Back-reference to the calling reports module
-     */
-    public function __construct(ReportController $reportsModule)
-    {
-        $this->reportsModule = $reportsModule;
-        $this->getLanguageService()->includeLLFile('EXT:sv/Resources/Private/Language/locallang.xlf');
-    }
-
-    /**
-     * This method renders the report
-     *
-     * @return string The status report as HTML
-     */
-    public function getReport()
-    {
-        // Rendering of the output via fluid
-        $view = GeneralUtility::makeInstance(StandaloneView::class);
-        $view->setTemplatePathAndFilename(GeneralUtility::getFileAbsFileName(
-            'EXT:sv/Resources/Private/Templates/ServicesListReport.html'
-        ));
-
-        $view->assignMultiple([
-            'servicesList' => $this->getServicesList(),
-            'searchPaths' => $this->getExecutablesSearchPathList()
-        ]);
-
-        return $view->render();
-    }
-
-    /**
-     * This method assembles a list of all installed services
-     *
-     * @return array with data to display
-     */
-    protected function getServicesList()
-    {
-        $servicesList = [];
-        $services = $this->getInstalledServices();
-        foreach ($services as $serviceType => $installedServices) {
-            $servicesList[] = $this->getServiceTypeList($serviceType, $installedServices);
-        }
-        return $servicesList;
-    }
-
-    /**
-     * 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 array Service list as array for one service type
-     */
-    protected function getServiceTypeList($serviceType, $services)
-    {
-        $lang = $this->getLanguageService();
-        $serviceList = [];
-        $serviceList['Type'] = sprintf($lang->getLL('service_type'), $serviceType);
-
-        $serviceList['Services'] = [];
-        foreach ($services as $serviceKey => $serviceInformation) {
-            $serviceList['Services'][] = $this->getServiceRow($serviceKey, $serviceInformation);
-        }
-
-        return $serviceList;
-    }
-
-    /**
-     * 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 array data for one row for the service.
-     */
-    protected function getServiceRow($serviceKey, $serviceInformation)
-    {
-        $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/Resources/Private/Language/locallang_common.xlf:no'),
-        ];
-
-        try {
-            $serviceDetails = ExtensionManagementUtility::findServiceByKey($serviceKey);
-            if ($serviceDetails['available']) {
-                $result['AvailabilityClass'] = 'success';
-                $result['Available'] = $this->getLanguageService()->sL('LLL:EXT:lang/Resources/Private/Language/locallang_common.xlf:yes');
-            }
-        } catch (Exception $e) {
-        }
-
-        return $result;
-    }
-
-    /**
-     * This method assembles a list of all defined executables search paths
-     *
-     * @return array data to display
-     */
-    protected function getExecutablesSearchPathList()
-    {
-        $searchPaths = CommandUtility::getPaths(true);
-        $result = [];
-
-        foreach ($searchPaths as $path => $isValid) {
-            $searchPathData = $this->getServicePathStatus($isValid);
-            $result[] = [
-                'class' => $searchPathData['statusCSSClass'],
-                'accessible' => 'LLL:EXT:lang/Resources/Private/Language/locallang_common.xlf:' . $searchPathData['accessible'],
-                'path' => GeneralUtility::fixWindowsFilePath($path),
-            ];
-        }
-
-        return $result;
-    }
-
-    /**
-     * This method filters the $T3_SERVICES global array to return a relevant,
-     * ordered list of installed services.
-     *
-     * Every installed service appears twice in $T3_SERVICES: once as a service key
-     * for a given service type, and once a service type all by itself
-     * The list of services to display must avoid these duplicates
-     *
-     * Furthermore, inside each service type, installed services must be
-     * ordered by priority and quality
-     *
-     * @return array List of filtered and ordered services
-     */
-    protected function getInstalledServices()
-    {
-        $filteredServices = [];
-        foreach ($GLOBALS['T3_SERVICES'] as $serviceType => $serviceList) {
-            // If the (first) key of the service list is not the same as the service type,
-            // it's a "true" service type. Keep it and sort it.
-            if (key($serviceList) !== $serviceType) {
-                uasort($serviceList, [$this, 'sortServices']);
-                $filteredServices[$serviceType] = $serviceList;
-            }
-        }
-        return $filteredServices;
-    }
-
-    /**
-     * Utility method used to sort services according to their priority and
-     * quality.
-     *
-     * @param array $a First service to compare
-     * @param array $b Second service to compare
-     * @return int 1, 0 or -1 if $a is smaller, equal or greater than $b, respectively
-     */
-    protected function sortServices(array $a, array $b)
-    {
-        $result = 0;
-        // If priorities are the same, test 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;
-            }
-        } else {
-            // Service with highest priority should come first,
-            // thus it must be marked as smaller
-            $result = $a['priority'] > $b['priority'] ? -1 : 1;
-        }
-        return $result;
-    }
-
-    /**
-     * Method to check if the service in path is available
-     * @param bool|string $isValid
-     * @return array
-     */
-    private function getServicePathStatus($isValid): array
-    {
-        $statusCSSClass = 'danger';
-        $accessible = 'no';
-
-        if ($isValid) {
-            $statusCSSClass = 'success';
-            $accessible = 'yes';
-        }
-        return [
-            'statusCSSClass' => $statusCSSClass,
-            'accessible' => $accessible
-        ];
-    }
-
-    /**
-     * Returns LanguageService
-     *
-     * @return \TYPO3\CMS\Core\Localization\LanguageService
-     */
-    protected function getLanguageService()
-    {
-        return $GLOBALS['LANG'];
-    }
-}
diff --git a/typo3/sysext/sv/Resources/Private/Language/locallang.xlf b/typo3/sysext/sv/Resources/Private/Language/locallang.xlf
deleted file mode 100644 (file)
index 0dd4b56..0000000
+++ /dev/null
@@ -1,59 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<xliff version="1.0" xmlns:t3="http://typo3.org/schemas/xliff">
-       <file t3:id="1415814992" source-language="en" datatype="plaintext" original="messages" date="2011-10-17T20:22:37Z" product-name="sv">
-               <header/>
-               <body>
-                       <trans-unit id="report_title">
-                               <source>Installed Services</source>
-                       </trans-unit>
-                       <trans-unit id="report_description">
-                               <source>List of all installed services with information and status for each of them.</source>
-                       </trans-unit>
-                       <trans-unit id="report_explanation">
-                               <source>This report displays a list of installed services, with detailed information about each of them. The services are ordered by type, priority and quality. Unavailable services are highlighted with an error status.</source>
-                       </trans-unit>
-                       <trans-unit id="externals_explanation">
-                               <source>The "Externals" column shows which external programs a given service relies on. If such program is missing or not executable, the service will be unavailable. Search paths for executables are listed at the bottom of this report.</source>
-                       </trans-unit>
-                       <trans-unit id="service_type">
-                               <source>Service type: %s</source>
-                       </trans-unit>
-                       <trans-unit id="service">
-                               <source>Service</source>
-                       </trans-unit>
-                       <trans-unit id="priority">
-                               <source>Priority</source>
-                       </trans-unit>
-                       <trans-unit id="quality">
-                               <source>Quality</source>
-                       </trans-unit>
-                       <trans-unit id="subtypes">
-                               <source>Subtypes</source>
-                       </trans-unit>
-                       <trans-unit id="os">
-                               <source>OS</source>
-                       </trans-unit>
-                       <trans-unit id="externals">
-                               <source>Externals</source>
-                       </trans-unit>
-                       <trans-unit id="available">
-                               <source>Available</source>
-                       </trans-unit>
-                       <trans-unit id="any">
-                               <source>Any</source>
-                       </trans-unit>
-                       <trans-unit id="search_paths">
-                               <source>Configured search paths for external programs</source>
-                       </trans-unit>
-                       <trans-unit id="path">
-                               <source>Path</source>
-                       </trans-unit>
-                       <trans-unit id="valid">
-                               <source>Valid</source>
-                       </trans-unit>
-                       <trans-unit id="no_search_paths">
-                               <source>No search paths configured.</source>
-                       </trans-unit>
-               </body>
-       </file>
-</xliff>
diff --git a/typo3/sysext/sv/Resources/Private/Templates/ServicesListReport.html b/typo3/sysext/sv/Resources/Private/Templates/ServicesListReport.html
deleted file mode 100644 (file)
index 22774fd..0000000
+++ /dev/null
@@ -1,77 +0,0 @@
-<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/Resources/Public/Images/service-reports.png b/typo3/sysext/sv/Resources/Public/Images/service-reports.png
deleted file mode 100644 (file)
index c782b5b..0000000
Binary files a/typo3/sysext/sv/Resources/Public/Images/service-reports.png and /dev/null differ
diff --git a/typo3/sysext/sv/Tests/Unit/Report/ServicesListReportTest.php b/typo3/sysext/sv/Tests/Unit/Report/ServicesListReportTest.php
deleted file mode 100644 (file)
index d33e4e4..0000000
+++ /dev/null
@@ -1,104 +0,0 @@
-<?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\Localization\LanguageService;
-use TYPO3\CMS\Core\Utility\GeneralUtility;
-use TYPO3\CMS\Fluid\View\StandaloneView;
-use TYPO3\CMS\Reports\Controller\ReportController;
-use TYPO3\CMS\Sv\Report\ServicesListReport;
-
-/**
- * Test case for class ServicesListReport
- */
-class ServicesListReportTest extends \TYPO3\TestingFramework\Core\Unit\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;
-    }
-}
diff --git a/typo3/sysext/sv/ext_tables.php b/typo3/sysext/sv/ext_tables.php
deleted file mode 100644 (file)
index 371b9a0..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-<?php
-defined('TYPO3_MODE') or die();
-
-if (TYPO3_MODE === 'BE') {
-    $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['reports']['sv']['services'] = [
-        'title' => 'LLL:EXT:sv/Resources/Private/Language/locallang.xlf:report_title',
-        'description' => 'LLL:EXT:sv/Resources/Private/Language/locallang.xlf:report_description',
-        'icon' => 'EXT:sv/Resources/Public/Images/service-reports.png',
-        'report' => \TYPO3\CMS\Sv\Report\ServicesListReport::class
-    ];
-}