From 61144dab75ac873e4f17374d83fbdd2d1a5d01a3 Mon Sep 17 00:00:00 2001 From: Daniel Siepmann Date: Wed, 29 Nov 2023 10:36:59 +0100 Subject: [PATCH 1/2] Add meta tags (#49) A new class is added which will add meta tags for dates and events. The class has an interface which allows it to be replaced via DI to alter behaviour. Refactor import regarding data handler. We now also need to add a new column "keywords". We use the new DataHandler approach. But that approach only covered relations so far. We therefore refactor that area to be more generic and use that one for new keywords column. Relates: #10642 --- Classes/Controller/DateController.php | 11 +- Classes/Controller/EventController.php | 11 +- Classes/Domain/Model/Event.php | 10 ++ .../DateMetaInformationInterface.php | 31 ++++ .../DateMetaInformationService.php | 84 ++++++++++ .../EventMetaInformationInterface.php | 31 ++++ .../EventMetaInformationService.php | 78 +++++++++ .../Service/DestinationDataImportService.php | 33 ++-- .../DataHandler.php | 25 +-- .../DataHandler/Assignment.php | 53 +++--- .../TCA/tx_events_domain_model_event.php | 10 ++ Documentation/Changelog/3.9.0.rst | 34 ++++ Documentation/Features/MetaTags.rst | 15 ++ Tests/Functional/Frontend/DatesTest.php | 17 ++ .../DatesTestFixtures/DateMetaTags.php | 34 ++++ Tests/Functional/Frontend/EventsTest.php | 62 +++++++ .../EventsTestFixtures/EventMetaTags.php | 25 +++ .../Extensions/example/ext_localconf.php | 6 + .../Assertions/ImportsKeywords.php | 18 +++ .../Fixtures/ResponseWithKeywords.json | 153 ++++++++++++++++++ .../ImportsExampleAsExpectedTest.php | 14 ++ ext_emconf.php | 2 +- ext_tables.sql | 1 + phpstan-baseline.neon | 5 + 24 files changed, 706 insertions(+), 57 deletions(-) create mode 100644 Classes/Frontend/MetaInformation/DateMetaInformationInterface.php create mode 100644 Classes/Frontend/MetaInformation/DateMetaInformationService.php create mode 100644 Classes/Frontend/MetaInformation/EventMetaInformationInterface.php create mode 100644 Classes/Frontend/MetaInformation/EventMetaInformationService.php create mode 100644 Documentation/Changelog/3.9.0.rst create mode 100644 Documentation/Features/MetaTags.rst create mode 100644 Tests/Functional/Frontend/DatesTestFixtures/DateMetaTags.php create mode 100644 Tests/Functional/Frontend/EventsTest.php create mode 100644 Tests/Functional/Frontend/EventsTestFixtures/EventMetaTags.php create mode 100644 Tests/Functional/Import/DestinationDataTest/Assertions/ImportsKeywords.php create mode 100644 Tests/Functional/Import/DestinationDataTest/Fixtures/ResponseWithKeywords.json diff --git a/Classes/Controller/DateController.php b/Classes/Controller/DateController.php index e071636..7ab4de0 100644 --- a/Classes/Controller/DateController.php +++ b/Classes/Controller/DateController.php @@ -13,6 +13,7 @@ use Wrm\Events\Domain\Repository\RegionRepository; use Wrm\Events\Events\Controller\DateListVariables; use Wrm\Events\Events\Controller\DateSearchVariables; +use Wrm\Events\Frontend\MetaInformation\DateMetaInformationInterface; use Wrm\Events\Pagination\Factory; use Wrm\Events\Service\DataProcessingForModels; @@ -58,6 +59,11 @@ class DateController extends AbstractController */ protected $extensionService; + /** + * @var DateMetaInformationInterface + */ + protected $metaInformationService; + public function __construct( DateDemandFactory $demandFactory, DateRepository $dateRepository, @@ -66,7 +72,8 @@ public function __construct( Factory $paginationFactory, DataProcessingForModels $dataProcessing, EventDispatcher $eventDispatcher, - ExtensionService $extensionService + ExtensionService $extensionService, + DateMetaInformationInterface $metaInformationService ) { $this->demandFactory = $demandFactory; $this->dateRepository = $dateRepository; @@ -76,6 +83,7 @@ public function __construct( $this->dataProcessing = $dataProcessing; $this->eventDispatcher = $eventDispatcher; $this->extensionService = $extensionService; + $this->metaInformationService = $metaInformationService; } protected function initializeAction(): void @@ -163,6 +171,7 @@ public function showAction(Date $date): void $this->trigger404('No event found for requested date.'); } + $this->metaInformationService->setDate($date); $this->view->assign('date', $date); } diff --git a/Classes/Controller/EventController.php b/Classes/Controller/EventController.php index d0a6412..ad03552 100644 --- a/Classes/Controller/EventController.php +++ b/Classes/Controller/EventController.php @@ -3,6 +3,7 @@ namespace Wrm\Events\Controller; use TYPO3\CMS\Extbase\Annotation as Extbase; +use Wrm\Events\Frontend\MetaInformation\EventMetaInformationInterface; use Wrm\Events\Domain\Model\Dto\EventDemandFactory; use Wrm\Events\Domain\Model\Event; use Wrm\Events\Domain\Repository\EventRepository; @@ -25,14 +26,21 @@ class EventController extends AbstractController */ protected $demandFactory; + /** + * @var EventMetaInformationInterface + */ + protected $metaInformationService; + public function __construct( EventRepository $eventRepository, DataProcessingForModels $dataProcessing, - EventDemandFactory $demandFactory + EventDemandFactory $demandFactory, + EventMetaInformationInterface $metaInformationService ) { $this->eventRepository = $eventRepository; $this->dataProcessing = $dataProcessing; $this->demandFactory = $demandFactory; + $this->metaInformationService = $metaInformationService; } protected function initializeAction(): void @@ -54,6 +62,7 @@ public function listAction(): void */ public function showAction(Event $event): void { + $this->metaInformationService->setEvent($event); $this->view->assign('event', $event); } diff --git a/Classes/Domain/Model/Event.php b/Classes/Domain/Model/Event.php index c072e21..19dfda7 100644 --- a/Classes/Domain/Model/Event.php +++ b/Classes/Domain/Model/Event.php @@ -120,6 +120,11 @@ class Event extends AbstractEntity */ protected $features; + /** + * @var string + */ + protected $keywords = ''; + /** * @var ObjectStorage */ @@ -437,6 +442,11 @@ public function getFeatures(): array return $this->getSortedCategory($this->features); } + public function getKeywords(): string + { + return $this->keywords; + } + public function setLanguageUid(int $languageUid): void { $this->_languageUid = $languageUid; diff --git a/Classes/Frontend/MetaInformation/DateMetaInformationInterface.php b/Classes/Frontend/MetaInformation/DateMetaInformationInterface.php new file mode 100644 index 0000000..1ac69d7 --- /dev/null +++ b/Classes/Frontend/MetaInformation/DateMetaInformationInterface.php @@ -0,0 +1,31 @@ + + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + */ + +namespace Wrm\Events\Frontend\MetaInformation; + +use Wrm\Events\Domain\Model\Date; + +interface DateMetaInformationInterface +{ + public function setDate(Date $date): void; +} diff --git a/Classes/Frontend/MetaInformation/DateMetaInformationService.php b/Classes/Frontend/MetaInformation/DateMetaInformationService.php new file mode 100644 index 0000000..3e19415 --- /dev/null +++ b/Classes/Frontend/MetaInformation/DateMetaInformationService.php @@ -0,0 +1,84 @@ + + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + */ + +namespace Wrm\Events\Frontend\MetaInformation; + +use TYPO3\CMS\Core\MetaTag\MetaTagManagerRegistry; +use Wrm\Events\Domain\Model\Date; + +/** + * TYPO3 has many different APIs to set meta information like: Page Title, Meta Tags, OpenGraph Tags, etc. + * Those are combined here for Date detail view. + * That way there is a single place to connect the details to TYPO3 APIs. + */ +final class DateMetaInformationService implements DateMetaInformationInterface +{ + /** + * @var MetaTagManagerRegistry + */ + private $metaTagManagerRegistry; + + public function __construct( + MetaTagManagerRegistry $metaTagManagerRegistry + ) { + $this->metaTagManagerRegistry = $metaTagManagerRegistry; + } + + public function setDate(Date $date): void + { + $this->setDescription($date); + $this->setKeywords($date); + } + + private function setDescription(Date $date): void + { + $description = ''; + if ($date->getEvent() !== null) { + $description = $date->getEvent()->getTeaser(); + } + if ($description === '') { + return; + } + + $this->metaTagManagerRegistry + ->getManagerForProperty('description') + ->addProperty('description', $description) + ; + } + + private function setKeywords(Date $date): void + { + $keywords = ''; + if ($date->getEvent() !== null) { + $keywords = $date->getEvent()->getKeywords(); + } + if ($keywords === '') { + return; + } + + $this->metaTagManagerRegistry + ->getManagerForProperty('keywords') + ->addProperty('keywords', $keywords) + ; + } +} diff --git a/Classes/Frontend/MetaInformation/EventMetaInformationInterface.php b/Classes/Frontend/MetaInformation/EventMetaInformationInterface.php new file mode 100644 index 0000000..6195d04 --- /dev/null +++ b/Classes/Frontend/MetaInformation/EventMetaInformationInterface.php @@ -0,0 +1,31 @@ + + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + */ + +namespace Wrm\Events\Frontend\MetaInformation; + +use Wrm\Events\Domain\Model\Event; + +interface EventMetaInformationInterface +{ + public function setEvent(Event $event): void; +} diff --git a/Classes/Frontend/MetaInformation/EventMetaInformationService.php b/Classes/Frontend/MetaInformation/EventMetaInformationService.php new file mode 100644 index 0000000..56e5481 --- /dev/null +++ b/Classes/Frontend/MetaInformation/EventMetaInformationService.php @@ -0,0 +1,78 @@ + + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + */ + +namespace Wrm\Events\Frontend\MetaInformation; + +use TYPO3\CMS\Core\MetaTag\MetaTagManagerRegistry; +use Wrm\Events\Domain\Model\Event; + +/** + * TYPO3 has many different APIs to set meta information like: Page Title, Meta Tags, OpenGraph Tags, etc. + * Those are combined here for Event detail view. + * That way there is a single place to connect the details to TYPO3 APIs. + */ +final class EventMetaInformationService implements EventMetaInformationInterface +{ + /** + * @var MetaTagManagerRegistry + */ + private $metaTagManagerRegistry; + + public function __construct( + MetaTagManagerRegistry $metaTagManagerRegistry + ) { + $this->metaTagManagerRegistry = $metaTagManagerRegistry; + } + + public function setEvent(Event $event): void + { + $this->setDescription($event); + $this->setKeywords($event); + } + + private function setDescription(Event $event): void + { + $description = $event->getTeaser(); + if ($description === '') { + return; + } + + $this->metaTagManagerRegistry + ->getManagerForProperty('description') + ->addProperty('description', $description) + ; + } + + private function setKeywords(Event $event): void + { + $keywords = $event->getKeywords(); + if ($keywords === '') { + return; + } + + $this->metaTagManagerRegistry + ->getManagerForProperty('keywords') + ->addProperty('keywords', $keywords) + ; + } +} diff --git a/Classes/Service/DestinationDataImportService.php b/Classes/Service/DestinationDataImportService.php index acf8ba8..953d297 100644 --- a/Classes/Service/DestinationDataImportService.php +++ b/Classes/Service/DestinationDataImportService.php @@ -293,14 +293,21 @@ public function processData(array $data): int $this->persistenceManager->persistAll(); // Apply changes via DataHandler (The new way) - $this->logger->info('Apply changes via DataHandler'); - if ($event['categories'] ?? false) { - $this->setCategories($event['categories']); - } - if ($event['features']) { - $this->setFeatures($event['features']); + $eventUid = $this->tmpCurrentEvent->getUid(); + if (is_int($eventUid) === false) { + throw new Exception('Could not persist and fetch uid of event.', 1701244570); } + $this->logger->info('Apply changes via DataHandler'); + $this->dataHandler->updateEvent( + $eventUid, + [ + new Assignment('keywords', implode(', ', $event['keywords'] ?? [])), + $this->getCategories($event['categories'] ?? []), + $this->getFeatures($event['features'] ?? []), + ] + ); + $this->logger->info('Update slugs'); $this->slugger->update('tx_events_domain_model_event'); $this->slugger->update('tx_events_domain_model_date'); @@ -313,7 +320,7 @@ public function processData(array $data): int return 0; } - private function setCategories(array $categories): void + private function getCategories(array $categories): Assignment { $categories = $this->categoriesAssignment->getCategories(new CategoryImport( $this->import->getCategoryParent(), @@ -327,14 +334,13 @@ private function setCategories(array $categories): void ); $this->eventDispatcher->dispatch($event); - $this->dataHandler->storeAssignments(new Assignment( - $this->tmpCurrentEvent->getUid(), + return Assignment::createFromDomainObjects( 'categories', $event->getCategories()->toArray() - )); + ); } - private function setFeatures(array $features): void + private function getFeatures(array $features): Assignment { $features = $this->categoriesAssignment->getCategories(new CategoryImport( $this->import->getFeaturesParent(), @@ -343,11 +349,10 @@ private function setFeatures(array $features): void true )); - $this->dataHandler->storeAssignments(new Assignment( - $this->tmpCurrentEvent->getUid(), + return Assignment::createFromDomainObjects( 'features', $features->toArray() - )); + ); } private function setDates( diff --git a/Classes/Service/DestinationDataImportService/DataHandler.php b/Classes/Service/DestinationDataImportService/DataHandler.php index 36e53f5..d22b775 100644 --- a/Classes/Service/DestinationDataImportService/DataHandler.php +++ b/Classes/Service/DestinationDataImportService/DataHandler.php @@ -42,25 +42,26 @@ public function __construct( $this->logger = $logManager->getLogger(__CLASS__); } - public function storeAssignments( - Assignment $assignment + /** + * @param Assignment[] $assignments + */ + public function updateEvent( + int $eventUid, + array $assignments ): void { - $data = [ - 'tx_events_domain_model_event' => [ - $assignment->getUid() => [ - $assignment->getColumnName() => implode(',', $assignment->getUids()), - ], - ], - ]; + $data = ['tx_events_domain_model_event' => [$eventUid => []]]; + foreach ($assignments as $assignment) { + $data['tx_events_domain_model_event'][$eventUid][$assignment->getColumnName()] = $assignment->getValue(); + } - $this->logger->debug('Import assignment.', $data); + $this->logger->debug('Update event data.', $data); $dataHandler = GeneralUtility::makeInstance(Typo3DataHandler::class); $dataHandler->start($data, []); $dataHandler->process_datamap(); if ($dataHandler->errorLog !== []) { - $this->logger->error('Error during import of assignments.', [ - 'assignment' => $assignment, + $this->logger->error('Error during update of event data.', [ + 'assignments' => $assignments, 'errors' => $dataHandler->errorLog, ]); } diff --git a/Classes/Service/DestinationDataImportService/DataHandler/Assignment.php b/Classes/Service/DestinationDataImportService/DataHandler/Assignment.php index 205d68b..264a68b 100644 --- a/Classes/Service/DestinationDataImportService/DataHandler/Assignment.php +++ b/Classes/Service/DestinationDataImportService/DataHandler/Assignment.php @@ -28,55 +28,52 @@ final class Assignment { - /** - * @var int - */ - private $uid; - /** * @var string */ private $columnName; /** - * @var int[] + * @var string */ - private $uids; + private $value; - /** - * @param AbstractDomainObject[] $assignments - */ public function __construct( - int $uid, string $columnName, - array $assignments + string $value ) { - $this->uid = $uid; $this->columnName = $columnName; - $this->uids = array_map(static function (AbstractDomainObject $model): int { - $uid = $model->getUid(); - if (is_int($uid) === false) { - throw new InvalidArgumentException('Only object with uid supported.', 1698936965); - } - return $uid; - }, $assignments); + $this->value = $value; } - public function getUid(): int + public function getColumnName(): string { - return $this->uid; + return $this->columnName; } - public function getColumnName(): string + public function getValue(): string { - return $this->columnName; + return $this->value; } /** - * @return int[] + * @param AbstractDomainObject[] $objects */ - public function getUids(): array - { - return $this->uids; + public static function createFromDomainObjects( + string $columnName, + array $objects + ): self { + $uids = array_map(static function (AbstractDomainObject $model): int { + $uid = $model->getUid(); + if (is_int($uid) === false) { + throw new InvalidArgumentException('Only object with uid supported.', 1698936965); + } + return $uid; + }, $objects); + + return new self( + $columnName, + implode(',', $uids) + ); } } diff --git a/Configuration/TCA/tx_events_domain_model_event.php b/Configuration/TCA/tx_events_domain_model_event.php index 39c185e..e8e3cbd 100644 --- a/Configuration/TCA/tx_events_domain_model_event.php +++ b/Configuration/TCA/tx_events_domain_model_event.php @@ -54,6 +54,7 @@ partner, categories, features, + keywords, references_events, pages, --div--;' . $l10nPath . ':tx_events_domain_model_event.tabs.media, @@ -400,6 +401,15 @@ 'features' => [ 'exclude' => true, ], + 'keywords' => [ + 'exclude' => true, + 'label' => 'Keywords', + 'config' => [ + 'type' => 'text', + 'cols' => 40, + 'rows' => 3, + ], + ], 'dates' => [ 'exclude' => true, diff --git a/Documentation/Changelog/3.9.0.rst b/Documentation/Changelog/3.9.0.rst new file mode 100644 index 0000000..f4559dd --- /dev/null +++ b/Documentation/Changelog/3.9.0.rst @@ -0,0 +1,34 @@ +3.9.0 +===== + +Breaking +-------- + +Nothing + +Features +-------- + +Backport of 4.0.0 features: + +* Add meta tags. + A new class is added which will add meta tags for dates and events. + The class has an interface which allows it to be replaced via DI to alter behaviour. + +* Import keywords for events from destination.one. + That way keywords are available for usage in meta tags. + +Fixes +----- + +Nothing + +Tasks +----- + +Nothing + +Deprecation +----------- + +Nothing diff --git a/Documentation/Features/MetaTags.rst b/Documentation/Features/MetaTags.rst new file mode 100644 index 0000000..4284d2f --- /dev/null +++ b/Documentation/Features/MetaTags.rst @@ -0,0 +1,15 @@ +.. index:: single: meta tags +.. _metaTags: + +Meta Tags +========= + +The extension comes with default implementations for meta tags. + +The default implementation can be exchanged by leveraging TYPO3 Dependency Injection. + +Further resources: + +* https://docs.typo3.org/m/typo3/reference-coreapi/12.4/en-us/ApiOverview/Seo/MetaTagApi.html + +* https://docs.typo3.org/m/typo3/reference-coreapi/12.4/en-us/ApiOverview/DependencyInjection/Index.html diff --git a/Tests/Functional/Frontend/DatesTest.php b/Tests/Functional/Frontend/DatesTest.php index dff5386..faa465e 100644 --- a/Tests/Functional/Frontend/DatesTest.php +++ b/Tests/Functional/Frontend/DatesTest.php @@ -199,4 +199,21 @@ public function returnsUpcomingDates(): void self::assertStringNotContainsString('Event 1', $html); self::assertStringContainsString('Event 2', $html); } + + #[Test] + public function addsMetaTags(): void + { + $this->importPHPDataSet(__DIR__ . '/DatesTestFixtures/DateMetaTags.php'); + + $request = new InternalRequest(); + $request = $request->withPageId(1); + $request = $request->withQueryParameter('tx_events_dateshow[date]', '1'); + $response = $this->executeFrontendRequest($request); + + self::assertSame(200, $response->getStatusCode()); + $html = (string)$response->getBody(); + + self::assertStringContainsString('', $html); + self::assertStringContainsString('', $html); + } } diff --git a/Tests/Functional/Frontend/DatesTestFixtures/DateMetaTags.php b/Tests/Functional/Frontend/DatesTestFixtures/DateMetaTags.php new file mode 100644 index 0000000..e6d7eff --- /dev/null +++ b/Tests/Functional/Frontend/DatesTestFixtures/DateMetaTags.php @@ -0,0 +1,34 @@ + [ + 0 => [ + 'uid' => '1', + 'pid' => '1', + 'CType' => 'list', + 'list_type' => 'events_dateshow', + 'header' => 'Singleview', + ], + ], + 'tx_events_domain_model_event' => [ + 0 => [ + 'uid' => '1', + 'pid' => '2', + 'title' => 'Title of Event', + 'teaser' => 'Teaser of Event', + 'keywords' => 'Gewölbe, Goethe, Horst Damm, Kästner, Theater', + 'hidden' => '0', + ], + ], + 'tx_events_domain_model_date' => [ + 0 => [ + 'uid' => '1', + 'pid' => '2', + 'event' => '1', + 'start' => '1676419200', + 'end' => '1676484000', + ], + ], +]; diff --git a/Tests/Functional/Frontend/EventsTest.php b/Tests/Functional/Frontend/EventsTest.php new file mode 100644 index 0000000..b30a820 --- /dev/null +++ b/Tests/Functional/Frontend/EventsTest.php @@ -0,0 +1,62 @@ + + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + */ + +namespace Wrm\Events\Tests\Functional\Frontend; + +use PHPUnit\Framework\Attributes\Test; +use TYPO3\TestingFramework\Core\Functional\Framework\Frontend\InternalRequest; +use Wrm\Events\Tests\Functional\AbstractFunctionalTestCase; + +class EventsTest extends AbstractFunctionalTestCase +{ + protected function setUp(): void + { + $this->testExtensionsToLoad = [ + 'typo3conf/ext/events/Tests/Functional/Frontend/Fixtures/Extensions/example', + ]; + + parent::setUp(); + + $this->importPHPDataSet(__DIR__ . '/Fixtures/Database/SiteStructure.php'); + $this->setUpFrontendRendering(); + } + + /** + * @test + */ + public function addsMetaTags(): void + { + $this->importPHPDataSet(__DIR__ . '/EventsTestFixtures/EventMetaTags.php'); + + $request = new InternalRequest(); + $request = $request->withPageId(1); + $request = $request->withQueryParameter('tx_events_eventshow[event]', '1'); + $response = $this->executeFrontendRequest($request); + + self::assertSame(200, $response->getStatusCode()); + $html = (string)$response->getBody(); + + self::assertStringContainsString('', $html); + self::assertStringContainsString('', $html); + } +} diff --git a/Tests/Functional/Frontend/EventsTestFixtures/EventMetaTags.php b/Tests/Functional/Frontend/EventsTestFixtures/EventMetaTags.php new file mode 100644 index 0000000..34e69ca --- /dev/null +++ b/Tests/Functional/Frontend/EventsTestFixtures/EventMetaTags.php @@ -0,0 +1,25 @@ + [ + 0 => [ + 'uid' => '1', + 'pid' => '1', + 'CType' => 'list', + 'list_type' => 'events_eventshow', + 'header' => 'Singleview', + ], + ], + 'tx_events_domain_model_event' => [ + 0 => [ + 'uid' => '1', + 'pid' => '2', + 'title' => 'Title of Event', + 'teaser' => 'Teaser of Event', + 'keywords' => 'Gewölbe, Goethe, Horst Damm, Kästner, Theater', + 'hidden' => '0', + ], + ], +]; diff --git a/Tests/Functional/Frontend/Fixtures/Extensions/example/ext_localconf.php b/Tests/Functional/Frontend/Fixtures/Extensions/example/ext_localconf.php index 0ea100d..f6286c7 100644 --- a/Tests/Functional/Frontend/Fixtures/Extensions/example/ext_localconf.php +++ b/Tests/Functional/Frontend/Fixtures/Extensions/example/ext_localconf.php @@ -5,3 +5,9 @@ 'DateListTest', [\Wrm\Events\Controller\DateController::class => 'list'] ); + +\TYPO3\CMS\Extbase\Utility\ExtensionUtility::configurePlugin( + 'Events', + 'EventShow', + [\Wrm\Events\Controller\EventController::class => 'show'] +); diff --git a/Tests/Functional/Import/DestinationDataTest/Assertions/ImportsKeywords.php b/Tests/Functional/Import/DestinationDataTest/Assertions/ImportsKeywords.php new file mode 100644 index 0000000..860adf9 --- /dev/null +++ b/Tests/Functional/Import/DestinationDataTest/Assertions/ImportsKeywords.php @@ -0,0 +1,18 @@ + [ + [ + 'uid' => 1, + 'global_id' => 'e_100347853', + 'keywords' => 'Gewölbe, Goethe, Horst Damm, Kästner, Theater, low_image_qualit', + ], + [ + 'uid' => 2, + 'global_id' => 'e_100347854', + 'keywords' => '', + ], + ], +]; diff --git a/Tests/Functional/Import/DestinationDataTest/Fixtures/ResponseWithKeywords.json b/Tests/Functional/Import/DestinationDataTest/Fixtures/ResponseWithKeywords.json new file mode 100644 index 0000000..4d865b9 --- /dev/null +++ b/Tests/Functional/Import/DestinationDataTest/Fixtures/ResponseWithKeywords.json @@ -0,0 +1,153 @@ +{ + "status": "OK", + "count": 2, + "overallcount": 2, + "channels": [], + "facetGroups": [], + "items": [ + { + "global_id": "e_100347853", + "id": "100347853", + "title": "Allerlei Weihnachtliches (Heute mit Johannes Geißer)", + "type": "Event", + "categories": [ + ], + "texts": [ + { + "rel": "details", + "type": "text/html", + "value": "Die Lichter sind entzündet, die Plätzchen duften, man rückt endlich wieder näher zusammen und lauscht den Geschichten. Vier Schauspieler*innen unseres Theaters überraschen mit ihren weihnachtlichen Texten, die sie für uns ausgewählt haben. Dazu plaudern sie über persönliche Anekdoten und erinnern sich an ihre schönsten und verrücktesten Weihnachtsfeste. Und da der Genuss in der Vorweihnachtszeit nicht fehlen darf, wird an jedem Adventssonntag eine andere weihnachtliche Spezialität serviert.
Eintritt: 10 € (inkl. Gedeck mit weihnachtlicher Schillerlocke)
Um Voranmeldung unter 03672-486470 oder schillerhaus@rudolstadt.de wird gebeten.
Es gilt die 2G-PLUS-Regel. 
" + }, + { + "rel": "details", + "type": "text/plain", + "value": "Die Lichter sind entzündet, die Plätzchen duften, man rückt endlich wieder näher zusammen und lauscht den Geschichten. Vier Schauspieler*innen unseres Theaters überraschen mit ihren weihnachtlichen Texten, die sie für uns ausgewählt haben. Dazu plaudern sie über persönliche Anekdoten und erinnern sich an ihre schönsten und verrücktesten Weihnachtsfeste. Und da der Genuss in der Vorweihnachtszeit nicht fehlen darf, wird an jedem Adventssonntag eine andere weihnachtliche Spezialität serviert.\nEintritt: 10 € (inkl. Gedeck mit weihnachtlicher Schillerlocke)\nUm Voranmeldung unter 03672-486470 oder schillerhaus@rudolstadt.de wird gebeten.\nEs gilt die 2G-PLUS-Regel." + }, + { + "rel": "teaser", + "type": "text/html" + }, + { + "rel": "teaser", + "type": "text/plain" + } + ], + "country": "Deutschland", + "areas": [ + "Rudolstadt und Umgebung" + ], + "city": "Rudolstadt", + "zip": "07407", + "street": "Schillerstraße 25", + "phone": "+ 49 3672 / 486470", + "fax": "+ 49 3672 / 486475", + "web": "http://www.schillerhaus.rudolstadt.de/", + "email": "schillerhaus@rudolstadt.de", + "author": "support@hubermedia.de", + "media_objects": [ + ], + "keywords": [ + "Gewölbe", + "Goethe", + "Horst Damm", + "Kästner", + "Theater", + "low_image_qualit" + ], + "timeIntervals": [ + { + "weekdays": [], + "start": "2099-12-19T15:00:00+01:00", + "end": "2099-12-19T16:30:00+01:00", + "tz": "Europe/Berlin", + "interval": 1 + } + ], + "name": "Schillerhaus Rudolstadt", + "features": [ + ], + "addresses": [ + ], + "created": "2099-10-31T12:29:00+00:00", + "changed": "2099-12-14T08:29:00+00:00", + "company": "", + "district": "", + "postoffice": "", + "phone2": "", + "seasons": [], + "subitems": [], + "hyperObjects": [] + }, + { + "global_id": "e_100347854", + "id": "100347854", + "title": "Allerlei Weihnachtliches (Heute mit Johannes Geißer)", + "type": "Event", + "categories": [ + ], + "texts": [ + { + "rel": "details", + "type": "text/html", + "value": "Die Lichter sind entzündet, die Plätzchen duften, man rückt endlich wieder näher zusammen und lauscht den Geschichten. Vier Schauspieler*innen unseres Theaters überraschen mit ihren weihnachtlichen Texten, die sie für uns ausgewählt haben. Dazu plaudern sie über persönliche Anekdoten und erinnern sich an ihre schönsten und verrücktesten Weihnachtsfeste. Und da der Genuss in der Vorweihnachtszeit nicht fehlen darf, wird an jedem Adventssonntag eine andere weihnachtliche Spezialität serviert.
Eintritt: 10 € (inkl. Gedeck mit weihnachtlicher Schillerlocke)
Um Voranmeldung unter 03672-486470 oder schillerhaus@rudolstadt.de wird gebeten.
Es gilt die 2G-PLUS-Regel. 
" + }, + { + "rel": "details", + "type": "text/plain", + "value": "Die Lichter sind entzündet, die Plätzchen duften, man rückt endlich wieder näher zusammen und lauscht den Geschichten. Vier Schauspieler*innen unseres Theaters überraschen mit ihren weihnachtlichen Texten, die sie für uns ausgewählt haben. Dazu plaudern sie über persönliche Anekdoten und erinnern sich an ihre schönsten und verrücktesten Weihnachtsfeste. Und da der Genuss in der Vorweihnachtszeit nicht fehlen darf, wird an jedem Adventssonntag eine andere weihnachtliche Spezialität serviert.\nEintritt: 10 € (inkl. Gedeck mit weihnachtlicher Schillerlocke)\nUm Voranmeldung unter 03672-486470 oder schillerhaus@rudolstadt.de wird gebeten.\nEs gilt die 2G-PLUS-Regel." + }, + { + "rel": "teaser", + "type": "text/html" + }, + { + "rel": "teaser", + "type": "text/plain" + } + ], + "country": "Deutschland", + "areas": [ + "Rudolstadt und Umgebung" + ], + "city": "Rudolstadt", + "zip": "07407", + "street": "Schillerstraße 25", + "phone": "+ 49 3672 / 486470", + "fax": "+ 49 3672 / 486475", + "web": "http://www.schillerhaus.rudolstadt.de/", + "email": "schillerhaus@rudolstadt.de", + "author": "support@hubermedia.de", + "media_objects": [ + ], + "keywords": [ + ], + "timeIntervals": [ + { + "weekdays": [], + "start": "2099-12-19T15:00:00+01:00", + "end": "2099-12-19T16:30:00+01:00", + "tz": "Europe/Berlin", + "interval": 1 + } + ], + "name": "Schillerhaus Rudolstadt", + "features": [ + ], + "addresses": [ + ], + "created": "2099-10-31T12:29:00+00:00", + "changed": "2099-12-14T08:29:00+00:00", + "source": { + "url": "https://example.com", + "value": "Foreign Example 1" + }, + "company": "", + "district": "", + "postoffice": "", + "phone2": "", + "seasons": [], + "subitems": [], + "hyperObjects": [] + } + ] +} diff --git a/Tests/Functional/Import/DestinationDataTest/ImportsExampleAsExpectedTest.php b/Tests/Functional/Import/DestinationDataTest/ImportsExampleAsExpectedTest.php index 5d3f0cd..13e32e3 100644 --- a/Tests/Functional/Import/DestinationDataTest/ImportsExampleAsExpectedTest.php +++ b/Tests/Functional/Import/DestinationDataTest/ImportsExampleAsExpectedTest.php @@ -94,4 +94,18 @@ public function importsSource(): void $this->assertPHPDataSet(__DIR__ . '/Assertions/ImportsSource.php'); $this->assertEmptyLog(); } + + #[Test] + public function importsKeywords(): void + { + $this->importPHPDataSet(__DIR__ . '/Fixtures/Database/DefaultImportConfiguration.php'); + $this->setUpResponses([ + new Response(200, [], file_get_contents(__DIR__ . '/Fixtures/ResponseWithKeywords.json') ?: ''), + ]); + + $this->executeCommand(); + + $this->assertPHPDataSet(__DIR__ . '/Assertions/ImportsKeywords.php'); + $this->assertEmptyLog(); + } } diff --git a/ext_emconf.php b/ext_emconf.php index d55cbdd..60445de 100644 --- a/ext_emconf.php +++ b/ext_emconf.php @@ -9,7 +9,7 @@ 'state' => 'stable', 'createDirs' => '', 'clearCacheOnLoad' => 0, - 'version' => '3.8.0', + 'version' => '3.9.0', 'constraints' => [ 'depends' => [ 'typo3' => '10.4.00-11.5.99', diff --git a/ext_tables.sql b/ext_tables.sql index 83b2f46..fe6210d 100644 --- a/ext_tables.sql +++ b/ext_tables.sql @@ -15,6 +15,7 @@ CREATE TABLE tx_events_domain_model_event ( images int(11) unsigned NOT NULL default '0', categories int(11) DEFAULT '0' NOT NULL, features int(11) DEFAULT '0' NOT NULL, + keywords text, pages text, dates int(11) unsigned DEFAULT '0' NOT NULL, organizer int(11) unsigned DEFAULT '0', diff --git a/phpstan-baseline.neon b/phpstan-baseline.neon index e447268..62c5015 100644 --- a/phpstan-baseline.neon +++ b/phpstan-baseline.neon @@ -90,6 +90,11 @@ parameters: count: 1 path: Classes/Service/Cleanup/Files.php + - + message: "#^Parameter \\#2 \\$objects of static method Wrm\\\\Events\\\\Service\\\\DestinationDataImportService\\\\DataHandler\\\\Assignment\\:\\:createFromDomainObjects\\(\\) expects array\\, array\\ given\\.$#" + count: 2 + path: Classes/Service/DestinationDataImportService.php + - message: "#^Parameter \\#1 \\$uid of class Wrm\\\\Events\\\\Service\\\\DestinationDataImportService\\\\DataHandler\\\\Assignment constructor expects int, int\\|null given\\.$#" count: 2 From 24ffd71a5a5f1e8a5fccdaf8b6c6a49b1d19410f Mon Sep 17 00:00:00 2001 From: Daniel Siepmann Date: Wed, 29 Nov 2023 10:52:57 +0100 Subject: [PATCH 2/2] Provide Page Titles (#46) That way it is possible to alter the TYPO3 page title when showing a date or event. Relates: #10640 --- .../DateMetaInformationService.php | 12 ++++- .../EventMetaInformationService.php | 12 ++++- .../PageTitleProvider/DateTitleProvider.php | 51 +++++++++++++++++++ .../DateTitleProviderInterface.php | 33 ++++++++++++ .../PageTitleProvider/EventTitleProvider.php | 48 +++++++++++++++++ .../EventTitleProviderInterface.php | 33 ++++++++++++ Documentation/Changelog/3.9.0.rst | 2 + Documentation/Features/PageTitle.rst | 15 ++++++ Tests/Functional/Frontend/DatesTest.php | 22 +++++++- .../DatesTestFixtures/DatePageTitle.php | 32 ++++++++++++ Tests/Functional/Frontend/EventsTest.php | 18 +++++++ .../EventsTestFixtures/EventPageTitle.php | 23 +++++++++ .../Fixtures/TypoScript/Rendering.typoscript | 13 +++++ 13 files changed, 311 insertions(+), 3 deletions(-) create mode 100644 Classes/Frontend/PageTitleProvider/DateTitleProvider.php create mode 100644 Classes/Frontend/PageTitleProvider/DateTitleProviderInterface.php create mode 100644 Classes/Frontend/PageTitleProvider/EventTitleProvider.php create mode 100644 Classes/Frontend/PageTitleProvider/EventTitleProviderInterface.php create mode 100644 Documentation/Features/PageTitle.rst create mode 100644 Tests/Functional/Frontend/DatesTestFixtures/DatePageTitle.php create mode 100644 Tests/Functional/Frontend/EventsTestFixtures/EventPageTitle.php diff --git a/Classes/Frontend/MetaInformation/DateMetaInformationService.php b/Classes/Frontend/MetaInformation/DateMetaInformationService.php index 3e19415..89aa262 100644 --- a/Classes/Frontend/MetaInformation/DateMetaInformationService.php +++ b/Classes/Frontend/MetaInformation/DateMetaInformationService.php @@ -25,6 +25,7 @@ use TYPO3\CMS\Core\MetaTag\MetaTagManagerRegistry; use Wrm\Events\Domain\Model\Date; +use Wrm\Events\Frontend\PageTitleProvider\DateTitleProviderInterface; /** * TYPO3 has many different APIs to set meta information like: Page Title, Meta Tags, OpenGraph Tags, etc. @@ -38,16 +39,25 @@ final class DateMetaInformationService implements DateMetaInformationInterface */ private $metaTagManagerRegistry; + /** + * @var DateTitleProviderInterface + */ + private $titleProvider; + public function __construct( - MetaTagManagerRegistry $metaTagManagerRegistry + MetaTagManagerRegistry $metaTagManagerRegistry, + DateTitleProviderInterface $titleProvider ) { $this->metaTagManagerRegistry = $metaTagManagerRegistry; + $this->titleProvider = $titleProvider; } public function setDate(Date $date): void { $this->setDescription($date); $this->setKeywords($date); + + $this->titleProvider->setDate($date); } private function setDescription(Date $date): void diff --git a/Classes/Frontend/MetaInformation/EventMetaInformationService.php b/Classes/Frontend/MetaInformation/EventMetaInformationService.php index 56e5481..a3d84b8 100644 --- a/Classes/Frontend/MetaInformation/EventMetaInformationService.php +++ b/Classes/Frontend/MetaInformation/EventMetaInformationService.php @@ -25,6 +25,7 @@ use TYPO3\CMS\Core\MetaTag\MetaTagManagerRegistry; use Wrm\Events\Domain\Model\Event; +use Wrm\Events\Frontend\PageTitleProvider\EventTitleProviderInterface; /** * TYPO3 has many different APIs to set meta information like: Page Title, Meta Tags, OpenGraph Tags, etc. @@ -38,16 +39,25 @@ final class EventMetaInformationService implements EventMetaInformationInterface */ private $metaTagManagerRegistry; + /** + * @var EventTitleProviderInterface + */ + private $titleProvider; + public function __construct( - MetaTagManagerRegistry $metaTagManagerRegistry + MetaTagManagerRegistry $metaTagManagerRegistry, + EventTitleProviderInterface $titleProvider ) { $this->metaTagManagerRegistry = $metaTagManagerRegistry; + $this->titleProvider = $titleProvider; } public function setEvent(Event $event): void { $this->setDescription($event); $this->setKeywords($event); + + $this->titleProvider->setEvent($event); } private function setDescription(Event $event): void diff --git a/Classes/Frontend/PageTitleProvider/DateTitleProvider.php b/Classes/Frontend/PageTitleProvider/DateTitleProvider.php new file mode 100644 index 0000000..50b544e --- /dev/null +++ b/Classes/Frontend/PageTitleProvider/DateTitleProvider.php @@ -0,0 +1,51 @@ + + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + */ + +namespace Wrm\Events\Frontend\PageTitleProvider; + +use Wrm\Events\Domain\Model\Date; + +final class DateTitleProvider implements DateTitleProviderInterface +{ + /** + * @var null|Date + */ + private $date = null; + + public function setDate(Date $date): void + { + $this->date = $date; + } + + public function getTitle(): string + { + if ($this->date === null) { + return ''; + } + + return implode(' ', [ + $this->date->getEvent()->getTitle(), + $this->date->getStart()->format('d.m.Y H:i'), + ]); + } +} diff --git a/Classes/Frontend/PageTitleProvider/DateTitleProviderInterface.php b/Classes/Frontend/PageTitleProvider/DateTitleProviderInterface.php new file mode 100644 index 0000000..f48e7a8 --- /dev/null +++ b/Classes/Frontend/PageTitleProvider/DateTitleProviderInterface.php @@ -0,0 +1,33 @@ + + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + */ + +namespace Wrm\Events\Frontend\PageTitleProvider; + +use TYPO3\CMS\Core\PageTitle\PageTitleProviderInterface; +use TYPO3\CMS\Core\SingletonInterface; +use Wrm\Events\Domain\Model\Date; + +interface DateTitleProviderInterface extends PageTitleProviderInterface, SingletonInterface +{ + public function setDate(Date $date): void; +} diff --git a/Classes/Frontend/PageTitleProvider/EventTitleProvider.php b/Classes/Frontend/PageTitleProvider/EventTitleProvider.php new file mode 100644 index 0000000..ed6d86d --- /dev/null +++ b/Classes/Frontend/PageTitleProvider/EventTitleProvider.php @@ -0,0 +1,48 @@ + + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + */ + +namespace Wrm\Events\Frontend\PageTitleProvider; + +use Wrm\Events\Domain\Model\Event; + +final class EventTitleProvider implements EventTitleProviderInterface +{ + /** + * @var null|Event + */ + private $event = null; + + public function setEvent(Event $event): void + { + $this->event = $event; + } + + public function getTitle(): string + { + if ($this->event === null) { + return ''; + } + + return $this->event->getTitle(); + } +} diff --git a/Classes/Frontend/PageTitleProvider/EventTitleProviderInterface.php b/Classes/Frontend/PageTitleProvider/EventTitleProviderInterface.php new file mode 100644 index 0000000..c3b5463 --- /dev/null +++ b/Classes/Frontend/PageTitleProvider/EventTitleProviderInterface.php @@ -0,0 +1,33 @@ + + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + */ + +namespace Wrm\Events\Frontend\PageTitleProvider; + +use TYPO3\CMS\Core\PageTitle\PageTitleProviderInterface; +use TYPO3\CMS\Core\SingletonInterface; +use Wrm\Events\Domain\Model\Event; + +interface EventTitleProviderInterface extends PageTitleProviderInterface, SingletonInterface +{ + public function setEvent(Event $event): void; +} diff --git a/Documentation/Changelog/3.9.0.rst b/Documentation/Changelog/3.9.0.rst index f4559dd..637af2e 100644 --- a/Documentation/Changelog/3.9.0.rst +++ b/Documentation/Changelog/3.9.0.rst @@ -18,6 +18,8 @@ Backport of 4.0.0 features: * Import keywords for events from destination.one. That way keywords are available for usage in meta tags. +* Add page title provider. That way it is possible to alter the TYPO3 page title when showing a date or event. + Fixes ----- diff --git a/Documentation/Features/PageTitle.rst b/Documentation/Features/PageTitle.rst new file mode 100644 index 0000000..edbc6b3 --- /dev/null +++ b/Documentation/Features/PageTitle.rst @@ -0,0 +1,15 @@ +.. index:: single: page title +.. _pageTitle: + +Page Title +========== + +The extension comes with default implementations for PageTitleProvider. + +The default implementation can be exchanged by leveraging TYPO3 Dependency Injection. + +Further resources: + +* https://docs.typo3.org/m/typo3/reference-coreapi/12.4/en-us/ApiOverview/Seo/PageTitleApi.html + +* https://docs.typo3.org/m/typo3/reference-coreapi/12.4/en-us/ApiOverview/DependencyInjection/Index.html diff --git a/Tests/Functional/Frontend/DatesTest.php b/Tests/Functional/Frontend/DatesTest.php index faa465e..e34ee81 100644 --- a/Tests/Functional/Frontend/DatesTest.php +++ b/Tests/Functional/Frontend/DatesTest.php @@ -200,7 +200,9 @@ public function returnsUpcomingDates(): void self::assertStringContainsString('Event 2', $html); } - #[Test] + /** + * @test + */ public function addsMetaTags(): void { $this->importPHPDataSet(__DIR__ . '/DatesTestFixtures/DateMetaTags.php'); @@ -216,4 +218,22 @@ public function addsMetaTags(): void self::assertStringContainsString('', $html); self::assertStringContainsString('', $html); } + + /** + * @test + */ + public function altersPageTitle(): void + { + $this->importPHPDataSet(__DIR__ . '/DatesTestFixtures/DatePageTitle.php'); + + $request = new InternalRequest(); + $request = $request->withPageId(1); + $request = $request->withQueryParameter('tx_events_dateshow[date]', '1'); + $response = $this->executeFrontendRequest($request); + + self::assertSame(200, $response->getStatusCode()); + $html = (string)$response->getBody(); + + self::assertStringContainsString('Title of Event 15.02.2023 00:00', $html); + } } diff --git a/Tests/Functional/Frontend/DatesTestFixtures/DatePageTitle.php b/Tests/Functional/Frontend/DatesTestFixtures/DatePageTitle.php new file mode 100644 index 0000000..ce6fbfd --- /dev/null +++ b/Tests/Functional/Frontend/DatesTestFixtures/DatePageTitle.php @@ -0,0 +1,32 @@ + [ + 0 => [ + 'uid' => '1', + 'pid' => '1', + 'CType' => 'list', + 'list_type' => 'events_dateshow', + 'header' => 'Singleview', + ], + ], + 'tx_events_domain_model_event' => [ + 0 => [ + 'uid' => '1', + 'pid' => '2', + 'title' => 'Title of Event', + 'hidden' => '0', + ], + ], + 'tx_events_domain_model_date' => [ + 0 => [ + 'uid' => '1', + 'pid' => '2', + 'event' => '1', + 'start' => '1676419200', + 'end' => '1676484000', + ], + ], +]; diff --git a/Tests/Functional/Frontend/EventsTest.php b/Tests/Functional/Frontend/EventsTest.php index b30a820..f01df3f 100644 --- a/Tests/Functional/Frontend/EventsTest.php +++ b/Tests/Functional/Frontend/EventsTest.php @@ -59,4 +59,22 @@ public function addsMetaTags(): void self::assertStringContainsString('', $html); self::assertStringContainsString('', $html); } + + /** + * @test + */ + public function altersPageTitle(): void + { + $this->importPHPDataSet(__DIR__ . '/EventsTestFixtures/EventPageTitle.php'); + + $request = new InternalRequest(); + $request = $request->withPageId(1); + $request = $request->withQueryParameter('tx_events_eventshow[event]', '1'); + $response = $this->executeFrontendRequest($request); + + self::assertSame(200, $response->getStatusCode()); + $html = (string)$response->getBody(); + + self::assertStringContainsString('Title of Event', $html); + } } diff --git a/Tests/Functional/Frontend/EventsTestFixtures/EventPageTitle.php b/Tests/Functional/Frontend/EventsTestFixtures/EventPageTitle.php new file mode 100644 index 0000000..0d3ff66 --- /dev/null +++ b/Tests/Functional/Frontend/EventsTestFixtures/EventPageTitle.php @@ -0,0 +1,23 @@ + [ + 0 => [ + 'uid' => '1', + 'pid' => '1', + 'CType' => 'list', + 'list_type' => 'events_eventshow', + 'header' => 'Singleview', + ], + ], + 'tx_events_domain_model_event' => [ + 0 => [ + 'uid' => '1', + 'pid' => '2', + 'title' => 'Title of Event', + 'hidden' => '0', + ], + ], +]; diff --git a/Tests/Functional/Frontend/Fixtures/TypoScript/Rendering.typoscript b/Tests/Functional/Frontend/Fixtures/TypoScript/Rendering.typoscript index 716ed1d..382c81b 100644 --- a/Tests/Functional/Frontend/Fixtures/TypoScript/Rendering.typoscript +++ b/Tests/Functional/Frontend/Fixtures/TypoScript/Rendering.typoscript @@ -38,3 +38,16 @@ plugin.tx_events { start = 1660158000 } } + +config { + pageTitleProviders { + date { + provider = Wrm\Events\Frontend\PageTitleProvider\DateTitleProvider + before = record + } + event { + provider = Wrm\Events\Frontend\PageTitleProvider\EventTitleProvider + before = record + } + } +}