Add Social Media Tags by default. (#50)

https://ogp.me/ is used by some platforms, especially social media, to
generate previews of shared links.
The extension now delivers default open-graph tags for better user
experience.
Twitter uses its own way which is also supported.
This commit is contained in:
Daniel Siepmann 2023-11-30 11:55:32 +01:00 committed by GitHub
parent 1d3c28f228
commit 7db61a189a
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
14 changed files with 615 additions and 51 deletions

View file

@ -23,6 +23,7 @@ declare(strict_types=1);
namespace WerkraumMedia\Events\Frontend\MetaInformation; namespace WerkraumMedia\Events\Frontend\MetaInformation;
use TYPO3\CMS\Core\MetaTag\GenericMetaTagManager;
use TYPO3\CMS\Core\MetaTag\MetaTagManagerRegistry; use TYPO3\CMS\Core\MetaTag\MetaTagManagerRegistry;
use WerkraumMedia\Events\Domain\Model\Date; use WerkraumMedia\Events\Domain\Model\Date;
use WerkraumMedia\Events\Frontend\PageTitleProvider\DateTitleProviderInterface; use WerkraumMedia\Events\Frontend\PageTitleProvider\DateTitleProviderInterface;
@ -36,41 +37,53 @@ final class DateMetaInformationService implements DateMetaInformationInterface
{ {
public function __construct( public function __construct(
private readonly MetaTagManagerRegistry $metaTagManagerRegistry, private readonly MetaTagManagerRegistry $metaTagManagerRegistry,
private readonly EventMetaInformationService $eventService,
private readonly DateTitleProviderInterface $titleProvider private readonly DateTitleProviderInterface $titleProvider
) { ) {
} }
public function setDate(Date $date): void public function setDate(Date $date): void
{ {
$this->setDescription($date); $event = $date->getEvent();
$this->setKeywords($date); if ($event === null) {
return;
}
// A date mostly sets info based on event, re use existing features.
$this->eventService->setEvent($event);
// Now set date specifics.
$this->titleProvider->setDate($date); $this->titleProvider->setDate($date);
$this->updateTitles();
} }
private function setDescription(Date $date): void private function updateTitles(): void
{ {
$description = $date->getEvent()?->getTeaser() ?? ''; $title = $this->titleProvider->getTitle();
if ($description === '') { if ($title === '') {
return; return;
} }
$this->metaTagManagerRegistry $this->updateOpenGraphTitle($title);
->getManagerForProperty('description') $this->updateTwitterTitle($title);
->addProperty('description', $description)
;
} }
private function setKeywords(Date $date): void private function updateOpenGraphTitle(string $title): void
{ {
$keywords = $date->getEvent()?->getKeywords() ?? ''; $manager = $this->metaTagManagerRegistry->getManagerForProperty('og:title');
if ($keywords === '') { if ($manager instanceof GenericMetaTagManager) {
return; return;
} }
$this->metaTagManagerRegistry $manager->removeProperty('og:title');
->getManagerForProperty('keywords') $manager->addProperty('og:title', $title);
->addProperty('keywords', $keywords) }
;
private function updateTwitterTitle(string $title): void
{
$manager = $this->metaTagManagerRegistry->getManagerForProperty('twitter:title');
$manager->removeProperty('twitter:title');
$manager->addProperty('twitter:title', $title);
} }
} }

View file

@ -23,7 +23,9 @@ declare(strict_types=1);
namespace WerkraumMedia\Events\Frontend\MetaInformation; namespace WerkraumMedia\Events\Frontend\MetaInformation;
use TYPO3\CMS\Core\MetaTag\GenericMetaTagManager;
use TYPO3\CMS\Core\MetaTag\MetaTagManagerRegistry; use TYPO3\CMS\Core\MetaTag\MetaTagManagerRegistry;
use TYPO3\CMS\Core\Utility\GeneralUtility;
use WerkraumMedia\Events\Domain\Model\Event; use WerkraumMedia\Events\Domain\Model\Event;
use WerkraumMedia\Events\Frontend\PageTitleProvider\EventTitleProviderInterface; use WerkraumMedia\Events\Frontend\PageTitleProvider\EventTitleProviderInterface;
@ -42,10 +44,12 @@ final class EventMetaInformationService implements EventMetaInformationInterface
public function setEvent(Event $event): void public function setEvent(Event $event): void
{ {
$this->titleProvider->setEvent($event);
$this->setDescription($event); $this->setDescription($event);
$this->setKeywords($event); $this->setKeywords($event);
$this->setOpenGraphTags($event);
$this->titleProvider->setEvent($event); $this->setSocialMediaTags($event);
} }
private function setDescription(Event $event): void private function setDescription(Event $event): void
@ -73,4 +77,51 @@ final class EventMetaInformationService implements EventMetaInformationInterface
->addProperty('keywords', $keywords) ->addProperty('keywords', $keywords)
; ;
} }
private function setOpenGraphTags(Event $event): void
{
$tags = array_filter([
'title' => $this->titleProvider->getTitle(),
'type' => 'website',
'image' => $this->getImageUrl($event),
]);
foreach ($tags as $property => $value) {
$property = 'og:' . $property;
$manager = $this->metaTagManagerRegistry->getManagerForProperty($property);
if ($manager instanceof GenericMetaTagManager) {
continue;
}
$manager->addProperty($property, $value);
}
}
private function setSocialMediaTags(Event $event): void
{
$title = $this->titleProvider->getTitle();
$tags = array_filter([
'twitter:card' => 'summary',
'twitter:title' => $title,
'twitter:description' => $event->getTeaser(),
'twitter:image' => $this->getImageUrl($event),
]);
foreach ($tags as $property => $value) {
$this->metaTagManagerRegistry
->getManagerForProperty($property)
->addProperty($property, $value)
;
}
}
private function getImageUrl(Event $event): string
{
$imageUrl = $event->getImages()[0]?->getOriginalResource()->getPublicUrl() ?? '';
if ($imageUrl) {
$imageUrl = GeneralUtility::locationHeaderUrl($imageUrl);
}
return $imageUrl;
}
} }

