first commit

This commit is contained in:
Sven Wappler
2021-04-17 00:26:33 +02:00
commit 866c63cc63
813 changed files with 100696 additions and 0 deletions

View File

@@ -0,0 +1,74 @@
<?php
namespace WapplerSystems\Meilisearch\Report;
/***************************************************************
* Copyright notice
*
* (c) 2017 Timo Hund <timo.hund@dkd.de>
* All rights reserved
*
* This script is part of the TYPO3 project. The TYPO3 project is
* free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* The GNU General Public License can be found at
* http://www.gnu.org/copyleft/gpl.html.
*
* This script is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* This copyright notice MUST APPEAR in all copies of the script!
***************************************************************/
use TYPO3\CMS\Fluid\View\StandaloneView;
use TYPO3\CMS\Core\Utility\GeneralUtility;
use TYPO3\CMS\Reports\StatusProviderInterface;
/**
* Provides shared functionality for all Solr reports.
*
* @author Timo Hund <timo.hund@dkd.de>
*/
abstract class AbstractSolrStatus implements StatusProviderInterface
{
/**
* Assigns variables to the fluid StandaloneView and renders the view.
*
* @param string $templateFilename
* @param array $variables
* @return string
*/
protected function getRenderedReport($templateFilename = '', $variables = [])
{
$templatePath = 'EXT:meilisearch/Resources/Private/Templates/Backend/Reports/' . $templateFilename;
$standaloneView = $this->getFluidStandaloneViewWithTemplate($templatePath);
$standaloneView->assignMultiple($variables);
return $standaloneView->render();
}
/**
* Initializes a StandaloneView with a template and returns it.
*
* @param string $templatePath
* @return StandaloneView
*/
private function getFluidStandaloneViewWithTemplate($templatePath = '')
{
$standaloneView = GeneralUtility::makeInstance(StandaloneView::class);
$standaloneView->setTemplatePathAndFilename(GeneralUtility::getFileAbsFileName($templatePath));
return $standaloneView;
}
/**
* Returns the status of an extension or (sub)system
*
* @return array An array of \TYPO3\CMS\Reports\Status objects
*/
abstract public function getStatus();
}

View File

@@ -0,0 +1,189 @@
<?php
namespace WapplerSystems\Meilisearch\Report;
/***************************************************************
* Copyright notice
*
* (c) 2010-2015 Ingo Renner <ingo@typo3.org>
* All rights reserved
*
* This script is part of the TYPO3 project. The TYPO3 project is
* free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* The GNU General Public License can be found at
* http://www.gnu.org/copyleft/gpl.html.
*
* This script is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* This copyright notice MUST APPEAR in all copies of the script!
***************************************************************/
use WapplerSystems\Meilisearch\ConnectionManager;
use WapplerSystems\Meilisearch\System\Solr\Service\SolrAdminService;
use TYPO3\CMS\Core\Utility\GeneralUtility;
use TYPO3\CMS\Reports\Status;
/**
* Provides a status report about whether the Access Filter Query Parser Plugin
* is installed on the Solr server.
*
* @author Ingo Renner <ingo@typo3.org>
*/
class AccessFilterPluginInstalledStatus extends AbstractSolrStatus
{
/**
* Solr Access Filter plugin version.
*
* Must be updated when changing the plugin.
*
* @var string
*/
const RECOMMENDED_PLUGIN_VERSION = '3.0.0';
/**
* The plugin's Java class name.
*
* @var string
*/
const PLUGIN_CLASS_NAME = 'org.typo3.solr.search.AccessFilterQParserPlugin';
/**
* Compiles a collection of solrconfig.xml checks against each configured
* Solr server. Only adds an entry if the Access Filter Query Parser Plugin
* is not configured.
*
*/
public function getStatus()
{
$reports = [];
$solrConnections = GeneralUtility::makeInstance(ConnectionManager::class)->getAllConnections();
foreach ($solrConnections as $solrConnection) {
$adminService = $solrConnection->getAdminService();
if ($adminService->ping()) {
$installationStatus = $this->checkPluginInstallationStatus($adminService);
$versionStatus = $this->checkPluginVersion($adminService);
if (!is_null($installationStatus)) {
$reports[] = $installationStatus;
}
if (!is_null($versionStatus)) {
$reports[] = $versionStatus;
}
}
}
return $reports;
}
/**
* Checks whether the Solr plugin is installed.
*
* @param SolrAdminService $adminService
* @return null|\TYPO3\CMS\Reports\Status
*/
protected function checkPluginInstallationStatus(SolrAdminService $adminService)
{
if ($this->isPluginInstalled($adminService)) {
return null;
}
$variables = ['solr' => $adminService, 'recommendedVersion' => self::RECOMMENDED_PLUGIN_VERSION];
$report = $this->getRenderedReport('AccessFilterPluginInstalledStatusNotInstalled.html', $variables);
return GeneralUtility::makeInstance(
Status::class,
/** @scrutinizer ignore-type */ 'Access Filter Plugin',
/** @scrutinizer ignore-type */ 'Not Installed',
/** @scrutinizer ignore-type */ $report,
/** @scrutinizer ignore-type */ Status::WARNING
);
}
/**
* Checks whether the Solr plugin version is up to date.
*
* @param SolrAdminService $adminService
* @return null|\TYPO3\CMS\Reports\Status
*/
protected function checkPluginVersion(SolrAdminService $adminService)
{
if (!($this->isPluginInstalled($adminService) && $this->isPluginOutdated($adminService))) {
return null;
}
$version = $this->getInstalledPluginVersion($adminService);
$variables = ['solr' => $adminService, 'installedVersion' => $version, 'recommendedVersion' => self::RECOMMENDED_PLUGIN_VERSION];
$report = $this->getRenderedReport('AccessFilterPluginInstalledStatusIsOutDated.html', $variables);
return GeneralUtility::makeInstance(
Status::class,
/** @scrutinizer ignore-type */ 'Access Filter Plugin',
/** @scrutinizer ignore-type */ 'Outdated',
/** @scrutinizer ignore-type */ $report,
/** @scrutinizer ignore-type */ Status::WARNING
);
}
/**
* Checks whether the Access Filter Query Parser Plugin is installed for
* the given Solr server instance.
*
* @param SolrAdminService $adminService
* @return bool True if the plugin is installed, FALSE otherwise.
*/
protected function isPluginInstalled(SolrAdminService $adminService)
{
$accessFilterQueryParserPluginInstalled = false;
$pluginsInformation = $adminService->getPluginsInformation();
if (isset($pluginsInformation->plugins->OTHER->{self::PLUGIN_CLASS_NAME})) {
$accessFilterQueryParserPluginInstalled = true;
}
return $accessFilterQueryParserPluginInstalled;
}
/**
* Checks whether the installed plugin is current.
*
* @param SolrAdminService $adminService
* @return bool True if the plugin is outdated, FALSE if it meets the current version recommendation.
*/
protected function isPluginOutdated(SolrAdminService $adminService)
{
$pluginVersion = $this->getInstalledPluginVersion($adminService);
$pluginVersionOutdated = version_compare($pluginVersion, self::RECOMMENDED_PLUGIN_VERSION, '<');
return $pluginVersionOutdated;
}
/**
* Gets the version of the installed plugin.
*
* @param SolrAdminService $adminService
* @return string The installed plugin's version number.
*/
public function getInstalledPluginVersion(SolrAdminService $adminService)
{
$pluginsInformation = $adminService->getPluginsInformation();
$description = $pluginsInformation->plugins->OTHER->{self::PLUGIN_CLASS_NAME}->description;
$matches = [];
preg_match_all('/.*\(Version: (?<version>[^\)]*)\)/ums', $description, $matches);
$rawVersion = $matches['version'][0] ?? '';
$explodedRawVersion = explode('-', $rawVersion);
$version = $explodedRawVersion[0];
return $version;
}
}

