From 85c9037d278942f5cc4f3f36def93e8110af4c67 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Wolda=C5=84ski?= Date: Wed, 21 Aug 2024 16:18:48 +0200 Subject: [PATCH] [FEATURE] Add TYPO3 v13 compatibility - adjust tests for T3v13 --- .github/workflows/ci.yaml | 74 ++++- .../JsonContentContentObject.php | 51 +++- .../ShortcutAndMountPointRedirect.php | 113 +------- Classes/Seo/CanonicalGenerator.php | 67 ++--- Classes/Seo/MetaHandler.php | 2 +- .../Controller/FormFrontendController.php | 83 ++++-- Classes/XClass/ResourceLocalDriver.php | 4 +- .../SiteConfiguration/Overrides/site.php | 1 - Tests/Functional/BaseTest.php | 5 + .../ContentTypes/BaseContentTypeTest.php | 2 +- .../ContentTypes/BasicListElementTest.php | 2 +- .../ContentTypes/BulletsElementTest.php | 2 +- .../ContentTypes/DefaultContentsTest.php | 2 +- .../ContentTypes/DivElementTest.php | 2 +- .../ContentTypes/HeaderElementTest.php | 2 +- .../ContentTypes/HtmlElementTest.php | 2 +- .../ContentTypes/ImageElementTest.php | 2 +- .../MenuAbstractPagesElementTest.php | 2 +- .../MenuCategorizedContentElementTest.php | 2 +- .../MenuCategorizedPagesElementTest.php | 2 +- .../ContentTypes/MenuPagesElementTest.php | 2 +- .../MenuRecentlyUpdatedPagesElementTest.php | 2 +- .../MenuRelatedPagesElementTest.php | 2 +- .../ContentTypes/MenuSectionElementTest.php | 2 +- .../ContentTypes/MenuSitemapElementTest.php | 2 +- .../MenuSitemapSelectedPagesElementTest.php | 2 +- .../ContentTypes/MenuSubpagesElementTest.php | 2 +- .../ContentTypes/ShortcutElementTest.php | 2 +- .../ContentTypes/TableElementTest.php | 2 +- .../ContentTypes/TextElementTest.php | 2 +- .../ContentTypes/TextMediaElementTest.php | 2 +- .../ContentTypes/TextpicElementTest.php | 2 +- .../PageTypes/BasePageTypesTest.php | 2 +- .../PageTypes/SchemaPageTypesTest.php | 4 +- .../PageTypes/StructurePageTypesTest.php | 2 +- .../BooleanContentObjectTest.php | 2 +- .../ContentObject/FloatContentObjectTest.php | 2 +- .../IntegerContentObjectTest.php | 2 +- .../ContentObject/JsonContentObjectTest.php | 23 +- .../DataProcessingTraitTest.php | 2 +- ...acheableContentIsGeneratedListenerTest.php | 8 +- .../AfterLinkIsGeneratedListenerTest.php | 14 +- ...edirectUrlAdditionalParamsListenerTest.php | 13 +- Tests/Unit/Hooks/HeadlessUserIntTest.php | 60 ---- Tests/Unit/Json/JsonDecoderTest.php | 2 +- Tests/Unit/Json/JsonEncoderTest.php | 2 +- .../ShortcutAndMountPointRedirectTest.php | 273 ------------------ .../Unit/Middleware/UserIntMiddlewareTest.php | 2 +- composer.json | 26 +- 49 files changed, 299 insertions(+), 586 deletions(-) delete mode 100644 Tests/Unit/Middleware/ShortcutAndMountPointRedirectTest.php diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 06285280..d4e8c1b2 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: ^10, phpcov: ^9, yaml: ^6 } + + 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: ^11, phpcov: ^10, yaml: ^7 } 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 --dev --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/Classes/ContentObject/JsonContentContentObject.php b/Classes/ContentObject/JsonContentContentObject.php index 3f717984..5437deeb 100755 --- a/Classes/ContentObject/JsonContentContentObject.php +++ b/Classes/ContentObject/JsonContentContentObject.php @@ -14,7 +14,10 @@ use FriendsOfTYPO3\Headless\Json\JsonEncoder; use FriendsOfTYPO3\Headless\Json\JsonEncoderInterface; use FriendsOfTYPO3\Headless\Utility\HeadlessUserInt; +use Psr\EventDispatcher\EventDispatcherInterface; use TYPO3\CMS\Backend\View\BackendLayoutView; +use TYPO3\CMS\Core\Information\Typo3Version; +use TYPO3\CMS\Core\TimeTracker\TimeTracker; use TYPO3\CMS\Core\Utility\GeneralUtility; use TYPO3\CMS\Frontend\ContentObject\ContentContentObject; use TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer; @@ -23,6 +26,7 @@ use function count; use function is_array; use function json_decode; +use function json_encode; use function str_contains; use function trim; @@ -102,11 +106,18 @@ class JsonContentContentObject extends ContentContentObject { private HeadlessUserInt $headlessUserInt; private JsonEncoderInterface $jsonEncoder; + /** + * @var mixed|object|\Psr\Log\LoggerAwareInterface|\TYPO3\CMS\Core\SingletonInterface|TimeTracker|(TimeTracker&\Psr\Log\LoggerAwareInterface)|(TimeTracker&\TYPO3\CMS\Core\SingletonInterface)|null + */ + private TimeTracker $timeTracker; + private EventDispatcherInterface $eventDispatcher; public function __construct() { $this->headlessUserInt = GeneralUtility::makeInstance(HeadlessUserInt::class); $this->jsonEncoder = GeneralUtility::makeInstance(JsonEncoder::class); + $this->timeTracker = GeneralUtility::makeInstance(TimeTracker::class); + $this->eventDispatcher = GeneralUtility::makeInstance(EventDispatcherInterface::class); } /** @@ -199,6 +210,8 @@ protected function groupContentElementsByColPos(array $contentElements, array $c */ private function prepareValue(array $conf): array { + $t3v13andAbove = (new Typo3Version())->getMajorVersion() >= 13; + $frontendController = $this->getTypoScriptFrontendController(); $theValue = []; $originalRec = $frontendController->currentRecord; @@ -233,20 +246,44 @@ private function prepareValue(array $conf): array $tmpValue = ''; do { - $records = $this->cObj->getRecords($conf['table'], $conf['select.']); + if ($t3v13andAbove) { + $modifyRecordsEvent = $this->eventDispatcher->dispatch( + new \TYPO3\CMS\Frontend\ContentObject\Event\ModifyRecordsAfterFetchingContentEvent( + $this->cObj->getRecords($conf['table'], $conf['select.']), + json_encode($theValue, JSON_THROW_ON_ERROR), + $slide, + $slideCollect, + $slideCollectReverse, + $slideCollectFuzzy, + $conf + ) + ); + + $records = $modifyRecordsEvent->getRecords(); + $theValue = json_decode($modifyRecordsEvent->getFinalContent(), true, 512, JSON_THROW_ON_ERROR); + $slide = $modifyRecordsEvent->getSlide(); + $slideCollect = $modifyRecordsEvent->getSlideCollect(); + $slideCollectReverse = $modifyRecordsEvent->getSlideCollectReverse(); + $slideCollectFuzzy = $modifyRecordsEvent->getSlideCollectFuzzy(); + $conf = $modifyRecordsEvent->getConfiguration(); + } else { + $records = $this->cObj->getRecords($conf['table'], $conf['select.']); + } $cobjValue = []; if (!empty($records)) { - $this->getTimeTracker()->setTSlogMessage('NUMROWS: ' . count($records)); + $this->timeTracker->setTSlogMessage('NUMROWS: ' . count($records)); $cObj = GeneralUtility::makeInstance(ContentObjectRenderer::class, $frontendController); $cObj->setParent($this->cObj->data, $this->cObj->currentRecord); $this->cObj->currentRecordNumber = 0; foreach ($records as $row) { - // Call hook for possible manipulation of database row for cObj->data - foreach ($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['tslib/class.tslib_content_content.php']['modifyDBRow'] ?? [] as $className) { - $_procObj = GeneralUtility::makeInstance($className); - $_procObj->modifyDBRow($row, $conf['table']); + if (!$t3v13andAbove) { + // Call hook for possible manipulation of database row for cObj->data + foreach ($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['tslib/class.tslib_content_content.php']['modifyDBRow'] ?? [] as $className) { + $_procObj = GeneralUtility::makeInstance($className); + $_procObj->modifyDBRow($row, $conf['table']); + } } $registerField = $conf['table'] . ':' . ($row['uid'] ?? 0); if (!($frontendController->recordRegister[$registerField] ?? false)) { @@ -282,7 +319,7 @@ private function prepareValue(array $conf): array } $again = (string)$conf['select.']['pidInList'] !== ''; } - } while ($again && $slide && ((string)$tmpValue === '' && $slideCollectFuzzy || $slideCollect)); + } while ($again && $slide && (((string)$tmpValue === '' && $slideCollectFuzzy) || $slideCollect)); $theValue = $this->groupContentElementsByColPos($theValue, $conf); // Restore diff --git a/Classes/Middleware/ShortcutAndMountPointRedirect.php b/Classes/Middleware/ShortcutAndMountPointRedirect.php index 8c644bfa..0c8b15b9 100644 --- a/Classes/Middleware/ShortcutAndMountPointRedirect.php +++ b/Classes/Middleware/ShortcutAndMountPointRedirect.php @@ -12,29 +12,16 @@ namespace FriendsOfTYPO3\Headless\Middleware; use FriendsOfTYPO3\Headless\Utility\HeadlessMode; +use FriendsOfTYPO3\Headless\Utility\UrlUtility; use Psr\Http\Message\ResponseInterface; use Psr\Http\Message\ServerRequestInterface; -use Psr\Http\Server\MiddlewareInterface; use Psr\Http\Server\RequestHandlerInterface; -use Psr\Log\LoggerAwareInterface; -use Psr\Log\LoggerAwareTrait; -use TYPO3\CMS\Core\Domain\Repository\PageRepository; -use TYPO3\CMS\Core\Http\ImmediateResponseException; use TYPO3\CMS\Core\Http\JsonResponse; use TYPO3\CMS\Core\Http\RedirectResponse; -use TYPO3\CMS\Core\Routing\PageArguments; use TYPO3\CMS\Core\Utility\GeneralUtility; -use TYPO3\CMS\Frontend\Controller\ErrorController; -use TYPO3\CMS\Frontend\Page\PageAccessFailureReasons; - -use function is_array; -use function parse_url; - -class ShortcutAndMountPointRedirect implements MiddlewareInterface, LoggerAwareInterface +class ShortcutAndMountPointRedirect extends \TYPO3\CMS\Frontend\Middleware\ShortcutAndMountPointRedirect { - use LoggerAwareTrait; - public function __construct(private readonly HeadlessMode $headlessMode) {} public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface @@ -46,96 +33,18 @@ public function process(ServerRequestInterface $request, RequestHandlerInterface return $handler->handle($request); } - $exposeInformation = $GLOBALS['TYPO3_CONF_VARS']['FE']['exposeRedirectInformation'] ?? false; - - // Check for shortcut page and mount point redirect - try { - $redirectToUri = $this->getRedirectUri($request); - } catch (ImmediateResponseException $e) { - return $e->getResponse(); - } - if ($redirectToUri !== null && $redirectToUri !== (string)$request->getUri()) { - /** @var PageArguments $pageArguments */ - $pageArguments = $request->getAttribute('routing', null); - $message = 'TYPO3 Shortcut/Mountpoint' . ($exposeInformation ? ' at page with ID ' . $pageArguments->getPageId() : ''); - - if ($this->isHeadlessEnabled($request)) { - $parsed = parse_url($redirectToUri); - if (is_array($parsed)) { - $path = $parsed['path'] ?? '/'; - return new JsonResponse(['redirectUrl' => $path, 'statusCode' => 307]); - } - } - - return new RedirectResponse( - $redirectToUri, - 307, - ['X-Redirect-By' => $message] - ); - } - - // See if the current page is of doktype "External URL", if so, do a redirect as well. - $controller = $request->getAttribute('frontend.controller'); - if ((int)$controller->page['doktype'] === PageRepository::DOKTYPE_LINK) { - $externalUrl = $this->prefixExternalPageUrl( - $controller->page['url'], - $request->getAttribute('normalizedParams')->getSiteUrl() - ); - $message = 'TYPO3 External URL' . ($exposeInformation ? ' at page with ID ' . $controller->page['uid'] : ''); - if (!empty($externalUrl)) { - if ($this->isHeadlessEnabled($request)) { - return new JsonResponse(['redirectUrl' => $externalUrl, 'statusCode' => 303]); - } + $coreResponse = parent::process($request, $handler); - return new RedirectResponse( - $externalUrl, - 303, - ['X-Redirect-By' => $message] - ); - } - $this->logger->error( - 'Page of type "External URL" could not be resolved properly', - [ - 'page' => $controller->page, - ] - ); - return GeneralUtility::makeInstance(ErrorController::class)->pageNotFoundAction( - $request, - 'Page of type "External URL" could not be resolved properly', - $controller->getPageAccessFailureReasons(PageAccessFailureReasons::INVALID_EXTERNAL_URL) - ); + if ($coreResponse instanceof RedirectResponse && $this->isHeadlessEnabled($request)) { + return new JsonResponse([ + 'redirectUrl' => GeneralUtility::makeInstance(UrlUtility::class) + ->withRequest($request) + ->prepareRelativeUrlIfPossible($coreResponse->getHeader('location')[0] ?? ''), + 'statusCode' => $coreResponse->getStatusCode(), + ]); } - return $handler->handle($request); - } - - protected function getRedirectUri(ServerRequestInterface $request): ?string - { - $controller = $request->getAttribute('frontend.controller'); - $redirectToUri = $controller->getRedirectUriForShortcut($request); - return $redirectToUri ?? $controller->getRedirectUriForMountPoint($request); - } - - /** - * Returns the redirect URL for the input page row IF the doktype is set to 3. - * - * @param string $redirectTo The page row to return URL type for - * @param string $sitePrefix if no protocol or relative path given, the site prefix is added - * @return string The URL from based on the external page URL given with a prefix. - */ - protected function prefixExternalPageUrl(string $redirectTo, string $sitePrefix): string - { - $uI = parse_url($redirectTo); - // If relative path, prefix Site URL - // If it's a valid email without protocol, add "mailto:" - if (!($uI['scheme'] ?? false)) { - if (GeneralUtility::validEmail($redirectTo)) { - $redirectTo = 'mailto:' . $redirectTo; - } elseif (!str_starts_with($redirectTo, '/')) { - $redirectTo = $sitePrefix . $redirectTo; - } - } - return $redirectTo; + return $coreResponse; } private function isHeadlessEnabled(ServerRequestInterface $request): bool diff --git a/Classes/Seo/CanonicalGenerator.php b/Classes/Seo/CanonicalGenerator.php index fafb93cc..e24f9cf6 100644 --- a/Classes/Seo/CanonicalGenerator.php +++ b/Classes/Seo/CanonicalGenerator.php @@ -12,73 +12,42 @@ namespace FriendsOfTYPO3\Headless\Seo; use FriendsOfTYPO3\Headless\Utility\HeadlessMode; -use Psr\EventDispatcher\EventDispatcherInterface; -use TYPO3\CMS\Core\Domain\Page; -use TYPO3\CMS\Core\Domain\Repository\PageRepository; use TYPO3\CMS\Core\Utility\GeneralUtility; -use TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController; -use TYPO3\CMS\Seo\Event\ModifyUrlForCanonicalTagEvent; +use TYPO3\CMS\Seo\Canonical\CanonicalGenerator as CoreCanonicalGenerator; use function htmlspecialchars; use function json_encode; /** - * Overridden core version with headless implementation + * Decorate Core version with headless flavor * * @codeCoverageIgnore */ -class CanonicalGenerator extends \TYPO3\CMS\Seo\Canonical\CanonicalGenerator +class CanonicalGenerator { - protected TypoScriptFrontendController $typoScriptFrontendController; - protected PageRepository $pageRepository; - protected EventDispatcherInterface $eventDispatcher; - public function handle(array &$params): string { - if ($this->typoScriptFrontendController->config['config']['disableCanonical'] ?? false) { - return ''; - } + $canonical = GeneralUtility::makeInstance(CoreCanonicalGenerator::class)->generate($params); - $event = new ModifyUrlForCanonicalTagEvent('', $params['request'], new Page($params['page'])); - $event = $this->eventDispatcher->dispatch($event); - $href = $event->getUrl(); - - if (empty($href) && (int)$this->typoScriptFrontendController->page['no_index'] === 1) { + if ($canonical === '') { return ''; } - if (empty($href)) { - // 1) Check if page has canonical URL set - $href = $this->checkForCanonicalLink(); - } - if (empty($href)) { - // 2) Check if page show content from other page - $href = $this->checkContentFromPid(); - } - if (empty($href)) { - // 3) Fallback, create canonical URL - $href = $this->checkDefaultCanonical(); - } + if (GeneralUtility::makeInstance(HeadlessMode::class)->withRequest($params['request'])->isEnabled()) { + $canonical = [ + 'href' => $this->processCanonical($canonical), + 'rel' => 'canonical', + ]; - if (!empty($href)) { - if (GeneralUtility::makeInstance(HeadlessMode::class)->withRequest($params['request'])->isEnabled()) { - $canonical = [ - 'href' => htmlspecialchars($href), - 'rel' => 'canonical', - ]; + $params['_seoLinks'][] = $canonical; + $canonical = json_encode($canonical); + } - $params['_seoLinks'][] = $canonical; - $canonical = json_encode($canonical); - } else { - $canonical = ' 'canonical', - 'href' => $href, - ], true) . '/>' . LF; - $this->typoScriptFrontendController->additionalHeaderData[] = $canonical; - } + return $canonical; + } - return $canonical; - } - return ''; + protected function processCanonical(string $canonical): string + { + return htmlspecialchars(GeneralUtility::get_tag_attributes($canonical)['href'] ?? ''); } } diff --git a/Classes/Seo/MetaHandler.php b/Classes/Seo/MetaHandler.php index d8b7f799..1f1aa2b3 100644 --- a/Classes/Seo/MetaHandler.php +++ b/Classes/Seo/MetaHandler.php @@ -36,7 +36,7 @@ public function process(ServerRequestInterface $request, TypoScriptFrontendContr GeneralUtility::callUserFunction($_funcRef, $_params, $_ref); } - $content['seo']['title'] = $controller->generatePageTitle(); + $content['seo']['title'] = $controller->generatePageTitle($request); $this->generateMetaTagsFromTyposcript( $controller->pSetup['meta.'] ?? [], diff --git a/Classes/XClass/Controller/FormFrontendController.php b/Classes/XClass/Controller/FormFrontendController.php index bc62fb04..64c13a8e 100644 --- a/Classes/XClass/Controller/FormFrontendController.php +++ b/Classes/XClass/Controller/FormFrontendController.php @@ -18,39 +18,34 @@ use FriendsOfTYPO3\Headless\Utility\HeadlessMode; use FriendsOfTYPO3\Headless\XClass\FormRuntime; use Psr\Http\Message\ResponseInterface; +use TYPO3\CMS\Core\Information\Typo3Version; use TYPO3\CMS\Core\Utility\ArrayUtility; use TYPO3\CMS\Core\Utility\GeneralUtility; +use TYPO3\CMS\Extbase\Configuration\ConfigurationManagerInterface as ExtbaseConfigurationManagerInterface; use TYPO3\CMS\Extbase\Error\Error; -use TYPO3\CMS\Extbase\Security\Cryptography\HashService; +use TYPO3\CMS\Extbase\Mvc\ExtbaseRequestParameters; use TYPO3\CMS\Form\Domain\Factory\ArrayFormFactory; use TYPO3\CMS\Form\Domain\Model\FormDefinition; use function array_merge; use function array_pop; use function base64_encode; +use function class_exists; use function count; use function in_array; +use function is_array; use function json_decode; use function serialize; use function str_replace; /** - * The frontend controller + * Overridden form implementation with headless flavor * - * Scope: frontend * @internal * @codeCoverageIgnore */ class FormFrontendController extends \TYPO3\CMS\Form\Controller\FormFrontendController { - private Translator $jsonFormTranslator; - - public function __construct() - { - $this->hashService = GeneralUtility::makeInstance(HashService::class); - $this->jsonFormTranslator = GeneralUtility::makeInstance(Translator::class); - } - /** * Take the form which should be rendered from the plugin settings * and overlay the formDefinition with additional data from @@ -64,13 +59,28 @@ public function renderAction(): ResponseInterface { $headlessMode = GeneralUtility::makeInstance(HeadlessMode::class); - if (!$headlessMode->withRequest($GLOBALS['TYPO3_REQUEST'])->isEnabled()) { + if (!$headlessMode->withRequest($this->request)->isEnabled()) { return parent::renderAction(); } $formDefinition = []; if (!empty($this->settings['persistenceIdentifier'])) { - $formDefinition = $this->formPersistenceManager->load($this->settings['persistenceIdentifier']); + $formSettings = []; + $typoScriptSettings = []; + + if ((new Typo3Version())->getMajorVersion() >= 13) { + $typoScriptSettings = $this->configurationManager->getConfiguration( + ExtbaseConfigurationManagerInterface::CONFIGURATION_TYPE_SETTINGS, + 'form' + ); + $formSettings = $this->extFormConfigurationManager->getYamlConfiguration($typoScriptSettings, true); + } + + $formDefinition = $this->formPersistenceManager->load( + $this->settings['persistenceIdentifier'], + $formSettings, + $typoScriptSettings + ); $formDefinition['persistenceIdentifier'] = $this->settings['persistenceIdentifier']; $formDefinition = $this->overrideByFlexFormSettings($formDefinition); $formDefinition = ArrayUtility::setValueByPath( @@ -80,10 +90,7 @@ public function renderAction(): ResponseInterface '.' ); - $formId = ($this->configurationManager->getContentObject() !== null ? - ($this->configurationManager->getContentObject()->data['uid'] ?? 0) : 0); - - $formDefinition['identifier'] .= '-' . $formId; + $formDefinition['identifier'] .= '-' . ($this->request->getAttribute('currentContentObject')?->data['uid'] ?? ''); } $i18n = []; @@ -128,14 +135,21 @@ public function renderAction(): ResponseInterface $honeyPot = array_pop($elements); } - $stateHash = $this->hashService->appendHmac(base64_encode(serialize($formState))); + $stateHash = $this->getHashService()->appendHmac( + base64_encode(serialize($formState)), + class_exists(\TYPO3\CMS\Form\Security\HashScope::class) ? \TYPO3\CMS\Form\Security\HashScope::FormState->prefix() : '' + ); $currentPageIndex = $formRuntime->getCurrentPage() ? $formRuntime->getCurrentPage()->getIndex() : 0; $currentPageId = $currentPageIndex + 1; $formFields = $formDefinition['renderables'][$currentPageIndex]['renderables'] ?? []; // provides support for custom options providers (dynamic selects/radio/checkboxes) - $formFieldsNames = $this->generateFieldNamesAndReplaceCustomOptions($formFields, $formDefinition['identifier'], $formRuntime); + $formFieldsNames = $this->generateFieldNamesAndReplaceCustomOptions( + $formFields, + $formDefinition['identifier'], + $formRuntime + ); if ($honeyPot) { $formFields[] = [ @@ -188,7 +202,7 @@ public function renderAction(): ResponseInterface $formDefinition['renderables'][$currentPageIndex]['renderables'] = $formFields; $formDefinition['i18n'] = count($i18n) ? $i18n : null; - $formDefinition = $this->jsonFormTranslator->translate( + $formDefinition = $this->getFormTranslator()->translate( $formDefinition, $formRuntime->getFormDefinition()->getRenderingOptions(), $formRuntime->getFormState() ? $formRuntime->getFormState()->getFormValues() : [] @@ -260,8 +274,11 @@ private function getNextPage(\TYPO3\CMS\Form\Domain\Runtime\FormRuntime $formRun * @param array $formFields * @return array */ - private function generateFieldNamesAndReplaceCustomOptions(array &$formFields, string $identifier, FormRuntime $formRuntime): array - { + private function generateFieldNamesAndReplaceCustomOptions( + array &$formFields, + string $identifier, + FormRuntime $formRuntime + ): array { $formFieldsNames = []; foreach ($formFields as &$field) { @@ -274,7 +291,13 @@ private function generateFieldNamesAndReplaceCustomOptions(array &$formFields, s ); } else { if (!empty($field['properties']['customOptions'])) { - $customOptions = GeneralUtility::makeInstance($field['properties']['customOptions'], $field, $formFields, $identifier, $formRuntime); + $customOptions = GeneralUtility::makeInstance( + $field['properties']['customOptions'], + $field, + $formFields, + $identifier, + $formRuntime + ); if ($customOptions instanceof CustomOptionsInterface) { $field['properties']['options'] = $customOptions->get(); @@ -295,4 +318,18 @@ private function generateFieldNamesAndReplaceCustomOptions(array &$formFields, s return $formFieldsNames; } + + private function getHashService(): \TYPO3\CMS\Extbase\Security\Cryptography\HashService|\TYPO3\CMS\Core\Crypto\HashService + { + if ((new Typo3Version())->getMajorVersion() >= 13) { + return GeneralUtility::makeInstance(\TYPO3\CMS\Core\Crypto\HashService::class); + } + + return GeneralUtility::makeInstance(\TYPO3\CMS\Extbase\Security\Cryptography\HashService::class); + } + + private function getFormTranslator(): Translator + { + return GeneralUtility::makeInstance(Translator::class); + } } diff --git a/Classes/XClass/ResourceLocalDriver.php b/Classes/XClass/ResourceLocalDriver.php index 285479af..a67207d5 100644 --- a/Classes/XClass/ResourceLocalDriver.php +++ b/Classes/XClass/ResourceLocalDriver.php @@ -16,6 +16,8 @@ use Psr\Http\Message\ServerRequestInterface; use TYPO3\CMS\Core\Http\ApplicationType; use TYPO3\CMS\Core\Http\Uri; +use TYPO3\CMS\Core\Information\Typo3Version; +use TYPO3\CMS\Core\Resource\Capabilities; use TYPO3\CMS\Core\Resource\Driver\LocalDriver; use TYPO3\CMS\Core\Resource\ResourceStorage; use TYPO3\CMS\Core\Utility\GeneralUtility; @@ -41,7 +43,7 @@ protected function determineBaseUrl(): void return; } - if ($this->hasCapability(ResourceStorage::CAPABILITY_PUBLIC)) { + if ($this->hasCapability(((new Typo3Version())->getMajorVersion() < 13) ? ResourceStorage::CAPABILITY_PUBLIC : Capabilities::CAPABILITY_PUBLIC)) { $urlUtility = GeneralUtility::makeInstance(UrlUtility::class)->withRequest($request); $basePath = match (true) { diff --git a/Configuration/SiteConfiguration/Overrides/site.php b/Configuration/SiteConfiguration/Overrides/site.php index e3f14f98..03bfb80e 100644 --- a/Configuration/SiteConfiguration/Overrides/site.php +++ b/Configuration/SiteConfiguration/Overrides/site.php @@ -7,7 +7,6 @@ * LICENSE.md file that was distributed with this source code. */ -use FriendsOfTYPO3\Headless\Utility\Headless; use FriendsOfTYPO3\Headless\Utility\HeadlessMode; use TYPO3\CMS\Core\Configuration\Features; use TYPO3\CMS\Core\Utility\GeneralUtility; diff --git a/Tests/Functional/BaseTest.php b/Tests/Functional/BaseTest.php index b07fbcb1..b8b1f163 100644 --- a/Tests/Functional/BaseTest.php +++ b/Tests/Functional/BaseTest.php @@ -129,4 +129,9 @@ protected function checkHeaderFieldsLink($contentElement, $link, $urlPrefix, $ta self::assertStringStartsWith($urlPrefix, $contentElementHeaderFieldsLink['href'], 'url mismatch'); self::assertEquals($target, $contentElementHeaderFieldsLink['target'], 'target mismatch'); } + + protected function importDataSet(string $string): void + { + // @TODO move data into CSV + } } diff --git a/Tests/Functional/ContentTypes/BaseContentTypeTest.php b/Tests/Functional/ContentTypes/BaseContentTypeTest.php index ae4caa90..c5652b29 100644 --- a/Tests/Functional/ContentTypes/BaseContentTypeTest.php +++ b/Tests/Functional/ContentTypes/BaseContentTypeTest.php @@ -13,7 +13,7 @@ use FriendsOfTYPO3\Headless\Tests\Functional\BaseTest; -abstract class BaseContentTypeTest extends BaseTest +class BaseContentTypeTest extends BaseTest { /** * set up objects diff --git a/Tests/Functional/ContentTypes/BasicListElementTest.php b/Tests/Functional/ContentTypes/BasicListElementTest.php index 162f0b4f..985170ba 100644 --- a/Tests/Functional/ContentTypes/BasicListElementTest.php +++ b/Tests/Functional/ContentTypes/BasicListElementTest.php @@ -17,7 +17,7 @@ class BasicListElementTest extends BaseContentTypeTest { public function testBasicListContentElement() { - $response = $this->executeFrontendRequest( + $response = $this->executeFrontendSubRequest( new InternalRequest('https://website.local/') ); diff --git a/Tests/Functional/ContentTypes/BulletsElementTest.php b/Tests/Functional/ContentTypes/BulletsElementTest.php index 98342110..3684bc85 100644 --- a/Tests/Functional/ContentTypes/BulletsElementTest.php +++ b/Tests/Functional/ContentTypes/BulletsElementTest.php @@ -19,7 +19,7 @@ public function testBulletsContentElement() { $testBulletsContent = ['Top1', 'Top2', 'Top3']; - $response = $this->executeFrontendRequest( + $response = $this->executeFrontendSubRequest( new InternalRequest('https://website.local/') ); diff --git a/Tests/Functional/ContentTypes/DefaultContentsTest.php b/Tests/Functional/ContentTypes/DefaultContentsTest.php index c4a8201a..68fbca8e 100644 --- a/Tests/Functional/ContentTypes/DefaultContentsTest.php +++ b/Tests/Functional/ContentTypes/DefaultContentsTest.php @@ -17,7 +17,7 @@ class DefaultContentsTest extends BaseContentTypeTest { public function testContentStructure() { - $response = $this->executeFrontendRequest( + $response = $this->executeFrontendSubRequest( new InternalRequest('https://website.local/') ); diff --git a/Tests/Functional/ContentTypes/DivElementTest.php b/Tests/Functional/ContentTypes/DivElementTest.php index 06b1094c..011774a5 100644 --- a/Tests/Functional/ContentTypes/DivElementTest.php +++ b/Tests/Functional/ContentTypes/DivElementTest.php @@ -17,7 +17,7 @@ class DivElementTest extends BaseContentTypeTest { public function testDivContentElement() { - $response = $this->executeFrontendRequest( + $response = $this->executeFrontendSubRequest( new InternalRequest('https://website.local/') ); diff --git a/Tests/Functional/ContentTypes/HeaderElementTest.php b/Tests/Functional/ContentTypes/HeaderElementTest.php index cf2bc75b..73eb00f6 100644 --- a/Tests/Functional/ContentTypes/HeaderElementTest.php +++ b/Tests/Functional/ContentTypes/HeaderElementTest.php @@ -17,7 +17,7 @@ class HeaderElementTest extends BaseContentTypeTest { public function testHeaderContentElement() { - $response = $this->executeFrontendRequest( + $response = $this->executeFrontendSubRequest( new InternalRequest('https://website.local/') ); diff --git a/Tests/Functional/ContentTypes/HtmlElementTest.php b/Tests/Functional/ContentTypes/HtmlElementTest.php index 09c39b27..f94111dd 100644 --- a/Tests/Functional/ContentTypes/HtmlElementTest.php +++ b/Tests/Functional/ContentTypes/HtmlElementTest.php @@ -17,7 +17,7 @@ class HtmlElementTest extends BaseContentTypeTest { public function testHtmlContentElement() { - $response = $this->executeFrontendRequest( + $response = $this->executeFrontendSubRequest( new InternalRequest('https://website.local/') ); diff --git a/Tests/Functional/ContentTypes/ImageElementTest.php b/Tests/Functional/ContentTypes/ImageElementTest.php index bb2bcd7e..b4021565 100644 --- a/Tests/Functional/ContentTypes/ImageElementTest.php +++ b/Tests/Functional/ContentTypes/ImageElementTest.php @@ -17,7 +17,7 @@ class ImageElementTest extends BaseContentTypeTest { public function testImageContentElement() { - $response = $this->executeFrontendRequest( + $response = $this->executeFrontendSubRequest( new InternalRequest('https://website.local/') ); diff --git a/Tests/Functional/ContentTypes/MenuAbstractPagesElementTest.php b/Tests/Functional/ContentTypes/MenuAbstractPagesElementTest.php index d2108350..6bdc6658 100644 --- a/Tests/Functional/ContentTypes/MenuAbstractPagesElementTest.php +++ b/Tests/Functional/ContentTypes/MenuAbstractPagesElementTest.php @@ -17,7 +17,7 @@ class MenuAbstractPagesElementTest extends BaseContentTypeTest { public function testMenuContentElement() { - $response = $this->executeFrontendRequest( + $response = $this->executeFrontendSubRequest( new InternalRequest('https://website.local/') ); diff --git a/Tests/Functional/ContentTypes/MenuCategorizedContentElementTest.php b/Tests/Functional/ContentTypes/MenuCategorizedContentElementTest.php index cac77ff5..9b28180c 100644 --- a/Tests/Functional/ContentTypes/MenuCategorizedContentElementTest.php +++ b/Tests/Functional/ContentTypes/MenuCategorizedContentElementTest.php @@ -17,7 +17,7 @@ class MenuCategorizedContentElementTest extends BaseContentTypeTest { public function testMenuContentElement() { - $response = $this->executeFrontendRequest( + $response = $this->executeFrontendSubRequest( new InternalRequest('https://website.local/') ); diff --git a/Tests/Functional/ContentTypes/MenuCategorizedPagesElementTest.php b/Tests/Functional/ContentTypes/MenuCategorizedPagesElementTest.php index d596983e..1ffa48dd 100644 --- a/Tests/Functional/ContentTypes/MenuCategorizedPagesElementTest.php +++ b/Tests/Functional/ContentTypes/MenuCategorizedPagesElementTest.php @@ -17,7 +17,7 @@ class MenuCategorizedPagesElementTest extends BaseContentTypeTest { public function testMenuContentElement() { - $response = $this->executeFrontendRequest( + $response = $this->executeFrontendSubRequest( new InternalRequest('https://website.local/page1') ); diff --git a/Tests/Functional/ContentTypes/MenuPagesElementTest.php b/Tests/Functional/ContentTypes/MenuPagesElementTest.php index 463d6a78..f45682ad 100644 --- a/Tests/Functional/ContentTypes/MenuPagesElementTest.php +++ b/Tests/Functional/ContentTypes/MenuPagesElementTest.php @@ -17,7 +17,7 @@ class MenuPagesElementTest extends BaseContentTypeTest { public function testMenuContentElement() { - $response = $this->executeFrontendRequest( + $response = $this->executeFrontendSubRequest( new InternalRequest('https://website.local/') ); diff --git a/Tests/Functional/ContentTypes/MenuRecentlyUpdatedPagesElementTest.php b/Tests/Functional/ContentTypes/MenuRecentlyUpdatedPagesElementTest.php index 96d2d064..0d39c1ee 100644 --- a/Tests/Functional/ContentTypes/MenuRecentlyUpdatedPagesElementTest.php +++ b/Tests/Functional/ContentTypes/MenuRecentlyUpdatedPagesElementTest.php @@ -33,7 +33,7 @@ public function setUp(): void public function testMenuContentElement() { - $response = $this->executeFrontendRequest( + $response = $this->executeFrontendSubRequest( new InternalRequest('https://website.local/') ); diff --git a/Tests/Functional/ContentTypes/MenuRelatedPagesElementTest.php b/Tests/Functional/ContentTypes/MenuRelatedPagesElementTest.php index 8a68c30a..69720c43 100644 --- a/Tests/Functional/ContentTypes/MenuRelatedPagesElementTest.php +++ b/Tests/Functional/ContentTypes/MenuRelatedPagesElementTest.php @@ -17,7 +17,7 @@ class MenuRelatedPagesElementTest extends BaseContentTypeTest { public function testMenuContentElement() { - $response = $this->executeFrontendRequest( + $response = $this->executeFrontendSubRequest( new InternalRequest('https://website.local/') ); diff --git a/Tests/Functional/ContentTypes/MenuSectionElementTest.php b/Tests/Functional/ContentTypes/MenuSectionElementTest.php index d16fee55..86f1574e 100644 --- a/Tests/Functional/ContentTypes/MenuSectionElementTest.php +++ b/Tests/Functional/ContentTypes/MenuSectionElementTest.php @@ -17,7 +17,7 @@ class MenuSectionElementTest extends BaseContentTypeTest { public function testMenuContentElement() { - $response = $this->executeFrontendRequest( + $response = $this->executeFrontendSubRequest( new InternalRequest('https://website.local/') ); diff --git a/Tests/Functional/ContentTypes/MenuSitemapElementTest.php b/Tests/Functional/ContentTypes/MenuSitemapElementTest.php index dc791a86..d3f82498 100644 --- a/Tests/Functional/ContentTypes/MenuSitemapElementTest.php +++ b/Tests/Functional/ContentTypes/MenuSitemapElementTest.php @@ -17,7 +17,7 @@ class MenuSitemapElementTest extends BaseContentTypeTest { public function testMenuContentElement() { - $response = $this->executeFrontendRequest( + $response = $this->executeFrontendSubRequest( new InternalRequest('https://website.local/') ); diff --git a/Tests/Functional/ContentTypes/MenuSitemapSelectedPagesElementTest.php b/Tests/Functional/ContentTypes/MenuSitemapSelectedPagesElementTest.php index 965a3b5b..c0a967f1 100644 --- a/Tests/Functional/ContentTypes/MenuSitemapSelectedPagesElementTest.php +++ b/Tests/Functional/ContentTypes/MenuSitemapSelectedPagesElementTest.php @@ -17,7 +17,7 @@ class MenuSitemapSelectedPagesElementTest extends BaseContentTypeTest { public function testMenuContentElement() { - $response = $this->executeFrontendRequest( + $response = $this->executeFrontendSubRequest( new InternalRequest('https://website.local/page3') ); diff --git a/Tests/Functional/ContentTypes/MenuSubpagesElementTest.php b/Tests/Functional/ContentTypes/MenuSubpagesElementTest.php index bfd0993b..a3273314 100644 --- a/Tests/Functional/ContentTypes/MenuSubpagesElementTest.php +++ b/Tests/Functional/ContentTypes/MenuSubpagesElementTest.php @@ -17,7 +17,7 @@ class MenuSubpagesElementTest extends BaseContentTypeTest { public function testMenuSubpagesContentElement() { - $response = $this->executeFrontendRequest( + $response = $this->executeFrontendSubRequest( new InternalRequest('https://website.local/') ); diff --git a/Tests/Functional/ContentTypes/ShortcutElementTest.php b/Tests/Functional/ContentTypes/ShortcutElementTest.php index 1197f237..159df9cc 100644 --- a/Tests/Functional/ContentTypes/ShortcutElementTest.php +++ b/Tests/Functional/ContentTypes/ShortcutElementTest.php @@ -17,7 +17,7 @@ class ShortcutElementTest extends BaseContentTypeTest { public function testShortcutContentElement() { - $response = $this->executeFrontendRequest( + $response = $this->executeFrontendSubRequest( new InternalRequest('https://website.local/') ); diff --git a/Tests/Functional/ContentTypes/TableElementTest.php b/Tests/Functional/ContentTypes/TableElementTest.php index dc527aa6..ef641261 100644 --- a/Tests/Functional/ContentTypes/TableElementTest.php +++ b/Tests/Functional/ContentTypes/TableElementTest.php @@ -19,7 +19,7 @@ public function testTableContentElement() { $testTableContent = json_decode('[["Cell1.1","Cell1.2","Cell1.3","Cell1.4","",""],["Cell2.1","","","","",""],["Cell3.1","","","","",""],["\"","","","","",""]]', true); - $response = $this->executeFrontendRequest( + $response = $this->executeFrontendSubRequest( new InternalRequest('https://website.local/') ); diff --git a/Tests/Functional/ContentTypes/TextElementTest.php b/Tests/Functional/ContentTypes/TextElementTest.php index 654072b2..685fbebc 100644 --- a/Tests/Functional/ContentTypes/TextElementTest.php +++ b/Tests/Functional/ContentTypes/TextElementTest.php @@ -17,7 +17,7 @@ class TextElementTest extends BaseContentTypeTest { public function testTextContentElement() { - $response = $this->executeFrontendRequest( + $response = $this->executeFrontendSubRequest( new InternalRequest('https://website.local/') ); diff --git a/Tests/Functional/ContentTypes/TextMediaElementTest.php b/Tests/Functional/ContentTypes/TextMediaElementTest.php index 8115c5d8..e3941843 100644 --- a/Tests/Functional/ContentTypes/TextMediaElementTest.php +++ b/Tests/Functional/ContentTypes/TextMediaElementTest.php @@ -17,7 +17,7 @@ class TextMediaElementTest extends BaseContentTypeTest { public function testTextMediaContentElement() { - $response = $this->executeFrontendRequest( + $response = $this->executeFrontendSubRequest( new InternalRequest('https://website.local/') ); diff --git a/Tests/Functional/ContentTypes/TextpicElementTest.php b/Tests/Functional/ContentTypes/TextpicElementTest.php index 1e5010e5..ef42108c 100644 --- a/Tests/Functional/ContentTypes/TextpicElementTest.php +++ b/Tests/Functional/ContentTypes/TextpicElementTest.php @@ -17,7 +17,7 @@ class TextpicElementTest extends BaseContentTypeTest { public function testTextpicContentElement() { - $response = $this->executeFrontendRequest( + $response = $this->executeFrontendSubRequest( new InternalRequest('https://website.local/') ); diff --git a/Tests/Functional/PageTypes/BasePageTypesTest.php b/Tests/Functional/PageTypes/BasePageTypesTest.php index fb426ba2..e485aebf 100644 --- a/Tests/Functional/PageTypes/BasePageTypesTest.php +++ b/Tests/Functional/PageTypes/BasePageTypesTest.php @@ -17,7 +17,7 @@ use JsonSchema\Validator; use TYPO3\CMS\Core\Utility\ExtensionManagementUtility; -abstract class BasePageTypesTest extends BaseTest +class BasePageTypesTest extends BaseTest { /** * @param string $jsonString diff --git a/Tests/Functional/PageTypes/SchemaPageTypesTest.php b/Tests/Functional/PageTypes/SchemaPageTypesTest.php index 8ec042fa..621adf9d 100644 --- a/Tests/Functional/PageTypes/SchemaPageTypesTest.php +++ b/Tests/Functional/PageTypes/SchemaPageTypesTest.php @@ -20,7 +20,7 @@ class SchemaPageTypesTest extends BasePageTypesTest */ public function getMenu() { - $response = $this->executeFrontendRequest( + $response = $this->executeFrontendSubRequest( new InternalRequest('https://website.local/?type=834') ); @@ -32,7 +32,7 @@ public function getMenu() */ public function getPage() { - $response = $this->executeFrontendRequest( + $response = $this->executeFrontendSubRequest( new InternalRequest('https://website.local/') ); diff --git a/Tests/Functional/PageTypes/StructurePageTypesTest.php b/Tests/Functional/PageTypes/StructurePageTypesTest.php index aee84608..bfa7993e 100644 --- a/Tests/Functional/PageTypes/StructurePageTypesTest.php +++ b/Tests/Functional/PageTypes/StructurePageTypesTest.php @@ -20,7 +20,7 @@ class StructurePageTypesTest extends BasePageTypesTest */ public function getMenuStructure() { - $response = $this->executeFrontendRequest( + $response = $this->executeFrontendSubRequest( new InternalRequest('https://website.local/?type=834') ); diff --git a/Tests/Unit/ContentObject/BooleanContentObjectTest.php b/Tests/Unit/ContentObject/BooleanContentObjectTest.php index 76f1e289..e5d1c3b1 100644 --- a/Tests/Unit/ContentObject/BooleanContentObjectTest.php +++ b/Tests/Unit/ContentObject/BooleanContentObjectTest.php @@ -50,7 +50,7 @@ public function renderWithProviderTest($argument, bool $result) self::assertEquals($result, $contentObject->render($argument)); } - public function dataProvider(): array + public static function dataProvider(): array { return [ ['test', false], diff --git a/Tests/Unit/ContentObject/FloatContentObjectTest.php b/Tests/Unit/ContentObject/FloatContentObjectTest.php index 9ffb9891..5ea09d01 100644 --- a/Tests/Unit/ContentObject/FloatContentObjectTest.php +++ b/Tests/Unit/ContentObject/FloatContentObjectTest.php @@ -47,7 +47,7 @@ public function renderWithProviderTest($argument, float $result) self::assertEquals($result, $contentObject->render($argument)); } - public function dataProvider(): array + public static function dataProvider(): array { return [ ['test', 0.0], diff --git a/Tests/Unit/ContentObject/IntegerContentObjectTest.php b/Tests/Unit/ContentObject/IntegerContentObjectTest.php index 4abbbee8..662b6c33 100644 --- a/Tests/Unit/ContentObject/IntegerContentObjectTest.php +++ b/Tests/Unit/ContentObject/IntegerContentObjectTest.php @@ -50,7 +50,7 @@ public function renderWithProviderTest($argument, int $result) self::assertEquals($result, $contentObject->render($argument)); } - public function dataProvider(): array + public static function dataProvider(): array { return [ ['test', 0], diff --git a/Tests/Unit/ContentObject/JsonContentObjectTest.php b/Tests/Unit/ContentObject/JsonContentObjectTest.php index 0d8addb9..4cef81e7 100644 --- a/Tests/Unit/ContentObject/JsonContentObjectTest.php +++ b/Tests/Unit/ContentObject/JsonContentObjectTest.php @@ -18,8 +18,11 @@ 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\Cache\Frontend\FrontendInterface; +use TYPO3\CMS\Core\EventDispatcher\EventDispatcher; use TYPO3\CMS\Core\Http\ServerRequest; use TYPO3\CMS\Core\Service\MarkerBasedTemplateService; use TYPO3\CMS\Core\TimeTracker\TimeTracker; @@ -86,6 +89,18 @@ protected function setUp(): void 'BOOL' => BooleanContentObject::class, ]; + $container = new Container(); + + $eventDispatcher = $this->prophesize(EventDispatcher::class); + $eventDispatcher->dispatch(Argument::any())->willReturnArgument(); + + $container->set(MarkerBasedTemplateService::class, new MarkerBasedTemplateService($this->prophesize(FrontendInterface::class)->reveal(), $this->prophesize(FrontendInterface::class)->reveal())); + $container->set(TimeTracker::class, new TimeTracker(false)); + $container->set(EventDispatcherInterface::class, $eventDispatcher->reveal()); + $container->set(RecordsContentObject::class, new RecordsContentObject($container->get(TimeTracker::class))); + $container->set(ContentContentObject::class, new ContentContentObject($container->get(TimeTracker::class), $container->get(EventDispatcherInterface::class))); + GeneralUtility::setContainer($container); + $request = new ServerRequest(); $contentObjectRenderer = GeneralUtility::makeInstance(ContentObjectRenderer::class); $contentObjectRenderer->setRequest($request); @@ -101,7 +116,7 @@ protected function setUp(): void return $obj; }); - $container = new Container(); + $container = GeneralUtility::getContainer(); $container->set(ContentObjectFactory::class, $factory->reveal()); GeneralUtility::setContainer($container); @@ -113,9 +128,7 @@ protected function setUp(): void } GeneralUtility::makeInstance(JsonContentObject::class, $contentDataProcessor); - GeneralUtility::makeInstance(ImageContentObject::class, $this->prophesize(MarkerBasedTemplateService::class)->reveal()); - - GeneralUtility::makeInstance(TimeTracker::class, false); + // GeneralUtility::makeInstance(ImageContentObject::class, $this->prophesize(MarkerBasedTemplateService::class)->reveal()); $tsfe = $this->prophesize(TypoScriptFrontendController::class); $tsfe->uniqueHash()->willReturn(md5('123')); @@ -144,7 +157,7 @@ public function renderWithProviderTest($argument, $result) self::assertEquals($result, $this->contentObject->render($argument)); } - public function dataProvider(): array + public static function dataProvider(): array { return [ [[], '[]'], diff --git a/Tests/Unit/DataProcessing/DataProcessingTraitTest.php b/Tests/Unit/DataProcessing/DataProcessingTraitTest.php index c41b0750..8019b4f2 100644 --- a/Tests/Unit/DataProcessing/DataProcessingTraitTest.php +++ b/Tests/Unit/DataProcessing/DataProcessingTraitTest.php @@ -96,7 +96,7 @@ public function isMenuProcessor() )); } - public function dataProvider(): array + public static function dataProvider(): array { return [ [ 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/AfterLinkIsGeneratedListenerTest.php b/Tests/Unit/Event/Listener/AfterLinkIsGeneratedListenerTest.php index f5397f48..318741da 100644 --- a/Tests/Unit/Event/Listener/AfterLinkIsGeneratedListenerTest.php +++ b/Tests/Unit/Event/Listener/AfterLinkIsGeneratedListenerTest.php @@ -13,6 +13,7 @@ use FriendsOfTYPO3\Headless\Utility\UrlUtility; use Prophecy\Argument; use Prophecy\PhpUnit\ProphecyTrait; +use Psr\EventDispatcher\EventDispatcherInterface; use TYPO3\CMS\Core\ExpressionLanguage\Resolver; use TYPO3\CMS\Core\Http\ServerRequest; use TYPO3\CMS\Core\LinkHandling\LinkService; @@ -39,7 +40,7 @@ public function test__construct() $this->prophesize(Logger::class)->reveal(), new UrlUtility(null, $resolver->reveal(), $siteFinder->reveal()), $this->prophesize(LinkService::class)->reveal(), - new TypoLinkCodecService(), + new TypoLinkCodecService($this->prophesize(EventDispatcherInterface::class)->reveal()), $this->prophesize(SiteFinder::class)->reveal() ); @@ -56,7 +57,7 @@ public function test__invokeNotModifingAnything() $this->prophesize(Logger::class)->reveal(), new UrlUtility(null, $resolver->reveal(), $siteFinder->reveal()), $this->prophesize(LinkService::class)->reveal(), - new TypoLinkCodecService(), + new TypoLinkCodecService($this->prophesize(EventDispatcherInterface::class)->reveal()), $this->prophesize(SiteFinder::class)->reveal() ); @@ -109,7 +110,7 @@ public function test__invokeModifingFromPageUid() $this->prophesize(Logger::class)->reveal(), $urlUtility->reveal(), $this->prophesize(LinkService::class)->reveal(), - new TypoLinkCodecService(), + new TypoLinkCodecService($this->prophesize(EventDispatcherInterface::class)->reveal()), $this->prophesize(SiteFinder::class)->reveal() ); @@ -146,7 +147,7 @@ public function test__invokeModifingExternalSite() $this->prophesize(Logger::class)->reveal(), $urlUtility->reveal(), $linkService->reveal(), - new TypoLinkCodecService(), + new TypoLinkCodecService($this->prophesize(EventDispatcherInterface::class)->reveal()), $this->prophesize(SiteFinder::class)->reveal() ); $linkResult = new LinkResult('page', '/'); @@ -186,11 +187,14 @@ public function test__SitemapLink() $urlUtility->withRequest($request)->willReturn($urlUtility->reveal()); + $eventDispatcher = $this->prophesize(EventDispatcherInterface::class); + $eventDispatcher->dispatch(Argument::any())->willReturnArgument(); + $listener = new AfterLinkIsGeneratedListener( $this->prophesize(Logger::class)->reveal(), $urlUtility->reveal(), $linkService->reveal(), - new TypoLinkCodecService(), + new TypoLinkCodecService($eventDispatcher->reveal()), $siteFinder->reveal() ); diff --git a/Tests/Unit/Event/Listener/RedirectUrlAdditionalParamsListenerTest.php b/Tests/Unit/Event/Listener/RedirectUrlAdditionalParamsListenerTest.php index 92df106e..d3fe7e6a 100644 --- a/Tests/Unit/Event/Listener/RedirectUrlAdditionalParamsListenerTest.php +++ b/Tests/Unit/Event/Listener/RedirectUrlAdditionalParamsListenerTest.php @@ -19,6 +19,7 @@ use InvalidArgumentException; use Prophecy\Argument; use Prophecy\PhpUnit\ProphecyTrait; +use Psr\EventDispatcher\EventDispatcherInterface; use Psr\Http\Message\UriInterface; use TYPO3\CMS\Core\ExpressionLanguage\Resolver; use TYPO3\CMS\Core\Http\ServerRequest; @@ -40,8 +41,11 @@ class RedirectUrlAdditionalParamsListenerTest extends UnitTestCase */ public function invokeTest() { + $eventDispatcher = $this->prophesize(EventDispatcherInterface::class); + $eventDispatcher->dispatch(Argument::any())->willReturnArgument(); + $listener = new RedirectUrlAdditionalParamsListener( - new TypoLinkCodecService(), + new TypoLinkCodecService($eventDispatcher->reveal()), new LinkService(), $this->getUrlUtility() ); @@ -119,7 +123,7 @@ public function invokeTest() $mockListener->method('getPageRouterForSite') ->willReturn($pageRouter->reveal()); $mockListener->__construct( - new TypoLinkCodecService(), + new TypoLinkCodecService($eventDispatcher->reveal()), new LinkService(), $this->getUrlUtility() ); @@ -133,6 +137,9 @@ public function invokeTest() */ public function invokeWithLanguageTest() { + $eventDispatcher = $this->prophesize(EventDispatcherInterface::class); + $eventDispatcher->dispatch(Argument::any())->willReturnArgument(); + $targetUrl = 'https://test.domain2.tld/123'; $additionalParams = 'tx_test[action]=test&tx_test[controller]=Test&tx_test[test]=123'; $expectedUri = new Uri($targetUrl . '&' . $additionalParams); @@ -180,7 +187,7 @@ public function invokeWithLanguageTest() ->willReturn($pageRouter->reveal()); $mockListener->__construct( - new TypoLinkCodecService(), + new TypoLinkCodecService($eventDispatcher->reveal()), new LinkService(), $this->getUrlUtility($site) ); diff --git a/Tests/Unit/Hooks/HeadlessUserIntTest.php b/Tests/Unit/Hooks/HeadlessUserIntTest.php index 5b121945..2a7165ca 100644 --- a/Tests/Unit/Hooks/HeadlessUserIntTest.php +++ b/Tests/Unit/Hooks/HeadlessUserIntTest.php @@ -13,7 +13,6 @@ use FriendsOfTYPO3\Headless\Utility\HeadlessUserInt; use Prophecy\PhpUnit\ProphecyTrait; -use TYPO3\CMS\Core\TypoScript\TemplateService; use TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController; use TYPO3\TestingFramework\Core\Unit\UnitTestCase; @@ -31,15 +30,7 @@ public function processingOnPlainTextWithNewline() $testProcessed = 'PlainText' . PHP_EOL . 'NextLine'; $testContent = 'HEADLESS_INT_START<<' . $testProcessed . '>>HEADLESS_INT_END'; - $setup = []; - $setup['plugin.']['tx_headless.']['staticTemplate'] = '1'; - - $tmpl = $this->prophesize(TemplateService::class); - $tmpl->setup = $setup; - $tsfe = $this->prophesize(TypoScriptFrontendController::class); - $tsfe->tmpl = $tmpl->reveal(); - $tsfe->content = $testContent; $classUnderTest = new HeadlessUserInt(); @@ -57,15 +48,7 @@ public function processingOnQuotedText() $testProcessed = '"PlainText' . PHP_EOL . 'NextLine"'; $testContent = 'HEADLESS_INT_START<<' . $testProcessed . '>>HEADLESS_INT_END'; - $setup = []; - $setup['plugin.']['tx_headless.']['staticTemplate'] = '1'; - - $tmpl = $this->prophesize(TemplateService::class); - $tmpl->setup = $setup; - $tsfe = $this->prophesize(TypoScriptFrontendController::class); - $tsfe->tmpl = $tmpl->reveal(); - $tsfe->content = $testContent; $classUnderTest = new HeadlessUserInt(); @@ -84,14 +67,8 @@ public function processingOnQuotedContent() $testContent = '"HEADLESS_INT_START<<' . $testProcessed . '>>HEADLESS_INT_END"'; $setup = []; - $setup['plugin.']['tx_headless.']['staticTemplate'] = '1'; - - $tmpl = $this->prophesize(TemplateService::class); - $tmpl->setup = $setup; $tsfe = $this->prophesize(TypoScriptFrontendController::class); - $tsfe->tmpl = $tmpl->reveal(); - $tsfe->content = $testContent; $classUnderTest = new HeadlessUserInt(); @@ -113,15 +90,7 @@ public function processingOnQuotedJsonContent() ); $testContent = '"HEADLESS_INT_START<<' . $testProcessed . '>>HEADLESS_INT_END"'; - $setup = []; - $setup['plugin.']['tx_headless.']['staticTemplate'] = '1'; - - $tmpl = $this->prophesize(TemplateService::class); - $tmpl->setup = $setup; - $tsfe = $this->prophesize(TypoScriptFrontendController::class); - $tsfe->tmpl = $tmpl->reveal(); - $tsfe->content = $testContent; $classUnderTest = new HeadlessUserInt(); @@ -141,15 +110,7 @@ public function processingEmptyPluginResponse() ); $testContent = '"HEADLESS_INT_NULL_START<<' . $testProcessed . '>>HEADLESS_INT_NULL_END"'; - $setup = []; - $setup['plugin.']['tx_headless.']['staticTemplate'] = '1'; - - $tmpl = $this->prophesize(TemplateService::class); - $tmpl->setup = $setup; - $tsfe = $this->prophesize(TypoScriptFrontendController::class); - $tsfe->tmpl = $tmpl->reveal(); - $tsfe->content = $testContent; $classUnderTest = new HeadlessUserInt(); @@ -163,15 +124,7 @@ public function processingEmptyPluginResponse() ); $testContent = '"NESTED_HEADLESS_INT_NULL_START<<' . $testProcessed . '>>NESTED_HEADLESS_INT_NULL_END"'; - $setup = []; - $setup['plugin.']['tx_headless.']['staticTemplate'] = '1'; - - $tmpl = $this->prophesize(TemplateService::class); - $tmpl->setup = $setup; - $tsfe = $this->prophesize(TypoScriptFrontendController::class); - $tsfe->tmpl = $tmpl->reveal(); - $tsfe->content = $testContent; $classUnderTest = new HeadlessUserInt(); @@ -217,12 +170,7 @@ public function processingOnNestedJsonContent() $setup = []; $setup['plugin.']['tx_headless.']['staticTemplate'] = '1'; - $tmpl = $this->prophesize(TemplateService::class); - $tmpl->setup = $setup; - $tsfe = $this->prophesize(TypoScriptFrontendController::class); - $tsfe->tmpl = $tmpl->reveal(); - $tsfe->content = $testContent; $classUnderTest = new HeadlessUserInt(); @@ -276,15 +224,7 @@ public function processingOnMultipleUserIntOnPageJsonContent() $testContent = '["HEADLESS_INT_START<<' . $testProcessed . '>>HEADLESS_INT_END","HEADLESS_INT_START<<' . $testProcessed2 . '>>HEADLESS_INT_END"]'; - $setup = []; - $setup['plugin.']['tx_headless.']['staticTemplate'] = '1'; - - $tmpl = $this->prophesize(TemplateService::class); - $tmpl->setup = $setup; - $tsfe = $this->prophesize(TypoScriptFrontendController::class); - $tsfe->tmpl = $tmpl->reveal(); - $tsfe->content = $testContent; $classUnderTest = new HeadlessUserInt(); diff --git a/Tests/Unit/Json/JsonDecoderTest.php b/Tests/Unit/Json/JsonDecoderTest.php index 090adce2..3203bb98 100644 --- a/Tests/Unit/Json/JsonDecoderTest.php +++ b/Tests/Unit/Json/JsonDecoderTest.php @@ -71,7 +71,7 @@ public function testDecoding(): void self::assertEquals(json_decode($encoded), $jsonDecoder->decode(['teststring'])); } - public function possibleJsonProvider(): array + public static function possibleJsonProvider(): array { return [ [' "12"', false], diff --git a/Tests/Unit/Json/JsonEncoderTest.php b/Tests/Unit/Json/JsonEncoderTest.php index e911970c..3515f917 100644 --- a/Tests/Unit/Json/JsonEncoderTest.php +++ b/Tests/Unit/Json/JsonEncoderTest.php @@ -50,7 +50,7 @@ public function testPrettyEncoding(): void self::assertSame(json_encode($encodeValue, JSON_PRETTY_PRINT), $encoder->encode($encodeValue)); } - public function jsonProvider(): array + public static function jsonProvider(): array { return [ [[], '[]'], diff --git a/Tests/Unit/Middleware/ShortcutAndMountPointRedirectTest.php b/Tests/Unit/Middleware/ShortcutAndMountPointRedirectTest.php deleted file mode 100644 index 687cb7d1..00000000 --- a/Tests/Unit/Middleware/ShortcutAndMountPointRedirectTest.php +++ /dev/null @@ -1,273 +0,0 @@ -test'; - $linkRedirect = 'https://test.domain2.tld'; - $genericResponse = new HtmlResponse($genericHtml); - $middleware = new ShortcutAndMountPointRedirect((new HeadlessMode())->withRequest((new ServerRequest())->withAttribute( - 'headless', - ['mode' => HeadlessMode::FULL] - ))); - - $correctRedirect = [ - 'redirectUrl' => $linkRedirect, - 'statusCode' => 303, - ]; - - $linkRedirectResponse = $middleware->process( - $this->getTestRequest( - ['type' => 0], - 'https://test.domain.tld', - $this->getTsfeProphecy( - '1', - ['id' => 1, 'doktype' => PageRepository::DOKTYPE_LINK, 'url' => $linkRedirect] - )->reveal() - ), - $this->getMockHandlerWithResponse($genericResponse), - ); - $linkRedirectJson = json_decode($linkRedirectResponse->getBody()->__toString(), true); - self::assertEquals($correctRedirect, $linkRedirectJson); - - $initialDataResponse = $middleware->process( - $this->getTestRequest(['type' => 834], 'https://test.domain.tld'), - $this->getMockHandlerWithResponse($genericResponse) - ); - - self::assertEquals($genericHtml, $initialDataResponse->getBody()->__toString()); - - $middleware = new ShortcutAndMountPointRedirect((new HeadlessMode())->withRequest((new ServerRequest())->withAttribute( - 'headless', - ['mode' => HeadlessMode::FULL] - ))); - $shortcutJsonDecoded = [ - 'redirectUrl' => '/shortcut-target', - 'statusCode' => 307, - ]; - - $middlewareResponse = $middleware->process( - $this->getTestRequest( - ['type' => 0], - 'https://test.domain.tld', - $this->getTsfeProphecy( - '1', - ['id' => 1, 'doktype' => PageRepository::DOKTYPE_SHORTCUT, 'shortcut' => '5'] - )->reveal() - ), - $this->getMockHandlerWithResponse($genericResponse) - ); - self::assertEquals($shortcutJsonDecoded, json_decode($middlewareResponse->getBody()->__toString(), true)); - - $middleware = new ShortcutAndMountPointRedirect((new HeadlessMode())); - - $testRedirectResponse = new RedirectResponse('https://test.domain.tld/shortcut-target', 307); - - $middlewareResponse = $middleware->process( - $this->getTestRequest( - ['type' => 0], - 'https://test.domain.tld', - $this->getTsfeProphecy( - '0', - ['id' => 1, 'doktype' => PageRepository::DOKTYPE_SHORTCUT, 'shortcut' => '5'] - )->reveal(), - false - ), - $this->getMockHandlerWithResponse($genericResponse) - ); - - self::assertEquals( - $testRedirectResponse->getHeader('location')[0], - $middlewareResponse->getHeader('location')[0] - ); - self::assertEquals($testRedirectResponse->getStatusCode(), $middlewareResponse->getStatusCode()); - - $middleware = new ShortcutAndMountPointRedirect(new HeadlessMode()); - - $linkRedirectResponse = $middleware->process( - $this->getTestRequest( - ['type' => 0], - 'https://test.domain.tld', - $this->getTsfeProphecy( - '0', - ['id' => 1, 'doktype' => PageRepository::DOKTYPE_LINK, 'url' => $linkRedirect] - )->reveal(), - false - ), - $this->getMockHandlerWithResponse($genericResponse) - ); - - self::assertEquals($linkRedirect, $linkRedirectResponse->getHeader('location')[0]); - self::assertEquals(303, $linkRedirectResponse->getStatusCode()); - - $middleware = new ShortcutAndMountPointRedirect((new HeadlessMode())->withRequest((new ServerRequest())->withAttribute( - 'headless', - ['mode' => HeadlessMode::FULL] - ))); - $tsfe = $this->getTsfeProphecy( - '0', - ['id' => 1, 'doktype' => PageRepository::DOKTYPE_DEFAULT, 'url' => $linkRedirect] - ); - $tsfe->getRedirectUriForShortcut(Argument::any())->willReturn(null); - $tsfe->getRedirectUriForMountPoint(Argument::any())->willReturn(null); - - $GLOBALS['TSFE'] = $tsfe->reveal(); - - $normalResponse = $middleware->process( - $this->getTestRequest( - ['type' => 0], - 'https://test.domain.tld', - $GLOBALS['TSFE'] - ), - $this->getMockHandlerWithResponse($genericResponse) - ); - - self::assertEquals($genericHtml, $normalResponse->getBody()->__toString()); - } - - public function redirectProvider(): array - { - $domain = 'https://test.redirect.domain.tld'; - 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'], - ]; - } - - /** - * @param $url - * @param $expectedValue - * - * @test - * @dataProvider redirectProvider - */ - public function linkRedirectTest($url, $expectedValue): void - { - $domain = 'https://test.redirect.domain.tld'; - $genericHtml = 'test'; - $genericResponse = new HtmlResponse($genericHtml); - - $middleware = new ShortcutAndMountPointRedirect((new HeadlessMode())->withRequest((new ServerRequest())->withAttribute( - 'headless', - ['mode' => HeadlessMode::FULL] - ))); - - $linkRedirectResponse = $middleware->process( - $this->getTestRequest( - ['type' => 0], - $domain, - $this->getTsfeProphecy( - '1', - ['id' => 1, 'doktype' => PageRepository::DOKTYPE_LINK, 'url' => $url] - )->reveal() - ), - $this->getMockHandlerWithResponse($genericResponse) - ); - - $correctRedirect = [ - 'redirectUrl' => $expectedValue, - 'statusCode' => 303, - ]; - - $linkRedirectJson = json_decode($linkRedirectResponse->getBody()->__toString(), true); - self::assertEquals($correctRedirect, $linkRedirectJson); - } - - protected function getMockHandlerWithResponse($response) - { - $handler = $this->createPartialMock(RequestHandler::class, ['handle']); - $handler->method('handle')->willReturn($response); - return $handler; - } - - protected function getTestRequest( - array $withQueryParams = [], - string $withNormalizedParamsUrl = '', - $withTsfe = null, - bool $withEnabledHeadless = true - ) { - $request = new ServerRequest(); - $request = $request->withUri(new Uri('/')); - - if ($withQueryParams !== []) { - $request = $request->withQueryParams($withQueryParams); - } - - if ($withNormalizedParamsUrl !== '') { - $normalizedParams = $this->prophesize(NormalizedParams::class); - $normalizedParams->getSiteUrl()->willReturn($withNormalizedParamsUrl); - $request = $request->withAttribute('normalizedParams', $normalizedParams->reveal()); - } - - if ($withTsfe) { - $request = $request->withAttribute('frontend.controller', $withTsfe); - } - - $request = $request->withAttribute('headless', new Headless()); - - if ($withEnabledHeadless) { - $request = $request->withAttribute('site', new Site('test_site', 1, ['headless' => true])); - return $request->withAttribute('headless', new Headless(HeadlessMode::FULL)); - } - - return $request; - } - - protected function getTsfeProphecy(string $staticTemplate = '1', array $pageData = []) - { - $setup = []; - $setup['plugin.']['tx_headless.']['staticTemplate'] = $staticTemplate; - - $tmpl = $this->prophesize(TemplateService::class); - $tmpl->setup = $setup; - - $tsfe = $this->prophesize(TypoScriptFrontendController::class); - $tsfe->tmpl = $tmpl->reveal(); - - if ($pageData === []) { - $pageData = ['id' => 1, 'doktype' => PageRepository::DOKTYPE_LINK, 'url' => 'https://test.domain2.tld']; - } elseif ($pageData['doktype'] === PageRepository::DOKTYPE_SHORTCUT) { - $tsfe->getRedirectUriForShortcut(Argument::any())->willReturn('https://test.domain.tld/shortcut-target'); - } - - $tsfe->page = $pageData; - - return $tsfe; - } -} diff --git a/Tests/Unit/Middleware/UserIntMiddlewareTest.php b/Tests/Unit/Middleware/UserIntMiddlewareTest.php index 1f679d54..6ba384d8 100644 --- a/Tests/Unit/Middleware/UserIntMiddlewareTest.php +++ b/Tests/Unit/Middleware/UserIntMiddlewareTest.php @@ -113,7 +113,7 @@ public function processTest() protected function getMockHandlerWithResponse($response) { - $handler = $this->createPartialMock(RequestHandler::class, ['handle']); + $handler = $this->createMock(RequestHandler::class, ['handle']); $handler->method('handle')->willReturn($response); return $handler; } diff --git a/composer.json b/composer.json index 3eada16e..4a8d10bf 100644 --- a/composer.json +++ b/composer.json @@ -28,24 +28,24 @@ ], "require": { "ext-json": "*", - "typo3/cms-core": "^12.4", - "typo3/cms-install": "^12.4" + "typo3/cms-core": "^12.4 || ^13.3", + "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 || ^10", "saschaegerer/phpstan-typo3": "^1.1", - "seld/jsonlint": "^1.8", - "symfony/yaml": "^6.1", - "typo3/cms-form": "^12.4", - "typo3/testing-framework": "^7.0", + "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": {