View file

@ -36,6 +36,11 @@ Features
* Add page title provider. * Add page title provider.
That way it is possible to alter the TYPO3 page title when showing a date or event. That way it is possible to alter the TYPO3 page title when showing a date or event.
* Add Social Media Tags by default.
https://ogp.me/ is used by some platforms, especially social media, to generate previews of shared links.
The extension now delivers default open-graph tags for better user experience.
Twitter uses its own way which is also supported.
Fixes Fixes
----- -----

View file

@ -1,10 +1,14 @@
.. index:: single: meta tags .. index:: single: meta tags
.. index:: single: open graph
.. _metaTags: .. _metaTags:
.. _openGraph:
.. _twitter:
Meta Tags Meta Tags
========= =========
The extension comes with default implementations for meta tags. The extension comes with default implementations for meta tags.
This includes open graph and Twitter (X) tags.
The default implementation can be exchanged by leveraging TYPO3 Dependency Injection. The default implementation can be exchanged by leveraging TYPO3 Dependency Injection.
@ -13,3 +17,7 @@ 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/Seo/MetaTagApi.html
* https://docs.typo3.org/m/typo3/reference-coreapi/12.4/en-us/ApiOverview/DependencyInjection/Index.html * https://docs.typo3.org/m/typo3/reference-coreapi/12.4/en-us/ApiOverview/DependencyInjection/Index.html
* https://ogp.me/
* https://developer.twitter.com/en/docs/twitter-for-websites/cards/overview/summary

View file