View File

@@ -0,0 +1,69 @@
<?php
namespace WapplerSystems\Meilisearch\Report;
/***************************************************************
* Copyright notice
*
* (c) 2012-2015 Ingo Renner <ingo@typo3.org>
* All rights reserved
*
* This script is part of the TYPO3 project. The TYPO3 project is
* free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* The GNU General Public License can be found at
* http://www.gnu.org/copyleft/gpl.html.
*
* This script is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* This copyright notice MUST APPEAR in all copies of the script!
***************************************************************/
use TYPO3\CMS\Core\Utility\GeneralUtility;
use TYPO3\CMS\Reports\Status;
/**
* Provides a status report about whether the php.ini setting allow_url_fopen
* is activated or not.
*
* @author Ingo Renner <ingo@typo3.org>
*/
class AllowUrlFOpenStatus extends AbstractSolrStatus
{
/**
* Checks whether allow_url_fopen is enabled.
*
*/
public function getStatus()
{
$reports = [];
$severity = Status::OK;
$value = 'On';
$message = '';
if (!ini_get('allow_url_fopen')) {
$severity = Status::ERROR;
$value = 'Off';
$message = 'allow_url_fopen must be enabled in php.ini to allow
communication between TYPO3 and the Apache Solr server.
Indexing pages using the Index Queue will also not work with
this setting disabled.';
}
$reports[] = GeneralUtility::makeInstance(
Status::class,
/** @scrutinizer ignore-type */ 'allow_url_fopen',
/** @scrutinizer ignore-type */ $value,
/** @scrutinizer ignore-type */ $message,
/** @scrutinizer ignore-type */ $severity
);
return $reports;
}
}

View File

@@ -0,0 +1,68 @@
<?php
namespace WapplerSystems\Meilisearch\Report;
/***************************************************************
* Copyright notice
*
* (c) 2012-2015 Ingo Renner <ingo@typo3.org>
* All rights reserved
*
* This script is part of the TYPO3 project. The TYPO3 project is
* free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* The GNU General Public License can be found at
* http://www.gnu.org/copyleft/gpl.html.
*
* This script is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* This copyright notice MUST APPEAR in all copies of the script!
***************************************************************/
use TYPO3\CMS\Core\Utility\GeneralUtility;
use TYPO3\CMS\Reports\Status;
/**
* There's a buggy PHP version in Ubuntu LTS 10.04 which causes filter_var to
* produces incorrect results. This status checks for this issue.
*
* @author Ingo Renner <ingo@typo3.org>
*/
class FilterVarStatus extends AbstractSolrStatus
{
/**
* Checks whether allow_url_fopen is enabled.
*
*/
public function getStatus()
{
$reports = [];
$validUrl = 'http://www.typo3-solr.com';
if (!filter_var($validUrl, FILTER_VALIDATE_URL)) {
$message = 'You are using a PHP version that is affected by a bug in
function filter_var(). This bug causes said function to
incorrectly report valid URLs as invalid if they contain a
dash (-). EXT:meilisearch uses this function to validate URLs when
indexing TYPO3 pages. Please check with your administrator
whether a newer version can be installed.
More information is available at
<a href="https://bugs.php.net/bug.php?id=51192">php.net</a>.';
$reports[] = GeneralUtility::makeInstance(Status::class,
'PHP filter_var() bug',
'Affected PHP version detected.',
$message,
Status::ERROR
);
}
return $reports;
}
}

