From 685f569538643ebe939dceb93cca2eafd5824bac Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stefan=20Fr=C3=B6mken?= <123929835+sfroemkenjw@users.noreply.github.com> Date: Fri, 20 Dec 2024 11:58:35 +0100 Subject: [PATCH 1/3] Update composer.json --- composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/composer.json b/composer.json index 796279e..64ebbe7 100644 --- a/composer.json +++ b/composer.json @@ -19,7 +19,7 @@ }, "require": { "php": ">=5.6", - "typo3/cms-core": "^6.2 || ^7.6 || ^8.7 || ^9.5.17 || ^10.4.2 || ^11.0 || ^12.0" + "typo3/cms-core": "^6.2 || ^7.6 || ^8.7 || ^9.5.17 || ^10.4.2 || ^11.0 || ^12.0 || ^13.0" }, "require-dev": { "typo3/testing-framework": "^7.0.2", From 1f13d39af7e323a3eabac6543b914eb084b3f3bc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stefan=20Fr=C3=B6mken?= <123929835+sfroemkenjw@users.noreply.github.com> Date: Fri, 20 Dec 2024 11:58:52 +0100 Subject: [PATCH 2/3] Update ext_emconf.php --- ext_emconf.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ext_emconf.php b/ext_emconf.php index 68e9b5d..d727f71 100644 --- a/ext_emconf.php +++ b/ext_emconf.php @@ -12,7 +12,7 @@ 'constraints' => [ 'depends' => [ 'php' => '5.6.0-0.0.0', - 'typo3' => '6.2.0-12.4.99', + 'typo3' => '6.2.0-13.4.99', 'extbase' => '1.0.0-0.0.0', ], 'conflicts' => [], From f5181c22b867a15860ac966d7f1331869e71db56 Mon Sep 17 00:00:00 2001 From: Stefan Froemken Date: Fri, 20 Dec 2024 15:20:42 +0100 Subject: [PATCH 3/3] First few steps to upgrade to TYPO3 13 --- Classes/AvalexPlugin.php | 18 +- .../Preview/ContentPreviewRenderer.php | 35 ++-- Classes/Client/AvalexClient.php | 44 ++-- Classes/Client/Request/AbstractRequest.php | 86 ++------ Classes/Client/Request/BedingungenRequest.php | 20 +- .../Request/DatenschutzerklaerungRequest.php | 20 +- .../Client/Request/DomainRequestInterface.php | 5 +- .../Request/GetDomainLanguagesRequest.php | 20 +- Classes/Client/Request/ImpressumRequest.php | 20 +- .../Request/IsApiKeyConfiguredRequest.php | 22 +- .../Request/LocalizeableRequestInterface.php | 5 +- Classes/Client/Request/RequestInterface.php | 55 ++--- Classes/Client/Request/WiderrufRequest.php | 20 +- .../Domain/Repository/AbstractRepository.php | 73 ------- .../AvalexConfigurationRepository.php | 104 ++++----- Classes/Evaluation/DomainEvaluation.php | 9 +- .../AvalexConfigurationNotFoundException.php | 4 +- Classes/Exception/InvalidUidException.php | 4 +- Classes/Helper/MessageHelper.php | 118 ++++------- .../PostApiRequestHookInterface.php | 6 +- .../ApiService/PreApiRequestHookInterface.php | 3 +- .../{DataHandler.php => DataHandlerHook.php} | 40 +--- .../PageLayoutView/AvalexPreviewRenderer.php | 144 ------------- Classes/Service/ApiService.php | 27 +-- Classes/Service/LanguageService.php | 78 ++----- Classes/Utility/AvalexUtility.php | 46 +--- Classes/Utility/Typo3Utility.php | 40 ---- Configuration/Icons.php | 12 +- Configuration/Sets/Avalex/config.yaml | 2 + .../Sets/Avalex/settings.definitions.yaml | 36 ++++ Configuration/Sets/Avalex/setup.typoscript | 14 ++ Configuration/TCA/Overrides/tt_content.php | 78 +++++-- .../TCA/Overrides/tx_avalex_configuration.php | 20 -- Configuration/TCA/tx_avalex_configuration.php | 23 +- Resources/Public/Icons/avalex_avalex.svg | 2 +- Tests/Functional/AvalexPluginTest.php | 8 +- class.ext_update.php | 198 ------------------ ext_icon.png | Bin 13250 -> 0 bytes ext_localconf.php | 86 +------- ext_tables.php | 7 - 40 files changed, 361 insertions(+), 1191 deletions(-) delete mode 100644 Classes/Domain/Repository/AbstractRepository.php rename Classes/Hooks/{DataHandler.php => DataHandlerHook.php} (66%) delete mode 100644 Classes/Hooks/PageLayoutView/AvalexPreviewRenderer.php delete mode 100644 Classes/Utility/Typo3Utility.php create mode 100644 Configuration/Sets/Avalex/config.yaml create mode 100644 Configuration/Sets/Avalex/settings.definitions.yaml create mode 100644 Configuration/Sets/Avalex/setup.typoscript delete mode 100644 Configuration/TCA/Overrides/tx_avalex_configuration.php delete mode 100644 class.ext_update.php delete mode 100644 ext_icon.png delete mode 100644 ext_tables.php diff --git a/Classes/AvalexPlugin.php b/Classes/AvalexPlugin.php index ee704aa..e5e546e 100644 --- a/Classes/AvalexPlugin.php +++ b/Classes/AvalexPlugin.php @@ -217,27 +217,17 @@ static function ($match) use ($requestUrl, $encryptMailCallable) { ); } - /** - * @return callable - */ - protected function getEncryptedMailCallable() + protected function getEncryptedMailCallable(): callable { $cObj = $this->cObj; return static function ($mailAddress, $linkText) use ($cObj) { - if (version_compare(Typo3Utility::getTypo3Version(), '12.0', '>=')) { - $linkBuilder = GeneralUtility::makeInstance(EmailLinkBuilder::class, $cObj, $GLOBALS['TSFE']); - return $linkBuilder->processEmailLink((string)$mailAddress, (string)$linkText); - } - - return $cObj->getMailTo($mailAddress, $linkText); + $linkBuilder = GeneralUtility::makeInstance(EmailLinkBuilder::class, $cObj, $GLOBALS['TSFE']); + return $linkBuilder->processEmailLink((string)$mailAddress, (string)$linkText); }; } - /** - * @return LanguageService - */ - protected function getLanguageService(array $configuration) + protected function getLanguageService(array $configuration): LanguageService { return GeneralUtility::makeInstance(LanguageService::class, $configuration); } diff --git a/Classes/Backend/Preview/ContentPreviewRenderer.php b/Classes/Backend/Preview/ContentPreviewRenderer.php index bc51e63..c4a284e 100644 --- a/Classes/Backend/Preview/ContentPreviewRenderer.php +++ b/Classes/Backend/Preview/ContentPreviewRenderer.php @@ -13,12 +13,18 @@ use JWeiland\Avalex\Exception\AvalexConfigurationNotFoundException; use JWeiland\Avalex\Exception\InvalidUidException; use JWeiland\Avalex\Utility\AvalexUtility; +use TYPO3\CMS\Backend\Preview\StandardContentPreviewRenderer; use TYPO3\CMS\Backend\Routing\UriBuilder; use TYPO3\CMS\Backend\View\BackendLayout\Grid\GridColumnItem; use TYPO3\CMS\Core\Utility\GeneralUtility; -class ContentPreviewRenderer extends \TYPO3\CMS\Backend\Preview\StandardContentPreviewRenderer +class ContentPreviewRenderer extends StandardContentPreviewRenderer { + public function __construct( + private readonly AvalexConfigurationRepository $avalexConfigurationRepository, + private readonly UriBuilder $uriBuilder + ) {} + public function renderPageModulePreviewContent(GridColumnItem $item): string { $itemContent = parent::renderPageModulePreviewContent($item); @@ -33,23 +39,20 @@ public function renderPageModulePreviewContent(GridColumnItem $item): string return $itemContent; } - $avalexConfigurationRepository = GeneralUtility::makeInstance( - AvalexConfigurationRepository::class - ); $itemContent .= sprintf( '

Avalex: %s

', - $GLOBALS['LANG']->sL(sprintf('LLL:EXT:avalex/Resources/Private/Language/locallang_db.xlf:tx_%s.name', $row['list_type'])) + $GLOBALS['LANG']->sL(sprintf('LLL:EXT:avalex/Resources/Private/Language/locallang_db.xlf:tx_%s.name', $row['CType'])) ); try { - $configuration = $avalexConfigurationRepository->findByWebsiteRoot($rootPage, 'uid,description'); + $configuration = $this->avalexConfigurationRepository->findByWebsiteRoot($rootPage, 'uid,description'); $itemContent .= sprintf( '

%s

', sprintf($GLOBALS['LANG']->sL('LLL:EXT:avalex/Resources/Private/Language/locallang_db.xlf:preview_renderer.found_config'), $configuration['description']) ); $itemContent .= sprintf( '%s', - $this->getLinkToEditConfigurationRecord($configuration['uid']), + $this->getLinkToEditConfigurationRecord((int)$configuration['uid']), $GLOBALS['LANG']->sL('LLL:EXT:avalex/Resources/Private/Language/locallang_db.xlf:preview_renderer.button.edit') ); } catch (AvalexConfigurationNotFoundException $avalexConfigurationNotFoundException) { @@ -67,33 +70,23 @@ public function renderPageModulePreviewContent(GridColumnItem $item): string return $itemContent; } - /** - * @param int $uid - * - * @return string - */ - protected function getLinkToEditConfigurationRecord($uid) + protected function getLinkToEditConfigurationRecord(int $uid): string { - $uriBuilder = GeneralUtility::makeInstance(UriBuilder::class); $params = [ 'edit' => ['tx_avalex_configuration' => [$uid => 'edit']], 'returnUrl' => GeneralUtility::getIndpEnv('REQUEST_URI'), ]; - return (string)$uriBuilder->buildUriFromRoute('record_edit', $params); + return (string)$this->uriBuilder->buildUriFromRoute('record_edit', $params); } - /** - * @return string - */ - protected function getLinkToCreateConfigurationRecord() + protected function getLinkToCreateConfigurationRecord(): string { - $uriBuilder = GeneralUtility::makeInstance(UriBuilder::class); $params = [ 'edit' => ['tx_avalex_configuration' => [0 => 'new']], 'returnUrl' => GeneralUtility::getIndpEnv('REQUEST_URI'), ]; - return (string)$uriBuilder->buildUriFromRoute('record_edit', $params); + return (string)$this->uriBuilder->buildUriFromRoute('record_edit', $params); } } diff --git a/Classes/Client/AvalexClient.php b/Classes/Client/AvalexClient.php index 14fa92a..0de1f2f 100644 --- a/Classes/Client/AvalexClient.php +++ b/Classes/Client/AvalexClient.php @@ -17,6 +17,7 @@ use JWeiland\Avalex\Utility\Typo3Utility; use TYPO3\CMS\Core\Http\RequestFactory; use TYPO3\CMS\Core\Messaging\AbstractMessage; +use TYPO3\CMS\Core\Type\ContextualFeedbackSeverity; use TYPO3\CMS\Core\Utility\GeneralUtility; /** @@ -56,7 +57,7 @@ public function processRequest(RequestInterface $request) $this->messageHelper->addFlashMessage( $e->getMessage(), 'Request Exception', - AbstractMessage::ERROR + ContextualFeedbackSeverity::ERROR ); return new AvalexResponse(); } @@ -67,24 +68,13 @@ public function processRequest(RequestInterface $request) return $avalexResponse; } - /** - * @param RequestInterface $request - * @return AvalexResponse - */ - protected function request(RequestInterface $request) + protected function request(RequestInterface $request): AvalexResponse { - if (version_compare(Typo3Utility::getTypo3Version(), '8.1', '>=')) { - $requestFactory = GeneralUtility::makeInstance(RequestFactory::class); - $response = $requestFactory->request($request->buildUri()); - $content = (string)$response->getBody(); - $headers = $response->getHeaders(); - $status = $response->getStatusCode(); - } else { - $result = []; - $response = GeneralUtility::getUrl($request->buildUri(), 1, null, $result); - list($headers, $content) = explode(CRLF . CRLF, $response); - $status = isset($result['http_code']) ? $result['http_code'] : 0; - } + $requestFactory = GeneralUtility::makeInstance(RequestFactory::class); + $response = $requestFactory->request($request->buildUri()); + $content = (string)$response->getBody(); + $headers = $response->getHeaders(); + $status = $response->getStatusCode(); $avalexResponse = new AvalexResponse($content, $headers, $status); $avalexResponse->setIsJsonResponse($request->isJsonRequest()); @@ -92,28 +82,22 @@ protected function request(RequestInterface $request) return $avalexResponse; } - /** - * @return bool - */ - public function hasErrors() + public function hasErrors(): bool { return $this->messageHelper->hasErrorMessages(); } /** * Check response from Avalex for errors - * - * @param ResponseInterface $response - * @return bool */ - protected function hasResponseErrors(ResponseInterface $response) + protected function hasResponseErrors(ResponseInterface $response): bool { if ($response->isJsonResponse()) { if (!is_array($response->getBody())) { $this->messageHelper->addFlashMessage( 'The response of Avalex could not be converted to array.', 'Invalid Avalex JSON response', - AbstractMessage::ERROR + ContextualFeedbackSeverity::ERROR ); return true; } @@ -122,7 +106,7 @@ protected function hasResponseErrors(ResponseInterface $response) $this->messageHelper->addFlashMessage( 'The JSON response of Avalex is empty.', 'Empty Avalex JSON response', - AbstractMessage::ERROR + ContextualFeedbackSeverity::ERROR ); return true; } @@ -131,7 +115,7 @@ protected function hasResponseErrors(ResponseInterface $response) $this->messageHelper->addFlashMessage( 'The response of Avalex was empty.', 'Empty Avalex response', - AbstractMessage::ERROR + ContextualFeedbackSeverity::ERROR ); return true; } @@ -140,7 +124,7 @@ protected function hasResponseErrors(ResponseInterface $response) $this->messageHelper->addFlashMessage( $response->getBody(), 'Avalex Response Error', - AbstractMessage::ERROR + ContextualFeedbackSeverity::ERROR ); return true; diff --git a/Classes/Client/Request/AbstractRequest.php b/Classes/Client/Request/AbstractRequest.php index 86d446a..c4abe5c 100644 --- a/Classes/Client/Request/AbstractRequest.php +++ b/Classes/Client/Request/AbstractRequest.php @@ -19,123 +19,81 @@ */ abstract class AbstractRequest implements RequestInterface { - /** - * @var string - */ - private $apiDomain = 'avalex.de'; + private string $apiDomain = 'avalex.de'; - /** - * @var string - */ - private $apiVersion = '3.0.1'; + private string $apiVersion = '3.0.1'; /** * Is this is set, the required parameter API KEY will be overridden by this value. * Please use that only within API tests like IsApiKeyConfiguredRequest - * - * @var string */ - protected $overrideApiKey = ''; + protected string $overrideApiKey = ''; /** * Endpooint is something like "avx-get-domain-langs" or "avx-datenschutzerklaerung" * * @link https://documenter.getpostman.com/view/5293147/SWLYDCAk - * @var string */ - protected $endpoint = ''; + protected string $endpoint = ''; - /** - * @var bool - */ - protected $isJsonRequest = false; + protected bool $isJsonRequest = false; - /** - * @var array - */ - protected $parameters = []; + protected array $parameters = []; - /** - * @return string - */ - public function getEndpoint() + public function getEndpoint(): string { return $this->endpoint; } /** - * Endpoint 'avx-datenschutzerklaerung' ==> 'datenschutzerklaerung' - * - * @return string + * Endpoint 'avx-datenschutzerklaerung' - 'datenschutzerklaerung' */ - public function getEndpointWithoutPrefix() + public function getEndpointWithoutPrefix(): string { return substr($this->endpoint, 4); } - /** - * @return bool - */ - public function isJsonRequest() + public function isJsonRequest(): bool { return $this->isJsonRequest; } - /** - * @return array - */ - public function getParameters() + public function getParameters(): array { $this->setRequiredParameters(); return $this->parameters; } - /** - * @param array $parameters - */ - public function setParameters(array $parameters) + public function setParameters(array $parameters): void { $this->parameters = array_intersect_key($parameters, $this->allowedParameters); } - /** - * @param string $parameter - * @param $value - */ - public function addParameter($parameter, $value) + public function addParameter(string $parameter, mixed $value): void { if (array_key_exists($parameter, $this->allowedParameters)) { $this->parameters[$parameter] = $value; } } - /** - * @param string $parameter - * @return mixed - */ - public function getParameter($parameter) + public function getParameter(string $parameter): mixed { return $this->parameters[$parameter]; } /** * Check, if parameter exists - * - * @param string $parameter - * @return bool */ - public function hasParameter($parameter) + public function hasParameter(string $parameter): bool { return array_key_exists($parameter, $this->parameters); } /** * Merge all parameters to build an URI - * - * @return string */ - public function buildUri() + public function buildUri(): string { return sprintf( 'https://%s/%s?%s', @@ -145,10 +103,7 @@ public function buildUri() ); } - /** - * @return bool - */ - public function isValidRequest() + public function isValidRequest(): bool { $isValid = true; $uri = $this->buildUri(); @@ -171,7 +126,7 @@ public function isValidRequest() return $isValid; } - protected function setRequiredParameters() + protected function setRequiredParameters(): void { if ($this instanceof IsApiKeyConfiguredRequest && $this->overrideApiKey !== '') { $this->addParameter('apikey', $this->overrideApiKey); @@ -217,10 +172,7 @@ protected function setRequiredParameters() } } - /** - * @return AvalexConfigurationRepository - */ - protected function getAvalexConfigurationRepository() + protected function getAvalexConfigurationRepository(): AvalexConfigurationRepository { return GeneralUtility::makeInstance(AvalexConfigurationRepository::class); } diff --git a/Classes/Client/Request/BedingungenRequest.php b/Classes/Client/Request/BedingungenRequest.php index a040f5e..896b2d2 100644 --- a/Classes/Client/Request/BedingungenRequest.php +++ b/Classes/Client/Request/BedingungenRequest.php @@ -16,32 +16,20 @@ */ class BedingungenRequest extends AbstractRequest implements DomainRequestInterface, LocalizeableRequestInterface { - /** - * @var string - */ - protected $endpoint = 'avx-bedingungen'; + protected string $endpoint = 'avx-bedingungen'; - /** - * @var array - */ - protected $allowedParameters = [ + protected array $allowedParameters = [ 'apikey' => 1, 'domain' => 1, 'lang' => 1, ]; - /** - * @param string $domain - */ - public function setDomain($domain) + public function setDomain(string $domain): void { $this->addParameter('domain', $domain); } - /** - * @param string $twoLetterLangIsoCode - */ - public function setLang($twoLetterLangIsoCode) + public function setLang(string $twoLetterLangIsoCode): void { $this->addParameter('lang', $twoLetterLangIsoCode); } diff --git a/Classes/Client/Request/DatenschutzerklaerungRequest.php b/Classes/Client/Request/DatenschutzerklaerungRequest.php index 13660e2..d129aff 100644 --- a/Classes/Client/Request/DatenschutzerklaerungRequest.php +++ b/Classes/Client/Request/DatenschutzerklaerungRequest.php @@ -16,32 +16,20 @@ */ class DatenschutzerklaerungRequest extends AbstractRequest implements DomainRequestInterface, LocalizeableRequestInterface { - /** - * @var string - */ - protected $endpoint = 'avx-datenschutzerklaerung'; + protected string $endpoint = 'avx-datenschutzerklaerung'; - /** - * @var array - */ - protected $allowedParameters = [ + protected array $allowedParameters = [ 'apikey' => 1, 'domain' => 1, 'lang' => 1, ]; - /** - * @param string $domain - */ - public function setDomain($domain) + public function setDomain(string $domain): void { $this->addParameter('domain', $domain); } - /** - * @param string $twoLetterLangIsoCode - */ - public function setLang($twoLetterLangIsoCode) + public function setLang(string $twoLetterLangIsoCode): void { $this->addParameter('lang', $twoLetterLangIsoCode); } diff --git a/Classes/Client/Request/DomainRequestInterface.php b/Classes/Client/Request/DomainRequestInterface.php index 9e74e1f..d8d4e3e 100644 --- a/Classes/Client/Request/DomainRequestInterface.php +++ b/Classes/Client/Request/DomainRequestInterface.php @@ -14,8 +14,5 @@ */ interface DomainRequestInterface extends RequestInterface { - /** - * @param string $domain - */ - public function setDomain($domain); + public function setDomain(string $domain): void; } diff --git a/Classes/Client/Request/GetDomainLanguagesRequest.php b/Classes/Client/Request/GetDomainLanguagesRequest.php index 48b10ea..b977b6d 100644 --- a/Classes/Client/Request/GetDomainLanguagesRequest.php +++ b/Classes/Client/Request/GetDomainLanguagesRequest.php @@ -16,29 +16,17 @@ */ class GetDomainLanguagesRequest extends AbstractRequest implements DomainRequestInterface { - /** - * @var string - */ - protected $endpoint = 'avx-get-domain-langs'; + protected string $endpoint = 'avx-get-domain-langs'; - /** - * @var bool - */ - protected $isJsonRequest = true; + protected bool $isJsonRequest = true; - /** - * @var array - */ - protected $allowedParameters = [ + protected array $allowedParameters = [ 'apikey' => 1, 'domain' => 1, 'version' => 1, ]; - /** - * @param string $domain - */ - public function setDomain($domain) + public function setDomain(string $domain): void { $this->addParameter('domain', $domain); } diff --git a/Classes/Client/Request/ImpressumRequest.php b/Classes/Client/Request/ImpressumRequest.php index 932c049..9b179a7 100644 --- a/Classes/Client/Request/ImpressumRequest.php +++ b/Classes/Client/Request/ImpressumRequest.php @@ -16,32 +16,20 @@ */ class ImpressumRequest extends AbstractRequest implements DomainRequestInterface, LocalizeableRequestInterface { - /** - * @var string - */ - protected $endpoint = 'avx-impressum'; + protected string $endpoint = 'avx-impressum'; - /** - * @var array - */ - protected $allowedParameters = [ + protected array $allowedParameters = [ 'apikey' => 1, 'domain' => 1, 'lang' => 1, ]; - /** - * @param string $domain - */ - public function setDomain($domain) + public function setDomain(string $domain): void { $this->addParameter('domain', $domain); } - /** - * @param string $twoLetterLangIsoCode - */ - public function setLang($twoLetterLangIsoCode) + public function setLang(string $twoLetterLangIsoCode): void { $this->addParameter('lang', $twoLetterLangIsoCode); } diff --git a/Classes/Client/Request/IsApiKeyConfiguredRequest.php b/Classes/Client/Request/IsApiKeyConfiguredRequest.php index 8e6204f..3b0b557 100644 --- a/Classes/Client/Request/IsApiKeyConfiguredRequest.php +++ b/Classes/Client/Request/IsApiKeyConfiguredRequest.php @@ -16,28 +16,16 @@ */ class IsApiKeyConfiguredRequest extends AbstractRequest { - /** - * @var string - */ - protected $endpoint = 'api_keys/is_configured.json'; + protected string $endpoint = 'api_keys/is_configured.json'; - /** - * @var bool - */ - protected $isJsonRequest = true; + protected bool $isJsonRequest = true; - /** - * @var array - */ - protected $allowedParameters = ['apikey' => 1]; + protected array $allowedParameters = ['apikey' => 1]; /** - * If this was called, the request will not use the API KEY from Avalex configuration record but - * uses this one. This solution is only valid for just this class! - * - * @param string $apiKey + * @param string $apiKey If this was set, the request will not use the API KEY from Avalex configuration record, but uses this one */ - public function setApiKey($apiKey) + public function __construct(string $apiKey = '') { $this->overrideApiKey = $apiKey; } diff --git a/Classes/Client/Request/LocalizeableRequestInterface.php b/Classes/Client/Request/LocalizeableRequestInterface.php index b495d9f..2cdcb7d 100644 --- a/Classes/Client/Request/LocalizeableRequestInterface.php +++ b/Classes/Client/Request/LocalizeableRequestInterface.php @@ -14,8 +14,5 @@ */ interface LocalizeableRequestInterface extends RequestInterface { - /** - * @param string $twoLetterLangIsoCode - */ - public function setLang($twoLetterLangIsoCode); + public function setLang(string $twoLetterLangIsoCode): void; } diff --git a/Classes/Client/Request/RequestInterface.php b/Classes/Client/Request/RequestInterface.php index a32a138..47bc173 100644 --- a/Classes/Client/Request/RequestInterface.php +++ b/Classes/Client/Request/RequestInterface.php @@ -14,60 +14,29 @@ */ interface RequestInterface { - /** - * @return bool - */ - public function isValidRequest(); + public function isValidRequest(): bool; - /** - * @return bool - */ - public function isJsonRequest(); + public function isJsonRequest(): bool; - /** - * @return string - */ - public function getEndpoint(); + public function getEndpoint(): string; /** - * Endpoint 'avx-datenschutzerklaerung' ==> 'datenschutzerklaerung' - * - * @return string + * Endpoint 'avx-datenschutzerklaerung' - 'datenschutzerklaerung' */ - public function getEndpointWithoutPrefix(); + public function getEndpointWithoutPrefix(): string; - /** - * @return array - */ - public function getParameters(); + public function getParameters(): array; - /** - * @param array $parameters - */ - public function setParameters(array $parameters); + public function setParameters(array $parameters): void; - /** - * @param string $parameter - * @param mixed $value - */ - public function addParameter($parameter, $value); + public function addParameter(string $parameter, mixed $value): void; - /** - * @param string $parameter - * @return mixed - */ - public function getParameter($parameter); + public function getParameter(string $parameter): mixed; - /** - * @param string $parameter - * @return bool - */ - public function hasParameter($parameter); + public function hasParameter(string $parameter): bool; /** - * Merge all parameters to build an URI - * - * @return string + * Merge all parameters to build a URI */ - public function buildUri(); + public function buildUri(): string; } diff --git a/Classes/Client/Request/WiderrufRequest.php b/Classes/Client/Request/WiderrufRequest.php index ff443aa..9951c9f 100644 --- a/Classes/Client/Request/WiderrufRequest.php +++ b/Classes/Client/Request/WiderrufRequest.php @@ -16,32 +16,20 @@ */ class WiderrufRequest extends AbstractRequest implements DomainRequestInterface, LocalizeableRequestInterface { - /** - * @var string - */ - protected $endpoint = 'avx-widerruf'; + protected string $endpoint = 'avx-widerruf'; - /** - * @var array - */ - protected $allowedParameters = [ + protected array $allowedParameters = [ 'apikey' => 1, 'domain' => 1, 'lang' => 1, ]; - /** - * @param string $domain - */ - public function setDomain($domain) + public function setDomain(string $domain): void { $this->addParameter('domain', $domain); } - /** - * @param string $twoLetterLangIsoCode - */ - public function setLang($twoLetterLangIsoCode) + public function setLang(string $twoLetterLangIsoCode): void { $this->addParameter('lang', $twoLetterLangIsoCode); } diff --git a/Classes/Domain/Repository/AbstractRepository.php b/Classes/Domain/Repository/AbstractRepository.php deleted file mode 100644 index bb73a4b..0000000 --- a/Classes/Domain/Repository/AbstractRepository.php +++ /dev/null @@ -1,73 +0,0 @@ -getQueryBuilderForTable($table); - } - - /** - * Get additional where clause for a table - * - * @param string $table - * @return string - */ - protected function getAdditionalWhereClause($table) - { - $table = trim($table); - $environmentService = GeneralUtility::makeInstance(\TYPO3\CMS\Extbase\Service\EnvironmentService::class); - if ($environmentService->isEnvironmentInFrontendMode()) { - $whereClause = $this->getTypoScriptFrontendController()->sys_page->deleteClause($table) - . $this->getTypoScriptFrontendController()->sys_page->enableFields($table); - } else { - $whereClause = BackendUtility::deleteClause($table) . BackendUtility::BEenableFields($table); - } - return $whereClause; - } - - /** - * Get DatabaseConnection. - * Only for < TYPO3 8.5 - * - * @return DatabaseConnection - */ - protected function getDatabaseConnection() - { - return $GLOBALS['TYPO3_DB']; - } - - /** - * @return TypoScriptFrontendController - */ - protected function getTypoScriptFrontendController() - { - return $GLOBALS['TSFE']; - } -} diff --git a/Classes/Domain/Repository/AvalexConfigurationRepository.php b/Classes/Domain/Repository/AvalexConfigurationRepository.php index 409115c..82bbe02 100644 --- a/Classes/Domain/Repository/AvalexConfigurationRepository.php +++ b/Classes/Domain/Repository/AvalexConfigurationRepository.php @@ -11,75 +11,53 @@ use JWeiland\Avalex\Exception\AvalexConfigurationNotFoundException; use JWeiland\Avalex\Utility\Typo3Utility; +use TYPO3\CMS\Backend\Utility\BackendUtility; +use TYPO3\CMS\Core\Database\Connection; +use TYPO3\CMS\Core\Database\ConnectionPool; +use TYPO3\CMS\Core\Database\Query\QueryBuilder; use TYPO3\CMS\Core\Utility\GeneralUtility; +use TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController; /** * Class AvalexConfigurationRepository */ -class AvalexConfigurationRepository extends AbstractRepository +class AvalexConfigurationRepository { const TABLE = 'tx_avalex_configuration'; /** * Find all configurations - * - * @return array */ - public function findAll() + public function findAll(): array { - if (version_compare(Typo3Utility::getTypo3Version(), '8.4', '>')) { - $result = $this - ->getQueryBuilder(self::TABLE) - ->select('*') - ->from(self::TABLE) - ->execute() - ->fetchAll(); - } else { - $result = $this->getDatabaseConnection()->exec_SELECTgetRows( - '*', - 'tx_avalex_configuration', - substr($this->getAdditionalWhereClause(self::TABLE), 5) - ); - } + $result = $this + ->getQueryBuilder() + ->select('*') + ->from(self::TABLE) + ->executeQuery() + ->fetchAllAssociative(); + return ($result !== null) ? $result : []; } /** - * @param int $websiteRoot - * @param string $select - * @return array * @throws AvalexConfigurationNotFoundException * @throws \Doctrine\DBAL\DBALException */ - public function findByWebsiteRoot($websiteRoot, $select = '*') + public function findByWebsiteRoot(int $websiteRoot, string $select = '*'): array { // Order by "global" to get the individual configuration records first. - $websiteRoot = (int)$websiteRoot; - if (version_compare(Typo3Utility::getTypo3Version(), '8.4', '>')) { - $result = $this - ->getQueryBuilder(self::TABLE) - ->select(...GeneralUtility::trimExplode(',', $select)) - ->from(self::TABLE) - ->where($this->getQueryBuilder(self::TABLE)->expr()->inSet('website_root', $websiteRoot)) - ->orWhere($this->getQueryBuilder(self::TABLE)->expr()->eq('global', 1)) - ->orderBy('global', 'ASC') - ->execute() - ->fetch(); - } else { - $result = $this->getDatabaseConnection()->exec_SELECTgetSingleRow( - $select, - self::TABLE, - sprintf( - '(FIND_IN_SET(%d, website_root) OR global = 1) %s', - $websiteRoot, - $this->getAdditionalWhereClause(self::TABLE) - ), - '', - 'global ASC' - ); - } + $result = $this + ->getQueryBuilder(self::TABLE) + ->select(...GeneralUtility::trimExplode(',', $select)) + ->from(self::TABLE) + ->where($this->getQueryBuilder(self::TABLE)->expr()->inSet('website_root', $websiteRoot)) + ->orWhere($this->getQueryBuilder(self::TABLE)->expr()->eq('global', 1)) + ->orderBy('global', 'ASC') + ->executeQuery() + ->fetchAssociative(); - if ($result === null || $result === false) { + if ($result === false) { throw new AvalexConfigurationNotFoundException( 'No Avalex configuration could be found in database for page UID: ' . $websiteRoot ); @@ -87,4 +65,36 @@ public function findByWebsiteRoot($websiteRoot, $select = '*') return $result; } + + protected function getQueryBuilder(): QueryBuilder + { + return GeneralUtility::makeInstance(ConnectionPool::class) + ->getQueryBuilderForTable(self::TABLE); + } + + /** + * Get additional where clause for a table + */ + protected function getAdditionalWhereClause(string $table): string + { + $table = trim($table); + $environmentService = GeneralUtility::makeInstance(\TYPO3\CMS\Extbase\Service\EnvironmentService::class); + if ($environmentService->isEnvironmentInFrontendMode()) { + $whereClause = $this->getTypoScriptFrontendController()->sys_page->deleteClause($table) + . $this->getTypoScriptFrontendController()->sys_page->enableFields($table); + } else { + $whereClause = BackendUtility::deleteClause($table) . BackendUtility::BEenableFields($table); + } + return $whereClause; + } + + protected function getDatabaseConnection(): Connection + { + return $GLOBALS['TYPO3_DB']; + } + + protected function getTypoScriptFrontendController(): TypoScriptFrontendController + { + return $GLOBALS['TSFE']; + } } diff --git a/Classes/Evaluation/DomainEvaluation.php b/Classes/Evaluation/DomainEvaluation.php index d2fd03a..8629825 100644 --- a/Classes/Evaluation/DomainEvaluation.php +++ b/Classes/Evaluation/DomainEvaluation.php @@ -16,10 +16,8 @@ class DomainEvaluation { /** * JavaScript code for client side validation/evaluation - * - * @return string JavaScript code for client side validation/evaluation */ - public function returnFieldJS() + public function returnFieldJS(): string { return 'if (!value.includes(\'http\')) { value = \'https://\' + value; @@ -35,11 +33,12 @@ public function returnFieldJS() * @param bool $set Boolean defining if the value is written to the database or not. * @return string Evaluated field value */ - public function evaluateFieldValue($value, $isIn, &$set) + public function evaluateFieldValue(string $value , string $isIn, bool &$set): string { - if (strpos($value, 'http') === false) { + if (!str_contains($value, 'http')) { $value = 'https://' . $value; } + return $value; } } diff --git a/Classes/Exception/AvalexConfigurationNotFoundException.php b/Classes/Exception/AvalexConfigurationNotFoundException.php index 935af3a..3155d6f 100644 --- a/Classes/Exception/AvalexConfigurationNotFoundException.php +++ b/Classes/Exception/AvalexConfigurationNotFoundException.php @@ -12,6 +12,4 @@ /** * This exception will be thrown, if no avalex configuration could be found in database */ -class AvalexConfigurationNotFoundException extends \Exception -{ -} +class AvalexConfigurationNotFoundException extends \Exception {} diff --git a/Classes/Exception/InvalidUidException.php b/Classes/Exception/InvalidUidException.php index 0d3121e..c02367f 100644 --- a/Classes/Exception/InvalidUidException.php +++ b/Classes/Exception/InvalidUidException.php @@ -12,6 +12,4 @@ /** * Class InvalidUidException */ -class InvalidUidException extends \Exception -{ -} +class InvalidUidException extends \Exception {} diff --git a/Classes/Helper/MessageHelper.php b/Classes/Helper/MessageHelper.php index 13b5efa..34138f2 100644 --- a/Classes/Helper/MessageHelper.php +++ b/Classes/Helper/MessageHelper.php @@ -13,6 +13,7 @@ use TYPO3\CMS\Core\Messaging\FlashMessage; use TYPO3\CMS\Core\Messaging\FlashMessageQueue; use TYPO3\CMS\Core\Messaging\FlashMessageService; +use TYPO3\CMS\Core\Type\ContextualFeedbackSeverity; use TYPO3\CMS\Core\Utility\GeneralUtility; /** @@ -21,23 +22,13 @@ */ class MessageHelper { - /** - * @var FlashMessageService - */ - protected $flashMessageService; - - public function __construct() - { - $this->flashMessageService = GeneralUtility::makeInstance(FlashMessageService::class); - } + public function __construct(private readonly FlashMessageService $flashMessageService) {} - /** - * @param string $message - * @param string $title - * @param int $severity - */ - public function addFlashMessage($message, $title = '', $severity = AbstractMessage::OK) - { + public function addFlashMessage( + string $message, + string $title = '', + ContextualFeedbackSeverity $severity = ContextualFeedbackSeverity::OK + ): void { // We activate storeInSession, so that messages can be displayed when click on Save&Close button. $flashMessage = GeneralUtility::makeInstance( FlashMessage::class, @@ -55,10 +46,9 @@ public function addFlashMessage($message, $title = '', $severity = AbstractMessa } /** - * @param bool $flush - * @return FlashMessage[] + * @return array */ - public function getAllFlashMessages($flush = true) + public function getAllFlashMessages(bool $flush = true): array { if ($flush) { return $this->getFlashMessageQueue()->getAllMessagesAndFlush(); @@ -67,141 +57,113 @@ public function getAllFlashMessages($flush = true) return $this->getFlashMessageQueue()->getAllMessages(); } - /** - * @return bool - */ - public function hasMessages() + public function hasMessages(): bool { return !empty($this->getAllFlashMessages(false)); } /** - * @param int $severity Must be one of the constants in AbstractMessage class - * @return FlashMessage[] + * @return array */ - protected function getFlashMessagesBySeverity($severity) + protected function getFlashMessagesBySeverity(ContextualFeedbackSeverity $severity): array { return $this->getFlashMessageQueue()->getAllMessages($severity); } /** - * @param int $severity Must be one of the constants in AbstractMessage class - * @return FlashMessage[] + * @return array */ - public function getFlashMessagesBySeverityAndFlush($severity) + public function getFlashMessagesBySeverityAndFlush(ContextualFeedbackSeverity $severity): array { return $this->getFlashMessageQueue()->getAllMessagesAndFlush($severity); } - /** - * @return bool - */ - public function hasErrorMessages() + public function hasErrorMessages(): bool { return !empty($this->getErrorMessages(false)); } /** - * @param bool $flush - * @return FlashMessage[] + * @return array */ - public function getErrorMessages($flush = true) + public function getErrorMessages(bool $flush = true): array { if ($flush) { - return $this->getFlashMessagesBySeverityAndFlush(AbstractMessage::ERROR); + return $this->getFlashMessagesBySeverityAndFlush(ContextualFeedbackSeverity::ERROR); } - return $this->getFlashMessagesBySeverity(AbstractMessage::ERROR); + return $this->getFlashMessagesBySeverity(ContextualFeedbackSeverity::ERROR); } - /** - * @return bool - */ - public function hasWarningMessages() + public function hasWarningMessages(): bool { return !empty($this->getWarningMessages(false)); } /** - * @param bool $flush - * @return FlashMessage[] + * @return array */ - public function getWarningMessages($flush = true) + public function getWarningMessages(bool $flush = true): array { if ($flush) { - return $this->getFlashMessagesBySeverityAndFlush(AbstractMessage::WARNING); + return $this->getFlashMessagesBySeverityAndFlush(ContextualFeedbackSeverity::WARNING); } - return $this->getFlashMessagesBySeverity(AbstractMessage::WARNING); + return $this->getFlashMessagesBySeverity(ContextualFeedbackSeverity::WARNING); } - /** - * @return bool - */ - public function hasOkMessages() + public function hasOkMessages(): bool { return !empty($this->getOkMessages(false)); } /** - * @param bool $flush - * @return FlashMessage[] + * @return array */ - public function getOkMessages($flush = true) + public function getOkMessages(bool $flush = true): array { if ($flush) { - return $this->getFlashMessagesBySeverityAndFlush(AbstractMessage::OK); + return $this->getFlashMessagesBySeverityAndFlush(ContextualFeedbackSeverity::OK); } - return $this->getFlashMessagesBySeverity(AbstractMessage::OK); + return $this->getFlashMessagesBySeverity(ContextualFeedbackSeverity::OK); } - /** - * @return bool - */ - public function hasInfoMessages() + public function hasInfoMessages(): bool { return !empty($this->getInfoMessages(false)); } /** - * @param bool $flush - * @return FlashMessage[] + * @return array */ - public function getInfoMessages($flush = true) + public function getInfoMessages(bool $flush = true): array { if ($flush) { - return $this->getFlashMessagesBySeverityAndFlush(AbstractMessage::INFO); + return $this->getFlashMessagesBySeverityAndFlush(ContextualFeedbackSeverity::INFO); } - return $this->getFlashMessagesBySeverity(AbstractMessage::INFO); + return $this->getFlashMessagesBySeverity(ContextualFeedbackSeverity::INFO); } - /** - * @return bool - */ - public function hasNoticeMessages() + public function hasNoticeMessages(): bool { return !empty($this->getNoticeMessages(false)); } /** - * @param bool $flush - * @return FlashMessage[] + * @return array */ - public function getNoticeMessages($flush = true) + public function getNoticeMessages(bool $flush = true): array { if ($flush) { - return $this->getFlashMessagesBySeverityAndFlush(AbstractMessage::NOTICE); + return $this->getFlashMessagesBySeverityAndFlush(ContextualFeedbackSeverity::NOTICE); } - return $this->getFlashMessagesBySeverity(AbstractMessage::NOTICE); + return $this->getFlashMessagesBySeverity(ContextualFeedbackSeverity::NOTICE); } - /** - * @return FlashMessageQueue - */ - protected function getFlashMessageQueue() + protected function getFlashMessageQueue(): FlashMessageQueue { return $this->flashMessageService->getMessageQueueByIdentifier(); } diff --git a/Classes/Hooks/ApiService/PostApiRequestHookInterface.php b/Classes/Hooks/ApiService/PostApiRequestHookInterface.php index 0ce07a7..cc059d8 100644 --- a/Classes/Hooks/ApiService/PostApiRequestHookInterface.php +++ b/Classes/Hooks/ApiService/PostApiRequestHookInterface.php @@ -20,10 +20,6 @@ interface PostApiRequestHookInterface /** * Hook that allows you to modify the return value of ApiService::getHtmlForCurrentRootPage() using $content * and all public methods for information about the request. - * - * @param $content - * @param ApiService $apiService - * @return mixed */ - public function postApiRequest(&$content, ApiService $apiService); + public function postApiRequest(string &$content, ApiService $apiService): mixed; } diff --git a/Classes/Hooks/ApiService/PreApiRequestHookInterface.php b/Classes/Hooks/ApiService/PreApiRequestHookInterface.php index 1f82ba4..593d853 100644 --- a/Classes/Hooks/ApiService/PreApiRequestHookInterface.php +++ b/Classes/Hooks/ApiService/PreApiRequestHookInterface.php @@ -20,7 +20,6 @@ interface PreApiRequestHookInterface * the request to the avalex servers. * * @param array $configuration avalex configuration record ['uid' => '', 'api_key' => '', 'domain' => ''] - * @return string */ - public function preApiRequest(&$configuration); + public function preApiRequest(array &$configuration): string; } diff --git a/Classes/Hooks/DataHandler.php b/Classes/Hooks/DataHandlerHook.php similarity index 66% rename from Classes/Hooks/DataHandler.php rename to Classes/Hooks/DataHandlerHook.php index 88a9d21..c9db25a 100644 --- a/Classes/Hooks/DataHandler.php +++ b/Classes/Hooks/DataHandlerHook.php @@ -12,37 +12,24 @@ use JWeiland\Avalex\Client\AvalexClient; use JWeiland\Avalex\Client\Request\IsApiKeyConfiguredRequest; use JWeiland\Avalex\Helper\MessageHelper; -use TYPO3\CMS\Core\Messaging\AbstractMessage; -use TYPO3\CMS\Core\Utility\GeneralUtility; +use TYPO3\CMS\Core\DataHandling\DataHandler; +use TYPO3\CMS\Core\Type\ContextualFeedbackSeverity; use TYPO3\CMS\Extbase\Utility\LocalizationUtility; /** * Class DataHandler */ -class DataHandler +class DataHandlerHook { - /** - * @var MessageHelper - */ - protected $messageHelper; - - /** - * @var AvalexClient - */ - protected $avalexClient; - - public function __construct() - { - $this->messageHelper = GeneralUtility::makeInstance(MessageHelper::class); - $this->avalexClient = GeneralUtility::makeInstance(AvalexClient::class); - } + public function __construct( + private readonly MessageHelper $messageHelper, + private readonly AvalexClient $avalexClient + ) {} /** * Check API keys on save - * - * @param \TYPO3\CMS\Core\DataHandling\DataHandler $dataHandler */ - public function processDatamap_afterAllOperations(\TYPO3\CMS\Core\DataHandling\DataHandler $dataHandler) + public function processDatamap_afterAllOperations(DataHandler $dataHandler) { if (array_key_exists('tx_avalex_configuration', $dataHandler->datamap)) { foreach ($dataHandler->datamap['tx_avalex_configuration'] as $avalexConfigurationRecord) { @@ -56,7 +43,7 @@ public function processDatamap_afterAllOperations(\TYPO3\CMS\Core\DataHandling\D 'avalex' ), '', - AbstractMessage::ERROR + ContextualFeedbackSeverity::ERROR ); } } @@ -65,17 +52,12 @@ public function processDatamap_afterAllOperations(\TYPO3\CMS\Core\DataHandling\D /** * Check API key using Avalex API - * - * @param string $apiKey - * @return bool true if key is valid */ - protected function checkApiKey($apiKey) + protected function checkApiKey(string $apiKey): bool { $isValid = true; - $isApiKeyConfiguredRequest = GeneralUtility::makeInstance(IsApiKeyConfiguredRequest::class); - $isApiKeyConfiguredRequest->setApiKey($apiKey); - $avalexResponse = $this->avalexClient->processRequest($isApiKeyConfiguredRequest); + $avalexResponse = $this->avalexClient->processRequest(new IsApiKeyConfiguredRequest($apiKey)); $result = $avalexResponse->getBody(); if ( is_array($result) diff --git a/Classes/Hooks/PageLayoutView/AvalexPreviewRenderer.php b/Classes/Hooks/PageLayoutView/AvalexPreviewRenderer.php deleted file mode 100644 index 0a4faaa..0000000 --- a/Classes/Hooks/PageLayoutView/AvalexPreviewRenderer.php +++ /dev/null @@ -1,144 +0,0 @@ -id); - } catch (InvalidUidException $invalidUidException) { - $itemContent .= sprintf( - '

Avalex: %s

', - $invalidUidException->getMessage() - ); - $drawItem = false; - return; - } - - $avalexConfigurationRepository = GeneralUtility::makeInstance( - AvalexConfigurationRepository::class - ); - $itemContent .= sprintf( - '

Avalex: %s

', - $GLOBALS['LANG']->sL( - sprintf( - 'LLL:EXT:avalex/Resources/Private/Language/locallang_db.xlf:tx_%s.name', - $row['list_type'] - ) - ) - ); - - try { - $configuration = $avalexConfigurationRepository->findByWebsiteRoot($rootPage, 'uid,description'); - $itemContent .= sprintf( - '

%s

', - sprintf( - $GLOBALS['LANG']->sL( - 'LLL:EXT:avalex/Resources/Private/Language/locallang_db.xlf:preview_renderer.found_config' - ), - $configuration['description'] - ) - ); - $itemContent .= sprintf( - '%s', - $this->getLinkToEditConfigurationRecord($configuration['uid']), - $GLOBALS['LANG']->sL( - 'LLL:EXT:avalex/Resources/Private/Language/locallang_db.xlf:preview_renderer.button.edit' - ) - ); - } catch (AvalexConfigurationNotFoundException $avalexConfigurationNotFoundException) { - $itemContent .= sprintf( - '

%s

', - $GLOBALS['LANG']->sL( - 'LLL:EXT:avalex/Resources/Private/Language/locallang_db.xlf:preview_renderer.no_config' - ) - ); - $itemContent .= sprintf( - '%s', - $this->getLinkToCreateConfigurationRecord(), - $GLOBALS['LANG']->sL( - 'LLL:EXT:avalex/Resources/Private/Language/locallang_db.xlf:preview_renderer.button.add' - ) - ); - } - - $drawItem = false; - } - } - - /** - * @param $uid - * @return string - */ - protected function getLinkToEditConfigurationRecord($uid) - { - $params = [ - 'edit' => ['tx_avalex_configuration' => [$uid => 'edit']], - 'returnUrl' => GeneralUtility::getIndpEnv('REQUEST_URI'), - ]; - if (version_compare(Typo3Utility::getTypo3Version(), '7.4', '>')) { - $uriBuilder = GeneralUtility::makeInstance(UriBuilder::class); - $link = (string)$uriBuilder->buildUriFromRoute('record_edit', $params); - } else { - $link = sprintf( - '%salt_doc.php?returnUrl=%s&edit[tx_avalex_configuration][%d]=edit', - $GLOBALS['BACK_PATH'], - GeneralUtility::getIndpEnv('REQUEST_URI'), - (int)$uid - ); - } - return $link; - } - - /** - * @return string - */ - protected function getLinkToCreateConfigurationRecord() - { - $params = [ - 'edit' => ['tx_avalex_configuration' => [0 => 'new']], - 'returnUrl' => GeneralUtility::getIndpEnv('REQUEST_URI'), - ]; - if (version_compare(Typo3Utility::getTypo3Version(), '7.4', '>')) { - $uriBuilder = GeneralUtility::makeInstance(UriBuilder::class); - $link = (string)$uriBuilder->buildUriFromRoute('record_edit', $params); - } else { - $link = sprintf( - '%salt_doc.php?returnUrl=%s&edit[tx_avalex_configuration][0]=new', - $GLOBALS['BACK_PATH'], - GeneralUtility::getIndpEnv('REQUEST_URI') - ); - } - return $link; - } -} diff --git a/Classes/Service/ApiService.php b/Classes/Service/ApiService.php index f68a17d..5acb2c2 100644 --- a/Classes/Service/ApiService.php +++ b/Classes/Service/ApiService.php @@ -13,8 +13,6 @@ use JWeiland\Avalex\Client\Request\RequestInterface; use JWeiland\Avalex\Hooks\ApiService\PostApiRequestHookInterface; use JWeiland\Avalex\Hooks\ApiService\PreApiRequestHookInterface; -use TYPO3\CMS\Core\Log\Logger; -use TYPO3\CMS\Core\Log\LogManager; use TYPO3\CMS\Core\Utility\GeneralUtility; /** @@ -22,26 +20,10 @@ */ class ApiService { - /** - * @var Logger - */ - protected $logger; - - /** - * @var AvalexClient - */ - protected $avalexClient; + protected array $hookObjectsArray = []; - /** - * @var array - */ - protected $hookObjectsArray = []; - - public function __construct() + public function __construct(private readonly AvalexClient $avalexClient) { - $this->logger = GeneralUtility::makeInstance(LogManager::class)->getLogger(__CLASS__); - $this->avalexClient = GeneralUtility::makeInstance(AvalexClient::class); - if (is_array($GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['avalex'][__CLASS__])) { foreach ($GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['avalex'][__CLASS__] as $key => $classRef) { $hookObject = GeneralUtility::makeInstance($classRef); @@ -54,10 +36,9 @@ public function __construct() * Get HTML content for current page * * @param RequestInterface $endpointRequest API endpoint to be used e.g. imprint - * @param array $configuration required values: api_key: '', domain: '' - * @return string + * @param array $configuration required values: api_key: '', domain: '' */ - public function getHtmlForCurrentRootPage(RequestInterface $endpointRequest, array $configuration) + public function getHtmlForCurrentRootPage(RequestInterface $endpointRequest, array $configuration): string { // Hook: Allow to modify $apiKey and $domain before curl sends the request to avalex foreach ($this->hookObjectsArray as $hookObject) { diff --git a/Classes/Service/LanguageService.php b/Classes/Service/LanguageService.php index cb2effc..126a0bf 100644 --- a/Classes/Service/LanguageService.php +++ b/Classes/Service/LanguageService.php @@ -12,11 +12,10 @@ use JWeiland\Avalex\Client\AvalexClient; use JWeiland\Avalex\Client\Request\GetDomainLanguagesRequest; use JWeiland\Avalex\Client\Request\LocalizeableRequestInterface; -use JWeiland\Avalex\Utility\Typo3Utility; use Psr\Http\Message\ServerRequestInterface; use TYPO3\CMS\Core\Cache\CacheManager; use TYPO3\CMS\Core\Cache\Exception\NoSuchCacheException; -use TYPO3\CMS\Core\Cache\Frontend\VariableFrontend; +use TYPO3\CMS\Core\Cache\Frontend\FrontendInterface; use TYPO3\CMS\Core\Site\Entity\SiteLanguage; use TYPO3\CMS\Core\Utility\GeneralUtility; @@ -25,51 +24,34 @@ */ class LanguageService { - /** - * @var VariableFrontend - */ - protected $cache; - - /** - * @var AvalexClient - */ - protected $avalexClient; - - /** - * @var array required values: api_key: '', domain: '' - */ - protected $configuration = []; + protected FrontendInterface $cache; /** * Use AvalexConfigurationRepository::findByWebsiteRoot($rootPage, 'api_key, domain') * to find a configuration * - * @param array $configuration - * * @throws NoSuchCacheException */ - public function __construct(array $configuration) - { - $this->cache = GeneralUtility::makeInstance(CacheManager::class)->getCache('avalex_languages'); - $this->avalexClient = GeneralUtility::makeInstance(AvalexClient::class); - - $this->configuration = [ - 'domain' => (string)$configuration['domain'], - 'api_key' => (string)$configuration['api_key'], - ]; + public function __construct( + private readonly CacheManager $cacheManager, + private readonly AvalexClient $avalexClient + ) { + $this->cache = $this->cacheManager->getCache('avalex_languages'); } - public function addLanguageToEndpoint(LocalizeableRequestInterface $endpointRequest) + public function addLanguageToEndpoint(LocalizeableRequestInterface $endpointRequest, array $configuration): void { // In customer account of avalex company all texts are always available in german language. // If another language (currently only en is allowed as different language) is not available EXT:avalex // will fallback to the german texts. $language = 'de'; $frontendLanguage = $this->getFrontendLocale(); - $avalexLanguageResponse = $this->getLanguageResponseFromCache() ?: $this->fetchLanguageResponse(); + $avalexLanguageResponse = $this->getLanguageResponseFromCache($configuration) ?: $this->fetchLanguageResponse( + $configuration + ); + if ( - is_array($avalexLanguageResponse) - && array_key_exists($frontendLanguage, $avalexLanguageResponse) + array_key_exists($frontendLanguage, $avalexLanguageResponse) && array_key_exists( $endpointRequest->getEndpointWithoutPrefix(), $avalexLanguageResponse[$frontendLanguage] @@ -81,13 +63,10 @@ public function addLanguageToEndpoint(LocalizeableRequestInterface $endpointRequ $endpointRequest->setLang($language); } - /** - * @return array - */ - protected function getLanguageResponseFromCache() + protected function getLanguageResponseFromCache(array $configuration): array { $language = ''; - $cacheIdentifier = $this->getCacheIdentifier(); + $cacheIdentifier = $this->getCacheIdentifier($configuration); if ($this->cache->has($cacheIdentifier)) { $language = (array)$this->cache->get($cacheIdentifier); } @@ -95,26 +74,23 @@ protected function getLanguageResponseFromCache() return $language; } - /** - * @return array - */ - protected function fetchLanguageResponse() + protected function fetchLanguageResponse(array $configuration): array { $response = []; $getDomainLanguagesRequest = GeneralUtility::makeInstance(GetDomainLanguagesRequest::class); - $getDomainLanguagesRequest->setDomain($this->configuration['domain']); + $getDomainLanguagesRequest->setDomain($configuration['domain']); $result = $this->avalexClient->processRequest($getDomainLanguagesRequest)->getBody(); if ($result === '') { // Error or empty result $result = []; } - $this->cache->set($this->getCacheIdentifier(), $response, [], 21600); + $this->cache->set($this->getCacheIdentifier($configuration), $response, [], 21600); return $result; } - public function getFrontendLocale() + public function getFrontendLocale(): string { $fallBackLanguage = 'en'; $frontendLocale = ''; @@ -127,24 +103,14 @@ class_exists(SiteLanguage::class) ) { /** @var SiteLanguage $siteLanguage */ $siteLanguage = $GLOBALS['TYPO3_REQUEST']->getAttribute('language'); - if (version_compare(Typo3Utility::getTypo3Version(), '12.0', '<')) { - $frontendLocale = $siteLanguage ? $siteLanguage->getTwoLetterIsoCode() : ''; - } else { - $frontendLocale = $siteLanguage ? $siteLanguage->getLocale()->getLanguageCode() : ''; - } - } elseif (isset($GLOBALS['TSFE']->lang)) { - // In case of "default" the TS "config.language" was NOT set. So we expect "en" here. - $frontendLocale = $GLOBALS['TSFE']->lang === 'default' ? 'en' : $GLOBALS['TSFE']->lang; + $frontendLocale = $siteLanguage ? $siteLanguage->getLocale()->getLanguageCode() : ''; } return $frontendLocale ?: $fallBackLanguage; } - /** - * @return string - */ - protected function getCacheIdentifier() + protected function getCacheIdentifier(array $configuration): string { - return md5(sprintf('%s_%s', $this->configuration['domain'], $this->configuration['api_key'])); + return md5(sprintf('%s_%s', $configuration['domain'], $configuration['api_key'])); } } diff --git a/Classes/Utility/AvalexUtility.php b/Classes/Utility/AvalexUtility.php index 7e5ea1e..d33cd46 100644 --- a/Classes/Utility/AvalexUtility.php +++ b/Classes/Utility/AvalexUtility.php @@ -9,6 +9,7 @@ namespace JWeiland\Avalex\Utility; +use Doctrine\DBAL\Exception; use JWeiland\Avalex\Exception\InvalidUidException; use TYPO3\CMS\Core\Utility\GeneralUtility; use TYPO3\CMS\Core\Utility\RootlineUtility; @@ -20,50 +21,16 @@ */ class AvalexUtility { - const LIST_TYPES = [ - 'avalex_avalex', - 'avalex_imprint', - 'avalex_bedingungen', - 'avalex_widerruf', - ]; - - /** - * This method is here to just solve a problem while upgrading EXT:avalex from 6.* to 7.*. - * As long as the cache for ext_localconf.php is NOT flushed, TYPO3 will throw error: - * "Call to undefined method JWeiland\Avalex\Utility\AvalexUtility::getListTypes()" - * As you can't log in to TYPO3 then, we keep this method, but please don't make use of it. - * - * @deprecated Please use self::LIST_TYPES - */ - public static function getListTypes() - { - return self::LIST_TYPES; - } - - /** - * This method is here to just solve a problem while upgrading EXT:avalex from 6.* to 7.*. - * As long as the cache for ext_localconf.php is NOT flushed, TYPO3 will throw error: - * "Call to undefined method JWeiland\Avalex\Utility\AvalexUtility::getTypo3Version()" - * As you can't log in to TYPO3 then, we keep this method, but please don't make use of it. - * - * @deprecated Please Typo3Utility::getTypo3Version instead - */ - public static function getTypo3Version() - { - return Typo3Utility::getTypo3Version(); - } - /** * Returns the uid of the site root of current page * - * @param int $currentPageUid 0 = current TSFE id - * @return int * @throws InvalidUidException + * @throws Exception */ - public static function getRootForPage($currentPageUid = 0) + public static function getRootForPage(int $currentPageUid = 0): int { if ($currentPageUid === 0) { - $currentPageUid = (int)self::getTypoScriptFrontendController()->id; + $currentPageUid = self::getTypoScriptFrontendController()->id; } $rootLineUtility = GeneralUtility::makeInstance(RootlineUtility::class, $currentPageUid); @@ -90,10 +57,7 @@ public static function getRootForPage($currentPageUid = 0) return $rootPageUid; } - /** - * @return TypoScriptFrontendController - */ - protected static function getTypoScriptFrontendController() + protected static function getTypoScriptFrontendController(): TypoScriptFrontendController { return $GLOBALS['TSFE']; } diff --git a/Classes/Utility/Typo3Utility.php b/Classes/Utility/Typo3Utility.php deleted file mode 100644 index b74b62c..0000000 --- a/Classes/Utility/Typo3Utility.php +++ /dev/null @@ -1,40 +0,0 @@ -getVersion(); - } else { - // TYPO3_version will be removed with TYPO3 12.0 - static::$typo3Version = TYPO3_version; - } - } - - return static::$typo3Version; - } -} diff --git a/Configuration/Icons.php b/Configuration/Icons.php index 69fcd64..63cd2cf 100644 --- a/Configuration/Icons.php +++ b/Configuration/Icons.php @@ -1,24 +1,22 @@ [ - 'provider' => \TYPO3\CMS\Core\Imaging\IconProvider\SvgIconProvider::class, + 'provider' => SvgIconProvider::class, 'source' => 'EXT:avalex/Resources/Public/Icons/avalex_avalex.svg', ], 'avalex_imprint' => [ - 'provider' => \TYPO3\CMS\Core\Imaging\IconProvider\SvgIconProvider::class, + 'provider' => SvgIconProvider::class, 'source' => 'EXT:avalex/Resources/Public/Icons/avalex_imprint.svg', ], 'avalex_bedingungen' => [ - 'provider' => \TYPO3\CMS\Core\Imaging\IconProvider\SvgIconProvider::class, + 'provider' => SvgIconProvider::class, 'source' => 'EXT:avalex/Resources/Public/Icons/avalex_bedingungen.svg', ], 'avalex_widerruf' => [ - 'provider' => \TYPO3\CMS\Core\Imaging\IconProvider\SvgIconProvider::class, + 'provider' => SvgIconProvider::class, 'source' => 'EXT:avalex/Resources/Public/Icons/avalex_widerruf.svg', ], ]; diff --git a/Configuration/Sets/Avalex/config.yaml b/Configuration/Sets/Avalex/config.yaml new file mode 100644 index 0000000..0cbd4a4 --- /dev/null +++ b/Configuration/Sets/Avalex/config.yaml @@ -0,0 +1,2 @@ +name: jweiland/avalex +label: Avalex Site Set diff --git a/Configuration/Sets/Avalex/settings.definitions.yaml b/Configuration/Sets/Avalex/settings.definitions.yaml new file mode 100644 index 0000000..4692c1d --- /dev/null +++ b/Configuration/Sets/Avalex/settings.definitions.yaml @@ -0,0 +1,36 @@ +categories: + Maps2: + label: 'Maps2' + Maps2.templates: + label: 'Templates' + parent: Maps2 + Maps2.pages: + label: 'Pages' + parent: Maps2 + +settings: + maps2.templateRootPath: + label: 'Templates' + category: Maps2.templates + description: 'Path to template root' + type: string + default: 'EXT:maps2/Resources/Private/Templates/' + maps2.partialRootPath: + label: 'Partials' + category: Maps2.templates + description: 'Path to partial root' + type: string + default: 'EXT:maps2/Resources/Private/Partials/' + maps2.layoutRootPath: + label: 'Layouts' + category: Maps2.templates + description: 'Path to layout root' + type: string + default: 'EXT:maps2/Resources/Private/Layouts/' + + maps2.storagePid: + label: 'Default storage PID' + category: Maps2.pages + description: 'Folder that stores all POIs' + type: int + default: 0 diff --git a/Configuration/Sets/Avalex/setup.typoscript b/Configuration/Sets/Avalex/setup.typoscript new file mode 100644 index 0000000..53aeb06 --- /dev/null +++ b/Configuration/Sets/Avalex/setup.typoscript @@ -0,0 +1,14 @@ +tt_content.avalex_avalex = USER_INT +tt_content.avalex_avalex { + userFunc = JWeiland\Avalex\AvalexPlugin->render + endpoint = avx-datenschutzerklaerung +} + +tt_content.avalex_imprint < tt_content.avalex_avalex +tt_content.avalex_imprint.endpoint = avx-impressum + +tt_content.avalex_bedingungen < tt_content.avalex_avalex +tt_content.avalex_bedingungen.endpoint = avx-bedingungen + +tt_content.avalex_widerruf < tt_content.avalex_avalex +tt_content.avalex_widerruf.endpoint = avx-widerruf diff --git a/Configuration/TCA/Overrides/tt_content.php b/Configuration/TCA/Overrides/tt_content.php index 9a4a0c2..50519f0 100644 --- a/Configuration/TCA/Overrides/tt_content.php +++ b/Configuration/TCA/Overrides/tt_content.php @@ -1,25 +1,67 @@ 11) -$GLOBALS['TCA']['tt_content']['types']['list']['previewRenderer']['avalex_avalex'] = \JWeiland\Avalex\Backend\Preview\ContentPreviewRenderer::class; -$GLOBALS['TCA']['tt_content']['types']['list']['previewRenderer']['avalex_imprint'] = \JWeiland\Avalex\Backend\Preview\ContentPreviewRenderer::class; -$GLOBALS['TCA']['tt_content']['types']['list']['previewRenderer']['avalex_bedingungen'] = \JWeiland\Avalex\Backend\Preview\ContentPreviewRenderer::class; -$GLOBALS['TCA']['tt_content']['types']['list']['previewRenderer']['avalex_widerruf'] = \JWeiland\Avalex\Backend\Preview\ContentPreviewRenderer::class; +$GLOBALS['TCA']['tt_content']['types']['avalex_avalex']['previewRenderer'] = ContentPreviewRenderer::class; +$GLOBALS['TCA']['tt_content']['types']['avalex_imprint']['previewRenderer'] = ContentPreviewRenderer::class; +$GLOBALS['TCA']['tt_content']['types']['avalex_bedingungen']['previewRenderer'] = ContentPreviewRenderer::class; +$GLOBALS['TCA']['tt_content']['types']['avalex_widerruf']['previewRenderer'] = ContentPreviewRenderer::class; diff --git a/Configuration/TCA/Overrides/tx_avalex_configuration.php b/Configuration/TCA/Overrides/tx_avalex_configuration.php deleted file mode 100644 index b32f8c4..0000000 --- a/Configuration/TCA/Overrides/tx_avalex_configuration.php +++ /dev/null @@ -1,20 +0,0 @@ -=')) { - $GLOBALS['TCA']['tx_avalex_configuration']['columns']['starttime']['config']['renderType'] = 'inputDateTime'; - $GLOBALS['TCA']['tx_avalex_configuration']['columns']['endtime']['config']['renderType'] = 'inputDateTime'; - } -} diff --git a/Configuration/TCA/tx_avalex_configuration.php b/Configuration/TCA/tx_avalex_configuration.php index 6035e92..dde0a91 100644 --- a/Configuration/TCA/tx_avalex_configuration.php +++ b/Configuration/TCA/tx_avalex_configuration.php @@ -5,19 +5,8 @@ } $locallangTtc = 'LLL:EXT:frontend/Resources/Private/Language/locallang_ttc.xlf:'; -$locallangGeneral = 'LLL:EXT:lang/locallang_general.xlf:'; - -if (version_compare(\JWeiland\Avalex\Utility\Typo3Utility::getTypo3Version(), '9.3', '>=')) { - $locallangGeneral = 'LLL:EXT:core/Resources/Private/Language/locallang_general.xlf:'; -} -if (version_compare(\JWeiland\Avalex\Utility\Typo3Utility::getTypo3Version(), '7.4', '<')) { - $locallangTtc = 'LLL:EXT:cms/locallang_ttc.xlf:'; -} - +$locallangGeneral = 'LLL:EXT:core/Resources/Private/Language/locallang_general.xlf:'; $iconFile = 'EXT:avalex/Resources/Public/Icons/Extension.png'; -if (version_compare(\JWeiland\Avalex\Utility\Typo3Utility::getTypo3Version(), '8.7', '<')) { - $iconFile = 'EXT:avalex/ext_icon.png'; -} $tca = [ 'ctrl' => [ @@ -36,9 +25,6 @@ ], 'iconfile' => $iconFile, ], - 'interface' => [ - 'showRecordsFieldList' => 'hidden, api_key, website_root', - ], 'types' => [ '1' => [ 'showitem' => 'hidden, api_key, domain, website_root, global, description, --div--;' . $locallangTtc . 'tabs.access, starttime, endtime', @@ -138,11 +124,6 @@ ], ]; -if (version_compare(\JWeiland\Avalex\Utility\Typo3Utility::getTypo3Version(), '8.5', '<')) { - $tca['ctrl']['versioning_followPages'] = true; - $tca['ctrl']['versioningWS'] = 2; -} else { - $tca['ctrl']['versioningWS'] = true; -} +$tca['ctrl']['versioningWS'] = true; return $tca; diff --git a/Resources/Public/Icons/avalex_avalex.svg b/Resources/Public/Icons/avalex_avalex.svg index 6ce2c3b..3acd9f3 100644 --- a/Resources/Public/Icons/avalex_avalex.svg +++ b/Resources/Public/Icons/avalex_avalex.svg @@ -1 +1 @@ -dsgvo \ No newline at end of file +dsgvo diff --git a/Tests/Functional/AvalexPluginTest.php b/Tests/Functional/AvalexPluginTest.php index 7b1852b..a3d9194 100644 --- a/Tests/Functional/AvalexPluginTest.php +++ b/Tests/Functional/AvalexPluginTest.php @@ -146,12 +146,8 @@ protected function getEncryptedMailCallable(): callable $cObj = $this->subject->cObj; return static function ($mailAddress, $linkText) use ($cObj) { - if (version_compare(Typo3Utility::getTypo3Version(), '12.0', '>=')) { - $linkBuilder = GeneralUtility::makeInstance(EmailLinkBuilder::class, $cObj, $GLOBALS['TSFE']); - return $linkBuilder->processEmailLink((string)$mailAddress, (string)$linkText); - } - - return $cObj->getMailTo($mailAddress, $linkText); + $linkBuilder = GeneralUtility::makeInstance(EmailLinkBuilder::class, $cObj, $GLOBALS['TSFE']); + return $linkBuilder->processEmailLink((string)$mailAddress, (string)$linkText); }; } diff --git a/class.ext_update.php b/class.ext_update.php deleted file mode 100644 index 657c39a..0000000 --- a/class.ext_update.php +++ /dev/null @@ -1,198 +0,0 @@ -=') - && version_compare(Typo3Utility::getTypo3Version(), '8.7', '<=') - ) { - $this->init(); - $required = $this->apiKey && is_string($this->apiKey); - } - return $required; - } - - /** - * Main update function called by the extension manager. - * - * @return string - * @throws \Exception - */ - public function main() - { - $this->init(); - $this->processUpdates(); - return $this->generateOutput(); - } - - /** - * ext_update init - */ - protected function init() - { - $objectManager = GeneralUtility::makeInstance(ObjectManager::class); - $this->configurationUtility = $objectManager->get(\TYPO3\CMS\Extensionmanager\Utility\ConfigurationUtility::class); - $configuration = $this->configurationUtility->getCurrentConfiguration('avalex'); - $this->apiKey = isset($configuration['apiKey']['value']) ? $configuration['apiKey']['value'] : ''; - } - - /** - * The actual update function. Add your update task in here. - * - * @return bool - */ - protected function processUpdates() - { - $success = true; - try { - // create config for existing api key - if (!$this->migrateApiKeyToDb()) { - return false; - } - // the api key is no longer in extension configuration - // so we gonna remove it - $this->removeApiKeyFromExtConf(); - } catch (\Exception $exception) { - $this->messageArray[] = [ - AbstractMessage::ERROR, - 'Updater run into an exception', - $exception->getMessage(), - ]; - $success = false; - } - return $success; - } - - /** - * Migrate API key from extension configuration to database - * - * @return bool true on success - */ - protected function migrateApiKeyToDb() - { - $success = true; - $data = ['tx_avalex_configuration' => []]; - $data['tx_avalex_configuration']['NEW2018'] = [ - 'pid' => 0, - 'description' => 'Main', - 'global' => true, - 'api_key' => (string)$this->apiKey, - ]; - $dataHandler = GeneralUtility::makeInstance(DataHandler::class); - $dataHandler->start($data, []); - $dataHandler->process_datamap(); - if ($dataHandler->errorLog) { - foreach ($dataHandler->errorLog as $logEntry) { - $this->messageArray[] = [ - AbstractMessage::ERROR, - 'Error while running DataHandler', - $logEntry, - ]; - } - $success = false; - } else { - $this->messageArray[] = [ - AbstractMessage::OK, - '', - 'Successfully migrated API key from extension configuration to TCA record on page 0', - ]; - } - return $success; - } - - /** - * Remove api key from extension configuration - */ - protected function removeApiKeyFromExtConf() - { - $configuration = $this->configurationUtility->getCurrentConfiguration('avalex'); - unset($configuration['apiKey']); - $this->configurationUtility->writeConfiguration($configuration, 'avalex'); - - $this->messageArray[] = [ - AbstractMessage::OK, - '', - 'Successfully removed api key from extension configuration.', - ]; - } - - /** - * Generates output by using flash messages - * - * @return string - * @throws \Exception - */ - protected function generateOutput() - { - $flashMessageService = GeneralUtility::makeInstance(\TYPO3\CMS\Core\Messaging\FlashMessageService::class); - $flashMessageQueue = $flashMessageService->getMessageQueueByIdentifier(); - $view = GeneralUtility::makeInstance(\TYPO3\CMS\Fluid\View\StandaloneView::class); - $view->setTemplateSource(''); - foreach ($this->messageArray as $messageItem) { - $flashMessage = GeneralUtility::makeInstance( - \TYPO3\CMS\Core\Messaging\FlashMessage::class, - $messageItem[2], - $messageItem[1], - $messageItem[0] - ); - $flashMessageQueue->enqueue($flashMessage); - } - - return $view->render(); - } - - /** - * Get TYPO3s Database Connection - * - * @return \TYPO3\CMS\Core\Database\DatabaseConnection - */ - protected function getDatabaseConnection() - { - return $GLOBALS['TYPO3_DB']; - } -} diff --git a/ext_icon.png b/ext_icon.png deleted file mode 100644 index 558e56d98c5e4a817e83500ffc1c321d9ada8f4d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 13250 zcmZ{L1yEdJvhLu)-QC@S1c$*xa2?#;-QC?KxNDH$4#C|axVvj`cw~3)z5DjPd#3)= zeY*Q=`}{ z{u2NS3=IJB!GV2z0AP54zurDLfD{=1fAfl9tN`#28S2N<2sH;l{>#SdgZ{nrKGt8% zKd7s#E0ej6rK6#~oiUTGgXxDHA{Xp`V&sDVH(n?g;(z!LJAgW(xbp{rwUbnL1OSlw z{w}a&dL;Z0AJFE?ASaNFG>@UJHIu%Pt${IhOh)n#6DLc4GLVcsiHNO(F$pIV3lj^O02~Pk37>+Hl&M)o(*e_#L1)7Z`Ye3- zzrsFx^xtLuU%}k;?fwb+M>GDJBj4W)c;wC9jIGo~&8>}X96#z2VExR+_mABEAI<+% z_isqh|BC!K&3__AY^`h^l7f4&QR%>QZe zFEAhT-%0tm$@%A4{zLjPmjZAf$p4yg0k~Qb+;jkdIq0h>P}vRaOdG}vvwuOb&hw&J z*hcswFV&M=#vDAK9f$#mil3iPuvUgE>VyGFZqGK7a1?Lb-cX1Y$apg*-R(KD4*Uh1*5^P1i?EXO3-tV8=ZZ6 z-UZ*;SaSE+XQ`|z)s0ZZs;d_wBhWCvYrc}wIfd)x5*)M{Xe-D%y*b$X%JQdz_WNtO zqaHRQm{os^Z5&~HKi|8DLMfHpGu*9?%q6fQ*L6Z(|P|F8^H9aT}N z$iw3#&4 zD$8`Oa~Di`4{j0EOur|i;kA2U-jf)D@e8O2xGSBB>G&qqzPIA4@L{%()(?xTPoiwB zJ;5Ek>SE%{@N1&u9sb4*=AUnmthX{uJ6H~SE;H2ehWeWBNCAsW$^Yf46Lk_tj9>1_ z;Fc|9>u8t1EHsKn&Q+I`pZ9+0tDs=a4d0gI(UG{j9P@>^n*9#Xq>wIh$IoZ|*x#Bl z9=i>pr9R#c2flBitEq&GhbUrP(aydYH}$Tc$Jv}Fdv%m@P&sQsKSOTJi*MfAo7+&g z%C@aR$0|EmlYARTSg0Yt*~WhVc;+fdD*1jt`lcBLl9RbeoNQn*;8W>{?OKGJjBYOo zUA0lZTs`BTp`UMFxQV~0Sm^`=c5Hf<4nS0iP0Oi7eQC{7Lk>oyRV4oOXXhEF1K1(* zP`U_Wv3P9vnvl;|jOxr5>H#}TZ@+(EYYQXnulVxh_hu~Wxox=yWX@E3B9?M9Mc}z; zqrbtijbzGy6*X-!osW>1Ob1prq+q{PrB99GbrZoFRJQc12U$HA=d1?2jPpA|6 z+=$oS800r(8LW6RIcL}wJUbti{cX@!3_B@uaHy82(aa$3`e~B#^VBfJ8HQ`2ib%3J zphpS|>OWoCaI1WNw$8_{Ec1scMQFerb%mi#Fre8g!5wM{S{^^QI74!gtZXS&8yY+G zpc!r*Ew47TB{$m zw2tYn-JAmI5aX3XS0oyG**Kw_SOLF&Viybv*kl-9Ve;NW6O~@@x|CF<*5_@0e7kb5 zS|Wcjw!P7g@4>|HWoznK<5^N7TG`3Y3mW(JI?;4$)1DDyQu7BRn9gpruvFu*R=#aN zY}2j~s_e&KW?f=pp`|n)rF*RMv>&VEIKV^-*V&F+FOZ;sh9JK4+0@A;mpr;FmWOB6 zeuj;s9Eo25k1&X@VJSwi={6fTyJ8$Z5W)hU%oX^J! zl){ZGTP8!Lqzj87i?>klRe)*1kAPjq>1*2?L_>WQ&)9W5Nmqg<%vCSAfIYqJ`kusI zfZVkW_3fg_d+;$~Rw99bpBSZwM z3M!jO?Pkh@lKD^t%8IKK3RX0OkxM-Dv1T2j3K9YNJfD^ExH8H8!c= zhYDSVTV`1bQc9|;T_%Af-#7_^QE4Q?n?<4a3W3B;M6?)_l=~;BX%=KvXiUU6vn3u3c&iwgTz7KRx3yn#@(Ql; zp1nWafj&#(YN%LH37~(gS1zY~iaZ{AO*|!S^S;m4Vw6xf^pJrSFKKOD;H`zWJ=Igb z;oGL?EaSXGQOtN8qT=rJU{ijz^4!Y*q_993EUk4-N_&NhO*k@_v`g*LEun-DPxrBxhanU_PJu*L`%V`m(8+&8cb{)p<@gRboA>2%n)X- zbOk*>-N;e#iOVw8Mw2Wt5BLE0*9zNLvYJ(2ImOZO*F4eAqm0{O=F&$n`~A)k_DCsp z^l=*+j!Zre!MXl~QU-$*uognFy-<10$IQl}O~$-n{5YoWsor1btjZZFq#RKZCYka0 zMr1M--ee$-`7AF3In4Xxw4L?Pevw}x`9aU#k19ZfO_Wc2FKU6kAQG>r$!D-=6vt>x z@t_5c)JriwnU0TBBp7UH#P$gh1Oy*hkI=)_=iyZ}kA#FH#FqXM$fX^cU&(;oAcaiT zVR30_`;9~)7lbMXx{9Sw1~e+;5xbd#=CFZ-g|6Tm=6sIAaWoQp&et%PgsEB+vdBwT zq`;>-5@DR=86x2}J~K6h4oc+o&&>$d+_GIs^oa1n#?zL=Mg`@jNwzjeSq!nI4kI*l zA8$rbBlKat7mRTz4Sda2S`KW&wIiO?FmcY$6AseIG!Ee~T%AJzjvoPG2&Jw9D|`*) zZZ#U)e5SmPQ}M{qGYly*sc+nsgDyU$VLFhvQ$!k5TTJqV;DN`cZ2aY zWCroJlhfS=oV{DFh~9-vri5(aTb`VMO^@>UJUXDIv?j%joCcqq89l6&4Dj1-FhA21 zKGN>It_GRp6G?cWh&Xj4y8ZAZ0$t8bLY95%jU!P!uc|{9o`pUiYZ=INvumUoS%Gem zgh2GiMJJFc@gBq|EGLgUozNNm4YJH>`SXncO{}0|iK6Qi*kiJ?A-`nFRb1a*4aLr% zTAmS7-!Vq}dhn3cobSK~Io#$X4xkA4mwe7m;d(J5%-Y-(riPWXLM;{-ZI(MZ%7F&U z8u-3~*^TNlI2{|Z;=`_E5eVJK3MwR)3VcMq0&j9?r2GMcgg+B$sE6E!V{uwYHBKI) zRWL0DWf3Q^0Bmqy=5cdju|BLJgKT0d%^7v zn9C~KS^{ju_dp^k&=)oS8}@N@{ru9>3p|Np1W;%t^YpfJ{qxiOVZ(D7Mnv{k$~_hY z1)k#8ehyX57CBuHPt3U(u%p$BB&uG<(ZF6ruYq^_$9E`byZwtshg1`%KT)@@n{=k= zohpYKI6TL0x~F+S$@gyVcKc4yE9?#JbnB@ z@m1il=Tg)YUx%VI3Fx+7_}ue#NvGVI6}}`Uhud$(h05QpyQ?NBE%GNcpr6N6L5InZ z*ij_U;Z2i1#T<{e$$zE@r3rQlv%m{nez-umb{s?4Pb#x$ezbmm71revu(K!t@53}`uY0}{|`UU%Beyx};qf$9vnmqV}s|Lcc0)q`TLui^4 zAGK#;LA}Ls$t<2bgcQ1sWD4^L(~?Fe8>j?1GF|BZqAV*)$A(cyfS!2!kV zi}a}qFZnjc=`~rD=HkhLB8$qvQL^^a%>;F9kF`L2JLjejjgCh8R+KTykg!ZE5Rv1U zHh{X{qx==B*VOdogy|g&qOYOino6tcsqaO_j4YSJ7r+yGpu zf=_2GioL8I$~+RB%fo&3Bn$3;^c3uQa{z{Rk&MzK7_*mS0b3FMf)#Olmwm@Od6`ZU z+q>AyZq9qXIeGw31&EvZUPIUW0`{L%bv&fMRA6NWGx6(+%9d?hcMd{(WBvrXln*d) z_jqtBb1CEAEcEo87zETcwxO^V2;ixSQ_4MXu^40uZ1rXK4DEKeeCH~csHNFcZ1%NB z!v5h5OzQ0AvpPt@(ZHJ)y{d9cJPtb$!#?yPDyMzgW<1%Xl~2OZPs>U&zQmbpId^-9 zze}zW8L@T~YzDl#8}@eKTf=up$Q7^u-QUSqo%lgwt`L^W?1>(BBEDQb^_I3oDc!V9dvGyBv^th)ud~#J?_RsT@q1;LrAo&) z(r4AdKu6T>2Qb2Wa>O>2(p}RUR9t-z_pp%%Pb+bjChKP!;Tkbp)kkMQkiwiCjnyP3 z!w#x+3-pL!Im3P>sZ12vHS-!=zD%gR)0gxBW^4b3axf1{ZY?2`R81An(g`Lozs=x; zbTA!HhNP#7q zm8l0bVnGu65=hr%khLFQsdaR%RPr1+EFqvMa8zXx$@Gt3?3pW|LBnEd7;0URsPcK! z&to!2o{Qs?@M+2-6!{UtDH#7Y%6MnIB|<7sEoH{sYPshE7SZ(NOnlvKS{+nZ+k6y; zx$RV5He7(g)kTdxJn^@px(lqADjx34d1UF`pfPR7rmk-C`NW{(O~=K?X!!eesW($f z=#L2dmwR*J^EJg|DJAo4PqnedbQr!tQC?O_+bQu-mTDmFDJ z1#wbi1?ccY#>{zI9P8=Ee(#Tm)xg{tsg#PnK*52km$MC1AefX)4;`o(cf{l66hQ|0 zWi%)2C4L^S!aBNRW9|*p>~c1ZY3In0_Qw)vZtKxYObwRAzw(|RKond4gOQCj>+w7| zSG82h7Dqd3M%3#}y!tF`rgoUP72b%aaP2|^S^ct8dhL#5u}9`->?;1^E^*H7QLWSS z&FAI`WhmUq!4yeQbykA+uKEdUWdRM$_9~Ftm{VFIeiuuj=1eYt;6d2yAl)DtL0P7( zxh0^h@QJ4+PM>WOuPhtJ%MfNEuoaIsqJ14Z%1Ouvws)$!-Y*@@VZolxys4mrFLKGh zkqtrrj|wX*_G42#RO$!-KqgPt!THcmF>cpIPZZpJ3Mpp$Np+kj5)ru*_$AC-qx%kz za+KkwbnOPQJc2bxtRq~V_1P$qUCd<%9 zVH;$A(|O+K+V>^vF3^vtB7@APsd5M{ei$7I*NZC(6JI%0@q@HG79$zTt_S&(GTm=Y zVY&^(dzJn`T4L)mK^JnYpEmb4i>o;3 z5ch8GDc12@xlS^b_cRrTN2|DQ1Y3HjkE3&5xWCGq?AH)($jI89IX;XPOnyCVnZwnX z&cx`C?Fc)#7rQ;M8{`)p+js6%vdEk{ZxIkP6LXtqQ%36i&1$Ge*e!$Tw^-*irsc=# z7PGizAy-k><>hlj?cm43t=xH5Ptb!LC@5sAn{;y2y+W%V?k&O;<*7!adkb1wU)H2)4qGT`;Ki4w7Z!Z7EtMj-(jD&=8AN{Y==fp%%yYpfh< z-8(kHI+q8*WN%jD-O6AT;fRo0qM7EvRv&WtQRGUQPaj}Xzz zLH*{4;0r25Zi}h7m2c#W!}moY9q*u7(P?#t*@`c^LGeFhOXaJASLrrt|7au%wSS@` zwb%oUji5}%&hw=Sx}a?KNy9CaU_Npu_mfB3MO9r}BH&>j>2xq=4Lk@k$%Ix-hYdJq zp%7%M8c2u^ppdW5&R|#A!WlhwNsWBU^FCnuV)*KUl>$5?)n8y>DT2c`0<_8AtxIjB zb=oVjtw4^`rmr9zdthr2g0_75%6vA{>_ZQPgkA45yJ6qAcN=dOryvq9yH*UoRy1eR zfeeaf{!A%%=Nlf!nG1Bp|4os7HcWAyYS5+t3z6ZjJtKQGV$3F9E9=i$e>&Ht;jJF->#8-6% z&%M@5Ho6t5=vBV|ECg#?=;1hq-RL+!fiQiIOjI1>aqsjPncTcjewCnA6~B)<*USzw z%1=uRf-DW9-&Mb9)T1m>Uh3u{FcUO@n(+i>HQfzZ88jcB(V2d$*NAVZLM$@N5P(fY=BVZd;T-`IXxZb3Qz^GQj+5>6%9zmS3b3K8))@VC#z z(~u1}V77e44^^3r=(**-i!Ln zD5vV5zF)GebHOHQ%uvKJna0oSKy}`E`$3FFsJH95bPbC53CNft)lj1r=vETp|zCtHrMm*iHs$R&n1Ic3PR2YiMFCer+fB;q7F^GVdkX%sb%>n0{Zirl3 zM`J?!X|ZlEcL1S;u!q_u3zqQZq2lVcPJoH*r&sW`u7Pp}!|QzNl*y0ZzL9b`?fDwm z8J8nv;XryE2A|#rHXf%TgvQ(!6iu8PxeVUYXizC@;N{G>kwKY2W5t}s1X)Gl2 zJ1rIPofnBll{^@>wq>$6E(e{TH5e&jL+bH$Q>;?L!?)`E!UdTldlc#`tJf-y8f3PK z^Dzy*+bmkZTWag(m~Zp4U%sJrR{)LMNAgIZ0asSY3GC9{J$+nPQZ~G{xv_nx7GUL~ z_u)c$*Pq2~0>bx*P*@QH>;az!3_JA)U*dbWWWgSDF#X+aP(r=N-~z8WM(mSIn2ixF zeGaL-u)aC(Gq?!AWSphGj^~6~Db*VS8PcX51Ya)Jja~s@edgX#mpJN0~mI;W><`-&(KTn(C2 zHuuAw%ZRezQH+tLGF~zZpXyU2jVDtQ7Nh|^JsGeA9VyOWFzmcXWY|Ou6W!-7&_1qM zw{P|a6b`B4>blhPEZ*vrNSw<&^N%{~q8&zsFF~nU`VpPrWE*9V0jzq`nwYE!6Ws^J zQO@+<-!o1y+A%|!JyUr@^gJOovE&SRMk9x85S-P*H(Sm|TWG_;rubGa(P8yDQnTYG zZo^r6#^Y7CzvSiglq0#gM4Bnct|O5_v%WpbGu45!br(UM-?xYLmh09hXP;OO(!2II zDYJEr5vBcU=l-2Wpn086wG8QAts?q7$9kdV%pL&7XH-=}bH(LNXE7S2m0K}mcUDy> zRU<86amRXq#+y}qw04=jl{Iky|UTB0P=M&yJIJ6`IRPjHQ_io?SbvNrW|UCK0l?A5;8%#Mu6d4~-Ki zZ1A~0zt};`=7wr$Xk3G|aNI*m zm~he9i!g~UB4G^qbwfb4MZY8p8^{_GZV19OcA+9befF!_MQDltyywBts62=kg}yl9 z%07p`8`gt{3?se2ixn5*>__GsA^Jj?Ax(bxaYozgKcnG*kZ$568>{kXrv6E|9dsD~ zH+@utA8r{wwQGWBDf%~IE6oeZ!3_x%c=*$(GiQ*iD$1d(R^Mn3+Kv&lNgzOu{r9)D z13RvI*L)-?4wh$jnLbJPM(c80c23H4cx`%j;9&2Ws-scp0kg^Q8MPzBt&OEYwy2FZ zUZmer-grt>!Fd^qc&j@XGFP&_zF2)u?O=&&z=Ci{%)wf_HRWF+>FtbfhL}HLxRvSe?I)gwH+h zmiIxi0)|rS9)4x~?CCpPT?jUmT6{sNe!6;7h9<{f)rJ!_#V1<%llC&Qko7z*X5*%6 zwG;`YDzXGx{Y)phC-LQCFn2~Lny0fcoVGqkV)%nCduq^7u>X0fT*`GXY3NRS90096 zD}?Hg`_4ILkXaM1^V7uhqELL>`b@@~Dym6dvjW9Ps|FOqfNwN|&XnFM;sQVv`N z{ncpQi;qZF;pg+~;>1IT719&T9&QVIr#(Upew{1Q$bffQM`H9~uoY%?Z7HN{g#WdB zl0Alv%D6Y7HfyllBT*HRerjaogE+>lXSfG<@uslslS%}b;nsk<$n@LtEu5CT=RqTR zj71o5+!ye3iTV3)DL38j3OAGRL4gF{NO=?pA@JQyFMAv~JoVW9MovTu4@mJvj@xDq zE@fn11HSy2KO}%1_g^cVzVJhk62G{8X@=g%8rXJfWHOh;dI!Qu&J)MDT2-tTEJE*k zXTcu#t=*|MIB@L#7#Qn(51752SAkW)ETDS|QDSwIm`B@~s_!;=w+?R`$2{*~CH}pt zzDu=97Kzj-APm2i(sOFrTNy1n#-LY?K(fz)f_c3|NqrbcUtdcJ6YFdDd^yp(2sLZ;%cGJ!!Tm$u_?1TS@xa2`NrYU=v9_|aSboXUEg`NoJ=*)S(BBx#y3LJG5M{Bz zw`!jg1K~!{>_v1ob4K0CMKF0^?sAUa?$XWKZ{Rk$(#>BV@if%A-?3=;ke#;OA@ic? zxxs(#-&D7fBdu#W#cvRZQ*~4o>X;H3yH}-c*W#-mR)w$aswNoW_$B5sf1f8k_X~oq z@@ept%y}yO*^j5V6$3TU@pKo(DNXgr1)vJvk`l9KI%tU>zYb>skogKuz`OSMoYeCt zNB33?r&~awXN)L4Jv~j*^Jizr!jl4Dyk@ulld4XW5g#TR<`Gd18?OLCzvdpeGo&Bu zmbxgLnLCvhj2;t>AVdu?oZlB$VWcSGeo>uWj8SLb7+OEdl98NkLT^J3aauwbaDBB-;DVsruGp(5mFu z`w0%!CPRO2H~v|YD-9w=kd<&`)1Va-pLN6#)j}ft8kBiVIwPpE(ygGn879c_h<+2N zur|ArkuRdAkPU1(6DQ)b!Qr0IMz#eWN_6sxZ(p$a@^E{3QV?<+yLaAt8##UQ+Lx1j zAxqQiGt@|*wh}a2Mb)^xfV$1*v%xBGFJ(&bisP5IZ2> zbv@HV)oiCfwTn&9n{sQJbz^E2Ig`>T=?1>P>{_(N=uLBGpM%h#sjrMGSp`gisRo^& zgt!Y=SieCbNxdvJabL7x+iiAszaOvnkYQL(f@zrF=gvI2STR-FjKh!TWfi8FNg-_R#cdIo*eoscT zXO|^NMh}7ifZzby%dHfNJ+>x3?>V|*ZtCp54^C+%gxq?cdaf^?6aPg!f#{Q$75SQdKCO;JWL&?DMvMd! zmd&xw!*LwA;?dJ7z4#Jum>TeA=Mj)5tdS#9?5_D7dY^I(GMwJL;gY~6i68v_CP~07 zuKUYaBe2t=hWoNAfFT_ME8u8&K4!g6Rx^3L_Ob<^k?7<)Mu05e;(Indza84y5xr_1 zQM*fyWI6uF?;|-HPL^WsU591f+dj&-1JB3$Df9z02j(=#N0HHPj%A+FIz!FeZf$?^ zbe6Kt!|(st<8tBHC?6`lBF1m7V|l|nBY3>f4!f!++ow#Ahpz}@$wHl+uFbvzG?b#x zK`G#xN6;QjHq0*+#Y$1mgv$tWu$8lO&%Il>o?sne4t2%6)Q*RqX66C}umyh$21MiEkN#QUjLY+7*Q*$X4o0&bKj-X04Bi&@;Wi<$9;01lCsiZi(Topi{naf?zo z5i_zoJH!|tw$7|c(#25z=KjMgaffC`Q zkT);fQ8vZMCQ1ers5&StDvx>}X^5ot_Lm zlRhxdgzV%@006|hiX-t4R7p6^)6$j`L%xLHh%D40l)SYuoc*s62zg^aK1fLA6 z+6Kyus9yxT1nM#LWGo-D=%XKy069&|hs+Ej{m_!Vj3GTx4%9ISm^Bb*#e6bkq(7N0 zJ#mm2^7Pfjh!n@9x8;V2?X+k!KiIU(k^0h=@0>r81mdy z*CCgmA^RYg#LPCJAKATL9*%65q?z*W*hTSF@jN`(lL!BRY^sC5hr`iZgTvRrmQLb#Ta3Mb6539rQM6z7^V1u#Ytc% z{vZ?;eUk9&xv12+8T*wS)8!3oD1Zo2m%Jf7o!X0m-CdWzfDT#>iR$epu20e#{2Sz` z3#p-rf>pti2IqZyHBc+_6c+sF&OG#PhKSC|7kEodv|^kS$`F`lK-s*uZGq~+y5XX%$q?twg(luIu`%{13HUV8}Zj+Ph@ zH-s>mtHH`&q?Bj%OzccNO;9k?Xt};1V@p}uEmBeU>JoBmJ(e8nSMt~m2r@rHTT*jM zdL2D4s<6|%SSIMozCqIP$l}Ay=lbNg>Ojkzj&AH)5WJ2g_Ix5ZEl2saLmudhbz}w3 z6HFb9<}*29jP$}J$h(WHh=HDlqu5LUZy6S~&d_XHmVIA$ytV8!=O2Asg|8sN(AYfR z2aY|#G_3(F2}A#F4iV2BLU)AT-Ka;Z_Nj$jFH{fr*QmC33$7VrQvgi#aoBfMcb8uC zD2Wg;+G-D31~We8ZMMY$pTME`z*7o1ee$oB{em7Riebmz~h${nomYz z8l0r8<#OBQPZ;+w4aQ?W&J$vHn6ipizi3omV_|!KwVU#PCT2>f~v{O#pR{5@F7+xL?y z3+Ug5+XLe$ZFIxbt4%s~>_)uJ!)kfY z-EG7@KKSh$Q8(~$V|z^ur5!NW8mnydiBO4-7k+_>$3p{TY={Sg4egIMR3md<`KI%! znS{ui$nd^4q#YU|++MaN>KtD)6WDllB!51EVii6)Sw5_S^WB_vDEJ=bg_4I=9do6Q z?{!TbTX}*~w=t&E7v&~iEyBX|)bnZUODftm`E$=>3)B4QV~i)?y;DFA@*ub+(ds%& z3!2V*i5|npiR-ce9hpqR{Fuf?;Kp(@&DZ^!uvZXV+E_Hze)g0<@O{A36L$?S@M1~K zh+47PY5_I#sX3eBrJ_3y>l9dsvobu&8q;0;N^^zWlOqof&xG3Owla>}3Iyq8_^LYy zE=_qaqMvxnpCYE*-OIhntHR~pQ1H7@Z@qLscGgdGQ7A@Eqr))fK3~DCOMQrAY{Tnf-YK)@#|doI1%#yJ`iPfu|GGTIbbQv_3j`| z`ksJl>??^-o-l_nYNFD09VB{W&J9&crskeJgr5P$I97+&fXl9NQA2>XqP&SvC^xNI zFrA{ehYUi{h&>zQY<{2YnD==-9v=tgWl@*#w&|qJXDSax^kVZXeRZ)=jt4)aG|$?M zY^@qw&c@{i%*aIFzS~>em7)pGtZxgX%}~ekW>)Qkbv*iUnkTom; z${|`jdFMJBJGe?4>Y!4avxW~j)a&mOT>4WqJNAn!x~(u}|Jv^`xvVX$7Pba_wC~4B z4ofQO{@E^{a?NlVjL^PeStnEiD93a!L22gne(R5X4?|z+4k;Ccnoi^6vQI=F>_ZH0 z<>&ivJo+7^T0g9T36D`uU;0Yf;5Ld5-x z%8CLh%Fv$(iPJD_UI21o(7h6jisA|@rLJz*zOsRaG=1CeWPL7;%95DWw*8RmB`kH+ zMzt56s0JU$aNCAk-UscNvr)dr^mzIVxhNR_Uf=Z+$-C$-ZvNUz!BOb2xL!p*;&*c* zzpI-s$_7lw8*_r@u**Z)cdB(}x*|pT^rA}bWkh&YacI zhfsy=h!pvx^$S{tEb0d7A4`6e*!YaGhHnRHD!XOl1{3xj7%J6eYPodZ!n5u62g!inVt00= zoUG9k&46ffiLAQa@o|o*0n-{jrha#Li6~R&T$Vq?mI!6ql2<5XtN?$%mDMnZvDcId zHtkJhcvM!Dtc37#N9C-e+XGW!8?>*@AN99x+#A|l=`UAmZEEobS zROgOyT4}X?Cas0OdS1Uoq|ip=XvY!r9`96_p2w*1hcyw^-6E$YcR3F69%L%$V6bLuyGoVYk-byN-Rqj z*)SMc;ltPOQz_@aq(*TMIXEi8{EgnlUqJIsqLj;8H$3R* z67h@e3kQQ6()6N#lO|SxcVz9?A3Y4s$Mj*e${z|cl!AW=kq2LZ--vgOaLcsX%zp*J zmBZ#el2d*6%*z%NISutY?V0LFl+Lp$niM4;+oT5B%JUU%+odjnxF1rjNJgPeA0G!( z1V&;(_Xjw3D4FILIYQsp*fbZ(z01Cu9w(x5e!dwN0%Qz@M$D1CON)a6U1|jukmIxY zsZTW@;ql{qGWN1y7g6ls(r?zpaDMs)yz37m?a)DmOE|HJ5_awqp}VT1h62')) { - // Use IconRegistry for TYPO3 versions up to 11.4. Since TYPO3 11.4 we are using Icons.php - if (version_compare(\JWeiland\Avalex\Utility\Typo3Utility::getTypo3Version(), '11.4', '<')) { - // Use IconRegistry for TYPO3 versions up to 11.4 - $iconRegistry = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance( - \TYPO3\CMS\Core\Imaging\IconRegistry::class - ); - $iconRegistry->registerIcon( - $listType, - TYPO3\CMS\Core\Imaging\IconProvider\SvgIconProvider::class, - ['source' => 'EXT:avalex/Resources/Public/Icons/' . $listType . '.svg'] - ); - } - $elementIcon = 'iconIdentifier = ' . $listType; - } else { - $elementIcon = 'icon = EXT:avalex/Resources/Public/Icons/' . $listType . '.png'; - } - - $wizardItems .= str_replace( - ['###LIST_TYPE###', '###ICON###'], - [$listType, $elementIcon], - ' - ###LIST_TYPE### { - ###ICON### - title = LLL:EXT:avalex/Resources/Private/Language/locallang_db.xlf:tx_###LIST_TYPE###.name - description = LLL:EXT:avalex/Resources/Private/Language/locallang_db.xlf:tx_###LIST_TYPE###.description - tt_content_defValues { - CType = list - list_type = ###LIST_TYPE### - } - }' - ); - } - - $wizardItems .= ' - } - show = * - } -}'; - \TYPO3\CMS\Core\Utility\ExtensionManagementUtility::addPageTSConfig($wizardItems); - - // Configure frontend plugin - \TYPO3\CMS\Core\Utility\ExtensionManagementUtility::addTypoScript( - 'avalex', - 'setup', - 'tt_content.list.20 { - avalex_avalex = USER_INT - avalex_avalex { - includeLibs = EXT:avalex/Classes/AvalexPlugin.php - userFunc = ' . \JWeiland\Avalex\AvalexPlugin::class . '->render - endpoint = avx-datenschutzerklaerung - } - - avalex_imprint < tt_content.list.20.avalex_avalex - avalex_imprint.endpoint = avx-impressum - - avalex_bedingungen < tt_content.list.20.avalex_avalex - avalex_bedingungen.endpoint = avx-bedingungen - - avalex_widerruf < tt_content.list.20.avalex_avalex - avalex_widerruf.endpoint = avx-widerruf -}', - 'defaultContentRendering' - ); - // Use hook to check API key while saving the record $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_tcemain.php']['processDatamapClass']['avalex'] = - \JWeiland\Avalex\Hooks\DataHandler::class; + \JWeiland\Avalex\Hooks\DataHandlerHook::class; if (!isset($GLOBALS['TYPO3_CONF_VARS']['SYS']['caching']['cacheConfigurations']['avalex_languages'])) { $GLOBALS['TYPO3_CONF_VARS']['SYS']['caching']['cacheConfigurations']['avalex_languages'] = []; @@ -88,17 +17,6 @@ $GLOBALS['TYPO3_CONF_VARS']['SYS']['caching']['cacheConfigurations']['avalex_content'] = []; } - if ( - version_compare(\JWeiland\Avalex\Utility\Typo3Utility::getTypo3Version(), '10.0', '<') - || ( - ($features = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance(\TYPO3\CMS\Core\Configuration\Features::class)) - && $features->isFeatureEnabled('fluidBasedPageModule') === false - ) - ) { - $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['cms/layout/class.tx_cms_layout.php']['tt_content_drawItem']['avalex_newcontentelement'] - = \JWeiland\Avalex\Hooks\PageLayoutView\AvalexPreviewRenderer::class; - } - if (!isset($GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['avalex'][\JWeiland\Avalex\Service\ApiService::class])) { $GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['avalex'][\JWeiland\Avalex\Service\ApiService::class] = []; } diff --git a/ext_tables.php b/ext_tables.php deleted file mode 100644 index 6137585..0000000 --- a/ext_tables.php +++ /dev/null @@ -1,7 +0,0 @@ -