@ -326,7 +326,7 @@ class CacheTest extends AbstractFunctionalTestCase
private function getRequestWithSleep(array $typoScript = []): InternalRequest private function getRequestWithSleep(array $typoScript = []): InternalRequest
{ {
$request = new InternalRequest(); $request = new InternalRequest('https://example.com/');
$request = $request->withPageId(1); $request = $request->withPageId(1);
$request = $request->withInstructions([ $request = $request->withInstructions([
$this->getTypoScriptInstruction() $this->getTypoScriptInstruction()

View file

@ -24,6 +24,7 @@ declare(strict_types=1);
namespace WerkraumMedia\Events\Tests\Functional\Frontend; namespace WerkraumMedia\Events\Tests\Functional\Frontend;
use PHPUnit\Framework\Attributes\Test; use PHPUnit\Framework\Attributes\Test;
use Psr\Http\Message\ResponseInterface;
use TYPO3\TestingFramework\Core\Functional\Framework\Frontend\InternalRequest; use TYPO3\TestingFramework\Core\Functional\Framework\Frontend\InternalRequest;
use WerkraumMedia\Events\Frontend\Dates; use WerkraumMedia\Events\Frontend\Dates;
use WerkraumMedia\Events\Tests\Functional\AbstractFunctionalTestCase; use WerkraumMedia\Events\Tests\Functional\AbstractFunctionalTestCase;
@ -32,6 +33,10 @@ class DatesTest extends AbstractFunctionalTestCase
{ {
protected function setUp(): void protected function setUp(): void
{ {
$this->coreExtensionsToLoad = [
'seo',
];
parent::setUp(); parent::setUp();
$this->importPHPDataSet(__DIR__ . '/Fixtures/Database/SiteStructure.php'); $this->importPHPDataSet(__DIR__ . '/Fixtures/Database/SiteStructure.php');
@ -50,7 +55,7 @@ class DatesTest extends AbstractFunctionalTestCase
{ {
$this->importPHPDataSet(__DIR__ . '/DatesTestFixtures/ReturnsOnlyDatesWithAvailableEventByDemand.php'); $this->importPHPDataSet(__DIR__ . '/DatesTestFixtures/ReturnsOnlyDatesWithAvailableEventByDemand.php');
$request = new InternalRequest(); $request = new InternalRequest('https://example.com/');
$request = $request->withPageId(1); $request = $request->withPageId(1);
$response = $this->executeFrontendSubRequest($request); $response = $this->executeFrontendSubRequest($request);
@ -66,7 +71,7 @@ class DatesTest extends AbstractFunctionalTestCase
{ {
$this->importPHPDataSet(__DIR__ . '/DatesTestFixtures/ReturnsDateWithinTimeSpan.php'); $this->importPHPDataSet(__DIR__ . '/DatesTestFixtures/ReturnsDateWithinTimeSpan.php');
$request = new InternalRequest(); $request = new InternalRequest('https://example.com/');
$request = $request->withPageId(1); $request = $request->withPageId(1);
$request = $request->withQueryParameters([ $request = $request->withQueryParameters([
'events_search[search][start]' => '2023-02-16', 'events_search[search][start]' => '2023-02-16',
@ -92,7 +97,7 @@ class DatesTest extends AbstractFunctionalTestCase
{ {
$this->importPHPDataSet(__DIR__ . '/DatesTestFixtures/ReturnsDateWithinTimeSpan.php'); $this->importPHPDataSet(__DIR__ . '/DatesTestFixtures/ReturnsDateWithinTimeSpan.php');
$request = new InternalRequest(); $request = new InternalRequest('https://example.com/');
$request = $request->withPageId(1); $request = $request->withPageId(1);
$request = $request->withQueryParameters([ $request = $request->withQueryParameters([
'events_search[search][end]' => '2023-02-17', 'events_search[search][end]' => '2023-02-17',
@ -123,7 +128,7 @@ class DatesTest extends AbstractFunctionalTestCase
{ {
$this->importPHPDataSet(__DIR__ . '/DatesTestFixtures/ReturnsDateWithinTimeSpan.php'); $this->importPHPDataSet(__DIR__ . '/DatesTestFixtures/ReturnsDateWithinTimeSpan.php');
$request = new InternalRequest(); $request = new InternalRequest('https://example.com/');
$request = $request->withPageId(1); $request = $request->withPageId(1);
$request = $request->withQueryParameters([ $request = $request->withQueryParameters([
'events_search[search][start]' => '2023-02-16', 'events_search[search][start]' => '2023-02-16',
@ -150,12 +155,7 @@ class DatesTest extends AbstractFunctionalTestCase
{ {
$this->importPHPDataSet(__DIR__ . '/DatesTestFixtures/Returns404IfEventIsHidden.php'); $this->importPHPDataSet(__DIR__ . '/DatesTestFixtures/Returns404IfEventIsHidden.php');
$request = new InternalRequest(); $response = $this->issueDetailRequest();
$request = $request->withPageId(1);
$request = $request->withQueryParameters([
'tx_events_dateshow[date]' => '1',
]);
$response = $this->executeFrontendSubRequest($request);
self::assertSame(404, $response->getStatusCode()); self::assertSame(404, $response->getStatusCode());
} }
@ -165,7 +165,7 @@ class DatesTest extends AbstractFunctionalTestCase
{ {
$this->importPHPDataSet(__DIR__ . '/DatesTestFixtures/ReturnsUpcomingDates.php'); $this->importPHPDataSet(__DIR__ . '/DatesTestFixtures/ReturnsUpcomingDates.php');
$request = new InternalRequest(); $request = new InternalRequest('https://example.com/');
$request = $request->withPageId(1); $request = $request->withPageId(1);
$request = $request->withInstructions([ $request = $request->withInstructions([
$this->getTypoScriptInstruction() $this->getTypoScriptInstruction()
@ -193,10 +193,7 @@ class DatesTest extends AbstractFunctionalTestCase
{ {
$this->importPHPDataSet(__DIR__ . '/DatesTestFixtures/DateMetaTags.php'); $this->importPHPDataSet(__DIR__ . '/DatesTestFixtures/DateMetaTags.php');
$request = new InternalRequest(); $response = $this->issueDetailRequest();
$request = $request->withPageId(1);
$request = $request->withQueryParameter('tx_events_dateshow[date]', '1');
$response = $this->executeFrontendSubRequest($request);
self::assertSame(200, $response->getStatusCode()); self::assertSame(200, $response->getStatusCode());
$html = (string)$response->getBody(); $html = (string)$response->getBody();
@ -205,19 +202,54 @@ class DatesTest extends AbstractFunctionalTestCase
self::assertStringContainsString('<meta name="keywords" content="Gewölbe, Goethe, Horst Damm, Kästner, Theater" />', $html); self::assertStringContainsString('<meta name="keywords" content="Gewölbe, Goethe, Horst Damm, Kästner, Theater" />', $html);
} }
#[Test]
public function addsOpenGraphTags(): void
{
$this->importPHPDataSet(__DIR__ . '/DatesTestFixtures/DateOpenGraphTags.php');
$response = $this->issueDetailRequest();
self::assertSame(200, $response->getStatusCode());
$html = (string)$response->getBody();
self::assertStringContainsString('<meta property="og:title" content="Title of Event 15.02.2023 00:00" />', $html);
self::assertStringContainsString('<meta property="og:type" content="website" />', $html);
self::assertStringContainsString('<meta property="og:image" content="http://example.com/fileadmin/user_uploads/example-for-event.gif" />', $html);
}
#[Test]
public function addsSocialMediaTags(): void
{
$this->importPHPDataSet(__DIR__ . '/DatesTestFixtures/DateSocialMediaTags.php');
$response = $this->issueDetailRequest();
self::assertSame(200, $response->getStatusCode());
$html = (string)$response->getBody();
self::assertStringContainsString('<meta name="twitter:card" content="summary" />', $html);
self::assertStringContainsString('<meta name="twitter:title" content="Title of Event 15.02.2023 00:00" />', $html);
self::assertStringContainsString('<meta name="twitter:description" content="Teaser of Event" />', $html);
self::assertStringContainsString('<meta name="twitter:image" content="http://example.com/fileadmin/user_uploads/example-for-event.gif" />', $html);
}
#[Test] #[Test]
public function altersPageTitle(): void public function altersPageTitle(): void
{ {
$this->importPHPDataSet(__DIR__ . '/DatesTestFixtures/DatePageTitle.php'); $this->importPHPDataSet(__DIR__ . '/DatesTestFixtures/DatePageTitle.php');
$request = new InternalRequest(); $response = $this->issueDetailRequest();
$request = $request->withPageId(1);
$request = $request->withQueryParameter('tx_events_dateshow[date]', '1');
$response = $this->executeFrontendSubRequest($request);
self::assertSame(200, $response->getStatusCode()); self::assertSame(200, $response->getStatusCode());
$html = (string)$response->getBody(); $html = (string)$response->getBody();
self::assertStringContainsString('<title>Title of Event 15.02.2023 00:00</title>', $html); self::assertStringContainsString('<title>Title of Event 15.02.2023 00:00</title>', $html);
} }
private function issueDetailRequest(): ResponseInterface
{
$request = new InternalRequest('https://example.com/');
$request = $request->withPageId(1);
$request = $request->withQueryParameter('tx_events_dateshow[date]', '1');
return $this->executeFrontendSubRequest($request);
}
} }

View file

@ -0,0 +1,109 @@
<?php
declare(strict_types=1);
return [
'tt_content' => [
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',
'images' => '1',
],
],
'tx_events_domain_model_date' => [
0 => [
'uid' => '1',
'pid' => '2',
'event' => '1',
'start' => '1676419200',
'end' => '1676484000',
],
],
'sys_file_storage' => [
[
'uid' => '1',
'pid' => '0',
'tstamp' => '1423209858',
'crdate' => '1370878372',
'deleted' => '0',
'name' => 'fileadmin/ (auto-created)',
'description' => 'This is the local fileadmin/ directory. This storage mount has been created automatically by TYPO3.',
'driver' => 'Local',
'configuration' => '<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<T3FlexForms>
<data>
<sheet index="sDEF">
<language index="lDEF">
<field index="basePath">
<value index="vDEF">fileadmin/</value>
</field>
<field index="pathType">
<value index="vDEF">relative</value>
</field>
<field index="caseSensitive">
<value index="vDEF">1</value>
</field>
</language>
</sheet>
</data>
</T3FlexForms>
',
'is_browsable' => '1',
'is_public' => '1',
'is_writable' => '1',
'is_online' => '1',
'processingfolder' => '_processed_',
'is_default' => '1',
'auto_extract_metadata' => '1',
],
],
'sys_file' => [
0 => [
'uid' => '1',
'pid' => '0',
'tstamp' => '1371467047',
'type' => '2',
'storage' => '1',
'identifier' => '/user_uploads/example-for-event.gif',
'extension' => 'gif',
'mime_type' => 'image/gif',
'name' => 'ext_icon.gif',
'sha1' => '359ae0fb420fe8afe1a8b8bc5e46d75090a826b9',
'size' => '637',
'creation_date' => '1370877201',
'modification_date' => '1369407629',
'last_indexed' => '0',
'missing' => '0',
'metadata' => '0',
'identifier_hash' => '475768e491580fb8b74ed36c2b1aaf619ca5e11d',
'folder_hash' => 'b4ab666a114d9905a50606d1837b74d952dfd90f',
],
],
'sys_file_reference' => [
[
'uid' => '1',
'pid' => '2',
'tstamp' => '1373537480',
'crdate' => '1371484347',
'deleted' => '0',
'hidden' => '0',
'sys_language_uid' => '0',
'uid_local' => '1',
'uid_foreign' => '1',
'tablenames' => 'tx_events_domain_model_event',
'fieldname' => 'images',
'sorting_foreign' => '1',
],
],
];

View file

@ -0,0 +1,110 @@
<?php
declare(strict_types=1);
return [
'tt_content' => [
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',
'teaser' => 'Teaser of Event',
'images' => '1',
],
],
'tx_events_domain_model_date' => [
0 => [
'uid' => '1',
'pid' => '2',
'event' => '1',
'start' => '1676419200',
'end' => '1676484000',
],
],
'sys_file_storage' => [
[
'uid' => '1',
'pid' => '0',
'tstamp' => '1423209858',
'crdate' => '1370878372',
'deleted' => '0',
'name' => 'fileadmin/ (auto-created)',
'description' => 'This is the local fileadmin/ directory. This storage mount has been created automatically by TYPO3.',
'driver' => 'Local',
'configuration' => '<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<T3FlexForms>
<data>
<sheet index="sDEF">
<language index="lDEF">
<field index="basePath">
<value index="vDEF">fileadmin/</value>
</field>
<field index="pathType">
<value index="vDEF">relative</value>
</field>
<field index="caseSensitive">
<value index="vDEF">1</value>
</field>
</language>
</sheet>
</data>
</T3FlexForms>
',
'is_browsable' => '1',
'is_public' => '1',
'is_writable' => '1',
'is_online' => '1',
'processingfolder' => '_processed_',
'is_default' => '1',
'auto_extract_metadata' => '1',
],
],
'sys_file' => [
0 => [
'uid' => '1',
'pid' => '0',
'tstamp' => '1371467047',
'type' => '2',
'storage' => '1',
'identifier' => '/user_uploads/example-for-event.gif',
'extension' => 'gif',
'mime_type' => 'image/gif',
'name' => 'ext_icon.gif',
'sha1' => '359ae0fb420fe8afe1a8b8bc5e46d75090a826b9',
'size' => '637',
'creation_date' => '1370877201',
'modification_date' => '1369407629',
'last_indexed' => '0',
'missing' => '0',
'metadata' => '0',
'identifier_hash' => '475768e491580fb8b74ed36c2b1aaf619ca5e11d',
'folder_hash' => 'b4ab666a114d9905a50606d1837b74d952dfd90f',
],
],
'sys_file_reference' => [
[
'uid' => '1',
'pid' => '2',
'tstamp' => '1373537480',
'crdate' => '1371484347',
'deleted' => '0',
'hidden' => '0',
'sys_language_uid' => '0',
'uid_local' => '1',
'uid_foreign' => '1',
'tablenames' => 'tx_events_domain_model_event',
'fieldname' => 'images',
'sorting_foreign' => '1',
],
],
];

View file

@ -24,6 +24,7 @@ declare(strict_types=1);
namespace WerkraumMedia\Events\Tests\Functional\Frontend; namespace WerkraumMedia\Events\Tests\Functional\Frontend;
use PHPUnit\Framework\Attributes\Test; use PHPUnit\Framework\Attributes\Test;
use Psr\Http\Message\ResponseInterface;
use TYPO3\TestingFramework\Core\Functional\Framework\Frontend\InternalRequest; use TYPO3\TestingFramework\Core\Functional\Framework\Frontend\InternalRequest;
use WerkraumMedia\Events\Tests\Functional\AbstractFunctionalTestCase; use WerkraumMedia\Events\Tests\Functional\AbstractFunctionalTestCase;
@ -34,6 +35,9 @@ class EventsTest extends AbstractFunctionalTestCase
$this->testExtensionsToLoad = [ $this->testExtensionsToLoad = [
'typo3conf/ext/events/Tests/Functional/Frontend/Fixtures/Extensions/example', 'typo3conf/ext/events/Tests/Functional/Frontend/Fixtures/Extensions/example',
]; ];
$this->coreExtensionsToLoad = [
'seo',
];
parent::setUp(); parent::setUp();
@ -46,11 +50,7 @@ class EventsTest extends AbstractFunctionalTestCase
{ {
$this->importPHPDataSet(__DIR__ . '/EventsTestFixtures/EventMetaTags.php'); $this->importPHPDataSet(__DIR__ . '/EventsTestFixtures/EventMetaTags.php');
$request = new InternalRequest(); $response = $this->issueDetailRequest();
$request = $request->withPageId(1);
$request = $request->withQueryParameter('tx_events_eventshow[event]', '1');
$response = $this->executeFrontendSubRequest($request);
self::assertSame(200, $response->getStatusCode()); self::assertSame(200, $response->getStatusCode());
$html = (string)$response->getBody(); $html = (string)$response->getBody();
@ -58,19 +58,53 @@ class EventsTest extends AbstractFunctionalTestCase
self::assertStringContainsString('<meta name="keywords" content="Gewölbe, Goethe, Horst Damm, Kästner, Theater" />', $html); self::assertStringContainsString('<meta name="keywords" content="Gewölbe, Goethe, Horst Damm, Kästner, Theater" />', $html);
} }
#[Test]
public function addsOpenGraphTags(): void
{
$this->importPHPDataSet(__DIR__ . '/EventsTestFixtures/EventOpenGraphTags.php');
$response = $this->issueDetailRequest();
self::assertSame(200, $response->getStatusCode());
$html = (string)$response->getBody();
self::assertStringContainsString('<meta property="og:title" content="Title of Event" />', $html);
self::assertStringContainsString('<meta property="og:type" content="website" />', $html);
self::assertStringContainsString('<meta property="og:image" content="http://example.com/fileadmin/user_uploads/example-for-event.gif" />', $html);
}
#[Test]
public function addsSocialMediaTags(): void
{
$this->importPHPDataSet(__DIR__ . '/EventsTestFixtures/EventSocialMediaTags.php');
$response = $this->issueDetailRequest();
self::assertSame(200, $response->getStatusCode());
$html = (string)$response->getBody();
self::assertStringContainsString('<meta name="twitter:card" content="summary" />', $html);
self::assertStringContainsString('<meta name="twitter:title" content="Title of Event" />', $html);
self::assertStringContainsString('<meta name="twitter:description" content="Teaser of Event" />', $html);
self::assertStringContainsString('<meta name="twitter:image" content="http://example.com/fileadmin/user_uploads/example-for-event.gif" />', $html);
}
#[Test] #[Test]
public function altersPageTitle(): void public function altersPageTitle(): void
{ {
$this->importPHPDataSet(__DIR__ . '/EventsTestFixtures/EventPageTitle.php'); $this->importPHPDataSet(__DIR__ . '/EventsTestFixtures/EventPageTitle.php');
$request = new InternalRequest(); $response = $this->issueDetailRequest();
$request = $request->withPageId(1);
$request = $request->withQueryParameter('tx_events_eventshow[event]', '1');
$response = $this->executeFrontendSubRequest($request);
self::assertSame(200, $response->getStatusCode()); self::assertSame(200, $response->getStatusCode());
$html = (string)$response->getBody(); $html = (string)$response->getBody();
self::assertStringContainsString('<title>Title of Event</title>', $html); self::assertStringContainsString('<title>Title of Event</title>', $html);
} }
private function issueDetailRequest(): ResponseInterface
{
$request = new InternalRequest('https://example.com/');
$request = $request->withPageId(1);
$request = $request->withQueryParameter('tx_events_eventshow[event]', '1');
return $this->executeFrontendSubRequest($request);
}
} }

View file

@ -0,0 +1,100 @@
<?php
declare(strict_types=1);
return [
'tt_content' => [
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',
'images' => '1',
],
],
'sys_file_storage' => [
[
'uid' => '1',
'pid' => '0',
'tstamp' => '1423209858',
'crdate' => '1370878372',
'deleted' => '0',
'name' => 'fileadmin/ (auto-created)',
'description' => 'This is the local fileadmin/ directory. This storage mount has been created automatically by TYPO3.',
'driver' => 'Local',
'configuration' => '<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<T3FlexForms>
<data>
<sheet index="sDEF">
<language index="lDEF">
<field index="basePath">
<value index="vDEF">fileadmin/</value>
</field>
<field index="pathType">
<value index="vDEF">relative</value>
</field>
<field index="caseSensitive">
<value index="vDEF">1</value>
</field>
</language>
</sheet>
</data>
</T3FlexForms>
',
'is_browsable' => '1',
'is_public' => '1',
'is_writable' => '1',
'is_online' => '1',
'processingfolder' => '_processed_',
'is_default' => '1',
'auto_extract_metadata' => '1',
],
],
'sys_file' => [
0 => [
'uid' => '1',
'pid' => '0',
'tstamp' => '1371467047',
'type' => '2',
'storage' => '1',
'identifier' => '/user_uploads/example-for-event.gif',
'extension' => 'gif',
'mime_type' => 'image/gif',
'name' => 'ext_icon.gif',
'sha1' => '359ae0fb420fe8afe1a8b8bc5e46d75090a826b9',
'size' => '637',
'creation_date' => '1370877201',
'modification_date' => '1369407629',
'last_indexed' => '0',
'missing' => '0',
'metadata' => '0',
'identifier_hash' => '475768e491580fb8b74ed36c2b1aaf619ca5e11d',
'folder_hash' => 'b4ab666a114d9905a50606d1837b74d952dfd90f',
],
],
'sys_file_reference' => [
[
'uid' => '1',
'pid' => '2',
'tstamp' => '1373537480',
'crdate' => '1371484347',
'deleted' => '0',
'hidden' => '0',
'sys_language_uid' => '0',
'uid_local' => '1',
'uid_foreign' => '1',
'tablenames' => 'tx_events_domain_model_event',
'fieldname' => 'images',
'sorting_foreign' => '1',
],
],
];

View file

@ -0,0 +1,101 @@
<?php
declare(strict_types=1);
return [
'tt_content' => [
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',
'teaser' => 'Teaser of Event',
'images' => '1',
],
],
'sys_file_storage' => [
[
'uid' => '1',
'pid' => '0',
'tstamp' => '1423209858',
'crdate' => '1370878372',
'deleted' => '0',
'name' => 'fileadmin/ (auto-created)',
'description' => 'This is the local fileadmin/ directory. This storage mount has been created automatically by TYPO3.',
'driver' => 'Local',
'configuration' => '<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<T3FlexForms>
<data>
<sheet index="sDEF">
<language index="lDEF">
<field index="basePath">
<value index="vDEF">fileadmin/</value>
</field>
<field index="pathType">
<value index="vDEF">relative</value>
</field>
<field index="caseSensitive">
<value index="vDEF">1</value>
</field>
</language>
</sheet>
</data>
</T3FlexForms>
',
'is_browsable' => '1',
'is_public' => '1',
'is_writable' => '1',
'is_online' => '1',
'processingfolder' => '_processed_',
'is_default' => '1',
'auto_extract_metadata' => '1',
],
],
'sys_file' => [
0 => [
'uid' => '1',
'pid' => '0',
'tstamp' => '1371467047',
'type' => '2',
'storage' => '1',
'identifier' => '/user_uploads/example-for-event.gif',
'extension' => 'gif',
'mime_type' => 'image/gif',
'name' => 'ext_icon.gif',
'sha1' => '359ae0fb420fe8afe1a8b8bc5e46d75090a826b9',
'size' => '637',
'creation_date' => '1370877201',
'modification_date' => '1369407629',
'last_indexed' => '0',
'missing' => '0',
'metadata' => '0',
'identifier_hash' => '475768e491580fb8b74ed36c2b1aaf619ca5e11d',
'folder_hash' => 'b4ab666a114d9905a50606d1837b74d952dfd90f',
],
],
'sys_file_reference' => [
[
'uid' => '1',
'pid' => '2',
'tstamp' => '1373537480',
'crdate' => '1371484347',
'deleted' => '0',
'hidden' => '0',
'sys_language_uid' => '0',
'uid_local' => '1',
'uid_foreign' => '1',
'tablenames' => 'tx_events_domain_model_event',
'fieldname' => 'images',
'sorting_foreign' => '1',
],
],
];

View file

@ -23,7 +23,7 @@ class FilterTest extends AbstractFunctionalTestCase
{ {
$this->importPHPDataSet(__DIR__ . '/Fixtures/Database/FilterByASingleLocationViaFlexform.php'); $this->importPHPDataSet(__DIR__ . '/Fixtures/Database/FilterByASingleLocationViaFlexform.php');
$request = new InternalRequest(); $request = new InternalRequest('https://example.com/');
$request = $request->withPageId(1); $request = $request->withPageId(1);
$response = $this->executeFrontendSubRequest($request); $response = $this->executeFrontendSubRequest($request);
@ -39,7 +39,7 @@ class FilterTest extends AbstractFunctionalTestCase
{ {
$this->importPHPDataSet(__DIR__ . '/Fixtures/Database/FilterByTwoLocationsViaFlexform.php'); $this->importPHPDataSet(__DIR__ . '/Fixtures/Database/FilterByTwoLocationsViaFlexform.php');
$request = new InternalRequest(); $request = new InternalRequest('https://example.com/');
$request = $request->withPageId(1); $request = $request->withPageId(1);
$response = $this->executeFrontendSubRequest($request); $response = $this->executeFrontendSubRequest($request);

View file

@ -1,4 +1,4 @@
base: '/' base: 'https://example.com/'
languages: languages:
- -
title: English title: English

View file

@ -69,6 +69,7 @@
"saschaegerer/phpstan-typo3": "1.9.0", "saschaegerer/phpstan-typo3": "1.9.0",
"typo3/cms-backend": "^12.4", "typo3/cms-backend": "^12.4",
"typo3/cms-fluid-styled-content": "^12.4", "typo3/cms-fluid-styled-content": "^12.4",
"typo3/cms-seo": "^12.4",
"typo3/testing-framework": "^8.0" "typo3/testing-framework": "^8.0"
}, },
"config": { "config": {