View File

@@ -0,0 +1,101 @@
<?php
namespace WapplerSystems\Meilisearch\Report;
/***************************************************************
* Copyright notice
*
* (c) 2010-2015 Ingo Renner <ingo@typo3.org>
* All rights reserved
*
* This script is part of the TYPO3 project. The TYPO3 project is
* free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* The GNU General Public License can be found at
* http://www.gnu.org/copyleft/gpl.html.
*
* This script is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* This copyright notice MUST APPEAR in all copies of the script!
***************************************************************/
use WapplerSystems\Meilisearch\ConnectionManager;
use WapplerSystems\Meilisearch\System\Solr\SolrConnection;
use TYPO3\CMS\Core\Utility\GeneralUtility;
use TYPO3\CMS\Reports\Status;
/**
* Provides an status report about which schema version is used and checks
* whether it fits the recommended version shipping with the extension.
*
* @author Ingo Renner <ingo@typo3.org>
*/
class SchemaStatus extends AbstractSolrStatus
{
/**
* The schema name property is constructed as follows:
*
* tx_meilisearch - The extension key
* x-y-z - The extension version this schema is meant to work with
* YYYYMMDD - The date the schema file was changed the last time
*
* Must be updated when changing the schema.
*
* @var string
*/
const RECOMMENDED_SCHEMA_VERSION = 'tx_meilisearch-11-0-0--20200415';
/**
* Compiles a collection of schema version checks against each configured
* Solr server. Only adds an entry if a schema other than the
* recommended one was found.
*
*/
public function getStatus()
{
$reports = [];
/** @var $connectionManager ConnectionManager */
$connectionManager = GeneralUtility::makeInstance(ConnectionManager::class);
$solrConnections = $connectionManager->getAllConnections();
foreach ($solrConnections as $solrConnection) {
$adminService = $solrConnection->getAdminService();
/** @var $solrConnection SolrConnection */
if (!$adminService->ping()) {
$url = $adminService->__toString();
$pingFailedMsg = 'Could not ping solr server, can not check version ' . (string)$url;
$status = GeneralUtility::makeInstance(
Status::class,
/** @scrutinizer ignore-type */ 'Apache Solr Version',
/** @scrutinizer ignore-type */ 'Not accessible',
/** @scrutinizer ignore-type */ $pingFailedMsg,
/** @scrutinizer ignore-type */ Status::ERROR
);
$reports[] = $status;
continue;
}
$isWrongSchema = $adminService->getSchema()->getName() != self::RECOMMENDED_SCHEMA_VERSION;
if ($isWrongSchema) {
$variables = ['solr' => $adminService, 'recommendedVersion' => self::RECOMMENDED_SCHEMA_VERSION];
$report = $this->getRenderedReport('SchemaStatus.html', $variables);
$status = GeneralUtility::makeInstance(
Status::class,
/** @scrutinizer ignore-type */ 'Schema Version',
/** @scrutinizer ignore-type */ 'Unsupported Schema',
/** @scrutinizer ignore-type */ $report,
/** @scrutinizer ignore-type */ Status::WARNING
);
$reports[] = $status;
}
}
return $reports;
}
}

View File

