From 6e3af0734b70cc3ca25dd81bed1662d1b55a2ab5 Mon Sep 17 00:00:00 2001 From: Oliver Klee Date: Fri, 4 Oct 2024 17:16:18 +0200 Subject: [PATCH] [TASK] Merge `Csv/AbstractListView` into `AbstractRegistrationListView` Fixes #3697 --- CHANGELOG.md | 1 + Classes/Csv/AbstractListView.php | 190 ------------------- Classes/Csv/AbstractRegistrationListView.php | 155 ++++++++++++++- phpstan-baseline.neon | 10 - 4 files changed, 155 insertions(+), 201 deletions(-) delete mode 100644 Classes/Csv/AbstractListView.php diff --git a/CHANGELOG.md b/CHANGELOG.md index e32251d48..7528fdbeb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,7 @@ This project adheres to [Semantic Versioning](https://semver.org/). ### Changed +- Merge `Csv/AbstractListView` into `Csv/AbstractRegistrationListView` (#3771) - Convert the manual to the new PHP-based rendering (#3692, #3696) - Use PHP 7.4 language features and native type declarations (#3643, #3682, #3683, #3689, #3698, #3699, #3701, #3702, #3703, #3704, #3705, diff --git a/Classes/Csv/AbstractListView.php b/Classes/Csv/AbstractListView.php deleted file mode 100644 index 1bb54bf20..000000000 --- a/Classes/Csv/AbstractListView.php +++ /dev/null @@ -1,190 +0,0 @@ - - */ - protected int $pageUid = 0; - - protected ?LanguageService $translator = null; - - /** - * @var non-empty-string - */ - protected string $tableName; - - protected Configuration $configuration; - - public function __construct() - { - $this->configuration = ConfigurationRegistry::get('plugin.tx_seminars'); - } - - protected function getLanguageService(): ?LanguageService - { - return $GLOBALS['LANG'] ?? null; - } - - protected function getBackEndUser(): ?BackendUserAuthentication - { - return $GLOBALS['BE_USER'] ?? null; - } - - /** - * Loads the language data and returns the corresponding translator instance. - */ - protected function getInitializedTranslator(): LanguageService - { - if ($this->translator instanceof LanguageService) { - return $this->translator; - } - - if ($this->getLanguageService() instanceof LanguageService) { - $languageService = $this->getLanguageService(); - } else { - $backEndUser = $this->getBackEndUser(); - if ($backEndUser instanceof BackendUserAuthentication) { - $languageService = GeneralUtility::makeInstance(LanguageServiceFactory::class) - ->createFromUserPreferences($backEndUser); - } else { - $languageService = GeneralUtility::makeInstance(LanguageServiceFactory::class)->create('default'); - } - } - - $this->translator = $languageService; - $languageService->includeLLFile('EXT:core/Resources/Private/Language/locallang_general.xlf'); - $languageService->includeLLFile('EXT:seminars/Resources/Private/Language/locallang_db.xlf'); - $this->includeAdditionalLanguageFiles(); - - return $languageService; - } - - /** - * Includes additional language files for $this->translator. - * - * This function is intended to be overwritten in subclasses. - */ - protected function includeAdditionalLanguageFiles(): void - { - } - - /** - * @param int<0, max> $pageUid - * - * @throws \InvalidArgumentException - */ - abstract public function setPageUid(int $pageUid): void; - - /** - * @return int<0, max> - */ - protected function getPageUid(): int - { - return $this->pageUid; - } - - /** - * Checks whether a non-zero page UID has been set. - */ - protected function hasPageUid(): bool - { - return $this->getPageUid() > 0; - } - - /** - * Returns the name of the main table for this CSV export. - * - * @return non-empty-string - */ - protected function getTableName(): string - { - return $this->tableName; - } - - abstract public function render(): string; - - /** - * Depending on the configuration, either returns the first line containing the specification of the separator character - * or just an empty string. - */ - protected function createCsvSeparatorLine(): string - { - if (!$this->configuration->getAsBoolean('addExcelSpecificSeparatorLineToCsv')) { - return ''; - } - - return 'sep=' . self::COLUMN_SEPARATOR . self::LINE_SEPARATOR; - } - - /** - * Creates the heading line for a CSV event list. - * - * @return string header list, will not be empty if the CSV export has been configured correctly - */ - protected function createCsvHeading(): string - { - return \implode(self::COLUMN_SEPARATOR, $this->getLocalizedCsvHeadings()); - } - - /** - * Returns the localized field names. - * - * @return list the translated field names in an array, will be empty if no fields should be exported - */ - abstract protected function getLocalizedCsvHeadings(): array; - - /** - * Creates the body lines of the CSV export. - * - * @return list - */ - abstract protected function createCsvBodyLines(): array; - - /** - * Escapes a single field for CSV. - */ - protected function escapeFieldForCsv(string $fieldContent): string - { - if (\str_contains($fieldContent, '"')) { - $escapedFieldValue = '"' . \str_replace('"', '""', $fieldContent) . '"'; - } elseif (\str_contains($fieldContent, ';') || \str_contains($fieldContent, "\n")) { - $escapedFieldValue = '"' . $fieldContent . '"'; - } else { - $escapedFieldValue = $fieldContent; - } - - return $escapedFieldValue; - } -} diff --git a/Classes/Csv/AbstractRegistrationListView.php b/Classes/Csv/AbstractRegistrationListView.php index 7dacd3461..d015d1d50 100644 --- a/Classes/Csv/AbstractRegistrationListView.php +++ b/Classes/Csv/AbstractRegistrationListView.php @@ -4,10 +4,15 @@ namespace OliverKlee\Seminars\Csv; +use OliverKlee\Oelib\Configuration\ConfigurationRegistry; +use OliverKlee\Oelib\Interfaces\Configuration; use OliverKlee\Seminars\BagBuilder\RegistrationBagBuilder; use OliverKlee\Seminars\Hooks\HookProvider; use OliverKlee\Seminars\Hooks\Interfaces\RegistrationListCsv; use OliverKlee\Seminars\OldModel\LegacyRegistration; +use TYPO3\CMS\Core\Authentication\BackendUserAuthentication; +use TYPO3\CMS\Core\Localization\LanguageService; +use TYPO3\CMS\Core\Localization\LanguageServiceFactory; use TYPO3\CMS\Core\Utility\GeneralUtility; /** @@ -15,8 +20,32 @@ * * @internal */ -abstract class AbstractRegistrationListView extends AbstractListView +abstract class AbstractRegistrationListView { + /** + * @var non-empty-string + */ + protected const COLUMN_SEPARATOR = ';'; + + /** + * @var string + */ + protected const LINE_SEPARATOR = "\r\n"; + + /** + * @var int the depth of the recursion for the back-end pages + */ + protected const RECURSION_DEPTH = 250; + + protected Configuration $configuration; + + /** + * @var int<0, max> + */ + protected int $pageUid = 0; + + protected ?LanguageService $translator = null; + /** * @var non-empty-string */ @@ -27,6 +56,130 @@ abstract class AbstractRegistrationListView extends AbstractListView */ protected int $eventUid = 0; + public function __construct() + { + $this->configuration = ConfigurationRegistry::get('plugin.tx_seminars'); + } + + protected function getLanguageService(): ?LanguageService + { + $languageService = $GLOBALS['LANG'] ?? null; + \assert(($languageService instanceof LanguageService) || $languageService === null); + + return $languageService; + } + + protected function getBackEndUser(): ?BackendUserAuthentication + { + $backendUser = $GLOBALS['BE_USER'] ?? null; + \assert(($backendUser instanceof BackendUserAuthentication) || $backendUser === null); + + return $backendUser; + } + + /** + * Loads the language data and returns the corresponding translator instance. + */ + protected function getInitializedTranslator(): LanguageService + { + if ($this->translator instanceof LanguageService) { + return $this->translator; + } + + if ($this->getLanguageService() instanceof LanguageService) { + $languageService = $this->getLanguageService(); + } else { + $backEndUser = $this->getBackEndUser(); + if ($backEndUser instanceof BackendUserAuthentication) { + $languageService = GeneralUtility::makeInstance(LanguageServiceFactory::class) + ->createFromUserPreferences($backEndUser); + } else { + $languageService = GeneralUtility::makeInstance(LanguageServiceFactory::class)->create('default'); + } + } + + $this->translator = $languageService; + $languageService->includeLLFile('EXT:core/Resources/Private/Language/locallang_general.xlf'); + $languageService->includeLLFile('EXT:seminars/Resources/Private/Language/locallang_db.xlf'); + $this->includeAdditionalLanguageFiles(); + + return $languageService; + } + + /** + * Includes additional language files for $this->translator. + * + * This function is intended to be overwritten in subclasses. + */ + protected function includeAdditionalLanguageFiles(): void + { + } + + /** + * @return int<0, max> + */ + protected function getPageUid(): int + { + return $this->pageUid; + } + + /** + * Checks whether a non-zero page UID has been set. + */ + protected function hasPageUid(): bool + { + return $this->getPageUid() > 0; + } + + /** + * Returns the name of the main table for this CSV export. + * + * @return non-empty-string + */ + protected function getTableName(): string + { + return $this->tableName; + } + + /** + * Depending on the configuration, either returns the first line containing the specification of the separator character + * or just an empty string. + */ + protected function createCsvSeparatorLine(): string + { + if (!$this->configuration->getAsBoolean('addExcelSpecificSeparatorLineToCsv')) { + return ''; + } + + return 'sep=' . self::COLUMN_SEPARATOR . self::LINE_SEPARATOR; + } + + /** + * Creates the heading line for a CSV event list. + * + * @return string header list, will not be empty if the CSV export has been configured correctly + */ + protected function createCsvHeading(): string + { + return \implode(self::COLUMN_SEPARATOR, $this->getLocalizedCsvHeadings()); + } + + /** + * Escapes a single field for CSV. + */ + protected function escapeFieldForCsv(string $fieldContent): string + { + if (\str_contains($fieldContent, '"')) { + $escapedFieldValue = '"' . \str_replace('"', '""', $fieldContent) . '"'; + } elseif (\str_contains($fieldContent, ';') || \str_contains($fieldContent, "\n")) { + $escapedFieldValue = '"' . $fieldContent . '"'; + } else { + $escapedFieldValue = $fieldContent; + } + + return $escapedFieldValue; + } + /** * Sets the page UID of the records to retrieve. * diff --git a/phpstan-baseline.neon b/phpstan-baseline.neon index 6f2b74a60..4ebe28576 100644 --- a/phpstan-baseline.neon +++ b/phpstan-baseline.neon @@ -165,16 +165,6 @@ parameters: count: 1 path: Classes/Controller/EventRegistrationController.php - - - message: "#^Method OliverKlee\\\\Seminars\\\\Csv\\\\AbstractListView\\:\\:getBackEndUser\\(\\) should return TYPO3\\\\CMS\\\\Core\\\\Authentication\\\\BackendUserAuthentication\\|null but returns mixed\\.$#" - count: 1 - path: Classes/Csv/AbstractListView.php - - - - message: "#^Method OliverKlee\\\\Seminars\\\\Csv\\\\AbstractListView\\:\\:getLanguageService\\(\\) should return TYPO3\\\\CMS\\\\Core\\\\Localization\\\\LanguageService\\|null but returns mixed\\.$#" - count: 1 - path: Classes/Csv/AbstractListView.php - - message: "#^Method OliverKlee\\\\Seminars\\\\Csv\\\\AbstractRegistrationListView\\:\\:render\\(\\) should return string but returns mixed\\.$#" count: 1