From 80fddcbb5df7de830154debb42f67ac80523d774 Mon Sep 17 00:00:00 2001 From: Hoja Mustaffa Abdul Latheef Date: Tue, 23 Jan 2024 18:00:03 +0100 Subject: [PATCH 01/65] [TASK] Replacing TYPO3 Core Deprecations and Compatibility Fixes - Replaced Deprecations - Started compatibility fixing for TYPO3 12 LTS --- Classes/Controller/AbstractController.php | 11 ++--- Classes/Controller/SolrController.php | 43 ++++++++++++------- Classes/Controller/ToolsController.php | 5 ++- ...xecuteQueryTaskAdditionalFieldProvider.php | 3 +- Classes/Task/IndexQueueWorkerTask.php | 4 +- ...QueueWorkerTaskAdditionalFieldProvider.php | 3 +- Classes/Tca/ReduceCategoryTreeToPageTree.php | 10 +++-- Classes/ViewHelpers/Format/HtmlViewHelper.php | 5 ++- Classes/XClasses/LiveSearch/LiveSearch.php | 40 +++++------------ .../TCA/tx_jwtools2_stored_routes.php | 19 ++------ .../Hooks/InitializeStdWrapTest.php | 2 +- .../ViewHelpers/Format/HtmlViewHelperTest.php | 2 +- Tests/Unit/Task/ExecuteQueryTaskTest.php | 2 +- ext_localconf.php | 2 +- ext_tables.php | 2 +- 15 files changed, 70 insertions(+), 83 deletions(-) diff --git a/Classes/Controller/AbstractController.php b/Classes/Controller/AbstractController.php index 022cb9b..f8ba602 100644 --- a/Classes/Controller/AbstractController.php +++ b/Classes/Controller/AbstractController.php @@ -10,6 +10,7 @@ namespace JWeiland\Jwtools2\Controller; +use TYPO3\CMS\Backend\Template\ModuleTemplateFactory; use TYPO3\CMS\Backend\View\BackendTemplateView; use TYPO3\CMS\Core\Configuration\ExtensionConfiguration; use TYPO3\CMS\Core\Utility\GeneralUtility; @@ -21,13 +22,9 @@ */ abstract class AbstractController extends ActionController { - /** - * The default view object to use if none of the resolved views can render - * a response for the current request. - * - * @var string - */ - protected $defaultViewObjectName = BackendTemplateView::class; + public function __construct(private ModuleTemplateFactory $moduleTemplateFactory) + { + } /** * Initializes the view before invoking an action method. diff --git a/Classes/Controller/SolrController.php b/Classes/Controller/SolrController.php index 02fb5b0..f7ce174 100644 --- a/Classes/Controller/SolrController.php +++ b/Classes/Controller/SolrController.php @@ -19,6 +19,7 @@ use JWeiland\Jwtools2\Domain\Repository\SchedulerRepository; use JWeiland\Jwtools2\Domain\Repository\SolrRepository; use JWeiland\Jwtools2\Service\SolrService; +use Psr\Http\Message\ResponseInterface; use TYPO3\CMS\Core\Database\ConnectionPool; use TYPO3\CMS\Core\Messaging\AbstractMessage; use TYPO3\CMS\Core\Page\PageRenderer; @@ -87,20 +88,24 @@ public function initializeView(ViewInterface $view): void } } - public function listAction(): void + public function listAction(): ResponseInterface { $this->view->assign('sites', $this->solrRepository->findAllAvailableSites()); $this->view->assign('currentRootPageUid', $this->registry->get('jwtools2-solr', 'rootPageId', 0)); + + return $this->htmlResponse(); } - public function showAction(int $rootPageUid): void + public function showAction(int $rootPageUid): ResponseInterface { $site = $this->solrRepository->findByRootPage($rootPageUid); $this->view->assign('site', $site); $this->view->assign('memoryPeakUsage', $this->registry->get('jwtools2-solr', 'memoryPeakUsage', 0)); + + return $this->htmlResponse(); } - public function showIndexQueueAction(int $rootPageUid, string $configurationName): void + public function showIndexQueueAction(int $rootPageUid, string $configurationName): ResponseInterface { $site = $this->solrRepository->findByRootPage($rootPageUid); if ($site instanceof Site) { @@ -109,6 +114,8 @@ public function showIndexQueueAction(int $rootPageUid, string $configurationName $this->view->assign('solrConfiguration', $solrConfiguration); $this->view->assign('configurationName', $configurationName); } + + return $this->htmlResponse(); } public function indexOneRecordAction( @@ -116,7 +123,7 @@ public function indexOneRecordAction( string $configurationName, ?int $recordUid, int $languageUid = 0 - ): void { + ): ResponseInterface { if ($recordUid === null) { $this->addFlashMessage( 'Please enter a record UID before submitting the form', @@ -166,9 +173,11 @@ public function indexOneRecordAction( 'languageUid' => $languageUid, ] ); + + return $this->htmlResponse(); } - public function showClearIndexFormAction(int $rootPageUid): void + public function showClearIndexFormAction(int $rootPageUid): ResponseInterface { $site = $this->solrRepository->findByRootPage($rootPageUid); if ($site instanceof Site) { @@ -185,13 +194,13 @@ public function showClearIndexFormAction(int $rootPageUid): void ); $this->redirect('list'); } + + return $this->htmlResponse(); } - /** - * @Extbase\Validate("NotEmpty", param="configurationNames") - * @Extbase\Validate("NotEmpty", param="clear") - */ - public function clearIndexAction(int $rootPageUid, array $configurationNames, array $clear): void + #[Extbase\Validate(['validator' => 'NotEmpty', 'param' => 'configurationNames'])] + #[Extbase\Validate(['validator' => 'NotEmpty', 'param' => 'clear'])] + public function clearIndexAction(int $rootPageUid, array $configurationNames, array $clear): ResponseInterface { /** @var SolrService $solrService */ $solrService = GeneralUtility::makeInstance(SolrService::class); @@ -212,12 +221,14 @@ public function clearIndexAction(int $rootPageUid, array $configurationNames, ar AbstractMessage::WARNING ); } + + return $this->htmlResponse(); } /** * Show a form to clear full index */ - public function showClearFullIndexFormAction(): void + public function showClearFullIndexFormAction(): ResponseInterface { $pageRenderer = $this->objectManager->get(PageRenderer::class); $pageRenderer->loadRequireJsModule('TYPO3/CMS/Jwtools2/ClearFullIndex'); @@ -232,6 +243,8 @@ public function showClearFullIndexFormAction(): void } $this->view->assign('sites', $sites); $this->view->assign('configurationNamesOfAllSites', $configurationNamesOfAllSites); + + return $this->htmlResponse(); } protected function getIndexQueueItem(int $rootPageUid, string $configurationName, int $recordUid): ?Item @@ -255,8 +268,8 @@ protected function getIndexQueueItem(int $rootPageUid, string $configurationName $queryBuilder->createNamedParameter($recordUid, \PDO::PARAM_INT) ) ) - ->execute() - ->fetch(); + ->executeQuery() + ->fetchAssociative(); if ($indexQueueItem === false) { return null; @@ -273,8 +286,8 @@ protected function getIndexQueueItem(int $rootPageUid, string $configurationName $queryBuilder->createNamedParameter($recordUid, \PDO::PARAM_INT) ) ) - ->execute() - ->fetch(); + ->executeQuery() + ->fetchOne(); if ($tableRecord === false) { return null; diff --git a/Classes/Controller/ToolsController.php b/Classes/Controller/ToolsController.php index 676b994..1d626d1 100644 --- a/Classes/Controller/ToolsController.php +++ b/Classes/Controller/ToolsController.php @@ -10,12 +10,15 @@ namespace JWeiland\Jwtools2\Controller; +use Psr\Http\Message\ResponseInterface; + /** * Class ToolsController */ class ToolsController extends AbstractController { - public function overviewAction(): void + public function overviewAction(): ResponseInterface { + return $this->htmlResponse(); } } diff --git a/Classes/Task/ExecuteQueryTaskAdditionalFieldProvider.php b/Classes/Task/ExecuteQueryTaskAdditionalFieldProvider.php index 43e7d25..2cb7f9f 100644 --- a/Classes/Task/ExecuteQueryTaskAdditionalFieldProvider.php +++ b/Classes/Task/ExecuteQueryTaskAdditionalFieldProvider.php @@ -11,6 +11,7 @@ namespace JWeiland\Jwtools2\Task; use TYPO3\CMS\Extbase\Utility\LocalizationUtility; +use TYPO3\CMS\Scheduler\AbstractAdditionalFieldProvider; use TYPO3\CMS\Scheduler\AdditionalFieldProviderInterface; use TYPO3\CMS\Scheduler\Controller\SchedulerModuleController; use TYPO3\CMS\Scheduler\Task\AbstractTask; @@ -19,7 +20,7 @@ /** * Additional field provider for the execute query task */ -class ExecuteQueryTaskAdditionalFieldProvider implements AdditionalFieldProviderInterface +class ExecuteQueryTaskAdditionalFieldProvider implements AbstractAdditionalFieldProvider { /** * Used to define fields to provide the TYPO3 site to index and number of diff --git a/Classes/Task/IndexQueueWorkerTask.php b/Classes/Task/IndexQueueWorkerTask.php index a9f9fbb..b46e286 100644 --- a/Classes/Task/IndexQueueWorkerTask.php +++ b/Classes/Task/IndexQueueWorkerTask.php @@ -51,7 +51,7 @@ public function execute(): bool // Wrapped the CliEnvironment to avoid defining TYPO3_PATH_WEB since this // should only be done in the case when running it from outside TYPO3 BE // @see #921 and #934 on https://github.com/TYPO3-Solr - if (TYPO3_REQUESTTYPE & TYPO3_REQUESTTYPE_CLI) { + if (Environment::isCli()) { $cliEnvironment = GeneralUtility::makeInstance(CliEnvironment::class); $cliEnvironment->backup(); $cliEnvironment->initialize(Environment::getPublicPath() . '/'); @@ -82,7 +82,7 @@ public function execute(): bool $maxSitePosition > count($availableSites) ? 0 : $maxSitePosition ); - if (TYPO3_REQUESTTYPE & TYPO3_REQUESTTYPE_CLI) { + if (Environment::isCli()) { $cliEnvironment->restore(); } diff --git a/Classes/Task/IndexQueueWorkerTaskAdditionalFieldProvider.php b/Classes/Task/IndexQueueWorkerTaskAdditionalFieldProvider.php index 0073792..4a0c43d 100644 --- a/Classes/Task/IndexQueueWorkerTaskAdditionalFieldProvider.php +++ b/Classes/Task/IndexQueueWorkerTaskAdditionalFieldProvider.php @@ -11,6 +11,7 @@ namespace JWeiland\Jwtools2\Task; use TYPO3\CMS\Extbase\Utility\LocalizationUtility; +use TYPO3\CMS\Scheduler\AbstractAdditionalFieldProvider; use TYPO3\CMS\Scheduler\AdditionalFieldProviderInterface; use TYPO3\CMS\Scheduler\Controller\SchedulerModuleController; use TYPO3\CMS\Scheduler\Task\AbstractTask; @@ -19,7 +20,7 @@ /** * Additional field provider for the index queue worker task */ -class IndexQueueWorkerTaskAdditionalFieldProvider implements AdditionalFieldProviderInterface +class IndexQueueWorkerTaskAdditionalFieldProvider implements AbstractAdditionalFieldProvider { /** * Used to define fields to provide the TYPO3 site to index and number of diff --git a/Classes/Tca/ReduceCategoryTreeToPageTree.php b/Classes/Tca/ReduceCategoryTreeToPageTree.php index 21c20d4..67d48c1 100644 --- a/Classes/Tca/ReduceCategoryTreeToPageTree.php +++ b/Classes/Tca/ReduceCategoryTreeToPageTree.php @@ -10,6 +10,7 @@ namespace JWeiland\Jwtools2\Tca; +use Doctrine\DBAL\ArrayParameterType; use TYPO3\CMS\Backend\Tree\TreeNode; use TYPO3\CMS\Backend\Tree\TreeNodeCollection; use TYPO3\CMS\Backend\Utility\BackendUtility; @@ -20,6 +21,7 @@ use TYPO3\CMS\Core\Database\Connection; use TYPO3\CMS\Core\Database\ConnectionPool; use TYPO3\CMS\Core\Database\QueryGenerator; +use TYPO3\CMS\Core\Http\ApplicationType; use TYPO3\CMS\Core\Tree\Event\ModifyTreeDataEvent; use TYPO3\CMS\Core\Utility\GeneralUtility; @@ -57,7 +59,7 @@ public function __invoke(ModifyTreeDataEvent $event): void { try { if ( - (TYPO3_REQUESTTYPE & TYPO3_REQUESTTYPE_BE) + (TYPO3_REQUESTTYPE & ApplicationType::fromRequest($GLOBALS['TYPO3_REQUEST'])->isBackend()) && $this->extensionConfiguration->get('jwtools2', 'reduceCategoriesToPageTree') === '1' && !$this->getBackendUserAuthentication()->isAdmin() && $event->getProvider()->getTableName() === $this->categoryTableName @@ -147,12 +149,12 @@ protected function getListOfAllowedCategoryUids(int $pageUid): string 'pid', $queryBuilder->createNamedParameter( $this->getPagesOfCurrentRootPage($pageUid), - Connection::PARAM_INT_ARRAY + ArrayParameterType::INTEGER ) ) ) - ->execute() - ->fetchAll(); + ->executeQuery() + ->fetchAllAssociative(); if (empty($categories)) { return '0'; diff --git a/Classes/ViewHelpers/Format/HtmlViewHelper.php b/Classes/ViewHelpers/Format/HtmlViewHelper.php index f9976bb..8aae859 100644 --- a/Classes/ViewHelpers/Format/HtmlViewHelper.php +++ b/Classes/ViewHelpers/Format/HtmlViewHelper.php @@ -11,6 +11,7 @@ namespace JWeiland\Jwtools2\ViewHelpers\Format; use TYPO3\CMS\Core\Domain\Repository\PageRepository; +use TYPO3\CMS\Core\Http\ApplicationType; use TYPO3\CMS\Core\TypoScript\TemplateService; use TYPO3\CMS\Core\Utility\GeneralUtility; use TYPO3\CMS\Extbase\Configuration\ConfigurationManagerInterface; @@ -107,7 +108,7 @@ public static function renderStatic( RenderingContextInterface $renderingContext ): string { $parseFuncTSPath = $arguments['parseFuncTSPath']; - if (TYPO3_MODE === 'BE') { + if (ApplicationType::fromRequest($GLOBALS['TYPO3_REQUEST'])->isBackend()) { self::simulateFrontendEnvironment(); } @@ -116,7 +117,7 @@ public static function renderStatic( $contentObject->start($arguments['data'] ?? []); $content = $contentObject->parseFunc($value, [], '< ' . $parseFuncTSPath); - if (TYPO3_MODE === 'BE') { + if (ApplicationType::fromRequest($GLOBALS['TYPO3_REQUEST'])->isBackend()) { self::resetFrontendEnvironment(); } diff --git a/Classes/XClasses/LiveSearch/LiveSearch.php b/Classes/XClasses/LiveSearch/LiveSearch.php index 3347994..7689571 100644 --- a/Classes/XClasses/LiveSearch/LiveSearch.php +++ b/Classes/XClasses/LiveSearch/LiveSearch.php @@ -41,30 +41,15 @@ class LiveSearch */ const RECURSIVE_PAGE_LEVEL = 99; - /** - * @var string - */ - private $queryString = ''; + private string $queryString = ''; - /** - * @var int - */ - private $startCount = 0; + private int $startCount = 0; - /** - * @var int - */ - private $limitCount = 5; + private int $limitCount = 5; - /** - * @var string - */ - protected $userPermissions = ''; + protected string $userPermissions = ''; - /** - * @var QueryParser - */ - protected $queryParser; + protected QueryParser $queryParser; /** * Initialize access settings @@ -77,11 +62,8 @@ public function __construct() /** * Find records from database based on the given $searchQuery. - * - * @param string $searchQuery - * @return array Result list of database search. */ - public function find($searchQuery) + public function find(string $searchQuery): array { $recordArray = []; $pageIdList = $this->getPageIdList(); @@ -318,7 +300,7 @@ protected function makeQuerySearchByTable(QueryBuilder $queryBuilder, $tableName $evalRules = $fieldConfig['eval'] ?? ''; // Check whether search should be case-sensitive or not - $searchConstraint = $queryBuilder->expr()->andX( + $searchConstraint = $queryBuilder->expr()->and( $queryBuilder->expr()->comparison( 'LOWER(' . $queryBuilder->quoteIdentifier($fieldName) . ')', 'LIKE', @@ -339,13 +321,13 @@ protected function makeQuerySearchByTable(QueryBuilder $queryBuilder, $tableName // Apply additional condition, if any if ($fieldConfig['search']['andWhere'] ?? false) { if (GeneralUtility::makeInstance(Features::class)->isFeatureEnabled('runtimeDbQuotingOfTcaConfiguration')) { - $searchConstraint->add( + $searchConstraint = $searchConstraint->with( QueryHelper::stripLogicalOperatorPrefix(QueryHelper::quoteDatabaseIdentifiers($queryBuilder->getConnection(), $fieldConfig['search']['andWhere'])) ); } else { - $searchConstraint->add( + $searchConstraint = $searchConstraint->with( QueryHelper::stripLogicalOperatorPrefix($fieldConfig['search']['andWhere']) - ); + ); } } } @@ -367,7 +349,7 @@ protected function makeQuerySearchByTable(QueryBuilder $queryBuilder, $tableName return '0=1'; } - return $queryBuilder->expr()->orX(...$constraints); + return $queryBuilder->expr()->or(...$constraints); } /** diff --git a/Configuration/TCA/tx_jwtools2_stored_routes.php b/Configuration/TCA/tx_jwtools2_stored_routes.php index c708161..271d131 100755 --- a/Configuration/TCA/tx_jwtools2_stored_routes.php +++ b/Configuration/TCA/tx_jwtools2_stored_routes.php @@ -8,7 +8,6 @@ 'label_alt_force' => true, 'tstamp' => 'tstamp', 'crdate' => 'crdate', - 'dividers2tabs' => false, 'hideTable' => true, 'versioningWS' => false, 'languageField' => 'sys_language_uid', @@ -30,19 +29,7 @@ 'columns' => [ 'sys_language_uid' => [ 'label' => 'LLL:EXT:core/Resources/Private/Language/locallang_general.xlf:LGL.language', - 'config' => [ - 'type' => 'select', - 'renderType' => 'selectSingle', - 'special' => 'languages', - 'items' => [ - [ - 'LLL:EXT:core/Resources/Private/Language/locallang_general.xlf:LGL.allLanguages', - -1, - 'flags-multiple', - ], - ], - 'default' => 0, - ], + 'config' => ['type' => 'language'], ], 'l10n_parent' => [ 'displayCond' => 'FIELD:sys_language_uid:>:0', @@ -52,8 +39,8 @@ 'renderType' => 'selectSingle', 'items' => [ [ - '', - 0, + 'label' => '', + 'value' => 0, ], ], 'foreign_table' => 'tx_jwtools2_stored_routes', diff --git a/Tests/Functional/Hooks/InitializeStdWrapTest.php b/Tests/Functional/Hooks/InitializeStdWrapTest.php index ffb2e00..1863ddd 100644 --- a/Tests/Functional/Hooks/InitializeStdWrapTest.php +++ b/Tests/Functional/Hooks/InitializeStdWrapTest.php @@ -11,11 +11,11 @@ namespace TYPO3\CMS\Fluid\Tests\Functional\Hooks; use JWeiland\Jwtools2\Hooks\InitializeStdWrap; -use Nimut\TestingFramework\TestCase\FunctionalTestCase; use Prophecy\PhpUnit\ProphecyTrait; use Prophecy\Prophecy\ObjectProphecy; use TYPO3\CMS\Core\Configuration\ExtensionConfiguration; use TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer; +use TYPO3\TestingFramework\Core\Functional\FunctionalTestCase; /** * Test case diff --git a/Tests/Functional/ViewHelpers/Format/HtmlViewHelperTest.php b/Tests/Functional/ViewHelpers/Format/HtmlViewHelperTest.php index 25f3393..3d1422d 100644 --- a/Tests/Functional/ViewHelpers/Format/HtmlViewHelperTest.php +++ b/Tests/Functional/ViewHelpers/Format/HtmlViewHelperTest.php @@ -11,7 +11,6 @@ namespace TYPO3\CMS\Fluid\Tests\Functional\ViewHelpers\Format; use JWeiland\Jwtools2\ViewHelpers\Format\HtmlViewHelper; -use Nimut\TestingFramework\TestCase\FunctionalTestCase; use Prophecy\PhpUnit\ProphecyTrait; use Prophecy\Prophecy\ObjectProphecy; use TYPO3\CMS\Core\Information\Typo3Version; @@ -22,6 +21,7 @@ use TYPO3\CMS\Extbase\Object\ObjectManagerInterface; use TYPO3\CMS\Fluid\Core\Rendering\RenderingContext; use TYPO3\CMS\Frontend\Typolink\ExternalUrlLinkBuilder; +use TYPO3\TestingFramework\Core\Functional\FunctionalTestCase; /** * Test case diff --git a/Tests/Unit/Task/ExecuteQueryTaskTest.php b/Tests/Unit/Task/ExecuteQueryTaskTest.php index 1f3acd0..1ec7c89 100644 --- a/Tests/Unit/Task/ExecuteQueryTaskTest.php +++ b/Tests/Unit/Task/ExecuteQueryTaskTest.php @@ -12,13 +12,13 @@ use Doctrine\DBAL\Driver\Statement; use JWeiland\Jwtools2\Task\ExecuteQueryTask; -use Nimut\TestingFramework\TestCase\UnitTestCase; use Prophecy\PhpUnit\ProphecyTrait; use Prophecy\Prophecy\ObjectProphecy; use TYPO3\CMS\Core\Database\Connection; use TYPO3\CMS\Core\Database\ConnectionPool; use TYPO3\CMS\Core\Utility\GeneralUtility; use TYPO3\CMS\Scheduler\Scheduler; +use TYPO3\TestingFramework\Core\Unit\UnitTestCase; /** * Test case. diff --git a/ext_localconf.php b/ext_localconf.php index 28d2e86..3781af4 100644 --- a/ext_localconf.php +++ b/ext_localconf.php @@ -1,6 +1,6 @@ Date: Tue, 23 Jan 2024 18:49:26 +0100 Subject: [PATCH 02/65] Replaced deprecated ElementBrowserController namespace with new one --- Classes/Backend/Browser/FileBrowser.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Classes/Backend/Browser/FileBrowser.php b/Classes/Backend/Browser/FileBrowser.php index e2cdf14..dee1366 100644 --- a/Classes/Backend/Browser/FileBrowser.php +++ b/Classes/Backend/Browser/FileBrowser.php @@ -11,6 +11,7 @@ namespace JWeiland\Jwtools2\Backend\Browser; use Doctrine\DBAL\Schema\AbstractSchemaManager; +use TYPO3\CMS\Backend\Controller\ElementBrowserController; use TYPO3\CMS\Backend\Utility\BackendUtility; use TYPO3\CMS\Core\Configuration\Exception\ExtensionConfigurationExtensionNotConfiguredException; use TYPO3\CMS\Core\Configuration\Exception\ExtensionConfigurationPathDoesNotExistException; @@ -25,13 +26,12 @@ use TYPO3\CMS\Core\Resource\FileInterface; use TYPO3\CMS\Core\Utility\GeneralUtility; use TYPO3\CMS\Extbase\Utility\LocalizationUtility; -use TYPO3\CMS\Recordlist\Controller\ElementBrowserController; /** * Modified version of TYPO3's ElementBrowserController. * We have modified the templates to allow showing the upload form on top of the file/folder list */ -class FileBrowser extends \TYPO3\CMS\Recordlist\Browser\FileBrowser +class FileBrowser extends \TYPO3\CMS\Backend\ElementBrowser\FileBrowser { /** * @var ExtensionConfiguration From 8977887b089de4873b71bd5dfb0ae4cfd6f77c7d Mon Sep 17 00:00:00 2001 From: Hoja Mustaffa Abdul Latheef Date: Tue, 23 Jan 2024 18:50:01 +0100 Subject: [PATCH 03/65] DI for moduleTemplateController added and removed old BackendTemplate wrapper --- Classes/Controller/AbstractController.php | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/Classes/Controller/AbstractController.php b/Classes/Controller/AbstractController.php index f8ba602..f41b187 100644 --- a/Classes/Controller/AbstractController.php +++ b/Classes/Controller/AbstractController.php @@ -22,8 +22,11 @@ */ abstract class AbstractController extends ActionController { - public function __construct(private ModuleTemplateFactory $moduleTemplateFactory) + protected ModuleTemplateFactory $moduleTemplateFactory; + + public function __construct(ModuleTemplateFactory $moduleTemplateFactory) { + $this->moduleTemplateFactory = $moduleTemplateFactory; } /** From b09490a8ee591a416aba25076155f597ff34009b Mon Sep 17 00:00:00 2001 From: Hoja Mustaffa Abdul Latheef Date: Tue, 23 Jan 2024 18:55:37 +0100 Subject: [PATCH 04/65] Replaced execute() with executeQuery() and return type --- Classes/Command/ConvertPlainPasswordToHashCommand.php | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/Classes/Command/ConvertPlainPasswordToHashCommand.php b/Classes/Command/ConvertPlainPasswordToHashCommand.php index bde95f3..724ad87 100644 --- a/Classes/Command/ConvertPlainPasswordToHashCommand.php +++ b/Classes/Command/ConvertPlainPasswordToHashCommand.php @@ -11,6 +11,7 @@ namespace JWeiland\Jwtools2\Command; use Doctrine\DBAL\Driver\Statement; +use Doctrine\DBAL\Result; use Symfony\Component\Console\Command\Command; use Symfony\Component\Console\Input\InputArgument; use Symfony\Component\Console\Input\InputInterface; @@ -156,13 +157,13 @@ protected function getDefaultHashInstance(string $mode): PasswordHashInterface return $this->modeMapping[$mode]['hashInstance']; } - protected function getStatementForUsers(string $tableName): Statement + protected function getStatementForUsers(string $tableName): Result { $queryBuilder = $this->getConnectionPool()->getQueryBuilderForTable($tableName); return $queryBuilder ->select('uid', 'password') ->from($tableName) - ->execute(); + ->executeQuery(); } protected function getConnectionPool(): ConnectionPool From c84da891b283210d59c6ba8d04755401a0fefbfe Mon Sep 17 00:00:00 2001 From: Hoja Mustaffa Abdul Latheef Date: Tue, 23 Jan 2024 19:21:03 +0100 Subject: [PATCH 05/65] Replaced execute and fetch methods Classes/Hooks/CachingFrameworkLoggerHook.php Classes/Hooks/ModifyElementInformationHook.php Classes/Hooks/MoveTranslatedContentElementsHook.php Classes/Routing/Aspect/PersistedTableMapper.php Classes/Service/SolrService.php --- Classes/Hooks/CachingFrameworkLoggerHook.php | 2 +- .../Hooks/ModifyElementInformationHook.php | 19 ++++++++++--------- .../MoveTranslatedContentElementsHook.php | 4 ++-- .../Routing/Aspect/PersistedTableMapper.php | 4 ++-- Classes/Service/SolrService.php | 4 ++-- 5 files changed, 17 insertions(+), 16 deletions(-) diff --git a/Classes/Hooks/CachingFrameworkLoggerHook.php b/Classes/Hooks/CachingFrameworkLoggerHook.php index 32c17c5..18db53d 100644 --- a/Classes/Hooks/CachingFrameworkLoggerHook.php +++ b/Classes/Hooks/CachingFrameworkLoggerHook.php @@ -116,7 +116,7 @@ protected function getCacheExpressions(): array $queryBuilder->expr()->neq('expression', $queryBuilder->createNamedParameter('')) ) ->from('tx_jwtools2_cache_expression') - ->execute(); + ->executeQuery(); while ($cacheExpression = $statement->fetch(\PDO::FETCH_ASSOC)) { $cacheExpressions[] = $cacheExpression; diff --git a/Classes/Hooks/ModifyElementInformationHook.php b/Classes/Hooks/ModifyElementInformationHook.php index cf1a5ba..2b46865 100644 --- a/Classes/Hooks/ModifyElementInformationHook.php +++ b/Classes/Hooks/ModifyElementInformationHook.php @@ -16,6 +16,7 @@ use TYPO3\CMS\Backend\Form\FormDataCompiler; use TYPO3\CMS\Backend\Form\FormDataGroup\TcaDatabaseRecord; use TYPO3\CMS\Backend\Routing\Exception\RouteNotFoundException; +use TYPO3\CMS\Backend\Routing\PreviewUriBuilder; use TYPO3\CMS\Backend\Routing\UriBuilder; use TYPO3\CMS\Backend\Utility\BackendUtility; use TYPO3\CMS\Core\Authentication\BackendUserAuthentication; @@ -97,7 +98,7 @@ class ModifyElementInformationHook protected $row; /** - * @var \TYPO3\CMS\Core\Resource\File|null + * @var File|null */ protected $fileObject; @@ -613,7 +614,7 @@ protected function getRecordActions($table, $uid, ServerRequestInterface $reques $actions['webListUrl'] = (string)$this->uriBuilder->buildUriFromRoute('web_list', ['id' => $uid, 'returnUrl' => $request->getAttribute('normalizedParams')->getRequestUri()]); // View page button - $actions['viewOnClick'] = BackendUtility::viewOnClick($uid, '', BackendUtility::BEgetRootLine($uid)); + $actions['viewOnClick'] = PreviewUriBuilder::create($uid)->buildDispatcherDataAttributes(); } return $actions; @@ -623,7 +624,7 @@ protected function getRecordActions($table, $uid, ServerRequestInterface $reques * Make reference display * * @param string $table Table name - * @param int|\TYPO3\CMS\Core\Resource\File $ref Filename or uid + * @param int|File $ref Filename or uid * @param ServerRequestInterface $request * @return array * @throws RouteNotFoundException @@ -667,8 +668,8 @@ protected function makeRef($table, $ref, ServerRequestInterface $request): array ->select('*') ->from('sys_refindex') ->where(...$predicates) - ->execute() - ->fetchAll(); + ->executeQuery() + ->fetchAllAssociative(); // Compile information for title tag: foreach ($rows as $row) { @@ -759,8 +760,8 @@ protected function makeRefFrom($table, $ref, ServerRequestInterface $request): a ->select('*') ->from('sys_refindex') ->where(...$predicates) - ->execute() - ->fetchAll(); + ->executeQuery() + ->fetchAllAssociative(); // Compile information for title tag: foreach ($rows as $row) { @@ -818,8 +819,8 @@ protected function transformFileReferenceToRecordReference(array $referenceRecor $queryBuilder->createNamedParameter($referenceRecord['recuid'], Connection::PARAM_INT) ) ) - ->execute() - ->fetch(); + ->executeQuery() + ->fetchAssociative(); return [ 'recuid' => $fileReference['uid_foreign'], diff --git a/Classes/Hooks/MoveTranslatedContentElementsHook.php b/Classes/Hooks/MoveTranslatedContentElementsHook.php index bfe5d7f..0ef12f6 100644 --- a/Classes/Hooks/MoveTranslatedContentElementsHook.php +++ b/Classes/Hooks/MoveTranslatedContentElementsHook.php @@ -109,10 +109,10 @@ protected function getOverlayRecords($uid, DataHandler $dataHandler): array $queryBuilder->createNamedParameter($uid, \PDO::PARAM_INT, ':pointer') ) ) - ->execute(); + ->executeQuery(); $contentRecords = []; - while ($contentRecord = $statement->fetch()) { + while ($contentRecord = $statement->fetchAssociative()) { $contentRecords[] = $contentRecord; } diff --git a/Classes/Routing/Aspect/PersistedTableMapper.php b/Classes/Routing/Aspect/PersistedTableMapper.php index d78e8e5..f372311 100644 --- a/Classes/Routing/Aspect/PersistedTableMapper.php +++ b/Classes/Routing/Aspect/PersistedTableMapper.php @@ -126,8 +126,8 @@ protected function getStoredRoute(string $source = '', string $target = ''): arr $queryBuilder->createNamedParameter($source ?: $target, \PDO::PARAM_STR) ) ) - ->execute() - ->fetch(); + ->executeQuery() + ->fetchAllAssociative(); return $storedRoute ?: []; } diff --git a/Classes/Service/SolrService.php b/Classes/Service/SolrService.php index 90a8c18..7e40bba 100644 --- a/Classes/Service/SolrService.php +++ b/Classes/Service/SolrService.php @@ -38,10 +38,10 @@ public function getStatistic(): QueueStatistic ->from('tx_solr_indexqueue_item') ->groupBy('pending') ->addGroupBy('failed') - ->execute(); + ->executeQuery(); $indexQueueStats = []; - while ($indexQueueStat = $statement->fetch()) { + while ($indexQueueStat = $statement->fetchAssociative()) { $indexQueueStats[] = $indexQueueStat; } From daed3314f33b9e5cc78eb4d03e741b054f70adcb Mon Sep 17 00:00:00 2001 From: Hoja Mustaffa Abdul Latheef Date: Tue, 23 Jan 2024 19:22:09 +0100 Subject: [PATCH 06/65] Replaced FolderLinkHandler with new API function \TYPO3\CMS\Recordlist\LinkHandler\FolderLinkHandler replced with \TYPO3\CMS\Backend\LinkHandler\FolderLinkHandler --- Classes/LinkHandler/FolderLinkHandler.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Classes/LinkHandler/FolderLinkHandler.php b/Classes/LinkHandler/FolderLinkHandler.php index 0850164..7b63dc1 100644 --- a/Classes/LinkHandler/FolderLinkHandler.php +++ b/Classes/LinkHandler/FolderLinkHandler.php @@ -10,16 +10,16 @@ namespace JWeiland\Jwtools2\LinkHandler; +use TYPO3\CMS\Backend\Controller\AbstractLinkBrowserController; use TYPO3\CMS\Core\Information\Typo3Version; use TYPO3\CMS\Core\Utility\GeneralUtility; use TYPO3\CMS\Fluid\View\StandaloneView; -use TYPO3\CMS\Recordlist\Controller\AbstractLinkBrowserController; use TYPO3Fluid\Fluid\View\ViewInterface; /** * This folder LinkHandler overwrites the LinkHandler of TYPO3 and moves upload and create folder fields to top */ -class FolderLinkHandler extends \TYPO3\CMS\Recordlist\LinkHandler\FolderLinkHandler +class FolderLinkHandler extends \TYPO3\CMS\Backend\LinkHandler\FolderLinkHandler { /** * @var StandaloneView|ViewInterface From 55887659211354cb95c0572a82e25bd0b5ae1b65 Mon Sep 17 00:00:00 2001 From: Hoja Mustaffa Abdul Latheef Date: Tue, 23 Jan 2024 19:23:23 +0100 Subject: [PATCH 07/65] Replaced FolderLinkHandler with new API function \TYPO3\CMS\Recordlist\LinkHandler\FolderLinkHandler replced with \TYPO3\CMS\Backend\LinkHandler\FolderLinkHandler --- Classes/Hooks/ModifyLinkHandlerHook.php | 4 ++-- Classes/LinkHandler/FileLinkHandler.php | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Classes/Hooks/ModifyLinkHandlerHook.php b/Classes/Hooks/ModifyLinkHandlerHook.php index 994c9df..64fa806 100644 --- a/Classes/Hooks/ModifyLinkHandlerHook.php +++ b/Classes/Hooks/ModifyLinkHandlerHook.php @@ -10,8 +10,8 @@ namespace JWeiland\Jwtools2\Hooks; -use TYPO3\CMS\Recordlist\LinkHandler\FileLinkHandler; -use TYPO3\CMS\Recordlist\LinkHandler\FolderLinkHandler; +use TYPO3\CMS\Backend\LinkHandler\FileLinkHandler; +use TYPO3\CMS\Backend\LinkHandler\FolderLinkHandler; /** * Hook to modify per TSConfig registered LinkHandlers with our own implementations. diff --git a/Classes/LinkHandler/FileLinkHandler.php b/Classes/LinkHandler/FileLinkHandler.php index 567ff1f..1ceb1e3 100644 --- a/Classes/LinkHandler/FileLinkHandler.php +++ b/Classes/LinkHandler/FileLinkHandler.php @@ -10,16 +10,16 @@ namespace JWeiland\Jwtools2\LinkHandler; +use TYPO3\CMS\Backend\Controller\AbstractLinkBrowserController; use TYPO3\CMS\Core\Information\Typo3Version; use TYPO3\CMS\Core\Utility\GeneralUtility; use TYPO3\CMS\Fluid\View\StandaloneView; -use TYPO3\CMS\Recordlist\Controller\AbstractLinkBrowserController; use TYPO3Fluid\Fluid\View\ViewInterface; /** * This file LinkHandler overwrites the LinkHandler of TYPO3 and moves upload and create folder fields to top */ -class FileLinkHandler extends \TYPO3\CMS\Recordlist\LinkHandler\FileLinkHandler +class FileLinkHandler extends \TYPO3\CMS\Backend\LinkHandler\FileLinkHandler { /** * @var StandaloneView|ViewInterface From 13cd05dd53ad9051ba94d9fc1a98b5aacbaefadf Mon Sep 17 00:00:00 2001 From: Hoja Mustaffa Abdul Latheef Date: Tue, 23 Jan 2024 19:25:32 +0100 Subject: [PATCH 08/65] Deorecated caalls replaced - replaced GeneralUtility::getUrl with @file_get_content - replaced TYPO3_BE to ApplicationType method isFrontend() --- Classes/Command/StatusReportCommand.php | 2 +- Classes/Database/Database.php | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/Classes/Command/StatusReportCommand.php b/Classes/Command/StatusReportCommand.php index 9f56b71..d0b32ee 100644 --- a/Classes/Command/StatusReportCommand.php +++ b/Classes/Command/StatusReportCommand.php @@ -192,7 +192,7 @@ protected function getContentOfRobotsTxt(Site $site): string if ($content === '' && !$this->input->hasOption('exclude-robots-txt-url-check')) { $base = rtrim((string)$site->getBase(), '/') . '/'; - $content = GeneralUtility::getUrl($base . 'robots.txt'); + $content = @file_get_contents($base . 'robots.txt'); if (empty($content)) { $content = ''; diff --git a/Classes/Database/Database.php b/Classes/Database/Database.php index d01a388..6094b92 100644 --- a/Classes/Database/Database.php +++ b/Classes/Database/Database.php @@ -16,6 +16,7 @@ use TYPO3\CMS\Core\Database\Query\QueryBuilder; use TYPO3\CMS\Core\Database\Query\Restriction\FrontendRestrictionContainer; use TYPO3\CMS\Core\Database\Query\Restriction\QueryRestrictionContainerInterface; +use TYPO3\CMS\Core\Http\ApplicationType; use TYPO3\CMS\Core\Utility\GeneralUtility; /** @@ -34,7 +35,7 @@ public static function getQueryBuilderForTable( QueryRestrictionContainerInterface $restrictionContainer = null ): QueryBuilder { if ($useRestrictionsForCurrentTypo3Mode) { - if (TYPO3_MODE === 'FE') { + if (ApplicationType::fromRequest($GLOBALS['TYPO3_REQUEST'])->isFrontend()) { $restrictionContainer = GeneralUtility::makeInstance(FrontendRestrictionContainer::class); } else { $restrictionContainer = GeneralUtility::makeInstance(BackendRestrictionContainer::class); From 168f28e9239c6aba5ea1b9c8f3062a1bc060d976 Mon Sep 17 00:00:00 2001 From: Hoja Mustaffa Abdul Latheef Date: Tue, 23 Jan 2024 20:09:14 +0100 Subject: [PATCH 09/65] [TASK] Test Suite Updated - Updated Test Suite - Added Testing Docker Configuration --- .github/workflows/ci.yml | 80 ---- .github/workflows/testscorev12.yml | 54 +++ Build/FunctionalTests.xml | 28 ++ Build/FunctionalTestsBootstrap.php | 17 + Build/Scripts/runTests.sh | 395 +++++++++++++++++ Build/UnitTests.xml | 29 ++ Build/UnitTestsBootstrap.php | 75 ++++ .../{.php_cs.php => php-cs-fixer/config.php} | 49 +-- Build/testing-docker/docker-compose.yml | 398 ++++++++++++++++++ 9 files changed, 1019 insertions(+), 106 deletions(-) delete mode 100644 .github/workflows/ci.yml create mode 100644 .github/workflows/testscorev12.yml create mode 100644 Build/FunctionalTests.xml create mode 100644 Build/FunctionalTestsBootstrap.php create mode 100755 Build/Scripts/runTests.sh create mode 100644 Build/UnitTests.xml create mode 100644 Build/UnitTestsBootstrap.php rename Build/{.php_cs.php => php-cs-fixer/config.php} (70%) create mode 100644 Build/testing-docker/docker-compose.yml diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml deleted file mode 100644 index b6819d4..0000000 --- a/.github/workflows/ci.yml +++ /dev/null @@ -1,80 +0,0 @@ -# Adapted from https://github.com/TYPO3GmbH/blog/blob/master/.github/workflows/ci.yml -name: CI - -on: [pull_request] - -jobs: - build: - runs-on: ubuntu-latest - - strategy: - fail-fast: false - matrix: - typo3: [^10.4, ^11.5] - php: ['7.4'] - include: - - typo3: ^11.5 - php: '8.0' - - services: - mysql: - image: mysql:5.6 - env: - MYSQL_ALLOW_EMPTY_PASSWORD: false - MYSQL_ROOT_PASSWORD: password - MYSQL_DATABASE: test - ports: - - 3306/tcp - options: --health-cmd="mysqladmin ping" --health-interval=10s --health-timeout=5s --health-retries=3 - - steps: - - name: Checkout - uses: actions/checkout@v2 - - - name: Setup PHP ${{ matrix.php }}, with composer and extensions - uses: shivammathur/setup-php@v2 - with: - php-version: ${{ matrix.php }} - extensions: mbstring, dom, zip, mysql - - - name: Start mysql service - run: sudo /etc/init.d/mysql start - - - name: Validate composer.json and composer.lock - run: composer validate - - - name: Get composer cache directory - id: composer-cache - run: echo "::set-output name=dir::$(composer config cache-files-dir)" - - - name: Cache composer dependencies - uses: actions/cache@v2 - with: - path: ${{ steps.composer-cache.outputs.dir }} - key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.json') }} - restore-keys: ${{ runner.os }}-composer- - - - name: Install dependencies with typo3/cms-core:${{ matrix.typo3 }} - run: | - composer require typo3/cms-core:${{ matrix.typo3 }} --no-progress - composer require typo3/cms-extensionmanager:${{ matrix.typo3 }} --no-progress - git checkout composer.json - - - name: php-cs-fixer - run: composer ci:php:fixer - - - name: Lint PHP - run: composer ci:php:lint - - - name: Unit Tests - run: composer ci:tests:unit - - - name: Functional Tests - env: - typo3DatabaseName: test - typo3DatabaseUsername: root - typo3DatabasePassword: password - typo3DatabaseHost: 127.0.0.1 - typo3DatabasePort: ${{ job.services.mysql.ports['3306'] }} - run: | - composer ci:tests:functional diff --git a/.github/workflows/testscorev12.yml b/.github/workflows/testscorev12.yml new file mode 100644 index 0000000..0af6bc5 --- /dev/null +++ b/.github/workflows/testscorev12.yml @@ -0,0 +1,54 @@ +name: CI TYPO3 12.4 + +on: pull_request + +jobs: + CGL: + name: Coding Style Check (TYPO3 Community CGL) + + runs-on: ubuntu-latest + + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Composer + run: Build/Scripts/runTests.sh -t 12 -p 8.1 -s composerUpdate + + - name: Lint PHP + run: Build/Scripts/runTests.sh -t 12 -p 8.1 -s lint + + - name: Validate code against CGL + run: Build/Scripts/runTests.sh -t 12 -p 8.1 -s cgl -n + + testsuite: + name: PHP Unit and Functional Tests for TYPO3 Version 12 LTS + + needs: CGL + + runs-on: ubuntu-latest + + strategy: + matrix: + php: + - '8.1' + - '8.2' + + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Composer + run: Build/Scripts/runTests.sh -p ${{ matrix.php }} -t 12 -s composerUpdate + + - name: Unit Tests + run: Build/Scripts/runTests.sh -p ${{ matrix.php }} -s unit + + - name: Functional tests with mariadb + run: Build/Scripts/runTests.sh -p ${{ matrix.php }} -d mariadb -s functional + + - name: Functional tests with sqlite + run: Build/Scripts/runTests.sh -p ${{ matrix.php }} -d sqlite -s functional + + - name: Functional tests with postgres + run: Build/Scripts/runTests.sh -p ${{ matrix.php }} -d postgres -s functional diff --git a/Build/FunctionalTests.xml b/Build/FunctionalTests.xml new file mode 100644 index 0000000..59a41b6 --- /dev/null +++ b/Build/FunctionalTests.xml @@ -0,0 +1,28 @@ + + + + ../Tests/Functional/ + + + + + + + diff --git a/Build/FunctionalTestsBootstrap.php b/Build/FunctionalTestsBootstrap.php new file mode 100644 index 0000000..cbed347 --- /dev/null +++ b/Build/FunctionalTestsBootstrap.php @@ -0,0 +1,17 @@ +defineOriginalRootPath(); + $testbase->createDirectory(ORIGINAL_ROOT . 'typo3temp/var/tests'); + $testbase->createDirectory(ORIGINAL_ROOT . 'typo3temp/var/transient'); +}); diff --git a/Build/Scripts/runTests.sh b/Build/Scripts/runTests.sh new file mode 100755 index 0000000..eee705c --- /dev/null +++ b/Build/Scripts/runTests.sh @@ -0,0 +1,395 @@ +#!/usr/bin/env bash + +# +# TYPO3 core test runner based on docker and docker-compose. +# + +# Function to write a .env file in Build/testing-docker +# This is read by docker-compose and vars defined here are +# used in Build/testing-docker/docker-compose.yml +setUpDockerComposeDotEnv() { + # Delete possibly existing local .env file if exists + [ -e .env ] && rm .env + # Set up a new .env file for docker-compose + { + echo "COMPOSE_PROJECT_NAME=local" + # To prevent access rights of files created by the testing, the docker image later + # runs with the same user that is currently executing the script. docker-compose can't + # use $UID directly itself since it is a shell variable and not an env variable, so + # we have to set it explicitly here. + echo "HOST_UID=`id -u`" + # Your local user + echo "ROOT_DIR=${ROOT_DIR}" + echo "HOST_USER=${USER}" + echo "TEST_FILE=${TEST_FILE}" + echo "TYPO3_VERSION=${TYPO3_VERSION}" + echo "PHP_XDEBUG_ON=${PHP_XDEBUG_ON}" + echo "PHP_XDEBUG_PORT=${PHP_XDEBUG_PORT}" + echo "DOCKER_PHP_IMAGE=${DOCKER_PHP_IMAGE}" + echo "EXTRA_TEST_OPTIONS=${EXTRA_TEST_OPTIONS}" + echo "SCRIPT_VERBOSE=${SCRIPT_VERBOSE}" + echo "CGLCHECK_DRY_RUN=${CGLCHECK_DRY_RUN}" + echo "DATABASE_DRIVER=${DATABASE_DRIVER}" + } > .env +} + +# Options -a and -d depend on each other. The function +# validates input combinations and sets defaults. +handleDbmsAndDriverOptions() { + case ${DBMS} in + mysql|mariadb) + [ -z "${DATABASE_DRIVER}" ] && DATABASE_DRIVER="mysqli" + if [ "${DATABASE_DRIVER}" != "mysqli" ] && [ "${DATABASE_DRIVER}" != "pdo_mysql" ]; then + echo "Invalid option -a ${DATABASE_DRIVER} with -d ${DBMS}" >&2 + echo >&2 + echo "call \"./Build/Scripts/runTests.sh -h\" to display help and valid options" >&2 + exit 1 + fi + ;; + postgres|sqlite) + if [ -n "${DATABASE_DRIVER}" ]; then + echo "Invalid option -a ${DATABASE_DRIVER} with -d ${DBMS}" >&2 + echo >&2 + echo "call \"./Build/Scripts/runTests.sh -h\" to display help and valid options" >&2 + exit 1 + fi + ;; + esac +} + +# Load help text into $HELP +read -r -d '' HELP <=20.10 for xdebug break pointing to work reliably, and +a recent docker-compose (tested >=1.21.2) is needed. + +Usage: $0 [options] [file] + +No arguments: Run all unit tests with PHP 8.1 + +Options: + -s <...> + Specifies which test suite to run + - acceptance: backend acceptance tests + - cgl: cgl test and fix all php files + - clean: clean up build and testing related files + - composerUpdate: "composer update", handy if host has no PHP + - functional: functional tests + - lint: PHP linting + - phpstan: phpstan analyze + - phpstanGenerateBaseline: regenerate phpstan baseline, handy after phpstan updates + - unit (default): PHP unit tests + + -a + Only with -s acceptance,functional + Specifies to use another driver, following combinations are available: + - mysql + - mysqli (default) + - pdo_mysql + - mariadb + - mysqli (default) + - pdo_mysql + + -d + Only with -s acceptance,functional + Specifies on which DBMS tests are performed + - sqlite: (default) use sqlite + - mariadb: use mariadb + - mysql: use mysql + - postgres: use postgres + + + -p <7.4|8.0|8.1|8.2> + Specifies the PHP minor version to be used + - 7.4 (default): use PHP 7.4 + - 8.0: use PHP 8.0 + - 8.1: use PHP 8.1 + - 8.2: use PHP 8.2 + + -t <11|12> + Only with -s composerUpdate + Specifies the TYPO3 core major version to be used + - 11 (default): use TYPO3 core v11 + - 12: Use TYPO3 core v12 + + -e "" + Only with -s acceptance|functional|unit + Additional options to send to phpunit (unit & functional tests) or codeception (acceptance + tests). For phpunit, options starting with "--" must be added after options starting with "-". + Example -e "-v --filter canRetrieveValueWithGP" to enable verbose output AND filter tests + named "canRetrieveValueWithGP" + + -x + Only with -s functional|unit|acceptance + Send information to host instance for test or system under test break points. This is especially + useful if a local PhpStorm instance is listening on default xdebug port 9003. A different port + can be selected with -y + + -n + Only with -s cgl + Activate dry-run in CGL check that does not actively change files and only prints broken ones. + + -u + Update existing typo3/core-testing-*:latest docker images. Maintenance call to docker pull latest + versions of the main php images. The images are updated once in a while and only the youngest + ones are supported by core testing. Use this if weird test errors occur. Also removes obsolete + image versions of typo3/core-testing-*. + + -v + Enable verbose script output. Shows variables and docker commands. + + -h + Show this help. + +Examples: + # Run unit tests using PHP 7.4 + ./Build/Scripts/runTests.sh +EOF + +# Test if docker-compose exists, else exit out with error +if ! type "docker-compose" > /dev/null; then + echo "This script relies on docker and docker-compose. Please install" >&2 + exit 1 +fi + +# Go to the directory this script is located, so everything else is relative +# to this dir, no matter from where this script is called. +THIS_SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null && pwd )" +cd "$THIS_SCRIPT_DIR" || exit 1 + +# Go to directory that contains the local docker-compose.yml file +cd ../testing-docker || exit 1 + +# Option defaults +if ! command -v realpath &> /dev/null; then + echo "This script works best with realpath installed" >&2 + ROOT_DIR="${PWD}/../../" +else + ROOT_DIR=`realpath ${PWD}/../../` +fi +TEST_SUITE="unit" +DBMS="sqlite" +PHP_VERSION="7.4" +TYPO3_VERSION="11" +PHP_XDEBUG_ON=0 +PHP_XDEBUG_PORT=9003 +EXTRA_TEST_OPTIONS="" +SCRIPT_VERBOSE=0 +CGLCHECK_DRY_RUN="" +DATABASE_DRIVER="" + +# Option parsing +# Reset in case getopts has been used previously in the shell +OPTIND=1 +# Array for invalid options +INVALID_OPTIONS=(); +# Simple option parsing based on getopts (! not getopt) +while getopts ":s:a:d:p:t:e:xnhuv" OPT; do + case ${OPT} in + s) + TEST_SUITE=${OPTARG} + ;; + a) + DATABASE_DRIVER=${OPTARG} + ;; + d) + DBMS=${OPTARG} + ;; + p) + PHP_VERSION=${OPTARG} + if ! [[ ${PHP_VERSION} =~ ^(7.4|8.0|8.1|8.2)$ ]]; then + INVALID_OPTIONS+=("p ${OPTARG}") + fi + ;; + t) + TYPO3_VERSION=${OPTARG} + if ! [[ ${TYPO3_VERSION} =~ ^(11|12)$ ]]; then + INVALID_OPTIONS+=("p ${OPTARG}") + fi + ;; + e) + EXTRA_TEST_OPTIONS=${OPTARG} + ;; + x) + PHP_XDEBUG_ON=1 + ;; + y) + PHP_XDEBUG_PORT=${OPTARG} + ;; + h) + echo "${HELP}" + exit 0 + ;; + n) + CGLCHECK_DRY_RUN="-n" + ;; + u) + TEST_SUITE=update + ;; + v) + SCRIPT_VERBOSE=1 + ;; + \?) + INVALID_OPTIONS+=(${OPTARG}) + ;; + :) + INVALID_OPTIONS+=(${OPTARG}) + ;; + esac +done + +# Exit on invalid options +if [ ${#INVALID_OPTIONS[@]} -ne 0 ]; then + echo "Invalid option(s):" >&2 + for I in "${INVALID_OPTIONS[@]}"; do + echo "-"${I} >&2 + done + echo >&2 + echo "${HELP}" >&2 + exit 1 +fi + +# Move "7.4" to "php74", the latter is the docker container name +DOCKER_PHP_IMAGE=`echo "php${PHP_VERSION}" | sed -e 's/\.//'` + +# Set $1 to first mass argument, this is the optional test file or test directory to execute +shift $((OPTIND - 1)) +TEST_FILE=${1} + +if [ ${SCRIPT_VERBOSE} -eq 1 ]; then + set -x +fi + +# Suite execution +case ${TEST_SUITE} in + acceptance) + handleDbmsAndDriverOptions + setUpDockerComposeDotEnv + case ${DBMS} in + sqlite) + echo "Using driver: ${DATABASE_DRIVER}" + docker-compose run acceptance_cli_sqlite + SUITE_EXIT_CODE=$? + ;; + mysql) + echo "Using driver: ${DATABASE_DRIVER}" + docker-compose run acceptance_cli_mysql80 + SUITE_EXIT_CODE=$? + ;; + mariadb) + echo "Using driver: ${DATABASE_DRIVER}" + docker-compose run acceptance_cli_mariadb10 + SUITE_EXIT_CODE=$? + ;; + postgres) + docker-compose run acceptance_cli_postgres10 + SUITE_EXIT_CODE=$? + ;; + *) + echo "Acceptance tests don't run with DBMS ${DBMS}" >&2 + echo >&2 + echo "call \"./Build/Scripts/runTests.sh -h\" to display help and valid options" >&2 + exit 1 + esac + docker-compose down + ;; + cgl) + # Active dry-run for cgl needs not "-n" but specific options + if [[ ! -z ${CGLCHECK_DRY_RUN} ]]; then + CGLCHECK_DRY_RUN="--dry-run --diff" + fi + setUpDockerComposeDotEnv + docker-compose run cgl + SUITE_EXIT_CODE=$? + docker-compose down + ;; + clean) + rm -rf ../../composer.lock ../../.Build/ ../../Tests/Acceptance/Support/_generated/ ../../composer.json.testing + ;; + composerUpdate) + setUpDockerComposeDotEnv + cp ../../composer.json ../../composer.json.orig + if [ -f "../../composer.json.testing" ]; then + cp ../../composer.json ../../composer.json.orig + fi + docker-compose run composer_update + cp ../../composer.json ../../composer.json.testing + mv ../../composer.json.orig ../../composer.json + SUITE_EXIT_CODE=$? + docker-compose down + ;; + functional) + handleDbmsAndDriverOptions + setUpDockerComposeDotEnv + case ${DBMS} in + mariadb) + echo "Using driver: ${DATABASE_DRIVER}" + docker-compose run functional_mariadb10 + SUITE_EXIT_CODE=$? + ;; + mysql) + echo "Using driver: ${DATABASE_DRIVER}" + docker-compose run functional_mysql80 + SUITE_EXIT_CODE=$? + ;; + postgres) + docker-compose run functional_postgres10 + SUITE_EXIT_CODE=$? + ;; + sqlite) + # sqlite has a tmpfs as Web/typo3temp/var/tests/functional-sqlite-dbs/ + # Since docker is executed as root (yay!), the path to this dir is owned by + # root if docker creates it. Thank you, docker. We create the path beforehand + # to avoid permission issues. + mkdir -p ${ROOT_DIR}/Web/typo3temp/var/tests/functional-sqlite-dbs/ + docker-compose run functional_sqlite + SUITE_EXIT_CODE=$? + ;; + *) + echo "Invalid -d option argument ${DBMS}" >&2 + echo >&2 + echo "${HELP}" >&2 + exit 1 + esac + docker-compose down + ;; + lint) + setUpDockerComposeDotEnv + docker-compose run lint + SUITE_EXIT_CODE=$? + docker-compose down + ;; + phpstan) + setUpDockerComposeDotEnv + docker-compose run phpstan + SUITE_EXIT_CODE=$? + docker-compose down + ;; + phpstanGenerateBaseline) + setUpDockerComposeDotEnv + docker-compose run phpstan_generate_baseline + SUITE_EXIT_CODE=$? + docker-compose down + ;; + unit) + setUpDockerComposeDotEnv + docker-compose run unit + SUITE_EXIT_CODE=$? + docker-compose down + ;; + update) + # pull typo3/core-testing-*:latest versions of those ones that exist locally + docker images typo3/core-testing-*:latest --format "{{.Repository}}:latest" | xargs -I {} docker pull {} + # remove "dangling" typo3/core-testing-* images (those tagged as ) + docker images typo3/core-testing-* --filter "dangling=true" --format "{{.ID}}" | xargs -I {} docker rmi {} + ;; + *) + echo "Invalid -s option argument ${TEST_SUITE}" >&2 + echo >&2 + echo "${HELP}" >&2 + exit 1 +esac + +exit $SUITE_EXIT_CODE diff --git a/Build/UnitTests.xml b/Build/UnitTests.xml new file mode 100644 index 0000000..a90da4c --- /dev/null +++ b/Build/UnitTests.xml @@ -0,0 +1,29 @@ + + + + ../Tests/Unit/ + + + + + + + diff --git a/Build/UnitTestsBootstrap.php b/Build/UnitTestsBootstrap.php new file mode 100644 index 0000000..40a161d --- /dev/null +++ b/Build/UnitTestsBootstrap.php @@ -0,0 +1,75 @@ +getWebRoot(), '/')); + } + if (!getenv('TYPO3_PATH_WEB')) { + putenv('TYPO3_PATH_WEB=' . rtrim($testbase->getWebRoot(), '/')); + } + + $testbase->defineSitePath(); + + // We can use the "typo3/cms-composer-installers" constant "TYPO3_COMPOSER_MODE" to determine composer mode. + // This should be always true except for TYPO3 mono repository. + $composerMode = defined('TYPO3_COMPOSER_MODE') && TYPO3_COMPOSER_MODE === true; + $requestType = \TYPO3\CMS\Core\Core\SystemEnvironmentBuilder::REQUESTTYPE_BE | \TYPO3\CMS\Core\Core\SystemEnvironmentBuilder::REQUESTTYPE_CLI; + SystemEnvironmentBuilder::run(0, $requestType, $composerMode); + + $testbase->createDirectory(Environment::getPublicPath() . '/typo3conf/ext'); + $testbase->createDirectory(Environment::getPublicPath() . '/typo3temp/assets'); + $testbase->createDirectory(Environment::getPublicPath() . '/typo3temp/var/tests'); + $testbase->createDirectory(Environment::getPublicPath() . '/typo3temp/var/transient'); + + // Retrieve an instance of class loader and inject to core bootstrap + $classLoader = require $testbase->getPackagesPath() . '/autoload.php'; + Bootstrap::initializeClassLoader($classLoader); + + // Initialize default TYPO3_CONF_VARS + $configurationManager = new ConfigurationManager(); + $GLOBALS['TYPO3_CONF_VARS'] = $configurationManager->getDefaultConfiguration(); + + $cache = new PhpFrontend( + 'core', + new NullBackend('production', []) + ); + $packageManager = Bootstrap::createPackageManager( + UnitTestPackageManager::class, + Bootstrap::createPackageCache($cache) + ); + + GeneralUtility::setSingletonInstance(PackageManager::class, $packageManager); + ExtensionManagementUtility::setPackageManager($packageManager); + + $testbase->dumpClassLoadingInformation(); + + GeneralUtility::purgeInstances(); +})(); diff --git a/Build/.php_cs.php b/Build/php-cs-fixer/config.php similarity index 70% rename from Build/.php_cs.php rename to Build/php-cs-fixer/config.php index 1c8cbc7..aa0a91a 100644 --- a/Build/.php_cs.php +++ b/Build/php-cs-fixer/config.php @@ -1,27 +1,21 @@ name('*.php') ->exclude('.build') - ->exclude('var') ->in(__DIR__); -$config = new PhpCsFixer\Config(); -return $config +return (new \PhpCsFixer\Config()) + ->setFinder($finder) ->setRiskyAllowed(true) ->setRules([ '@DoctrineAnnotation' => true, - '@PSR2' => true, + '@PER' => true, 'header_comment' => [ - 'header' => $headerComment + 'header' => $headerComment, ], 'array_syntax' => ['syntax' => 'short'], 'blank_line_after_opening_tag' => true, @@ -49,9 +42,11 @@ 'concat_space' => ['spacing' => 'one'], 'declare_equal_normalize' => ['space' => 'none'], 'dir_constant' => true, + 'function_to_constant' => ['functions' => ['get_called_class', 'get_class', 'get_class_this', 'php_sapi_name', 'phpversion', 'pi']], 'function_typehint_space' => true, 'lowercase_cast' => true, 'method_argument_space' => ['on_multiline' => 'ensure_fully_multiline'], + 'modernize_strpos' => true, 'modernize_types_casting' => true, 'native_function_casing' => true, 'new_with_braces' => true, @@ -66,13 +61,14 @@ 'no_short_bool_cast' => true, 'no_singleline_whitespace_before_semicolons' => true, 'no_superfluous_elseif' => true, - 'no_trailing_comma_in_singleline_array' => true, + 'no_trailing_comma_in_singleline' => true, 'no_unneeded_control_parentheses' => true, 'no_unused_imports' => true, 'no_useless_else' => true, + 'no_useless_nullsafe_operator' => true, 'no_whitespace_in_blank_line' => true, 'ordered_imports' => true, - 'php_unit_construct' => true, + 'php_unit_construct' => ['assertions' => ['assertEquals', 'assertSame', 'assertNotEquals', 'assertNotSame']], 'php_unit_mock_short_will_return' => true, 'php_unit_test_case_static_method_calls' => ['call_type' => 'self'], 'phpdoc_no_access' => true, @@ -83,9 +79,10 @@ 'phpdoc_types' => true, 'phpdoc_types_order' => ['null_adjustment' => 'always_last', 'sort_algorithm' => 'none'], 'return_type_declaration' => ['space_before' => 'none'], - 'single_line_comment_style' => false, 'single_quote' => true, + 'single_line_comment_style' => ['comment_types' => ['hash']], 'single_trait_insert_per_statement' => true, - 'whitespace_after_comma_in_array' => true - ]) - ->setFinder($finder); + 'trailing_comma_in_multiline' => ['elements' => ['arrays']], + 'whitespace_after_comma_in_array' => ['ensure_single_space' => true], + 'yoda_style' => ['equal' => false, 'identical' => false, 'less_and_greater' => false], + ]); diff --git a/Build/testing-docker/docker-compose.yml b/Build/testing-docker/docker-compose.yml new file mode 100644 index 0000000..692b5ac --- /dev/null +++ b/Build/testing-docker/docker-compose.yml @@ -0,0 +1,398 @@ +version: '2.3' +services: + mariadb10: + # not using mariadb:10 for the time being, because 10.5.7 (currently latest) is broken + image: mariadb:10.5.6 + environment: + MYSQL_ROOT_PASSWORD: funcp + tmpfs: + - /var/lib/mysql/:rw,noexec,nosuid + + mysql80: + image: mysql:8.0 + environment: + MYSQL_ROOT_PASSWORD: funcp + tmpfs: + - /var/lib/mysql/:rw,noexec,nosuid + + postgres10: + image: postgres:10-alpine + environment: + POSTGRES_PASSWORD: funcp + POSTGRES_USER: ${HOST_USER} + tmpfs: + - /var/lib/postgresql/data:rw,noexec,nosuid + + acceptance_cli_mariadb10: + image: typo3/core-testing-${DOCKER_PHP_IMAGE}:latest + user: "${HOST_UID}" + links: + - mariadb10 + environment: + typo3DatabaseDriver: "${DATABASE_DRIVER}" + typo3DatabaseName: func_test + typo3DatabaseUsername: root + typo3DatabasePassword: funcp + typo3DatabaseHost: mariadb10 + volumes: + - ${ROOT_DIR}:${ROOT_DIR} + working_dir: ${ROOT_DIR}/ + extra_hosts: + - "host.docker.internal:host-gateway" + command: > + /bin/sh -c " + if [ ${SCRIPT_VERBOSE} -eq 1 ]; then + set -x + fi + echo Waiting for database start...; + while ! nc -z mariadb10 3306; do + sleep 1; + done; + echo Database is up; + php -v | grep '^PHP'; + mkdir -p .Build/Web/typo3temp/var/tests/ + COMMAND=\".Build/vendor/codeception/codeception/codecept run Cli -d -c Tests/codeception.yml ${TEST_FILE}\" + if [ ${PHP_XDEBUG_ON} -eq 0 ]; then + XDEBUG_MODE=\"off\" $${COMMAND}; + else + XDEBUG_MODE=\"debug,develop\" XDEBUG_TRIGGER=\"foo\" XDEBUG_CONFIG=\"client_host=host.docker.internal\" $${COMMAND}; + fi + " + + acceptance_cli_mysql80: + image: typo3/core-testing-${DOCKER_PHP_IMAGE}:latest + user: "${HOST_UID}" + links: + - mysql80 + environment: + typo3DatabaseDriver: "${DATABASE_DRIVER}" + typo3DatabaseName: func_test + typo3DatabaseUsername: root + typo3DatabasePassword: funcp + typo3DatabaseHost: mysql80 + volumes: + - ${ROOT_DIR}:${ROOT_DIR} + working_dir: ${ROOT_DIR} + extra_hosts: + - "host.docker.internal:host-gateway" + command: > + /bin/sh -c " + if [ ${SCRIPT_VERBOSE} -eq 1 ]; then + set -x + fi + echo Waiting for database start...; + while ! nc -z mysql80 3306; do + sleep 1; + done; + echo Database is up; + php -v | grep '^PHP'; + mkdir -p .Build/Web/typo3temp/var/tests/ + COMMAND=\".Build/vendor/codeception/codeception/codecept run Cli -d -c Tests/codeception.yml ${TEST_FILE}\" + if [ ${PHP_XDEBUG_ON} -eq 0 ]; then + XDEBUG_MODE=\"off\" $${COMMAND}; + else + XDEBUG_MODE=\"debug,develop\" XDEBUG_TRIGGER=\"foo\" XDEBUG_CONFIG=\"client_host=host.docker.internal\" $${COMMAND}; + fi + " + + acceptance_cli_postgres10: + image: typo3/core-testing-${DOCKER_PHP_IMAGE}:latest + user: "${HOST_UID}" + links: + - postgres10 + environment: + typo3DatabaseDriver: pdo_pgsql + typo3DatabaseName: bamboo + typo3DatabaseUsername: ${HOST_USER} + typo3DatabaseHost: postgres10 + typo3DatabasePassword: funcp + volumes: + - ${ROOT_DIR}:${ROOT_DIR} + working_dir: ${ROOT_DIR} + extra_hosts: + - "host.docker.internal:host-gateway" + command: > + /bin/sh -c " + if [ ${SCRIPT_VERBOSE} -eq 1 ]; then + set -x + fi + echo Waiting for database start...; + while ! nc -z postgres10 5432; do + sleep 1; + done; + echo Database is up; + php -v | grep '^PHP'; + mkdir -p .Build/Web/typo3temp/var/tests/ + COMMAND=\".Build/vendor/codeception/codeception/codecept run Cli -d -c Tests/codeception.yml ${TEST_FILE}\" + if [ ${PHP_XDEBUG_ON} -eq 0 ]; then + XDEBUG_MODE=\"off\" $${COMMAND}; + else + XDEBUG_MODE=\"debug,develop\" XDEBUG_TRIGGER=\"foo\" XDEBUG_CONFIG=\"client_host=host.docker.internal\" $${COMMAND}; + fi + " + + acceptance_cli_sqlite: + image: typo3/core-testing-${DOCKER_PHP_IMAGE}:latest + user: "${HOST_UID}" + environment: + typo3DatabaseDriver: pdo_sqlite + volumes: + - ${ROOT_DIR}:${ROOT_DIR} + working_dir: ${ROOT_DIR} + extra_hosts: + - "host.docker.internal:host-gateway" + command: > + /bin/sh -c " + if [ ${SCRIPT_VERBOSE} -eq 1 ]; then + set -x + fi + php -v | grep '^PHP'; + mkdir -p Web/typo3temp/var/tests/ + COMMAND=\".Build/vendor/codeception/codeception/codecept run Cli -d -c Tests/codeception.yml ${TEST_FILE}\" + if [ ${PHP_XDEBUG_ON} -eq 0 ]; then + XDEBUG_MODE=\"off\" $${COMMAND}; + else + XDEBUG_MODE=\"debug,develop\" XDEBUG_TRIGGER=\"foo\" XDEBUG_CONFIG=\"client_host=host.docker.internal\" $${COMMAND}; + fi + " + + cgl: + image: typo3/core-testing-${DOCKER_PHP_IMAGE}:latest + user: "${HOST_UID}" + volumes: + - ${ROOT_DIR}:${ROOT_DIR} + working_dir: ${ROOT_DIR} + extra_hosts: + - "host.docker.internal:host-gateway" + command: > + /bin/sh -c " + if [ ${SCRIPT_VERBOSE} -eq 1 ]; then + set -x + fi + php -v | grep '^PHP'; + if [ ${PHP_XDEBUG_ON} -eq 0 ]; then + php -dxdebug.mode=off .Build/bin/php-cs-fixer fix -v ${CGLCHECK_DRY_RUN} --config=Build/php-cs-fixer/config.php + else + XDEBUG_MODE=\"debug,develop\" XDEBUG_TRIGGER=\"foo\" XDEBUG_CONFIG=\"client_host=host.docker.internal\" PHP_CS_FIXER_ALLOW_XDEBUG=1 .Build/bin/php-cs-fixer fix -v ${CGLCHECK_DRY_RUN} --config=Build/php-cs-fixer/config.php + fi + " + + composer_update: + image: typo3/core-testing-${DOCKER_PHP_IMAGE}:latest + user: "${HOST_UID}" + volumes: + - ${ROOT_DIR}:${ROOT_DIR} + working_dir: ${ROOT_DIR} + environment: + COMPOSER_CACHE_DIR: ".cache/composer" + command: > + /bin/sh -c " + if [ ${SCRIPT_VERBOSE} -eq 1 ]; then + set -x + fi + php -v | grep '^PHP'; + if [ ${TYPO3_VERSION} -eq 11 ]; then + composer req --dev --no-update typo3/cms-composer-installers:^3.0 typo3/cms-workspaces:^11.5 typo3/cms-impexp:^11.5 + composer req typo3/cms-core:^11.5 --no-update + fi + if [ ${TYPO3_VERSION} -eq 12 ]; then + composer req --dev --no-update "typo3/cms-composer-installers:^5.0" typo3/cms-impexp:^12.4 typo3/cms-workspaces:^12.4 + composer req typo3/cms-core:^12.4 --no-update + fi + composer update --no-progress --no-interaction; + " + + functional_mariadb10: + image: typo3/core-testing-${DOCKER_PHP_IMAGE}:latest + user: "${HOST_UID}" + links: + - mariadb10 + volumes: + - ${ROOT_DIR}:${ROOT_DIR} + environment: + typo3DatabaseDriver: "${DATABASE_DRIVER}" + typo3DatabaseName: func_test + typo3DatabaseUsername: root + typo3DatabasePassword: funcp + typo3DatabaseHost: mariadb10 + working_dir: ${ROOT_DIR} + extra_hosts: + - "host.docker.internal:host-gateway" + command: > + /bin/sh -c " + if [ ${SCRIPT_VERBOSE} -eq 1 ]; then + set -x + fi + echo Waiting for database start...; + while ! nc -z mariadb10 3306; do + sleep 1; + done; + echo Database is up; + php -v | grep '^PHP'; + if [ ${PHP_XDEBUG_ON} -eq 0 ]; then + php -dxdebug.mode=off .Build/bin/phpunit -c Build/FunctionalTests.xml ${EXTRA_TEST_OPTIONS} ${TEST_FILE}; + else + php -dxdebug.mode='debug,develop' XDEBUG_TRIGGER='foo' XDEBUG_CONFIG='client_host=host.docker.internal' .Build/bin/phpunit -c Build/FunctionalTests.xml ${EXTRA_TEST_OPTIONS} ${TEST_FILE}; + fi + " + + functional_mysql80: + image: typo3/core-testing-${DOCKER_PHP_IMAGE}:latest + user: "${HOST_UID}" + links: + - mysql80 + volumes: + - ${ROOT_DIR}:${ROOT_DIR} + environment: + typo3DatabaseDriver: "${DATABASE_DRIVER}" + typo3DatabaseName: func_test + typo3DatabaseUsername: root + typo3DatabasePassword: funcp + typo3DatabaseHost: mysql80 + working_dir: ${ROOT_DIR} + extra_hosts: + - "host.docker.internal:host-gateway" + command: > + /bin/sh -c " + if [ ${SCRIPT_VERBOSE} -eq 1 ]; then + set -x + fi + echo Waiting for database start...; + while ! nc -z mysql80 3306; do + sleep 1; + done; + echo Database is up; + php -v | grep '^PHP'; + if [ ${PHP_XDEBUG_ON} -eq 0 ]; then + XDEBUG_MODE=\"off\" .Build/bin/phpunit -c Build/FunctionalTests.xml ${EXTRA_TEST_OPTIONS} ${TEST_FILE}; + else + XDEBUG_MODE=\"debug,develop\" XDEBUG_TRIGGER=\"foo\" XDEBUG_CONFIG=\"client_host=host.docker.internal\" .Build/bin/phpunit -c Build/FunctionalTests.xml ${EXTRA_TEST_OPTIONS} ${TEST_FILE}; + fi + " + + functional_postgres10: + image: typo3/core-testing-${DOCKER_PHP_IMAGE}:latest + user: "${HOST_UID}" + links: + - postgres10 + volumes: + - ${ROOT_DIR}:${ROOT_DIR} + environment: + typo3DatabaseDriver: pdo_pgsql + typo3DatabaseName: bamboo + typo3DatabaseUsername: ${HOST_USER} + typo3DatabaseHost: postgres10 + typo3DatabasePassword: funcp + working_dir: ${ROOT_DIR} + extra_hosts: + - "host.docker.internal:host-gateway" + command: > + /bin/sh -c " + if [ ${SCRIPT_VERBOSE} -eq 1 ]; then + set -x + fi + echo Waiting for database start...; + while ! nc -z postgres10 5432; do + sleep 1; + done; + echo Database is up; + php -v | grep '^PHP'; + if [ ${PHP_XDEBUG_ON} -eq 0 ]; then + XDEBUG_MODE=\"off\" .Build/bin/phpunit -c Build/FunctionalTests.xml ${EXTRA_TEST_OPTIONS} --exclude-group not-postgres ${TEST_FILE}; + else + XDEBUG_MODE=\"debug,develop\" XDEBUG_TRIGGER=\"foo\" XDEBUG_CONFIG=\"client_host=host.docker.internal\" .Build/bin/phpunit -c Build/FunctionalTests.xml ${EXTRA_TEST_OPTIONS} --exclude-group not-postgres ${TEST_FILE}; + fi + " + + functional_sqlite: + image: typo3/core-testing-${DOCKER_PHP_IMAGE}:latest + user: "${HOST_UID}" + volumes: + - ${ROOT_DIR}:${ROOT_DIR} + tmpfs: + - ${ROOT_DIR}/Web/typo3temp/var/tests/functional-sqlite-dbs/:rw,noexec,nosuid,uid=${HOST_UID} + environment: + typo3DatabaseDriver: pdo_sqlite + working_dir: ${ROOT_DIR} + extra_hosts: + - "host.docker.internal:host-gateway" + command: > + /bin/sh -c " + if [ ${SCRIPT_VERBOSE} -eq 1 ]; then + set -x + fi + php -v | grep '^PHP'; + if [ ${PHP_XDEBUG_ON} -eq 0 ]; then + XDEBUG_MODE=\"off\" .Build/bin/phpunit -c Build/FunctionalTests.xml ${EXTRA_TEST_OPTIONS} --exclude-group not-sqlite ${TEST_FILE}; + else + XDEBUG_MODE=\"debug,develop\" XDEBUG_TRIGGER=\"foo\" XDEBUG_CONFIG=\"client_host=host.docker.internal\" .Build/bin/phpunit -c Build/FunctionalTests.xml ${EXTRA_TEST_OPTIONS} --exclude-group not-sqlite ${TEST_FILE}; + fi + " + + lint: + image: typo3/core-testing-${DOCKER_PHP_IMAGE}:latest + user: "${HOST_UID}" + volumes: + - ${ROOT_DIR}:${ROOT_DIR} + working_dir: ${ROOT_DIR} + command: > + /bin/sh -c " + if [ ${SCRIPT_VERBOSE} -eq 1 ]; then + set -x + fi + php -v | grep '^PHP'; + find . -name \\*.php ! -path "./.Build/\\*" -print0 | xargs -0 -n1 -P4 php -dxdebug.mode=off -l >/dev/null + " + + phpstan: + image: typo3/core-testing-${DOCKER_PHP_IMAGE}:latest + user: "${HOST_UID}" + volumes: + - ${ROOT_DIR}:${ROOT_DIR} + working_dir: ${ROOT_DIR} + command: > + /bin/sh -c " + if [ ${SCRIPT_VERBOSE} -eq 1 ]; then + set -x + fi + mkdir -p .Build/.cache + php -v | grep '^PHP'; + php -dxdebug.mode=off .Build/bin/phpstan analyze -c Build/phpstan.neon --no-progress + " + + phpstan_generate_baseline: + image: typo3/core-testing-${DOCKER_PHP_IMAGE}:latest + user: "${HOST_UID}" + volumes: + - ${ROOT_DIR}:${ROOT_DIR} + working_dir: ${ROOT_DIR} + command: > + /bin/sh -c " + if [ ${SCRIPT_VERBOSE} -eq 1 ]; then + set -x + fi + mkdir -p .Build/.cache + php -v | grep '^PHP'; + php -dxdebug.mode=off .Build/bin/phpstan analyze -c Build/phpstan.neon --generate-baseline=Build/phpstan-baseline.neon + " + + unit: + image: typo3/core-testing-${DOCKER_PHP_IMAGE}:latest + user: "${HOST_UID}" + volumes: + - ${ROOT_DIR}:${ROOT_DIR} + working_dir: ${ROOT_DIR} + extra_hosts: + - "host.docker.internal:host-gateway" + command: > + /bin/sh -c " + if [ ${SCRIPT_VERBOSE} -eq 1 ]; then + set -x + fi + php -v | grep '^PHP'; + if [ ${PHP_XDEBUG_ON} -eq 0 ]; then + XDEBUG_MODE=\"off\" .Build/bin/phpunit -c Build/UnitTests.xml ${EXTRA_TEST_OPTIONS} ${TEST_FILE}; + else + XDEBUG_MODE=\"debug,develop\" XDEBUG_TRIGGER=\"foo\" XDEBUG_CONFIG=\"client_host=host.docker.internal\" .Build/bin/phpunit -c Build/UnitTests.xml ${EXTRA_TEST_OPTIONS} ${TEST_FILE}; + fi + " \ No newline at end of file From b9dd1b1f956c2b5b284a48770a70ef1af5f7b17d Mon Sep 17 00:00:00 2001 From: Hoja Mustaffa Abdul Latheef Date: Tue, 23 Jan 2024 20:09:36 +0100 Subject: [PATCH 10/65] Version details added --- composer.json | 42 ++++++++++++++++++------------------------ ext_emconf.php | 8 ++++---- 2 files changed, 22 insertions(+), 28 deletions(-) diff --git a/composer.json b/composer.json index a9be945..bd44cb9 100644 --- a/composer.json +++ b/composer.json @@ -10,6 +10,11 @@ "name": "Stefan Froemken", "email": "sfroemken@jweiland.net", "role": "Lead Developer" + }, + { + "name": "Hoja Mustaffa Abdul Latheef", + "email": "projects@jweiland.net", + "role": "Senior Developer" } ], "support": { @@ -18,15 +23,15 @@ "source": "https://github.com/jweiland-net/jwtools2" }, "require": { - "typo3/cms-core": "^10.4.33 || ^11.5.20", - "typo3/cms-scheduler": "^10.4.33 || ^11.5.20" + "typo3/cms-core": "^12.4.9", + "typo3/cms-scheduler": "^v12.4.9" }, "require-dev": { + "friendsofphp/php-cs-fixer": "^3.14", + "phpunit/phpunit": "^9.6", "roave/security-advisories": "dev-latest", - "friendsofphp/php-cs-fixer": "^3.10", - "nimut/testing-framework": "^6.0", - "phpunit/phpunit": "^9.5", - "phpspec/prophecy-phpunit": "^2.0" + "typo3/coding-standards": "^0.6", + "typo3/testing-framework": "^7.0.2" }, "replace": { "typo3-ter/jwtools2": "self.version" @@ -42,30 +47,19 @@ } }, "config": { - "vendor-dir": ".build/vendor", + "sort-packages": true, + "vendor-dir": ".Build/vendor", + "bin-dir": ".Build/bin", "allow-plugins": { "typo3/class-alias-loader": true, "typo3/cms-composer-installers": true - } }, + } + }, "extra": { "typo3/cms": { "extension-key": "jwtools2", - "app-dir": ".build", - "web-dir": ".build/public" + "app-dir": ".Build", + "web-dir": ".Build/public" } - }, - "scripts": { - "php:fix": ".build/vendor/bin/php-cs-fixer --config=Build/.php_cs.php fix Classes Tests", - "ci:php:lint": "find *.php Classes Configuration Tests -name '*.php' -print0 | xargs -0 -n 1 -P 4 php -l", - "ci:php:fixer": ".build/vendor/bin/php-cs-fixer --config=Build/.php_cs.php fix --dry-run -v --show-progress=dots --diff Classes Tests", - "ci:tests:unit": "php .build/vendor/bin/phpunit -c .build/vendor/nimut/testing-framework/res/Configuration/UnitTests.xml Tests/Unit", - "ci:tests:functional": "find 'Tests/Functional' -wholename '*Test.php' | parallel --gnu 'echo; echo \"Running functional test suite {}\"; php .build/vendor/bin/phpunit -c .build/vendor/nimut/testing-framework/res/Configuration/FunctionalTests.xml {}';", - "link-extension": [ - "@php -r 'is_dir($extFolder=__DIR__.\"/.build/public/typo3conf/ext/\") || mkdir($extFolder, 0777, true);'", - "@php -r 'file_exists($extFolder=__DIR__.\"/.build/public/typo3conf/ext/jwtools2\") || symlink(__DIR__,$extFolder);'" - ], - "post-autoload-dump": [ - "@link-extension" - ] } } diff --git a/ext_emconf.php b/ext_emconf.php index 81e02f3..369a6a0 100644 --- a/ext_emconf.php +++ b/ext_emconf.php @@ -6,19 +6,19 @@ SQL-Queries. Further there are settings to enable some features in TYPO3 like showing the Page UID in Pagetree with a simple click in extensionmanager.', 'category' => 'module', - 'author' => 'Stefan Froemken', + 'author' => 'Stefan Froemken, Hoja Mustaffa Abdul Latheef', 'author_email' => 'projects@jweiland.net', 'author_company' => 'jweiland.net', 'state' => 'stable', - 'version' => '6.0.6', + 'version' => '7.0.0', 'constraints' => [ 'depends' => [ - 'typo3' => '10.4.33-11.5.99', + 'typo3' => '12.4.9-12.4.99', ], 'conflicts' => [ ], 'suggests' => [ - 'solr' => '11.2.0-11.99.99', + 'solr' => '12.0.0-0.0.0', ], ], ]; From edf5418c2eda7b09ed7f44da6fdafd37a88e178e Mon Sep 17 00:00:00 2001 From: Hoja Mustaffa Abdul Latheef Date: Tue, 23 Jan 2024 20:10:02 +0100 Subject: [PATCH 11/65] ReadMe updated with better badges and new CI status --- README.md | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 2ce4628..0bd7b73 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,11 @@ # TYPO3 Extension `jwtools2` -![Build Status](https://github.com/jweiland-net/jwtools2/workflows/CI/badge.svg) +[![Latest Stable Version](https://poser.pugx.org/jweiland/jwtools2/v/stable.svg)](https://packagist.org/packages/jweiland/jwtools2) +[![TYPO3 12.4](https://img.shields.io/badge/TYPO3-12.4-green.svg)](https://get.typo3.org/version/12) +[![License](http://poser.pugx.org/jweiland/jwtools2/license)](https://packagist.org/packages/jweiland/jwtools2) +[![Total Downloads](https://poser.pugx.org/jweiland/jwtools2/downloads.svg)](https://packagist.org/packages/jweiland/jwtools2) +[![Monthly Downloads](https://poser.pugx.org/jweiland/jwtools2/d/monthly)](https://packagist.org/packages/jweiland/jwtools2) +![Build Status](https://github.com/jweiland-net/jwtools2/actions/workflows/testscorev12.yml/badge.svg) Implement various helpful features to TYPO3 and some extensions From 3542d3c47e73bb3a724fb465d350f8ae31950da9 Mon Sep 17 00:00:00 2001 From: Hoja Mustaffa Abdul Latheef Date: Wed, 24 Jan 2024 12:54:15 +0100 Subject: [PATCH 12/65] [BUGFIX] Replaced Interface with Abstract class and replaced its implementation with extend keyword --- Classes/Task/ExecuteQueryTaskAdditionalFieldProvider.php | 3 +-- Classes/Task/IndexQueueWorkerTaskAdditionalFieldProvider.php | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/Classes/Task/ExecuteQueryTaskAdditionalFieldProvider.php b/Classes/Task/ExecuteQueryTaskAdditionalFieldProvider.php index 2cb7f9f..20a1235 100644 --- a/Classes/Task/ExecuteQueryTaskAdditionalFieldProvider.php +++ b/Classes/Task/ExecuteQueryTaskAdditionalFieldProvider.php @@ -12,7 +12,6 @@ use TYPO3\CMS\Extbase\Utility\LocalizationUtility; use TYPO3\CMS\Scheduler\AbstractAdditionalFieldProvider; -use TYPO3\CMS\Scheduler\AdditionalFieldProviderInterface; use TYPO3\CMS\Scheduler\Controller\SchedulerModuleController; use TYPO3\CMS\Scheduler\Task\AbstractTask; use TYPO3\CMS\Scheduler\Task\Enumeration\Action; @@ -20,7 +19,7 @@ /** * Additional field provider for the execute query task */ -class ExecuteQueryTaskAdditionalFieldProvider implements AbstractAdditionalFieldProvider +class ExecuteQueryTaskAdditionalFieldProvider extends AbstractAdditionalFieldProvider { /** * Used to define fields to provide the TYPO3 site to index and number of diff --git a/Classes/Task/IndexQueueWorkerTaskAdditionalFieldProvider.php b/Classes/Task/IndexQueueWorkerTaskAdditionalFieldProvider.php index 4a0c43d..347ac2f 100644 --- a/Classes/Task/IndexQueueWorkerTaskAdditionalFieldProvider.php +++ b/Classes/Task/IndexQueueWorkerTaskAdditionalFieldProvider.php @@ -20,7 +20,7 @@ /** * Additional field provider for the index queue worker task */ -class IndexQueueWorkerTaskAdditionalFieldProvider implements AbstractAdditionalFieldProvider +class IndexQueueWorkerTaskAdditionalFieldProvider extends AbstractAdditionalFieldProvider { /** * Used to define fields to provide the TYPO3 site to index and number of From 4a601dde63046d04a56fba5b1bb99dadd2381f09 Mon Sep 17 00:00:00 2001 From: Hoja Mustaffa Abdul Latheef Date: Mon, 29 Jan 2024 11:36:43 +0100 Subject: [PATCH 13/65] Icon registration moved to Configuration/Icons.php --- Configuration/Icons.php | 8 ++++++++ 1 file changed, 8 insertions(+) create mode 100644 Configuration/Icons.php diff --git a/Configuration/Icons.php b/Configuration/Icons.php new file mode 100644 index 0000000..e2c5e65 --- /dev/null +++ b/Configuration/Icons.php @@ -0,0 +1,8 @@ + [ + 'provider' => \TYPO3\CMS\Core\Imaging\IconProvider\SvgIconProvider::class, + 'source' => 'EXT:jwtools2/Resources/Public/Icons/module_tools.svg' + ], +]; From 6fd803e72f58430d2843f8ba7d56d27c27bfa08f Mon Sep 17 00:00:00 2001 From: Hoja Mustaffa Abdul Latheef Date: Mon, 29 Jan 2024 11:37:54 +0100 Subject: [PATCH 14/65] BackendModule registration moved to Configuration/Backend/Modules.php --- Configuration/Backend/Modules.php | 30 ++++++++++++++++++++++++++++++ ext_localconf.php | 10 ---------- 2 files changed, 30 insertions(+), 10 deletions(-) create mode 100644 Configuration/Backend/Modules.php diff --git a/Configuration/Backend/Modules.php b/Configuration/Backend/Modules.php new file mode 100644 index 0000000..3cf2d53 --- /dev/null +++ b/Configuration/Backend/Modules.php @@ -0,0 +1,30 @@ + [ + 'parent' => 'tools', + 'position' => ['after' => 'web_info'], + 'access' => 'user,group', + 'workspaces' => 'live', + 'path' => '/module/web/club', + 'labels' => 'LLL:EXT:jwtools2/Resources/Private/Language/locallang_module_tools.xlf', + 'iconIdentifier' => 'ext-jwtools2-be-module-icon', + 'extensionName' => 'jwtools2', + 'controllerActions' => [ + ToolsController::class => [ + 'overview', + ], + SolrController::class => [ + 'list, show, showIndexQueue, indexOneRecord, createIndexQueueForAllSites, showClearFullIndexForm, showClearIndexForm, clearIndex', + ], + ], + ], +]; diff --git a/ext_localconf.php b/ext_localconf.php index 3781af4..ee4cbe8 100644 --- a/ext_localconf.php +++ b/ext_localconf.php @@ -5,9 +5,6 @@ } call_user_func(static function () { - $signalSlotDispatcher = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance( - \TYPO3\CMS\Extbase\SignalSlot\Dispatcher::class - ); $jwToolsConfiguration = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance( \TYPO3\CMS\Core\Configuration\ExtensionConfiguration::class )->get('jwtools2'); @@ -34,13 +31,6 @@ 'description' => 'LLL:EXT:jwtools2/Resources/Private/Language/locallang.xlf:indexqueueworker_description', 'additionalFields' => \JWeiland\Jwtools2\Task\IndexQueueWorkerTaskAdditionalFieldProvider::class, ]; - // Hook into Solr Index Service - $signalSlotDispatcher->connect( - \ApacheSolrForTypo3\Solr\Domain\Index\IndexService::class, - 'beforeIndexItem', - \JWeiland\Jwtools2\Hooks\IndexService::class, - 'beforeIndexItem' - ); } if ($jwToolsConfiguration['enableSqlQueryTask'] ?? false) { From ef5cc3321e7b7fd32a52d9d8826175c167a88c0c Mon Sep 17 00:00:00 2001 From: Hoja Mustaffa Abdul Latheef Date: Mon, 29 Jan 2024 11:38:19 +0100 Subject: [PATCH 15/65] BackendModule registration moved to Configuration/Backend/Modules.php --- ext_tables.php | 16 ---------------- 1 file changed, 16 deletions(-) diff --git a/ext_tables.php b/ext_tables.php index ee84632..01be305 100644 --- a/ext_tables.php +++ b/ext_tables.php @@ -3,19 +3,3 @@ if (!defined('TYPO3')) { die('Access denied.'); } - -\TYPO3\CMS\Extbase\Utility\ExtensionUtility::registerModule( - 'jwtools2', - 'tools', - 'tools', - '', - [ - \JWeiland\Jwtools2\Controller\ToolsController::class => 'overview', - \JWeiland\Jwtools2\Controller\SolrController::class => 'list, show, showIndexQueue, indexOneRecord, createIndexQueueForAllSites, showClearFullIndexForm, showClearIndexForm, clearIndex', - ], - [ - 'access' => 'user,group', - 'icon' => 'EXT:jwtools2/Resources/Public/Icons/module_tools.svg', - 'labels' => 'LLL:EXT:jwtools2/Resources/Private/Language/locallang_module_tools.xlf', - ] -); From c7e41473e9921fe1f4c809028d9b4de8e6e5e226 Mon Sep 17 00:00:00 2001 From: Hoja Mustaffa Abdul Latheef Date: Tue, 30 Jan 2024 17:01:30 +0100 Subject: [PATCH 16/65] [TASK] Fixing Backend module configurations and paths --- Classes/Backend/AbstractDocHeader.php | 31 +++++---------- Classes/Backend/Browser/FileBrowser.php | 14 +------ Classes/Backend/SolrDocHeader.php | 5 +++ Classes/Controller/AbstractController.php | 27 +++++++++---- Classes/Controller/SolrController.php | 38 +++++++++---------- Classes/Controller/ToolsController.php | 15 ++++++-- .../IndexServiceEventListener.php | 27 +++++++++++++ .../ReduceCategoryTreeToPageTree.php | 2 +- Classes/Provider/ReportProvider.php | 5 +++ Configuration/Backend/Modules.php | 6 +-- Configuration/Services.yaml | 9 ++++- 11 files changed, 109 insertions(+), 70 deletions(-) create mode 100644 Classes/EventListener/IndexServiceEventListener.php rename Classes/{Tca => EventListener}/ReduceCategoryTreeToPageTree.php (99%) diff --git a/Classes/Backend/AbstractDocHeader.php b/Classes/Backend/AbstractDocHeader.php index 4a18949..738cb01 100644 --- a/Classes/Backend/AbstractDocHeader.php +++ b/Classes/Backend/AbstractDocHeader.php @@ -10,6 +10,7 @@ namespace JWeiland\Jwtools2\Backend; +use TYPO3\CMS\Backend\Template\ModuleTemplate; use TYPO3\CMS\Backend\View\BackendTemplateView; use TYPO3\CMS\Core\Imaging\Icon; use TYPO3\CMS\Core\Imaging\IconFactory; @@ -17,35 +18,22 @@ use TYPO3\CMS\Extbase\Mvc\Request; use TYPO3\CMS\Extbase\Mvc\View\ViewInterface; use TYPO3\CMS\Extbase\Mvc\Web\Routing\UriBuilder; +use TYPO3\CMS\Fluid\View\TemplateView; /** * Abstract DocHeader for Backend Modules */ abstract class AbstractDocHeader { - /** - * @var UriBuilder - */ - protected $uriBuilder; + protected ?UriBuilder $uriBuilder = null; - /** - * @var IconFactory - */ - protected $iconFactory; + protected IconFactory $iconFactory; - /** - * @var BackendTemplateView - */ - protected $view; + protected ModuleTemplate $view; - /** - * The current request. - * - * @var Request - */ - protected $request; + protected Request $request; - public function __construct(Request $request, ViewInterface $view) + public function __construct(Request $request, ModuleTemplate $view) { $this->request = $request; $this->view = $view; @@ -63,7 +51,8 @@ public function injectIconFactory(IconFactory $iconFactory): void protected function addHelpButton(): void { - $buttonBar = $this->view->getModuleTemplate() + debug($this->view); + $buttonBar = $this->view ->getDocHeaderComponent() ->getButtonBar(); @@ -78,7 +67,6 @@ protected function addHelpButton(): void protected function addShortcutButton(): void { $buttonBar = $this->view - ->getModuleTemplate() ->getDocHeaderComponent() ->getButtonBar(); @@ -94,7 +82,6 @@ protected function addShortcutButton(): void protected function addCloseButton(): void { $buttonBar = $this->view - ->getModuleTemplate() ->getDocHeaderComponent() ->getButtonBar(); diff --git a/Classes/Backend/Browser/FileBrowser.php b/Classes/Backend/Browser/FileBrowser.php index dee1366..1867bd1 100644 --- a/Classes/Backend/Browser/FileBrowser.php +++ b/Classes/Backend/Browser/FileBrowser.php @@ -19,11 +19,11 @@ use TYPO3\CMS\Core\Database\ConnectionPool; use TYPO3\CMS\Core\Information\Typo3Version; use TYPO3\CMS\Core\Localization\LanguageService; -use TYPO3\CMS\Core\Messaging\AbstractMessage; use TYPO3\CMS\Core\Messaging\FlashMessage; use TYPO3\CMS\Core\Messaging\FlashMessageService; use TYPO3\CMS\Core\Resource\File; use TYPO3\CMS\Core\Resource\FileInterface; +use TYPO3\CMS\Core\Type\ContextualFeedbackSeverity; use TYPO3\CMS\Core\Utility\GeneralUtility; use TYPO3\CMS\Extbase\Utility\LocalizationUtility; @@ -33,16 +33,6 @@ */ class FileBrowser extends \TYPO3\CMS\Backend\ElementBrowser\FileBrowser { - /** - * @var ExtensionConfiguration - */ - protected $extensionConfiguration; - - public function injectExtensionConfiguration(ExtensionConfiguration $extensionConfiguration): void - { - $this->extensionConfiguration = $extensionConfiguration; - } - /** * Only load additional JavaScript, if in file or folder context */ @@ -84,7 +74,7 @@ public function isValid(string $mode, ElementBrowserController $elementBrowserCo LocalizationUtility::translate( 'LLL:EXT:jwtools2/Resources/Private/Language/locallang_mod.xlf:fileBrowser.flashMessage.requiredColumns.title' ), - AbstractMessage::INFO + ContextualFeedbackSeverity::INFO ) ); } diff --git a/Classes/Backend/SolrDocHeader.php b/Classes/Backend/SolrDocHeader.php index c96071d..98619d5 100644 --- a/Classes/Backend/SolrDocHeader.php +++ b/Classes/Backend/SolrDocHeader.php @@ -11,6 +11,8 @@ namespace JWeiland\Jwtools2\Backend; use TYPO3\CMS\Core\Imaging\Icon; +use TYPO3\CMS\Core\Utility\GeneralUtility; +use TYPO3\CMS\Extbase\Mvc\Web\Routing\UriBuilder; /** * DocHeader for our Solr Module @@ -20,6 +22,9 @@ class SolrDocHeader extends AbstractDocHeader public function renderDocHeader(): void { // initialize UriBuilder + if (!($this->uriBuilder instanceof UriBuilder)) { + $this->uriBuilder = GeneralUtility::makeInstance(UriBuilder::class); + } $this->uriBuilder->setRequest($this->request); // Render Buttons diff --git a/Classes/Controller/AbstractController.php b/Classes/Controller/AbstractController.php index f41b187..c2771bb 100644 --- a/Classes/Controller/AbstractController.php +++ b/Classes/Controller/AbstractController.php @@ -10,12 +10,15 @@ namespace JWeiland\Jwtools2\Controller; +use TYPO3\CMS\Backend\Routing\UriBuilder; +use TYPO3\CMS\Backend\Template\Components\Menu\Menu; +use TYPO3\CMS\Backend\Template\ModuleTemplate; use TYPO3\CMS\Backend\Template\ModuleTemplateFactory; -use TYPO3\CMS\Backend\View\BackendTemplateView; use TYPO3\CMS\Core\Configuration\ExtensionConfiguration; +use TYPO3\CMS\Core\Utility\ArrayUtility; use TYPO3\CMS\Core\Utility\GeneralUtility; use TYPO3\CMS\Extbase\Mvc\Controller\ActionController; -use TYPO3\CMS\Extbase\Mvc\View\ViewInterface; +use TYPO3\CMS\Fluid\View\TemplateView; /** * Class AbstractController @@ -24,20 +27,30 @@ abstract class AbstractController extends ActionController { protected ModuleTemplateFactory $moduleTemplateFactory; - public function __construct(ModuleTemplateFactory $moduleTemplateFactory) + protected ModuleTemplate $moduleTemplate; + + protected UriBuilder $backendUriBuilder; + + public function __construct(ModuleTemplateFactory $moduleTemplateFactory, UriBuilder $backendUriBuilder) { $this->moduleTemplateFactory = $moduleTemplateFactory; + $this->backendUriBuilder = $backendUriBuilder; } /** * Initializes the view before invoking an action method. * Override this method to solve assign variables common for all actions * or prepare the view in another way before the action is called. - * - * @param ViewInterface $view The view to be initialized */ - protected function initializeView(ViewInterface $view): void + protected function initializeView( TemplateView $view): void + { + $this->moduleTemplate = $this->moduleTemplateFactory->create($this->request); + $this->moduleTemplate->assign('extConf', $this->getExtensionConfiguration()); + } + + protected function getExtensionConfiguration(): array { - $view->assign('extConf', GeneralUtility::makeInstance(ExtensionConfiguration::class)->get('jwtools2')); + $extensionConfiguration = GeneralUtility::makeInstance(ExtensionConfiguration::class)->get('jwtools2'); + return is_array($extensionConfiguration) ? $extensionConfiguration : []; } } diff --git a/Classes/Controller/SolrController.php b/Classes/Controller/SolrController.php index f7ce174..d126599 100644 --- a/Classes/Controller/SolrController.php +++ b/Classes/Controller/SolrController.php @@ -20,6 +20,10 @@ use JWeiland\Jwtools2\Domain\Repository\SolrRepository; use JWeiland\Jwtools2\Service\SolrService; use Psr\Http\Message\ResponseInterface; +use Psr\Http\Message\ServerRequestInterface; +use TYPO3\CMS\Backend\Attribute\AsController; +use TYPO3\CMS\Backend\Template\ModuleTemplate; +use TYPO3\CMS\Backend\Template\ModuleTemplateFactory; use TYPO3\CMS\Core\Database\ConnectionPool; use TYPO3\CMS\Core\Messaging\AbstractMessage; use TYPO3\CMS\Core\Page\PageRenderer; @@ -30,25 +34,16 @@ use TYPO3\CMS\Extbase\Mvc\View\NotFoundView; use TYPO3\CMS\Extbase\Mvc\View\ViewInterface; -/** - * Class SolrController - */ +#[AsController] class SolrController extends AbstractController { - /** - * @var SolrRepository - */ - protected $solrRepository; + protected SolrRepository $solrRepository; - /** - * @var SchedulerRepository - */ - protected $schedulerRepository; + protected SchedulerRepository $schedulerRepository; - /** - * @var Registry - */ - protected $registry; + protected Registry $registry; + + protected PageRenderer $pageRenderer; public function injectSolrRepository(SolrRepository $solrRepository): void { @@ -65,17 +60,20 @@ public function injectRegistry(Registry $registry): void $this->registry = $registry; } - public function initializeView(ViewInterface $view): void + public function injectPageRenderer(PageRenderer $pageRenderer): void + { + $this->pageRenderer = $pageRenderer; + } + + public function initializeView($view): void { if (!$view instanceof NotFoundView) { parent::initializeView($view); - /** @var PageRenderer $pageRenderer */ - $pageRenderer = $this->objectManager->get(PageRenderer::class); - $pageRenderer->loadRequireJsModule('TYPO3/CMS/Jwtools2/SolrIndex'); + $this->pageRenderer->loadJavaScriptModule('TYPO3/CMS/Jwtools2/SolrIndex'); /** @var SolrDocHeader $docHeader */ - $docHeader = $this->objectManager->get(SolrDocHeader::class, $this->request, $view); + $docHeader = GeneralUtility::makeInstance(SolrDocHeader::class, $this->request, $this->moduleTemplate); $docHeader->renderDocHeader(); if (!$this->schedulerRepository->findSolrSchedulerTask()) { diff --git a/Classes/Controller/ToolsController.php b/Classes/Controller/ToolsController.php index 1d626d1..0270735 100644 --- a/Classes/Controller/ToolsController.php +++ b/Classes/Controller/ToolsController.php @@ -11,14 +11,21 @@ namespace JWeiland\Jwtools2\Controller; use Psr\Http\Message\ResponseInterface; +use Psr\Http\Message\ServerRequestInterface; +use TYPO3\CMS\Backend\Attribute\AsController; +use TYPO3\CMS\Backend\Template\ModuleTemplate; +use TYPO3\CMS\Backend\Template\ModuleTemplateFactory; -/** - * Class ToolsController - */ +#[AsController] class ToolsController extends AbstractController { + public function initializeAction(): void + { + parent::initializeAction(); + } + public function overviewAction(): ResponseInterface { - return $this->htmlResponse(); + return $this->moduleTemplate->renderResponse('Overview'); } } diff --git a/Classes/EventListener/IndexServiceEventListener.php b/Classes/EventListener/IndexServiceEventListener.php new file mode 100644 index 0000000..368c6f6 --- /dev/null +++ b/Classes/EventListener/IndexServiceEventListener.php @@ -0,0 +1,27 @@ +getItem(); + + $registry = GeneralUtility::makeInstance(Registry::class); + $registry->set('jwtools2-solr', 'indexQueueUid', $item->getIndexQueueUid()); + $registry->set('jwtools2-solr', 'memoryPeakUsage', memory_get_peak_usage(true)); + } +} diff --git a/Classes/Tca/ReduceCategoryTreeToPageTree.php b/Classes/EventListener/ReduceCategoryTreeToPageTree.php similarity index 99% rename from Classes/Tca/ReduceCategoryTreeToPageTree.php rename to Classes/EventListener/ReduceCategoryTreeToPageTree.php index 67d48c1..30479a6 100644 --- a/Classes/Tca/ReduceCategoryTreeToPageTree.php +++ b/Classes/EventListener/ReduceCategoryTreeToPageTree.php @@ -8,7 +8,7 @@ * LICENSE file that was distributed with this source code. */ -namespace JWeiland\Jwtools2\Tca; +namespace JWeiland\Jwtools2\EventListener; use Doctrine\DBAL\ArrayParameterType; use TYPO3\CMS\Backend\Tree\TreeNode; diff --git a/Classes/Provider/ReportProvider.php b/Classes/Provider/ReportProvider.php index 108a7ce..4336071 100644 --- a/Classes/Provider/ReportProvider.php +++ b/Classes/Provider/ReportProvider.php @@ -136,4 +136,9 @@ protected function getSeverity(bool $renderForReportMail): int // There is no need to render extension updates as WARNING in reports module. return $renderForReportMail && $extConfSeverity === 'warning' ? Status::WARNING : Status::INFO; } + + public function getLabel(): string + { + return ''; + } } diff --git a/Configuration/Backend/Modules.php b/Configuration/Backend/Modules.php index 3cf2d53..5c61afe 100644 --- a/Configuration/Backend/Modules.php +++ b/Configuration/Backend/Modules.php @@ -9,12 +9,12 @@ * Definitions for modules provided by EXT:jwtools2 */ return [ - 'club' => [ + 'tools_ts_jwtools2' => [ 'parent' => 'tools', 'position' => ['after' => 'web_info'], 'access' => 'user,group', 'workspaces' => 'live', - 'path' => '/module/web/club', + 'path' => '/module/tools/jwtools2', 'labels' => 'LLL:EXT:jwtools2/Resources/Private/Language/locallang_module_tools.xlf', 'iconIdentifier' => 'ext-jwtools2-be-module-icon', 'extensionName' => 'jwtools2', @@ -23,7 +23,7 @@ 'overview', ], SolrController::class => [ - 'list, show, showIndexQueue, indexOneRecord, createIndexQueueForAllSites, showClearFullIndexForm, showClearIndexForm, clearIndex', + 'list', ], ], ], diff --git a/Configuration/Services.yaml b/Configuration/Services.yaml index be38710..0f3ba17 100644 --- a/Configuration/Services.yaml +++ b/Configuration/Services.yaml @@ -48,7 +48,14 @@ services: JWeiland\Jwtools2\LinkHandling\FolderLinkHandler: public: true - JWeiland\Jwtools2\Tca\ReduceCategoryTreeToPageTree: + # Event Listeners + JWeiland\Jwtools2\EventListener\ReduceCategoryTreeToPageTree: tags: - name: event.listener event: TYPO3\CMS\Core\Tree\Event\ModifyTreeDataEvent + + JWeiland\Jwtools2\EventListener\IndexServiceEventListener: + tags: + - name: event.listener + identifier: 'jwtools2.events.beforeItemIsIndexedEvent' + event: ApacheSolrForTypo3\Solr\Event\Indexing\BeforeItemIsIndexedEvent From 6ec1abb6b94ace024fce6c57e81cc4e9729f8e96 Mon Sep 17 00:00:00 2001 From: Hoja Mustaffa Abdul Latheef Date: Tue, 13 Feb 2024 09:09:35 +0100 Subject: [PATCH 17/65] [TASK] Moved property DI to injectTraits --- Classes/Controller/SolrController.php | 66 ++++++------------- Classes/Traits/InjectPageRendererTrait.php | 27 ++++++++ Classes/Traits/InjectRegistryTrait.php | 26 ++++++++ .../Traits/InjectSchedulerRepositoryTrait.php | 26 ++++++++ Classes/Traits/InjectSolrRepositoryTrait.php | 26 ++++++++ 5 files changed, 126 insertions(+), 45 deletions(-) create mode 100644 Classes/Traits/InjectPageRendererTrait.php create mode 100644 Classes/Traits/InjectRegistryTrait.php create mode 100644 Classes/Traits/InjectSchedulerRepositoryTrait.php create mode 100644 Classes/Traits/InjectSolrRepositoryTrait.php diff --git a/Classes/Controller/SolrController.php b/Classes/Controller/SolrController.php index d126599..0427be2 100644 --- a/Classes/Controller/SolrController.php +++ b/Classes/Controller/SolrController.php @@ -16,18 +16,16 @@ use ApacheSolrForTypo3\Solr\IndexQueue\Queue; use ApacheSolrForTypo3\Solr\System\Configuration\TypoScriptConfiguration; use JWeiland\Jwtools2\Backend\SolrDocHeader; -use JWeiland\Jwtools2\Domain\Repository\SchedulerRepository; -use JWeiland\Jwtools2\Domain\Repository\SolrRepository; use JWeiland\Jwtools2\Service\SolrService; +use JWeiland\Jwtools2\Traits\InjectPageRendererTrait; +use JWeiland\Jwtools2\Traits\InjectRegistryTrait; +use JWeiland\Jwtools2\Traits\InjectSchedulerRepositoryTrait; +use JWeiland\Jwtools2\Traits\InjectSolrRepositoryTrait; use Psr\Http\Message\ResponseInterface; -use Psr\Http\Message\ServerRequestInterface; use TYPO3\CMS\Backend\Attribute\AsController; -use TYPO3\CMS\Backend\Template\ModuleTemplate; -use TYPO3\CMS\Backend\Template\ModuleTemplateFactory; use TYPO3\CMS\Core\Database\ConnectionPool; -use TYPO3\CMS\Core\Messaging\AbstractMessage; use TYPO3\CMS\Core\Page\PageRenderer; -use TYPO3\CMS\Core\Registry; +use TYPO3\CMS\Core\Type\ContextualFeedbackSeverity; use TYPO3\CMS\Core\Utility\ArrayUtility; use TYPO3\CMS\Core\Utility\GeneralUtility; use TYPO3\CMS\Extbase\Annotation as Extbase; @@ -37,40 +35,18 @@ #[AsController] class SolrController extends AbstractController { - protected SolrRepository $solrRepository; - - protected SchedulerRepository $schedulerRepository; - - protected Registry $registry; - - protected PageRenderer $pageRenderer; - - public function injectSolrRepository(SolrRepository $solrRepository): void - { - $this->solrRepository = $solrRepository; - } - - public function injectSchedulerRepository(SchedulerRepository $schedulerRepository): void - { - $this->schedulerRepository = $schedulerRepository; - } - - public function injectRegistry(Registry $registry): void - { - $this->registry = $registry; - } - - public function injectPageRenderer(PageRenderer $pageRenderer): void - { - $this->pageRenderer = $pageRenderer; - } + use InjectSolrRepositoryTrait; + use InjectSchedulerRepositoryTrait; + use InjectRegistryTrait; + use InjectPageRendererTrait; public function initializeView($view): void { if (!$view instanceof NotFoundView) { parent::initializeView($view); - $this->pageRenderer->loadJavaScriptModule('TYPO3/CMS/Jwtools2/SolrIndex'); + //$this->pageRenderer->loadJavaScriptModule('@jweiland/jwtools2/SolrBackendModule.js'); + $this->pageRenderer->loadRequireJsModule('TYPO3/CMS/Jwtools2/SolrIndex'); /** @var SolrDocHeader $docHeader */ $docHeader = GeneralUtility::makeInstance(SolrDocHeader::class, $this->request, $this->moduleTemplate); @@ -80,7 +56,7 @@ public function initializeView($view): void $this->addFlashMessage( 'No or wrong scheduler task UID configured in ExtensionManager Configuration of jwtools2', 'Missing or wrong configuration', - AbstractMessage::WARNING + ContextualFeedbackSeverity::WARNING ); } } @@ -88,10 +64,10 @@ public function initializeView($view): void public function listAction(): ResponseInterface { - $this->view->assign('sites', $this->solrRepository->findAllAvailableSites()); - $this->view->assign('currentRootPageUid', $this->registry->get('jwtools2-solr', 'rootPageId', 0)); + $this->moduleTemplate->assign('sites', $this->solrRepository->findAllAvailableSites()); + $this->moduleTemplate->assign('currentRootPageUid', $this->registry->get('jwtools2-solr', 'rootPageId', 0)); - return $this->htmlResponse(); + return $this->moduleTemplate->renderResponse('List'); } public function showAction(int $rootPageUid): ResponseInterface @@ -126,7 +102,7 @@ public function indexOneRecordAction( $this->addFlashMessage( 'Please enter a record UID before submitting the form', 'Record UID empty', - AbstractMessage::ERROR + ContextualFeedbackSeverity::ERROR ); } else { $site = $this->solrRepository->findByRootPage($rootPageUid); @@ -142,21 +118,21 @@ public function indexOneRecordAction( $this->addFlashMessage( 'Indexing Solr Queue Item object failed. Please check logs. Record UID: ' . $recordUid, 'Indexing Failed', - AbstractMessage::ERROR + ContextualFeedbackSeverity::ERROR ); } } else { $this->addFlashMessage( 'Solr Index Queue Item could not be found by Record UID: ' . $recordUid, 'Indexing Failed', - AbstractMessage::ERROR + ContextualFeedbackSeverity::ERROR ); } } else { $this->addFlashMessage( 'Solr Site object could not be retrieved by RootPageUid: ' . $rootPageUid, 'Indexing Failed', - AbstractMessage::ERROR + ContextualFeedbackSeverity::ERROR ); } } @@ -188,7 +164,7 @@ public function showClearIndexFormAction(int $rootPageUid): ResponseInterface $this->addFlashMessage( $rootPageUid . ' is no valid RootPage UID', 'Invalid RootPage UID', - AbstractMessage::WARNING + ContextualFeedbackSeverity::WARNING ); $this->redirect('list'); } @@ -216,7 +192,7 @@ public function clearIndexAction(int $rootPageUid, array $configurationNames, ar $this->addFlashMessage( 'We haven\'t found a Site with RootPage UID: ' . $rootPageUid, 'Site not found', - AbstractMessage::WARNING + ContextualFeedbackSeverity::WARNING ); } diff --git a/Classes/Traits/InjectPageRendererTrait.php b/Classes/Traits/InjectPageRendererTrait.php new file mode 100644 index 0000000..bed7e81 --- /dev/null +++ b/Classes/Traits/InjectPageRendererTrait.php @@ -0,0 +1,27 @@ +pageRenderer = $pageRenderer; + } +} diff --git a/Classes/Traits/InjectRegistryTrait.php b/Classes/Traits/InjectRegistryTrait.php new file mode 100644 index 0000000..335ae72 --- /dev/null +++ b/Classes/Traits/InjectRegistryTrait.php @@ -0,0 +1,26 @@ +registry = $registry; + } +} diff --git a/Classes/Traits/InjectSchedulerRepositoryTrait.php b/Classes/Traits/InjectSchedulerRepositoryTrait.php new file mode 100644 index 0000000..cf7f590 --- /dev/null +++ b/Classes/Traits/InjectSchedulerRepositoryTrait.php @@ -0,0 +1,26 @@ +schedulerRepository = $schedulerRepository; + } +} diff --git a/Classes/Traits/InjectSolrRepositoryTrait.php b/Classes/Traits/InjectSolrRepositoryTrait.php new file mode 100644 index 0000000..03ac8cb --- /dev/null +++ b/Classes/Traits/InjectSolrRepositoryTrait.php @@ -0,0 +1,26 @@ +solrRepository = $solrRepository; + } +} From ff3b5619d4ec2f120ac14e9e15f3d8df9338faed Mon Sep 17 00:00:00 2001 From: Hoja Mustaffa Abdul Latheef Date: Tue, 13 Feb 2024 09:25:32 +0100 Subject: [PATCH 18/65] [TASK] Replaced deprecated AbstractMessage::MESSAGETYPE with ContextualFeedbackSeverity::Message --- Classes/Task/ExecuteQueryTask.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Classes/Task/ExecuteQueryTask.php b/Classes/Task/ExecuteQueryTask.php index 8e2ef70..c95e66b 100644 --- a/Classes/Task/ExecuteQueryTask.php +++ b/Classes/Task/ExecuteQueryTask.php @@ -11,9 +11,9 @@ namespace JWeiland\Jwtools2\Task; use TYPO3\CMS\Core\Database\ConnectionPool; -use TYPO3\CMS\Core\Messaging\AbstractMessage; use TYPO3\CMS\Core\Messaging\FlashMessage; use TYPO3\CMS\Core\Messaging\FlashMessageService; +use TYPO3\CMS\Core\Type\ContextualFeedbackSeverity; use TYPO3\CMS\Core\Utility\GeneralUtility; use TYPO3\CMS\Scheduler\Task\AbstractTask; @@ -55,7 +55,7 @@ public function execute(): bool } catch (\Exception $e) { $this->addMessage( 'Error occurred: ' . $e->getMessage(), - AbstractMessage::ERROR + ContextualFeedbackSeverity::ERROR ); return false; @@ -77,7 +77,7 @@ public function setSqlQuery(string $sqlQuery): void * * @throws \Exception */ - public function addMessage(string $message, int $severity = AbstractMessage::OK): void + public function addMessage(string $message, ContextualFeedbackSeverity $severity = ContextualFeedbackSeverity::OK): void { $flashMessage = GeneralUtility::makeInstance(FlashMessage::class, $message, '', $severity); $flashMessageService = GeneralUtility::makeInstance(FlashMessageService::class); From c08e538cc0ac58365f289aabf0c57cd037592992 Mon Sep 17 00:00:00 2001 From: Hoja Mustaffa Abdul Latheef Date: Tue, 13 Feb 2024 09:51:15 +0100 Subject: [PATCH 19/65] [TASK] Replaced GeneralUtility::_GP with ServerRequestInterface methods --- Classes/Backend/Browser/FileBrowser.php | 8 ++++-- Classes/Traits/RequestArgumentsTrait.php | 36 ++++++++++++++++++++++++ 2 files changed, 42 insertions(+), 2 deletions(-) create mode 100644 Classes/Traits/RequestArgumentsTrait.php diff --git a/Classes/Backend/Browser/FileBrowser.php b/Classes/Backend/Browser/FileBrowser.php index 1867bd1..c397c57 100644 --- a/Classes/Backend/Browser/FileBrowser.php +++ b/Classes/Backend/Browser/FileBrowser.php @@ -11,6 +11,8 @@ namespace JWeiland\Jwtools2\Backend\Browser; use Doctrine\DBAL\Schema\AbstractSchemaManager; +use JWeiland\Jwtools2\Traits\RequestArgumentsTrait; +use Psr\Http\Message\ServerRequestInterface; use TYPO3\CMS\Backend\Controller\ElementBrowserController; use TYPO3\CMS\Backend\Utility\BackendUtility; use TYPO3\CMS\Core\Configuration\Exception\ExtensionConfigurationExtensionNotConfiguredException; @@ -33,16 +35,18 @@ */ class FileBrowser extends \TYPO3\CMS\Backend\ElementBrowser\FileBrowser { + use RequestArgumentsTrait; + /** * Only load additional JavaScript, if in file or folder context */ - protected function initialize(): void + protected function initialize(ServerRequestInterface $request): void { // We have to prevent, that __construct() of AbstractElementBrowser will call initialize() // of TYPO3's FileBrowser where additional JavaScript will be loaded. That would break the selection and // transfer of chosen records into the parent form. Error: file_undefined insteadof file_123. // JS module "TYPO3/CMS/Recordlist/BrowseFiles" should NOT be loaded, if we are not in file or folder context!!! - if (in_array((string)GeneralUtility::_GP('mode'), ['file', 'folder'])) { + if (in_array($this->getGPValue('mode'), ['file', 'folder'])) { parent::initialize(); } } diff --git a/Classes/Traits/RequestArgumentsTrait.php b/Classes/Traits/RequestArgumentsTrait.php new file mode 100644 index 0000000..dd6e104 --- /dev/null +++ b/Classes/Traits/RequestArgumentsTrait.php @@ -0,0 +1,36 @@ +getParsedBody()[$key] ?? $request->getQueryParams()[$key]; + } + + public function getMergedPostAndGetValues(): array + { + /** @var ServerRequestInterface $request */ + $request = GeneralUtility::makeInstance(ServerRequestInterface::class); + + return array_merge($request->getQueryParams(), $request->getParsedBody()); + } +} From d4de1a41c79cfd55fd73cb208cae713482a157bb Mon Sep 17 00:00:00 2001 From: Hoja Mustaffa Abdul Latheef Date: Tue, 13 Feb 2024 09:54:53 +0100 Subject: [PATCH 20/65] [TASK] Fixed deprecations for BE Module templates and controller --- Classes/Backend/AbstractDocHeader.php | 19 +++++++++---------- Classes/Backend/SolrDocHeader.php | 16 ++++++++++++---- Resources/Private/Templates/Solr/List.html | 6 ++++-- .../Private/Templates/Tools/Overview.html | 13 ++++++------- 4 files changed, 31 insertions(+), 23 deletions(-) diff --git a/Classes/Backend/AbstractDocHeader.php b/Classes/Backend/AbstractDocHeader.php index 738cb01..d7beb5c 100644 --- a/Classes/Backend/AbstractDocHeader.php +++ b/Classes/Backend/AbstractDocHeader.php @@ -26,17 +26,18 @@ abstract class AbstractDocHeader { protected ?UriBuilder $uriBuilder = null; - - protected IconFactory $iconFactory; - - protected ModuleTemplate $view; - - protected Request $request; + protected ?IconFactory $iconFactory = null; + protected ?ModuleTemplate $view = null; + protected ?Request $request = null; public function __construct(Request $request, ModuleTemplate $view) { $this->request = $request; $this->view = $view; + + if ($this->iconFactory === null) { + $this->iconFactory = GeneralUtility::makeInstance(IconFactory::class); + } } public function injectUriBuilder(UriBuilder $uriBuilder): void @@ -51,7 +52,6 @@ public function injectIconFactory(IconFactory $iconFactory): void protected function addHelpButton(): void { - debug($this->view); $buttonBar = $this->view ->getDocHeaderComponent() ->getButtonBar(); @@ -72,9 +72,8 @@ protected function addShortcutButton(): void $shortcutButton = $buttonBar ->makeShortcutButton() - ->setModuleName( - $this->request->getPluginName() - ); + ->setRouteIdentifier($this->request->getPluginName()) + ->setDisplayName('Jwtools2'); $buttonBar->addButton($shortcutButton); } diff --git a/Classes/Backend/SolrDocHeader.php b/Classes/Backend/SolrDocHeader.php index 98619d5..313325c 100644 --- a/Classes/Backend/SolrDocHeader.php +++ b/Classes/Backend/SolrDocHeader.php @@ -37,7 +37,6 @@ public function renderDocHeader(): void protected function addModuleSelector(): void { $buttonBar = $this->view - ->getModuleTemplate() ->getDocHeaderComponent() ->getButtonBar(); @@ -48,17 +47,26 @@ protected function addModuleSelector(): void ->makeInputButton() ->setName('module') ->setValue('solr') - ->setOnClick($this->getLinkForUrl($this->uriBuilder->reset()->uriFor('list', [], 'Solr'))) + //->setOnClick() ->setIcon($this->iconFactory->getIcon('actions-document-new', Icon::SIZE_SMALL)) ->setTitle('Solr Overview') - ->setShowLabelText(true); + ->setShowLabelText(true) + ->setDataAttributes([ + 'dispatch-action' => 'TYPO3.WindowManager.localOpen', + // JSON encoded representation of JavaScript function arguments + // (HTML attributes are encoded in \TYPO3\CMS\Backend\Template\Components\Buttons\LinkButton) + 'dispatch-args' => GeneralUtility::jsonEncodeForHtmlAttribute([ + $this->getLinkForUrl($this->uriBuilder->reset()->uriFor('list', [], 'Solr')), + ], false) + ]); + $splitButtonBar->addItem($newButton, true); $newButton = $buttonBar ->makeInputButton() ->setName('module') ->setValue('cleanUp') - ->setOnClick($this->getLinkForUrl($this->uriBuilder->reset()->uriFor('showClearFullIndexForm', [], 'Solr'))) + //->setOnClick($this->getLinkForUrl($this->uriBuilder->reset()->uriFor('showClearFullIndexForm', [], 'Solr'))) ->setIcon($this->iconFactory->getIcon('actions-document-new', Icon::SIZE_SMALL)) ->setTitle('Clear full index...') ->setShowLabelText(true); diff --git a/Resources/Private/Templates/Solr/List.html b/Resources/Private/Templates/Solr/List.html index 5e50dc8..4abd95d 100644 --- a/Resources/Private/Templates/Solr/List.html +++ b/Resources/Private/Templates/Solr/List.html @@ -4,9 +4,11 @@ xmlns:c="http://typo3.org/ns/TYPO3\CMS\Core\ViewHelpers" data-namespace-typo3-fluid="true"> - + + + + -

{f:translate(key: 'mod.solr.solrFeaturesOverview')}

{f:translate(key: 'mod.solr.memoryUsageSchedulerTask')}

diff --git a/Resources/Private/Templates/Tools/Overview.html b/Resources/Private/Templates/Tools/Overview.html index 59ceaf1..cb0733b 100644 --- a/Resources/Private/Templates/Tools/Overview.html +++ b/Resources/Private/Templates/Tools/Overview.html @@ -1,15 +1,14 @@ - + - - -

Enabled Modules Please check Extension Configuration of jwtools2, if you miss some modules here

+ + +

Enabled Modules Please check Extension Configuration of jwtools2, if you miss some modules here

+
Solr
-
+
From 7d48560c219474c6b6672a07ec9fa27f66c5c94a Mon Sep 17 00:00:00 2001 From: Hoja Mustaffa Abdul Latheef Date: Tue, 13 Feb 2024 10:04:36 +0100 Subject: [PATCH 21/65] Code optimization for RequestArgumentsTrait --- Classes/Traits/RequestArgumentsTrait.php | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/Classes/Traits/RequestArgumentsTrait.php b/Classes/Traits/RequestArgumentsTrait.php index dd6e104..f1d6d79 100644 --- a/Classes/Traits/RequestArgumentsTrait.php +++ b/Classes/Traits/RequestArgumentsTrait.php @@ -18,19 +18,27 @@ */ trait RequestArgumentsTrait { + private ?ServerRequestInterface $request = null; + public function getGPValue(string $key): ?string { - /** @var ServerRequestInterface $request */ - $request = GeneralUtility::makeInstance(ServerRequestInterface::class); - + $request = $this->getServerRequestInterface(); return $request->getParsedBody()[$key] ?? $request->getQueryParams()[$key]; } public function getMergedPostAndGetValues(): array { - /** @var ServerRequestInterface $request */ - $request = GeneralUtility::makeInstance(ServerRequestInterface::class); + $request = $this->getServerRequestInterface(); return array_merge($request->getQueryParams(), $request->getParsedBody()); } + + private function getServerRequestInterface(): ServerRequestInterface + { + if ($this->request === null) { + $this->request = GeneralUtility::makeInstance(ServerRequestInterface::class); + } + + return $this->request; + } } From ca3bef8f975cb0e66e036683d7aa79a8b30a6dd1 Mon Sep 17 00:00:00 2001 From: Hoja Mustaffa Abdul Latheef Date: Thu, 15 Feb 2024 15:50:25 +0100 Subject: [PATCH 22/65] [BUGFIX] Compatibility fixes commands done --- Classes/Backend/AbstractDocHeader.php | 14 ---- Classes/Backend/Browser/FileBrowser.php | 9 ++- Classes/Command/StatusReportCommand.php | 75 ++++++++++++------- Classes/Controller/AbstractController.php | 7 ++ .../Controller/Ajax/AjaxSolrController.php | 41 ++++++---- Classes/Controller/SolrController.php | 2 +- Classes/Database/Query/QueryGenerator.php | 73 ++++++++++++++++++ .../ReduceCategoryTreeToPageTree.php | 17 +++-- Classes/Hooks/CachingFrameworkLoggerHook.php | 6 +- Classes/Provider/ReportProvider.php | 14 +--- Classes/Traits/RequestArgumentsTrait.php | 18 +++-- Classes/ViewHelpers/Format/HtmlViewHelper.php | 26 +++---- Configuration/JavaScriptModules.php | 11 +++ .../Public/JavaScript/SolrBackendModule.js | 1 + Resources/Public/JavaScript/SolrIndex.js | 1 - 15 files changed, 215 insertions(+), 100 deletions(-) create mode 100644 Classes/Database/Query/QueryGenerator.php create mode 100644 Configuration/JavaScriptModules.php create mode 100644 Resources/Public/JavaScript/SolrBackendModule.js diff --git a/Classes/Backend/AbstractDocHeader.php b/Classes/Backend/AbstractDocHeader.php index d7beb5c..84b2348 100644 --- a/Classes/Backend/AbstractDocHeader.php +++ b/Classes/Backend/AbstractDocHeader.php @@ -50,20 +50,6 @@ public function injectIconFactory(IconFactory $iconFactory): void $this->iconFactory = $iconFactory; } - protected function addHelpButton(): void - { - $buttonBar = $this->view - ->getDocHeaderComponent() - ->getButtonBar(); - - $cshButton = $buttonBar - ->makeHelpButton() - ->setModuleName('_MOD_' . 'tools_Jwtools2tools') - ->setFieldName(''); - - $buttonBar->addButton($cshButton); - } - protected function addShortcutButton(): void { $buttonBar = $this->view diff --git a/Classes/Backend/Browser/FileBrowser.php b/Classes/Backend/Browser/FileBrowser.php index c397c57..80e3f38 100644 --- a/Classes/Backend/Browser/FileBrowser.php +++ b/Classes/Backend/Browser/FileBrowser.php @@ -22,6 +22,7 @@ use TYPO3\CMS\Core\Information\Typo3Version; use TYPO3\CMS\Core\Localization\LanguageService; use TYPO3\CMS\Core\Messaging\FlashMessage; +use TYPO3\CMS\Core\Messaging\FlashMessageQueue; use TYPO3\CMS\Core\Messaging\FlashMessageService; use TYPO3\CMS\Core\Resource\File; use TYPO3\CMS\Core\Resource\FileInterface; @@ -40,7 +41,7 @@ class FileBrowser extends \TYPO3\CMS\Backend\ElementBrowser\FileBrowser /** * Only load additional JavaScript, if in file or folder context */ - protected function initialize(ServerRequestInterface $request): void + protected function initialize(): void { // We have to prevent, that __construct() of AbstractElementBrowser will call initialize() // of TYPO3's FileBrowser where additional JavaScript will be loaded. That would break the selection and @@ -59,8 +60,10 @@ public function isValid(string $mode, ElementBrowserController $elementBrowserCo if ($mode === 'file' || $mode === 'folder') { if ($this->getRequiredColumnsFromExtensionConfiguration()) { $flashMessageService = GeneralUtility::makeInstance(FlashMessageService::class); - $flashMessageQueue = $flashMessageService->getMessageQueueByIdentifier(); - $flashMessageQueue->addMessage( + $flashMessageQueue = $flashMessageService->getMessageQueueByIdentifier( + FlashMessageQueue::NOTIFICATION_QUEUE + ); + $flashMessageQueue->enqueue( GeneralUtility::makeInstance( FlashMessage::class, LocalizationUtility::translate( diff --git a/Classes/Command/StatusReportCommand.php b/Classes/Command/StatusReportCommand.php index d0b32ee..66ec280 100644 --- a/Classes/Command/StatusReportCommand.php +++ b/Classes/Command/StatusReportCommand.php @@ -21,6 +21,7 @@ use TYPO3\CMS\Core\Site\SiteFinder; use TYPO3\CMS\Core\Utility\GeneralUtility; use TYPO3\CMS\Install\Controller\MaintenanceController; +use TYPO3\CMS\Scheduler\Domain\Repository\SchedulerTaskRepository; use TYPO3\CMS\Scheduler\Scheduler; use TYPO3\CMS\Scheduler\Task\AbstractTask; @@ -31,6 +32,7 @@ class StatusReportCommand extends Command { private const RETURN_YES = 'YES'; private const RETURN_NO = 'NO'; + private SchedulerTaskRepository $taskRepository; /** * @var InputInterface @@ -47,6 +49,12 @@ class StatusReportCommand extends Command */ protected $ioStyled; + public function __construct(SchedulerTaskRepository $taskRepository) + { + parent::__construct(); + $this->taskRepository = $taskRepository; + } + public function configure(): void { $this @@ -98,32 +106,8 @@ protected function checkScheduler(): void $recurringTasks = []; $yesterday = time() - (60 * 60 * 24); - foreach ($this->getSchedulerTasks() as $taskRecord) { - // Do not add allowed_classes here - $taskObject = unserialize($taskRecord['serialized_task_object']); - if ( - is_subclass_of($taskObject, AbstractTask::class) - && $taskObject->getType() === AbstractTask::TYPE_RECURRING - ) { - if ($taskRecord['lastexecution_time'] > $lastExecution) { - $lastExecution = $taskRecord['lastexecution_time']; - } - - $taskTitle = sprintf( - '%d: %s - Context: %s', - $taskRecord['uid'], - $taskObject->getTaskTitle(), - $taskRecord['lastexecution_context'] - ); - if (!empty($taskRecord['serialized_executions'])) { - $recurringTasks[] = [$taskTitle => 'running...']; - } elseif ($taskRecord['lastexecution_time'] === 0) { - $recurringTasks[] = [$taskTitle => 'never executed']; - } else { - $recurringTasks[] = [$taskTitle => $taskRecord['lastexecution_time'] < $yesterday ? 'scheduled > 24h' : 'scheduled < 24h']; - } - } - } + $tasks = $this->getSchedulerTasks(); + $lastExecution = $this->processTasks($tasks, $recurringTasks, $yesterday, $lastExecution); $this->ioStyled->definitionList( $lastExecution < $yesterday ? 'The last execution was over 24 hours ago' : 'Last execution within last 24 hours', @@ -152,7 +136,7 @@ protected function checkDatabaseStatus(): void protected function getSchedulerTasks(): array { - return GeneralUtility::makeInstance(Scheduler::class)->fetchTasksWithCondition(''); + return $this->taskRepository->getGroupedTasks(); } protected function checkRobotsTxt(Site $site): string @@ -283,4 +267,41 @@ protected function getAllSites(): array { return GeneralUtility::makeInstance(SiteFinder::class)->getAllSites(); } + + protected function processTasks(array $tasks, array &$recurringTasks, int $yesterday, int $lastExecution): int + { + foreach ($tasks as $groups => $taskGroups) { + foreach ($taskGroups as $taskGroup) { + if (is_array($taskGroup['tasks']) && count($taskGroup['tasks'])) { + foreach ($taskGroup['tasks'] as $task) { + if ($task['lastExecutionTime'] > $lastExecution) { + $lastExecution = $task['lastExecutionTime']; + } + + $taskTitle = sprintf( + '%d: %s - Context: %s', + $task['uid'], + $task['classTitle'], + $task['lastExecutionContext'] + ); + + $recurringTasks[] = [$taskTitle => $this->getTaskStatus($task, $yesterday)]; + } + } + } + } + + return $lastExecution; + } + + protected function getTaskStatus(array $task, int $yesterday): string + { + if (isset($task['serializedExecutions']) && $task['serializedExecutions'] !== '') { + return 'running...'; + } elseif ($task['lastExecutionTime'] === 0) { + return 'never executed'; + } else { + return $task['lastExecutionTime'] < $yesterday ? 'scheduled > 24h' : 'scheduled < 24h'; + } + } } diff --git a/Classes/Controller/AbstractController.php b/Classes/Controller/AbstractController.php index c2771bb..f3d54e2 100644 --- a/Classes/Controller/AbstractController.php +++ b/Classes/Controller/AbstractController.php @@ -15,6 +15,7 @@ use TYPO3\CMS\Backend\Template\ModuleTemplate; use TYPO3\CMS\Backend\Template\ModuleTemplateFactory; use TYPO3\CMS\Core\Configuration\ExtensionConfiguration; +use TYPO3\CMS\Core\Imaging\IconFactory; use TYPO3\CMS\Core\Utility\ArrayUtility; use TYPO3\CMS\Core\Utility\GeneralUtility; use TYPO3\CMS\Extbase\Mvc\Controller\ActionController; @@ -29,8 +30,14 @@ abstract class AbstractController extends ActionController protected ModuleTemplate $moduleTemplate; + protected ?IconFactory $iconFactory = null; protected UriBuilder $backendUriBuilder; + public function injectIconFactory(IconFactory $iconFactory): void + { + $this->iconFactory = $iconFactory; + } + public function __construct(ModuleTemplateFactory $moduleTemplateFactory, UriBuilder $backendUriBuilder) { $this->moduleTemplateFactory = $moduleTemplateFactory; diff --git a/Classes/Controller/Ajax/AjaxSolrController.php b/Classes/Controller/Ajax/AjaxSolrController.php index 319b884..9301a03 100644 --- a/Classes/Controller/Ajax/AjaxSolrController.php +++ b/Classes/Controller/Ajax/AjaxSolrController.php @@ -13,19 +13,23 @@ use ApacheSolrForTypo3\Solr\Domain\Index\IndexService; use ApacheSolrForTypo3\Solr\Domain\Site\Site; use ApacheSolrForTypo3\Solr\IndexQueue\Queue; +use Doctrine\DBAL\ConnectionException; +use Doctrine\DBAL\Exception; use JWeiland\Jwtools2\Domain\Repository\SolrRepository; use JWeiland\Jwtools2\Service\SolrService; use Psr\Http\Message\ResponseInterface; use TYPO3\CMS\Core\Http\Response; use TYPO3\CMS\Core\Http\ServerRequest; use TYPO3\CMS\Core\Utility\GeneralUtility; -use TYPO3\CMS\Extbase\Object\ObjectManager; /** * Class AjaxSolrController */ class AjaxSolrController { + /** + * @throws \JsonException + */ public function clearIndexAction(ServerRequest $request): ResponseInterface { $response = new Response(); @@ -44,10 +48,8 @@ public function clearIndexAction(ServerRequest $request): ResponseInterface } if ($rootPageUid !== 0 && $configurationNames !== [] && $clear !== []) { - /** @var ObjectManager $objectManager */ - $objectManager = GeneralUtility::makeInstance(ObjectManager::class); /** @var SolrService $solrService */ - $solrService = $objectManager->get(SolrService::class); + $solrService = GeneralUtility::makeInstance(SolrService::class); $site = $this->getSolrSiteFromRequest($request); @@ -58,7 +60,7 @@ public function clearIndexAction(ServerRequest $request): ResponseInterface $response->getBody()->write( json_encode([ 'success' => 1, - ]) + ], JSON_THROW_ON_ERROR) ); } } @@ -68,6 +70,8 @@ public function clearIndexAction(ServerRequest $request): ResponseInterface /** * Create index queue entries for given site. + * + * @throws \JsonException */ public function createIndexQueueAction(ServerRequest $request): ResponseInterface { @@ -78,28 +82,35 @@ public function createIndexQueueAction(ServerRequest $request): ResponseInterfac $indexQueue = GeneralUtility::makeInstance(Queue::class); $indexingConfigurationsToReIndex = $site->getSolrConfiguration()->getEnabledIndexQueueConfigurationNames(); foreach ($indexingConfigurationsToReIndex as $indexingConfigurationName) { - $indexQueue->getInitializationService()->initializeBySiteAndIndexConfiguration( - $site, - $indexingConfigurationName - ); + try { + $indexQueue->getInitializationService()->initializeBySiteAndIndexConfiguration( + $site, + $indexingConfigurationName + ); + } catch (ConnectionException|Exception $e) { + } } $response->getBody()->write( json_encode([ 'success' => 1, - ]) + ], JSON_THROW_ON_ERROR) ); } else { $response->getBody()->write( json_encode([ 'success' => 0, - ]) + ], JSON_THROW_ON_ERROR) ); } return $response; } + /** + * @throws Exception + * @throws \JsonException + */ public function getProgressAction(ServerRequest $request): ResponseInterface { $response = new Response(); @@ -112,13 +123,13 @@ public function getProgressAction(ServerRequest $request): ResponseInterface json_encode([ 'success' => 1, 'progress' => $indexService->getProgress(), - ]) + ], JSON_THROW_ON_ERROR) ); } else { $response->getBody()->write( json_encode([ 'success' => 0, - ]) + ], JSON_THROW_ON_ERROR) ); } @@ -140,10 +151,8 @@ protected function getRootPageUidFromRequest(ServerRequest $request): int protected function getSolrSiteFromRequest(ServerRequest $request): ?Site { $rootPageUid = $this->getRootPageUidFromRequest($request); - /** @var ObjectManager $objectManager */ - $objectManager = GeneralUtility::makeInstance(ObjectManager::class); /** @var SolrRepository $solrRepository */ - $solrRepository = $objectManager->get(SolrRepository::class); + $solrRepository = GeneralUtility::makeInstance(SolrRepository::class); return $solrRepository->findByRootPage($rootPageUid); } diff --git a/Classes/Controller/SolrController.php b/Classes/Controller/SolrController.php index 0427be2..c9b6455 100644 --- a/Classes/Controller/SolrController.php +++ b/Classes/Controller/SolrController.php @@ -204,7 +204,7 @@ public function clearIndexAction(int $rootPageUid, array $configurationNames, ar */ public function showClearFullIndexFormAction(): ResponseInterface { - $pageRenderer = $this->objectManager->get(PageRenderer::class); + $pageRenderer = GeneralUtility::makeInstance(PageRenderer::class); $pageRenderer->loadRequireJsModule('TYPO3/CMS/Jwtools2/ClearFullIndex'); $configurationNamesOfAllSites = []; diff --git a/Classes/Database/Query/QueryGenerator.php b/Classes/Database/Query/QueryGenerator.php new file mode 100644 index 0000000..fdf8e87 --- /dev/null +++ b/Classes/Database/Query/QueryGenerator.php @@ -0,0 +1,73 @@ + 0) { + $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable('pages'); + $queryBuilder->getRestrictions()->removeAll()->add(GeneralUtility::makeInstance(DeletedRestriction::class)); + $queryBuilder->select('uid') + ->from('pages') + ->where( + $queryBuilder->expr()->eq('pid', $queryBuilder->createNamedParameter($id, \PDO::PARAM_INT)), + $queryBuilder->expr()->eq('sys_language_uid', 0) + ) + ->orderBy('uid'); + if ($permClause !== '') { + $queryBuilder->andWhere(self::stripLogicalOperatorPrefix($permClause)); + } + $statement = $queryBuilder->executeQuery(); + while ($row = $statement->fetchAssociative()) { + if ($begin <= 0) { + $theList .= ',' . $row['uid']; + } + if ($depth > 1) { + $theSubList = $this->getTreeList($row['uid'], $depth - 1, $begin - 1, $permClause); + if (!empty($theList) && !empty($theSubList) && ($theSubList[0] !== ',')) { + $theList .= ','; + } + $theList .= $theSubList; + } + } + } + return $theList; + } + + public static function stripLogicalOperatorPrefix(string $constraint): string + { + return preg_replace('/^(?:(AND|OR)[[:space:]]*)+/i', '', trim($constraint)) ?: ''; + } +} diff --git a/Classes/EventListener/ReduceCategoryTreeToPageTree.php b/Classes/EventListener/ReduceCategoryTreeToPageTree.php index 30479a6..0c5051c 100644 --- a/Classes/EventListener/ReduceCategoryTreeToPageTree.php +++ b/Classes/EventListener/ReduceCategoryTreeToPageTree.php @@ -11,6 +11,9 @@ namespace JWeiland\Jwtools2\EventListener; use Doctrine\DBAL\ArrayParameterType; +use Doctrine\DBAL\Exception; +use JWeiland\Jwtools2\Query\QueryGenerator; +use JWeiland\Jwtools2\Traits\RequestArgumentsTrait; use TYPO3\CMS\Backend\Tree\TreeNode; use TYPO3\CMS\Backend\Tree\TreeNodeCollection; use TYPO3\CMS\Backend\Utility\BackendUtility; @@ -20,7 +23,6 @@ use TYPO3\CMS\Core\Configuration\ExtensionConfiguration; use TYPO3\CMS\Core\Database\Connection; use TYPO3\CMS\Core\Database\ConnectionPool; -use TYPO3\CMS\Core\Database\QueryGenerator; use TYPO3\CMS\Core\Http\ApplicationType; use TYPO3\CMS\Core\Tree\Event\ModifyTreeDataEvent; use TYPO3\CMS\Core\Utility\GeneralUtility; @@ -30,6 +32,8 @@ */ class ReduceCategoryTreeToPageTree { + use RequestArgumentsTrait; + /** * @var string */ @@ -59,7 +63,7 @@ public function __invoke(ModifyTreeDataEvent $event): void { try { if ( - (TYPO3_REQUESTTYPE & ApplicationType::fromRequest($GLOBALS['TYPO3_REQUEST'])->isBackend()) + (ApplicationType::fromRequest($GLOBALS['TYPO3_REQUEST'])->isBackend()) && $this->extensionConfiguration->get('jwtools2', 'reduceCategoriesToPageTree') === '1' && !$this->getBackendUserAuthentication()->isAdmin() && $event->getProvider()->getTableName() === $this->categoryTableName @@ -108,11 +112,11 @@ protected function removePageTreeForeignCategories(TreeNode $treeNode): void protected function getPageUid(): int { if (empty($this->pageUid)) { - $command = GeneralUtility::_GET('command'); + $command = $this->getGetArguments()['command'] ?? ''; if ($command === 'edit') { $record = BackendUtility::getRecordWSOL( - GeneralUtility::_GET('tableName'), - (int)GeneralUtility::_GET('uid'), + $this->getGetArguments()['tableName'] ?? '', + (int)$this->getGetArguments()['uid'], 'pid' ); if (empty($record)) { @@ -122,7 +126,7 @@ protected function getPageUid(): int } } else { // in case of command==new given uid is pid of current page - $pid = (int)GeneralUtility::_GET('uid'); + $pid = (int)$this->getGetArguments()['uid']; } $this->pageUid = $pid; @@ -136,6 +140,7 @@ protected function getPageUid(): int * * @param int $pageUid * @return string + * @throws Exception */ protected function getListOfAllowedCategoryUids(int $pageUid): string { diff --git a/Classes/Hooks/CachingFrameworkLoggerHook.php b/Classes/Hooks/CachingFrameworkLoggerHook.php index 18db53d..0c2b258 100644 --- a/Classes/Hooks/CachingFrameworkLoggerHook.php +++ b/Classes/Hooks/CachingFrameworkLoggerHook.php @@ -10,6 +10,7 @@ namespace JWeiland\Jwtools2\Hooks; +use JWeiland\Jwtools2\Traits\RequestArgumentsTrait; use Psr\Log\LoggerAwareInterface; use Psr\Log\LoggerAwareTrait; use TYPO3\CMS\Core\Cache\Frontend\FrontendInterface; @@ -23,6 +24,7 @@ class CachingFrameworkLoggerHook implements LoggerAwareInterface { use LoggerAwareTrait; + use RequestArgumentsTrait; /** * @var FrontendInterface @@ -93,8 +95,8 @@ protected function createLogEntry(string $entryIdentifier, array $cacheExpressio 'cacheExpression' => $cacheExpression, 'backtrace' => debug_backtrace(2), // 0 => without objects 'request' => GeneralUtility::getIndpEnv('_ARRAY'), - 'GET' => GeneralUtility::_GET(), - 'POST' => GeneralUtility::_POST(), + 'GET' => $this->getGetArguments(), + 'POST' => $this->getPostArguments(), ]; // Yes, we log that as error. In most cases you have problems on LIVE/PRODUCTION where severities of info and // warning are not logged. diff --git a/Classes/Provider/ReportProvider.php b/Classes/Provider/ReportProvider.php index 4336071..5555124 100644 --- a/Classes/Provider/ReportProvider.php +++ b/Classes/Provider/ReportProvider.php @@ -11,8 +11,8 @@ namespace JWeiland\Jwtools2\Provider; use TYPO3\CMS\Core\Configuration\ExtensionConfiguration; +use TYPO3\CMS\Core\Type\ContextualFeedbackSeverity; use TYPO3\CMS\Core\Utility\GeneralUtility; -use TYPO3\CMS\Extbase\Object\ObjectManager; use TYPO3\CMS\Extensionmanager\Domain\Model\Extension; use TYPO3\CMS\Extensionmanager\Utility\ListUtility; use TYPO3\CMS\Reports\ExtendedStatusProviderInterface; @@ -24,11 +24,6 @@ */ class ReportProvider implements StatusProviderInterface, ExtendedStatusProviderInterface { - /** - * @var ObjectManager - */ - protected $objectManager; - /** * @var ListUtility */ @@ -41,8 +36,7 @@ class ReportProvider implements StatusProviderInterface, ExtendedStatusProviderI public function __construct() { - $this->objectManager = GeneralUtility::makeInstance(ObjectManager::class); - $this->listUtility = $this->objectManager->get(ListUtility::class); + $this->listUtility = GeneralUtility::makeInstance(ListUtility::class); $this->extensionConfiguration = GeneralUtility::makeInstance(ExtensionConfiguration::class); } @@ -126,7 +120,7 @@ protected function getUpdatableExtensions(bool $renderForReportMail = false) ); } - protected function getSeverity(bool $renderForReportMail): int + protected function getSeverity(bool $renderForReportMail): ContextualFeedbackSeverity { $extConfSeverity = $this->extensionConfiguration->get( 'jwtools2', @@ -134,7 +128,7 @@ protected function getSeverity(bool $renderForReportMail): int ); // There is no need to render extension updates as WARNING in reports module. - return $renderForReportMail && $extConfSeverity === 'warning' ? Status::WARNING : Status::INFO; + return $renderForReportMail && $extConfSeverity === 'warning' ? ContextualFeedbackSeverity::WARNING : ContextualFeedbackSeverity::INFO; } public function getLabel(): string diff --git a/Classes/Traits/RequestArgumentsTrait.php b/Classes/Traits/RequestArgumentsTrait.php index f1d6d79..4d5687a 100644 --- a/Classes/Traits/RequestArgumentsTrait.php +++ b/Classes/Traits/RequestArgumentsTrait.php @@ -18,14 +18,22 @@ */ trait RequestArgumentsTrait { - private ?ServerRequestInterface $request = null; - public function getGPValue(string $key): ?string { $request = $this->getServerRequestInterface(); return $request->getParsedBody()[$key] ?? $request->getQueryParams()[$key]; } + public function getGetArguments(): array + { + return $this->getServerRequestInterface()->getQueryParams(); + } + + public function getPostArguments(): array + { + return $this->getServerRequestInterface()->getParsedBody(); + } + public function getMergedPostAndGetValues(): array { $request = $this->getServerRequestInterface(); @@ -35,10 +43,6 @@ public function getMergedPostAndGetValues(): array private function getServerRequestInterface(): ServerRequestInterface { - if ($this->request === null) { - $this->request = GeneralUtility::makeInstance(ServerRequestInterface::class); - } - - return $this->request; + return GeneralUtility::makeInstance(ServerRequestInterface::class); } } diff --git a/Classes/ViewHelpers/Format/HtmlViewHelper.php b/Classes/ViewHelpers/Format/HtmlViewHelper.php index 8aae859..f813d1e 100644 --- a/Classes/ViewHelpers/Format/HtmlViewHelper.php +++ b/Classes/ViewHelpers/Format/HtmlViewHelper.php @@ -10,12 +10,13 @@ namespace JWeiland\Jwtools2\ViewHelpers\Format; +use TYPO3\CMS\Core\Context\Context; +use TYPO3\CMS\Core\Context\Exception\AspectNotFoundException; use TYPO3\CMS\Core\Domain\Repository\PageRepository; use TYPO3\CMS\Core\Http\ApplicationType; use TYPO3\CMS\Core\TypoScript\TemplateService; use TYPO3\CMS\Core\Utility\GeneralUtility; use TYPO3\CMS\Extbase\Configuration\ConfigurationManagerInterface; -use TYPO3\CMS\Extbase\Object\ObjectManager; use TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer; use TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController; use TYPO3Fluid\Fluid\Core\Rendering\RenderingContextInterface; @@ -127,23 +128,22 @@ public static function renderStatic( /** * Copies the specified parseFunc configuration to $GLOBALS['TSFE']->tmpl->setup in Backend mode * This somewhat hacky work around is currently needed because the parseFunc() function of \TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer relies on those variables to be set + * + * @throws AspectNotFoundException */ protected static function simulateFrontendEnvironment(): void { + $context = GeneralUtility::makeInstance(Context::class); if ( - !$GLOBALS['TSFE'] instanceof TypoScriptFrontendController - || !$GLOBALS['TSFE']->tmpl instanceof TemplateService - || !$GLOBALS['TSFE']->sys_page instanceof PageRepository + !$context->getPropertyFromAspect('typoscript', 'frontendController') instanceof TypoScriptFrontendController ) { - self::$tsfeBackup = $GLOBALS['TSFE'] ?? null; - $GLOBALS['TSFE'] = new \stdClass(); - $GLOBALS['TSFE']->cObjectDepthCounter = 50; - $GLOBALS['TSFE']->tmpl = new \stdClass(); - $objectManager = GeneralUtility::makeInstance(ObjectManager::class); - $configurationManager = $objectManager->get(ConfigurationManagerInterface::class); - $GLOBALS['TSFE']->tmpl->setup = $configurationManager->getConfiguration( - ConfigurationManagerInterface::CONFIGURATION_TYPE_FULL_TYPOSCRIPT - ); + self::$tsfeBackup = $context->getPropertyFromAspect('typoscript', 'frontendController'); + $context->setAspect('typoscript', $context->getAspect('frontendController'), new \stdClass()); + $context->setAspect('typoscript', $context->getAspect('cObjectDepthCounter'), 50); + $context->setAspect('typoscript', $context->getAspect('templateService'), new \stdClass()); + + $typoScriptService = GeneralUtility::makeInstance(TypoScriptService::class); + $context->setAspect('typoscript', $context->getAspect('setup'), $typoScriptService->getConfiguration()); } } diff --git a/Configuration/JavaScriptModules.php b/Configuration/JavaScriptModules.php new file mode 100644 index 0000000..45931ae --- /dev/null +++ b/Configuration/JavaScriptModules.php @@ -0,0 +1,11 @@ + [ + 'backend', + 'core', + ], + 'imports' => [ + '@jweiland/jwtools2/' => 'EXT:jwtools2/Resources/Public/JavaScript/', + ], +]; diff --git a/Resources/Public/JavaScript/SolrBackendModule.js b/Resources/Public/JavaScript/SolrBackendModule.js new file mode 100644 index 0000000..e858729 --- /dev/null +++ b/Resources/Public/JavaScript/SolrBackendModule.js @@ -0,0 +1 @@ +alert('solr module loaded!'); diff --git a/Resources/Public/JavaScript/SolrIndex.js b/Resources/Public/JavaScript/SolrIndex.js index 6812025..8303909 100644 --- a/Resources/Public/JavaScript/SolrIndex.js +++ b/Resources/Public/JavaScript/SolrIndex.js @@ -10,7 +10,6 @@ * * The TYPO3 project - inspiring people to share! */ - /** * Module: TYPO3/CMS/Jwtools2/SolrIndex */ From c5454e6942fb6a78c7bcbf52ff3c642bc08a9732 Mon Sep 17 00:00:00 2001 From: Hoja Mustaffa Abdul Latheef Date: Thu, 15 Feb 2024 17:16:56 +0100 Subject: [PATCH 23/65] Removed addHelpButton from header --- Classes/Backend/SolrDocHeader.php | 1 - 1 file changed, 1 deletion(-) diff --git a/Classes/Backend/SolrDocHeader.php b/Classes/Backend/SolrDocHeader.php index 313325c..b1beee0 100644 --- a/Classes/Backend/SolrDocHeader.php +++ b/Classes/Backend/SolrDocHeader.php @@ -28,7 +28,6 @@ public function renderDocHeader(): void $this->uriBuilder->setRequest($this->request); // Render Buttons - $this->addHelpButton(); $this->addShortcutButton(); $this->addCloseButton(); $this->addModuleSelector(); From b14e1886c2659ee9194e2a52d8d337a909ad0903 Mon Sep 17 00:00:00 2001 From: Hoja Mustaffa Abdul Latheef Date: Fri, 16 Feb 2024 14:32:18 +0100 Subject: [PATCH 24/65] [TASK] Replaced annotation property type return to strictly typed return types --- Classes/Command/CacheQueryCommand.php | 5 +---- .../ConvertPlainPasswordToHashCommand.php | 19 +++++-------------- Classes/Command/ExtensionUpdateCommand.php | 5 ----- Classes/Command/StatusReportCommand.php | 16 ++++------------ 4 files changed, 10 insertions(+), 35 deletions(-) diff --git a/Classes/Command/CacheQueryCommand.php b/Classes/Command/CacheQueryCommand.php index 05eaa28..3e29d87 100644 --- a/Classes/Command/CacheQueryCommand.php +++ b/Classes/Command/CacheQueryCommand.php @@ -29,10 +29,7 @@ */ class CacheQueryCommand extends Command { - /** - * @var OutputInterface - */ - protected $output; + protected OutputInterface $output; public function configure(): void { diff --git a/Classes/Command/ConvertPlainPasswordToHashCommand.php b/Classes/Command/ConvertPlainPasswordToHashCommand.php index 724ad87..ab60ff4 100644 --- a/Classes/Command/ConvertPlainPasswordToHashCommand.php +++ b/Classes/Command/ConvertPlainPasswordToHashCommand.php @@ -29,20 +29,11 @@ */ class ConvertPlainPasswordToHashCommand extends Command { - /** - * @var OutputInterface - */ - protected $output; - - /** - * @var PasswordHashFactory - */ - protected $passwordHashFactory; - - /** - * @var array - */ - protected $modeMapping = [ + protected OutputInterface $output; + + protected PasswordHashFactory $passwordHashFactory; + + protected array $modeMapping = [ 'FE' => [ 'table' => 'fe_users', ], diff --git a/Classes/Command/ExtensionUpdateCommand.php b/Classes/Command/ExtensionUpdateCommand.php index 53164de..4ae0547 100644 --- a/Classes/Command/ExtensionUpdateCommand.php +++ b/Classes/Command/ExtensionUpdateCommand.php @@ -112,9 +112,6 @@ protected function execute(InputInterface $input, OutputInterface $output): int /** * Execute update script of extension - * - * @param string $extKey - * @return bool */ protected function updateExtension(string $extKey): bool { @@ -130,8 +127,6 @@ protected function updateExtension(string $extKey): bool /** * Get all active extensions with class.ext_update.php * where an update is possible (Method call returns true) - * - * @return array */ protected function getUpdatePossibleActivePackages(): array { diff --git a/Classes/Command/StatusReportCommand.php b/Classes/Command/StatusReportCommand.php index 66ec280..96ce32e 100644 --- a/Classes/Command/StatusReportCommand.php +++ b/Classes/Command/StatusReportCommand.php @@ -34,24 +34,16 @@ class StatusReportCommand extends Command private const RETURN_NO = 'NO'; private SchedulerTaskRepository $taskRepository; - /** - * @var InputInterface - */ - protected $input; + protected InputInterface $input; - /** - * @var OutputInterface - */ - protected $output; + protected OutputInterface $output; - /** - * @var SymfonyStyle - */ - protected $ioStyled; + protected SymfonyStyle $ioStyled; public function __construct(SchedulerTaskRepository $taskRepository) { parent::__construct(); + $this->taskRepository = $taskRepository; } From 68405efef02092cf89a6f7bf4046600b07646086 Mon Sep 17 00:00:00 2001 From: Hoja Mustaffa Abdul Latheef Date: Fri, 16 Feb 2024 14:33:48 +0100 Subject: [PATCH 25/65] [BUGFIX] Fixed property types as return and passed argument as casted (int) --- Classes/Task/IndexQueueWorkerTask.php | 10 ++-------- .../IndexQueueWorkerTaskAdditionalFieldProvider.php | 4 ++-- 2 files changed, 4 insertions(+), 10 deletions(-) diff --git a/Classes/Task/IndexQueueWorkerTask.php b/Classes/Task/IndexQueueWorkerTask.php index b46e286..25d8473 100644 --- a/Classes/Task/IndexQueueWorkerTask.php +++ b/Classes/Task/IndexQueueWorkerTask.php @@ -27,15 +27,9 @@ */ class IndexQueueWorkerTask extends AbstractTask implements ProgressProviderInterface { - /** - * @var int - */ - protected $documentsToIndexLimit = 50; + protected int $documentsToIndexLimit = 50; - /** - * @var int - */ - protected $maxSitesPerRun = 10; + protected int $maxSitesPerRun = 10; /** * Works through the indexing queue and indexes the queued items into Solr. diff --git a/Classes/Task/IndexQueueWorkerTaskAdditionalFieldProvider.php b/Classes/Task/IndexQueueWorkerTaskAdditionalFieldProvider.php index 347ac2f..bf74ac8 100644 --- a/Classes/Task/IndexQueueWorkerTaskAdditionalFieldProvider.php +++ b/Classes/Task/IndexQueueWorkerTaskAdditionalFieldProvider.php @@ -95,7 +95,7 @@ public function validateAdditionalFields(array &$submittedData, SchedulerModuleC public function saveAdditionalFields(array $submittedData, AbstractTask $task): void { /** @var IndexQueueWorkerTask $task */ - $task->setDocumentsToIndexLimit($submittedData['documentsToIndexLimit']); - $task->setMaxSitesPerRun($submittedData['maxSitesPerRun']); + $task->setDocumentsToIndexLimit((int)$submittedData['documentsToIndexLimit']); + $task->setMaxSitesPerRun((int)$submittedData['maxSitesPerRun']); } } From 27dea0ab6ef44a60ffc615b285f806f02d305dc4 Mon Sep 17 00:00:00 2001 From: Hoja Mustaffa Abdul Latheef Date: Fri, 16 Feb 2024 14:35:04 +0100 Subject: [PATCH 26/65] [TASK] Replaced arguments with Traits --- .../ViewHelpers/Solr/NextRunViewHelper.php | 45 +++++-------------- 1 file changed, 12 insertions(+), 33 deletions(-) diff --git a/Classes/ViewHelpers/Solr/NextRunViewHelper.php b/Classes/ViewHelpers/Solr/NextRunViewHelper.php index 2b3b600..4a5eeec 100644 --- a/Classes/ViewHelpers/Solr/NextRunViewHelper.php +++ b/Classes/ViewHelpers/Solr/NextRunViewHelper.php @@ -11,45 +11,24 @@ namespace JWeiland\Jwtools2\ViewHelpers\Solr; use ApacheSolrForTypo3\Solr\Domain\Site\Site; -use JWeiland\Jwtools2\Domain\Repository\SchedulerRepository; -use JWeiland\Jwtools2\Domain\Repository\SolrRepository; -use TYPO3\CMS\Core\Registry; +use JWeiland\Jwtools2\Traits\InjectRegistryTrait; +use JWeiland\Jwtools2\Traits\InjectSchedulerRepositoryTrait; +use JWeiland\Jwtools2\Traits\InjectSolrRepositoryTrait; use TYPO3Fluid\Fluid\Core\ViewHelper\AbstractViewHelper; /** - * Class NextRunViewHelper + * This ViewHelper is used to calculate the next run for a given site. + * + * Example usage in Fluid template: + * + * + * */ class NextRunViewHelper extends AbstractViewHelper { - /** - * @var SolrRepository - */ - protected $solrRepository; - - /** - * @var SchedulerRepository - */ - protected $schedulerRepository; - - /** - * @var Registry - */ - protected $registry; - - public function injectSolrRepository(SolrRepository $solrRepository): void - { - $this->solrRepository = $solrRepository; - } - - public function injectSchedulerRepository(SchedulerRepository $schedulerRepository): void - { - $this->schedulerRepository = $schedulerRepository; - } - - public function injectRegistry(Registry $registry): void - { - $this->registry = $registry; - } + use InjectSolrRepositoryTrait; + use InjectSchedulerRepositoryTrait; + use InjectRegistryTrait; public function initializeArguments(): void { From 9dde4d7da7623477e2c7ae58e84776313b816734 Mon Sep 17 00:00:00 2001 From: Hoja Mustaffa Abdul Latheef Date: Fri, 16 Feb 2024 14:42:22 +0100 Subject: [PATCH 27/65] [TASK] Compatibility fixes --- Classes/Controller/SolrController.php | 37 +++++++++++++-------------- 1 file changed, 18 insertions(+), 19 deletions(-) diff --git a/Classes/Controller/SolrController.php b/Classes/Controller/SolrController.php index c9b6455..434453f 100644 --- a/Classes/Controller/SolrController.php +++ b/Classes/Controller/SolrController.php @@ -23,6 +23,7 @@ use JWeiland\Jwtools2\Traits\InjectSolrRepositoryTrait; use Psr\Http\Message\ResponseInterface; use TYPO3\CMS\Backend\Attribute\AsController; +use TYPO3\CMS\Core\Database\Connection; use TYPO3\CMS\Core\Database\ConnectionPool; use TYPO3\CMS\Core\Page\PageRenderer; use TYPO3\CMS\Core\Type\ContextualFeedbackSeverity; @@ -73,10 +74,10 @@ public function listAction(): ResponseInterface public function showAction(int $rootPageUid): ResponseInterface { $site = $this->solrRepository->findByRootPage($rootPageUid); - $this->view->assign('site', $site); - $this->view->assign('memoryPeakUsage', $this->registry->get('jwtools2-solr', 'memoryPeakUsage', 0)); + $this->moduleTemplate->assign('site', $site); + $this->moduleTemplate->assign('memoryPeakUsage', $this->registry->get('jwtools2-solr', 'memoryPeakUsage', 0)); - return $this->htmlResponse(); + return $this->moduleTemplate->renderResponse('Show'); } public function showIndexQueueAction(int $rootPageUid, string $configurationName): ResponseInterface @@ -84,12 +85,12 @@ public function showIndexQueueAction(int $rootPageUid, string $configurationName $site = $this->solrRepository->findByRootPage($rootPageUid); if ($site instanceof Site) { $solrConfiguration = $site->getSolrConfiguration()->getIndexQueueConfigurationByName($configurationName); - $this->view->assign('site', $site); - $this->view->assign('solrConfiguration', $solrConfiguration); - $this->view->assign('configurationName', $configurationName); + $this->moduleTemplate->assign('site', $site); + $this->moduleTemplate->assign('solrConfiguration', $solrConfiguration); + $this->moduleTemplate->assign('configurationName', $configurationName); } - return $this->htmlResponse(); + return $this->moduleTemplate->renderResponse('showIndexQueue'); } public function indexOneRecordAction( @@ -137,7 +138,7 @@ public function indexOneRecordAction( } } - $this->redirect( + return $this->redirect( 'showIndexQueue', 'Solr', 'jwtools2', @@ -147,16 +148,14 @@ public function indexOneRecordAction( 'languageUid' => $languageUid, ] ); - - return $this->htmlResponse(); } public function showClearIndexFormAction(int $rootPageUid): ResponseInterface { $site = $this->solrRepository->findByRootPage($rootPageUid); if ($site instanceof Site) { - $this->view->assign('site', $site); - $this->view->assign( + $this->moduleTemplate->assign('site', $site); + $this->moduleTemplate->assign( 'enabledConfigurationNames', $site->getSolrConfiguration()->getEnabledIndexQueueConfigurationNames() ); @@ -166,10 +165,10 @@ public function showClearIndexFormAction(int $rootPageUid): ResponseInterface 'Invalid RootPage UID', ContextualFeedbackSeverity::WARNING ); - $this->redirect('list'); + return $this->redirect('list'); } - return $this->htmlResponse(); + return $this->moduleTemplate->renderResponse('showClearIndexForm'); } #[Extbase\Validate(['validator' => 'NotEmpty', 'param' => 'configurationNames'])] @@ -231,15 +230,15 @@ protected function getIndexQueueItem(int $rootPageUid, string $configurationName ->where( $queryBuilder->expr()->eq( 'root', - $queryBuilder->createNamedParameter($rootPageUid, \PDO::PARAM_INT) + $queryBuilder->createNamedParameter($rootPageUid, Connection::PARAM_INT) ), $queryBuilder->expr()->eq( 'indexing_configuration', - $queryBuilder->createNamedParameter($configurationName, \PDO::PARAM_STR) + $queryBuilder->createNamedParameter($configurationName) ), $queryBuilder->expr()->eq( 'item_uid', - $queryBuilder->createNamedParameter($recordUid, \PDO::PARAM_INT) + $queryBuilder->createNamedParameter($recordUid, Connection::PARAM_INT) ) ) ->executeQuery() @@ -257,11 +256,11 @@ protected function getIndexQueueItem(int $rootPageUid, string $configurationName ->where( $queryBuilder->expr()->eq( 'uid', - $queryBuilder->createNamedParameter($recordUid, \PDO::PARAM_INT) + $queryBuilder->createNamedParameter($recordUid, Connection::PARAM_INT) ) ) ->executeQuery() - ->fetchOne(); + ->fetchAssociative(); if ($tableRecord === false) { return null; From 52f4df8df0032c1ffeebd830e741b1cd8ed03c2c Mon Sep 17 00:00:00 2001 From: Hoja Mustaffa Abdul Latheef Date: Fri, 16 Feb 2024 14:43:09 +0100 Subject: [PATCH 28/65] [TASK] Fixed issues with BE Modules for Solr module --- Classes/Database/Query/QueryGenerator.php | 3 +- Classes/Hooks/CachingFrameworkLoggerHook.php | 3 +- .../MoveTranslatedContentElementsHook.php | 3 +- .../Routing/Aspect/PersistedTableMapper.php | 19 +-- Classes/XClasses/LiveSearch/LiveSearch.php | 8 +- Configuration/Backend/Modules.php | 2 +- Resources/Private/Layouts/Default.html | 12 +- Resources/Private/Templates/Solr/List.html | 149 +++++++++--------- Resources/Private/Templates/Solr/Show.html | 58 +++---- .../Templates/Solr/ShowClearIndexForm.html | 92 ++++++----- .../Templates/Solr/ShowIndexQueue.html | 23 ++- 11 files changed, 194 insertions(+), 178 deletions(-) diff --git a/Classes/Database/Query/QueryGenerator.php b/Classes/Database/Query/QueryGenerator.php index fdf8e87..46bcf6d 100644 --- a/Classes/Database/Query/QueryGenerator.php +++ b/Classes/Database/Query/QueryGenerator.php @@ -11,6 +11,7 @@ namespace JWeiland\Jwtools2\Database\Query; use Doctrine\DBAL\Exception; +use TYPO3\CMS\Core\Database\Connection; use TYPO3\CMS\Core\Database\ConnectionPool; use TYPO3\CMS\Core\Database\Query\Restriction\DeletedRestriction; use TYPO3\CMS\Core\Utility\GeneralUtility; @@ -42,7 +43,7 @@ public function getTreeList($id, $depth, $begin = 0, $permClause = ''): float|in $queryBuilder->select('uid') ->from('pages') ->where( - $queryBuilder->expr()->eq('pid', $queryBuilder->createNamedParameter($id, \PDO::PARAM_INT)), + $queryBuilder->expr()->eq('pid', $queryBuilder->createNamedParameter($id, Connection::PARAM_INT)), $queryBuilder->expr()->eq('sys_language_uid', 0) ) ->orderBy('uid'); diff --git a/Classes/Hooks/CachingFrameworkLoggerHook.php b/Classes/Hooks/CachingFrameworkLoggerHook.php index 0c2b258..1dd95fb 100644 --- a/Classes/Hooks/CachingFrameworkLoggerHook.php +++ b/Classes/Hooks/CachingFrameworkLoggerHook.php @@ -15,6 +15,7 @@ use Psr\Log\LoggerAwareTrait; use TYPO3\CMS\Core\Cache\Frontend\FrontendInterface; use TYPO3\CMS\Core\Cache\Frontend\VariableFrontend; +use TYPO3\CMS\Core\Database\Connection; use TYPO3\CMS\Core\Database\ConnectionPool; use TYPO3\CMS\Core\Utility\GeneralUtility; @@ -120,7 +121,7 @@ protected function getCacheExpressions(): array ->from('tx_jwtools2_cache_expression') ->executeQuery(); - while ($cacheExpression = $statement->fetch(\PDO::FETCH_ASSOC)) { + while ($cacheExpression = $statement->fetchAssociative()) { $cacheExpressions[] = $cacheExpression; } } catch (\Exception $exception) { diff --git a/Classes/Hooks/MoveTranslatedContentElementsHook.php b/Classes/Hooks/MoveTranslatedContentElementsHook.php index 0ef12f6..142c038 100644 --- a/Classes/Hooks/MoveTranslatedContentElementsHook.php +++ b/Classes/Hooks/MoveTranslatedContentElementsHook.php @@ -10,6 +10,7 @@ namespace JWeiland\Jwtools2\Hooks; +use TYPO3\CMS\Core\Database\Connection; use TYPO3\CMS\Core\Database\ConnectionPool; use TYPO3\CMS\Core\Database\Query\Restriction\DeletedRestriction; use TYPO3\CMS\Core\Database\Query\Restriction\WorkspaceRestriction; @@ -106,7 +107,7 @@ protected function getOverlayRecords($uid, DataHandler $dataHandler): array ->where( $queryBuilder->expr()->eq( $GLOBALS['TCA']['tt_content']['ctrl']['transOrigPointerField'], - $queryBuilder->createNamedParameter($uid, \PDO::PARAM_INT, ':pointer') + $queryBuilder->createNamedParameter($uid, Connection::PARAM_INT, ':pointer') ) ) ->executeQuery(); diff --git a/Classes/Routing/Aspect/PersistedTableMapper.php b/Classes/Routing/Aspect/PersistedTableMapper.php index f372311..4ee6700 100644 --- a/Classes/Routing/Aspect/PersistedTableMapper.php +++ b/Classes/Routing/Aspect/PersistedTableMapper.php @@ -10,6 +10,7 @@ namespace JWeiland\Jwtools2\Routing\Aspect; +use TYPO3\CMS\Core\Database\Connection; use TYPO3\CMS\Core\Database\ConnectionPool; use TYPO3\CMS\Core\Database\Query\Restriction\FrontendRestrictionContainer; use TYPO3\CMS\Core\DataHandling\SlugHelper; @@ -107,23 +108,23 @@ protected function getStoredRoute(string $source = '', string $target = ''): arr ->where( $queryBuilder->expr()->eq( 'sys_language_uid', - $queryBuilder->createNamedParameter($this->getSiteLanguage()->getLanguageId(), \PDO::PARAM_INT) + $queryBuilder->createNamedParameter($this->getSiteLanguage()->getLanguageId(), Connection::PARAM_INT) ), $queryBuilder->expr()->eq( 'root_page', - $queryBuilder->createNamedParameter($this->getSite()->getRootPageId(), \PDO::PARAM_INT) + $queryBuilder->createNamedParameter($this->getSite()->getRootPageId(), Connection::PARAM_INT) ), $queryBuilder->expr()->eq( 'tablename', - $queryBuilder->createNamedParameter($this->tableName, \PDO::PARAM_STR) + $queryBuilder->createNamedParameter($this->tableName, Connection::PARAM_STR) ), $queryBuilder->expr()->eq( 'fieldname', - $queryBuilder->createNamedParameter($this->fieldName, \PDO::PARAM_STR) + $queryBuilder->createNamedParameter($this->fieldName) ), $queryBuilder->expr()->eq( $source ? 'source' : 'target', - $queryBuilder->createNamedParameter($source ?: $target, \PDO::PARAM_STR) + $queryBuilder->createNamedParameter($source ?: $target) ) ) ->executeQuery() @@ -148,10 +149,10 @@ protected function setStoredRoute(string $source = '', string $target = ''): voi 'target' => $target, ], [ - \PDO::PARAM_INT, - \PDO::PARAM_INT, - \PDO::PARAM_STR, - \PDO::PARAM_STR, + Connection::PARAM_INT, + Connection::PARAM_INT, + Connection::PARAM_STR, + Connection::PARAM_STR, ] ); } diff --git a/Classes/XClasses/LiveSearch/LiveSearch.php b/Classes/XClasses/LiveSearch/LiveSearch.php index 7689571..3952450 100644 --- a/Classes/XClasses/LiveSearch/LiveSearch.php +++ b/Classes/XClasses/LiveSearch/LiveSearch.php @@ -287,7 +287,7 @@ protected function makeQuerySearchByTable(QueryBuilder $queryBuilder, $tableName // some pages where "11" is somewhere in a timestamp or whatever $constraints[] = $queryBuilder->expr()->eq( 'uid', - $queryBuilder->createNamedParameter($this->queryString, \PDO::PARAM_INT) + $queryBuilder->createNamedParameter($this->queryString, Connection::PARAM_INT) ); } else { $like = '%' . $queryBuilder->escapeLikeWildcards($this->queryString) . '%'; @@ -304,17 +304,17 @@ protected function makeQuerySearchByTable(QueryBuilder $queryBuilder, $tableName $queryBuilder->expr()->comparison( 'LOWER(' . $queryBuilder->quoteIdentifier($fieldName) . ')', 'LIKE', - $queryBuilder->createNamedParameter(mb_strtolower($like), \PDO::PARAM_STR) + $queryBuilder->createNamedParameter(mb_strtolower($like)) ) ); if (is_array($fieldConfig['search'] ?? false)) { if (in_array('case', $fieldConfig['search'], true)) { // Replace case insensitive default constraint - $searchConstraint = $queryBuilder->expr()->andX( + $searchConstraint = $queryBuilder->expr()->and( $queryBuilder->expr()->like( $fieldName, - $queryBuilder->createNamedParameter($like, \PDO::PARAM_STR) + $queryBuilder->createNamedParameter($like) ) ); } diff --git a/Configuration/Backend/Modules.php b/Configuration/Backend/Modules.php index 5c61afe..758ce58 100644 --- a/Configuration/Backend/Modules.php +++ b/Configuration/Backend/Modules.php @@ -23,7 +23,7 @@ 'overview', ], SolrController::class => [ - 'list', + 'list','show', 'showIndexQueue', 'indexOneRecord', 'showClearIndexForm', 'clearIndex', 'showClearFullIndexForm', ], ], ], diff --git a/Resources/Private/Layouts/Default.html b/Resources/Private/Layouts/Default.html index 3fc3e67..127a39d 100644 --- a/Resources/Private/Layouts/Default.html +++ b/Resources/Private/Layouts/Default.html @@ -1,12 +1,12 @@ + xmlns:f="http://typo3.org/ns/TYPO3/CMS/Fluid/ViewHelpers" + data-namespace-typo3-fluid="true">
- + -
- -
+
+ +
diff --git a/Resources/Private/Templates/Solr/List.html b/Resources/Private/Templates/Solr/List.html index 4abd95d..6720c4c 100644 --- a/Resources/Private/Templates/Solr/List.html +++ b/Resources/Private/Templates/Solr/List.html @@ -1,82 +1,85 @@ + xmlns:f="http://typo3.org/ns/TYPO3/CMS/Fluid/ViewHelpers" + xmlns:t="http://typo3.org/ns/JWeiland\Jwtools2\ViewHelpers" + xmlns:c="http://typo3.org/ns/TYPO3\CMS\Core\ViewHelpers" + data-namespace-typo3-fluid="true"> - + - + -
-

{f:translate(key: 'mod.solr.solrFeaturesOverview')}

-

{f:translate(key: 'mod.solr.memoryUsageSchedulerTask')}

-
+
+

{f:translate(key: 'mod.solr.solrFeaturesOverview')}

+

{f:translate(key: 'mod.solr.memoryUsageSchedulerTask')}

+
-
- -
-
- {progress} % -
-
-
-
+
+ +
+
+ {progress} % +
+
+
+
-
-

{f:translate(key: 'mod.solr.configuredRootPages')}

-
- - - -
- - - - - - - - - - - - - - - - - - - -
UIDTitleActionsStatus
- - {site.rootPage.uid} - - - - {site.rootPage.title} - {f:if(condition: '{site.rootPage.uid}=={currentRootPageUid}', then: 'Indexing...')} - - - - - Clear Index... - -  
-
-
- - - -
+
+

{f:translate(key: 'mod.solr.configuredRootPages')}

+
+ + + +
+ + + + + + + + + + + + + + + + + + + +
UIDTitleActionsStatus
+ + {site.rootPageRecord.uid} + + + + {site.rootPageRecord.title} + {f:if(condition: '{site.rootPageRecord.uid}=={currentRootPageUid}', then: ' + Indexing... + + ')} + + + + + Clear Index... + +  
+
+
+ + + +
diff --git a/Resources/Private/Templates/Solr/Show.html b/Resources/Private/Templates/Solr/Show.html index 4fff592..c028b4a 100644 --- a/Resources/Private/Templates/Solr/Show.html +++ b/Resources/Private/Templates/Solr/Show.html @@ -1,34 +1,38 @@ + xmlns:f="http://typo3.org/ns/TYPO3/CMS/Fluid/ViewHelpers" + xmlns:t="http://typo3.org/ns/JWeiland\Jwtools2\ViewHelpers" + data-namespace-typo3-fluid="true"> - + - -

{site.label}

+ + -
-
-

Next Run

-
-
- in {t:solr.nextRun(site: site)} seconds -
-
+
+

{site.label}

+
- -

Enabled IndexQueue Configuration names

-
    - -
  • - - {configurationName} - -
  • -
    -
-
+
+
+

Next Run

+
+
+ in {t:solr.nextRun(site: site)} seconds +
+
+ + +

Enabled IndexQueue Configuration names

+
    + +
  • + + {configurationName} + +
  • +
    +
+
diff --git a/Resources/Private/Templates/Solr/ShowClearIndexForm.html b/Resources/Private/Templates/Solr/ShowClearIndexForm.html index 1a5008a..ec986b1 100644 --- a/Resources/Private/Templates/Solr/ShowClearIndexForm.html +++ b/Resources/Private/Templates/Solr/ShowClearIndexForm.html @@ -1,48 +1,54 @@ - - - -

Clear Index

- - - -

Enabled configuration names for Site: {site.rootPage.title} ({site.rootPage.uid})

- - -
- - -
-
- -

Choose which index should be cleared

- -
- - -
-
- - -
-
- - -
- - -
+ xmlns:f="http://typo3.org/ns/TYPO3/CMS/Fluid/ViewHelpers" + data-namespace-typo3-fluid="true"> + + + + + + +

Clear Index

+ + + + +

Enabled configuration names for Site: {site.rootPageRecord.title} ({site.rootPageRecord.uid})

+ + +
+ + +
+
+ +

Choose which index should be cleared

+ +
+ + +
+
+ + +
+
+ + +
+ + +
+
- - - - - - - + + + + + + + diff --git a/Resources/Private/Templates/Solr/ShowIndexQueue.html b/Resources/Private/Templates/Solr/ShowIndexQueue.html index 6392305..8069552 100644 --- a/Resources/Private/Templates/Solr/ShowIndexQueue.html +++ b/Resources/Private/Templates/Solr/ShowIndexQueue.html @@ -1,18 +1,17 @@ + xmlns:f="http://typo3.org/ns/TYPO3/CMS/Fluid/ViewHelpers" + data-namespace-typo3-fluid="true"> - + - - + + -

Index individual record for configuration "{configurationName}"

- - - -
- -
+

Index individual record for configuration "{configurationName}"

+ + +
+ +
From ebee671bf5c643ee19664b684c1399759319a0c5 Mon Sep 17 00:00:00 2001 From: Hoja Mustaffa Abdul Latheef Date: Fri, 16 Feb 2024 15:26:19 +0100 Subject: [PATCH 29/65] [BUGFIX] Change redirect action with return --- Classes/Controller/SolrController.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Classes/Controller/SolrController.php b/Classes/Controller/SolrController.php index 434453f..1d7444e 100644 --- a/Classes/Controller/SolrController.php +++ b/Classes/Controller/SolrController.php @@ -186,7 +186,7 @@ public function clearIndexAction(int $rootPageUid, array $configurationNames, ar 'We successfully have cleared the index of Site: "' . $site->getTitle() . '"', 'Index cleared' ); - $this->redirect('list'); + return $this->redirect('list'); } else { $this->addFlashMessage( 'We haven\'t found a Site with RootPage UID: ' . $rootPageUid, @@ -195,7 +195,7 @@ public function clearIndexAction(int $rootPageUid, array $configurationNames, ar ); } - return $this->htmlResponse(); + return $this->moduleTemplate->renderResponse('clearIndex'); } /** From bffd468c91de080e61d6918fc97e2eacfb929406 Mon Sep 17 00:00:00 2001 From: Hoja Mustaffa Abdul Latheef Date: Tue, 20 Feb 2024 15:28:07 +0100 Subject: [PATCH 30/65] [TASK] Documentation updates and Code optimizations - Release documentations updated - Code optimizations done --- Classes/Command/CacheQueryCommand.php | 6 +- Classes/Command/ExtensionUpdateCommand.php | 153 --------------------- Documentation/ChangeLog/Index.rst | 8 ++ Documentation/Index.rst | 2 +- Documentation/Introduction/Index.rst | 6 - Documentation/Settings.cfg | 4 +- Resources/Private/Templates/Solr/List.html | 19 ++- 7 files changed, 27 insertions(+), 171 deletions(-) delete mode 100644 Classes/Command/ExtensionUpdateCommand.php diff --git a/Classes/Command/CacheQueryCommand.php b/Classes/Command/CacheQueryCommand.php index 3e29d87..71d3a96 100644 --- a/Classes/Command/CacheQueryCommand.php +++ b/Classes/Command/CacheQueryCommand.php @@ -68,7 +68,9 @@ protected function execute(InputInterface $input, OutputInterface $output): int } if ($input->getOption('tag') === null && $input->getOption('entryIdentifier') === null) { - $output->writeln('Without specifying tag or entryIdentifier option the result is too big. Please set one of these options.'); + $output->writeln( + 'Without specifying tag or entryIdentifier option the result is too big. Please set one of these options.' + ); return 105; } @@ -96,7 +98,7 @@ protected function execute(InputInterface $input, OutputInterface $output): int } elseif (is_bool($content)) { $output->writeln($content ? 'TRUE' : 'FALSE'); } elseif (is_array($content)) { - $output->writeln(json_encode($content, JSON_PRETTY_PRINT)); + $output->writeln(json_encode($content, JSON_THROW_ON_ERROR | JSON_PRETTY_PRINT)); } else { $output->writeln($content); } diff --git a/Classes/Command/ExtensionUpdateCommand.php b/Classes/Command/ExtensionUpdateCommand.php deleted file mode 100644 index 4ae0547..0000000 --- a/Classes/Command/ExtensionUpdateCommand.php +++ /dev/null @@ -1,153 +0,0 @@ -setDescription('Check and execute all extension updates (class.ext_update.php)') - ->addArgument( - 'ext_key', - InputArgument::OPTIONAL, - 'If set, only specified extension will be updated' - ) - ->addOption( - 'list', - 'l', - InputOption::VALUE_NONE, - 'If set, we only show the update possible active extension keys' - ) - ->addOption( - 'force', - 'f', - InputOption::VALUE_NONE, - 'If you execute all update scripts and a script will throw an exception this command will normally break and stop. Add this option to ignore that exception and process all other extensions' - ) - ->setHelp( - 'This command loops through all active extensions and searches for available class.ext_update.php files. If method access() returns true, this command will call main() method.' - ); - } - - protected function execute(InputInterface $input, OutputInterface $output): int - { - $typo3Version = GeneralUtility::makeInstance(Typo3Version::class); - if (version_compare($typo3Version->getBranch(), '11.0', '>=')) { - $output->writeln('Processing class.ext_update.php files has been removed with TYPO3 11. This command will only work in TYPO3 10.'); - return 100; - } - - $packages = $this->getUpdatePossibleActivePackages(); - - if ($input->getOption('list')) { - $output->writeln('List of extensions where update is possible'); - $table = new Table($output); - $table->setHeaders(['ext_key']); - $table->addRows($packages); - $table->render(); - - return 0; - } - if ($input->getArgument('ext_key')) { - if (!array_key_exists($input->getArgument('ext_key'), $packages)) { - $output->writeln('Given ext_key does not exist in possible extension list'); - return 1; - } - $output->writeln('Start update script of extension: ' . $input->getArgument('ext_key')); - if (!$this->updateExtension($input->getArgument('ext_key'))) { - $output->writeln( - sprintf( - 'Error while executing main() method of extension: %s', - $input->getArgument('ext_key') - ) - ); - return 2; - } - } else { - foreach ($packages as $extKey => $_) { - $output->writeln('Start update script of extension: ' . $extKey); - if (!$this->updateExtension($extKey)) { - $output->writeln( - sprintf( - 'Error while executing main() method of extension: %s', - $input->getArgument('ext_key') - ) - ); - if ($input->getOption('force')) { - continue; - } - return 2; - } - } - } - - $output->writeln('Update successful'); - - return 0; // everything fine - } - - /** - * Execute update script of extension - */ - protected function updateExtension(string $extKey): bool - { - $updateScriptUtility = GeneralUtility::makeInstance(UpdateScriptUtility::class); - try { - $updateScriptUtility->executeUpdateIfNeeded($extKey); - } catch (\Exception $exception) { - return false; - } - return true; - } - - /** - * Get all active extensions with class.ext_update.php - * where an update is possible (Method call returns true) - */ - protected function getUpdatePossibleActivePackages(): array - { - $packageManager = GeneralUtility::makeInstance( - PackageManager::class, - GeneralUtility::makeInstance(DependencyOrderingService::class) - ); - $activePackages = $packageManager->getActivePackages(); - $updateScriptUtility = GeneralUtility::makeInstance(UpdateScriptUtility::class); - - $packages = []; - foreach ($activePackages as $activePackage) { - if ($updateScriptUtility->checkUpdateScriptExists($activePackage->getPackageKey())) { - $packages[$activePackage->getPackageKey()] = [ - $activePackage->getPackageKey(), - ]; - } - } - - ksort($packages); - - return $packages; - } -} diff --git a/Documentation/ChangeLog/Index.rst b/Documentation/ChangeLog/Index.rst index 4f5033a..f731329 100644 --- a/Documentation/ChangeLog/Index.rst +++ b/Documentation/ChangeLog/Index.rst @@ -10,6 +10,14 @@ ChangeLog .. contents:: :local: +Version 7.0.0 +============= + +* [TASK] Compatibility fix for TYPO3 12 +* [TASK] Testing Framework migrated to TYPO3 Tesing Framework +* [TASK] Remove support for TYPO3 11 and lower versions +* [TASK] Removed jwtools2:executeExtensionUpdate command line controller as it is obsolete. + Version 6.0.6 ============= diff --git a/Documentation/Index.rst b/Documentation/Index.rst index 1f1be10..f46d293 100644 --- a/Documentation/Index.rst +++ b/Documentation/Index.rst @@ -18,7 +18,7 @@ JW Tools 2 en :Author: - Stefan Froemken + Stefan Froemken, Hoja Mustaffa Abdul Latheef :License: This document is published under the diff --git a/Documentation/Introduction/Index.rst b/Documentation/Introduction/Index.rst index 1dbf715..aa5da35 100644 --- a/Documentation/Introduction/Index.rst +++ b/Documentation/Introduction/Index.rst @@ -50,12 +50,6 @@ Be careful: This command does not know, if password in DB is a plain password or over all configured Hash Methods of TYPO3. If no Hash Method was found for current password in database, the password will be updated. -jwtools2:executeExtensionUpdate -******************************* - -With this command you can execute the update script of extensions via ``class.ext_update.php``. It only starts the -update, but if you have something special or a wizard in this file this command will not help. - Database -------- diff --git a/Documentation/Settings.cfg b/Documentation/Settings.cfg index c7be53b..049c7c4 100644 --- a/Documentation/Settings.cfg +++ b/Documentation/Settings.cfg @@ -4,8 +4,8 @@ [general] project = Jwtools2 -version = 6.0.6 -release = 6.0 +version = 7.0.0 +release = 7.0 copyright = since 2019 by jweiland.net [html_theme_options] diff --git a/Resources/Private/Templates/Solr/List.html b/Resources/Private/Templates/Solr/List.html index 6720c4c..6222e02 100644 --- a/Resources/Private/Templates/Solr/List.html +++ b/Resources/Private/Templates/Solr/List.html @@ -17,7 +17,11 @@

{f:translate(key: 'mod.solr.memoryUsageSchedulerTask')}

-
{progress} %
@@ -55,15 +59,16 @@

{f:translate(key: 'mod.solr.configuredRootPages')}

{site.rootPageRecord.title} - {f:if(condition: '{site.rootPageRecord.uid}=={currentRootPageUid}', then: ' - Indexing... - - ')} + + Indexing... + + - + Clear Index... From e8e75f2fd3c6f1e9682cc94eb19072d42b98bff3 Mon Sep 17 00:00:00 2001 From: Hoja Mustaffa Abdul Latheef Date: Fri, 23 Feb 2024 09:38:23 +0100 Subject: [PATCH 31/65] [TASK] Migrating Test Cases to TYPO3 Testing Framework - Unit Tests migrated to TYPO3 Testing Framework - Functional Tests migrated to TYPO3 Testing Framework - Removed obselete test cases which are removed because of removal --- .../Hooks/InitializeStdWrapTest.php | 60 ++--- .../ViewHelpers/Format/HtmlViewHelperTest.php | 246 ------------------ Tests/Unit/Task/ExecuteQueryTaskTest.php | 147 +++++------ 3 files changed, 88 insertions(+), 365 deletions(-) delete mode 100644 Tests/Functional/ViewHelpers/Format/HtmlViewHelperTest.php diff --git a/Tests/Functional/Hooks/InitializeStdWrapTest.php b/Tests/Functional/Hooks/InitializeStdWrapTest.php index 1863ddd..fd7578b 100644 --- a/Tests/Functional/Hooks/InitializeStdWrapTest.php +++ b/Tests/Functional/Hooks/InitializeStdWrapTest.php @@ -11,8 +11,7 @@ namespace TYPO3\CMS\Fluid\Tests\Functional\Hooks; use JWeiland\Jwtools2\Hooks\InitializeStdWrap; -use Prophecy\PhpUnit\ProphecyTrait; -use Prophecy\Prophecy\ObjectProphecy; +use PHPUnit\Framework\MockObject\MockObject; use TYPO3\CMS\Core\Configuration\ExtensionConfiguration; use TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer; use TYPO3\TestingFramework\Core\Functional\FunctionalTestCase; @@ -22,43 +21,22 @@ */ class InitializeStdWrapTest extends FunctionalTestCase { - use ProphecyTrait; + protected InitializeStdWrap $subject; - /** - * @var InitializeStdWrap - */ - protected $subject; - - /** - * @var ExtensionConfiguration|ObjectProphecy - */ - protected $extensionConfigurationProphecy; + protected ExtensionConfiguration | MockObject $extensionConfigurationMock; - /** - * @var array - */ - protected $testExtensionsToLoad = [ - 'typo3conf/ext/jwtools2', + protected array $testExtensionsToLoad = [ + 'jweiland/jwtools2', ]; protected function setUp(): void { parent::setUp(); - $this->extensionConfigurationProphecy = $this->prophesize(ExtensionConfiguration::class); + $this->extensionConfigurationMock = $this->getAccessibleMock(ExtensionConfiguration::class); $this->subject = new InitializeStdWrap( - $this->extensionConfigurationProphecy->reveal() - ); - } - - protected function tearDown(): void - { - unset( - $this->subject, - $this->extensionConfigurationProphecy + $this->extensionConfigurationMock ); - - parent::tearDown(); } /** @@ -71,8 +49,10 @@ public function postProcessWillNotModifyContentObjectBecauseOfNonArray(): void 'title' => 'Hello' ]; - $this->extensionConfigurationProphecy - ->get('jwtools2') + $this->extensionConfigurationMock + ->expects(self::any()) + ->method('get') + ->with('jwtools2') ->willReturn([ 'typo3TransferTypoScriptCurrent' => '1' ]); @@ -99,8 +79,10 @@ public function postProcessWillNotModifyContentObjectBecauseOfEmptyArray(): void 'title' => 'Hello' ]; - $this->extensionConfigurationProphecy - ->get('jwtools2') + $this->extensionConfigurationMock + ->expects(self::any()) + ->method('get') + ->with('jwtools2') ->willReturn([ 'typo3TransferTypoScriptCurrent' => '1' ]); @@ -132,8 +114,10 @@ public function postProcessWillNotModifyContentObjectBecauseFeatureIsDisabled(): $parentRecordData = $data; $parentRecordData[$contentObject->currentValKey] = 'Welcome'; - $this->extensionConfigurationProphecy - ->get('jwtools2') + $this->extensionConfigurationMock + ->expects(self::atLeastOnce()) + ->method('get') + ->with('jwtools2') ->willReturn([ 'typo3TransferTypoScriptCurrent' => '0' ]); @@ -164,8 +148,10 @@ public function postProcessWillModifyContentObject(): void $parentRecordData = $data; $parentRecordData[$contentObject->currentValKey] = 'Welcome'; - $this->extensionConfigurationProphecy - ->get('jwtools2') + $this->extensionConfigurationMock + ->expects(self::atLeastOnce()) + ->method('get') + ->with('jwtools2') ->willReturn([ 'typo3TransferTypoScriptCurrent' => '1' ]); diff --git a/Tests/Functional/ViewHelpers/Format/HtmlViewHelperTest.php b/Tests/Functional/ViewHelpers/Format/HtmlViewHelperTest.php deleted file mode 100644 index 3d1422d..0000000 --- a/Tests/Functional/ViewHelpers/Format/HtmlViewHelperTest.php +++ /dev/null @@ -1,246 +0,0 @@ - [ - 'parseFunc_RTE.' => [ - 'allowTags' => 'a,p', - 'denyTags' => '*', - 'makelinks' => '1', - 'makelinks.' => [ - 'http' => [ - 'keep' => 'path', - ], - ], - 'tags.' => [ - 'a' => 'TEXT', - 'a.' => [ - 'current' => '1', - 'typolink.' => [ - 'parameter.' => [ - 'data' => 'parameters:href', - ], - 'ATagParams.' => [ - 'data' => 'parameters:allParams', - ], - ], - ], - ], - 'nonTypoTagStdWrap.' => [ - 'setContentToCurrent' => '1', - 'cObject' => 'CASE', - 'cObject.' => [ - 'key.' => [ - 'field' => 'colPos', - ], - 'default' => 'TEXT', - 'default.' => [ - 'current' => '1', - 'HTMLparser' => '1', - 'HTMLparser.' => [ - 'tags.' => [ - 'a.' => [ - 'fixAttrib.' => [ - 'style.' => [ - 'always' => '1', - 'set' => 'color: blue;', - ], - ], - ], - ], - ], - ], - '2' => 'TEXT', - '2.' => [ - 'current' => '1', - 'HTMLparser' => '1', - 'HTMLparser.' => [ - 'tags.' => [ - 'a.' => [ - 'fixAttrib.' => [ - 'style.' => [ - 'always' => '1', - 'set' => 'color: red;', - ], - ], - ], - ], - ], - ], - ], - ], - ], - ], - ]; - - protected function setUp(): void - { - parent::setUp(); - - $this->configurationManagerProphecy = $this->prophesize(ConfigurationManager::class); - $this->configurationManagerProphecy - ->getConfiguration(ConfigurationManagerInterface::CONFIGURATION_TYPE_FULL_TYPOSCRIPT) - ->shouldBeCalled() - ->willReturn($this->typoScript); - - $this->objectManagerProphecy = $this->prophesize(ObjectManager::class); - $this->objectManagerProphecy - ->get(ConfigurationManagerInterface::class) - ->shouldBeCalled() - ->willReturn($this->configurationManagerProphecy->reveal()); - - $linkDetails = [ - 'url' => 'https://typo3.org', - 'type' => 'url', - 'typoLinkParameter' => 'https://typo3.org', - ]; - - /** @var ExternalUrlLinkBuilder|ObjectProphecy $linkBuilder */ - $linkBuilder = $this->prophesize(ExternalUrlLinkBuilder::class); - $linkBuilder - ->build( - $linkDetails, - 'Link', - '', - [ - 'parameter.' => [ - 'data' => 'parameters:href', - ], - 'ATagParams.' => [ - 'data' => 'parameters:allParams', - ], - ] - ) - ->shouldBeCalled() - ->willReturn([ - 'https://typo3.org', - 'Link', - '_blank', - ]); - - GeneralUtility::setSingletonInstance(ObjectManager::class, $this->objectManagerProphecy->reveal()); - GeneralUtility::addInstance( - ExternalUrlLinkBuilder::class, - $linkBuilder->reveal() - ); - - $this->subject = new HtmlViewHelper(); - $this->subject->setRenderingContext($this->prophesize(RenderingContext::class)->reveal()); - } - - protected function tearDown(): void - { - unset( - $this->subject, - $this->objectManagerProphecy, - $this->configurationManagerProphecy - ); - GeneralUtility::resetSingletonInstances([]); - parent::tearDown(); - } - - /** - * @test - */ - public function renderWithParseFuncTsPathWillRenderBlueLinks(): void - { - $typo3Version = GeneralUtility::makeInstance(Typo3Version::class); - if (version_compare($typo3Version->getBranch(), '10.4', '=')) { - $this->subject->setArguments([ - 'parseFuncTSPath' => 'lib.parseFunc_RTE', - ]); - - $this->subject->setRenderChildrenClosure(function () { - return 'I am a Link'; - }); - - self::assertSame( - 'I am a Link', - $this->subject->initializeArgumentsAndRender() - ); - } else { - self::markTestSkipped('Skipped, because our modified version of HtmlViewHelper was merged to TYPO3 11'); - } - } - - /** - * @test - */ - public function renderWithParseFuncTsPathWillConsiderTsConditionAndRendersRedLinks(): void - { - $typo3Version = GeneralUtility::makeInstance(Typo3Version::class); - if (version_compare($typo3Version->getBranch(), '10.4', '=')) { - $this->subject->setArguments([ - 'parseFuncTSPath' => 'lib.parseFunc_RTE', - 'data' => [ - 'colPos' => '2', - ], - ]); - - $this->subject->setRenderChildrenClosure(function () { - return 'I am a Link'; - }); - - self::assertSame( - 'I am a Link', - $this->subject->initializeArgumentsAndRender() - ); - } else { - self::markTestSkipped('Skipped, because our modified version of HtmlViewHelper was merged to TYPO3 11'); - } - } -} diff --git a/Tests/Unit/Task/ExecuteQueryTaskTest.php b/Tests/Unit/Task/ExecuteQueryTaskTest.php index 1ec7c89..5dd4220 100644 --- a/Tests/Unit/Task/ExecuteQueryTaskTest.php +++ b/Tests/Unit/Task/ExecuteQueryTaskTest.php @@ -2,55 +2,47 @@ declare(strict_types=1); -/* - * This file is part of the package jweiland/jwtools2. - * For the full copyright and license information, please read the - * LICENSE file that was distributed with this source code. - */ - namespace JWeiland\Jwtools2\Tests\Unit\Task; use Doctrine\DBAL\Driver\Statement; use JWeiland\Jwtools2\Task\ExecuteQueryTask; -use Prophecy\PhpUnit\ProphecyTrait; -use Prophecy\Prophecy\ObjectProphecy; use TYPO3\CMS\Core\Database\Connection; use TYPO3\CMS\Core\Database\ConnectionPool; use TYPO3\CMS\Core\Utility\GeneralUtility; use TYPO3\CMS\Scheduler\Scheduler; use TYPO3\TestingFramework\Core\Unit\UnitTestCase; -/** - * Test case. - */ class ExecuteQueryTaskTest extends UnitTestCase { - use ProphecyTrait; - - /** - * @var ExecuteQueryTask - */ - protected $subject; + protected ExecuteQueryTask $subject; protected function setUp(): void { - // Because of AbstractTask __construct we have to set our own Scheduler class - /** @var Scheduler|ObjectProphecy $schedulerProphecy */ - $schedulerProphecy = $this->prophesize(Scheduler::class); - GeneralUtility::setSingletonInstance(Scheduler::class, $schedulerProphecy->reveal()); + parent::setUp(); + + $GLOBALS['TYPO3_CONF_VARS'] = [ + 'SYS' => [ + 'trustedHostsPattern' => '.*', + 'devIPmask' => '*', + ], + 'DB' => [ + 'Connections' => [ + 'Default' => [ + 'driver' => 'pdo_sqlite', + 'url' => 'sqlite::memory:', + ], + ], + ], + ]; + + $this->resetSingletonInstances = true; + + // Mock the Scheduler class + GeneralUtility::setSingletonInstance(Scheduler::class, $this->createMock(Scheduler::class)); $this->subject = new ExecuteQueryTask(); } - protected function tearDown(): void - { - unset( - $this->subject - ); - - parent::tearDown(); - } - /** * @test */ @@ -68,27 +60,26 @@ public function executeWithSingleQueryWillReturnTrue(): void { $this->subject->setSqlQuery('UPDATE what_ever;'); - /** @var Statement|ObjectProphecy $statementProphecy */ - $statementProphecy = $this->prophesize(Statement::class); - $statementProphecy - ->execute() - ->shouldBeCalled() - ->willReturn(true); - - /** @var Connection|ObjectProphecy $connectionProphecy */ - $connectionProphecy = $this->prophesize(Connection::class); - $connectionProphecy - ->query('UPDATE what_ever;') - ->shouldBeCalled() - ->willReturn($statementProphecy->reveal()); - - /** @var ConnectionPool|ObjectProphecy $connectionPoolProphecy */ - $connectionPoolProphecy = $this->prophesize(ConnectionPool::class); - $connectionPoolProphecy - ->getConnectionByName('Default') - ->shouldBeCalled() - ->willReturn($connectionProphecy->reveal()); - GeneralUtility::addInstance(ConnectionPool::class, $connectionPoolProphecy->reveal()); + $statementMock = $this->getMockBuilder(Statement::class) + ->disableOriginalConstructor() + ->getMock(); + + $connectionMock = $this->createMock(Connection::class); + $connectionMock->expects(self::once()) + ->method('executeStatement') + ->with( + $this->equalTo('UPDATE what_ever;'), + $this->equalTo([]) + ) + ->willReturn($statementMock); + + $connectionPoolMock = $this->createMock(ConnectionPool::class); + $connectionPoolMock->expects(self::once()) + ->method('getConnectionByName') + ->with('Default') + ->willReturn($connectionMock); + + GeneralUtility::addInstance(ConnectionPool::class, $connectionPoolMock); self::assertTrue( $this->subject->execute() @@ -100,37 +91,29 @@ public function executeWithSingleQueryWillReturnTrue(): void */ public function executeWithMultipleQueriesWillReturnTrue(): void { - $this->subject->setSqlQuery("UPDATE this;\nUPDATE that;\nUPDATE else;"); - - /** @var Statement|ObjectProphecy $statementProphecy */ - $statementProphecy = $this->prophesize(Statement::class); - $statementProphecy - ->execute() - ->shouldBeCalled() - ->willReturn(true); - - /** @var Connection|ObjectProphecy $connectionProphecy */ - $connectionProphecy = $this->prophesize(Connection::class); - $connectionProphecy - ->query('UPDATE this') - ->shouldBeCalled() - ->willReturn($statementProphecy->reveal()); - $connectionProphecy - ->query('UPDATE that') - ->shouldBeCalled() - ->willReturn($statementProphecy->reveal()); - $connectionProphecy - ->query('UPDATE else;') - ->shouldBeCalled() - ->willReturn($statementProphecy->reveal()); - - /** @var ConnectionPool|ObjectProphecy $connectionPoolProphecy */ - $connectionPoolProphecy = $this->prophesize(ConnectionPool::class); - $connectionPoolProphecy - ->getConnectionByName('Default') - ->shouldBeCalled() - ->willReturn($connectionProphecy->reveal()); - GeneralUtility::addInstance(ConnectionPool::class, $connectionPoolProphecy->reveal()); + $this->subject->setSqlQuery("UPDATE what_ever;\nUPDATE that;\nUPDATE else;"); + + $statementMock = $this->getMockBuilder(Statement::class) + ->disableOriginalConstructor() + ->getMock(); + + $connectionMock = $this->createMock(Connection::class); + $connectionMock->expects(self::exactly(3)) + ->method('executeStatement') + ->withConsecutive( + [$this->equalTo('UPDATE what_ever;'), $this->equalTo([])], + [$this->equalTo('UPDATE that;'), $this->equalTo([])], + [$this->equalTo('UPDATE else;'), $this->equalTo([])] + ) + ->willReturn($statementMock); + + $connectionPoolMock = $this->createMock(ConnectionPool::class); + $connectionPoolMock->expects(self::once()) + ->method('getConnectionByName') + ->with('Default') + ->willReturn($connectionMock); + + GeneralUtility::addInstance(ConnectionPool::class, $connectionPoolMock); self::assertTrue( $this->subject->execute() From e3b6a7eee1f983e535450e86a2a2ec612caf4ba1 Mon Sep 17 00:00:00 2001 From: Hoja Mustaffa Abdul Latheef Date: Wed, 6 Mar 2024 14:07:25 +0100 Subject: [PATCH 32/65] Added .env and testing related paths to ignore --- .gitignore | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index d66a47d..7909705 100644 --- a/.gitignore +++ b/.gitignore @@ -30,5 +30,11 @@ nbproject .session *.log +# Ignore testing stuff +*.env +/.Build +/composer.json.orig +/composer.json.testing + # Ignore composer stuff -/composer.lock \ No newline at end of file +/composer.lock From 766ac185421f0d89e423e8f01bf9527498179486 Mon Sep 17 00:00:00 2001 From: Hoja Mustaffa Abdul Latheef Date: Wed, 6 Mar 2024 14:20:37 +0100 Subject: [PATCH 33/65] [TASK] Migrated filelist context menu action for update/create metadata to version 12 LTS - Removed jQuery dependency - Replaced deprecations - Removed old registration methods to updated --- .../UpdateFileMetaDataProvider.php | 5 ++- Classes/Controller/Ajax/SysFileController.php | 12 ++---- Configuration/JavaScriptModules.php | 7 +++- Configuration/Services.yaml | 6 +++ .../Public/JavaScript/context-menu-actions.js | 37 +++++++++++++++++++ ext_localconf.php | 5 --- 6 files changed, 55 insertions(+), 17 deletions(-) create mode 100644 Resources/Public/JavaScript/context-menu-actions.js diff --git a/Classes/ContextMenu/ItemProviders/UpdateFileMetaDataProvider.php b/Classes/ContextMenu/ItemProviders/UpdateFileMetaDataProvider.php index d1bc6dd..39a6f87 100644 --- a/Classes/ContextMenu/ItemProviders/UpdateFileMetaDataProvider.php +++ b/Classes/ContextMenu/ItemProviders/UpdateFileMetaDataProvider.php @@ -14,7 +14,8 @@ use TYPO3\CMS\Filelist\ContextMenu\ItemProviders\FileProvider; /** - * A command to execute extension updates realized with class.ext_update.php + * Adds a new entry ``Create/Update file metadata`` into context menu of filelist module to create a missing file + * metadata record or to update the existing metadata record (sys_file_metadata). */ class UpdateFileMetaDataProvider extends FileProvider { @@ -69,7 +70,7 @@ protected function canUpdateFile(): bool protected function getAdditionalAttributes(string $itemName): array { return [ - 'data-callback-module' => 'TYPO3/CMS/Jwtools2/ContextMenuActions', + 'data-callback-module' => '@jweiland/jwtools2/context-menu-actions', 'data-status-title' => $this->languageService->sL( 'LLL:EXT:jwtools2/Resources/Private/Language/locallang_mod.xlf:statusDeleteTitle' ), diff --git a/Classes/Controller/Ajax/SysFileController.php b/Classes/Controller/Ajax/SysFileController.php index a7b9444..8725c35 100644 --- a/Classes/Controller/Ajax/SysFileController.php +++ b/Classes/Controller/Ajax/SysFileController.php @@ -14,6 +14,7 @@ use TYPO3\CMS\Core\Http\JsonResponse; use TYPO3\CMS\Core\Imaging\GraphicalFunctions; use TYPO3\CMS\Core\Resource\Event\AfterFileAddedEvent; +use TYPO3\CMS\Core\Resource\Exception\IllegalFileExtensionException; use TYPO3\CMS\Core\Resource\FileInterface; use TYPO3\CMS\Core\Resource\Folder; use TYPO3\CMS\Core\Resource\Index\Indexer; @@ -29,15 +30,9 @@ */ class SysFileController { - /** - * @var ResourceFactory - */ - protected $resourceFactory; + protected ResourceFactory $resourceFactory; - /** - * @var GraphicalFunctions - */ - protected $graphicalFunctions; + protected GraphicalFunctions $graphicalFunctions; public function __construct(ResourceFactory $resourceFactory, GraphicalFunctions $graphicalFunctions) { @@ -69,6 +64,7 @@ public function updateFileMetadataAction(ServerRequestInterface $request): JsonR * which does not read the original image dimensions, but width/height from EXIF data instead. * * @param FileInterface $fileObject + * @throws IllegalFileExtensionException */ protected function updateExifData(FileInterface $fileObject): void { diff --git a/Configuration/JavaScriptModules.php b/Configuration/JavaScriptModules.php index 45931ae..e33c3dc 100644 --- a/Configuration/JavaScriptModules.php +++ b/Configuration/JavaScriptModules.php @@ -2,8 +2,11 @@ return [ 'dependencies' => [ - 'backend', - 'core', + 'backend', 'core' + ], + 'tags' => [ + 'backend.module', + 'backend.contextmenu', ], 'imports' => [ '@jweiland/jwtools2/' => 'EXT:jwtools2/Resources/Public/JavaScript/', diff --git a/Configuration/Services.yaml b/Configuration/Services.yaml index 0f3ba17..1418a7d 100644 --- a/Configuration/Services.yaml +++ b/Configuration/Services.yaml @@ -59,3 +59,9 @@ services: - name: event.listener identifier: 'jwtools2.events.beforeItemIsIndexedEvent' event: ApacheSolrForTypo3\Solr\Event\Indexing\BeforeItemIsIndexedEvent + + # Backend Context Menu Provider + JWeiland\Jwtools2\ContextMenu\ItemProviders\UpdateFileMetaDataProvider: + tags: + - name: backend.contextmenu.itemprovider + identifier: 'jwtools2.contextmenu.itemproviders.updatefilemetadata' diff --git a/Resources/Public/JavaScript/context-menu-actions.js b/Resources/Public/JavaScript/context-menu-actions.js new file mode 100644 index 0000000..104cb6d --- /dev/null +++ b/Resources/Public/JavaScript/context-menu-actions.js @@ -0,0 +1,37 @@ +import AjaxRequest from '@typo3/core/ajax/ajax-request.js'; +import Md5 from '@typo3/backend/hashing/md5.js'; + +/** + * Module: @jweiland/jwtools2/context-menu-actions + * + * @exports @jweiland/jwtools2/context-menu-actions + */ +class ContextMenuActions { + + /** + * Update/Create sys_file_metadata record + * + * @param {string} table + * @param {int} uid of the sys_file record + * @param {Object} dataAttributes + */ + updateFileMetadata(table, uid, dataAttributes) { + if (table === 'sys_file') { + const hash = Md5.hash(uid).substring(0, 10); + const url = TYPO3.settings.ajaxUrls.jwtools2_updateFileMetadata; + const request = new AjaxRequest(url); + const queryParameters = { CB: { files: { ["_FILE%7C" + hash]: uid } } }; + request.withQueryArguments(queryParameters).get().finally(() => { + // We need refresh of frame to show updated filesize + top.TYPO3.Backend.ContentContainer.refresh(true); + top.TYPO3.Notification.success( + dataAttributes.statusTitle, + dataAttributes.statusDescription, + 5 + ); + }); + } + } +} + +export default new ContextMenuActions(); diff --git a/ext_localconf.php b/ext_localconf.php index ee4cbe8..ff6479b 100644 --- a/ext_localconf.php +++ b/ext_localconf.php @@ -93,11 +93,6 @@ = \JWeiland\Jwtools2\Hooks\MoveTranslatedContentElementsHook::class; } - if ($jwToolsConfiguration['enableContextMenuToUpdateFileMetadata'] ?? false) { - $GLOBALS['TYPO3_CONF_VARS']['BE']['ContextMenu']['ItemProviders'][1622440501] - = \JWeiland\Jwtools2\ContextMenu\ItemProviders\UpdateFileMetaDataProvider::class; - } - if ($jwToolsConfiguration['enableCachingFrameworkLogger'] ?? false) { $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/cache/frontend/class.t3lib_cache_frontend_variablefrontend.php']['set'][1655965501] = \JWeiland\Jwtools2\Hooks\CachingFrameworkLoggerHook::class . '->analyze'; From b56c2c74a5f042ec2eb5a5ee4d4f198ab4369f5d Mon Sep 17 00:00:00 2001 From: Hoja Mustaffa Abdul Latheef Date: Wed, 6 Mar 2024 14:23:08 +0100 Subject: [PATCH 34/65] Updated Build path --- Build/php-cs-fixer/config.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Build/php-cs-fixer/config.php b/Build/php-cs-fixer/config.php index aa0a91a..a798a53 100644 --- a/Build/php-cs-fixer/config.php +++ b/Build/php-cs-fixer/config.php @@ -22,7 +22,7 @@ $finder = PhpCsFixer\Finder::create() ->name('*.php') - ->exclude('.build') + ->exclude('.Build') ->in(__DIR__); return (new \PhpCsFixer\Config()) From 206d283365169bba6a08775066288f826e8d6dc7 Mon Sep 17 00:00:00 2001 From: Hoja Mustaffa Abdul Latheef Date: Wed, 6 Mar 2024 14:24:17 +0100 Subject: [PATCH 35/65] Removed old ContextMenuActions.js --- .../Public/JavaScript/ContextMenuActions.js | 43 ------------------- 1 file changed, 43 deletions(-) delete mode 100644 Resources/Public/JavaScript/ContextMenuActions.js diff --git a/Resources/Public/JavaScript/ContextMenuActions.js b/Resources/Public/JavaScript/ContextMenuActions.js deleted file mode 100644 index 8a95cf6..0000000 --- a/Resources/Public/JavaScript/ContextMenuActions.js +++ /dev/null @@ -1,43 +0,0 @@ -/** - * Module: TYPO3/CMS/Jwtools2/ContextMenuActions - * - * @exports TYPO3/CMS/Jwtools2/ContextMenuActions - */ -define(["TYPO3/CMS/Core/Ajax/AjaxRequest", "TYPO3/CMS/Backend/Hashing/Md5", "jquery"], function (typo3Ajax, hashMd5, jQuery) { - 'use strict'; - - // Add surrounding object into jQuery.default - // Needed in updateFileMetadata() - jQuery = __importDefault(jQuery); - - /** - * @exports TYPO3/CMS/ExtensionKey/ContextMenuActions - */ - let ContextMenuActions = {}; - - /** - * Update/Create sys_file_metadata record - * - * @param {string} table - * @param {int} uid of the sys_file record - */ - ContextMenuActions.updateFileMetadata = function (table, uid) { - if (table === "sys_file") { - let hash = hashMd5.hash(uid).substring(0, 10); - let url = TYPO3.settings.ajaxUrls.jwtools2_updateFileMetadata; - let request = {CB: {files: {["_FILE%7C" + hash]: uid}}}; - - new typo3Ajax(url).withQueryArguments(request).get().finally(() => { - // We need refresh of frame to show updated filesize - top.TYPO3.Backend.ContentContainer.refresh(true); - top.TYPO3.Notification.success( - jQuery.default(this).data("status-title"), - jQuery.default(this).data("status-description"), - 5 - ); - }); - } - }; - - return ContextMenuActions; -}); From a0192036bfe2c0040d83296680022038595865bd Mon Sep 17 00:00:00 2001 From: Hoja Mustaffa Abdul Latheef Date: Wed, 6 Mar 2024 14:36:20 +0100 Subject: [PATCH 36/65] [BUGFIX] Fixed issue with argument missing in CLI run of Command Controller --- Configuration/Services.yaml | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/Configuration/Services.yaml b/Configuration/Services.yaml index 1418a7d..fd82af7 100644 --- a/Configuration/Services.yaml +++ b/Configuration/Services.yaml @@ -25,12 +25,9 @@ services: - name: 'console.command' command: 'jwtools2:convertpasswords' schedulable: false - JWeiland\Jwtools2\Command\ExtensionUpdateCommand: - tags: - - name: 'console.command' - command: 'jwtools2:executeExtensionUpdate' - schedulable: false JWeiland\Jwtools2\Command\StatusReportCommand: + arguments: + - '@TYPO3\CMS\Scheduler\Domain\Repository\SchedulerTaskRepository' tags: - name: 'console.command' command: 'jwtools2:statusreport' From db912740c5ce112fe9cfdfc563eca864e2427dfc Mon Sep 17 00:00:00 2001 From: Hoja Mustaffa Abdul Latheef Date: Fri, 8 Mar 2024 10:18:17 +0100 Subject: [PATCH 37/65] [TASK] Removed obselete functionalities no more needed for 12 and cleanup --- Classes/Backend/Browser/FileBrowser.php | 2 - Classes/Hooks/CachingFrameworkLoggerHook.php | 6 +- Classes/Hooks/InitializeStdWrap.php | 5 +- Classes/Task/ExecuteQueryTask.php | 12 +- Classes/XClasses/LiveSearch/LiveSearch.php | 445 ------------------ Documentation/Configuration/Index.rst | 13 - Resources/Private/Language/ExtConf.xlf | 6 - Resources/Private/Language/de.ExtConf.xlf | 5 - .../Hooks/InitializeStdWrapTest.php | 5 + composer.json | 4 +- ext_conf_template.txt | 3 - ext_localconf.php | 14 +- ext_tables.php | 5 - 13 files changed, 20 insertions(+), 505 deletions(-) delete mode 100644 Classes/XClasses/LiveSearch/LiveSearch.php delete mode 100644 ext_tables.php diff --git a/Classes/Backend/Browser/FileBrowser.php b/Classes/Backend/Browser/FileBrowser.php index 80e3f38..85a0c92 100644 --- a/Classes/Backend/Browser/FileBrowser.php +++ b/Classes/Backend/Browser/FileBrowser.php @@ -12,12 +12,10 @@ use Doctrine\DBAL\Schema\AbstractSchemaManager; use JWeiland\Jwtools2\Traits\RequestArgumentsTrait; -use Psr\Http\Message\ServerRequestInterface; use TYPO3\CMS\Backend\Controller\ElementBrowserController; use TYPO3\CMS\Backend\Utility\BackendUtility; use TYPO3\CMS\Core\Configuration\Exception\ExtensionConfigurationExtensionNotConfiguredException; use TYPO3\CMS\Core\Configuration\Exception\ExtensionConfigurationPathDoesNotExistException; -use TYPO3\CMS\Core\Configuration\ExtensionConfiguration; use TYPO3\CMS\Core\Database\ConnectionPool; use TYPO3\CMS\Core\Information\Typo3Version; use TYPO3\CMS\Core\Localization\LanguageService; diff --git a/Classes/Hooks/CachingFrameworkLoggerHook.php b/Classes/Hooks/CachingFrameworkLoggerHook.php index 1dd95fb..a37b106 100644 --- a/Classes/Hooks/CachingFrameworkLoggerHook.php +++ b/Classes/Hooks/CachingFrameworkLoggerHook.php @@ -15,7 +15,6 @@ use Psr\Log\LoggerAwareTrait; use TYPO3\CMS\Core\Cache\Frontend\FrontendInterface; use TYPO3\CMS\Core\Cache\Frontend\VariableFrontend; -use TYPO3\CMS\Core\Database\Connection; use TYPO3\CMS\Core\Database\ConnectionPool; use TYPO3\CMS\Core\Utility\GeneralUtility; @@ -27,10 +26,7 @@ class CachingFrameworkLoggerHook implements LoggerAwareInterface use LoggerAwareTrait; use RequestArgumentsTrait; - /** - * @var FrontendInterface - */ - protected $frontend; + protected FrontendInterface $frontend; /** * Analyze the data. If it matches create a new log entry diff --git a/Classes/Hooks/InitializeStdWrap.php b/Classes/Hooks/InitializeStdWrap.php index 94dbbf9..14d13b0 100644 --- a/Classes/Hooks/InitializeStdWrap.php +++ b/Classes/Hooks/InitializeStdWrap.php @@ -21,10 +21,7 @@ */ class InitializeStdWrap implements ContentObjectPostInitHookInterface { - /** - * @var ExtensionConfiguration - */ - protected $extensionConfiguration; + protected ExtensionConfiguration $extensionConfiguration; public function __construct(ExtensionConfiguration $extensionConfiguration) { diff --git a/Classes/Task/ExecuteQueryTask.php b/Classes/Task/ExecuteQueryTask.php index c95e66b..368c624 100644 --- a/Classes/Task/ExecuteQueryTask.php +++ b/Classes/Task/ExecuteQueryTask.php @@ -22,10 +22,7 @@ */ class ExecuteQueryTask extends AbstractTask { - /** - * @var string - */ - protected $sqlQuery = ''; + protected string $sqlQuery = ''; public function execute(): bool { @@ -37,14 +34,17 @@ public function execute(): bool } $sqlQueries = array_filter($sqlQueries); - if (empty($sqlQueries)) { $this->addMessage('No queries for execution found'); return false; } foreach ($sqlQueries as $sqlQuery) { - $connection->query($sqlQuery)->execute(); + // check $sqlQuery ends with a semi-colon otherwise add it + if (substr($sqlQuery, -1) !== ';') { + $sqlQuery .= ';'; + } + $connection->executeStatement($sqlQuery); } $this->addMessage( diff --git a/Classes/XClasses/LiveSearch/LiveSearch.php b/Classes/XClasses/LiveSearch/LiveSearch.php deleted file mode 100644 index 3952450..0000000 --- a/Classes/XClasses/LiveSearch/LiveSearch.php +++ /dev/null @@ -1,445 +0,0 @@ -userPermissions = $this->getBackendUser()->getPagePermsClause(Permission::PAGE_SHOW); - $this->queryParser = GeneralUtility::makeInstance(QueryParser::class); - } - - /** - * Find records from database based on the given $searchQuery. - */ - public function find(string $searchQuery): array - { - $recordArray = []; - $pageIdList = $this->getPageIdList(); - if ($this->queryParser->isValidCommand($searchQuery)) { - $this->setQueryString($this->queryParser->getSearchQueryValue($searchQuery)); - $tableName = $this->queryParser->getTableNameFromCommand($searchQuery); - if ($tableName) { - $recordArray[] = $this->findByTable($tableName, $pageIdList, $this->startCount, $this->limitCount); - } - } else { - $this->setQueryString($searchQuery); - $recordArray = $this->findByGlobalTableList($pageIdList); - } - return $recordArray; - } - - /** - * List of available page uids for user, empty array for admin users. - */ - protected function getPageIdList(): array - { - $pageList = []; - if ($this->getBackendUser()->isAdmin()) { - return $pageList; - } - $mounts = $this->getBackendUser()->returnWebmounts(); - foreach ($mounts as $pageId) { - $pageList[] = $this->getAvailablePageIds($pageId, self::RECURSIVE_PAGE_LEVEL); - } - return array_unique(explode(',', implode(',', $pageList))); - } - - /** - * Find records from all registered TCA table & column values. - * - * @param array $pageIdList Comma separated list of page IDs - * @return array Records found in the database matching the searchQuery - */ - protected function findByGlobalTableList($pageIdList) - { - $limit = $this->limitCount; - $getRecordArray = []; - foreach ($GLOBALS['TCA'] as $tableName => $value) { - // if no access for the table (read or write) or table is hidden, skip this table - if ( - (isset($value['ctrl']['hideTable']) && $value['ctrl']['hideTable']) - || - ( - !$this->getBackendUser()->check('tables_select', $tableName) && - !$this->getBackendUser()->check('tables_modify', $tableName) - ) - ) { - continue; - } - $recordArray = $this->findByTable($tableName, $pageIdList, 0, $limit); - $recordCount = count($recordArray); - if ($recordCount) { - $limit -= $recordCount; - $getRecordArray[] = $recordArray; - if ($limit <= 0) { - break; - } - } - } - return $getRecordArray; - } - - /** - * Find records by given table name. - * - * @param string $tableName Database table name - * @param array $pageIdList Comma separated list of page IDs - * @param int $firstResult - * @param int $maxResults - * @return array Records found in the database matching the searchQuery - * @see getRecordArray() - * @see makeQuerySearchByTable() - * @see extractSearchableFieldsFromTable() - */ - protected function findByTable($tableName, $pageIdList, $firstResult, $maxResults) - { - $fieldsToSearchWithin = $this->extractSearchableFieldsFromTable($tableName); - $getRecordArray = []; - if (!empty($fieldsToSearchWithin)) { - $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class) - ->getQueryBuilderForTable($tableName); - $queryBuilder->getRestrictions() - ->removeByType(HiddenRestriction::class) - ->removeByType(StartTimeRestriction::class) - ->removeByType(EndTimeRestriction::class); - - $queryBuilder - ->select('*') - ->from($tableName) - ->where( - $this->makeQuerySearchByTable($queryBuilder, $tableName, $fieldsToSearchWithin) - ) - ->setFirstResult($firstResult) - ->setMaxResults($maxResults); - - if ($pageIdList !== []) { - $queryBuilder->andWhere( - $queryBuilder->expr()->in( - 'pid', - $queryBuilder->createNamedParameter($pageIdList, Connection::PARAM_INT_ARRAY) - ) - ); - } - - if ($tableName === 'pages' && $this->userPermissions) { - $queryBuilder->andWhere($this->userPermissions); - } - - $queryBuilder->addOrderBy('uid', 'DESC'); - - $getRecordArray = $this->getRecordArray($queryBuilder, $tableName); - } - - return $getRecordArray; - } - - /** - * Process the Database operation to get the search result. - * - * @param QueryBuilder $queryBuilder Database table name - * @param string $tableName - * @return array - * @see getTitleFromCurrentRow() - * @see getEditLink() - */ - protected function getRecordArray($queryBuilder, $tableName) - { - $collect = []; - $result = $queryBuilder->execute(); - $iconFactory = GeneralUtility::makeInstance(IconFactory::class); - while ($row = $result->fetchAssociative()) { - BackendUtility::workspaceOL($tableName, $row); - if (!is_array($row)) { - continue; - } - $onlineUid = ($row['t3ver_oid'] ?? false) ?: $row['uid']; - $title = 'id=' . $row['uid'] . ', pid=' . $row['pid']; - $collect[$onlineUid] = [ - 'id' => $tableName . ':' . $row['uid'], - 'pageId' => $tableName === 'pages' ? $row['uid'] : $row['pid'], - 'typeLabel' => $this->getTitleOfCurrentRecordType($tableName), - 'iconHTML' => '' . $iconFactory->getIconForRecord($tableName, $row, Icon::SIZE_SMALL)->render() . '', - 'title' => BackendUtility::getRecordTitle($tableName, $row), - 'editLink' => $this->getEditLink($tableName, $row), - ]; - } - return $collect; - } - - /** - * Build a backend edit link based on given record. - * - * @param string $tableName Record table name - * @param array $row Current record row from database. - * @return string Link to open an edit window for record. - * @see \TYPO3\CMS\Backend\Utility\BackendUtility::readPageAccess() - */ - protected function getEditLink($tableName, $row) - { - $backendUser = $this->getBackendUser(); - $editLink = ''; - if ($tableName === 'pages') { - $permsEdit = $backendUser->calcPerms(BackendUtility::getRecord('pages', $row['uid']) ?? []) & Permission::PAGE_EDIT; - } else { - $permsEdit = $backendUser->calcPerms(BackendUtility::readPageAccess($row['pid'], $this->userPermissions) ?: []) & Permission::CONTENT_EDIT; - } - // "Edit" link - Only with proper edit permissions - if (!($GLOBALS['TCA'][$tableName]['ctrl']['readOnly'] ?? false) - && ( - $backendUser->isAdmin() - || ( - $permsEdit - && !($GLOBALS['TCA'][$tableName]['ctrl']['adminOnly'] ?? false) - && $backendUser->check('tables_modify', $tableName) - && $backendUser->recordEditAccessInternals($tableName, $row) - ) - ) - ) { - $uriBuilder = GeneralUtility::makeInstance(UriBuilder::class); - $returnUrl = (string)$uriBuilder->buildUriFromRoute('web_list', ['id' => $row['pid']]); - $editLink = (string)$uriBuilder->buildUriFromRoute('record_edit', [ - 'edit[' . $tableName . '][' . $row['uid'] . ']' => 'edit', - 'returnUrl' => $returnUrl - ]); - } - return $editLink; - } - - /** - * Retrieve the record name - * - * @param string $tableName Record table name - * @return string - */ - protected function getTitleOfCurrentRecordType($tableName) - { - return $this->getLanguageService()->sL($GLOBALS['TCA'][$tableName]['ctrl']['title']); - } - - /** - * Build the MySql where clause by table. - * - * @param QueryBuilder $queryBuilder - * @param string $tableName Record table name - * @param array $fieldsToSearchWithin User right based visible fields where we can search within. - * @return CompositeExpression - */ - protected function makeQuerySearchByTable(QueryBuilder $queryBuilder, $tableName, array $fieldsToSearchWithin) - { - $constraints = []; - - // If the search string is a simple integer, assemble an equality comparison - if (MathUtility::canBeInterpretedAsInteger($this->queryString)) { - // SF: We have reduced this query to just UID column. - // So, if you search for #page:11 you will get just the page with UID 11 and not - // some pages where "11" is somewhere in a timestamp or whatever - $constraints[] = $queryBuilder->expr()->eq( - 'uid', - $queryBuilder->createNamedParameter($this->queryString, Connection::PARAM_INT) - ); - } else { - $like = '%' . $queryBuilder->escapeLikeWildcards($this->queryString) . '%'; - foreach ($fieldsToSearchWithin as $fieldName) { - if (!isset($GLOBALS['TCA'][$tableName]['columns'][$fieldName])) { - continue; - } - $fieldConfig = $GLOBALS['TCA'][$tableName]['columns'][$fieldName]['config'] ?? []; - $fieldType = $fieldConfig['type'] ?? ''; - $evalRules = $fieldConfig['eval'] ?? ''; - - // Check whether search should be case-sensitive or not - $searchConstraint = $queryBuilder->expr()->and( - $queryBuilder->expr()->comparison( - 'LOWER(' . $queryBuilder->quoteIdentifier($fieldName) . ')', - 'LIKE', - $queryBuilder->createNamedParameter(mb_strtolower($like)) - ) - ); - - if (is_array($fieldConfig['search'] ?? false)) { - if (in_array('case', $fieldConfig['search'], true)) { - // Replace case insensitive default constraint - $searchConstraint = $queryBuilder->expr()->and( - $queryBuilder->expr()->like( - $fieldName, - $queryBuilder->createNamedParameter($like) - ) - ); - } - // Apply additional condition, if any - if ($fieldConfig['search']['andWhere'] ?? false) { - if (GeneralUtility::makeInstance(Features::class)->isFeatureEnabled('runtimeDbQuotingOfTcaConfiguration')) { - $searchConstraint = $searchConstraint->with( - QueryHelper::stripLogicalOperatorPrefix(QueryHelper::quoteDatabaseIdentifiers($queryBuilder->getConnection(), $fieldConfig['search']['andWhere'])) - ); - } else { - $searchConstraint = $searchConstraint->with( - QueryHelper::stripLogicalOperatorPrefix($fieldConfig['search']['andWhere']) - ); - } - } - } - // Assemble the search condition only if the field makes sense to be searched - if ($fieldType === 'text' - || $fieldType === 'flex' - || $fieldType === 'slug' - || ($fieldType === 'input' && (!$evalRules || !preg_match('/\b(?:date|time|int)\b/', $evalRules))) - ) { - if ($searchConstraint->count() !== 0) { - $constraints[] = $searchConstraint; - } - } - } - } - - // If no search field conditions have been build ensure no results are returned - if (empty($constraints)) { - return '0=1'; - } - - return $queryBuilder->expr()->or(...$constraints); - } - - /** - * Get all fields from given table where we can search for. - * - * @param string $tableName Name of the table for which to get the searchable fields - * @return array - */ - protected function extractSearchableFieldsFromTable($tableName) - { - // Get the list of fields to search in from the TCA, if any - if (isset($GLOBALS['TCA'][$tableName]['ctrl']['searchFields'])) { - $fieldListArray = GeneralUtility::trimExplode(',', $GLOBALS['TCA'][$tableName]['ctrl']['searchFields'], true); - } else { - $fieldListArray = []; - } - // Add special fields - if ($this->getBackendUser()->isAdmin()) { - $fieldListArray[] = 'uid'; - $fieldListArray[] = 'pid'; - } - return $fieldListArray; - } - - /** - * Setter for limit value. - * - * @param int $limitCount - */ - public function setLimitCount($limitCount) - { - $limit = MathUtility::convertToPositiveInteger($limitCount); - if ($limit > 0) { - $this->limitCount = $limit; - } - } - - /** - * Setter for start count value. - * - * @param int $startCount - */ - public function setStartCount($startCount) - { - $this->startCount = MathUtility::convertToPositiveInteger($startCount); - } - - /** - * Setter for the search query string. - * - * @param string $queryString - */ - public function setQueryString($queryString) - { - $this->queryString = $queryString; - } - - /** - * Creates an instance of \TYPO3\CMS\Backend\Tree\View\PageTreeView which will select a - * page tree to $depth and return the object. In that object we will find the ids of the tree. - * - * @param int $id Page id. - * @param int $depth Depth to go down. - * @return string Comma separated list of uids - */ - protected function getAvailablePageIds($id, $depth) - { - $tree = GeneralUtility::makeInstance(PageTreeView::class); - $tree->init('AND ' . $this->userPermissions); - $tree->makeHTML = 0; - $tree->fieldArray = ['uid', 'php_tree_stop']; - if ($depth) { - $tree->getTree($id, $depth); - } - $tree->ids[] = $id; - // add workspace pid - workspace permissions are taken into account by where clause later - $tree->ids[] = -1; - return implode(',', $tree->ids); - } - - protected function getBackendUser(): BackendUserAuthentication - { - return $GLOBALS['BE_USER']; - } - - /** - * @return LanguageService|null - */ - protected function getLanguageService(): ?LanguageService - { - return $GLOBALS['LANG'] ?? null; - } -} diff --git a/Documentation/Configuration/Index.rst b/Documentation/Configuration/Index.rst index eaa014d..136ea54 100644 --- a/Documentation/Configuration/Index.rst +++ b/Documentation/Configuration/Index.rst @@ -202,18 +202,6 @@ case sensitive strings. For more complex search activate checkbox for regular ex PHP:preg_match search internally. You don't need to prepend/append a delimiter. It uses "/" internally and escaped values for you automatically. - -.. _enableLiveSearchPerformanceForAdmins: - -enableLiveSearchPerformanceForAdmins ------------------------------------- - -For admins LiveSearch is very slow (TYPO3 < 11). That's because LiveSearch builds up a complete list of -ALL available page UIDs. That's not neccessary as admins always have access to all pages. - -Activate that checkbox to get more performance while searching with LiveSearch as admin. - - .. _enableReportProvider: enableReportProvider @@ -227,7 +215,6 @@ Currently following information will be shown: * List of all (not only security related) updatable extensions incl. version number. * ... - .. _sendUpdatableExtensionsWithSeverity: sendUpdatableExtensionsWithSeverity diff --git a/Resources/Private/Language/ExtConf.xlf b/Resources/Private/Language/ExtConf.xlf index 70f9018..a53e8c0 100644 --- a/Resources/Private/Language/ExtConf.xlf +++ b/Resources/Private/Language/ExtConf.xlf @@ -60,12 +60,6 @@ var/log/. - - Enable LiveSearch performance: Overwrite LiveSearch class to get more performance for searchresults as - admin. - - - Enable provider for EXT reports: If EXT:reports is installed it will show additional information about updatable extensions. diff --git a/Resources/Private/Language/de.ExtConf.xlf b/Resources/Private/Language/de.ExtConf.xlf index 8252ade..a22f22e 100644 --- a/Resources/Private/Language/de.ExtConf.xlf +++ b/Resources/Private/Language/de.ExtConf.xlf @@ -47,11 +47,6 @@ Enable Caching Framework Logger: Hooks into the TYPO3 caching framework and parses all data using expression records to be created on the root page (PID: 0). If these match, a log entry is created in var/log/. Caching Framework Logger aktivieren: Klinkt sich in das TYPO3 Caching Framework ein und analysiert alle Daten anhand von Expression Records, die auf der Root-Seite (PID: 0) zu erstellen sind. Wenn diese übereinstimmen, wird ein Protokolleintrag in var/log/ erzeugt - - Enable LiveSearch performance: Overwrite LiveSearch class to get more performance for searchresults as admin. - Aktivieren Sie LiveSearch Performance: Überschreiben Sie die LiveSearch-Klasse, um mehr Leistung für Suchergebnisse als Admin zu erhalten. - - Enable provider for EXT reports: If EXT:reports is installed it will show additional information about updatable extensions. Aktiviere Status-Provider für EXT reports: Wenn die EXT:reports installiert und aktiviert ist werden zusätzlich Informationen über updatefähige Extensions angezeigt. diff --git a/Tests/Functional/Hooks/InitializeStdWrapTest.php b/Tests/Functional/Hooks/InitializeStdWrapTest.php index fd7578b..c014a82 100644 --- a/Tests/Functional/Hooks/InitializeStdWrapTest.php +++ b/Tests/Functional/Hooks/InitializeStdWrapTest.php @@ -13,7 +13,9 @@ use JWeiland\Jwtools2\Hooks\InitializeStdWrap; use PHPUnit\Framework\MockObject\MockObject; use TYPO3\CMS\Core\Configuration\ExtensionConfiguration; +use TYPO3\CMS\Core\Utility\GeneralUtility; use TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer; +use TYPO3\CMS\Scheduler\Domain\Repository\SchedulerTaskRepository; use TYPO3\TestingFramework\Core\Functional\FunctionalTestCase; /** @@ -33,6 +35,9 @@ protected function setUp(): void { parent::setUp(); + $schedulerTaskRepository = GeneralUtility::makeInstance(SchedulerTaskRepository::class); + GeneralUtility::addInstance(SchedulerTaskRepository::class, $schedulerTaskRepository); + $this->extensionConfigurationMock = $this->getAccessibleMock(ExtensionConfiguration::class); $this->subject = new InitializeStdWrap( $this->extensionConfigurationMock diff --git a/composer.json b/composer.json index bd44cb9..5021331 100644 --- a/composer.json +++ b/composer.json @@ -24,7 +24,9 @@ }, "require": { "typo3/cms-core": "^12.4.9", - "typo3/cms-scheduler": "^v12.4.9" + "typo3/cms-scheduler": "^v12.4.9", + "typo3/cms-filelist": "^v12.4.9", + "typo3/cms-filemetadata": "^v12.4.9" }, "require-dev": { "friendsofphp/php-cs-fixer": "^3.14", diff --git a/ext_conf_template.txt b/ext_conf_template.txt index ea80874..5821946 100644 --- a/ext_conf_template.txt +++ b/ext_conf_template.txt @@ -20,9 +20,6 @@ enableSqlQueryTask = 0 enableContextMenuToUpdateFileMetadata = 0 # cat=typo3; type=boolean; label=LLL:EXT:jwtools2/Resources/Private/Language/ExtConf.xlf:enableCachingFrameworkLogger enableCachingFrameworkLogger = 0 -# cat=typo3; type=boolean; label=LLL:EXT:jwtools2/Resources/Private/Language/ExtConf.xlf:enableLiveSearchPerformanceForAdmins -enableLiveSearchPerformanceForAdmins = 0 - # cat=reports; type=boolean; label=LLL:EXT:jwtools2/Resources/Private/Language/ExtConf.xlf:enableReportProvider enableReportProvider = 0 # cat=reports; type=options[Info=info,Warning=warning]; label=LLL:EXT:jwtools2/Resources/Private/Language/ExtConf.xlf:sendUpdatableExtensionsWithSeverity diff --git a/ext_localconf.php b/ext_localconf.php index ff6479b..cd5a659 100644 --- a/ext_localconf.php +++ b/ext_localconf.php @@ -49,12 +49,15 @@ ); } + // @todo: Removed this Hook in TYPO3 12 if ( ($jwToolsConfiguration['typo3RequiredColumnsForFiles'] ?? false) || ($jwToolsConfiguration['typo3UploadFieldsInTopOfEB'] ?? false) ) { - $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['typo3/browse_links.php']['browserRendering']['jwtools2_file'] + $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['ElementBrowsers']['jwtools2_file'] = \JWeiland\Jwtools2\Backend\Browser\FileBrowser::class; + //$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['typo3/browse_links.php']['browserRendering']['jwtools2_file'] + // = \JWeiland\Jwtools2\Backend\Browser\FileBrowser::class; } if ($jwToolsConfiguration['typo3UploadFieldsInTopOfEB'] ?? false) { @@ -69,15 +72,6 @@ = \JWeiland\Jwtools2\Hooks\ModifyElementInformationHook::class; } - // Feature was implemented in TYPO3 11.5. No need to XClass LiveSearch. - // Remove that feature while removing TYPO3 10 compatibility. - if ( - ($jwToolsConfiguration['enableLiveSearchPerformanceForAdmins'] ?? false) - && version_compare($typo3Version->getBranch(), '11.5', '<') - ) { - $GLOBALS['TYPO3_CONF_VARS']['SYS']['Objects'][\TYPO3\CMS\Backend\Search\LiveSearch\LiveSearch::class]['className'] = \JWeiland\Jwtools2\XClasses\LiveSearch\LiveSearch::class; - } - if ($jwToolsConfiguration['typo3ExcludeVideoFilesFromFalFilter'] ?? false) { // Exclude .youtube and .vimeo from hidden files in filelist $GLOBALS['TYPO3_CONF_VARS']['SYS']['fal']['defaultFilterCallbacks'] = [ diff --git a/ext_tables.php b/ext_tables.php deleted file mode 100644 index 01be305..0000000 --- a/ext_tables.php +++ /dev/null @@ -1,5 +0,0 @@ - Date: Fri, 8 Mar 2024 12:04:40 +0100 Subject: [PATCH 38/65] [TASK] Refactored ModifyElementInformationHook --- .../Hooks/ModifyElementInformationHook.php | 114 +++--------------- 1 file changed, 18 insertions(+), 96 deletions(-) diff --git a/Classes/Hooks/ModifyElementInformationHook.php b/Classes/Hooks/ModifyElementInformationHook.php index 2b46865..fecdaa3 100644 --- a/Classes/Hooks/ModifyElementInformationHook.php +++ b/Classes/Hooks/ModifyElementInformationHook.php @@ -49,73 +49,39 @@ */ class ModifyElementInformationHook { - /** - * Record table name - * - * @var string - */ - protected $table; + protected string $table; - /** - * Record uid - * - * @var int - */ - protected $uid; + protected int $uid; - /** - * @var string - */ - protected $permsClause; + protected string $permsClause; - /** - * @var bool - */ - protected $access = false; + protected bool $access = false; /** * Which type of element: * - "file" * - "db" - * - * @var string */ - protected $type = ''; + protected string $type = ''; /** * For type "db": Set to page record of the parent page of the item set * (if type="db") - * - * @var array */ - protected $pageInfo; + protected array $pageInfo; /** * Database records identified by table/uid - * - * @var array */ - protected $row; + protected array $row; - /** - * @var File|null - */ - protected $fileObject; + protected ?File $fileObject; - /** - * @var Folder - */ - protected $folderObject; + protected ?Folder $folderObject; - /** - * @var IconFactory - */ - protected $iconFactory; + protected IconFactory $iconFactory; - /** - * @var UriBuilder - */ - protected $uriBuilder; + protected UriBuilder $uriBuilder; public function __construct() { @@ -137,15 +103,13 @@ public function render(string $type, ElementInformationController $elementInform /** * Determines if table/uid point to database record or file and * if user has access to view information - * - * @param ServerRequestInterface $request */ protected function init(ServerRequestInterface $request): void { $queryParams = $request->getQueryParams(); $this->table = $queryParams['table'] ?? null; - $this->uid = $queryParams['uid'] ?? null; + $this->uid = (int)$queryParams['uid'] ?? null; $this->permsClause = $this->getBackendUser()->getPagePermsClause(Permission::PAGE_SHOW); @@ -190,13 +154,13 @@ protected function initDatabaseRecord(): void protected function initFileOrFolderRecord(): void { $fileOrFolderObject = GeneralUtility::makeInstance(ResourceFactory::class)->retrieveFileOrFolderObject($this->uid); - if ($fileOrFolderObject instanceof Folder) { $this->folderObject = $fileOrFolderObject; $this->access = $this->folderObject->checkActionPermission('read'); $this->type = 'folder'; } elseif ($fileOrFolderObject instanceof File) { $this->fileObject = $fileOrFolderObject; + $this->folderObject = null; $this->access = $this->fileObject->checkActionPermission('read'); $this->type = 'file'; $this->table = 'sys_file'; @@ -237,8 +201,6 @@ protected function main(ServerRequestInterface $request): string /** * Get page title with icon, table title and record title - * - * @return array */ protected function getPageTitle(): array { @@ -262,8 +224,6 @@ protected function getPageTitle(): array /** * Get preview for current record - * - * @return array */ protected function getPreview(ServerRequestInterface $request): array { @@ -316,8 +276,6 @@ protected function getPreview(ServerRequestInterface $request): array /** * Get property array for html table - * - * @return array */ protected function getPropertiesForTable(): array { @@ -435,10 +393,6 @@ protected function getPropertiesForTable(): array /** * Get the list of fields that should be shown for the given table - * - * @param string $table - * @param int $uid - * @return array */ protected function getFieldList(string $table, int $uid): array { @@ -470,8 +424,6 @@ protected function getFieldList(string $table, int $uid): array /** * Get the extra fields (uid, timestamps, creator) for the table - * - * @return array */ protected function getExtraFields(): array { @@ -531,9 +483,6 @@ protected function getExtraFields(): array /** * Get references section (references from and references to current record) - * - * @param ServerRequestInterface $request - * @return array */ protected function getReferences(ServerRequestInterface $request): array { @@ -557,12 +506,8 @@ protected function getReferences(ServerRequestInterface $request): array /** * Get field name for specified table/column name - * - * @param string $tableName Table name - * @param string $fieldName Column name - * @return string label */ - protected function getLabelForTableColumn($tableName, $fieldName): string + protected function getLabelForTableColumn(string $tableName, string $fieldName): string { if (($GLOBALS['TCA'][$tableName]['columns'][$fieldName]['label'] ?? null) !== null) { $field = $this->getLanguageService()->sL($GLOBALS['TCA'][$tableName]['columns'][$fieldName]['label']); @@ -577,14 +522,9 @@ protected function getLabelForTableColumn($tableName, $fieldName): string /** * Returns the record actions - * - * @param string $table - * @param int $uid - * @param ServerRequestInterface $request - * @return array * @throws RouteNotFoundException */ - protected function getRecordActions($table, $uid, ServerRequestInterface $request): array + protected function getRecordActions(string $table, int $uid, ServerRequestInterface $request): array { if ($table === '' || $uid < 0) { return []; @@ -622,14 +562,9 @@ protected function getRecordActions($table, $uid, ServerRequestInterface $reques /** * Make reference display - * - * @param string $table Table name - * @param int|File $ref Filename or uid - * @param ServerRequestInterface $request - * @return array * @throws RouteNotFoundException */ - protected function makeRef($table, $ref, ServerRequestInterface $request): array + protected function makeRef(string $table, File|int $ref, ServerRequestInterface $request): array { $refLines = []; $lang = $this->getLanguageService(); @@ -722,13 +657,8 @@ protected function makeRef($table, $ref, ServerRequestInterface $request): array /** * Make reference display (what this elements points to) - * - * @param string $table Table name - * @param int $ref Filename or uid - * @param ServerRequestInterface $request - * @return array */ - protected function makeRefFrom($table, $ref, ServerRequestInterface $request): array + protected function makeRefFrom(string $table, int $ref, ServerRequestInterface $request): array { $refFromLines = []; $lang = $this->getLanguageService(); @@ -801,9 +731,6 @@ protected function makeRefFrom($table, $ref, ServerRequestInterface $request): a /** * Convert FAL file reference (sys_file_reference) to reference index (sys_refindex) table format - * - * @param array $referenceRecord - * @return array */ protected function transformFileReferenceToRecordReference(array $referenceRecord): array { @@ -832,16 +759,11 @@ protected function transformFileReferenceToRecordReference(array $referenceRecor ]; } - /** - * @param string $tableName Name of the table - * @param array $record Record to be checked (ensure pid is resolved for workspaces) - * @return bool - */ protected function canAccessPage(string $tableName, array $record): bool { $recordPid = (int)($tableName === 'pages' ? $record['uid'] : $record['pid']); return $this->getBackendUser()->isInWebMount($tableName === 'pages' ? $record : $record['pid']) - || $recordPid === 0 && !empty($GLOBALS['TCA'][$tableName]['ctrl']['security']['ignoreRootLevelRestriction']); + || ($recordPid === 0 && !empty($GLOBALS['TCA'][$tableName]['ctrl']['security']['ignoreRootLevelRestriction'])); } /** From 7a441c90b3731d4ea3a8367c95e51d57c82afe4b Mon Sep 17 00:00:00 2001 From: Hoja Mustaffa Abdul Latheef Date: Wed, 13 Mar 2024 15:14:35 +0100 Subject: [PATCH 39/65] Removed unwanted use of Connection class --- Classes/EventListener/ReduceCategoryTreeToPageTree.php | 1 - 1 file changed, 1 deletion(-) diff --git a/Classes/EventListener/ReduceCategoryTreeToPageTree.php b/Classes/EventListener/ReduceCategoryTreeToPageTree.php index 0c5051c..61205fa 100644 --- a/Classes/EventListener/ReduceCategoryTreeToPageTree.php +++ b/Classes/EventListener/ReduceCategoryTreeToPageTree.php @@ -21,7 +21,6 @@ use TYPO3\CMS\Core\Configuration\Exception\ExtensionConfigurationExtensionNotConfiguredException; use TYPO3\CMS\Core\Configuration\Exception\ExtensionConfigurationPathDoesNotExistException; use TYPO3\CMS\Core\Configuration\ExtensionConfiguration; -use TYPO3\CMS\Core\Database\Connection; use TYPO3\CMS\Core\Database\ConnectionPool; use TYPO3\CMS\Core\Http\ApplicationType; use TYPO3\CMS\Core\Tree\Event\ModifyTreeDataEvent; From 374a8adfbf9c371a7db5b9f548ab211659736495 Mon Sep 17 00:00:00 2001 From: Hoja Mustaffa Abdul Latheef Date: Wed, 13 Mar 2024 15:15:24 +0100 Subject: [PATCH 40/65] Post Processing issue occures if the colPos 0 is handled --- Classes/Hooks/InitializeStdWrap.php | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Classes/Hooks/InitializeStdWrap.php b/Classes/Hooks/InitializeStdWrap.php index 14d13b0..604530b 100644 --- a/Classes/Hooks/InitializeStdWrap.php +++ b/Classes/Hooks/InitializeStdWrap.php @@ -41,7 +41,9 @@ public function postProcessContentObjectInitialization(ContentObjectRenderer &$p && ($this->getConfiguration()['typo3TransferTypoScriptCurrent'] ?? false) ) { // Set current to value of parent current - $parentObject->data[$parentObject->currentValKey] = $parentObject->parentRecord['data'][$parentObject->currentValKey]; + if (isset($parentObject->data['colPos']) && $parentObject->data['colPos'] !== 0) { + $parentObject->data[$parentObject->currentValKey] = $parentObject->parentRecord['data'][$parentObject->currentValKey]; + } } } From e58db3b46d700fd7068f9b470b38be9088c0c865 Mon Sep 17 00:00:00 2001 From: Hoja Mustaffa Abdul Latheef Date: Thu, 14 Mar 2024 14:58:37 +0100 Subject: [PATCH 41/65] Removed deprecated files --- .../Recordlist/Templates/V10/File.html | 35 ------- .../Recordlist/Templates/V10/Folder.html | 34 ------- .../Public/JavaScript/clear-full-index.js | 91 +++++++++++++++++++ 3 files changed, 91 insertions(+), 69 deletions(-) delete mode 100644 Resources/Private/Extensions/Recordlist/Templates/V10/File.html delete mode 100644 Resources/Private/Extensions/Recordlist/Templates/V10/Folder.html create mode 100644 Resources/Public/JavaScript/clear-full-index.js diff --git a/Resources/Private/Extensions/Recordlist/Templates/V10/File.html b/Resources/Private/Extensions/Recordlist/Templates/V10/File.html deleted file mode 100644 index 47a8220..0000000 --- a/Resources/Private/Extensions/Recordlist/Templates/V10/File.html +++ /dev/null @@ -1,35 +0,0 @@ -
-
-
- {tree -> f:format.raw()} -
-
-
-
- {uploadFileForm -> f:format.raw()} - {createFolderForm -> f:format.raw()} - -

- - {selectedFolderIcon -> f:format.raw()} {selectedFolderTitle} - - - - -
-
-
-
diff --git a/Resources/Private/Extensions/Recordlist/Templates/V10/Folder.html b/Resources/Private/Extensions/Recordlist/Templates/V10/Folder.html deleted file mode 100644 index c3221ef..0000000 --- a/Resources/Private/Extensions/Recordlist/Templates/V10/Folder.html +++ /dev/null @@ -1,34 +0,0 @@ -
-
-
- {tree -> f:format.raw()} -
-
-
-
- {createFolderForm -> f:format.raw()} - -

- - {selectedFolderIcon -> f:format.raw()} {selectedFolderTitle} - - - - -
-
-
-
diff --git a/Resources/Public/JavaScript/clear-full-index.js b/Resources/Public/JavaScript/clear-full-index.js new file mode 100644 index 0000000..38684ec --- /dev/null +++ b/Resources/Public/JavaScript/clear-full-index.js @@ -0,0 +1,91 @@ +/* + * This file is part of the jwtools2 project. + * + * It is free software; you can redistribute it and/or modify it under + * the terms of the GNU General Public License, either version 2 + * of the License, or any later version. + * + * For the full copyright and license information, please read the + * LICENSE.txt file that was distributed with this source code. + * + * The TYPO3 project - inspiring people to share! + */ +import { getIcon } from 'TYPO3/CMS/Backend/Icons'; +import { success as showSuccessNotification } from 'TYPO3/CMS/Backend/Notification'; + +class ClearIndex { + constructor() { + this.clearIndexAction = this.clearIndexAction.bind(this); + this.clearIndexByRows = this.clearIndexByRows.bind(this); + this.clearIndexByRow = this.clearIndexByRow.bind(this); + this.executeAjaxRequest = this.executeAjaxRequest.bind(this); + this.displaySuccess = this.displaySuccess.bind(this); + this.$button = document.getElementById("clearFullIndex"); + this.$button.addEventListener("click", this.clearIndexAction); + } + + clearIndexAction() { + const activeRows = document.querySelectorAll('table>tbody>tr'); + + if (activeRows.length > 0) { + this.clearIndexByRows(activeRows); + } + } + + clearIndexByRows(rows) { + if (rows) { + rows.forEach(row => { + const rootPageUid = row.querySelector(".rootPageUid").dataset.rootPageUid; + const configurationNames = Array.from(document.querySelectorAll("input.configurationNames:checked")).map(input => input.value); + const clear = Array.from(document.querySelectorAll("input.clear:checked")).map(input => input.value); + + row.querySelector("div.status").style.display = 'block'; + this.clearIndexByRow({ rootPageUid, configurationNames, clear }, row); + }); + } + } + + clearIndexByRow(data, row) { + this.executeAjaxRequest(TYPO3.settings.ajaxUrls['jwtools2_clearIndex'], data) + .then(response => { + if (response.success) { + getIcon("status-status-permission-granted", "small") + .then(ok => { + const iconSpan = row.querySelector('span.icon'); + if (iconSpan) { + iconSpan.parentNode.replaceChild(ok, iconSpan); + } + }) + .catch(error => { + console.error('Error getting icon:', error); + }); + } else { + alert('Error'); + } + }) + .catch(error => { + console.error('Error:', error); + }); + } + + executeAjaxRequest(uri, data) { + const newData = { tx_jwtools2: data }; + return fetch(uri, { + method: 'POST', + cache: 'no-cache', + body: JSON.stringify(newData), + headers: { + 'Content-Type': 'application/json' + } + }) + .then(response => response.json()); + } + + displaySuccess(label) { + if (typeof label === 'string' && label !== '') { + showSuccessNotification('Success', label); + } + } +} + +new ClearIndex(); From 69b8f7496d8966f4bd26f398897ad39d79259081 Mon Sep 17 00:00:00 2001 From: Hoja Mustaffa Abdul Latheef Date: Thu, 14 Mar 2024 14:59:25 +0100 Subject: [PATCH 42/65] Moved functionalities related to Link and Folder LinkHandler from Hooks to EventListener --- .../EventListener/ModifyLinkEventListener.php | 31 +++++++++++++++++++ 1 file changed, 31 insertions(+) create mode 100644 Classes/EventListener/ModifyLinkEventListener.php diff --git a/Classes/EventListener/ModifyLinkEventListener.php b/Classes/EventListener/ModifyLinkEventListener.php new file mode 100644 index 0000000..f675045 --- /dev/null +++ b/Classes/EventListener/ModifyLinkEventListener.php @@ -0,0 +1,31 @@ +overrideFileLinkHandler($event); + } + + private function overrideFileLinkHandler($event): void + { + $fileHandler = $event->getLinkHandler('file.'); + if ($fileHandler['handler'] === 'TYPO3\CMS\Filelist\LinkHandler\FileLinkHandler') { + $fileHandler['handler'] = FileLinkHandler::class; + } + $event->setLinkHandler('file.', $fileHandler); + } +} From 6be2471557a9367da091f75667df317cae912180 Mon Sep 17 00:00:00 2001 From: Hoja Mustaffa Abdul Latheef Date: Thu, 14 Mar 2024 15:01:03 +0100 Subject: [PATCH 43/65] Implementation for LinkHandlers done in EventListener --- Classes/LinkHandler/FileLinkHandler.php | 36 ++++++++--------------- Classes/LinkHandler/FolderLinkHandler.php | 13 ++++---- 2 files changed, 17 insertions(+), 32 deletions(-) diff --git a/Classes/LinkHandler/FileLinkHandler.php b/Classes/LinkHandler/FileLinkHandler.php index 1ceb1e3..3499dfb 100644 --- a/Classes/LinkHandler/FileLinkHandler.php +++ b/Classes/LinkHandler/FileLinkHandler.php @@ -10,21 +10,20 @@ namespace JWeiland\Jwtools2\LinkHandler; +use Psr\Http\Message\ServerRequestInterface; use TYPO3\CMS\Backend\Controller\AbstractLinkBrowserController; use TYPO3\CMS\Core\Information\Typo3Version; use TYPO3\CMS\Core\Utility\GeneralUtility; +use TYPO3\CMS\Filelist\LinkHandler\AbstractResourceLinkHandler; use TYPO3\CMS\Fluid\View\StandaloneView; -use TYPO3Fluid\Fluid\View\ViewInterface; +use TYPO3\CMS\Core\View\ViewInterface; /** * This file LinkHandler overwrites the LinkHandler of TYPO3 and moves upload and create folder fields to top */ -class FileLinkHandler extends \TYPO3\CMS\Backend\LinkHandler\FileLinkHandler +class FileLinkHandler extends \TYPO3\CMS\Filelist\LinkHandler\FileLinkHandler { - /** - * @var StandaloneView|ViewInterface - */ - protected $view; + protected ViewInterface $view; public function initialize( AbstractLinkBrowserController $linkBrowser, @@ -32,37 +31,26 @@ public function initialize( array $configuration ): void { parent::initialize($linkBrowser, $identifier, $configuration); - - $this->addTemplatePath($this->view); } /** * The parent::setView() method was implemented with TYPO3 11.2. * For earlier TYPO3 version we still need the approach from above */ - public function setView(ViewInterface $view): void + public function setView(ViewInterface $view): AbstractResourceLinkHandler { $this->addTemplatePath($view); - parent::setView($view); + return parent::setView($view); } - /** - * Yes, since TYPO3 11.2 this method will be called twice, but - * at first call $view (coming from initialize) is empty (not instance of StandaloneView). - * So, nothing will be changed on first call. - */ protected function addTemplatePath(?ViewInterface $view): void { - if ($view instanceof StandaloneView) { - $typo3Version = GeneralUtility::makeInstance(Typo3Version::class); - $templateRootPaths = ['EXT:recordlist/Resources/Private/Templates/LinkBrowser']; - if (version_compare($typo3Version->getBranch(), '11.2', '<')) { - $templateRootPaths[] = 'EXT:jwtools2/Resources/Private/Extensions/Recordlist/Templates/V10'; - } else { - $templateRootPaths[] = 'EXT:jwtools2/Resources/Private/Extensions/Recordlist/Templates'; - } - $view->setTemplateRootPaths($templateRootPaths); + if ($view instanceof ViewInterface) { + //$templateRootPaths = ['EXT:recordlist/Resources/Private/Templates/LinkBrowser']; + //$templateRootPaths[] = 'EXT:jwtools2/Resources/Private/Extensions/Recordlist/Templates'; + //debug($view->getCurrentRenderingContext()); + //setTemplateRootPaths($templateRootPaths); } } } diff --git a/Classes/LinkHandler/FolderLinkHandler.php b/Classes/LinkHandler/FolderLinkHandler.php index 7b63dc1..76d382a 100644 --- a/Classes/LinkHandler/FolderLinkHandler.php +++ b/Classes/LinkHandler/FolderLinkHandler.php @@ -14,24 +14,21 @@ use TYPO3\CMS\Core\Information\Typo3Version; use TYPO3\CMS\Core\Utility\GeneralUtility; use TYPO3\CMS\Fluid\View\StandaloneView; -use TYPO3Fluid\Fluid\View\ViewInterface; +use TYPO3\CMS\Core\View\ViewInterface; /** * This folder LinkHandler overwrites the LinkHandler of TYPO3 and moves upload and create folder fields to top */ -class FolderLinkHandler extends \TYPO3\CMS\Backend\LinkHandler\FolderLinkHandler +class FolderLinkHandler extends \TYPO3\CMS\Filelist\LinkHandler\FolderLinkHandler { - /** - * @var StandaloneView|ViewInterface - */ - protected $view; + protected ViewInterface $view; public function initialize( AbstractLinkBrowserController $linkBrowser, $identifier, array $configuration ): void { - parent::initialize($linkBrowser, $identifier, $configuration); + //parent::initialize($linkBrowser, $identifier, $configuration); $this->addTemplatePath($this->view); } @@ -40,7 +37,7 @@ public function initialize( * The parent::setView() method was implemented with TYPO3 11.2 * For earlier TYPO3 version we still need the approach from above */ - public function setView(ViewInterface $view): void + public function setView(ViewInterface $view): \TYPO3\CMS\Filelist\LinkHandler\AbstractResourceLinkHandler { $this->addTemplatePath($view); From 38f461140d6742f3f7417ab3c7a7eac155bd92d1 Mon Sep 17 00:00:00 2001 From: Hoja Mustaffa Abdul Latheef Date: Thu, 14 Mar 2024 15:01:36 +0100 Subject: [PATCH 44/65] EventListener registration done in Services.yaml --- Configuration/Services.yaml | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/Configuration/Services.yaml b/Configuration/Services.yaml index fd82af7..8cb398e 100644 --- a/Configuration/Services.yaml +++ b/Configuration/Services.yaml @@ -8,8 +8,8 @@ services: resource: '../Classes/*' # Called by makeInstance in main of ElementBrowserController - JWeiland\Jwtools2\Backend\Browser\FileBrowser: - public: true + #JWeiland\Jwtools2\Backend\Browser\FileBrowser: + # public: true # Called by makeInstance in getCallableFromTarget of Dispatcher JWeiland\Jwtools2\Controller\Ajax\SysFileController: @@ -37,12 +37,15 @@ services: JWeiland\Jwtools2\Hooks\InitializeStdWrap: public: true - # Called by makeInstance in constructor of LinkService - JWeiland\Jwtools2\LinkHandling\FileLinkHandler: + # Element Browser should be registered with tags `recordlist.elementbrowser` + #JWeiland\Jwtools2\Backend\Browser\FileBrowser: + # tags: + # - name: recordlist.elementbrowser + + JWeiland\Jwtools2\LinkHandler\FileLinkHandler: public: true - # Called by makeInstance in constructor of LinkService - JWeiland\Jwtools2\LinkHandling\FolderLinkHandler: + JWeiland\Jwtools2\LinkHandler\FolderLinkHandler: public: true # Event Listeners @@ -56,6 +59,11 @@ services: - name: event.listener identifier: 'jwtools2.events.beforeItemIsIndexedEvent' event: ApacheSolrForTypo3\Solr\Event\Indexing\BeforeItemIsIndexedEvent + JWeiland\Jwtools2\EventListener\ModifyLinkEventListener: + tags: + - name: event.listener + identifier: 'jwtools2.events.modifyLinksEventListener' + event: TYPO3\CMS\Backend\Controller\Event\ModifyLinkHandlersEvent # Backend Context Menu Provider JWeiland\Jwtools2\ContextMenu\ItemProviders\UpdateFileMetaDataProvider: From 5efd193fc9b624377d6c22b8d192bbee3eca616d Mon Sep 17 00:00:00 2001 From: Hoja Mustaffa Abdul Latheef Date: Thu, 14 Mar 2024 15:02:25 +0100 Subject: [PATCH 45/65] Comment todo: for Hooks which needs to be removed after the release --- ext_localconf.php | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/ext_localconf.php b/ext_localconf.php index cd5a659..aa13860 100644 --- a/ext_localconf.php +++ b/ext_localconf.php @@ -49,17 +49,15 @@ ); } - // @todo: Removed this Hook in TYPO3 12 + // @todo: Removed this Hook in TYPO3 12 it must be implemented with new ElementBrowser API or alternative if ( ($jwToolsConfiguration['typo3RequiredColumnsForFiles'] ?? false) || ($jwToolsConfiguration['typo3UploadFieldsInTopOfEB'] ?? false) ) { - $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['ElementBrowsers']['jwtools2_file'] - = \JWeiland\Jwtools2\Backend\Browser\FileBrowser::class; - //$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['typo3/browse_links.php']['browserRendering']['jwtools2_file'] + //$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['ElementBrowsers']['jwtools2_file'] // = \JWeiland\Jwtools2\Backend\Browser\FileBrowser::class; } - + // @todo: Removed this Hook in TYPO3 12 moved the logic to EventListener if ($jwToolsConfiguration['typo3UploadFieldsInTopOfEB'] ?? false) { // For LinkHandler: overwrite TYPO3's LinkHandlers $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['LinkBrowser']['hooks']['jwtools2'] = [ From da18cbd86a5d5265fab703301165a946d8bb3cb7 Mon Sep 17 00:00:00 2001 From: Hoja Mustaffa Abdul Latheef Date: Thu, 14 Mar 2024 15:13:48 +0100 Subject: [PATCH 46/65] Property type fix --- Classes/Fal/Filter/FileNameFilter.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Classes/Fal/Filter/FileNameFilter.php b/Classes/Fal/Filter/FileNameFilter.php index 81665cf..8bf5e56 100644 --- a/Classes/Fal/Filter/FileNameFilter.php +++ b/Classes/Fal/Filter/FileNameFilter.php @@ -23,7 +23,7 @@ class FileNameFilter * * @var bool */ - protected static $showHiddenFilesAndFolders = false; + protected static bool $showHiddenFilesAndFolders = false; /** * Filter method that checks if a file/folder name starts with a dot (e.g. .htaccess) @@ -38,7 +38,7 @@ public static function filterHiddenFilesAndFolders( string $parentIdentifier, array $additionalInformation, DriverInterface $driverInstance - ) { + ): bool|int { // Only apply the filter if hidden files should not be listed if ( self::$showHiddenFilesAndFolders === false From 6938f16acac7fac161f315b452b04668727537e3 Mon Sep 17 00:00:00 2001 From: Hoja Mustaffa Abdul Latheef Date: Tue, 19 Mar 2024 08:50:28 +0100 Subject: [PATCH 47/65] [TASK] Refactoring and Code optimizations --- Classes/Backend/AbstractDocHeader.php | 1 - Classes/Backend/Browser/FileBrowser.php | 24 ++++---- .../ConvertPlainPasswordToHashCommand.php | 3 +- Classes/Command/StatusReportCommand.php | 21 +++---- Classes/Controller/AbstractController.php | 2 - Classes/Controller/Ajax/SysFileController.php | 2 +- Classes/Controller/ToolsController.php | 3 - Classes/Database/Query/QueryGenerator.php | 2 +- .../BackendRestrictionContainer.php | 2 +- .../ReduceCategoryTreeToPageTree.php | 41 +++---------- .../Hooks/ModifyElementInformationHook.php | 2 +- Classes/LinkHandler/FileLinkHandler.php | 4 -- Classes/Provider/ReportProvider.php | 12 +--- .../Routing/Aspect/PersistedTableMapper.php | 17 ++---- Classes/Service/SolrService.php | 3 - Classes/Task/ExecuteQueryTask.php | 4 +- ...xecuteQueryTaskAdditionalFieldProvider.php | 4 +- Classes/Task/IndexQueueWorkerTask.php | 3 +- ...QueueWorkerTaskAdditionalFieldProvider.php | 5 +- ext_conf_template.txt | 4 ++ ext_localconf.php | 57 ++++++++++++------- 21 files changed, 87 insertions(+), 129 deletions(-) diff --git a/Classes/Backend/AbstractDocHeader.php b/Classes/Backend/AbstractDocHeader.php index 84b2348..d5d64ed 100644 --- a/Classes/Backend/AbstractDocHeader.php +++ b/Classes/Backend/AbstractDocHeader.php @@ -18,7 +18,6 @@ use TYPO3\CMS\Extbase\Mvc\Request; use TYPO3\CMS\Extbase\Mvc\View\ViewInterface; use TYPO3\CMS\Extbase\Mvc\Web\Routing\UriBuilder; -use TYPO3\CMS\Fluid\View\TemplateView; /** * Abstract DocHeader for Backend Modules diff --git a/Classes/Backend/Browser/FileBrowser.php b/Classes/Backend/Browser/FileBrowser.php index 85a0c92..3afda44 100644 --- a/Classes/Backend/Browser/FileBrowser.php +++ b/Classes/Backend/Browser/FileBrowser.php @@ -11,31 +11,29 @@ namespace JWeiland\Jwtools2\Backend\Browser; use Doctrine\DBAL\Schema\AbstractSchemaManager; -use JWeiland\Jwtools2\Traits\RequestArgumentsTrait; -use TYPO3\CMS\Backend\Controller\ElementBrowserController; +use TYPO3\CMS\Backend\ElementBrowser\AbstractElementBrowser; use TYPO3\CMS\Backend\Utility\BackendUtility; use TYPO3\CMS\Core\Configuration\Exception\ExtensionConfigurationExtensionNotConfiguredException; use TYPO3\CMS\Core\Configuration\Exception\ExtensionConfigurationPathDoesNotExistException; use TYPO3\CMS\Core\Database\ConnectionPool; use TYPO3\CMS\Core\Information\Typo3Version; use TYPO3\CMS\Core\Localization\LanguageService; +use TYPO3\CMS\Core\Messaging\AbstractMessage; use TYPO3\CMS\Core\Messaging\FlashMessage; -use TYPO3\CMS\Core\Messaging\FlashMessageQueue; use TYPO3\CMS\Core\Messaging\FlashMessageService; use TYPO3\CMS\Core\Resource\File; use TYPO3\CMS\Core\Resource\FileInterface; -use TYPO3\CMS\Core\Type\ContextualFeedbackSeverity; use TYPO3\CMS\Core\Utility\GeneralUtility; use TYPO3\CMS\Extbase\Utility\LocalizationUtility; +use TYPO3\CMS\Recordlist\Controller\ElementBrowserController; /** * Modified version of TYPO3's ElementBrowserController. * We have modified the templates to allow showing the upload form on top of the file/folder list */ -class FileBrowser extends \TYPO3\CMS\Backend\ElementBrowser\FileBrowser +#class FileBrowser extends \TYPO3\CMS\Recordlist\Browser\FileBrowser +class FileBrowser extends AbstractElementBrowser { - use RequestArgumentsTrait; - /** * Only load additional JavaScript, if in file or folder context */ @@ -45,7 +43,7 @@ protected function initialize(): void // of TYPO3's FileBrowser where additional JavaScript will be loaded. That would break the selection and // transfer of chosen records into the parent form. Error: file_undefined insteadof file_123. // JS module "TYPO3/CMS/Recordlist/BrowseFiles" should NOT be loaded, if we are not in file or folder context!!! - if (in_array($this->getGPValue('mode'), ['file', 'folder'])) { + if (in_array((string)GeneralUtility::_GP('mode'), ['file', 'folder'])) { parent::initialize(); } } @@ -58,10 +56,8 @@ public function isValid(string $mode, ElementBrowserController $elementBrowserCo if ($mode === 'file' || $mode === 'folder') { if ($this->getRequiredColumnsFromExtensionConfiguration()) { $flashMessageService = GeneralUtility::makeInstance(FlashMessageService::class); - $flashMessageQueue = $flashMessageService->getMessageQueueByIdentifier( - FlashMessageQueue::NOTIFICATION_QUEUE - ); - $flashMessageQueue->enqueue( + $flashMessageQueue = $flashMessageService->getMessageQueueByIdentifier(); + $flashMessageQueue->addMessage( GeneralUtility::makeInstance( FlashMessage::class, LocalizationUtility::translate( @@ -79,7 +75,7 @@ public function isValid(string $mode, ElementBrowserController $elementBrowserCo LocalizationUtility::translate( 'LLL:EXT:jwtools2/Resources/Private/Language/locallang_mod.xlf:fileBrowser.flashMessage.requiredColumns.title' ), - ContextualFeedbackSeverity::INFO + AbstractMessage::INFO ) ); } @@ -146,7 +142,7 @@ protected function fileIsSelectableInFileList(FileInterface $file, array $imgInf ? trim($properties[$requiredColumn]) : $properties[$requiredColumn]; - if (empty($value)) { + if (!isset($value) || trim($value) === '') { return false; } } diff --git a/Classes/Command/ConvertPlainPasswordToHashCommand.php b/Classes/Command/ConvertPlainPasswordToHashCommand.php index ab60ff4..02b21cd 100644 --- a/Classes/Command/ConvertPlainPasswordToHashCommand.php +++ b/Classes/Command/ConvertPlainPasswordToHashCommand.php @@ -10,7 +10,6 @@ namespace JWeiland\Jwtools2\Command; -use Doctrine\DBAL\Driver\Statement; use Doctrine\DBAL\Result; use Symfony\Component\Console\Command\Command; use Symfony\Component\Console\Input\InputArgument; @@ -79,7 +78,7 @@ protected function updateUsers(string $mode): void $connection = $this->getConnectionPool()->getConnectionForTable($this->modeMapping[$mode]['table']); $statement = $this->getStatementForUsers($this->modeMapping[$mode]['table']); while ($user = $statement->fetch()) { - if (empty($user['password'])) { + if (!isset($user['password']) || $user['password'] === '') { continue; } try { diff --git a/Classes/Command/StatusReportCommand.php b/Classes/Command/StatusReportCommand.php index 96ce32e..ac9f5dd 100644 --- a/Classes/Command/StatusReportCommand.php +++ b/Classes/Command/StatusReportCommand.php @@ -22,8 +22,6 @@ use TYPO3\CMS\Core\Utility\GeneralUtility; use TYPO3\CMS\Install\Controller\MaintenanceController; use TYPO3\CMS\Scheduler\Domain\Repository\SchedulerTaskRepository; -use TYPO3\CMS\Scheduler\Scheduler; -use TYPO3\CMS\Scheduler\Task\AbstractTask; /** * A command which shows a status report about the TYPO3 system @@ -119,10 +117,14 @@ protected function checkDatabaseStatus(): void $result = json_decode($json, true); + $hasSuggestions = isset($result['suggestions']) && $result['suggestions'] !== '' + ? 'YES' + : 'NO'; + $this->ioStyled->definitionList( 'Checking database maintenance', ['Status' => $result['success'] ? 'OK' : 'Error'], - ['Has suggestions?' => !empty($result['suggestions']) ? 'YES' : 'NO'] + ['Has suggestions?' => $hasSuggestions] ); } @@ -169,10 +171,7 @@ protected function getContentOfRobotsTxt(Site $site): string if ($content === '' && !$this->input->hasOption('exclude-robots-txt-url-check')) { $base = rtrim((string)$site->getBase(), '/') . '/'; $content = @file_get_contents($base . 'robots.txt'); - - if (empty($content)) { - $content = ''; - } + $content = $content ?? ''; } return $content; @@ -290,10 +289,12 @@ protected function getTaskStatus(array $task, int $yesterday): string { if (isset($task['serializedExecutions']) && $task['serializedExecutions'] !== '') { return 'running...'; - } elseif ($task['lastExecutionTime'] === 0) { + } + + if ($task['lastExecutionTime'] === 0) { return 'never executed'; - } else { - return $task['lastExecutionTime'] < $yesterday ? 'scheduled > 24h' : 'scheduled < 24h'; } + + return $task['lastExecutionTime'] < $yesterday ? 'scheduled > 24h' : 'scheduled < 24h'; } } diff --git a/Classes/Controller/AbstractController.php b/Classes/Controller/AbstractController.php index f3d54e2..b35af47 100644 --- a/Classes/Controller/AbstractController.php +++ b/Classes/Controller/AbstractController.php @@ -11,12 +11,10 @@ namespace JWeiland\Jwtools2\Controller; use TYPO3\CMS\Backend\Routing\UriBuilder; -use TYPO3\CMS\Backend\Template\Components\Menu\Menu; use TYPO3\CMS\Backend\Template\ModuleTemplate; use TYPO3\CMS\Backend\Template\ModuleTemplateFactory; use TYPO3\CMS\Core\Configuration\ExtensionConfiguration; use TYPO3\CMS\Core\Imaging\IconFactory; -use TYPO3\CMS\Core\Utility\ArrayUtility; use TYPO3\CMS\Core\Utility\GeneralUtility; use TYPO3\CMS\Extbase\Mvc\Controller\ActionController; use TYPO3\CMS\Fluid\View\TemplateView; diff --git a/Classes/Controller/Ajax/SysFileController.php b/Classes/Controller/Ajax/SysFileController.php index 8725c35..bb692cd 100644 --- a/Classes/Controller/Ajax/SysFileController.php +++ b/Classes/Controller/Ajax/SysFileController.php @@ -136,7 +136,7 @@ protected function determineImageMagickVersion(): string // A version like 6.9.10-23 $version = ''; - if (!empty($string)) { + if (isset($string) && $string !== '') { [, $version] = explode('Magick', $string); [$version] = explode(' ', trim($version)); [$version] = explode('-', trim($version)); diff --git a/Classes/Controller/ToolsController.php b/Classes/Controller/ToolsController.php index 0270735..380b250 100644 --- a/Classes/Controller/ToolsController.php +++ b/Classes/Controller/ToolsController.php @@ -11,10 +11,7 @@ namespace JWeiland\Jwtools2\Controller; use Psr\Http\Message\ResponseInterface; -use Psr\Http\Message\ServerRequestInterface; use TYPO3\CMS\Backend\Attribute\AsController; -use TYPO3\CMS\Backend\Template\ModuleTemplate; -use TYPO3\CMS\Backend\Template\ModuleTemplateFactory; #[AsController] class ToolsController extends AbstractController diff --git a/Classes/Database/Query/QueryGenerator.php b/Classes/Database/Query/QueryGenerator.php index 46bcf6d..f0e6473 100644 --- a/Classes/Database/Query/QueryGenerator.php +++ b/Classes/Database/Query/QueryGenerator.php @@ -57,7 +57,7 @@ public function getTreeList($id, $depth, $begin = 0, $permClause = ''): float|in } if ($depth > 1) { $theSubList = $this->getTreeList($row['uid'], $depth - 1, $begin - 1, $permClause); - if (!empty($theList) && !empty($theSubList) && ($theSubList[0] !== ',')) { + if (($theList !== '') && !empty($theSubList) && ($theSubList[0] !== ',')) { $theList .= ','; } $theList .= $theSubList; diff --git a/Classes/Database/Query/Restriction/BackendRestrictionContainer.php b/Classes/Database/Query/Restriction/BackendRestrictionContainer.php index ea00b62..0c9b624 100644 --- a/Classes/Database/Query/Restriction/BackendRestrictionContainer.php +++ b/Classes/Database/Query/Restriction/BackendRestrictionContainer.php @@ -25,7 +25,7 @@ class BackendRestrictionContainer extends AbstractRestrictionContainer * * @var QueryRestrictionInterface[] */ - protected $defaultRestrictionTypes = [ + protected array $defaultRestrictionTypes = [ DeletedRestriction::class, ]; diff --git a/Classes/EventListener/ReduceCategoryTreeToPageTree.php b/Classes/EventListener/ReduceCategoryTreeToPageTree.php index 61205fa..fd3315c 100644 --- a/Classes/EventListener/ReduceCategoryTreeToPageTree.php +++ b/Classes/EventListener/ReduceCategoryTreeToPageTree.php @@ -11,7 +11,6 @@ namespace JWeiland\Jwtools2\EventListener; use Doctrine\DBAL\ArrayParameterType; -use Doctrine\DBAL\Exception; use JWeiland\Jwtools2\Query\QueryGenerator; use JWeiland\Jwtools2\Traits\RequestArgumentsTrait; use TYPO3\CMS\Backend\Tree\TreeNode; @@ -33,25 +32,13 @@ class ReduceCategoryTreeToPageTree { use RequestArgumentsTrait; - /** - * @var string - */ - protected $categoryTableName = 'sys_category'; + protected string $categoryTableName = 'sys_category'; - /** - * @var int - */ - protected $pageUid = 0; + protected int $pageUid = 0; - /** - * @var string - */ - protected $listOfCategoryUids = ''; + protected string $listOfCategoryUids = ''; - /** - * @var ExtensionConfiguration - */ - protected $extensionConfiguration; + protected ExtensionConfiguration $extensionConfiguration; public function __construct(ExtensionConfiguration $extensionConfiguration) { @@ -75,8 +62,6 @@ public function __invoke(ModifyTreeDataEvent $event): void /** * Remove all categories which are not in current page tree - * - * @param TreeNode $treeNode */ protected function removePageTreeForeignCategories(TreeNode $treeNode): void { @@ -105,12 +90,10 @@ protected function removePageTreeForeignCategories(TreeNode $treeNode): void /** * Get current page UID - * - * @return int */ protected function getPageUid(): int { - if (empty($this->pageUid)) { + if (!isset($this->pageUid) || $this->pageUid === 0) { $command = $this->getGetArguments()['command'] ?? ''; if ($command === 'edit') { $record = BackendUtility::getRecordWSOL( @@ -136,14 +119,10 @@ protected function getPageUid(): int /** * Get comma separated list of category UIDs - * - * @param int $pageUid - * @return string - * @throws Exception */ protected function getListOfAllowedCategoryUids(int $pageUid): string { - if (empty($this->listOfCategoryUids)) { + if ($this->listOfCategoryUids === '') { $queryBuilder = $this->getConnectionPool()->getQueryBuilderForTable('sys_category'); $categories = $queryBuilder ->select('uid') @@ -160,7 +139,7 @@ protected function getListOfAllowedCategoryUids(int $pageUid): string ->executeQuery() ->fetchAllAssociative(); - if (empty($categories)) { + if ($categories === []) { return '0'; } @@ -177,9 +156,6 @@ protected function getListOfAllowedCategoryUids(int $pageUid): string /** * Get all page UIDs of current page tree - * - * @param int $pageUid - * @return array */ public function getPagesOfCurrentRootPage(int $pageUid): array { @@ -198,9 +174,6 @@ public function getPagesOfCurrentRootPage(int $pageUid): array /** * Slide up through RootLine and return UID of page which is configured with is_siteroot - * - * @param int $uid - * @return int */ protected function getRootPageUid(int $uid): int { diff --git a/Classes/Hooks/ModifyElementInformationHook.php b/Classes/Hooks/ModifyElementInformationHook.php index fecdaa3..68cafea 100644 --- a/Classes/Hooks/ModifyElementInformationHook.php +++ b/Classes/Hooks/ModifyElementInformationHook.php @@ -137,7 +137,7 @@ protected function initDatabaseRecord(): void } else { $this->row = BackendUtility::getRecordWSOL($this->table, $this->uid); if ($this->row) { - if (!empty($this->row['t3ver_oid'])) { + if ((int)$this->row['t3ver_oid'] !== 0) { // Make $this->uid the uid of the versioned record, while $this->row['uid'] is live record uid $this->uid = (int)$this->row['_ORIG_uid']; } diff --git a/Classes/LinkHandler/FileLinkHandler.php b/Classes/LinkHandler/FileLinkHandler.php index 3499dfb..7bf6e2e 100644 --- a/Classes/LinkHandler/FileLinkHandler.php +++ b/Classes/LinkHandler/FileLinkHandler.php @@ -10,12 +10,8 @@ namespace JWeiland\Jwtools2\LinkHandler; -use Psr\Http\Message\ServerRequestInterface; use TYPO3\CMS\Backend\Controller\AbstractLinkBrowserController; -use TYPO3\CMS\Core\Information\Typo3Version; -use TYPO3\CMS\Core\Utility\GeneralUtility; use TYPO3\CMS\Filelist\LinkHandler\AbstractResourceLinkHandler; -use TYPO3\CMS\Fluid\View\StandaloneView; use TYPO3\CMS\Core\View\ViewInterface; /** diff --git a/Classes/Provider/ReportProvider.php b/Classes/Provider/ReportProvider.php index 5555124..2c167e8 100644 --- a/Classes/Provider/ReportProvider.php +++ b/Classes/Provider/ReportProvider.php @@ -24,15 +24,9 @@ */ class ReportProvider implements StatusProviderInterface, ExtendedStatusProviderInterface { - /** - * @var ListUtility - */ - protected $listUtility; + protected ListUtility $listUtility; - /** - * @var ExtensionConfiguration - */ - protected $extensionConfiguration; + protected ExtensionConfiguration $extensionConfiguration; public function __construct() { @@ -66,7 +60,7 @@ public function getDetailedStatus(): array ]; } - protected function getUpdatableExtensions(bool $renderForReportMail = false) + protected function getUpdatableExtensions(bool $renderForReportMail = false): Status { $extensionInformation = $this->listUtility->getAvailableAndInstalledExtensionsWithAdditionalInformation(); $updatableExtensions = []; diff --git a/Classes/Routing/Aspect/PersistedTableMapper.php b/Classes/Routing/Aspect/PersistedTableMapper.php index 4ee6700..f6c026c 100644 --- a/Classes/Routing/Aspect/PersistedTableMapper.php +++ b/Classes/Routing/Aspect/PersistedTableMapper.php @@ -48,19 +48,14 @@ class PersistedTableMapper implements StaticMappableAspectInterface, SiteLanguageAwareInterface, SiteAwareInterface { use SiteAccessorTrait; + use SiteLanguageAccessorTrait; - protected $settings; + protected array $settings; - /** - * @var string - */ - protected $tableName = ''; + protected string $tableName = ''; - /** - * @var string - */ - protected $fieldName = ''; + protected string $fieldName = ''; public function __construct(array $settings) { @@ -76,7 +71,7 @@ public function generate(string $value): ?string $value = str_replace('/', '-', $value); $storedRoute = $this->getStoredRoute($value); - if (empty($storedRoute)) { + if ($storedRoute === []) { $slugHelper = $this->getSlugHelper(); $target = $slugHelper->sanitize($value); $this->setStoredRoute($value, $target); @@ -90,7 +85,7 @@ public function generate(string $value): ?string public function resolve(string $value): ?string { $storedRoute = $this->getStoredRoute('', $value); - if (empty($storedRoute)) { + if ($storedRoute === []) { return null; } diff --git a/Classes/Service/SolrService.php b/Classes/Service/SolrService.php index 7e40bba..ab71d1d 100644 --- a/Classes/Service/SolrService.php +++ b/Classes/Service/SolrService.php @@ -26,9 +26,6 @@ class SolrService /** * Instead of the Solr Statistic, this Statistic will return * a statistic over all sites - * - * @return QueueStatistic - * @throws DBALException */ public function getStatistic(): QueueStatistic { diff --git a/Classes/Task/ExecuteQueryTask.php b/Classes/Task/ExecuteQueryTask.php index 368c624..70072d8 100644 --- a/Classes/Task/ExecuteQueryTask.php +++ b/Classes/Task/ExecuteQueryTask.php @@ -34,7 +34,7 @@ public function execute(): bool } $sqlQueries = array_filter($sqlQueries); - if (empty($sqlQueries)) { + if ($sqlQueries === []) { $this->addMessage('No queries for execution found'); return false; } @@ -74,8 +74,6 @@ public function setSqlQuery(string $sqlQuery): void /** * This method is used to add a message to the internal queue - * - * @throws \Exception */ public function addMessage(string $message, ContextualFeedbackSeverity $severity = ContextualFeedbackSeverity::OK): void { diff --git a/Classes/Task/ExecuteQueryTaskAdditionalFieldProvider.php b/Classes/Task/ExecuteQueryTaskAdditionalFieldProvider.php index 20a1235..49e8bb5 100644 --- a/Classes/Task/ExecuteQueryTaskAdditionalFieldProvider.php +++ b/Classes/Task/ExecuteQueryTaskAdditionalFieldProvider.php @@ -29,8 +29,8 @@ class ExecuteQueryTaskAdditionalFieldProvider extends AbstractAdditionalFieldPro * @param AbstractTask $task when editing, reference to the current task object. Null when adding. * @param SchedulerModuleController $schedulerModule : reference to the calling object (Scheduler's BE module) * @return array Array containing all the information pertaining to the additional fields - * The array is multidimensional, keyed to the task class name and each field's id - * For each field it provides an associative sub-array with the following: + * The array is multidimensional, keyed to the task class name and each field's id + * For each field it provides an associative sub-array with the following: */ public function getAdditionalFields(array &$taskInfo, $task, SchedulerModuleController $schedulerModule): array { diff --git a/Classes/Task/IndexQueueWorkerTask.php b/Classes/Task/IndexQueueWorkerTask.php index 25d8473..f1f7b94 100644 --- a/Classes/Task/IndexQueueWorkerTask.php +++ b/Classes/Task/IndexQueueWorkerTask.php @@ -86,8 +86,6 @@ public function execute(): bool /** * Returns some additional information about indexing progress, shown in * the scheduler's task overview list. - * - * @throws Exception */ public function getAdditionalInformation(): string { @@ -115,6 +113,7 @@ public function getAdditionalInformation(): string $message .= ' / Index queue UID: ' . $registry->get('jwtools2-solr', 'indexQueueUid'); $message .= ' / Memory Peak: ' . (float)$registry->get('jwtools2-solr', 'memoryPeakUsage'); } + return $message; } diff --git a/Classes/Task/IndexQueueWorkerTaskAdditionalFieldProvider.php b/Classes/Task/IndexQueueWorkerTaskAdditionalFieldProvider.php index bf74ac8..a0d88a8 100644 --- a/Classes/Task/IndexQueueWorkerTaskAdditionalFieldProvider.php +++ b/Classes/Task/IndexQueueWorkerTaskAdditionalFieldProvider.php @@ -12,7 +12,6 @@ use TYPO3\CMS\Extbase\Utility\LocalizationUtility; use TYPO3\CMS\Scheduler\AbstractAdditionalFieldProvider; -use TYPO3\CMS\Scheduler\AdditionalFieldProviderInterface; use TYPO3\CMS\Scheduler\Controller\SchedulerModuleController; use TYPO3\CMS\Scheduler\Task\AbstractTask; use TYPO3\CMS\Scheduler\Task\Enumeration\Action; @@ -30,8 +29,8 @@ class IndexQueueWorkerTaskAdditionalFieldProvider extends AbstractAdditionalFiel * @param AbstractTask $task when editing, reference to the current task object. Null when adding. * @param SchedulerModuleController $schedulerModule : reference to the calling object (Scheduler's BE module) * @return array Array containing all the information pertaining to the additional fields - * The array is multidimensional, keyed to the task class name and each field's id - * For each field it provides an associative sub-array with the following: + * The array is multidimensional, keyed to the task class name and each field's id + * For each field it provides an associative sub-array with the following: */ public function getAdditionalFields(array &$taskInfo, $task, SchedulerModuleController $schedulerModule): array { diff --git a/ext_conf_template.txt b/ext_conf_template.txt index 5821946..2dc2238 100644 --- a/ext_conf_template.txt +++ b/ext_conf_template.txt @@ -2,8 +2,12 @@ typo3EnableUidInPageTree = 0 # cat=typo3; type=boolean; label=LLL:EXT:jwtools2/Resources/Private/Language/ExtConf.xlf:typo3TransferTypoScriptCurrent typo3TransferTypoScriptCurrent = 0 + +# @todo: rafactor this for version 12 # cat=typo3; type=boolean; label=LLL:EXT:jwtools2/Resources/Private/Language/ExtConf.xlf:typo3UploadFieldsInTopOfEB typo3UploadFieldsInTopOfEB = 0 + +# @todo: rafactor this for version 12 # cat=typo3; type=string; label=LLL:EXT:jwtools2/Resources/Private/Language/ExtConf.xlf:typo3RequiredColumnsForFiles typo3RequiredColumnsForFiles = # cat=typo3; type=boolean; label=LLL:EXT:jwtools2/Resources/Private/Language/ExtConf.xlf:typo3ShowEditButtonInElementInformation diff --git a/ext_localconf.php b/ext_localconf.php index aa13860..547ee2b 100644 --- a/ext_localconf.php +++ b/ext_localconf.php @@ -4,19 +4,32 @@ die('Access denied.'); } +use JWeiland\Jwtools2\Fal\Filter\FileNameFilter; +use JWeiland\Jwtools2\Hooks\CachingFrameworkLoggerHook; +use JWeiland\Jwtools2\Hooks\InitializeStdWrap; +use JWeiland\Jwtools2\Hooks\ModifyElementInformationHook; v bh +use JWeiland\Jwtools2\Hooks\ModifyLinkHandlerHook; +use JWeiland\Jwtools2\Hooks\MoveTranslatedContentElementsHook; +use JWeiland\Jwtools2\Provider\ReportProvider; +use JWeiland\Jwtools2\Routing\Aspect\PersistedTableMapper; +use JWeiland\Jwtools2\Task\ExecuteQueryTask; +use JWeiland\Jwtools2\Task\ExecuteQueryTaskAdditionalFieldProvider; +use JWeiland\Jwtools2\Task\IndexQueueWorkerTask; +use JWeiland\Jwtools2\Task\IndexQueueWorkerTaskAdditionalFieldProvider; +use Psr\Log\LogLevel; +use TYPO3\CMS\Core\Configuration\ExtensionConfiguration; +use TYPO3\CMS\Core\Log\Writer\FileWriter; +use TYPO3\CMS\Core\Utility\ExtensionManagementUtility; +use TYPO3\CMS\Core\Utility\GeneralUtility; + call_user_func(static function () { - $jwToolsConfiguration = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance( - \TYPO3\CMS\Core\Configuration\ExtensionConfiguration::class - )->get('jwtools2'); - $typo3Version = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance( - \TYPO3\CMS\Core\Information\Typo3Version::class - ); + $jwToolsConfiguration = GeneralUtility::makeInstance(ExtensionConfiguration::class)->get('jwtools2'); // Create our own logger file if (!isset($GLOBALS['TYPO3_CONF_VARS']['LOG']['JWeiland']['Jwtools2']['writerConfiguration'])) { $GLOBALS['TYPO3_CONF_VARS']['LOG']['JWeiland']['Jwtools2']['writerConfiguration'] = [ - \Psr\Log\LogLevel::INFO => [ - \TYPO3\CMS\Core\Log\Writer\FileWriter::class => [ + LogLevel::INFO => [ + FileWriter::class => [ 'logFileInfix' => 'jwtools2', ], ], @@ -25,26 +38,26 @@ if ($jwToolsConfiguration['solrEnable'] ?? false) { // Add scheduler task to index all Solr Sites - $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['scheduler']['tasks'][\JWeiland\Jwtools2\Task\IndexQueueWorkerTask::class] = [ + $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['scheduler']['tasks'][IndexQueueWorkerTask::class] = [ 'extension' => 'jwtools2', 'title' => 'LLL:EXT:jwtools2/Resources/Private/Language/locallang.xlf:indexqueueworker_title', 'description' => 'LLL:EXT:jwtools2/Resources/Private/Language/locallang.xlf:indexqueueworker_description', - 'additionalFields' => \JWeiland\Jwtools2\Task\IndexQueueWorkerTaskAdditionalFieldProvider::class, + 'additionalFields' => IndexQueueWorkerTaskAdditionalFieldProvider::class, ]; } if ($jwToolsConfiguration['enableSqlQueryTask'] ?? false) { // Add scheduler task to execute SQL-Queries - $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['scheduler']['tasks'][\JWeiland\Jwtools2\Task\ExecuteQueryTask::class] = [ + $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['scheduler']['tasks'][ExecuteQueryTask::class] = [ 'extension' => 'jwtools2', 'title' => 'LLL:EXT:jwtools2/Resources/Private/Language/locallang.xlf:executeQueryTask.title', 'description' => 'LLL:EXT:jwtools2/Resources/Private/Language/locallang.xlf:executeQueryTask.description', - 'additionalFields' => \JWeiland\Jwtools2\Task\ExecuteQueryTaskAdditionalFieldProvider::class, + 'additionalFields' => ExecuteQueryTaskAdditionalFieldProvider::class, ]; } if ($jwToolsConfiguration['typo3EnableUidInPageTree'] ?? false) { - \TYPO3\CMS\Core\Utility\ExtensionManagementUtility::addUserTSConfig( + ExtensionManagementUtility::addUserTSConfig( 'options.pageTree.showPageIdWithTitle = 1' ); } @@ -61,20 +74,20 @@ if ($jwToolsConfiguration['typo3UploadFieldsInTopOfEB'] ?? false) { // For LinkHandler: overwrite TYPO3's LinkHandlers $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['LinkBrowser']['hooks']['jwtools2'] = [ - 'handler' => \JWeiland\Jwtools2\Hooks\ModifyLinkHandlerHook::class + 'handler' => ModifyLinkHandlerHook::class ]; } if ($jwToolsConfiguration['typo3ShowEditButtonInElementInformation'] ?? false) { $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['typo3/show_item.php']['typeRendering']['jwtools'] - = \JWeiland\Jwtools2\Hooks\ModifyElementInformationHook::class; + = ModifyElementInformationHook::class; } if ($jwToolsConfiguration['typo3ExcludeVideoFilesFromFalFilter'] ?? false) { // Exclude .youtube and .vimeo from hidden files in filelist $GLOBALS['TYPO3_CONF_VARS']['SYS']['fal']['defaultFilterCallbacks'] = [ [ - \JWeiland\Jwtools2\Fal\Filter\FileNameFilter::class, + FileNameFilter::class, 'filterHiddenFilesAndFolders', ], ]; @@ -82,27 +95,27 @@ if ($jwToolsConfiguration['typo3ApplyFixForMoveTranslatedContentElements'] ?? false) { $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_tcemain.php']['processCmdmapClass']['jwtools2MoveTranslated'] - = \JWeiland\Jwtools2\Hooks\MoveTranslatedContentElementsHook::class; + = MoveTranslatedContentElementsHook::class; } if ($jwToolsConfiguration['enableCachingFrameworkLogger'] ?? false) { $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/cache/frontend/class.t3lib_cache_frontend_variablefrontend.php']['set'][1655965501] - = \JWeiland\Jwtools2\Hooks\CachingFrameworkLoggerHook::class . '->analyze'; + = CachingFrameworkLoggerHook::class . '->analyze'; } if ( ($jwToolsConfiguration['enableReportProvider'] ?? false) - && \TYPO3\CMS\Core\Utility\ExtensionManagementUtility::isLoaded('reports') + && ExtensionManagementUtility::isLoaded('reports') ) { $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['reports']['tx_reports']['status']['providers']['jwtools2'][] - = \JWeiland\Jwtools2\Provider\ReportProvider::class; + = ReportProvider::class; } // Retrieve stdWrap current value into sub cObj. CONTENT $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['tslib/class.tslib_content.php']['postInit']['jwtools2_initStdWrap'] - = \JWeiland\Jwtools2\Hooks\InitializeStdWrap::class; + = InitializeStdWrap::class; // Register an Aspect to store source/target-mapping. Will be activated, if used in SiteConfiguration only. $GLOBALS['TYPO3_CONF_VARS']['SYS']['routing']['aspects']['PersistedTableMapper'] - = \JWeiland\Jwtools2\Routing\Aspect\PersistedTableMapper::class; + = PersistedTableMapper::class; }); From 0256b067f7d2665f296b76d0ab4d521235e3dc32 Mon Sep 17 00:00:00 2001 From: Hoja Mustaffa Abdul Latheef Date: Wed, 20 Mar 2024 16:10:10 +0100 Subject: [PATCH 48/65] Migrated SolrIndex.js from requireJS to ES6 Compatible by removing jquery support --- .../Controller/Ajax/AjaxSolrController.php | 15 +- Classes/Controller/SolrController.php | 3 +- Classes/Service/SolrService.php | 2 +- .../Public/JavaScript/SolrBackendModule.js | 1 - Resources/Public/JavaScript/SolrIndex.js | 167 ------------------ .../Public/JavaScript/clear-full-index.js | 1 + .../Public/JavaScript/solr-backend-module.js | 121 +++++++++++++ ext_localconf.php | 2 +- 8 files changed, 132 insertions(+), 180 deletions(-) delete mode 100644 Resources/Public/JavaScript/SolrBackendModule.js delete mode 100644 Resources/Public/JavaScript/SolrIndex.js create mode 100644 Resources/Public/JavaScript/solr-backend-module.js diff --git a/Classes/Controller/Ajax/AjaxSolrController.php b/Classes/Controller/Ajax/AjaxSolrController.php index 9301a03..6e7d272 100644 --- a/Classes/Controller/Ajax/AjaxSolrController.php +++ b/Classes/Controller/Ajax/AjaxSolrController.php @@ -33,8 +33,7 @@ class AjaxSolrController public function clearIndexAction(ServerRequest $request): ResponseInterface { $response = new Response(); - $postData = $request->getParsedBody(); - $moduleData = $postData['tx_jwtools2']; + $moduleData = $request->getParsedBody(); $rootPageUid = $this->getRootPageUidFromRequest($request); $configurationNames = []; @@ -83,10 +82,11 @@ public function createIndexQueueAction(ServerRequest $request): ResponseInterfac $indexingConfigurationsToReIndex = $site->getSolrConfiguration()->getEnabledIndexQueueConfigurationNames(); foreach ($indexingConfigurationsToReIndex as $indexingConfigurationName) { try { - $indexQueue->getInitializationService()->initializeBySiteAndIndexConfiguration( - $site, - $indexingConfigurationName - ); + $indexQueue->getQueueInitializationService() + ->initializeBySiteAndIndexConfiguration( + $site, + $indexingConfigurationName + ); } catch (ConnectionException|Exception $e) { } } @@ -138,8 +138,7 @@ public function getProgressAction(ServerRequest $request): ResponseInterface protected function getRootPageUidFromRequest(ServerRequest $request): int { - $postData = $request->getParsedBody(); - $moduleData = $postData['tx_jwtools2']; + $moduleData = $request->getParsedBody(); $rootPageUid = 0; if (array_key_exists('rootPageUid', $moduleData)) { $rootPageUid = (int)$moduleData['rootPageUid']; diff --git a/Classes/Controller/SolrController.php b/Classes/Controller/SolrController.php index 1d7444e..12aad40 100644 --- a/Classes/Controller/SolrController.php +++ b/Classes/Controller/SolrController.php @@ -46,8 +46,7 @@ public function initializeView($view): void if (!$view instanceof NotFoundView) { parent::initializeView($view); - //$this->pageRenderer->loadJavaScriptModule('@jweiland/jwtools2/SolrBackendModule.js'); - $this->pageRenderer->loadRequireJsModule('TYPO3/CMS/Jwtools2/SolrIndex'); + $this->pageRenderer->loadJavaScriptModule('@jweiland/jwtools2/solr-backend-module.js'); /** @var SolrDocHeader $docHeader */ $docHeader = GeneralUtility::makeInstance(SolrDocHeader::class, $this->request, $this->moduleTemplate); diff --git a/Classes/Service/SolrService.php b/Classes/Service/SolrService.php index ab71d1d..3cd369e 100644 --- a/Classes/Service/SolrService.php +++ b/Classes/Service/SolrService.php @@ -133,7 +133,7 @@ public function clearFileTableByType(Site $site, string $type = ''): void */ public function clearSolrIndexByType(Site $site, $type = ''): void { - $tableName = $site->getSolrConfiguration()->getIndexQueueTableNameOrFallbackToConfigurationName($type); + $tableName = $site->getSolrConfiguration()->getIndexQueueTypeOrFallbackToConfigurationName($type); $solrServers = GeneralUtility::makeInstance(ConnectionManager::class) ->getConnectionsBySite($site); diff --git a/Resources/Public/JavaScript/SolrBackendModule.js b/Resources/Public/JavaScript/SolrBackendModule.js deleted file mode 100644 index e858729..0000000 --- a/Resources/Public/JavaScript/SolrBackendModule.js +++ /dev/null @@ -1 +0,0 @@ -alert('solr module loaded!'); diff --git a/Resources/Public/JavaScript/SolrIndex.js b/Resources/Public/JavaScript/SolrIndex.js deleted file mode 100644 index 8303909..0000000 --- a/Resources/Public/JavaScript/SolrIndex.js +++ /dev/null @@ -1,167 +0,0 @@ -/* - * This file is part of the jwtools2 project. - * - * It is free software; you can redistribute it and/or modify it under - * the terms of the GNU General Public License, either version 2 - * of the License, or any later version. - * - * For the full copyright and license information, please read the - * LICENSE.txt file that was distributed with this source code. - * - * The TYPO3 project - inspiring people to share! - */ -/** - * Module: TYPO3/CMS/Jwtools2/SolrIndex - */ -define(['jquery', - 'TYPO3/CMS/Backend/Icons', - 'TYPO3/CMS/Backend/Notification' - ], function($, Icons, Notification) { - let SolrIndex = { - me: this - }; - - SolrIndex.showSolrProgress = function() { - let $activeRows = $('#solrSites tbody tr'); - - if ($activeRows.length > 0) { - SolrIndex.processRows( - $activeRows, - 'jwtools2_getSolrProgress', - function($row, status, data, response) { - if (status === 'success') { - $row.find(".status").html("" + - "
" + - "
" + - "" + response.progress + "% Complete" + - "
" + - "
" - ); - } else if (status === 'error') { - alert('Error'); - } else if (status === 'finished') { - SolrIndex.displaySuccess('Solr Status all all Sites has been updated'); - } - }); - } - }; - - SolrIndex.createSolrIndexQueue = function() { - let $activeRows = $('#solrSites tbody tr'); - - if ($activeRows.length > 0) { - SolrIndex.processRows( - $activeRows, - 'jwtools2_createSolrIndexQueue', - function($row, status, data, response) { - if (status === 'success') { - $row.find(".status").html("Solr Index Queue created"); - } else if (status === 'error') { - alert('Error'); - } else if (status === 'finished') { - SolrIndex.displaySuccess('Solr Index Queue of all Solr Site has been created'); - } - }); - } - }; - - /** - * Show solr progress for rows - * - * @param {Object} rows - * @param {String} uri - * @param {function} callback - */ - SolrIndex.processRows = function(rows, uri, callback) { - if (rows) { - rows = $(rows).toArray(); - let $row = $(rows.shift()); - let data = { - 'rootPageUid': $row.find(".rootPageUid").data("rootPageUid") - }; - - SolrIndex.processRow(data, uri, function(status, data, response) { - callback($row, status, data, response); - if (status === 'success') { - if (rows.length) { - SolrIndex.processRows(rows, uri, callback); - } else { - callback($row, 'finished', data, response); - } - } - }); - } - }; - - /** - * Show solr status for row - * - * @param {Object} data - * @param {String} uri - * @param {function} callback - */ - SolrIndex.processRow = function(data, uri, callback) { - SolrIndex.executeAjaxRequest( - TYPO3.settings.ajaxUrls[uri], - data, - function(response, status) { - if (status === 'success' && response.success) { - callback('success', data, response); - } else { - callback('error', data, response); - } - }); - }; - - /** - * Execute AJAX request - * - * @param {String} uri - * @param {Object} data - * @param {function} callback - */ - SolrIndex.executeAjaxRequest = function(uri, data, callback) { - let newData = { - tx_jwtools2: data - }; - SolrIndex.currentRequest = $.ajax({ - type: 'POST', - cache: false, - url: uri, - data: newData, - dataType: 'json', - success: function(response, status) { - if (typeof callback === 'function') { - callback(response, status); - } - }, - error: function(response, status) { - if (typeof callback === 'function') { - callback(response, status); - } - } - }); - }; - - /** - * Display success flash message - * - * @param {String} label - */ - SolrIndex.displaySuccess = function(label) { - if (typeof label === 'string' && label !== '') { - Notification.success('Success', label); - } - }; - - let $showSolrProgressButton = $("#showSolrProgress"); - $showSolrProgressButton.on("click", function(event) { - event.preventDefault(); - SolrIndex.showSolrProgress(); - }); - let $createSolrIndexQueueButton = $("#createSolrIndexQueue"); - $createSolrIndexQueueButton.on("click", function(event) { - event.preventDefault(); - SolrIndex.createSolrIndexQueue(); - }); -}); diff --git a/Resources/Public/JavaScript/clear-full-index.js b/Resources/Public/JavaScript/clear-full-index.js index 38684ec..1e78680 100644 --- a/Resources/Public/JavaScript/clear-full-index.js +++ b/Resources/Public/JavaScript/clear-full-index.js @@ -15,6 +15,7 @@ import { success as showSuccessNotification } from 'TYPO3/CMS/Backend/Notificati class ClearIndex { constructor() { + alert('here'); this.clearIndexAction = this.clearIndexAction.bind(this); this.clearIndexByRows = this.clearIndexByRows.bind(this); this.clearIndexByRow = this.clearIndexByRow.bind(this); diff --git a/Resources/Public/JavaScript/solr-backend-module.js b/Resources/Public/JavaScript/solr-backend-module.js new file mode 100644 index 0000000..6c465a5 --- /dev/null +++ b/Resources/Public/JavaScript/solr-backend-module.js @@ -0,0 +1,121 @@ +import Notification from "@typo3/backend/notification.js"; + +/** + * Module: @jweiland/jwtools2/solr-backend-module + */ +class SolrIndex { + constructor() { + this.showSolrProgressButton = document.getElementById('showSolrProgress'); + this.createSolrIndexQueueButton = document.getElementById('createSolrIndexQueue'); + this.activeRows = document.querySelectorAll('#solrSites tbody tr'); + this.init(); + } + + init() { + if (this.showSolrProgressButton) { + this.showSolrProgressButton.addEventListener('click', (event) => { + event.preventDefault(); + this.showSolrProgress(); + }); + } + + if (this.createSolrIndexQueueButton) { + this.createSolrIndexQueueButton.addEventListener('click', (event) => { + event.preventDefault(); + this.createSolrIndexQueue(); + }); + } + } + + showSolrProgress() { + if (this.activeRows.length > 0) { + this.processRows('jwtools2_getSolrProgress', (row, status, data, response) => { + console.log(status); + if (status === 'success') { + console.log(response); + row.querySelector('.status').innerHTML = ` +
+
${response.progress}% Complete
+
`; + } else if (status === 'error') { + console.log('Error'); + this.displayError(); + } else if (status === 'finished') { + console.log(response); + this.displaySuccess('Solr Status all all Sites has been updated'); + } + }); + } + } + + createSolrIndexQueue() { + if (this.activeRows.length > 0) { + this.processRows('jwtools2_createSolrIndexQueue', (row, status, data, response) => { + if (status === 'success') { + row.querySelector('.status').textContent = 'Solr Index Queue created'; + } else if (status === 'error') { + alert('Error'); + } else if (status === 'finished') { + this.displaySuccess('Solr Index Queue of all Solr Site has been created'); + } + }); + } + } + + processRows(uri, callback) { + if (this.activeRows.length > 0) { + const row = this.activeRows[0]; + const data = { 'rootPageUid': row.querySelector('.rootPageUid').dataset.rootPageUid }; + this.processRow(data, uri, (status, data, response) => { + callback(row, status, data, response); + if (status === 'success') { + if (this.activeRows.length > 1) { + this.activeRows = Array.from(this.activeRows).slice(1); + this.processRows(uri, callback); + } else { + callback(row, 'finished', data, response); + } + } + }); + } + } + + processRow(data, uri, callback) { + this.executeAjaxRequest(TYPO3.settings.ajaxUrls[uri], data, (response, status) => { + if (status === 'success' && response.success) { + callback('success', data, response); + } else { + callback('error', data, response); + } + }); + } + + executeAjaxRequest(uri, data, callback) { + const formData = new URLSearchParams(); + Object.entries(data).forEach(([key, value]) => { + formData.append(key, value); + }); + fetch(uri, { + method: 'POST', + cache: 'no-cache', + body: formData, + headers: { + 'Content-Type': 'application/x-www-form-urlencoded' + }, + }).then(response => response.json()) + .then(response => callback(response, 'success')) + .catch(error => callback(error, 'error')); + } + + displaySuccess(label) { + if (typeof label === 'string' && label !== '') { + Notification.success('Success', label); + } + } + + displayError () { + console.log('Error!') + } +} + +const solrIndex = new SolrIndex(); diff --git a/ext_localconf.php b/ext_localconf.php index 547ee2b..71a9dba 100644 --- a/ext_localconf.php +++ b/ext_localconf.php @@ -7,7 +7,7 @@ use JWeiland\Jwtools2\Fal\Filter\FileNameFilter; use JWeiland\Jwtools2\Hooks\CachingFrameworkLoggerHook; use JWeiland\Jwtools2\Hooks\InitializeStdWrap; -use JWeiland\Jwtools2\Hooks\ModifyElementInformationHook; v bh +use JWeiland\Jwtools2\Hooks\ModifyElementInformationHook; use JWeiland\Jwtools2\Hooks\ModifyLinkHandlerHook; use JWeiland\Jwtools2\Hooks\MoveTranslatedContentElementsHook; use JWeiland\Jwtools2\Provider\ReportProvider; From e5c60f1c132c58896a39987e34d95a339b875efa Mon Sep 17 00:00:00 2001 From: Hoja Mustaffa Abdul Latheef Date: Thu, 21 Mar 2024 15:16:46 +0100 Subject: [PATCH 49/65] Fixed CacheClearFullIndexForm to ES6 Removing jquery --- Classes/Backend/SolrDocHeader.php | 38 ++--- .../Controller/Ajax/AjaxSolrController.php | 1 - Classes/Controller/SolrController.php | 10 +- .../Solr/ShowClearFullIndexForm.html | 148 +++++++++--------- .../Templates/Solr/ShowClearIndexForm.html | 2 +- Resources/Public/JavaScript/ClearFullIndex.js | 141 ----------------- .../Public/JavaScript/clear-full-index.js | 43 +++-- .../Public/JavaScript/solr-backend-module.js | 4 - 8 files changed, 112 insertions(+), 275 deletions(-) delete mode 100644 Resources/Public/JavaScript/ClearFullIndex.js diff --git a/Classes/Backend/SolrDocHeader.php b/Classes/Backend/SolrDocHeader.php index b1beee0..312dd25 100644 --- a/Classes/Backend/SolrDocHeader.php +++ b/Classes/Backend/SolrDocHeader.php @@ -39,38 +39,22 @@ protected function addModuleSelector(): void ->getDocHeaderComponent() ->getButtonBar(); - $splitButtonBar = $buttonBar - ->makeSplitButton(); - - $newButton = $buttonBar - ->makeInputButton() - ->setName('module') - ->setValue('solr') - //->setOnClick() + $overviewButton = $buttonBar + ->makeLinkButton() + ->setHref($this->uriBuilder->reset()->uriFor('list', [], 'Solr')) ->setIcon($this->iconFactory->getIcon('actions-document-new', Icon::SIZE_SMALL)) - ->setTitle('Solr Overview') - ->setShowLabelText(true) - ->setDataAttributes([ - 'dispatch-action' => 'TYPO3.WindowManager.localOpen', - // JSON encoded representation of JavaScript function arguments - // (HTML attributes are encoded in \TYPO3\CMS\Backend\Template\Components\Buttons\LinkButton) - 'dispatch-args' => GeneralUtility::jsonEncodeForHtmlAttribute([ - $this->getLinkForUrl($this->uriBuilder->reset()->uriFor('list', [], 'Solr')), - ], false) - ]); - - $splitButtonBar->addItem($newButton, true); + ->setTitle('Overview') + ->setShowLabelText(true); - $newButton = $buttonBar - ->makeInputButton() - ->setName('module') - ->setValue('cleanUp') - //->setOnClick($this->getLinkForUrl($this->uriBuilder->reset()->uriFor('showClearFullIndexForm', [], 'Solr'))) + $clearFullIndexButton = $buttonBar + ->makeLinkButton() + ->setHref($this->uriBuilder->reset()->uriFor('showClearFullIndexForm', [], 'Solr')) ->setIcon($this->iconFactory->getIcon('actions-document-new', Icon::SIZE_SMALL)) ->setTitle('Clear full index...') ->setShowLabelText(true); - $splitButtonBar->addItem($newButton); - $buttonBar->addButton($splitButtonBar); + $buttonBar + ->addButton($overviewButton) + ->addButton($clearFullIndexButton); } } diff --git a/Classes/Controller/Ajax/AjaxSolrController.php b/Classes/Controller/Ajax/AjaxSolrController.php index 6e7d272..d816cf5 100644 --- a/Classes/Controller/Ajax/AjaxSolrController.php +++ b/Classes/Controller/Ajax/AjaxSolrController.php @@ -34,7 +34,6 @@ public function clearIndexAction(ServerRequest $request): ResponseInterface { $response = new Response(); $moduleData = $request->getParsedBody(); - $rootPageUid = $this->getRootPageUidFromRequest($request); $configurationNames = []; if (array_key_exists('configurationNames', $moduleData)) { diff --git a/Classes/Controller/SolrController.php b/Classes/Controller/SolrController.php index 12aad40..c99f85d 100644 --- a/Classes/Controller/SolrController.php +++ b/Classes/Controller/SolrController.php @@ -202,8 +202,8 @@ public function clearIndexAction(int $rootPageUid, array $configurationNames, ar */ public function showClearFullIndexFormAction(): ResponseInterface { - $pageRenderer = GeneralUtility::makeInstance(PageRenderer::class); - $pageRenderer->loadRequireJsModule('TYPO3/CMS/Jwtools2/ClearFullIndex'); + $this->pageRenderer->loadJavaScriptModule('@jweiland/jwtools2/clear-full-index.js'); + //$pageRenderer->loadRequireJsModule('TYPO3/CMS/Jwtools2/ClearFullIndex'); $configurationNamesOfAllSites = []; $sites = $this->solrRepository->findAllAvailableSites(); @@ -213,10 +213,10 @@ public function showClearFullIndexFormAction(): ResponseInterface $site->getSolrConfiguration()->getEnabledIndexQueueConfigurationNames() ); } - $this->view->assign('sites', $sites); - $this->view->assign('configurationNamesOfAllSites', $configurationNamesOfAllSites); + $this->moduleTemplate->assign('sites', $sites); + $this->moduleTemplate->assign('configurationNamesOfAllSites', $configurationNamesOfAllSites); - return $this->htmlResponse(); + return $this->moduleTemplate->renderResponse('showClearFullIndexForm'); } protected function getIndexQueueItem(int $rootPageUid, string $configurationName, int $recordUid): ?Item diff --git a/Resources/Private/Templates/Solr/ShowClearFullIndexForm.html b/Resources/Private/Templates/Solr/ShowClearFullIndexForm.html index 7e3daf5..851cf34 100644 --- a/Resources/Private/Templates/Solr/ShowClearFullIndexForm.html +++ b/Resources/Private/Templates/Solr/ShowClearFullIndexForm.html @@ -1,83 +1,87 @@ + xmlns:f="http://typo3.org/ns/TYPO3/CMS/Fluid/ViewHelpers" + xmlns:c="http://typo3.org/ns/TYPO3\CMS\Core\ViewHelpers" + data-namespace-typo3-fluid="true"> - + -

Clear Index of all sites

+ + - -

- Configuration names - This is a merged collection of all configuration names of all sites -

- - -
- - -
-
+

Clear Index of all sites

-

Choose which index should be cleared

- -
- - -
-
- - -
-
- - -
+ +

+ Configuration names + This is a merged collection of all configuration names of all sites +

+ + +
+ + +
+
- -
+

Choose which index should be cleared

+ +
+ + +
+
+ + +
+
+ + +
-

Configured Sites

- - - - - - - - - - - - - - - - - - - - -
UIDTitleStatus
{site.rootPage.uid}{site.rootPage.title} - -
-
- - No Solr RootPages configured - -
+ +
+

Configured Sites

+ + + + + + + + + + + + + + + + + + + +
UIDTitleStatus
{site.rootPageRecord.uid}{site.rootPageRecord.title} + +
+
+ + No Solr RootPages configured + +
+
- - - - - - - + + + + + + + diff --git a/Resources/Private/Templates/Solr/ShowClearIndexForm.html b/Resources/Private/Templates/Solr/ShowClearIndexForm.html index ec986b1..4b6f8a4 100644 --- a/Resources/Private/Templates/Solr/ShowClearIndexForm.html +++ b/Resources/Private/Templates/Solr/ShowClearIndexForm.html @@ -38,7 +38,7 @@

Choose which index should be cleared

- + diff --git a/Resources/Public/JavaScript/ClearFullIndex.js b/Resources/Public/JavaScript/ClearFullIndex.js deleted file mode 100644 index 55a789a..0000000 --- a/Resources/Public/JavaScript/ClearFullIndex.js +++ /dev/null @@ -1,141 +0,0 @@ -/* - * This file is part of the jwtools2 project. - * - * It is free software; you can redistribute it and/or modify it under - * the terms of the GNU General Public License, either version 2 - * of the License, or any later version. - * - * For the full copyright and license information, please read the - * LICENSE.txt file that was distributed with this source code. - * - * The TYPO3 project - inspiring people to share! - */ - -/** - * Module: TYPO3/CMS/Jwtools2/ClearFullIndex - */ -define(['jquery', - 'TYPO3/CMS/Backend/Icons', - 'TYPO3/CMS/Backend/Notification' - ], function($, Icons, Notification) { - let ClearIndex = { - me: this - }; - - ClearIndex.clearIndexAction = function() { - let $activeRows = $('table>tbody>tr'); - - if ($activeRows.length > 0) { - ClearIndex.clearIndexByRows($activeRows, function($row, status, data, response) { - if (status === 'success') { - Icons.getIcon("status-status-permission-granted", Icons.sizes.small).done(function(ok) { - $row.find('span.icon').replaceWith(ok); - }); - } else if (status === 'error') { - alert('Error'); - } else if (status === 'finished') { - ClearIndex.displaySuccess('Index of all Sites has been cleared'); - } - }); - } - }; - - /** - * Clear index by rows - * - * @param {Object} rows - * @param {function} callback - */ - ClearIndex.clearIndexByRows = function(rows, callback) { - if (rows) { - rows = $(rows).toArray(); - let $row = $(rows.shift()); - let data = { - 'rootPageUid': $row.find(".rootPageUid").data("rootPageUid"), - configurationNames: [], - clear: [] - }; - $("input.configurationNames:checked").each(function() { - data.configurationNames.push($(this).val()); - }); - $("input.clear:checked").each(function() { - data.clear.push($(this).val()); - }); - - $row.find("div.status").show(); - ClearIndex.clearIndexByRow(data, function(status, data, response) { - callback($row, status, data, response); - if (status === 'success') { - if (rows.length) { - ClearIndex.clearIndexByRows(rows, callback); - } else { - callback($row, 'finished', data, response); - } - } - }); - } - }; - - /** - * Clear index by row - * - * @param {Object} data - * @param {function} callback - */ - ClearIndex.clearIndexByRow = function(data, callback) { - ClearIndex.executeAjaxRequest(TYPO3.settings.ajaxUrls['jwtools2_clearIndex'], data, function(response, status) { - if (status === 'success' && response.success) { - callback('success', data, response); - } else { - callback('error', data, response); - } - }); - }; - - /** - * Execute AJAX request - * - * @param {String} uri - * @param {Object} data - * @param {function} callback - */ - ClearIndex.executeAjaxRequest = function(uri, data, callback) { - let newData = { - tx_jwtools2: data - }; - ClearIndex.currentRequest = $.ajax({ - type: 'POST', - cache: false, - url: uri, - data: newData, - dataType: 'json', - success: function(response, status) { - if (typeof callback === 'function') { - callback(response, status); - } - }, - error: function(response, status) { - if (typeof callback === 'function') { - callback(response, status); - } - } - }); - }; - - /** - * Display success flash message - * - * @param {String} label - */ - ClearIndex.displaySuccess = function(label) { - if (typeof label === 'string' && label !== '') { - Notification.success('Success', label); - } - }; - - let $button = $("#clearFullIndex"); - $button.on("click", function(event) { - event.preventDefault(); - ClearIndex.clearIndexAction(); - }); -}); diff --git a/Resources/Public/JavaScript/clear-full-index.js b/Resources/Public/JavaScript/clear-full-index.js index 1e78680..346bb29 100644 --- a/Resources/Public/JavaScript/clear-full-index.js +++ b/Resources/Public/JavaScript/clear-full-index.js @@ -1,21 +1,11 @@ -/* - * This file is part of the jwtools2 project. - * - * It is free software; you can redistribute it and/or modify it under - * the terms of the GNU General Public License, either version 2 - * of the License, or any later version. - * - * For the full copyright and license information, please read the - * LICENSE.txt file that was distributed with this source code. - * - * The TYPO3 project - inspiring people to share! - */ -import { getIcon } from 'TYPO3/CMS/Backend/Icons'; -import { success as showSuccessNotification } from 'TYPO3/CMS/Backend/Notification'; +import Icons from "@typo3/backend/icons.js"; +import Notification from "@typo3/backend/notification.js"; +/** + * Module: @jweiland/jwtools2/clear-full-index + */ class ClearIndex { constructor() { - alert('here'); this.clearIndexAction = this.clearIndexAction.bind(this); this.clearIndexByRows = this.clearIndexByRows.bind(this); this.clearIndexByRow = this.clearIndexByRow.bind(this); @@ -50,11 +40,14 @@ class ClearIndex { this.executeAjaxRequest(TYPO3.settings.ajaxUrls['jwtools2_clearIndex'], data) .then(response => { if (response.success) { - getIcon("status-status-permission-granted", "small") + Icons.getIcon("status-status-permission-granted", Icons.sizes.small) .then(ok => { const iconSpan = row.querySelector('span.icon'); if (iconSpan) { - iconSpan.parentNode.replaceChild(ok, iconSpan); + const newIcon = document.createElement('span'); + newIcon.innerHTML = ok; + iconSpan.parentNode.replaceChild(newIcon, iconSpan); + this.displaySuccess('Index of all Sites has been cleared'); } }) .catch(error => { @@ -70,21 +63,23 @@ class ClearIndex { } executeAjaxRequest(uri, data) { - const newData = { tx_jwtools2: data }; + const formData = new URLSearchParams(); + Object.entries(data).forEach(([key, value]) => { + formData.append(key, value); + }); return fetch(uri, { method: 'POST', cache: 'no-cache', - body: JSON.stringify(newData), + body: formData, headers: { - 'Content-Type': 'application/json' - } - }) - .then(response => response.json()); + 'Content-Type': 'application/x-www-form-urlencoded' + }, + }).then(response => response.json()); } displaySuccess(label) { if (typeof label === 'string' && label !== '') { - showSuccessNotification('Success', label); + Notification.success('Success', label); } } } diff --git a/Resources/Public/JavaScript/solr-backend-module.js b/Resources/Public/JavaScript/solr-backend-module.js index 6c465a5..6cf4d55 100644 --- a/Resources/Public/JavaScript/solr-backend-module.js +++ b/Resources/Public/JavaScript/solr-backend-module.js @@ -30,18 +30,14 @@ class SolrIndex { showSolrProgress() { if (this.activeRows.length > 0) { this.processRows('jwtools2_getSolrProgress', (row, status, data, response) => { - console.log(status); if (status === 'success') { - console.log(response); row.querySelector('.status').innerHTML = `
${response.progress}% Complete
`; } else if (status === 'error') { - console.log('Error'); this.displayError(); } else if (status === 'finished') { - console.log(response); this.displaySuccess('Solr Status all all Sites has been updated'); } }); From 828a201852f38704561dc2e96a1e843842e14177 Mon Sep 17 00:00:00 2001 From: Hoja Mustaffa Abdul Latheef Date: Fri, 22 Mar 2024 16:21:36 +0100 Subject: [PATCH 50/65] [TASK] Refactor `typo3RequiredColumnsForFiles` functionality - Deleted Classes/Backend/Browser/FileBrowser.php as now it is not compatible - Moved logic to PSR-14 event `IsFileSelectableEvent` - Removed unwanted configurations and settings from ext_localconf - Updated documentations --- Classes/Backend/Browser/FileBrowser.php | 273 ------------------ Classes/Controller/SolrController.php | 3 - .../IsFileSelectableEventListener.php | 208 +++++++++++++ .../EventListener/ModifyLinkEventListener.php | 31 -- .../Hooks/ModifyElementInformationHook.php | 20 +- Configuration/Services.yaml | 17 +- Configuration/page.tsconfig | 1 + Documentation/AdministratorManual/Index.rst | 18 ++ .../AdministratorManual/Upgrade/Index.rst | 15 + Documentation/ChangeLog/Index.rst | 2 + .../Templates/File.html | 0 .../Extensions/FileList/Templates/Folder.html | 39 +++ .../Recordlist/Templates/Folder.html | 39 --- ext_conf_template.txt | 2 - ext_localconf.php | 26 -- 15 files changed, 300 insertions(+), 394 deletions(-) delete mode 100644 Classes/Backend/Browser/FileBrowser.php create mode 100644 Classes/EventListener/IsFileSelectableEventListener.php delete mode 100644 Classes/EventListener/ModifyLinkEventListener.php create mode 100644 Configuration/page.tsconfig create mode 100644 Documentation/AdministratorManual/Index.rst create mode 100644 Documentation/AdministratorManual/Upgrade/Index.rst rename Resources/Private/Extensions/{Recordlist => FileList}/Templates/File.html (100%) create mode 100644 Resources/Private/Extensions/FileList/Templates/Folder.html delete mode 100644 Resources/Private/Extensions/Recordlist/Templates/Folder.html diff --git a/Classes/Backend/Browser/FileBrowser.php b/Classes/Backend/Browser/FileBrowser.php deleted file mode 100644 index 3afda44..0000000 --- a/Classes/Backend/Browser/FileBrowser.php +++ /dev/null @@ -1,273 +0,0 @@ -getRequiredColumnsFromExtensionConfiguration()) { - $flashMessageService = GeneralUtility::makeInstance(FlashMessageService::class); - $flashMessageQueue = $flashMessageService->getMessageQueueByIdentifier(); - $flashMessageQueue->addMessage( - GeneralUtility::makeInstance( - FlashMessage::class, - LocalizationUtility::translate( - 'LLL:EXT:jwtools2/Resources/Private/Language/locallang_mod.xlf:fileBrowser.flashMessage.requiredColumns.description', - null, - [ - implode( - ', ', - $this->getTranslatedColumnNames( - $this->getRequiredColumnsFromExtensionConfiguration() - ) - ) - ] - ), - LocalizationUtility::translate( - 'LLL:EXT:jwtools2/Resources/Private/Language/locallang_mod.xlf:fileBrowser.flashMessage.requiredColumns.title' - ), - AbstractMessage::INFO - ) - ); - } - - return true; - } - - return false; - } - - protected function getTranslatedColumnNames(array $requiredColumns): array - { - if (!$this->getLanguageService() instanceof LanguageService) { - return $requiredColumns; - } - - foreach ($requiredColumns as $key => $requiredColumn) { - $label = BackendUtility::getItemLabel('sys_file', $requiredColumn); - if ($label === '' || $label === null) { - $label = BackendUtility::getItemLabel('sys_file_metadata', $requiredColumn); - } - - if ($label === '' || $label === null) { - continue; - } - - $translatedLabel = $this->getLanguageService()->sL($label); - if ($translatedLabel === '' || $translatedLabel === null) { - continue; - } - - $requiredColumns[$key] = $translatedLabel; - } - - return $requiredColumns; - } - - protected function fileIsSelectableInFileList(FileInterface $file, array $imgInfo): bool - { - // Return true, if there are no columns to skip. - if ($this->getRequiredColumnsFromExtensionConfiguration() === []) { - return true; - } - - // Do not process folders or processed files - if (!$file instanceof File) { - return true; - } - - // Process only images - if ($file->getType() !== 2) { - return true; - } - - foreach ($this->getRequiredColumnsForFileMetaData() as $requiredColumn) { - $properties = $file->getProperties(); - - // Do not use isset() as "null" values have to be tested, too. - if (!array_key_exists($requiredColumn, $properties)) { - return false; - } - - $value = is_string($properties[$requiredColumn]) - ? trim($properties[$requiredColumn]) - : $properties[$requiredColumn]; - - if (!isset($value) || trim($value) === '') { - return false; - } - } - - return true; - } - - /** - * This method must exist, as this method will be checked by method_exists in ElementBrowserController - */ - public function render(): string - { - if (is_callable([$this, 'setRequest'])) { - $this->setRequest($GLOBALS['TYPO3_REQUEST']); - } - - if (!$this->isShowUploadFieldsInTopOfEB()) { - return parent::render(); - } - - $typo3Version = GeneralUtility::makeInstance(Typo3Version::class); - if (version_compare($typo3Version->getBranch(), '11.5', '=')) { - //

is the first header. It's before the three following forms: searchForm, uploadForm and createForm - // Do not remove empty values. In same cases $top contains just spaces/tabs. - [$top, $content] = GeneralUtility::trimExplode('

)(?P
\v<\/div>)(?P
.*<\/table> <\/div>)(?P)(?P)/usm'; - if (preg_match($pattern, '

is the first header. It's before the three following forms: searchForm, uploadForm and createForm - [$top, $content] = GeneralUtility::trimExplode('

', parent::render(), true, 2); - $pattern = '/(?P

.*?<\/h3>)(?P)(?P
.*<\/div>)(?P)(?P)/usm'; - if (preg_match($pattern, '

' . $content, $matches)) { - return sprintf( - '%s%s%s%s%s%s', - $top, - $matches['uploadForm'], - $matches['createForm'], - $matches['header'], - $matches['searchForm'], - $matches['fileList'] - ); - } - - return $top . '

' . $content; - } - - protected function getRequiredColumnsForFileMetaData(): array - { - // Cache result, is this method will be called from within a loop - static $requiredColumns = null; - - if ($requiredColumns === null) { - $validColumns = []; - foreach ($this->getRequiredColumnsFromExtensionConfiguration() as $column) { - if ($this->isValidColumn($column)) { - $validColumns[] = $column; - } - } - $requiredColumns = $validColumns; - } - - return $requiredColumns; - } - - protected function getRequiredColumnsFromExtensionConfiguration(): array - { - static $requiredColumns = null; - - if ($requiredColumns === null) { - try { - $requiredColumns = GeneralUtility::trimExplode( - ',', - $this->extensionConfiguration->get('jwtools2', 'typo3RequiredColumnsForFiles'), - true - ); - } catch (ExtensionConfigurationExtensionNotConfiguredException | ExtensionConfigurationPathDoesNotExistException $exception) { - } - } - - return $requiredColumns; - } - - protected function isShowUploadFieldsInTopOfEB(): bool - { - try { - return (bool)$this->extensionConfiguration->get('jwtools2', 'typo3UploadFieldsInTopOfEB'); - } catch (ExtensionConfigurationExtensionNotConfiguredException | ExtensionConfigurationPathDoesNotExistException $exception) { - } - - return false; - } - - protected function isValidColumn(string $column, string $table = 'sys_file'): bool - { - $columnExists = false; - $connection = $this->getConnectionPool()->getConnectionForTable($table); - $schemaManager = $connection->getSchemaManager(); - if ( - $schemaManager instanceof AbstractSchemaManager - && $schemaManager->tablesExist($table) - ) { - $columnExists = $schemaManager->listTableDetails($table)->hasColumn($column); - if ($columnExists === false && $table !== 'sys_file_metadata') { - $columnExists = $this->isValidColumn($column, 'sys_file_metadata'); - } - } - - return $columnExists; - } - - protected function getConnectionPool(): ConnectionPool - { - return GeneralUtility::makeInstance(ConnectionPool::class); - } -} diff --git a/Classes/Controller/SolrController.php b/Classes/Controller/SolrController.php index c99f85d..de8c3a6 100644 --- a/Classes/Controller/SolrController.php +++ b/Classes/Controller/SolrController.php @@ -25,7 +25,6 @@ use TYPO3\CMS\Backend\Attribute\AsController; use TYPO3\CMS\Core\Database\Connection; use TYPO3\CMS\Core\Database\ConnectionPool; -use TYPO3\CMS\Core\Page\PageRenderer; use TYPO3\CMS\Core\Type\ContextualFeedbackSeverity; use TYPO3\CMS\Core\Utility\ArrayUtility; use TYPO3\CMS\Core\Utility\GeneralUtility; @@ -203,8 +202,6 @@ public function clearIndexAction(int $rootPageUid, array $configurationNames, ar public function showClearFullIndexFormAction(): ResponseInterface { $this->pageRenderer->loadJavaScriptModule('@jweiland/jwtools2/clear-full-index.js'); - //$pageRenderer->loadRequireJsModule('TYPO3/CMS/Jwtools2/ClearFullIndex'); - $configurationNamesOfAllSites = []; $sites = $this->solrRepository->findAllAvailableSites(); foreach ($sites as $site) { diff --git a/Classes/EventListener/IsFileSelectableEventListener.php b/Classes/EventListener/IsFileSelectableEventListener.php new file mode 100644 index 0000000..dd53063 --- /dev/null +++ b/Classes/EventListener/IsFileSelectableEventListener.php @@ -0,0 +1,208 @@ +getRequiredColumnsFromExtensionConfiguration()) { + $flashMessageService = GeneralUtility::makeInstance(FlashMessageService::class); + $flashMessageQueue = $flashMessageService->getMessageQueueByIdentifier(); + $message = $this->getFlashMessageDescription($requiredColumns); + + if (!$this->checkMessageExists($flashMessageQueue, $message)) { + $this->addFlashMessage($flashMessageQueue, $message); + } + + if (!$event->getFile() instanceof File) { + // Do not process folders or processed files + return; + } + + if ($event->getFile()->getType() !== 2) { + // Process only images + return; + } + + foreach ($this->getRequiredColumnsForFileMetaData() as $requiredColumn) { + $properties = $event->getFile()->getProperties(); + + // Do not use isset() as "null" values have to be tested, too. + if (!array_key_exists($requiredColumn, $properties)) { + $event->denyFileSelection(); + } + + $value = is_string($properties[$requiredColumn]) + ? trim($properties[$requiredColumn]) + : $properties[$requiredColumn]; + + if (!isset($value) || trim($value) === null || trim($value) === '') { + $event->denyFileSelection(); + } + } + } + } + + protected function addFlashMessage(FlashMessageQueue $flashMessageQueue, string $message): void + { + $flashMessageQueue->addMessage( + GeneralUtility::makeInstance( + FlashMessage::class, + $message, + LocalizationUtility::translate( + 'LLL:EXT:jwtools2/Resources/Private/Language/locallang_mod.xlf:fileBrowser.flashMessage.requiredColumns.title' + ), + ContextualFeedbackSeverity::INFO + ) + ); + } + + protected function getFlashMessageDescription(array $requiredColumns): string + { + return LocalizationUtility::translate( + 'LLL:EXT:jwtools2/Resources/Private/Language/locallang_mod.xlf:fileBrowser.flashMessage.requiredColumns.description', + null, + [ + implode( + ', ', + $this->getTranslatedColumnNames( + $requiredColumns + ) + ), + ] + ); + } + + protected function getTranslatedColumnNames(array $requiredColumns): array + { + if (!$this->getLanguageService() instanceof LanguageService) { + return $requiredColumns; + } + + foreach ($requiredColumns as $key => $requiredColumn) { + $label = BackendUtility::getItemLabel('sys_file', $requiredColumn); + if ($label === '' || $label === null) { + $label = BackendUtility::getItemLabel('sys_file_metadata', $requiredColumn); + } + + if ($label === '' || $label === null) { + continue; + } + + $translatedLabel = $this->getLanguageService()->sL($label); + if ($translatedLabel === '' || $translatedLabel === null) { + continue; + } + + $requiredColumns[$key] = $translatedLabel; + } + + return $requiredColumns; + } + + protected function getRequiredColumnsForFileMetaData(): array + { + // Cache result, is this method will be called from within a loop + static $requiredColumns = null; + + if ($requiredColumns === null) { + $validColumns = []; + foreach ($this->getRequiredColumnsFromExtensionConfiguration() as $column) { + if ($this->isValidColumn($column)) { + $validColumns[] = $column; + } + } + $requiredColumns = $validColumns; + } + + return $requiredColumns; + } + + protected function getRequiredColumnsFromExtensionConfiguration(): array + { + static $requiredColumns = null; + + if ($requiredColumns === null) { + try { + $requiredColumns = GeneralUtility::trimExplode( + ',', + $this->extensionConfiguration->get('jwtools2', 'typo3RequiredColumnsForFiles'), + true + ); + } catch (ExtensionConfigurationExtensionNotConfiguredException|ExtensionConfigurationPathDoesNotExistException $exception) { + } + } + + return $requiredColumns; + } + + protected function isValidColumn(string $column, string $table = 'sys_file'): bool + { + $columnExists = false; + $connection = $this->getConnectionPool()->getConnectionForTable($table); + $schemaManager = $connection->createSchemaManager(); + if ( + $schemaManager->tablesExist($table) + ) { + $columnExists = $schemaManager->introspectTable($table)->hasColumn($column); + if ($columnExists === false && $table !== 'sys_file_metadata') { + $columnExists = $this->isValidColumn($column, 'sys_file_metadata'); + } + } + + return $columnExists; + } + + protected function checkMessageExists(FlashMessageQueue $flashMessageQueue, string $message): bool + { + $messageExists = false; + foreach ($flashMessageQueue as $flashMessage) { + if ($flashMessage->getMessage() === $message) { + $messageExists = true; + break; + } + } + return $messageExists; + } + + protected function getLanguageService(): LanguageService + { + return $GLOBALS['LANG']; + } + + protected function getConnectionPool(): ConnectionPool + { + return GeneralUtility::makeInstance(ConnectionPool::class); + } +} diff --git a/Classes/EventListener/ModifyLinkEventListener.php b/Classes/EventListener/ModifyLinkEventListener.php deleted file mode 100644 index f675045..0000000 --- a/Classes/EventListener/ModifyLinkEventListener.php +++ /dev/null @@ -1,31 +0,0 @@ -overrideFileLinkHandler($event); - } - - private function overrideFileLinkHandler($event): void - { - $fileHandler = $event->getLinkHandler('file.'); - if ($fileHandler['handler'] === 'TYPO3\CMS\Filelist\LinkHandler\FileLinkHandler') { - $fileHandler['handler'] = FileLinkHandler::class; - } - $event->setLinkHandler('file.', $fileHandler); - } -} diff --git a/Classes/Hooks/ModifyElementInformationHook.php b/Classes/Hooks/ModifyElementInformationHook.php index 68cafea..612eddc 100644 --- a/Classes/Hooks/ModifyElementInformationHook.php +++ b/Classes/Hooks/ModifyElementInformationHook.php @@ -253,7 +253,7 @@ protected function getPreview(ServerRequestInterface $request): array $fileMetaUid => 'edit' ] ], - 'returnUrl' => $request->getAttribute('normalizedParams')->getRequestUri() + 'returnUrl' => $request->getAttribute('normalizedParams')->getRequestUrl() ]; $preview['editUrl'] = (string)$this->uriBuilder->buildUriFromRoute('record_edit', $urlParameters); } @@ -507,7 +507,7 @@ protected function getReferences(ServerRequestInterface $request): array /** * Get field name for specified table/column name */ - protected function getLabelForTableColumn(string $tableName, string $fieldName): string + protected function getLabelForTableColumnByTable(string $tableName, string $fieldName): string { if (($GLOBALS['TCA'][$tableName]['columns'][$fieldName]['label'] ?? null) !== null) { $field = $this->getLanguageService()->sL($GLOBALS['TCA'][$tableName]['columns'][$fieldName]['label']); @@ -538,20 +538,20 @@ protected function getRecordActions(string $table, int $uid, ServerRequestInterf $uid => 'edit', ], ], - 'returnUrl' => $request->getAttribute('normalizedParams')->getRequestUri(), + 'returnUrl' => $request->getAttribute('normalizedParams')->getRequestUrl(), ]; $actions['recordEditUrl'] = (string)$this->uriBuilder->buildUriFromRoute('record_edit', $urlParameters); // History button $urlParameters = [ 'element' => $table . ':' . $uid, - 'returnUrl' => $request->getAttribute('normalizedParams')->getRequestUri(), + 'returnUrl' => $request->getAttribute('normalizedParams')->getRequestUrl(), ]; $actions['recordHistoryUrl'] = (string)$this->uriBuilder->buildUriFromRoute('record_history', $urlParameters); if ($table === 'pages') { // Recordlist button - $actions['webListUrl'] = (string)$this->uriBuilder->buildUriFromRoute('web_list', ['id' => $uid, 'returnUrl' => $request->getAttribute('normalizedParams')->getRequestUri()]); + $actions['webListUrl'] = (string)$this->uriBuilder->buildUriFromRoute('web_list', ['id' => $uid, 'returnUrl' => $request->getAttribute('normalizedParams')->getRequestUrl()]); // View page button $actions['viewOnClick'] = PreviewUriBuilder::create($uid)->buildDispatcherDataAttributes(); @@ -631,7 +631,7 @@ protected function makeRef(string $table, File|int $ref, ServerRequestInterface $row['recuid'] => 'edit', ], ], - 'returnUrl' => $request->getAttribute('normalizedParams')->getRequestUri(), + 'returnUrl' => $request->getAttribute('normalizedParams')->getRequestUrl(), ]; $url = (string)$this->uriBuilder->buildUriFromRoute('record_edit', $urlParameters); $line['url'] = $url; @@ -642,13 +642,13 @@ protected function makeRef(string $table, File|int $ref, ServerRequestInterface $line['parentRecord'] = $parentRecord; $line['parentRecordTitle'] = $parentRecordTitle; $line['title'] = $lang->sL($GLOBALS['TCA'][$row['tablename']]['ctrl']['title']); - $line['labelForTableColumn'] = $this->getLabelForTableColumn($row['tablename'], $row['field']); + $line['labelForTableColumn'] = $this->getLabelForTableColumnByTable($row['tablename'], $row['field']); $line['path'] = BackendUtility::getRecordPath($record['pid'], '', 0, 0); $line['actions'] = $this->getRecordActions($row['tablename'], $row['recuid'], $request); } else { $line['row'] = $row; $line['title'] = $lang->sL($GLOBALS['TCA'][$row['tablename']]['ctrl']['title'] ?? '') ?: $row['tablename']; - $line['labelForTableColumn'] = $this->getLabelForTableColumn($row['tablename'], $row['field']); + $line['labelForTableColumn'] = $this->getLabelForTableColumnByTable($row['tablename'], $row['field']); } $refLines[] = $line; } @@ -716,13 +716,13 @@ protected function makeRefFrom(string $table, int $ref, ServerRequestInterface $ $line['record'] = $record; $line['recordTitle'] = BackendUtility::getRecordTitle($row['ref_table'], $record, false, true); $line['title'] = $lang->sL($GLOBALS['TCA'][$row['ref_table']]['ctrl']['title'] ?? ''); - $line['labelForTableColumn'] = $this->getLabelForTableColumn($table, $row['field']); + $line['labelForTableColumn'] = $this->getLabelForTableColumnByTable($table, $row['field']); $line['path'] = BackendUtility::getRecordPath($record['pid'], '', 0, 0); $line['actions'] = $this->getRecordActions($row['ref_table'], $row['ref_uid'], $request); } else { $line['row'] = $row; $line['title'] = $lang->sL($GLOBALS['TCA'][$row['ref_table']]['ctrl']['title'] ?? ''); - $line['labelForTableColumn'] = $this->getLabelForTableColumn($table, $row['field']); + $line['labelForTableColumn'] = $this->getLabelForTableColumnByTable($table, $row['field']); } $refFromLines[] = $line; } diff --git a/Configuration/Services.yaml b/Configuration/Services.yaml index 8cb398e..f4d6976 100644 --- a/Configuration/Services.yaml +++ b/Configuration/Services.yaml @@ -7,10 +7,6 @@ services: JWeiland\Jwtools2\: resource: '../Classes/*' - # Called by makeInstance in main of ElementBrowserController - #JWeiland\Jwtools2\Backend\Browser\FileBrowser: - # public: true - # Called by makeInstance in getCallableFromTarget of Dispatcher JWeiland\Jwtools2\Controller\Ajax\SysFileController: public: true @@ -38,9 +34,9 @@ services: public: true # Element Browser should be registered with tags `recordlist.elementbrowser` - #JWeiland\Jwtools2\Backend\Browser\FileBrowser: - # tags: - # - name: recordlist.elementbrowser + JWeiland\Jwtools2\Backend\Browser\FileBrowser: + tags: + - name: recordlist.elementbrowser JWeiland\Jwtools2\LinkHandler\FileLinkHandler: public: true @@ -59,11 +55,12 @@ services: - name: event.listener identifier: 'jwtools2.events.beforeItemIsIndexedEvent' event: ApacheSolrForTypo3\Solr\Event\Indexing\BeforeItemIsIndexedEvent - JWeiland\Jwtools2\EventListener\ModifyLinkEventListener: + + JWeiland\Jwtools2\EventListener\IsFileSelectableEventListener: tags: - name: event.listener - identifier: 'jwtools2.events.modifyLinksEventListener' - event: TYPO3\CMS\Backend\Controller\Event\ModifyLinkHandlersEvent + identifier: 'jwtools2.events.isFileSelectableEvent' + event: TYPO3\CMS\Backend\ElementBrowser\Event\IsFileSelectableEvent # Backend Context Menu Provider JWeiland\Jwtools2\ContextMenu\ItemProviders\UpdateFileMetaDataProvider: diff --git a/Configuration/page.tsconfig b/Configuration/page.tsconfig new file mode 100644 index 0000000..e0f6bfd --- /dev/null +++ b/Configuration/page.tsconfig @@ -0,0 +1 @@ +templates.typo3/cms-filelist.1710898891 = jweiland/jwtools2:Resources/Private/Extensions/FileList/Templates diff --git a/Documentation/AdministratorManual/Index.rst b/Documentation/AdministratorManual/Index.rst new file mode 100644 index 0000000..819be0e --- /dev/null +++ b/Documentation/AdministratorManual/Index.rst @@ -0,0 +1,18 @@ +.. include:: /Includes.rst.txt + + +.. _admin-manual: + +==================== +Administrator manual +==================== + +.. only:: html + + This chapter describes how to manage the extension from a superuser point of view. + +.. toctree:: + :maxdepth: 2 + :titlesonly: + + Upgrade/Index diff --git a/Documentation/AdministratorManual/Upgrade/Index.rst b/Documentation/AdministratorManual/Upgrade/Index.rst new file mode 100644 index 0000000..34d7bfb --- /dev/null +++ b/Documentation/AdministratorManual/Upgrade/Index.rst @@ -0,0 +1,15 @@ +.. include:: /Includes.rst.txt + + +======= +Upgrade +======= + +If you upgrade EXT:jwtools2 to a newer version, please read this section carefully! + +Upgrade to Version 7.0.0 +========================= + +This version is not TYPO3 11 compatible! + +We removed diff --git a/Documentation/ChangeLog/Index.rst b/Documentation/ChangeLog/Index.rst index f731329..b60a12e 100644 --- a/Documentation/ChangeLog/Index.rst +++ b/Documentation/ChangeLog/Index.rst @@ -17,6 +17,8 @@ Version 7.0.0 * [TASK] Testing Framework migrated to TYPO3 Tesing Framework * [TASK] Remove support for TYPO3 11 and lower versions * [TASK] Removed jwtools2:executeExtensionUpdate command line controller as it is obsolete. +* [TASK] Removed deprecated functions and usages + Version 6.0.6 ============= diff --git a/Resources/Private/Extensions/Recordlist/Templates/File.html b/Resources/Private/Extensions/FileList/Templates/File.html similarity index 100% rename from Resources/Private/Extensions/Recordlist/Templates/File.html rename to Resources/Private/Extensions/FileList/Templates/File.html diff --git a/Resources/Private/Extensions/FileList/Templates/Folder.html b/Resources/Private/Extensions/FileList/Templates/Folder.html new file mode 100644 index 0000000..3e4aab8 --- /dev/null +++ b/Resources/Private/Extensions/FileList/Templates/Folder.html @@ -0,0 +1,39 @@ + + + + + + + + + +

+
+ + + {selectedFolderIcon -> f:format.raw()} {selectedFolderTitle} + + +
+ {selectedFolderIcon -> f:format.raw()} {selectedFolderTitle} +
+
+
+ + + +
+
+ {createFolderForm -> f:format.raw()} +
diff --git a/Resources/Private/Extensions/Recordlist/Templates/Folder.html b/Resources/Private/Extensions/Recordlist/Templates/Folder.html deleted file mode 100644 index 098fd99..0000000 --- a/Resources/Private/Extensions/Recordlist/Templates/Folder.html +++ /dev/null @@ -1,39 +0,0 @@ - - - - - - - - - {createFolderForm -> f:format.raw()} - -

-
- - - {selectedFolderIcon -> f:format.raw()} {selectedFolderTitle} - - -
- {selectedFolderIcon -> f:format.raw()} {selectedFolderTitle} -
-
-
- - - -
-
-
diff --git a/ext_conf_template.txt b/ext_conf_template.txt index 2dc2238..c5a6440 100644 --- a/ext_conf_template.txt +++ b/ext_conf_template.txt @@ -24,8 +24,6 @@ enableSqlQueryTask = 0 enableContextMenuToUpdateFileMetadata = 0 # cat=typo3; type=boolean; label=LLL:EXT:jwtools2/Resources/Private/Language/ExtConf.xlf:enableCachingFrameworkLogger enableCachingFrameworkLogger = 0 -# cat=reports; type=boolean; label=LLL:EXT:jwtools2/Resources/Private/Language/ExtConf.xlf:enableReportProvider -enableReportProvider = 0 # cat=reports; type=options[Info=info,Warning=warning]; label=LLL:EXT:jwtools2/Resources/Private/Language/ExtConf.xlf:sendUpdatableExtensionsWithSeverity sendUpdatableExtensionsWithSeverity = info diff --git a/ext_localconf.php b/ext_localconf.php index 71a9dba..234b2ff 100644 --- a/ext_localconf.php +++ b/ext_localconf.php @@ -8,9 +8,7 @@ use JWeiland\Jwtools2\Hooks\CachingFrameworkLoggerHook; use JWeiland\Jwtools2\Hooks\InitializeStdWrap; use JWeiland\Jwtools2\Hooks\ModifyElementInformationHook; -use JWeiland\Jwtools2\Hooks\ModifyLinkHandlerHook; use JWeiland\Jwtools2\Hooks\MoveTranslatedContentElementsHook; -use JWeiland\Jwtools2\Provider\ReportProvider; use JWeiland\Jwtools2\Routing\Aspect\PersistedTableMapper; use JWeiland\Jwtools2\Task\ExecuteQueryTask; use JWeiland\Jwtools2\Task\ExecuteQueryTaskAdditionalFieldProvider; @@ -62,22 +60,6 @@ ); } - // @todo: Removed this Hook in TYPO3 12 it must be implemented with new ElementBrowser API or alternative - if ( - ($jwToolsConfiguration['typo3RequiredColumnsForFiles'] ?? false) - || ($jwToolsConfiguration['typo3UploadFieldsInTopOfEB'] ?? false) - ) { - //$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['ElementBrowsers']['jwtools2_file'] - // = \JWeiland\Jwtools2\Backend\Browser\FileBrowser::class; - } - // @todo: Removed this Hook in TYPO3 12 moved the logic to EventListener - if ($jwToolsConfiguration['typo3UploadFieldsInTopOfEB'] ?? false) { - // For LinkHandler: overwrite TYPO3's LinkHandlers - $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['LinkBrowser']['hooks']['jwtools2'] = [ - 'handler' => ModifyLinkHandlerHook::class - ]; - } - if ($jwToolsConfiguration['typo3ShowEditButtonInElementInformation'] ?? false) { $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['typo3/show_item.php']['typeRendering']['jwtools'] = ModifyElementInformationHook::class; @@ -103,14 +85,6 @@ = CachingFrameworkLoggerHook::class . '->analyze'; } - if ( - ($jwToolsConfiguration['enableReportProvider'] ?? false) - && ExtensionManagementUtility::isLoaded('reports') - ) { - $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['reports']['tx_reports']['status']['providers']['jwtools2'][] - = ReportProvider::class; - } - // Retrieve stdWrap current value into sub cObj. CONTENT $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['tslib/class.tslib_content.php']['postInit']['jwtools2_initStdWrap'] = InitializeStdWrap::class; From 6ba72075ec9fa212c7e51a90ec848cd349533332 Mon Sep 17 00:00:00 2001 From: Hoja Mustaffa Abdul Latheef Date: Mon, 25 Mar 2024 01:11:08 +0100 Subject: [PATCH 51/65] Documentation added with update details and fixed issue with uid type --- .../Hooks/ModifyElementInformationHook.php | 6 ++--- Configuration/Services.yaml | 5 ---- .../AdministratorManual/Upgrade/Index.rst | 25 +++++++++++++++++-- Documentation/Index.rst | 1 + 4 files changed, 27 insertions(+), 10 deletions(-) diff --git a/Classes/Hooks/ModifyElementInformationHook.php b/Classes/Hooks/ModifyElementInformationHook.php index 612eddc..78d60e8 100644 --- a/Classes/Hooks/ModifyElementInformationHook.php +++ b/Classes/Hooks/ModifyElementInformationHook.php @@ -51,7 +51,7 @@ class ModifyElementInformationHook { protected string $table; - protected int $uid; + protected string $uid; protected string $permsClause; @@ -97,6 +97,7 @@ public function isValid(string $type, ElementInformationController $elementInfor public function render(string $type, ElementInformationController $elementInformationController): string { $this->init($GLOBALS['TYPO3_REQUEST']); + return $this->main($GLOBALS['TYPO3_REQUEST']); } @@ -107,9 +108,8 @@ public function render(string $type, ElementInformationController $elementInform protected function init(ServerRequestInterface $request): void { $queryParams = $request->getQueryParams(); - $this->table = $queryParams['table'] ?? null; - $this->uid = (int)$queryParams['uid'] ?? null; + $this->uid = $queryParams['uid'] ?? null; $this->permsClause = $this->getBackendUser()->getPagePermsClause(Permission::PAGE_SHOW); diff --git a/Configuration/Services.yaml b/Configuration/Services.yaml index f4d6976..c3599a6 100644 --- a/Configuration/Services.yaml +++ b/Configuration/Services.yaml @@ -33,11 +33,6 @@ services: JWeiland\Jwtools2\Hooks\InitializeStdWrap: public: true - # Element Browser should be registered with tags `recordlist.elementbrowser` - JWeiland\Jwtools2\Backend\Browser\FileBrowser: - tags: - - name: recordlist.elementbrowser - JWeiland\Jwtools2\LinkHandler\FileLinkHandler: public: true diff --git a/Documentation/AdministratorManual/Upgrade/Index.rst b/Documentation/AdministratorManual/Upgrade/Index.rst index 34d7bfb..8a8b1b9 100644 --- a/Documentation/AdministratorManual/Upgrade/Index.rst +++ b/Documentation/AdministratorManual/Upgrade/Index.rst @@ -10,6 +10,27 @@ If you upgrade EXT:jwtools2 to a newer version, please read this section careful Upgrade to Version 7.0.0 ========================= -This version is not TYPO3 11 compatible! +.. important:: + + This version is not TYPO3 11 compatible! + +Removed Option: `typo3UploadFieldsInTopOfEB` +-------------------------------------------- + +In the latest version of TYPO3, the `typo3UploadFieldsInTopOfEB` option has been removed. This change was necessitated +by the introduction of a paginator in File Abstraction Layer (FAL). As a result, it's no longer possible to adjust the +position of File upload or create fields above the list without Xclass. + +Compatibility Fixes and Updates +------------------------------- + +- Compatibility fix for TYPO3 12 +- Testing Framework migrated to TYPO3 Testing Framework + +Deprecated and Obsolete Features +-------------------------------- + +- Remove support for TYPO3 11 and lower versions +- Removed `jwtools2:executeExtensionUpdate` command line controller as it is obsolete. +- Removed deprecated functions and usages -We removed diff --git a/Documentation/Index.rst b/Documentation/Index.rst index f46d293..2e96d99 100644 --- a/Documentation/Index.rst +++ b/Documentation/Index.rst @@ -45,6 +45,7 @@ activated first, before using. So, only activate, what you really need. Installation/Index Configuration/Index KnownProblems/Index + AdministratorManual/Index Contribute/Index ChangeLog/Index Links From 2559481be556d16877e44e8608002aeb887fa341 Mon Sep 17 00:00:00 2001 From: Hoja Mustaffa Abdul Latheef Date: Mon, 25 Mar 2024 01:44:18 +0100 Subject: [PATCH 52/65] Fixed FTC issue with DI --- Classes/Command/StatusReportCommand.php | 4 ++-- Configuration/Services.yaml | 2 -- Tests/Functional/Hooks/InitializeStdWrapTest.php | 6 +----- 3 files changed, 3 insertions(+), 9 deletions(-) diff --git a/Classes/Command/StatusReportCommand.php b/Classes/Command/StatusReportCommand.php index ac9f5dd..4cc187d 100644 --- a/Classes/Command/StatusReportCommand.php +++ b/Classes/Command/StatusReportCommand.php @@ -38,11 +38,11 @@ class StatusReportCommand extends Command protected SymfonyStyle $ioStyled; - public function __construct(SchedulerTaskRepository $taskRepository) + public function __construct() { parent::__construct(); - $this->taskRepository = $taskRepository; + $this->taskRepository = GeneralUtility::makeInstance(SchedulerTaskRepository::class); } public function configure(): void diff --git a/Configuration/Services.yaml b/Configuration/Services.yaml index c3599a6..dd5e4a0 100644 --- a/Configuration/Services.yaml +++ b/Configuration/Services.yaml @@ -22,8 +22,6 @@ services: command: 'jwtools2:convertpasswords' schedulable: false JWeiland\Jwtools2\Command\StatusReportCommand: - arguments: - - '@TYPO3\CMS\Scheduler\Domain\Repository\SchedulerTaskRepository' tags: - name: 'console.command' command: 'jwtools2:statusreport' diff --git a/Tests/Functional/Hooks/InitializeStdWrapTest.php b/Tests/Functional/Hooks/InitializeStdWrapTest.php index c014a82..3bd2879 100644 --- a/Tests/Functional/Hooks/InitializeStdWrapTest.php +++ b/Tests/Functional/Hooks/InitializeStdWrapTest.php @@ -13,9 +13,7 @@ use JWeiland\Jwtools2\Hooks\InitializeStdWrap; use PHPUnit\Framework\MockObject\MockObject; use TYPO3\CMS\Core\Configuration\ExtensionConfiguration; -use TYPO3\CMS\Core\Utility\GeneralUtility; use TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer; -use TYPO3\CMS\Scheduler\Domain\Repository\SchedulerTaskRepository; use TYPO3\TestingFramework\Core\Functional\FunctionalTestCase; /** @@ -35,9 +33,6 @@ protected function setUp(): void { parent::setUp(); - $schedulerTaskRepository = GeneralUtility::makeInstance(SchedulerTaskRepository::class); - GeneralUtility::addInstance(SchedulerTaskRepository::class, $schedulerTaskRepository); - $this->extensionConfigurationMock = $this->getAccessibleMock(ExtensionConfiguration::class); $this->subject = new InitializeStdWrap( $this->extensionConfigurationMock @@ -147,6 +142,7 @@ public function postProcessWillModifyContentObject(): void $data = [ 'uid' => 123, + 'colPos' => 1, 'title' => 'Hello' ]; From 51d922fcbacc49427d60b616a3751559b22e5d6f Mon Sep 17 00:00:00 2001 From: Hoja Mustaffa Abdul Latheef Date: Mon, 25 Mar 2024 01:46:52 +0100 Subject: [PATCH 53/65] Removed Link Handlers as the logic moved now to the PSR-14 event listener --- Classes/LinkHandler/FileLinkHandler.php | 52 ------------------ Classes/LinkHandler/FolderLinkHandler.php | 66 ----------------------- 2 files changed, 118 deletions(-) delete mode 100644 Classes/LinkHandler/FileLinkHandler.php delete mode 100644 Classes/LinkHandler/FolderLinkHandler.php diff --git a/Classes/LinkHandler/FileLinkHandler.php b/Classes/LinkHandler/FileLinkHandler.php deleted file mode 100644 index 7bf6e2e..0000000 --- a/Classes/LinkHandler/FileLinkHandler.php +++ /dev/null @@ -1,52 +0,0 @@ -addTemplatePath($view); - - return parent::setView($view); - } - - protected function addTemplatePath(?ViewInterface $view): void - { - if ($view instanceof ViewInterface) { - //$templateRootPaths = ['EXT:recordlist/Resources/Private/Templates/LinkBrowser']; - //$templateRootPaths[] = 'EXT:jwtools2/Resources/Private/Extensions/Recordlist/Templates'; - //debug($view->getCurrentRenderingContext()); - //setTemplateRootPaths($templateRootPaths); - } - } -} diff --git a/Classes/LinkHandler/FolderLinkHandler.php b/Classes/LinkHandler/FolderLinkHandler.php deleted file mode 100644 index 76d382a..0000000 --- a/Classes/LinkHandler/FolderLinkHandler.php +++ /dev/null @@ -1,66 +0,0 @@ -addTemplatePath($this->view); - } - - /** - * The parent::setView() method was implemented with TYPO3 11.2 - * For earlier TYPO3 version we still need the approach from above - */ - public function setView(ViewInterface $view): \TYPO3\CMS\Filelist\LinkHandler\AbstractResourceLinkHandler - { - $this->addTemplatePath($view); - - parent::setView($view); - } - - /** - * Yes, since TYPO3 11.2 this method will be called twice, but - * at first call $view (coming from initialize) is empty (not instance of StandaloneView). - * So, nothing will be changed on first call. - */ - protected function addTemplatePath(?ViewInterface $view): void - { - if ($view instanceof StandaloneView) { - $typo3Version = GeneralUtility::makeInstance(Typo3Version::class); - $templateRootPaths = ['EXT:recordlist/Resources/Private/Templates/LinkBrowser']; - if (version_compare($typo3Version->getBranch(), '11.2', '<')) { - $templateRootPaths[] = 'EXT:jwtools2/Resources/Private/Extensions/Recordlist/Templates/V10'; - } else { - $templateRootPaths[] = 'EXT:jwtools2/Resources/Private/Extensions/Recordlist/Templates'; - } - - $view->setTemplateRootPaths($templateRootPaths); - } - } -} From eb152b203f99345da59e0bc4862ee32a53fef290 Mon Sep 17 00:00:00 2001 From: Hoja Mustaffa Abdul Latheef Date: Mon, 25 Mar 2024 10:34:01 +0100 Subject: [PATCH 54/65] Fixed formatting in documentation --- Documentation/AdministratorManual/Upgrade/Index.rst | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/Documentation/AdministratorManual/Upgrade/Index.rst b/Documentation/AdministratorManual/Upgrade/Index.rst index 8a8b1b9..bdb7a9e 100644 --- a/Documentation/AdministratorManual/Upgrade/Index.rst +++ b/Documentation/AdministratorManual/Upgrade/Index.rst @@ -8,7 +8,7 @@ Upgrade If you upgrade EXT:jwtools2 to a newer version, please read this section carefully! Upgrade to Version 7.0.0 -========================= +======================== .. important:: @@ -33,4 +33,3 @@ Deprecated and Obsolete Features - Remove support for TYPO3 11 and lower versions - Removed `jwtools2:executeExtensionUpdate` command line controller as it is obsolete. - Removed deprecated functions and usages - From c0b89b40a22cfb70d333651ce29041f7f6968983 Mon Sep 17 00:00:00 2001 From: Hoja Mustaffa Abdul Latheef Date: Tue, 26 Mar 2024 11:04:26 +0100 Subject: [PATCH 55/65] Small cleanup and optimizations --- Classes/Backend/AbstractDocHeader.php | 92 ----------------------- Classes/Backend/SolrDocHeader.php | 54 ++++++++++++- Classes/Controller/AbstractController.php | 23 ++---- Classes/Controller/SolrController.php | 44 +++++++---- Classes/Traits/InjectIconFactoryTrait.php | 26 +++++++ Classes/Traits/InjectUriBuilderTrait.php | 26 +++++++ 6 files changed, 139 insertions(+), 126 deletions(-) delete mode 100644 Classes/Backend/AbstractDocHeader.php create mode 100644 Classes/Traits/InjectIconFactoryTrait.php create mode 100644 Classes/Traits/InjectUriBuilderTrait.php diff --git a/Classes/Backend/AbstractDocHeader.php b/Classes/Backend/AbstractDocHeader.php deleted file mode 100644 index d5d64ed..0000000 --- a/Classes/Backend/AbstractDocHeader.php +++ /dev/null @@ -1,92 +0,0 @@ -request = $request; - $this->view = $view; - - if ($this->iconFactory === null) { - $this->iconFactory = GeneralUtility::makeInstance(IconFactory::class); - } - } - - public function injectUriBuilder(UriBuilder $uriBuilder): void - { - $this->uriBuilder = $uriBuilder; - } - - public function injectIconFactory(IconFactory $iconFactory): void - { - $this->iconFactory = $iconFactory; - } - - protected function addShortcutButton(): void - { - $buttonBar = $this->view - ->getDocHeaderComponent() - ->getButtonBar(); - - $shortcutButton = $buttonBar - ->makeShortcutButton() - ->setRouteIdentifier($this->request->getPluginName()) - ->setDisplayName('Jwtools2'); - - $buttonBar->addButton($shortcutButton); - } - - protected function addCloseButton(): void - { - $buttonBar = $this->view - ->getDocHeaderComponent() - ->getButtonBar(); - - $uri = $this->uriBuilder - ->reset() - ->uriFor('overview', [], 'Tools'); - - $closeButton = $buttonBar - ->makeLinkButton() - ->setHref($uri) - ->setIcon($this->iconFactory->getIcon('actions-close', Icon::SIZE_SMALL)) - ->setTitle('Close'); - - $buttonBar->addButton($closeButton); - } - - /** - * Get Link to create new configuration records of defined type - */ - protected function getLinkForUrl(string $url): string - { - return 'window.location.href=' . GeneralUtility::quoteJSvalue($url) . '; return false;'; - } -} diff --git a/Classes/Backend/SolrDocHeader.php b/Classes/Backend/SolrDocHeader.php index 312dd25..b4cdf97 100644 --- a/Classes/Backend/SolrDocHeader.php +++ b/Classes/Backend/SolrDocHeader.php @@ -10,15 +10,26 @@ namespace JWeiland\Jwtools2\Backend; + +use TYPO3\CMS\Backend\Template\ModuleTemplate; use TYPO3\CMS\Core\Imaging\Icon; +use TYPO3\CMS\Core\Imaging\IconFactory; use TYPO3\CMS\Core\Utility\GeneralUtility; +use TYPO3\CMS\Extbase\Mvc\Request; use TYPO3\CMS\Extbase\Mvc\Web\Routing\UriBuilder; /** * DocHeader for our Solr Module */ -class SolrDocHeader extends AbstractDocHeader +class SolrDocHeader { + public function __construct( + private readonly Request $request, + private readonly ModuleTemplate $view, + private readonly IconFactory $iconFactory, + private readonly UriBuilder $uriBuilder + ) {} + public function renderDocHeader(): void { // initialize UriBuilder @@ -57,4 +68,45 @@ protected function addModuleSelector(): void ->addButton($overviewButton) ->addButton($clearFullIndexButton); } + + protected function addShortcutButton(): void + { + $buttonBar = $this->view + ->getDocHeaderComponent() + ->getButtonBar(); + + $shortcutButton = $buttonBar + ->makeShortcutButton() + ->setRouteIdentifier($this->request->getPluginName()) + ->setDisplayName('Jwtools2'); + + $buttonBar->addButton($shortcutButton); + } + + protected function addCloseButton(): void + { + $buttonBar = $this->view + ->getDocHeaderComponent() + ->getButtonBar(); + + $uri = $this->uriBuilder + ->reset() + ->uriFor('overview', [], 'Tools'); + + $closeButton = $buttonBar + ->makeLinkButton() + ->setHref($uri) + ->setIcon($this->iconFactory->getIcon('actions-close', Icon::SIZE_SMALL)) + ->setTitle('Close'); + + $buttonBar->addButton($closeButton); + } + + /** + * Get Link to create new configuration records of defined type + */ + protected function getLinkForUrl(string $url): string + { + return 'window.location.href=' . GeneralUtility::quoteJSvalue($url) . '; return false;'; + } } diff --git a/Classes/Controller/AbstractController.php b/Classes/Controller/AbstractController.php index b35af47..2b5d14a 100644 --- a/Classes/Controller/AbstractController.php +++ b/Classes/Controller/AbstractController.php @@ -10,11 +10,10 @@ namespace JWeiland\Jwtools2\Controller; -use TYPO3\CMS\Backend\Routing\UriBuilder; +use JWeiland\Jwtools2\Traits\InjectIconFactoryTrait; use TYPO3\CMS\Backend\Template\ModuleTemplate; use TYPO3\CMS\Backend\Template\ModuleTemplateFactory; use TYPO3\CMS\Core\Configuration\ExtensionConfiguration; -use TYPO3\CMS\Core\Imaging\IconFactory; use TYPO3\CMS\Core\Utility\GeneralUtility; use TYPO3\CMS\Extbase\Mvc\Controller\ActionController; use TYPO3\CMS\Fluid\View\TemplateView; @@ -24,23 +23,13 @@ */ abstract class AbstractController extends ActionController { - protected ModuleTemplateFactory $moduleTemplateFactory; + use InjectIconFactoryTrait; - protected ModuleTemplate $moduleTemplate; + protected ?ModuleTemplate $moduleTemplate = null; - protected ?IconFactory $iconFactory = null; - protected UriBuilder $backendUriBuilder; - - public function injectIconFactory(IconFactory $iconFactory): void - { - $this->iconFactory = $iconFactory; - } - - public function __construct(ModuleTemplateFactory $moduleTemplateFactory, UriBuilder $backendUriBuilder) - { - $this->moduleTemplateFactory = $moduleTemplateFactory; - $this->backendUriBuilder = $backendUriBuilder; - } + public function __construct( + protected readonly ModuleTemplateFactory $moduleTemplateFactory + ) {} /** * Initializes the view before invoking an action method. diff --git a/Classes/Controller/SolrController.php b/Classes/Controller/SolrController.php index de8c3a6..f0cfb83 100644 --- a/Classes/Controller/SolrController.php +++ b/Classes/Controller/SolrController.php @@ -29,8 +29,7 @@ use TYPO3\CMS\Core\Utility\ArrayUtility; use TYPO3\CMS\Core\Utility\GeneralUtility; use TYPO3\CMS\Extbase\Annotation as Extbase; -use TYPO3\CMS\Extbase\Mvc\View\NotFoundView; -use TYPO3\CMS\Extbase\Mvc\View\ViewInterface; +use TYPO3Fluid\Fluid\View\TemplateAwareViewInterface; #[AsController] class SolrController extends AbstractController @@ -42,22 +41,11 @@ class SolrController extends AbstractController public function initializeView($view): void { - if (!$view instanceof NotFoundView) { + if ($view instanceof TemplateAwareViewInterface) { parent::initializeView($view); - $this->pageRenderer->loadJavaScriptModule('@jweiland/jwtools2/solr-backend-module.js'); - - /** @var SolrDocHeader $docHeader */ - $docHeader = GeneralUtility::makeInstance(SolrDocHeader::class, $this->request, $this->moduleTemplate); - $docHeader->renderDocHeader(); - - if (!$this->schedulerRepository->findSolrSchedulerTask()) { - $this->addFlashMessage( - 'No or wrong scheduler task UID configured in ExtensionManager Configuration of jwtools2', - 'Missing or wrong configuration', - ContextualFeedbackSeverity::WARNING - ); - } + $this->renderDocHeader(); + $this->checkSchedulerTaskConfig(); } } @@ -312,4 +300,28 @@ protected function getIndexerByItem(string $indexingConfigurationName, TypoScrip return $indexer; } + + protected function renderDocHeader(): void + { + /** @var SolrDocHeader $docHeader */ + $docHeader = GeneralUtility::makeInstance( + SolrDocHeader::class, + $this->request, + $this->moduleTemplate, + $this->iconFactory, + $this->uriBuilder + ); + $docHeader->renderDocHeader(); + } + + protected function checkSchedulerTaskConfig(): void + { + if (!$this->schedulerRepository->findSolrSchedulerTask()) { + $this->addFlashMessage( + 'No or wrong scheduler task UID configured in ExtensionManager Configuration of jwtools2', + 'Missing or wrong configuration', + ContextualFeedbackSeverity::WARNING + ); + } + } } diff --git a/Classes/Traits/InjectIconFactoryTrait.php b/Classes/Traits/InjectIconFactoryTrait.php new file mode 100644 index 0000000..73fd023 --- /dev/null +++ b/Classes/Traits/InjectIconFactoryTrait.php @@ -0,0 +1,26 @@ +iconFactory = $iconFactory; + } +} diff --git a/Classes/Traits/InjectUriBuilderTrait.php b/Classes/Traits/InjectUriBuilderTrait.php new file mode 100644 index 0000000..82d9240 --- /dev/null +++ b/Classes/Traits/InjectUriBuilderTrait.php @@ -0,0 +1,26 @@ +uriBuilder = $uriBuilder; + } +} From 0683c5e1a4c5ee37989ce001a3320c0733fa97a7 Mon Sep 17 00:00:00 2001 From: Hoja Mustaffa Abdul Latheef Date: Mon, 8 Apr 2024 09:41:38 +0200 Subject: [PATCH 56/65] [TASK] CR Fixes - Removed typo3UploadFieldsInTopOfEB configuration related references - Services.yaml configuration for DI of SchedulerTaskRepository https://github.com/jweiland-net/jwtools2/pull/74#discussion_r1549583142 - Rename method to getQueryResultForUsers https://github.com/jweiland-net/jwtools2/pull/74#discussion_r1549588058 - https://github.com/jweiland-net/jwtools2/pull/74#discussion_r1549590280 - Removed space https://github.com/jweiland-net/jwtools2/pull/74#discussion_r1549626275 - Removed #AsController https://github.com/jweiland-net/jwtools2/pull/74#discussion_r1549639251 - Changed function name https://github.com/jweiland-net/jwtools2/pull/74#discussion_r1549655337 - Removed count https://github.com/jweiland-net/jwtools2/pull/74#discussion_r1549602310 - Moved $yesterday inside the function and removed from function arguments https://github.com/jweiland-net/jwtools2/pull/74#discussion_r1549621061 https://github.com/jweiland-net/jwtools2/pull/74#discussion_r1549621556 - Changed comment style https://github.com/jweiland-net/jwtools2/pull/74#discussion_r1549623525 - Removed float return type https://github.com/jweiland-net/jwtools2/pull/74#discussion_r1549640894 - Changed variable type https://github.com/jweiland-net/jwtools2/pull/74#discussion_r1549657556 - Replaced substr with str_ends_with https://github.com/jweiland-net/jwtools2/pull/74#discussion_r1549813428 - Remove unwanted casting as the variable is already casted https://github.com/jweiland-net/jwtools2/pull/74#discussion_r1549816431 - Deleted ViewHelper https://github.com/jweiland-net/jwtools2/pull/74#discussion_r1549823686 - Missing space inserted https://github.com/jweiland-net/jwtools2/pull/74#discussion_r1549826892 - Documentation Corrections https://github.com/jweiland-net/jwtools2/pull/74#discussion_r1549832518 - Changed backslashes to forward slashes https://github.com/jweiland-net/jwtools2/pull/74#discussion_r1549845172 - Changed backslashes to forward slashes https://github.com/jweiland-net/jwtools2/pull/74#discussion_r1549843633 - Add lang attribute https://github.com/jweiland-net/jwtools2/pull/74#discussion_r1549848126 - Removed todo comments as it was already done https://github.com/jweiland-net/jwtools2/pull/74#discussion_r1549863404 - Changed getAccessibleMock to createMock https://github.com/jweiland-net/jwtools2/pull/74#discussion_r1549857896 --- Classes/Backend/SolrDocHeader.php | 6 - .../ConvertPlainPasswordToHashCommand.php | 4 +- Classes/Command/StatusReportCommand.php | 23 ++- .../UpdateFileMetaDataProvider.php | 2 +- Classes/Controller/AbstractController.php | 2 +- Classes/Controller/SolrController.php | 4 +- Classes/Controller/ToolsController.php | 4 +- Classes/Database/Query/QueryGenerator.php | 2 +- .../Hooks/ModifyElementInformationHook.php | 18 +- Classes/Task/ExecuteQueryTask.php | 2 +- ...QueueWorkerTaskAdditionalFieldProvider.php | 4 +- Classes/ViewHelpers/Format/HtmlViewHelper.php | 161 ------------------ Configuration/Backend/Modules.php | 2 +- Configuration/Services.yaml | 4 + .../AdministratorManual/Upgrade/Index.rst | 2 +- Documentation/ChangeLog/Index.rst | 1 + Documentation/Configuration/Index.rst | 15 -- Resources/Private/Language/ExtConf.xlf | 5 - Resources/Private/Language/de.ExtConf.xlf | 4 - Resources/Private/Templates/Solr/List.html | 4 +- Resources/Private/Templates/Solr/Show.html | 2 +- .../Solr/ShowClearFullIndexForm.html | 2 +- .../Private/Templates/Tools/Overview.html | 4 +- .../Hooks/InitializeStdWrapTest.php | 2 +- ext_conf_template.txt | 7 - q | 15 ++ 26 files changed, 68 insertions(+), 233 deletions(-) delete mode 100644 Classes/ViewHelpers/Format/HtmlViewHelper.php create mode 100644 q diff --git a/Classes/Backend/SolrDocHeader.php b/Classes/Backend/SolrDocHeader.php index b4cdf97..01126fc 100644 --- a/Classes/Backend/SolrDocHeader.php +++ b/Classes/Backend/SolrDocHeader.php @@ -32,12 +32,6 @@ public function __construct( public function renderDocHeader(): void { - // initialize UriBuilder - if (!($this->uriBuilder instanceof UriBuilder)) { - $this->uriBuilder = GeneralUtility::makeInstance(UriBuilder::class); - } - $this->uriBuilder->setRequest($this->request); - // Render Buttons $this->addShortcutButton(); $this->addCloseButton(); diff --git a/Classes/Command/ConvertPlainPasswordToHashCommand.php b/Classes/Command/ConvertPlainPasswordToHashCommand.php index 02b21cd..6f1ca92 100644 --- a/Classes/Command/ConvertPlainPasswordToHashCommand.php +++ b/Classes/Command/ConvertPlainPasswordToHashCommand.php @@ -76,7 +76,7 @@ protected function updateUsers(string $mode): void { $counter = 0; $connection = $this->getConnectionPool()->getConnectionForTable($this->modeMapping[$mode]['table']); - $statement = $this->getStatementForUsers($this->modeMapping[$mode]['table']); + $statement = $this->getQueryResultForUsers($this->modeMapping[$mode]['table']); while ($user = $statement->fetch()) { if (!isset($user['password']) || $user['password'] === '') { continue; @@ -147,7 +147,7 @@ protected function getDefaultHashInstance(string $mode): PasswordHashInterface return $this->modeMapping[$mode]['hashInstance']; } - protected function getStatementForUsers(string $tableName): Result + protected function getQueryResultForUsers(string $tableName): Result { $queryBuilder = $this->getConnectionPool()->getQueryBuilderForTable($tableName); return $queryBuilder diff --git a/Classes/Command/StatusReportCommand.php b/Classes/Command/StatusReportCommand.php index 4cc187d..b8ae654 100644 --- a/Classes/Command/StatusReportCommand.php +++ b/Classes/Command/StatusReportCommand.php @@ -40,9 +40,7 @@ class StatusReportCommand extends Command public function __construct() { - parent::__construct(); - - $this->taskRepository = GeneralUtility::makeInstance(SchedulerTaskRepository::class); + parent::__construct('Start Report Command'); } public function configure(): void @@ -90,14 +88,14 @@ protected function checkSiteConfiguration(): void protected function checkScheduler(): void { + $yesterday = time() - (60 * 60 * 24); $this->ioStyled->title('Checking scheduler tasks'); $lastExecution = 0; $recurringTasks = []; - $yesterday = time() - (60 * 60 * 24); $tasks = $this->getSchedulerTasks(); - $lastExecution = $this->processTasks($tasks, $recurringTasks, $yesterday, $lastExecution); + $lastExecution = $this->processTasks($tasks, $recurringTasks, $lastExecution); $this->ioStyled->definitionList( $lastExecution < $yesterday ? 'The last execution was over 24 hours ago' : 'Last execution within last 24 hours', @@ -259,11 +257,11 @@ protected function getAllSites(): array return GeneralUtility::makeInstance(SiteFinder::class)->getAllSites(); } - protected function processTasks(array $tasks, array &$recurringTasks, int $yesterday, int $lastExecution): int + protected function processTasks(array $tasks, array &$recurringTasks, int $lastExecution): int { foreach ($tasks as $groups => $taskGroups) { foreach ($taskGroups as $taskGroup) { - if (is_array($taskGroup['tasks']) && count($taskGroup['tasks'])) { + if (is_array($taskGroup['tasks'])) { foreach ($taskGroup['tasks'] as $task) { if ($task['lastExecutionTime'] > $lastExecution) { $lastExecution = $task['lastExecutionTime']; @@ -276,7 +274,7 @@ protected function processTasks(array $tasks, array &$recurringTasks, int $yeste $task['lastExecutionContext'] ); - $recurringTasks[] = [$taskTitle => $this->getTaskStatus($task, $yesterday)]; + $recurringTasks[] = [$taskTitle => $this->getTaskStatus($task)]; } } } @@ -285,8 +283,10 @@ protected function processTasks(array $tasks, array &$recurringTasks, int $yeste return $lastExecution; } - protected function getTaskStatus(array $task, int $yesterday): string + protected function getTaskStatus(array $task): string { + $yesterday = time() - (60 * 60 * 24); + if (isset($task['serializedExecutions']) && $task['serializedExecutions'] !== '') { return 'running...'; } @@ -297,4 +297,9 @@ protected function getTaskStatus(array $task, int $yesterday): string return $task['lastExecutionTime'] < $yesterday ? 'scheduled > 24h' : 'scheduled < 24h'; } + + public function setTaskRepository(SchedulerTaskRepository $taskRepository): void + { + $this->taskRepository = $taskRepository; + } } diff --git a/Classes/ContextMenu/ItemProviders/UpdateFileMetaDataProvider.php b/Classes/ContextMenu/ItemProviders/UpdateFileMetaDataProvider.php index 39a6f87..9c85234 100644 --- a/Classes/ContextMenu/ItemProviders/UpdateFileMetaDataProvider.php +++ b/Classes/ContextMenu/ItemProviders/UpdateFileMetaDataProvider.php @@ -14,7 +14,7 @@ use TYPO3\CMS\Filelist\ContextMenu\ItemProviders\FileProvider; /** - * Adds a new entry ``Create/Update file metadata`` into context menu of filelist module to create a missing file + * Adds a new entry 'Create/Update file metadata' into context menu of filelist module to create a missing file * metadata record or to update the existing metadata record (sys_file_metadata). */ class UpdateFileMetaDataProvider extends FileProvider diff --git a/Classes/Controller/AbstractController.php b/Classes/Controller/AbstractController.php index 2b5d14a..b964b1c 100644 --- a/Classes/Controller/AbstractController.php +++ b/Classes/Controller/AbstractController.php @@ -36,7 +36,7 @@ public function __construct( * Override this method to solve assign variables common for all actions * or prepare the view in another way before the action is called. */ - protected function initializeView( TemplateView $view): void + protected function initializeView(TemplateView $view): void { $this->moduleTemplate = $this->moduleTemplateFactory->create($this->request); $this->moduleTemplate->assign('extConf', $this->getExtensionConfiguration()); diff --git a/Classes/Controller/SolrController.php b/Classes/Controller/SolrController.php index f0cfb83..943d346 100644 --- a/Classes/Controller/SolrController.php +++ b/Classes/Controller/SolrController.php @@ -31,7 +31,9 @@ use TYPO3\CMS\Extbase\Annotation as Extbase; use TYPO3Fluid\Fluid\View\TemplateAwareViewInterface; -#[AsController] +/** + * SolrController for backend module + */ class SolrController extends AbstractController { use InjectSolrRepositoryTrait; diff --git a/Classes/Controller/ToolsController.php b/Classes/Controller/ToolsController.php index 380b250..04885d1 100644 --- a/Classes/Controller/ToolsController.php +++ b/Classes/Controller/ToolsController.php @@ -13,7 +13,9 @@ use Psr\Http\Message\ResponseInterface; use TYPO3\CMS\Backend\Attribute\AsController; -#[AsController] +/** + * ToolsController for backend module + */ class ToolsController extends AbstractController { public function initializeAction(): void diff --git a/Classes/Database/Query/QueryGenerator.php b/Classes/Database/Query/QueryGenerator.php index f0e6473..b9e846e 100644 --- a/Classes/Database/Query/QueryGenerator.php +++ b/Classes/Database/Query/QueryGenerator.php @@ -24,7 +24,7 @@ class QueryGenerator /** * @throws Exception */ - public function getTreeList($id, $depth, $begin = 0, $permClause = ''): float|int|string + public function getTreeList($id, $depth, $begin = 0, $permClause = ''): int|string { $depth = (int)$depth; $begin = (int)$begin; diff --git a/Classes/Hooks/ModifyElementInformationHook.php b/Classes/Hooks/ModifyElementInformationHook.php index 78d60e8..e5237de 100644 --- a/Classes/Hooks/ModifyElementInformationHook.php +++ b/Classes/Hooks/ModifyElementInformationHook.php @@ -10,6 +10,7 @@ namespace JWeiland\Jwtools2\Hooks; +use Doctrine\DBAL\Exception; use Psr\Http\Message\ServerRequestInterface; use TYPO3\CMS\Backend\Backend\Avatar\Avatar; use TYPO3\CMS\Backend\Controller\ContentElement\ElementInformationController; @@ -507,7 +508,7 @@ protected function getReferences(ServerRequestInterface $request): array /** * Get field name for specified table/column name */ - protected function getLabelForTableColumnByTable(string $tableName, string $fieldName): string + protected function getLabelForColumnByTable(string $tableName, string $fieldName): string { if (($GLOBALS['TCA'][$tableName]['columns'][$fieldName]['label'] ?? null) !== null) { $field = $this->getLanguageService()->sL($GLOBALS['TCA'][$tableName]['columns'][$fieldName]['label']); @@ -562,9 +563,10 @@ protected function getRecordActions(string $table, int $uid, ServerRequestInterf /** * Make reference display - * @throws RouteNotFoundException + * + * @throws RouteNotFoundException|Exception */ - protected function makeRef(string $table, File|int $ref, ServerRequestInterface $request): array + protected function makeRef(string $table, File|int|string $ref, ServerRequestInterface $request): array { $refLines = []; $lang = $this->getLanguageService(); @@ -642,13 +644,13 @@ protected function makeRef(string $table, File|int $ref, ServerRequestInterface $line['parentRecord'] = $parentRecord; $line['parentRecordTitle'] = $parentRecordTitle; $line['title'] = $lang->sL($GLOBALS['TCA'][$row['tablename']]['ctrl']['title']); - $line['labelForTableColumn'] = $this->getLabelForTableColumnByTable($row['tablename'], $row['field']); + $line['labelForTableColumn'] = $this->getLabelForColumnByTable($row['tablename'], $row['field']); $line['path'] = BackendUtility::getRecordPath($record['pid'], '', 0, 0); $line['actions'] = $this->getRecordActions($row['tablename'], $row['recuid'], $request); } else { $line['row'] = $row; $line['title'] = $lang->sL($GLOBALS['TCA'][$row['tablename']]['ctrl']['title'] ?? '') ?: $row['tablename']; - $line['labelForTableColumn'] = $this->getLabelForTableColumnByTable($row['tablename'], $row['field']); + $line['labelForTableColumn'] = $this->getLabelForColumnByTable($row['tablename'], $row['field']); } $refLines[] = $line; } @@ -658,7 +660,7 @@ protected function makeRef(string $table, File|int $ref, ServerRequestInterface /** * Make reference display (what this elements points to) */ - protected function makeRefFrom(string $table, int $ref, ServerRequestInterface $request): array + protected function makeRefFrom(string $table, string $ref, ServerRequestInterface $request): array { $refFromLines = []; $lang = $this->getLanguageService(); @@ -716,13 +718,13 @@ protected function makeRefFrom(string $table, int $ref, ServerRequestInterface $ $line['record'] = $record; $line['recordTitle'] = BackendUtility::getRecordTitle($row['ref_table'], $record, false, true); $line['title'] = $lang->sL($GLOBALS['TCA'][$row['ref_table']]['ctrl']['title'] ?? ''); - $line['labelForTableColumn'] = $this->getLabelForTableColumnByTable($table, $row['field']); + $line['labelForTableColumn'] = $this->getLabelForColumnByTable($table, $row['field']); $line['path'] = BackendUtility::getRecordPath($record['pid'], '', 0, 0); $line['actions'] = $this->getRecordActions($row['ref_table'], $row['ref_uid'], $request); } else { $line['row'] = $row; $line['title'] = $lang->sL($GLOBALS['TCA'][$row['ref_table']]['ctrl']['title'] ?? ''); - $line['labelForTableColumn'] = $this->getLabelForTableColumnByTable($table, $row['field']); + $line['labelForTableColumn'] = $this->getLabelForColumnByTable($table, $row['field']); } $refFromLines[] = $line; } diff --git a/Classes/Task/ExecuteQueryTask.php b/Classes/Task/ExecuteQueryTask.php index 70072d8..6203780 100644 --- a/Classes/Task/ExecuteQueryTask.php +++ b/Classes/Task/ExecuteQueryTask.php @@ -41,7 +41,7 @@ public function execute(): bool foreach ($sqlQueries as $sqlQuery) { // check $sqlQuery ends with a semi-colon otherwise add it - if (substr($sqlQuery, -1) !== ';') { + if (!str_ends_with($sqlQuery, ';')) { $sqlQuery .= ';'; } $connection->executeStatement($sqlQuery); diff --git a/Classes/Task/IndexQueueWorkerTaskAdditionalFieldProvider.php b/Classes/Task/IndexQueueWorkerTaskAdditionalFieldProvider.php index a0d88a8..a2273b9 100644 --- a/Classes/Task/IndexQueueWorkerTaskAdditionalFieldProvider.php +++ b/Classes/Task/IndexQueueWorkerTaskAdditionalFieldProvider.php @@ -94,7 +94,7 @@ public function validateAdditionalFields(array &$submittedData, SchedulerModuleC public function saveAdditionalFields(array $submittedData, AbstractTask $task): void { /** @var IndexQueueWorkerTask $task */ - $task->setDocumentsToIndexLimit((int)$submittedData['documentsToIndexLimit']); - $task->setMaxSitesPerRun((int)$submittedData['maxSitesPerRun']); + $task->setDocumentsToIndexLimit($submittedData['documentsToIndexLimit']); + $task->setMaxSitesPerRun($submittedData['maxSitesPerRun']); } } diff --git a/Classes/ViewHelpers/Format/HtmlViewHelper.php b/Classes/ViewHelpers/Format/HtmlViewHelper.php deleted file mode 100644 index f813d1e..0000000 --- a/Classes/ViewHelpers/Format/HtmlViewHelper.php +++ /dev/null @@ -1,161 +0,0 @@ - - * foo bar. Some Link. - * - * Output:: - *

foo bar. Some link.

- * Depending on TYPO3 setup. - * Custom parseFunc - * ---------------- - * :: - * - * foo bar. Some Link. - * - * Output:: - * foo bar. Some link. - * Individual data attribute - * ------------------------- - * If you work with TS:field property in lib.parseFunc you should add current record to Html VH. - * :: - * - * foo bar. Some Link. - * - * Output:: - * foo bar. Some link. - * Inline notation - * --------------- - * :: - * {someText -> jw:format.html(parseFuncTSPath: 'lib.parseFunc')} - * Output:: - * foo bar. Some link. - * .. _parseFunc: https://docs.typo3.org/m/typo3/reference-typoscript/master/en-us/Functions/Parsefunc.html - * - * @deprecated Will be removed while removing TYPO3 10 compatibility. Please use f:format.html which has all options now. - */ -class HtmlViewHelper extends AbstractViewHelper -{ - use CompileWithRenderStatic; - - /** - * @var TypoScriptFrontendController contains a backup of the current $GLOBALS['TSFE'] if used in BE mode - */ - protected static $tsfeBackup; - - /** - * Children must not be escaped, to be able to pass {bodytext} directly to it - * - * @var bool - */ - protected $escapeChildren = false; - - /** - * Plain HTML should be returned, no output escaping allowed - * - * @var bool - */ - protected $escapeOutput = false; - - public function initializeArguments(): void - { - $this->registerArgument( - 'parseFuncTSPath', - 'string', - 'Path to TypoScript parseFunc setup.', - false, - 'lib.parseFunc_RTE' - ); - $this->registerArgument('data', 'array', 'Initialize ContentObjectRenderer with this set of data.', false, []); - } - - public static function renderStatic( - array $arguments, - \Closure $renderChildrenClosure, - RenderingContextInterface $renderingContext - ): string { - $parseFuncTSPath = $arguments['parseFuncTSPath']; - if (ApplicationType::fromRequest($GLOBALS['TYPO3_REQUEST'])->isBackend()) { - self::simulateFrontendEnvironment(); - } - - $value = $renderChildrenClosure(); - $contentObject = GeneralUtility::makeInstance(ContentObjectRenderer::class); - $contentObject->start($arguments['data'] ?? []); - $content = $contentObject->parseFunc($value, [], '< ' . $parseFuncTSPath); - - if (ApplicationType::fromRequest($GLOBALS['TYPO3_REQUEST'])->isBackend()) { - self::resetFrontendEnvironment(); - } - - return $content; - } - - /** - * Copies the specified parseFunc configuration to $GLOBALS['TSFE']->tmpl->setup in Backend mode - * This somewhat hacky work around is currently needed because the parseFunc() function of \TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer relies on those variables to be set - * - * @throws AspectNotFoundException - */ - protected static function simulateFrontendEnvironment(): void - { - $context = GeneralUtility::makeInstance(Context::class); - if ( - !$context->getPropertyFromAspect('typoscript', 'frontendController') instanceof TypoScriptFrontendController - ) { - self::$tsfeBackup = $context->getPropertyFromAspect('typoscript', 'frontendController'); - $context->setAspect('typoscript', $context->getAspect('frontendController'), new \stdClass()); - $context->setAspect('typoscript', $context->getAspect('cObjectDepthCounter'), 50); - $context->setAspect('typoscript', $context->getAspect('templateService'), new \stdClass()); - - $typoScriptService = GeneralUtility::makeInstance(TypoScriptService::class); - $context->setAspect('typoscript', $context->getAspect('setup'), $typoScriptService->getConfiguration()); - } - } - - /** - * Resets $GLOBALS['TSFE'] if it was previously changed by simulateFrontendEnvironment() - * - * @see simulateFrontendEnvironment() - */ - protected static function resetFrontendEnvironment(): void - { - if ($GLOBALS['TSFE'] instanceof \stdClass) { - $GLOBALS['TSFE'] = self::$tsfeBackup; - } - } -} diff --git a/Configuration/Backend/Modules.php b/Configuration/Backend/Modules.php index 758ce58..5c864da 100644 --- a/Configuration/Backend/Modules.php +++ b/Configuration/Backend/Modules.php @@ -23,7 +23,7 @@ 'overview', ], SolrController::class => [ - 'list','show', 'showIndexQueue', 'indexOneRecord', 'showClearIndexForm', 'clearIndex', 'showClearFullIndexForm', + 'list', 'show', 'showIndexQueue', 'indexOneRecord', 'showClearIndexForm', 'clearIndex', 'showClearFullIndexForm', ], ], ], diff --git a/Configuration/Services.yaml b/Configuration/Services.yaml index dd5e4a0..3b868a5 100644 --- a/Configuration/Services.yaml +++ b/Configuration/Services.yaml @@ -22,6 +22,10 @@ services: command: 'jwtools2:convertpasswords' schedulable: false JWeiland\Jwtools2\Command\StatusReportCommand: + calls: + - method: setTaskRepository + arguments: + - '@TYPO3\CMS\Scheduler\Domain\Repository\SchedulerTaskRepository' tags: - name: 'console.command' command: 'jwtools2:statusreport' diff --git a/Documentation/AdministratorManual/Upgrade/Index.rst b/Documentation/AdministratorManual/Upgrade/Index.rst index bdb7a9e..bdecdde 100644 --- a/Documentation/AdministratorManual/Upgrade/Index.rst +++ b/Documentation/AdministratorManual/Upgrade/Index.rst @@ -17,7 +17,7 @@ Upgrade to Version 7.0.0 Removed Option: `typo3UploadFieldsInTopOfEB` -------------------------------------------- -In the latest version of TYPO3, the `typo3UploadFieldsInTopOfEB` option has been removed. This change was necessitated +The `typo3UploadFieldsInTopOfEB` option has been removed from TYPO3 before 6.2 version. This change was necessitated by the introduction of a paginator in File Abstraction Layer (FAL). As a result, it's no longer possible to adjust the position of File upload or create fields above the list without Xclass. diff --git a/Documentation/ChangeLog/Index.rst b/Documentation/ChangeLog/Index.rst index b60a12e..8683702 100644 --- a/Documentation/ChangeLog/Index.rst +++ b/Documentation/ChangeLog/Index.rst @@ -17,6 +17,7 @@ Version 7.0.0 * [TASK] Testing Framework migrated to TYPO3 Tesing Framework * [TASK] Remove support for TYPO3 11 and lower versions * [TASK] Removed jwtools2:executeExtensionUpdate command line controller as it is obsolete. +* [TASK] Removed typo3UploadFieldsInTopOfEB configuration as it is not possible to change upload form without Xclass. * [TASK] Removed deprecated functions and usages diff --git a/Documentation/Configuration/Index.rst b/Documentation/Configuration/Index.rst index 136ea54..f640cc7 100644 --- a/Documentation/Configuration/Index.rst +++ b/Documentation/Configuration/Index.rst @@ -83,21 +83,6 @@ If you activate ``typo3TransferTypoScriptCurrent`` we make use of a hook in TYPO This option will only work for cObj types CONTENT and RECORD. -.. _typo3UploadFieldsInTopOfEB: - -typo3UploadFieldsInTopOfEB --------------------------- - -With TYPO3 8.7.0 following UserTSconfig was removed: - -options.uploadFieldsInTopOfEB = 1 - -https://review.typo3.org/c/Packages/TYPO3.CMS/+/52170 - -After activating this Option we XClasses 3 files to show -Upload Fields in top of ElementBrowser and LinkHandler again. - - .. _typo3RequiredColumnsForFiles: typo3RequiredColumnsForFiles diff --git a/Resources/Private/Language/ExtConf.xlf b/Resources/Private/Language/ExtConf.xlf index a53e8c0..293ca84 100644 --- a/Resources/Private/Language/ExtConf.xlf +++ b/Resources/Private/Language/ExtConf.xlf @@ -16,11 +16,6 @@ sub-property of renderObj. - - Upload Fields in top of EB: The UserTSconfig option uploadFieldsInTopOfEB was removed with TYPO3 8.7.0. - Activate this Option to show upload fields in top of ElementBrowser and LinkHandler again. - - Required columns for image files: Enter here columns of the DB tables sys_file and/or sys_file_metadata which are to be regarded as mandatory fields. Files for which these columns are not set are available in the file browser, but cannot be selected. diff --git a/Resources/Private/Language/de.ExtConf.xlf b/Resources/Private/Language/de.ExtConf.xlf index a22f22e..dda8035 100644 --- a/Resources/Private/Language/de.ExtConf.xlf +++ b/Resources/Private/Language/de.ExtConf.xlf @@ -11,10 +11,6 @@ Transfer TypoScript current: For each record, found by CONTENT, a new instance of ContentObjectRenderer will be created by renderObj. The data property will be filled with the values of the record. The TypoScript current value will be resetted. Activate this option if you want to transfer the parent current value into the sub-property of renderObj. Übertrage TypoScript current: Für jeden Datensatz, der durch CONTENT gefunden wurde, wird bei der Verarbeitung durch renderObj immer eine neue Instanz vom ContentObjectRenderer erzeugt. Die data-Eigenschaft wird mit den Werten des Datensatzes gefüllt während die current-Eigenschaft geleert wird. Nach Aktivierung dieser Option wird der Wert der Eltern current-Eigenschaft mit in die Kind-Eigenschaft (renderObj) übertragen. - - Upload Fields in top of EB: The UserTSconfig option uploadFieldsInTopOfEB was removed with TYPO3 8.7.0. Activate this Option to show upload fields in top of ElementBrowser and LinkHandler again. - Uploadfelder oberhalb EB anzeigen: Die UserTSconfig Option uploadFieldsInTopOfEB wurde mit TYPO3 8.7.0 entfernt. Aktivieren Sie diese Option, um die Uploadfelder wieder oberhalb des ElementBrowser und des LinkHandlers anzeigen zu lassen. - Required columns for image files: Enter here columns of the DB tables sys_file and/or sys_file_metadata which are to be regarded as mandatory fields. Files for which these columns are not set are available in the file browser, but cannot be selected. Benötigte Spalten für Bilddateien: Tragen Sie hier Spalten der DB Tabellen sys_file und/oder sys_file_metadata ein, die als Pflichtfelder anzusehen sind. Dateien, bei denen diese Spalten nicht gesetzt sind stehen im Dateibrowser zwar zur Verfügung, können jedoch nicht ausgewählt werden. diff --git a/Resources/Private/Templates/Solr/List.html b/Resources/Private/Templates/Solr/List.html index 6222e02..2b65fa4 100644 --- a/Resources/Private/Templates/Solr/List.html +++ b/Resources/Private/Templates/Solr/List.html @@ -1,7 +1,7 @@ diff --git a/Resources/Private/Templates/Solr/Show.html b/Resources/Private/Templates/Solr/Show.html index c028b4a..98847bc 100644 --- a/Resources/Private/Templates/Solr/Show.html +++ b/Resources/Private/Templates/Solr/Show.html @@ -1,6 +1,6 @@ diff --git a/Resources/Private/Templates/Solr/ShowClearFullIndexForm.html b/Resources/Private/Templates/Solr/ShowClearFullIndexForm.html index 851cf34..95221a5 100644 --- a/Resources/Private/Templates/Solr/ShowClearFullIndexForm.html +++ b/Resources/Private/Templates/Solr/ShowClearFullIndexForm.html @@ -1,6 +1,6 @@ diff --git a/Resources/Private/Templates/Tools/Overview.html b/Resources/Private/Templates/Tools/Overview.html index cb0733b..45b9aef 100644 --- a/Resources/Private/Templates/Tools/Overview.html +++ b/Resources/Private/Templates/Tools/Overview.html @@ -1,4 +1,6 @@ - + diff --git a/Tests/Functional/Hooks/InitializeStdWrapTest.php b/Tests/Functional/Hooks/InitializeStdWrapTest.php index 3bd2879..c860393 100644 --- a/Tests/Functional/Hooks/InitializeStdWrapTest.php +++ b/Tests/Functional/Hooks/InitializeStdWrapTest.php @@ -33,7 +33,7 @@ protected function setUp(): void { parent::setUp(); - $this->extensionConfigurationMock = $this->getAccessibleMock(ExtensionConfiguration::class); + $this->extensionConfigurationMock = $this->createMock(ExtensionConfiguration::class); $this->subject = new InitializeStdWrap( $this->extensionConfigurationMock ); diff --git a/ext_conf_template.txt b/ext_conf_template.txt index c5a6440..0de35b0 100644 --- a/ext_conf_template.txt +++ b/ext_conf_template.txt @@ -2,12 +2,6 @@ typo3EnableUidInPageTree = 0 # cat=typo3; type=boolean; label=LLL:EXT:jwtools2/Resources/Private/Language/ExtConf.xlf:typo3TransferTypoScriptCurrent typo3TransferTypoScriptCurrent = 0 - -# @todo: rafactor this for version 12 -# cat=typo3; type=boolean; label=LLL:EXT:jwtools2/Resources/Private/Language/ExtConf.xlf:typo3UploadFieldsInTopOfEB -typo3UploadFieldsInTopOfEB = 0 - -# @todo: rafactor this for version 12 # cat=typo3; type=string; label=LLL:EXT:jwtools2/Resources/Private/Language/ExtConf.xlf:typo3RequiredColumnsForFiles typo3RequiredColumnsForFiles = # cat=typo3; type=boolean; label=LLL:EXT:jwtools2/Resources/Private/Language/ExtConf.xlf:typo3ShowEditButtonInElementInformation @@ -26,7 +20,6 @@ enableContextMenuToUpdateFileMetadata = 0 enableCachingFrameworkLogger = 0 # cat=reports; type=options[Info=info,Warning=warning]; label=LLL:EXT:jwtools2/Resources/Private/Language/ExtConf.xlf:sendUpdatableExtensionsWithSeverity sendUpdatableExtensionsWithSeverity = info - # cat=solr; type=boolean; label=LLL:EXT:jwtools2/Resources/Private/Language/ExtConf.xlf:solrEnable solrEnable = 0 # cat=solr; type=int+; label=LLL:EXT:jwtools2/Resources/Private/Language/ExtConf.xlf:solrSchedulerTaskUid diff --git a/q b/q new file mode 100644 index 0000000..1adf3d3 --- /dev/null +++ b/q @@ -0,0 +1,15 @@ +[TASK] CR Fixes + +- https://github.com/jweiland-net/jwtools2/pull/74#discussion_r1549583142 +- https://github.com/jweiland-net/jwtools2/pull/74#discussion_r1549588058 + +# Please enter the commit message for your changes. Lines starting +# with '#' will be ignored, and an empty message aborts the commit. +# +# Date: Mon Apr 8 09:41:38 2024 +0200 +# +# On branch typo3_12_compatibility +# Changes to be committed: +# modified: Classes/Backend/SolrDocHeader.php +# modified: Classes/Command/ConvertPlainPasswordToHashCommand.php +# From e3ff1d7caa0cf8ca6b409e2b0095eeca3a47ee3b Mon Sep 17 00:00:00 2001 From: Hoja Mustaffa Abdul Latheef Date: Mon, 8 Apr 2024 16:04:18 +0200 Subject: [PATCH 57/65] Loaded scheduler extension as it is not loaded by default --- Tests/Functional/Hooks/InitializeStdWrapTest.php | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Tests/Functional/Hooks/InitializeStdWrapTest.php b/Tests/Functional/Hooks/InitializeStdWrapTest.php index c860393..3834cb6 100644 --- a/Tests/Functional/Hooks/InitializeStdWrapTest.php +++ b/Tests/Functional/Hooks/InitializeStdWrapTest.php @@ -25,6 +25,10 @@ class InitializeStdWrapTest extends FunctionalTestCase protected ExtensionConfiguration | MockObject $extensionConfigurationMock; + protected array $coreExtensionsToLoad = [ + 'typo3/cms-scheduler' + ]; + protected array $testExtensionsToLoad = [ 'jweiland/jwtools2', ]; From a57a4f2111e778b44e87222e832567f5d1a87e9f Mon Sep 17 00:00:00 2001 From: Hoja Mustaffa Abdul Latheef Date: Mon, 8 Apr 2024 16:18:57 +0200 Subject: [PATCH 58/65] [TASK] Removed nullable in property declaration --- Classes/Controller/AbstractController.php | 2 +- Classes/Traits/InjectIconFactoryTrait.php | 2 +- Classes/Traits/InjectPageRendererTrait.php | 1 - Classes/Traits/InjectUriBuilderTrait.php | 2 +- 4 files changed, 3 insertions(+), 4 deletions(-) diff --git a/Classes/Controller/AbstractController.php b/Classes/Controller/AbstractController.php index b964b1c..75ef73c 100644 --- a/Classes/Controller/AbstractController.php +++ b/Classes/Controller/AbstractController.php @@ -25,7 +25,7 @@ abstract class AbstractController extends ActionController { use InjectIconFactoryTrait; - protected ?ModuleTemplate $moduleTemplate = null; + protected ModuleTemplate $moduleTemplate; public function __construct( protected readonly ModuleTemplateFactory $moduleTemplateFactory diff --git a/Classes/Traits/InjectIconFactoryTrait.php b/Classes/Traits/InjectIconFactoryTrait.php index 73fd023..cb0eefe 100644 --- a/Classes/Traits/InjectIconFactoryTrait.php +++ b/Classes/Traits/InjectIconFactoryTrait.php @@ -17,7 +17,7 @@ */ trait InjectIconFactoryTrait { - protected ?IconFactory $iconFactory = null; + protected IconFactory $iconFactory; public function injectIconFactory(IconFactory $iconFactory): void { diff --git a/Classes/Traits/InjectPageRendererTrait.php b/Classes/Traits/InjectPageRendererTrait.php index bed7e81..40aead6 100644 --- a/Classes/Traits/InjectPageRendererTrait.php +++ b/Classes/Traits/InjectPageRendererTrait.php @@ -11,7 +11,6 @@ namespace JWeiland\Jwtools2\Traits; use TYPO3\CMS\Core\Page\PageRenderer; -use TYPO3\CMS\Core\Registry; /** * Trait to inject InjectPageRenderer. Mostly used in controllers. diff --git a/Classes/Traits/InjectUriBuilderTrait.php b/Classes/Traits/InjectUriBuilderTrait.php index 82d9240..31b0581 100644 --- a/Classes/Traits/InjectUriBuilderTrait.php +++ b/Classes/Traits/InjectUriBuilderTrait.php @@ -17,7 +17,7 @@ */ trait InjectUriBuilderTrait { - protected ?UriBuilder $uriBuilder = null; + protected UriBuilder $uriBuilder; public function injectUriBuilder(UriBuilder $uriBuilder): void { From 0f72202aecf7d264a91d94f66a4bbeefd04fbf68 Mon Sep 17 00:00:00 2001 From: Hoja Mustaffa Abdul Latheef Date: Tue, 9 Apr 2024 09:20:51 +0200 Subject: [PATCH 59/65] Removed constructor as the DI used with a setter method --- Classes/Command/StatusReportCommand.php | 5 ----- 1 file changed, 5 deletions(-) diff --git a/Classes/Command/StatusReportCommand.php b/Classes/Command/StatusReportCommand.php index b8ae654..0e3d15a 100644 --- a/Classes/Command/StatusReportCommand.php +++ b/Classes/Command/StatusReportCommand.php @@ -38,11 +38,6 @@ class StatusReportCommand extends Command protected SymfonyStyle $ioStyled; - public function __construct() - { - parent::__construct('Start Report Command'); - } - public function configure(): void { $this From 54bac2ab39b108e2204a09ec7ecdeb5e2f25c8bb Mon Sep 17 00:00:00 2001 From: Hoja Mustaffa Abdul Latheef Date: Tue, 9 Apr 2024 09:33:31 +0200 Subject: [PATCH 60/65] Change return type to string for getTreeList function --- Classes/Database/Query/QueryGenerator.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Classes/Database/Query/QueryGenerator.php b/Classes/Database/Query/QueryGenerator.php index b9e846e..0cf64ff 100644 --- a/Classes/Database/Query/QueryGenerator.php +++ b/Classes/Database/Query/QueryGenerator.php @@ -24,7 +24,7 @@ class QueryGenerator /** * @throws Exception */ - public function getTreeList($id, $depth, $begin = 0, $permClause = ''): int|string + public function getTreeList($id, $depth, $begin = 0, $permClause = ''): string { $depth = (int)$depth; $begin = (int)$begin; @@ -64,7 +64,7 @@ public function getTreeList($id, $depth, $begin = 0, $permClause = ''): int|stri } } } - return $theList; + return (string)$theList; } public static function stripLogicalOperatorPrefix(string $constraint): string From d6c2af9e3f8b15360b2c5684561a1feee9437d0d Mon Sep 17 00:00:00 2001 From: Hoja Mustaffa Abdul Latheef Date: Tue, 9 Apr 2024 09:33:59 +0200 Subject: [PATCH 61/65] [TASK] Template cleanup - Cleanup templates which are not required anymore - Formating Fluid templates with space instead of tab intendation Resolves: # Releases: main, 12.4 --- .../Extensions/FileList/Templates/File.html | 32 -- .../Extensions/FileList/Templates/Folder.html | 39 -- .../ContentElement/ElementInformation.html | 443 +++++++++--------- .../Solr/CreateIndexQueueForAllSites.html | 52 +- .../Private/Templates/Tools/Overview.html | 4 +- 5 files changed, 251 insertions(+), 319 deletions(-) delete mode 100644 Resources/Private/Extensions/FileList/Templates/File.html delete mode 100644 Resources/Private/Extensions/FileList/Templates/Folder.html diff --git a/Resources/Private/Extensions/FileList/Templates/File.html b/Resources/Private/Extensions/FileList/Templates/File.html deleted file mode 100644 index f28ca33..0000000 --- a/Resources/Private/Extensions/FileList/Templates/File.html +++ /dev/null @@ -1,32 +0,0 @@ - - - - - - - - - {uploadFileForm -> f:format.raw()} - {createFolderForm -> f:format.raw()} - -

-
-
- {selectedFolderIcon -> f:format.raw()} {selectedFolderTitle} -
- - - -
-
-
diff --git a/Resources/Private/Extensions/FileList/Templates/Folder.html b/Resources/Private/Extensions/FileList/Templates/Folder.html deleted file mode 100644 index 3e4aab8..0000000 --- a/Resources/Private/Extensions/FileList/Templates/Folder.html +++ /dev/null @@ -1,39 +0,0 @@ - - - - - - - - - -

-
- - - {selectedFolderIcon -> f:format.raw()} {selectedFolderTitle} - - -
- {selectedFolderIcon -> f:format.raw()} {selectedFolderTitle} -
-
-
- - - -
-
- {createFolderForm -> f:format.raw()} -
diff --git a/Resources/Private/Templates/ContentElement/ElementInformation.html b/Resources/Private/Templates/ContentElement/ElementInformation.html index dbb564d..7ee395e 100644 --- a/Resources/Private/Templates/ContentElement/ElementInformation.html +++ b/Resources/Private/Templates/ContentElement/ElementInformation.html @@ -1,239 +1,242 @@ - -
-
+ +
+
-
-
- {icon -> f:format.raw()} -
+
+
+ {icon -> f:format.raw()} +
-
-

{title -> f:format.crop(maxCharacters: maxTitleLength)}[{extraFields.uid.fieldLabel}: {extraFields.uid.value}]

- - {table} - -
-
+
+

{title -> f:format.crop(maxCharacters: maxTitleLength)} + [{extraFields.uid.fieldLabel}: {extraFields.uid.value}] +

+ + {table} + +
+
-
-
- - -
- {extraField.fieldLabel}
- {extraField.value} -
-
-
-
- -
-
-
-
- {extraFields.creatorRecord.value.icon -> f:format.raw()} -
-
- {extraFields.creatorRecord.value.username}
- {extraFields.creatorRecord.value.realName} -
-
-
-
-
-
-
-
+
+
+ + +
+ {extraField.fieldLabel}
+ {extraField.value} +
+
+
+
+ +
+
+
+
+ {extraFields.creatorRecord.value.icon -> f:format.raw()} +
+
+ {extraFields.creatorRecord.value.username}
+ {extraFields.creatorRecord.value.realName} +
+
+
+
+
+
+
+
- - - {missingFile} - - -

- {fileRenderer -> f:format.raw()} -

-
- -

- -

-
- -

- - - - - - - - - - -

-
-
- - - - -
-
- - - - - - - -

-
- - - - - - - - - - - - - - - - - - - - -
-
-
- -

-
- - - - - - - - - - - - - - - - - - - - - -
-
-
-
- - {f:translate(key: 'LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.noEditPermission')} - + + {missingFile} + + +

+ {fileRenderer -> f:format.raw()} +

+
+ +

+ +

+
+ +

+ + + + + + + + + + +

+
+
+ + + + +
+
+ + + + + + + +

+
+ + + + + + + + + + + + + + + + + + + + +
+
+
+ +

+
+ + + + + + + + + + + + + + + + + + + + + +
+
+
+ + + {f:translate(key: 'LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.noEditPermission')} +
- - {row.fieldLabel} - {row.fieldValue} - + + {row.fieldLabel} + {row.fieldValue} + - - - - {line.icon -> f:format.raw()} - {line.recordTitle -> f:format.crop(maxCharacters: maxTitleLength)} - {line.title} - + + + + {line.icon -> f:format.raw()} + {line.recordTitle -> f:format.crop(maxCharacters: maxTitleLength)} + {line.title} + + {line.record.uid} - - - - - (uid={line.row.recuid} - {line.row.title} - - - - {line.path} - {line.labelForTableColumn} - {line.row.flexpointer} - {line.row.softref_key} - {line.row.sorting} - - - - + + + + + + (uid={line.row.recuid} + {line.row.title} + + + + {line.path} + {line.labelForTableColumn} + {line.row.flexpointer} + {line.row.softref_key} + {line.row.sorting} + + + + - - - - {line.icon -> f:format.raw()} - {line.recordTitle -> f:format.crop(maxCharacters: maxTitleLength)} - {line.title} - {line.row.ref_uid} - - - - (uid={line.row.recuid} - {line.row.title} - - - - {line.path} - {line.labelForTableColumn} - {line.row.flexpointer} - {line.row.softref_key} - {line.row.sorting} - {line.row.ref_string} - - - - + + + + {line.icon -> f:format.raw()} + {line.recordTitle -> f:format.crop(maxCharacters: maxTitleLength)} + {line.title} + {line.row.ref_uid} + + + + (uid={line.row.recuid} + {line.row.title} + + + + {line.path} + {line.labelForTableColumn} + {line.row.flexpointer} + {line.row.softref_key} + {line.row.sorting} + {line.row.ref_string} + + + + -
- - - - - - - - -
-
- - - -
- -
- - - -
-
+
+ + + + + + + + +
+
+ + + +
+ +
+ + + +
+
diff --git a/Resources/Private/Templates/Solr/CreateIndexQueueForAllSites.html b/Resources/Private/Templates/Solr/CreateIndexQueueForAllSites.html index ff11210..993c6c3 100644 --- a/Resources/Private/Templates/Solr/CreateIndexQueueForAllSites.html +++ b/Resources/Private/Templates/Solr/CreateIndexQueueForAllSites.html @@ -1,30 +1,30 @@ + xmlns:f="http://typo3.org/ns/TYPO3/CMS/Fluid/ViewHelpers" + data-namespace-typo3-fluid="true">

Result

- Indexed Items: {totalItemsAddedToIndexQueue} - - -
    -
  • Root Site: {site}
  • -
  • Results:
  • -
  • -
      -
    • IndexQueue: {queueName}
    • -
    • Status: - - - FINE - - - ERROR - - -
    • -
    -
  • -
-
-
+Indexed Items: {totalItemsAddedToIndexQueue} + + +
    +
  • Root Site: {site}
  • +
  • Results:
  • +
  • +
      +
    • IndexQueue: {queueName}
    • +
    • Status: + + + FINE + + + ERROR + + +
    • +
    +
  • +
+
+
diff --git a/Resources/Private/Templates/Tools/Overview.html b/Resources/Private/Templates/Tools/Overview.html index 45b9aef..7faf4ea 100644 --- a/Resources/Private/Templates/Tools/Overview.html +++ b/Resources/Private/Templates/Tools/Overview.html @@ -1,6 +1,6 @@ + xmlns:f="http://typo3.org/ns/TYPO3/CMS/Fluid/ViewHelpers" + data-namespace-typo3-fluid="true"> From 7348e77a0820b0af1b8b7ed3c1dbd1555cb0c78e Mon Sep 17 00:00:00 2001 From: Hoja Mustaffa Abdul Latheef Date: Tue, 9 Apr 2024 09:35:40 +0200 Subject: [PATCH 62/65] Missing comma issue --- Tests/Functional/Hooks/InitializeStdWrapTest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Tests/Functional/Hooks/InitializeStdWrapTest.php b/Tests/Functional/Hooks/InitializeStdWrapTest.php index 3834cb6..32611a2 100644 --- a/Tests/Functional/Hooks/InitializeStdWrapTest.php +++ b/Tests/Functional/Hooks/InitializeStdWrapTest.php @@ -26,7 +26,7 @@ class InitializeStdWrapTest extends FunctionalTestCase protected ExtensionConfiguration | MockObject $extensionConfigurationMock; protected array $coreExtensionsToLoad = [ - 'typo3/cms-scheduler' + 'typo3/cms-scheduler', ]; protected array $testExtensionsToLoad = [ From ee376fa546a63ddd972fd3e581e48277b1b2e3bb Mon Sep 17 00:00:00 2001 From: Hoja Mustaffa Abdul Latheef Date: Tue, 9 Apr 2024 09:36:09 +0200 Subject: [PATCH 63/65] Removed unwanted file created as part of commit error --- q | 15 --------------- 1 file changed, 15 deletions(-) delete mode 100644 q diff --git a/q b/q deleted file mode 100644 index 1adf3d3..0000000 --- a/q +++ /dev/null @@ -1,15 +0,0 @@ -[TASK] CR Fixes - -- https://github.com/jweiland-net/jwtools2/pull/74#discussion_r1549583142 -- https://github.com/jweiland-net/jwtools2/pull/74#discussion_r1549588058 - -# Please enter the commit message for your changes. Lines starting -# with '#' will be ignored, and an empty message aborts the commit. -# -# Date: Mon Apr 8 09:41:38 2024 +0200 -# -# On branch typo3_12_compatibility -# Changes to be committed: -# modified: Classes/Backend/SolrDocHeader.php -# modified: Classes/Command/ConvertPlainPasswordToHashCommand.php -# From c4db6f0b51c0e875eddda655452c89da0facf909 Mon Sep 17 00:00:00 2001 From: Hoja Mustaffa Abdul Latheef Date: Tue, 9 Apr 2024 09:37:08 +0200 Subject: [PATCH 64/65] Removed annotations which are not used --- Classes/Controller/SolrController.php | 1 - 1 file changed, 1 deletion(-) diff --git a/Classes/Controller/SolrController.php b/Classes/Controller/SolrController.php index 943d346..ca8de47 100644 --- a/Classes/Controller/SolrController.php +++ b/Classes/Controller/SolrController.php @@ -22,7 +22,6 @@ use JWeiland\Jwtools2\Traits\InjectSchedulerRepositoryTrait; use JWeiland\Jwtools2\Traits\InjectSolrRepositoryTrait; use Psr\Http\Message\ResponseInterface; -use TYPO3\CMS\Backend\Attribute\AsController; use TYPO3\CMS\Core\Database\Connection; use TYPO3\CMS\Core\Database\ConnectionPool; use TYPO3\CMS\Core\Type\ContextualFeedbackSeverity; From ec7cf2326180c3a23ab6fa0757df5b44d4b12207 Mon Sep 17 00:00:00 2001 From: Hoja Mustaffa Abdul Latheef Date: Tue, 9 Apr 2024 10:28:08 +0200 Subject: [PATCH 65/65] Removed addHelpButton implementation as it is no more valid and render empty.