@@ -0,0 +1,189 @@
<?php
namespace WapplerSystems\Meilisearch\Report;
/***************************************************************
* Copyright notice
*
* (c) 2019- dkd Internet Services GmbH (info@dkd.de)
* All rights reserved
*
* This script is part of the TYPO3 project. The TYPO3 project is
* free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* The GNU General Public License can be found at
* http://www.gnu.org/copyleft/gpl.html.
*
* This script is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* This copyright notice MUST APPEAR in all copies of the script!
***************************************************************/
use WapplerSystems\Meilisearch\Domain\Site\Site;
use WapplerSystems\Meilisearch\Domain\Site\SiteRepository;
use WapplerSystems\Meilisearch\Domain\Site\Typo3ManagedSite;
use WapplerSystems\Meilisearch\System\Configuration\ExtensionConfiguration;
use Exception;
use Psr\Http\Message\UriInterface;
use TYPO3\CMS\Core\Site\Entity\Site as Typo3Site;
use TYPO3\CMS\Core\Site\Entity\SiteLanguage;
use TYPO3\CMS\Core\Utility\GeneralUtility;
use TYPO3\CMS\Reports\Status;
/**
* Provides an status report about current state of site handling configurations.
*
* Following thigs are checked currently:
* * Entry Point[base] scheme expects -> http[s]
* * Entry Point[base] authority expects -> [user-info@]host[:port]
*/
class SiteHandlingStatus extends AbstractSolrStatus
{
const TITLE_SITE_HANDLING_CONFIGURATION = 'Site handling configuration';
const
CSS_STATUS_NOTICE = 'notice',
CSS_STATUS_INFO = 'info',
CSS_STATUS_OK = 'success',
CSS_STATUS_WARNING = 'warning',
CSS_STATUS_ERROR = 'danger';
/**
* Site Repository
*
* @var SiteRepository
*/
protected $siteRepository = null;
/**
* @var ExtensionConfiguration
*/
protected $extensionConfiguration = null;
/**
* SolrStatus constructor.
* @param ExtensionConfiguration $extensionConfiguration
* @param SiteRepository|null $siteRepository
*/
public function __construct(ExtensionConfiguration $extensionConfiguration = null, SiteRepository $siteRepository = null)
{
$this->extensionConfiguration = $extensionConfiguration ?? GeneralUtility::makeInstance(ExtensionConfiguration::class);
$this->siteRepository = $siteRepository ?? GeneralUtility::makeInstance(SiteRepository::class);
}
/**
* @return array
* @throws Exception
*/
public function getStatus()
{
$reports = [];
/* @var Site $site */
foreach ($this->siteRepository->getAvailableSites() as $site) {
if (!($site instanceof Typo3ManagedSite)) {
$reports[] = GeneralUtility::makeInstance(
Status::class,
/** @scrutinizer ignore-type */ self::TITLE_SITE_HANDLING_CONFIGURATION,
/** @scrutinizer ignore-type */ 'Something went wrong',
/** @scrutinizer ignore-type */ vsprintf('The configured Site "%s" is not TYPO3 managed site. Please refer to TYPO3 site management docs and configure the site properly.', [$site->getLabel()]),
/** @scrutinizer ignore-type */ Status::ERROR
);
continue;
}
$reports[] = $this->generateValidationReportForSingleSite($site->getTypo3SiteObject());
}
return $reports;
}
/**
* Renders validation results for desired typo3 site configuration.
*
* @param Typo3Site $ypo3Site
* @return Status
*/
protected function generateValidationReportForSingleSite(Typo3Site $ypo3Site): Status
{
$variables = [
'identifier' => $ypo3Site->getIdentifier()
];
$globalPassedStateForThisSite = true;
foreach ($ypo3Site->getAllLanguages() as $siteLanguage) {
if (!$siteLanguage->isEnabled()) {
$variables['validationResults'][$siteLanguage->getTitle()] = [
'label' => 'Language: ' . $siteLanguage->getTitle(),
'message' => 'No checks: The language is disabled in site configuration.',
'CSSClassesFor' => [
'tr' => self::CSS_STATUS_NOTICE
],
'passed' => true
];
continue;
}
$variables['validationResults'][$siteLanguage->getTitle()] = $this->generateValidationResultsForSingleSiteLanguage($siteLanguage);
$globalPassedStateForThisSite = $globalPassedStateForThisSite && $variables['validationResults'][$siteLanguage->getTitle()]['passed'];
}
$renderedReport = $this->getRenderedReport('SiteHandlingStatus.html', $variables);
/* @var Status $status */
$status = GeneralUtility::makeInstance(
Status::class,
/** @scrutinizer ignore-type */ sprintf('Site Identifier: "%s"', $ypo3Site->getIdentifier()),
/** @scrutinizer ignore-type */ '',
/** @scrutinizer ignore-type */ $renderedReport,
/** @scrutinizer ignore-type */ $globalPassedStateForThisSite == true ? Status::OK : Status::ERROR
);
return $status;
}
/**
* Generates the validation result array for using them in standalone view as an table row.
*
* @param SiteLanguage $siteLanguage
* @return array
*/
protected function generateValidationResultsForSingleSiteLanguage(SiteLanguage $siteLanguage): array
{
$validationResult = [
'label' => 'Language: ' . $siteLanguage->getTitle(),
'passed' => true,
'CSSClassesFor' => [
'tr' => self::CSS_STATUS_OK
]
];
if (!GeneralUtility::isValidUrl((string)$siteLanguage->getBase())) {
$validationResult['message'] = sprintf('Entry Point[base]="%s" is not valid URL. Following parts of defined URL are empty or invalid: "%s"', (string)$siteLanguage->getBase(), $this->fetchInvalidPartsOfUri($siteLanguage->getBase()));
$validationResult['passed'] = false;
$validationResult['CSSClassesFor']['tr'] = self::CSS_STATUS_ERROR;
} else {
$validationResult['message'] = sprintf('Entry Point[base]="%s" is valid URL.', (string)$siteLanguage->getBase());
}
return $validationResult;
}
/**
* @param UriInterface $uri
* @return string
*/
protected function fetchInvalidPartsOfUri(UriInterface $uri): string
{
$invalidParts = [];
if (empty($uri->getScheme())) {
$invalidParts[] = 'scheme';
}
if (empty($uri->getHost())) {
$invalidParts[] = 'host';
}
return implode(', ', $invalidParts);
}
}

View File

