diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 06285280..cedc0e2e 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -63,14 +63,69 @@ jobs: - "php:cs-fixer" php-version: - 8.2 - tests: + testV12: runs-on: ubuntu-latest strategy: max-parallel: 2 matrix: - php-versions: [8.1] + php-versions: [ 8.1, 8.2 ] typo3-versions: - - {typo3: 12, testing: ^7.0@dev} + - { typo3: 12, testing: ^7.0, phpunit: ^9, yaml: ^6, phpcov: ^8 } + + name: "Run tests with PHP ${{ matrix.php-versions }} + using TYPO3 ${{ matrix.typo3-versions.typo3 }} + with testing framework version ${{ matrix.typo3-versions.testing }}" + steps: + - uses: actions/checkout@v4 + + - uses: shivammathur/setup-php@v2 + with: + php-version: ${{ matrix.php-versions }} + extensions: intl, mbstring, pdo_sqlite + + - name: "Cache composer dependencies" + uses: actions/cache@v4 + with: + path: ~/.composer/cache + key: php-${{ matrix.php-versions }} + -typo3-${{ matrix.typo3-versions.typo3 }} + -phpunit-${{ matrix.typo3-versions.phpunit }} + -phpcov-${{ matrix.typo3-versions.phpcov }} + -yaml-${{ matrix.typo3-versions.yaml }} + -testing-${{ matrix.typo3-versions.testing }} + -composer-${{ hashFiles('composer.json') }} + restore-keys: | + php-${{ matrix.php-versions }} + -typo3-${{ matrix.typo3-versions.typo3 }} + -phpunit-${{ matrix.typo3-versions.phpunit }} + -phpcov-${{ matrix.typo3-versions.phpcov }} + -yaml-${{ matrix.typo3-versions.yaml }} + -testing-${{ matrix.typo3-versions.testing }}composer- + php-${{ matrix.php-versions }}-typo3- + + - name: "Install composer dependencies" + run: composer require typo3/minimal + "^${{ matrix.typo3-versions.typo3 }}" + typo3/testing-framework "${{ matrix.typo3-versions.testing }}" + phpunit/phpunit "${{ matrix.typo3-versions.phpunit }}" + phpunit/phpcov "${{ matrix.typo3-versions.phpcov }}" + symfony/yaml "${{ matrix.typo3-versions.yaml }}" + --prefer-dist --no-progress --no-suggest + + - name: "Run Unit tests" + run: composer ci:test:unit + + - name: "Functional tests" + run: composer ci:test:functional + + testsV13: + runs-on: ubuntu-latest + strategy: + max-parallel: 2 + matrix: + php-versions: [8.2, 8.3] + typo3-versions: + - {typo3: 13, testing: ^8.0, phpunit: ^10, yaml: ^7, phpcov: ^9 } name: "Run tests with PHP ${{ matrix.php-versions }} using TYPO3 ${{ matrix.typo3-versions.typo3 }} @@ -89,19 +144,28 @@ jobs: path: ~/.composer/cache key: php-${{ matrix.php-versions }} -typo3-${{ matrix.typo3-versions.typo3 }} + -phpunit-${{ matrix.typo3-versions.phpunit }} + -phpcov-${{ matrix.typo3-versions.phpcov }} + -yaml-${{ matrix.typo3-versions.yaml }} -testing-${{ matrix.typo3-versions.testing }} -composer-${{ hashFiles('composer.json') }} restore-keys: | php-${{ matrix.php-versions }} -typo3-${{ matrix.typo3-versions.typo3 }} + -phpunit-${{ matrix.typo3-versions.phpunit }} + -phpcov-${{ matrix.typo3-versions.phpcov }} + -yaml-${{ matrix.typo3-versions.yaml }} -testing-${{ matrix.typo3-versions.testing }}composer- php-${{ matrix.php-versions }}-typo3- - name: "Install composer dependencies" - run: composer require typo3/minimal + run: composer remove php-coveralls/php-coveralls --no-progress && composer require typo3/minimal "^${{ matrix.typo3-versions.typo3 }}" typo3/testing-framework "${{ matrix.typo3-versions.testing }}" - --prefer-dist --no-progress --no-suggest + phpunit/phpunit "${{ matrix.typo3-versions.phpunit }}" + phpunit/phpcov "${{ matrix.typo3-versions.phpcov }}" + symfony/yaml "${{ matrix.typo3-versions.yaml }}" + --prefer-dist --no-progress - name: "Run Unit tests" run: composer ci:test:unit diff --git a/.php-cs-fixer.php b/.php-cs-fixer.php index 52eeb886..59fc45de 100644 --- a/.php-cs-fixer.php +++ b/.php-cs-fixer.php @@ -10,6 +10,7 @@ $config = \TYPO3\CodingStandards\CsFixerConfig::create(); $config->getFinder()->in('Classes')->in('Configuration')->in('Tests'); $rules = $config->getRules(); +$rules['global_namespace_import'] = ['import_classes' => true, 'import_constants' => true, 'import_functions' => true]; $rules['ordered_imports'] = [ 'imports_order' => [ 'class', @@ -26,4 +27,4 @@ ]; $config->setRules($rules); -return $config; \ No newline at end of file +return $config; diff --git a/Classes/DataProcessing/DatabaseQueryProcessor.php b/Classes/DataProcessing/DatabaseQueryProcessor.php index f3289df0..21c108b2 100644 --- a/Classes/DataProcessing/DatabaseQueryProcessor.php +++ b/Classes/DataProcessing/DatabaseQueryProcessor.php @@ -17,6 +17,8 @@ use TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer; use TYPO3\CMS\Frontend\ContentObject\DataProcessorInterface; +use function json_decode; + /** * Fetch records from the database, using the default .select syntax from TypoScript. * @@ -109,13 +111,13 @@ public function process(ContentObjectRenderer $cObj, array $contentObjectConfigu $objConf = $this->typoScriptService->convertPlainArrayToTypoScriptArray(['fields' => $fields, '_typoScriptNodeValue' => 'JSON']); } - $processedRecordVariables[$key] = $objConf !== [] ? \json_decode($recordContentObjectRenderer->cObjGetSingle($objName, $objConf), true) : $record; + $processedRecordVariables[$key] = $objConf !== [] ? json_decode($recordContentObjectRenderer->cObjGetSingle($objName, $objConf), true) : $record; $processedRecordVariables[$key] = $this->contentDataProcessor->process($recordContentObjectRenderer, $processorConfiguration, $processedRecordVariables[$key]); if (isset($processorConfiguration['overrideFields.'])) { $overrideFields = $this->typoScriptService->convertTypoScriptArrayToPlainArray($processorConfiguration['overrideFields.']); $jsonCE = $this->typoScriptService->convertPlainArrayToTypoScriptArray(['fields' => $overrideFields, '_typoScriptNodeValue' => 'JSON']); - $record = \json_decode($recordContentObjectRenderer->cObjGetSingle('JSON', $jsonCE), true); + $record = json_decode($recordContentObjectRenderer->cObjGetSingle('JSON', $jsonCE), true); foreach ($record as $fieldName => $overrideData) { $processedRecordVariables[$key][$fieldName] = $overrideData; diff --git a/Classes/DataProcessing/ExtractPropertyProcessor.php b/Classes/DataProcessing/ExtractPropertyProcessor.php index 46b7ea40..6ce1bd28 100644 --- a/Classes/DataProcessing/ExtractPropertyProcessor.php +++ b/Classes/DataProcessing/ExtractPropertyProcessor.php @@ -11,6 +11,7 @@ namespace FriendsOfTYPO3\Headless\DataProcessing; +use Exception; use TYPO3\CMS\Core\Utility\GeneralUtility; use TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer; use TYPO3\CMS\Frontend\ContentObject\DataProcessorInterface; @@ -49,11 +50,11 @@ public function process( array $processedData ) { if (empty($processorConfiguration['as'])) { - throw new \Exception('Please specify property \'as\''); + throw new Exception('Please specify property \'as\''); } if (empty($processorConfiguration['key'])) { - throw new \Exception('Please specify property \'key\''); + throw new Exception('Please specify property \'key\''); } $targetFieldName = (string)$cObj->stdWrapValue( diff --git a/Classes/DataProcessing/FlexFormProcessor.php b/Classes/DataProcessing/FlexFormProcessor.php index 1b283484..1f74834e 100644 --- a/Classes/DataProcessing/FlexFormProcessor.php +++ b/Classes/DataProcessing/FlexFormProcessor.php @@ -17,6 +17,10 @@ use TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer; use TYPO3\CMS\Frontend\ContentObject\DataProcessorInterface; +use function is_array; +use function is_string; +use function json_decode; + /** * Basic TypoScript configuration: * Processing the field pi_flexform and overrides the values stored in data @@ -106,9 +110,9 @@ public function process(ContentObjectRenderer $cObj, array $contentObjectConfigu // processing the flexform data $originalValue = $processedData['data'][$fieldName] ?? $processedData[$fieldName]; - if (\is_array($originalValue)) { + if (is_array($originalValue)) { $flexformData = $originalValue; - } elseif (\is_string($originalValue)) { + } elseif (is_string($originalValue)) { $flexformData = $this->flexFormService->convertFlexFormContentToArray($originalValue); } else { return $processedData; @@ -149,7 +153,7 @@ public function processOverrideFields(array $data, array $flexformData, array $p $typoScriptService = GeneralUtility::makeInstance(TypoScriptService::class); $overrideFields = $typoScriptService->convertTypoScriptArrayToPlainArray($processorConfiguration['overrideFields.']); $jsonCE = $typoScriptService->convertPlainArrayToTypoScriptArray(['fields' => $overrideFields, '_typoScriptNodeValue' => 'JSON']); - $record = \json_decode($recordContentObjectRenderer->cObjGetSingle('JSON', $jsonCE), true); + $record = json_decode($recordContentObjectRenderer->cObjGetSingle('JSON', $jsonCE), true); foreach ($record as $fieldName => $overrideData) { $flexformData[$fieldName] = $overrideData; diff --git a/Classes/DataProcessing/MenuProcessor.php b/Classes/DataProcessing/MenuProcessor.php index 736464f9..615d905d 100644 --- a/Classes/DataProcessing/MenuProcessor.php +++ b/Classes/DataProcessing/MenuProcessor.php @@ -14,6 +14,8 @@ use TYPO3\CMS\Core\Utility\ArrayUtility; use TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer; +use function is_array; + /** * This menu processor utilizes HMENU to generate a json encoded menu * string that will be decoded again and assigned to JSON as @@ -143,7 +145,7 @@ public function buildConfiguration() { // Before rendering the actual menu via HMENU we want to update $this->menuLevelConfig $overwriteMenuLevelConfig = $this->getConfigurationValue('overwriteMenuLevelConfig.'); - if (\is_array($overwriteMenuLevelConfig)) { + if (is_array($overwriteMenuLevelConfig)) { ArrayUtility::mergeRecursiveWithOverrule($this->menuLevelConfig, $overwriteMenuLevelConfig); } @@ -151,7 +153,7 @@ public function buildConfiguration() // override built configuration $overwriteMenuConfig = $this->getConfigurationValue('overwriteMenuConfig.'); - if (\is_array($overwriteMenuConfig)) { + if (is_array($overwriteMenuConfig)) { ArrayUtility::mergeRecursiveWithOverrule($this->menuConfig, $overwriteMenuConfig); } } diff --git a/Classes/DataProcessing/RootSiteProcessing/SiteProvider.php b/Classes/DataProcessing/RootSiteProcessing/SiteProvider.php index 9de39d66..ea607285 100644 --- a/Classes/DataProcessing/RootSiteProcessing/SiteProvider.php +++ b/Classes/DataProcessing/RootSiteProcessing/SiteProvider.php @@ -12,10 +12,12 @@ namespace FriendsOfTYPO3\Headless\DataProcessing\RootSiteProcessing; use Doctrine\DBAL\Driver\Exception; +use InvalidArgumentException; use TYPO3\CMS\Core\Database\Connection; use TYPO3\CMS\Core\Database\ConnectionPool; use TYPO3\CMS\Core\Site\Entity\Site; use TYPO3\CMS\Core\Site\SiteFinder; + use TYPO3\CMS\Core\Utility\GeneralUtility; use function array_filter; @@ -23,6 +25,7 @@ use function array_values; use function count; use function in_array; +use function is_a; use function usort; class SiteProvider implements SiteProviderInterface @@ -84,8 +87,8 @@ public function prepare(array $config, int $siteUid): self $pages = $this->fetchPageData($sites, $config); if ($customSorting !== null) { - if (!\is_a($customSorting, SiteSortingInterface::class, true)) { - throw new \InvalidArgumentException('Invalid implementation of SiteSortingInterface'); + if (!is_a($customSorting, SiteSortingInterface::class, true)) { + throw new InvalidArgumentException('Invalid implementation of SiteSortingInterface'); } /** * @var SiteSortingInterface $sorting diff --git a/Classes/Event/Listener/AfterCacheableContentIsGeneratedListener.php b/Classes/Event/Listener/AfterCacheableContentIsGeneratedListener.php index ba2a0233..6d9ee326 100644 --- a/Classes/Event/Listener/AfterCacheableContentIsGeneratedListener.php +++ b/Classes/Event/Listener/AfterCacheableContentIsGeneratedListener.php @@ -15,7 +15,9 @@ use FriendsOfTYPO3\Headless\Seo\MetaHandler; use FriendsOfTYPO3\Headless\Utility\HeadlessMode; use FriendsOfTYPO3\Headless\Utility\HeadlessUserInt; +use Throwable; use TYPO3\CMS\Core\Utility\GeneralUtility; + use TYPO3\CMS\Frontend\Event\AfterCacheableContentIsGeneratedEvent; use function json_decode; @@ -51,7 +53,7 @@ public function __invoke(AfterCacheableContentIsGeneratedEvent $event) $content = $this->metaHandler->process($event->getRequest(), $event->getController(), $content); $event->getController()->content = $this->encoder->encode($content); - } catch (\Throwable $e) { + } catch (Throwable $e) { return; } } diff --git a/Classes/Event/Listener/RedirectUrlAdditionalParamsListener.php b/Classes/Event/Listener/RedirectUrlAdditionalParamsListener.php index 45571a78..9027ddfc 100644 --- a/Classes/Event/Listener/RedirectUrlAdditionalParamsListener.php +++ b/Classes/Event/Listener/RedirectUrlAdditionalParamsListener.php @@ -11,6 +11,7 @@ namespace FriendsOfTYPO3\Headless\Event\Listener; +use Exception; use FriendsOfTYPO3\Headless\Event\RedirectUrlEvent; use FriendsOfTYPO3\Headless\Utility\HeadlessFrontendUrlInterface; use Psr\Log\LoggerAwareInterface; @@ -22,6 +23,7 @@ use TYPO3\CMS\Core\Resource\Folder; use TYPO3\CMS\Core\Routing\PageRouter; use TYPO3\CMS\Core\Site\Entity\Site; + use TYPO3\CMS\Core\Utility\GeneralUtility; use function parse_str; @@ -82,7 +84,7 @@ public function __invoke(RedirectUrlEvent $event): void ); $event->setTargetUrl($frontendUrl); - } catch (\Exception $exception) { + } catch (Exception $exception) { $this->logError( 'Error during action redirect', ['record' => $event->getRedirectRecord(), 'uri' => $url] diff --git a/Classes/Seo/MetaHandler.php b/Classes/Seo/MetaHandler.php index bf8a573c..1f1aa2b3 100644 --- a/Classes/Seo/MetaHandler.php +++ b/Classes/Seo/MetaHandler.php @@ -11,6 +11,7 @@ namespace FriendsOfTYPO3\Headless\Seo; +use InvalidArgumentException; use Psr\EventDispatcher\EventDispatcherInterface; use Psr\Http\Message\ServerRequestInterface; use TYPO3\CMS\Core\MetaTag\MetaTagManagerRegistry; @@ -121,7 +122,7 @@ private function setMetaTag(string $type, string $name, string $content, array $ $type = strtolower($type); $name = strtolower($name); if (!in_array($type, ['property', 'name', 'http-equiv'], true)) { - throw new \InvalidArgumentException( + throw new InvalidArgumentException( 'When setting a meta tag the only types allowed are property, name or http-equiv. "' . $type . '" given.', 1496402460 ); diff --git a/Classes/Utility/FileUtility.php b/Classes/Utility/FileUtility.php index b7a9bdf0..d82869cf 100644 --- a/Classes/Utility/FileUtility.php +++ b/Classes/Utility/FileUtility.php @@ -14,7 +14,9 @@ use FriendsOfTYPO3\Headless\Event\EnrichFileDataEvent; use FriendsOfTYPO3\Headless\Event\FileDataAfterCropVariantProcessingEvent; use FriendsOfTYPO3\Headless\Utility\File\ProcessingConfiguration; +use InvalidArgumentException; use Psr\EventDispatcher\EventDispatcherInterface; +use RuntimeException; use Throwable; use TYPO3\CMS\Core\Configuration\Features; use TYPO3\CMS\Core\Http\NormalizedParams; @@ -26,8 +28,10 @@ use TYPO3\CMS\Core\Utility\GeneralUtility; use TYPO3\CMS\Extbase\Service\ImageService; use TYPO3\CMS\Extbase\Utility\LocalizationUtility; + use TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer; use TYPO3\CMS\Frontend\Typolink\LinkResultInterface; +use UnexpectedValueException; use function array_key_exists; use function array_merge; @@ -309,7 +313,7 @@ public function processImageFile( } return $this->imageService->applyProcessingInstructions($fileReference, $instructions); - } catch (\UnexpectedValueException|\RuntimeException|\InvalidArgumentException $e) { + } catch (UnexpectedValueException|RuntimeException|InvalidArgumentException $e) { $type = lcfirst(get_class($fileReference)); $status = get_class($e); $this->errors['processImageFile'][$type . '-' . $fileReference->getUid()] = $status; diff --git a/Classes/ViewHelpers/DomainViewHelper.php b/Classes/ViewHelpers/DomainViewHelper.php index fa66be2f..a4028825 100644 --- a/Classes/ViewHelpers/DomainViewHelper.php +++ b/Classes/ViewHelpers/DomainViewHelper.php @@ -11,6 +11,7 @@ namespace FriendsOfTYPO3\Headless\ViewHelpers; +use Closure; use FriendsOfTYPO3\Headless\Utility\UrlUtility; use TYPO3\CMS\Core\Utility\GeneralUtility; use TYPO3Fluid\Fluid\Core\Rendering\RenderingContextInterface; @@ -25,7 +26,7 @@ public function initializeArguments() public static function renderStatic( array $arguments, - \Closure $renderChildrenClosure, + Closure $renderChildrenClosure, RenderingContextInterface $renderingContext ) { $urlUtility = GeneralUtility::makeInstance(UrlUtility::class); diff --git a/Classes/ViewHelpers/Form/RegisterFieldViewHelper.php b/Classes/ViewHelpers/Form/RegisterFieldViewHelper.php index 82e17c61..e53f7873 100644 --- a/Classes/ViewHelpers/Form/RegisterFieldViewHelper.php +++ b/Classes/ViewHelpers/Form/RegisterFieldViewHelper.php @@ -11,6 +11,7 @@ namespace FriendsOfTYPO3\Headless\ViewHelpers\Form; +use Traversable; use TYPO3\CMS\Fluid\ViewHelpers\Form\AbstractFormFieldViewHelper; use TYPO3Fluid\Fluid\Core\ViewHelper\Exception; @@ -59,7 +60,7 @@ public function render() $propertyValue = $this->getPropertyValue(); } - if ($propertyValue instanceof \Traversable) { + if ($propertyValue instanceof Traversable) { $propertyValue = iterator_to_array($propertyValue); } if (is_array($propertyValue)) { diff --git a/Classes/ViewHelpers/Format/Json/DecodeViewHelper.php b/Classes/ViewHelpers/Format/Json/DecodeViewHelper.php index f3e85eaa..e9da0c89 100644 --- a/Classes/ViewHelpers/Format/Json/DecodeViewHelper.php +++ b/Classes/ViewHelpers/Format/Json/DecodeViewHelper.php @@ -9,6 +9,7 @@ namespace FriendsOfTYPO3\Headless\ViewHelpers\Format\Json; +use Exception; use TYPO3Fluid\Fluid\Core\ViewHelper\AbstractViewHelper; /** @@ -45,7 +46,7 @@ public function render() return $object; } if ($GLOBALS['TYPO3_CONF_VARS']['FE']['debug'] ?? false) { - throw new \Exception(sprintf( + throw new Exception(sprintf( 'Failure "%s" occured when running json_decode() for string: %s', json_last_error_msg(), $json diff --git a/Classes/ViewHelpers/Iterator/ExplodeViewHelper.php b/Classes/ViewHelpers/Iterator/ExplodeViewHelper.php index 705e4263..752d7aa8 100644 --- a/Classes/ViewHelpers/Iterator/ExplodeViewHelper.php +++ b/Classes/ViewHelpers/Iterator/ExplodeViewHelper.php @@ -65,7 +65,7 @@ protected function resolveGlue(): string $glue = $this->arguments['glue']; if (str_contains($glue, ':') && strlen($glue) > 1) { // glue contains a special type identifier, resolve the actual glue - list($type, $value) = explode(':', $glue); + [$type, $value] = explode(':', $glue); switch ($type) { case 'constant': $glue = constant($value); diff --git a/Classes/ViewHelpers/LoginFormViewHelper.php b/Classes/ViewHelpers/LoginFormViewHelper.php index e8d7b95a..0bc68e98 100644 --- a/Classes/ViewHelpers/LoginFormViewHelper.php +++ b/Classes/ViewHelpers/LoginFormViewHelper.php @@ -11,17 +11,20 @@ namespace FriendsOfTYPO3\Headless\ViewHelpers; +use LogicException; use Psr\Http\Message\RequestInterface; +use RuntimeException; use TYPO3\CMS\Core\Context\Context; use TYPO3\CMS\Core\Context\SecurityAspect; use TYPO3\CMS\Core\Security\RequestToken; use TYPO3\CMS\Core\Utility\GeneralUtility; use TYPO3\CMS\Extbase\DomainObject\AbstractDomainObject; + use TYPO3\CMS\Extbase\Persistence\Generic\LazyLoadingProxy; + use TYPO3\CMS\Fluid\ViewHelpers\FormViewHelper; use function base64_encode; - use function is_int; use function is_object; use function is_string; @@ -84,7 +87,7 @@ public function render(): string $renderingContext = $this->renderingContext; $request = $renderingContext->getRequest(); if (!$request instanceof RequestInterface) { - throw new \RuntimeException( + throw new RuntimeException( 'ViewHelper f:form can be used only in extbase context and needs a request implementing extbase RequestInterface.', 1639821904 ); @@ -271,7 +274,7 @@ protected function renderRequestTokenHiddenField(): string return ''; } if (strtolower((string)($this->arguments['method'] ?? '')) === 'get') { - throw new \LogicException('Cannot apply request token for forms sent via HTTP GET', 1651775963); + throw new LogicException('Cannot apply request token for forms sent via HTTP GET', 1651775963); } $context = GeneralUtility::makeInstance(Context::class); @@ -280,7 +283,7 @@ protected function renderRequestTokenHiddenField(): string $signingType = $signingType ?: 'nonce'; $signingProvider = $securityAspect->getSigningSecretResolver()->findByType($signingType); if ($signingProvider === null) { - throw new \LogicException(sprintf('Cannot find request token signing type "%s"', $signingType), 1664260307); + throw new LogicException(sprintf('Cannot find request token signing type "%s"', $signingType), 1664260307); } $signingSecret = $signingProvider->provideSigningSecret(); diff --git a/Classes/XClass/Preview/PreviewUriBuilder.php b/Classes/XClass/Preview/PreviewUriBuilder.php index d1eec263..adefbc1d 100644 --- a/Classes/XClass/Preview/PreviewUriBuilder.php +++ b/Classes/XClass/Preview/PreviewUriBuilder.php @@ -13,6 +13,7 @@ use FriendsOfTYPO3\Headless\Utility\HeadlessMode; use FriendsOfTYPO3\Headless\Utility\UrlUtility; +use InvalidArgumentException; use TYPO3\CMS\Core\Exception\SiteNotFoundException; use TYPO3\CMS\Core\Routing\InvalidRouteArgumentsException; use TYPO3\CMS\Core\Routing\UnableToLinkToPageException; @@ -43,7 +44,7 @@ public function buildUriForPage(int $uid, int $languageId = 0): string $site = $siteFinder->getSiteByPageId($uid); try { $language = $site->getLanguageById($languageId); - } catch (\InvalidArgumentException $e) { + } catch (InvalidArgumentException $e) { $language = $site->getDefaultLanguage(); } diff --git a/Classes/XClass/TemplateView.php b/Classes/XClass/TemplateView.php index 3d48dcc9..8710b5be 100644 --- a/Classes/XClass/TemplateView.php +++ b/Classes/XClass/TemplateView.php @@ -12,9 +12,11 @@ namespace FriendsOfTYPO3\Headless\XClass; use FriendsOfTYPO3\Headless\Utility\HeadlessMode; +use Throwable; use TYPO3\CMS\Core\Http\ApplicationType; use TYPO3\CMS\Core\Utility\GeneralUtility; use TYPO3Fluid\Fluid\Core\Rendering\RenderingContextInterface; + use TYPO3Fluid\Fluid\View\Exception\InvalidTemplateResourceException; use function extract; @@ -63,7 +65,7 @@ private function loadTemplate(string $templateFile, RenderingContextInterface $r ob_start(); include $templateFile; $__jsonContent = ob_get_clean(); - } catch (\Throwable $e) { + } catch (Throwable $e) { ob_end_clean(); throw $e; } diff --git a/Tests/Unit/ContentObject/JsonContentObjectTest.php b/Tests/Unit/ContentObject/JsonContentObjectTest.php index 30422068..bc58b15d 100644 --- a/Tests/Unit/ContentObject/JsonContentObjectTest.php +++ b/Tests/Unit/ContentObject/JsonContentObjectTest.php @@ -18,7 +18,10 @@ use FriendsOfTYPO3\Headless\ContentObject\JsonContentObject; use Prophecy\Argument; use Prophecy\PhpUnit\ProphecyTrait; +use Psr\EventDispatcher\EventDispatcherInterface; +use stdClass; use Symfony\Component\DependencyInjection\Container; +use TYPO3\CMS\Core\EventDispatcher\EventDispatcher; use TYPO3\CMS\Core\Http\ServerRequest; use TYPO3\CMS\Core\Service\MarkerBasedTemplateService; use TYPO3\CMS\Core\TimeTracker\TimeTracker; @@ -43,6 +46,7 @@ use TYPO3\CMS\Frontend\ContentObject\UserInternalContentObject; use TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController; use TYPO3\CMS\Frontend\DataProcessing\DataProcessorRegistry; + use TYPO3\TestingFramework\Core\Unit\UnitTestCase; use function json_encode; @@ -100,6 +104,7 @@ protected function setUp(): void }); $container = new Container(); + $container->set(EventDispatcherInterface::class, $this->prophesize(EventDispatcher::class)->reveal()); $container->set(ContentObjectFactory::class, $factory->reveal()); GeneralUtility::setContainer($container); @@ -161,7 +166,7 @@ public function dataProvider(): array [['fields.' => ['test' => 'TEXT', 'test.' => ['value' => 'false', 'boolval' => 1]]], json_encode(['test' => false])], [['fields.' => ['test' => 'TEXT', 'test.' => ['value' => '', 'ifEmptyReturnNull' => 0]]], json_encode(['test' => ''])], [['fields.' => ['test' => 'TEXT', 'test.' => ['value' => '', 'ifEmptyReturnNull' => 1]]], json_encode(['test' => null])], - [['fields.' => ['test' => 'TEXT', 'test.' => ['value' => null, 'stdWrap.' => ['ifEmpty' => '{}']]]], json_encode(['test' => new \stdClass()])], + [['fields.' => ['test' => 'TEXT', 'test.' => ['value' => null, 'stdWrap.' => ['ifEmpty' => '{}']]]], json_encode(['test' => new stdClass()])], [['fields.' => ['test' => 'TEXT', 'test.' => ['value' => '1']]], json_encode(['test' => '1'])], [['fields.' => ['test' => 'TEXT', 'test.' => ['value' => '1', 'intval' => 1]]], json_encode(['test' => 1])], [['fields.' => ['test' => 'TEXT', 'test.' => ['dataProcessing.' => ['10' => 'FriendsOfTYPO3\Headless\Tests\Unit\ContentObject\DataProcessingExample', '10.' => ['as' => 'sites'], '20' => 'FriendsOfTYPO3\Headless\Tests\Unit\ContentObject\DataProcessingExample', '20.' => ['as' => 'sites']]]]], json_encode(['test' => ['SomeCustomProcessing']])], diff --git a/Tests/Unit/DataProcessing/RootSitesProcessorTest.php b/Tests/Unit/DataProcessing/RootSitesProcessorTest.php index 7534a379..8e488dd1 100644 --- a/Tests/Unit/DataProcessing/RootSitesProcessorTest.php +++ b/Tests/Unit/DataProcessing/RootSitesProcessorTest.php @@ -14,8 +14,10 @@ use FriendsOfTYPO3\Headless\DataProcessing\RootSitesProcessor; use FriendsOfTYPO3\Headless\Tests\Unit\DataProcessing\RootSiteProcessing\TestDomainSchema; use FriendsOfTYPO3\Headless\Tests\Unit\DataProcessing\RootSiteProcessing\TestSiteProvider; +use InvalidArgumentException; use Prophecy\PhpUnit\ProphecyTrait; use Psr\Http\Message\ServerRequestInterface; +use stdClass; use TYPO3\CMS\Core\Utility\GeneralUtility; use TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer; use TYPO3\TestingFramework\Core\Unit\UnitTestCase; @@ -97,8 +99,8 @@ public function featureEnabledButWrongSiteProvider(): void $contentObjectRenderer->start([], 'tt_content'); $contentObjectRenderer->data['uid'] = 1; $conf = []; - $conf['siteProvider'] = \stdClass::class; - $this->expectException(\InvalidArgumentException::class); + $conf['siteProvider'] = stdClass::class; + $this->expectException(InvalidArgumentException::class); self::assertEquals([], $processor->process($contentObjectRenderer, [], $conf, [])); } @@ -114,8 +116,8 @@ public function featureEnabledButWrongSiteSchema(): void $contentObjectRenderer->start([], 'tt_content'); $contentObjectRenderer->data['uid'] = 1; $conf = []; - $conf['siteSchema'] = \stdClass::class; - $this->expectException(\InvalidArgumentException::class); + $conf['siteSchema'] = stdClass::class; + $this->expectException(InvalidArgumentException::class); self::assertEquals([], $processor->process($contentObjectRenderer, [], $conf, [])); } } diff --git a/Tests/Unit/Event/Listener/AfterCacheableContentIsGeneratedListenerTest.php b/Tests/Unit/Event/Listener/AfterCacheableContentIsGeneratedListenerTest.php index 55cb0f80..3c8579d4 100644 --- a/Tests/Unit/Event/Listener/AfterCacheableContentIsGeneratedListenerTest.php +++ b/Tests/Unit/Event/Listener/AfterCacheableContentIsGeneratedListenerTest.php @@ -84,7 +84,7 @@ public function testNotModifiedWhileValidJson(): void $controller = $this->prophesize(TypoScriptFrontendController::class); $controller->content = $content; - $controller->generatePageTitle()->willReturn('Modified title via PageTitleManager'); + $controller->generatePageTitle($request)->willReturn('Modified title via PageTitleManager'); $event = new AfterCacheableContentIsGeneratedEvent($request->reveal(), $controller->reveal(), 'abc', false); @@ -106,7 +106,7 @@ public function testNotModifiedWhenUserIntContent(): void $controller = $this->prophesize(TypoScriptFrontendController::class); $controller->content = $content; - $controller->generatePageTitle()->willReturn('Modified title via PageTitleManager'); + $controller->generatePageTitle($request)->willReturn('Modified title via PageTitleManager'); $event = new AfterCacheableContentIsGeneratedEvent($request->reveal(), $controller->reveal(), 'abc', false); @@ -131,7 +131,7 @@ public function testModifiedPageTitle(): void $controller = $this->prophesize(TypoScriptFrontendController::class); $controller->content = json_encode(['meta' => ['title' => 'test before event'], 'seo' => ['title' => 'test before event']]); $controller->cObj = $this->prophesize(ContentObjectRenderer::class)->reveal(); - $controller->generatePageTitle()->willReturn('Modified title via PageTitleProviderManager'); + $controller->generatePageTitle($request)->willReturn('Modified title via PageTitleProviderManager'); $event = new AfterCacheableContentIsGeneratedEvent($request->reveal(), $controller->reveal(), 'abc', false); @@ -162,7 +162,7 @@ public function testHreflangs(): void $controller = $this->prophesize(TypoScriptFrontendController::class); $controller->content = json_encode(['meta' => ['title' => 'test before event'], 'seo' => ['title' => 'test before event']]); $controller->cObj = $this->prophesize(ContentObjectRenderer::class)->reveal(); - $controller->generatePageTitle()->willReturn('Modified title via PageTitleProviderManager'); + $controller->generatePageTitle($request)->willReturn('Modified title via PageTitleProviderManager'); $registry = GeneralUtility::makeInstance(MetaTagManagerRegistry::class); $registry->registerManager('html5', Html5MetaTagManager::class); diff --git a/Tests/Unit/Event/Listener/RedirectUrlAdditionalParamsListenerTest.php b/Tests/Unit/Event/Listener/RedirectUrlAdditionalParamsListenerTest.php index fec44894..92df106e 100644 --- a/Tests/Unit/Event/Listener/RedirectUrlAdditionalParamsListenerTest.php +++ b/Tests/Unit/Event/Listener/RedirectUrlAdditionalParamsListenerTest.php @@ -16,6 +16,7 @@ use FriendsOfTYPO3\Headless\Utility\Headless; use FriendsOfTYPO3\Headless\Utility\HeadlessMode; use FriendsOfTYPO3\Headless\Utility\UrlUtility; +use InvalidArgumentException; use Prophecy\Argument; use Prophecy\PhpUnit\ProphecyTrait; use Psr\Http\Message\UriInterface; @@ -188,7 +189,7 @@ public function invokeWithLanguageTest() self::assertSame((string)$expectedUri, $newRedirectEvent->getTargetUrl()); $site = $this->createPartialMock(Site::class, ['getLanguageById']); - $site->method('getLanguageById')->willThrowException(new \InvalidArgumentException('test')); + $site->method('getLanguageById')->willThrowException(new InvalidArgumentException('test')); $request = $request->withAttribute('site', $site); $redirectEvent = new RedirectUrlEvent( diff --git a/Tests/Unit/Json/JsonDecoderTest.php b/Tests/Unit/Json/JsonDecoderTest.php index 932dde52..090adce2 100644 --- a/Tests/Unit/Json/JsonDecoderTest.php +++ b/Tests/Unit/Json/JsonDecoderTest.php @@ -12,7 +12,9 @@ namespace FriendsOfTYPO3\Headless\Tests\Unit\ContentObject; use FriendsOfTYPO3\Headless\Json\JsonDecoder; +use stdClass; use TYPO3\CMS\Core\Utility\GeneralUtility; + use TYPO3\TestingFramework\Core\Unit\UnitTestCase; use function array_fill; @@ -45,7 +47,7 @@ public function testDecoding(): void { $jsonDecoder = GeneralUtility::makeInstance(JsonDecoder::class); - $class = new \stdClass(); + $class = new stdClass(); $class->test = 1; $class->testProp = true; diff --git a/Tests/Unit/Json/JsonEncoderTest.php b/Tests/Unit/Json/JsonEncoderTest.php index 3dbce84a..e911970c 100644 --- a/Tests/Unit/Json/JsonEncoderTest.php +++ b/Tests/Unit/Json/JsonEncoderTest.php @@ -12,7 +12,9 @@ namespace FriendsOfTYPO3\Headless\Tests\Unit\ContentObject; use FriendsOfTYPO3\Headless\Json\JsonEncoder; +use stdClass; use TYPO3\CMS\Core\Utility\GeneralUtility; + use TYPO3\TestingFramework\Core\Unit\UnitTestCase; use function json_encode; @@ -53,7 +55,7 @@ public function jsonProvider(): array return [ [[], '[]'], [['test' => 1], '{"test":1}'], - [new \stdClass(), '{}'], + [new stdClass(), '{}'], ["\xB1\x31", '[]'], // exception caught, return empty array instead ]; } diff --git a/Tests/Unit/Middleware/ShortcutAndMountPointRedirectTest.php b/Tests/Unit/Middleware/ShortcutAndMountPointRedirectTest.php index 687cb7d1..9f1b8589 100644 --- a/Tests/Unit/Middleware/ShortcutAndMountPointRedirectTest.php +++ b/Tests/Unit/Middleware/ShortcutAndMountPointRedirectTest.php @@ -14,16 +14,21 @@ use FriendsOfTYPO3\Headless\Middleware\ShortcutAndMountPointRedirect; use FriendsOfTYPO3\Headless\Utility\Headless; use FriendsOfTYPO3\Headless\Utility\HeadlessMode; +use FriendsOfTYPO3\Headless\Utility\UrlUtility; use Prophecy\Argument; use Prophecy\PhpUnit\ProphecyTrait; +use Symfony\Component\DependencyInjection\Container; use TYPO3\CMS\Core\Domain\Repository\PageRepository; +use TYPO3\CMS\Core\ExpressionLanguage\Resolver; use TYPO3\CMS\Core\Http\HtmlResponse; use TYPO3\CMS\Core\Http\NormalizedParams; use TYPO3\CMS\Core\Http\RedirectResponse; use TYPO3\CMS\Core\Http\ServerRequest; use TYPO3\CMS\Core\Http\Uri; use TYPO3\CMS\Core\Site\Entity\Site; +use TYPO3\CMS\Core\Site\SiteFinder; use TYPO3\CMS\Core\TypoScript\TemplateService; +use TYPO3\CMS\Core\Utility\GeneralUtility; use TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController; use TYPO3\CMS\Frontend\Http\RequestHandler; use TYPO3\TestingFramework\Core\Unit\UnitTestCase; @@ -37,6 +42,16 @@ class ShortcutAndMountPointRedirectTest extends UnitTestCase */ public function processTest() { + $request = new ServerRequest(); + + $urlUtility = new UrlUtility(null, $this->createMock(Resolver::class), $this->createMock(SiteFinder::class), null); + $urlUtility->withRequest($request); + + $container = new Container(); + $container->set(UrlUtility::class, $urlUtility); + + GeneralUtility::setContainer($container); + $genericHtml = 'test'; $linkRedirect = 'https://test.domain2.tld'; $genericResponse = new HtmlResponse($genericHtml); @@ -76,7 +91,7 @@ public function processTest() ['mode' => HeadlessMode::FULL] ))); $shortcutJsonDecoded = [ - 'redirectUrl' => '/shortcut-target', + 'redirectUrl' => 'https://test.domain.tld/shortcut-target', 'statusCode' => 307, ]; @@ -165,7 +180,6 @@ public function redirectProvider(): array return [ ['user@tes@t', $domain . 'user@tes@t'], ['user@test.com', 'mailto:user@test.com'], - ['/false/url:1', '/false/url:1'], ['/relative-url', '/relative-url'], ]; } diff --git a/Tests/Unit/Utility/FileUtilityTest.php b/Tests/Unit/Utility/FileUtilityTest.php index f980c44a..67df0cfb 100644 --- a/Tests/Unit/Utility/FileUtilityTest.php +++ b/Tests/Unit/Utility/FileUtilityTest.php @@ -14,10 +14,13 @@ use FriendsOfTYPO3\Headless\Resource\Rendering\YouTubeRenderer; use FriendsOfTYPO3\Headless\Utility\File\ProcessingConfiguration; use FriendsOfTYPO3\Headless\Utility\FileUtility; +use InvalidArgumentException; use Prophecy\Argument; use Prophecy\PhpUnit\ProphecyTrait; use Prophecy\Prophecy\ObjectProphecy; +use RuntimeException; use Symfony\Component\DependencyInjection\Container; +use Throwable; use TYPO3\CMS\Core\Configuration\Features; use TYPO3\CMS\Core\EventDispatcher\EventDispatcher; use TYPO3\CMS\Core\EventDispatcher\ListenerProvider; @@ -33,9 +36,11 @@ use TYPO3\CMS\Core\Resource\Rendering\RendererRegistry; use TYPO3\CMS\Core\Resource\ResourceStorage; use TYPO3\CMS\Extbase\Service\ImageService; + use TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer; use TYPO3\CMS\Frontend\Typolink\LinkResult; use TYPO3\TestingFramework\Core\Unit\UnitTestCase; +use UnexpectedValueException; use function array_merge; @@ -454,9 +459,9 @@ public function testCustomProcessingOptions(): void public function testExceptionCatching(): void { - $this->testProcessImageFileException(new \UnexpectedValueException('test')); - $this->testProcessImageFileException(new \RuntimeException('test')); - $this->testProcessImageFileException(new \InvalidArgumentException('test')); + $this->testProcessImageFileException(new UnexpectedValueException('test')); + $this->testProcessImageFileException(new RuntimeException('test')); + $this->testProcessImageFileException(new InvalidArgumentException('test')); } protected function getFileUtility( @@ -803,7 +808,7 @@ protected function testProcessImageFileException($exception): void try { $fileUtility->processImageFile($fileReference, ProcessingConfiguration::fromOptions([])); - } catch (\Throwable $throwable) { + } catch (Throwable $throwable) { if (!empty($fileUtility->getErrors()['processImageFile'])) { $errors = $fileUtility->getErrors()['processImageFile']; if (reset($errors) !== get_class($exception)) { diff --git a/Tests/Unit/XClass/TemplateViewTest.php b/Tests/Unit/XClass/TemplateViewTest.php index 36f6a267..a3197b49 100644 --- a/Tests/Unit/XClass/TemplateViewTest.php +++ b/Tests/Unit/XClass/TemplateViewTest.php @@ -14,6 +14,7 @@ use FriendsOfTYPO3\Headless\Utility\Headless; use FriendsOfTYPO3\Headless\Utility\HeadlessMode; use FriendsOfTYPO3\Headless\XClass\TemplateView; +use RuntimeException; use TYPO3\CMS\Core\Http\ServerRequest; use TYPO3\CMS\Fluid\Core\Rendering\RenderingContext; use TYPO3\CMS\Fluid\Core\ViewHelper\ViewHelperResolver; @@ -21,6 +22,7 @@ use TYPO3\TestingFramework\Core\Unit\UnitTestCase; use TYPO3Fluid\Fluid\Core\Cache\FluidCacheInterface; use TYPO3Fluid\Fluid\Core\Variables\StandardVariableProvider; + use TYPO3Fluid\Fluid\View\Exception\InvalidTemplateResourceException; use function json_encode; @@ -137,7 +139,7 @@ public function testExceptionInTemplate(): void $context->setTemplatePaths($templatePaths); - $this->expectException(\RuntimeException::class); + $this->expectException(RuntimeException::class); $this->expectExceptionMessage('Example exception in template'); $view = new TemplateView($context); diff --git a/composer.json b/composer.json index 5be2f056..b1feba1a 100644 --- a/composer.json +++ b/composer.json @@ -32,21 +32,21 @@ "typo3/cms-install": "^12.4 || ^13.3" }, "require-dev": { - "ergebnis/composer-normalize": "^2.15.0", - "friendsofphp/php-cs-fixer": "^3.1", + "ergebnis/composer-normalize": "^2.43", + "friendsofphp/php-cs-fixer": "^v3", "helmich/typo3-typoscript-lint": "^v3", - "justinrainbow/json-schema": "^5.2", - "php-coveralls/php-coveralls": "^2.5.2", - "phpspec/prophecy-phpunit": "^2.0", + "justinrainbow/json-schema": "^5", + "php-coveralls/php-coveralls": "^2", + "phpspec/prophecy-phpunit": "^2", "phpstan/extension-installer": "^1.1", - "phpstan/phpstan": "^1.9", - "phpunit/phpcov": "^8.2", + "phpstan/phpstan": "^1.12", + "phpunit/phpcov": "^8 || ^9 ", "saschaegerer/phpstan-typo3": "^1.1", - "seld/jsonlint": "^1.8", - "symfony/yaml": "^6.1", - "typo3/cms-form": "^12.4", - "typo3/testing-framework": "^7.0", - "typo3/coding-standards": "^0.7.1" + "seld/jsonlint": "^1.11", + "symfony/yaml": "^6.1 || ^7.1", + "typo3/cms-form": "^12.4 || ^13.3", + "typo3/testing-framework": "^8.0", + "typo3/coding-standards": "^0.8" }, "conflict": { "typo3/cms-core": "<12.4.3"