@@ -0,0 +1,84 @@
<?php
namespace WapplerSystems\Meilisearch\Report;
/***************************************************************
* Copyright notice
*
* (c) 2010-2015 Ingo Renner <ingo@typo3.org>
* All rights reserved
*
* This script is part of the TYPO3 project. The TYPO3 project is
* free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* The GNU General Public License can be found at
* http://www.gnu.org/copyleft/gpl.html.
*
* This script is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* This copyright notice MUST APPEAR in all copies of the script!
***************************************************************/
use WapplerSystems\Meilisearch\ConnectionManager;
use TYPO3\CMS\Core\Utility\GeneralUtility;
use TYPO3\CMS\Reports\Status;
/**
* Provides a status report about which solrconfig version is used and checks
* whether it fits the recommended version shipping with the extension.
*
* @author Ingo Renner <ingo@typo3.org>
*/
class SolrConfigStatus extends AbstractSolrStatus
{
/**
* The config name property is constructed as follows:
*
* tx_meilisearch - The extension key
* x-y-z - The extension version this config is meant to work with
* YYYYMMDD - The date the config file was changed the last time
*
* Must be updated when changing the solrconfig.
*
* @var string
*/
const RECOMMENDED_SOLRCONFIG_VERSION = 'tx_meilisearch-11-0-0--20200415';
/**
* Compiles a collection of solrconfig version checks against each configured
* Solr server. Only adds an entry if a solrconfig other than the
* recommended one was found.
*
*/
public function getStatus()
{
$reports = [];
$solrConnections = GeneralUtility::makeInstance(ConnectionManager::class)->getAllConnections();
foreach ($solrConnections as $solrConnection) {
$adminService = $solrConnection->getAdminService();
if ($adminService->ping() && $adminService->getSolrconfigName() != self::RECOMMENDED_SOLRCONFIG_VERSION) {
$variables = ['solr' => $adminService, 'recommendedVersion' => self::RECOMMENDED_SOLRCONFIG_VERSION];
$report = $this->getRenderedReport('SolrConfigStatus.html', $variables);
$status = GeneralUtility::makeInstance(
Status::class,
/** @scrutinizer ignore-type */ 'Solrconfig Version',
/** @scrutinizer ignore-type */ 'Unsupported solrconfig.xml',
/** @scrutinizer ignore-type */ $report,
/** @scrutinizer ignore-type */ Status::WARNING
);
$reports[] = $status;
}
}
return $reports;
}
}

View File

@@ -0,0 +1,235 @@
<?php
namespace WapplerSystems\Meilisearch\Report;
/***************************************************************
* Copyright notice
*
* (c) 2011-2015 Ingo Renner <ingo@typo3.org>
* All rights reserved
*
* This script is part of the TYPO3 project. The TYPO3 project is
* free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* The GNU General Public License can be found at
* http://www.gnu.org/copyleft/gpl.html.
*
* This script is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* This copyright notice MUST APPEAR in all copies of the script!
***************************************************************/
use WapplerSystems\Meilisearch\FrontendEnvironment;
use WapplerSystems\Meilisearch\System\Configuration\ExtensionConfiguration;
use WapplerSystems\Meilisearch\System\Records\Pages\PagesRepository;
use RuntimeException;
use TYPO3\CMS\Core\Error\Http\ServiceUnavailableException;
use TYPO3\CMS\Core\Exception\SiteNotFoundException;
use TYPO3\CMS\Core\Http\ImmediateResponseException;
use TYPO3\CMS\Core\Utility\GeneralUtility;
use TYPO3\CMS\Reports\Status;
/**
* Provides an status report, which checks whether the configuration of the
* extension is ok.
*
* @author Ingo Renner <ingo@typo3.org>
*/
class SolrConfigurationStatus extends AbstractSolrStatus
{
/**
* @var ExtensionConfiguration
*/
protected $extensionConfiguration;
/**
* @var FrontendEnvironment
*/
protected $frontendEnvironment = null;
/**
* SolrConfigurationStatus constructor.
* @param ExtensionConfiguration|null $extensionConfiguration
* @param FrontendEnvironment|null $frontendEnvironment
*/
public function __construct(
ExtensionConfiguration $extensionConfiguration = null,
FrontendEnvironment $frontendEnvironment = null
)
{
$this->extensionConfiguration = $extensionConfiguration ?? GeneralUtility::makeInstance(ExtensionConfiguration::class);
$this->frontendEnvironment = $frontendEnvironment ?? GeneralUtility::makeInstance(FrontendEnvironment::class);
}
/**
* Compiles a collection of configuration status checks.
*
* @return array
* @throws ImmediateResponseException
*/
public function getStatus(): array
{
$reports = [];
$rootPageFlagStatus = $this->getRootPageFlagStatus();
if (!is_null($rootPageFlagStatus)) {
$reports[] = $rootPageFlagStatus;
// intended early return, no sense in going on if there are no root pages
return $reports;
}
$configIndexEnableStatus = $this->getConfigIndexEnableStatus();
if (!is_null($configIndexEnableStatus)) {
$reports[] = $configIndexEnableStatus;
}
return $reports;
}
/**
* Checks whether the "Use as Root Page" page property has been set for any
* site.
*
* @return NULL|Status An error status is returned if no root pages were found.
*/
protected function getRootPageFlagStatus(): ?Status
{
$rootPages = $this->getRootPages();
if (!empty($rootPages)) {
return null;
}
$report = $this->getRenderedReport('RootPageFlagStatus.html');
return GeneralUtility::makeInstance(
Status::class,
/** @scrutinizer ignore-type */ 'Sites',
/** @scrutinizer ignore-type */ 'No sites found',
/** @scrutinizer ignore-type */ $report,
/** @scrutinizer ignore-type */ Status::ERROR
);
}
/**
* Checks whether config.index_enable is set to 1, otherwise indexing will
* not work.
*
* @return NULL|Status An error status is returned for each site root page config.index_enable = 0.
* @throws ImmediateResponseException
*/
protected function getConfigIndexEnableStatus(): ?Status
{
$rootPagesWithIndexingOff = $this->getRootPagesWithIndexingOff();
if (empty($rootPagesWithIndexingOff)) {
return null;
}
$report = $this->getRenderedReport('SolrConfigurationStatusIndexing.html', ['pages' => $rootPagesWithIndexingOff]);
return GeneralUtility::makeInstance(
Status::class,
/** @scrutinizer ignore-type */ 'Page Indexing',
/** @scrutinizer ignore-type */ 'Indexing is disabled',
/** @scrutinizer ignore-type */ $report,
/** @scrutinizer ignore-type */ Status::WARNING
);
}
/**
* Returns an array of rootPages where the indexing is off and EXT:meilisearch is enabled.
*
* @return array
* @throws ImmediateResponseException
*/
protected function getRootPagesWithIndexingOff(): array
{
$rootPages = $this->getRootPages();
$rootPagesWithIndexingOff = [];
foreach ($rootPages as $rootPage) {
try {
$this->initializeTSFE($rootPage);
$solrIsEnabledAndIndexingDisabled = $this->getIsSolrEnabled() && !$this->getIsIndexingEnabled();
if ($solrIsEnabledAndIndexingDisabled) {
$rootPagesWithIndexingOff[] = $rootPage;
}
} catch (RuntimeException $rte) {
$rootPagesWithIndexingOff[] = $rootPage;
} catch (ServiceUnavailableException $sue) {
if ($sue->getCode() == 1294587218) {
// No TypoScript template found, continue with next site
$rootPagesWithIndexingOff[] = $rootPage;
continue;
}
} catch (SiteNotFoundException $sue) {
if ($sue->getCode() == 1521716622) {
// No site found, continue with next site
$rootPagesWithIndexingOff[] = $rootPage;
continue;
}
}
}
return $rootPagesWithIndexingOff;
}
/**
* Gets the site's root pages. The "Is root of website" flag must be set,
* which usually is the case for pages with pid = 0.
*
* @return array An array of (partial) root page records, containing the uid and title fields
*/
protected function getRootPages()
{
$pagesRepository = GeneralUtility::makeInstance(PagesRepository::class);
return $pagesRepository->findAllRootPages();
}
/**
* Checks if the solr plugin is enabled with plugin.tx_meilisearch.enabled.
*
* @return bool
*/
protected function getIsSolrEnabled(): bool
{
if (empty($GLOBALS['TSFE']->tmpl->setup['plugin.']['tx_meilisearch.']['enabled'])) {
return false;
}
return (bool)$GLOBALS['TSFE']->tmpl->setup['plugin.']['tx_meilisearch.']['enabled'];
}
/**
* Checks if the indexing is enabled with config.index_enable
*
* @return bool
*/
protected function getIsIndexingEnabled(): bool
{
if (empty($GLOBALS['TSFE']->config['config']['index_enable'])) {
return false;
}
return (bool)$GLOBALS['TSFE']->config['config']['index_enable'];
}
/**
* Initializes TSFE via FrontendEnvironment.
*
* Purpose: Unit test mocking helper method.
*
* @param array $rootPageRecord
* @throws ImmediateResponseException
* @throws ServiceUnavailableException
* @throws SiteNotFoundException
*/
protected function initializeTSFE(array $rootPageRecord)
{
$this->frontendEnvironment->initializeTsfe($rootPageRecord['uid']);
}
}

View File

@@ -0,0 +1,263 @@
<?php
namespace WapplerSystems\Meilisearch\Report;
/***************************************************************
* Copyright notice
*
* (c) 2009-2015 Ingo Renner <ingo@typo3.org>
* All rights reserved
*
* This script is part of the TYPO3 project. The TYPO3 project is
* free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* The GNU General Public License can be found at
* http://www.gnu.org/copyleft/gpl.html.
*
* This script is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* This copyright notice MUST APPEAR in all copies of the script!
***************************************************************/
use WapplerSystems\Meilisearch\ConnectionManager;
use WapplerSystems\Meilisearch\Domain\Site\SiteRepository;
use WapplerSystems\Meilisearch\PingFailedException;
use WapplerSystems\Meilisearch\System\Solr\Service\SolrAdminService;
use TYPO3\CMS\Core\Utility\GeneralUtility;
use TYPO3\CMS\Fluid\View\StandaloneView;
use TYPO3\CMS\Reports\Status;
use TYPO3\CMS\Reports\StatusProviderInterface;
/**
* Provides an status report about whether a connection to the Solr server can
* be established.
*
* @author Ingo Renner <ingo@typo3.org>
*/
class SolrStatus extends AbstractSolrStatus
{
/**
* Site Repository
*
* @var SiteRepository
*/
protected $siteRepository = null;
/**
* Connection Manager
*
* @var ConnectionManager
*/
protected $connectionManager = null;
/**
* Holds the response status
*
* @var int
*/
protected $responseStatus = Status::OK;
/**
* Holds the response message build by the checks
*
* @var string
*/
protected $responseMessage = '';
/**
* SolrStatus constructor.
* @param SiteRepository|null $siteRepository
* @param ConnectionManager|null $connectionManager
*/
public function __construct(SiteRepository $siteRepository = null, ConnectionManager $connectionManager = null)
{
$this->siteRepository = $siteRepository ?? GeneralUtility::makeInstance(SiteRepository::class);
$this->connectionManager = $connectionManager ?? GeneralUtility::makeInstance(ConnectionManager::class);
}
/**
* Compiles a collection of status checks against each configured Solr server.
*
*/
public function getStatus()
{
$reports = [];
foreach ($this->siteRepository->getAvailableSites() as $site) {
foreach ($site->getAllSolrConnectionConfigurations() as $solrConfiguration) {
$reports[] = $this->getConnectionStatus($solrConfiguration);
}
}
return $reports;
}
/**
* Checks whether a Solr server is available and provides some information.
*
* @param array $solrConnection Solr connection parameters
* @return Status Status of the Solr connection
*/
protected function getConnectionStatus(array $solrConnection)
{
$header = 'Your site has contacted the Apache Solr server.';
$this->responseStatus = Status::OK;
$solrAdmin = $this->connectionManager
->getSolrConnectionForNodes($solrConnection['read'], $solrConnection['write'])
->getAdminService();
$solrVersion = $this->checkSolrVersion($solrAdmin);
$accessFilter = $this->checkAccessFilter($solrAdmin);
$pingTime = $this->checkPingTime($solrAdmin);
$configName = $this->checkSolrConfigName($solrAdmin);
$schemaName = $this->checkSolrSchemaName($solrAdmin);
if ($this->responseStatus !== Status::OK) {
$header = 'Failed contacting the Solr server.';
}
$variables = [
'header' => $header,
'connection' => $solrConnection,
'solr' => $solrAdmin,
'solrVersion' => $solrVersion,
'pingTime' => $pingTime,
'configName' => $configName,
'schemaName' => $schemaName,
'accessFilter' => $accessFilter
];
$report = $this->getRenderedReport('SolrStatus.html', $variables);
return GeneralUtility::makeInstance(
Status::class,
/** @scrutinizer ignore-type */ 'Apache Solr',
/** @scrutinizer ignore-type */ '',
/** @scrutinizer ignore-type */ $report,
/** @scrutinizer ignore-type */ $this->responseStatus
);
}
/**
* Checks the solr version and adds it to the report.
*
* @param SolrAdminService $solr
* @return string solr version
*/
protected function checkSolrVersion(SolrAdminService $solr)
{
try {
$solrVersion = $this->formatSolrVersion($solr->getSolrServerVersion());
} catch (\Exception $e) {
$this->responseStatus = Status::ERROR;
$solrVersion = 'Error getting solr version: ' . $e->getMessage();
}
return $solrVersion;
}
/**
* Checks the access filter setup and adds it to the report.
*
* @param SolrAdminService $solrAdminService
* @return string
*/
protected function checkAccessFilter(SolrAdminService $solrAdminService)
{
try {
$accessFilterPluginStatus = GeneralUtility::makeInstance(AccessFilterPluginInstalledStatus::class);
$accessFilterPluginVersion = $accessFilterPluginStatus->getInstalledPluginVersion($solrAdminService);
$accessFilterMessage = $accessFilterPluginVersion;
} catch (\Exception $e) {
$this->responseStatus = Status::ERROR;
$accessFilterMessage = 'Error getting access filter: ' . $e->getMessage();
}
return $accessFilterMessage;
}
/**
* Checks the ping time and adds it to the report.
*
* @param SolrAdminService $solrAdminService
* @return string
*/
protected function checkPingTime(SolrAdminService $solrAdminService)
{
try {
$pingQueryTime = $solrAdminService->getPingRoundTripRuntime();
$pingMessage = (int)$pingQueryTime . ' ms';
} catch (PingFailedException $e) {
$this->responseStatus = Status::ERROR;
$pingMessage = 'Ping error: ' . $e->getMessage();
}
return $pingMessage;
}
/**
* Checks the solr config name and adds it to the report.
*
* @param SolrAdminService $solrAdminService
* @return string
*/
protected function checkSolrConfigName(SolrAdminService $solrAdminService)
{
try {
$solrConfigMessage = $solrAdminService->getSolrconfigName();
} catch (\Exception $e) {
$this->responseStatus = Status::ERROR;
$solrConfigMessage = 'Error determining solr config: ' . $e->getMessage();
}
return $solrConfigMessage;
}
/**
* Checks the solr schema name and adds it to the report.
*
* @param SolrAdminService $solrAdminService
* @return string
*/
protected function checkSolrSchemaName(SolrAdminService $solrAdminService)
{
try {
$solrSchemaMessage = $solrAdminService->getSchema()->getName();
} catch (\Exception $e) {
$this->responseStatus = Status::ERROR;
$solrSchemaMessage = 'Error determining schema name: ' . $e->getMessage();
}
return $solrSchemaMessage;
}
/**
* Formats the Apache Solr server version number. By default this is going
* to be the simple major.minor.patch-level version. Custom Builds provide
* more information though, in case of custom builds, their complete
* version will be added, too.
*
* @param string $solrVersion Unformatted Apache Solr version number as provided by Solr.
* @return string formatted short version number, in case of custom builds followed by the complete version number
*/
protected function formatSolrVersion($solrVersion)
{
$explodedSolrVersion = explode('.', $solrVersion);
$shortSolrVersion = $explodedSolrVersion[0]
. '.' . $explodedSolrVersion[1]
. '.' . $explodedSolrVersion[2];
$formattedSolrVersion = $shortSolrVersion;
if ($solrVersion != $shortSolrVersion) {
$formattedSolrVersion .= ' (' . $solrVersion . ')';
}
return $formattedSolrVersion;
}
}

View File

@@ -0,0 +1,138 @@
<?php
namespace WapplerSystems\Meilisearch\Report;
/***************************************************************
* Copyright notice
*
* (c) 2011-2015 Stefan Sprenger <stefan.sprenger@dkd.de>
* (c) 2012-2015 Ingo Renner <ingo@typo3.org>
* All rights reserved
*
* This script is part of the TYPO3 project. The TYPO3 project is
* free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* The GNU General Public License can be found at
* http://www.gnu.org/copyleft/gpl.html.
*
* This script is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* This copyright notice MUST APPEAR in all copies of the script!
***************************************************************/
use WapplerSystems\Meilisearch\ConnectionManager;
use WapplerSystems\Meilisearch\System\Solr\SolrConnection;
use TYPO3\CMS\Core\Utility\GeneralUtility;
use TYPO3\CMS\Reports\Status;
/**
* Provides a status report about whether the installed Solr version matches
* the required version.
*
* @author Stefan Sprenger <stefan.sprenger@dkd.de>
*/
class SolrVersionStatus extends AbstractSolrStatus
{
/**
* Required Solr version. The version that gets installed when using the
* provided install script EXT:meilisearch/Resources/Private/Install/install-solr.sh
*
* @var string
*/
const REQUIRED_SOLR_VERSION = '8.8.1';
/**
* Compiles a version check against each configured Solr server.
*
*/
public function getStatus()
{
$reports = [];
$solrConnections = GeneralUtility::makeInstance(ConnectionManager::class)->getAllConnections();
foreach ($solrConnections as $solrConnection) {
$coreAdmin = $solrConnection->getAdminService();
/** @var $solrConnection SolrConnection */
if (!$coreAdmin->ping()) {
$url = $coreAdmin->__toString();
$pingFailedMsg = 'Could not ping solr server, can not check version ' . (string)$url;
$status = GeneralUtility::makeInstance(
Status::class,
/** @scrutinizer ignore-type */ 'Apache Solr Version',
/** @scrutinizer ignore-type */ 'Not accessible',
/** @scrutinizer ignore-type */ $pingFailedMsg,
/** @scrutinizer ignore-type */ Status::ERROR
);
$reports[] = $status;
continue;
}
$solrVersion = $coreAdmin->getSolrServerVersion();
$isOutdatedVersion = version_compare($this->getCleanSolrVersion($solrVersion), self::REQUIRED_SOLR_VERSION, '<');
if (!$isOutdatedVersion) {
continue;
}
$formattedVersion = $this->formatSolrVersion($solrVersion);
$variables = ['requiredVersion' => self::REQUIRED_SOLR_VERSION, 'currentVersion' => $formattedVersion, 'solr' => $coreAdmin];
$report = $this->getRenderedReport('SolrVersionStatus.html', $variables);
$status = GeneralUtility::makeInstance(
Status::class,
/** @scrutinizer ignore-type */ 'Apache Solr Version',
/** @scrutinizer ignore-type */ 'Outdated, Unsupported',
/** @scrutinizer ignore-type */ $report,
/** @scrutinizer ignore-type */ Status::ERROR
);
$reports[] = $status;
}
return $reports;
}
/**
* Gets the clean Solr version in case of a custom build which may have
* additional information in the version string.
*
* @param string $solrVersion Unformatted Apache Solr version number as provided by Solr.
* @return string Clean Solr version number: mayor.minor.patchlevel
*/
protected function getCleanSolrVersion($solrVersion)
{
$explodedSolrVersion = explode('.', $solrVersion);
$shortSolrVersion = $explodedSolrVersion[0]
. '.' . $explodedSolrVersion[1]
. '.' . $explodedSolrVersion[2];
return $shortSolrVersion;
}
/**
* Formats the Apache Solr server version number. By default this is going
* to be the simple major.minor.patch-level version. Custom Builds provide
* more information though, in case of custom builds, their complete
* version will be added, too.
*
* @param string $solrVersion Unformatted Apache Solr version number as provided by Solr.
* @return string formatted short version number, in case of custom builds followed by the complete version number
*/
protected function formatSolrVersion($solrVersion)
{
$shortSolrVersion = $this->getCleanSolrVersion($solrVersion);
$formattedSolrVersion = $shortSolrVersion;
if ($solrVersion != $shortSolrVersion) {
$formattedSolrVersion .= ' (' . $solrVersion . ')';
}
return $formattedSolrVersion;
}
}