From f0f878764ac444ab62751b4f3512bbd3eca27f8a Mon Sep 17 00:00:00 2001
From: Richard Haeser <richard@maxserv.com>
Date: Thu, 27 Jun 2019 22:42:34 +0200
Subject: [PATCH] [FEATURE] Set Twitter Card Type in page properties
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

This option will make it possible to select a type of Twitter Card
that should be used when your page is shared on Twitter.

Resolves: #88648
Releases: master
Change-Id: I9b487cf51ae6380fe771e1bcbbfd196d8b952f0f
Reviewed-on: https://review.typo3.org/c/Packages/TYPO3.CMS/+/61163
Tested-by: TYPO3com <noreply@typo3.com>
Tested-by: Daniel Goerz <daniel.goerz@posteo.de>
Tested-by: Riny van Tiggelen <info@online-gamer.nl>
Tested-by: Richard Haeser <richard@maxserv.com>
Reviewed-by: Daniel Goerz <daniel.goerz@posteo.de>
Reviewed-by: Björn Jacob <bjoern.jacob@tritum.de>
Reviewed-by: Riny van Tiggelen <info@online-gamer.nl>
Reviewed-by: Richard Haeser <richard@maxserv.com>
---
 ...-DefineTwitterCardTypeInPageProperties.rst | 34 +++++++
 .../seo/Classes/MetaTag/MetaTagGenerator.php  |  6 +-
 .../seo/Configuration/TCA/Overrides/pages.php | 15 +++-
 .../Private/Language/locallang_tca.xlf        |  9 ++
 .../Scenarios/pages_with_seo_meta.xml         | 24 +++++
 .../Functional/Fixtures/page1.typoscript      |  5 ++
 .../Functional/Fixtures/page2.typoscript      |  6 ++
 .../Functional/Fixtures/page3.typoscript      |  7 ++
 .../Tests/Functional/MetaTag/MetaTagTest.php  | 88 +++++++++++++++++++
 typo3/sysext/seo/ext_tables.sql               |  1 +
 10 files changed, 189 insertions(+), 6 deletions(-)
 create mode 100644 typo3/sysext/core/Documentation/Changelog/master/Feature-88648-DefineTwitterCardTypeInPageProperties.rst
 create mode 100644 typo3/sysext/seo/Tests/Functional/Fixtures/Scenarios/pages_with_seo_meta.xml
 create mode 100644 typo3/sysext/seo/Tests/Functional/Fixtures/page1.typoscript
 create mode 100644 typo3/sysext/seo/Tests/Functional/Fixtures/page2.typoscript
 create mode 100644 typo3/sysext/seo/Tests/Functional/Fixtures/page3.typoscript
 create mode 100644 typo3/sysext/seo/Tests/Functional/MetaTag/MetaTagTest.php

diff --git a/typo3/sysext/core/Documentation/Changelog/master/Feature-88648-DefineTwitterCardTypeInPageProperties.rst b/typo3/sysext/core/Documentation/Changelog/master/Feature-88648-DefineTwitterCardTypeInPageProperties.rst
new file mode 100644
index 000000000000..83535e946aef
--- /dev/null
+++ b/typo3/sysext/core/Documentation/Changelog/master/Feature-88648-DefineTwitterCardTypeInPageProperties.rst
@@ -0,0 +1,34 @@
+.. include:: ../../Includes.txt
+
+==========================================================
+Feature: #88648 - Set Twitter Card Type in page properties
+==========================================================
+
+See :issue:`88648`
+
+Description
+===========
+
+It is now possible to select the type of Twitter Card to be shown when a page is shared
+on Twitter. This option will render the `twitter:card` meta tag in frontend.
+
+Impact
+======
+
+If you manually changed the value of the `twitter:card` by for example TypoScript and you
+want to override the value of the page properties, you have to use the replace option to
+override this value from the page properties.
+
+Example:
+
+.. code-block:: typoscript
+
+  page {
+    meta {
+      twitter:card = summary_large_image
+      twitter:card.replace = 1
+    }
+  }
+
+
+.. index:: ext:seo
diff --git a/typo3/sysext/seo/Classes/MetaTag/MetaTagGenerator.php b/typo3/sysext/seo/Classes/MetaTag/MetaTagGenerator.php
index df664188e74d..63e23a1388f3 100644
--- a/typo3/sysext/seo/Classes/MetaTag/MetaTagGenerator.php
+++ b/typo3/sysext/seo/Classes/MetaTag/MetaTagGenerator.php
@@ -79,12 +79,8 @@ class MetaTagGenerator
             }
         }
 
-        /*
-         * Set type of twitter card to summary. This value can be overridden by TypoScript or the MetaTag API by
-         * using the replace option. In v10 this will be a page property
-        */
         $manager = $metaTagManagerRegistry->getManagerForProperty('twitter:card');
-        $manager->addProperty('twitter:card', 'summary');
+        $manager->addProperty('twitter:card', $params['page']['twitter_card'] ?: 'summary');
 
         if (!empty($params['page']['twitter_title'])) {
             $manager = $metaTagManagerRegistry->getManagerForProperty('twitter:title');
diff --git a/typo3/sysext/seo/Configuration/TCA/Overrides/pages.php b/typo3/sysext/seo/Configuration/TCA/Overrides/pages.php
index 1674d600e5c9..613cb216b9cf 100644
--- a/typo3/sysext/seo/Configuration/TCA/Overrides/pages.php
+++ b/typo3/sysext/seo/Configuration/TCA/Overrides/pages.php
@@ -56,7 +56,7 @@ $tca = [
         ],
         'twittercards' => [
             'label' => 'LLL:EXT:seo/Resources/Private/Language/locallang_tca.xlf:pages.palettes.twittercards',
-            'showitem' => 'twitter_title, --linebreak--, twitter_description, --linebreak--, twitter_image',
+            'showitem' => 'twitter_title, --linebreak--, twitter_description, --linebreak--, twitter_image, --linebreak--, twitter_card',
         ],
     ],
     'columns' => [
@@ -269,6 +269,19 @@ $tca = [
                 $GLOBALS['TYPO3_CONF_VARS']['GFX']['imagefile_ext']
             )
         ],
+        'twitter_card' => [
+            'exclude' => true,
+            'label' => 'LLL:EXT:seo/Resources/Private/Language/locallang_tca.xlf:pages.twitter_card',
+            'config' => [
+                'type' => 'select',
+                'renderType' => 'selectSingle',
+                'default' => 'summary',
+                'items' => [
+                    ['LLL:EXT:seo/Resources/Private/Language/locallang_tca.xlf:pages.twitter_card.summary', 'summary'],
+                    ['LLL:EXT:seo/Resources/Private/Language/locallang_tca.xlf:pages.twitter_card.summary_large_image', 'summary_large_image'],
+                ]
+            ]
+        ],
     ],
 ];
 
diff --git a/typo3/sysext/seo/Resources/Private/Language/locallang_tca.xlf b/typo3/sysext/seo/Resources/Private/Language/locallang_tca.xlf
index b3c04d5ab0cf..5aba8489154b 100644
--- a/typo3/sysext/seo/Resources/Private/Language/locallang_tca.xlf
+++ b/typo3/sysext/seo/Resources/Private/Language/locallang_tca.xlf
@@ -52,6 +52,15 @@
 			<trans-unit id="pages.twitter_image">
 				<source>Image</source>
 			</trans-unit>
+			<trans-unit id="pages.twitter_card">
+				<source>Type of card to show</source>
+			</trans-unit>
+			<trans-unit id="pages.twitter_card.summary">
+				<source>Summary Card</source>
+			</trans-unit>
+			<trans-unit id="pages.twitter_card.summary_large_image">
+				<source>Summary Card with a large image</source>
+			</trans-unit>
 			<trans-unit id="pages.palettes.canonical">
 				<source>Canonical</source>
 			</trans-unit>
diff --git a/typo3/sysext/seo/Tests/Functional/Fixtures/Scenarios/pages_with_seo_meta.xml b/typo3/sysext/seo/Tests/Functional/Fixtures/Scenarios/pages_with_seo_meta.xml
new file mode 100644
index 000000000000..0fd314429f2a
--- /dev/null
+++ b/typo3/sysext/seo/Tests/Functional/Fixtures/Scenarios/pages_with_seo_meta.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?>
+<dataset>
+    <pages>
+        <uid>1</uid>
+        <pid>0</pid>
+        <title>Page with twitter_card</title>
+        <twitter_card>summary</twitter_card>
+        <deleted>0</deleted>
+    </pages>
+    <pages>
+        <uid>2</uid>
+        <pid>1</pid>
+        <title>Page with twitter_card and typoscript</title>
+        <twitter_card>summary</twitter_card>
+        <deleted>0</deleted>
+    </pages>
+    <pages>
+        <uid>3</uid>
+        <pid>1</pid>
+        <title>Page with twitter_card and typoscript with replace</title>
+        <twitter_card>summary</twitter_card>
+        <deleted>0</deleted>
+    </pages>
+</dataset>
diff --git a/typo3/sysext/seo/Tests/Functional/Fixtures/page1.typoscript b/typo3/sysext/seo/Tests/Functional/Fixtures/page1.typoscript
new file mode 100644
index 000000000000..e9ee8fdd20c5
--- /dev/null
+++ b/typo3/sysext/seo/Tests/Functional/Fixtures/page1.typoscript
@@ -0,0 +1,5 @@
+page = PAGE
+page {
+  meta {
+  }
+}
diff --git a/typo3/sysext/seo/Tests/Functional/Fixtures/page2.typoscript b/typo3/sysext/seo/Tests/Functional/Fixtures/page2.typoscript
new file mode 100644
index 000000000000..c45b50c6efad
--- /dev/null
+++ b/typo3/sysext/seo/Tests/Functional/Fixtures/page2.typoscript
@@ -0,0 +1,6 @@
+page = PAGE
+page {
+  meta {
+    twitter:card = summary_large_image
+  }
+}
diff --git a/typo3/sysext/seo/Tests/Functional/Fixtures/page3.typoscript b/typo3/sysext/seo/Tests/Functional/Fixtures/page3.typoscript
new file mode 100644
index 000000000000..4c423301c731
--- /dev/null
+++ b/typo3/sysext/seo/Tests/Functional/Fixtures/page3.typoscript
@@ -0,0 +1,7 @@
+page = PAGE
+page {
+  meta {
+    twitter:card = summary_large_image
+    twitter:card.replace = 1
+  }
+}
diff --git a/typo3/sysext/seo/Tests/Functional/MetaTag/MetaTagTest.php b/typo3/sysext/seo/Tests/Functional/MetaTag/MetaTagTest.php
new file mode 100644
index 000000000000..4503b640a707
--- /dev/null
+++ b/typo3/sysext/seo/Tests/Functional/MetaTag/MetaTagTest.php
@@ -0,0 +1,88 @@
+<?php
+declare(strict_types = 1);
+namespace TYPO3\CMS\Seo\Tests\Functional\MetaTag;
+
+/*
+ * This file is part of the TYPO3 CMS project.
+ *
+ * It is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License, either version 2
+ * of the License, or any later version.
+ *
+ * For the full copyright and license information, please read the
+ * LICENSE.txt file that was distributed with this source code.
+ *
+ * The TYPO3 project - inspiring people to share!
+ */
+
+use TYPO3\CMS\Frontend\Tests\Functional\SiteHandling\AbstractTestCase;
+use TYPO3\TestingFramework\Core\Functional\Framework\Frontend\InternalRequest;
+
+/**
+ * Functional test for the DataHandler
+ */
+class MetaTagTest extends AbstractTestCase
+{
+    protected function setUp(): void
+    {
+        $this->coreExtensionsToLoad[] = 'seo';
+
+        parent::setUp();
+        $this->importDataSet(ORIGINAL_ROOT . 'typo3/sysext/seo/Tests/Functional/Fixtures/Scenarios/pages_with_seo_meta.xml');
+
+        $this->writeSiteConfiguration(
+            'website-local',
+            $this->buildSiteConfiguration(1, 'http://localhost/'),
+            [
+                $this->buildDefaultLanguageConfiguration('EN', '/')
+            ]
+        );
+    }
+
+    public function ensureMetaDataAreCorrectDataProvider(): array
+    {
+        return [
+            'page with twitter_card in page properties' => [
+                1,
+                [
+                    ['type' => 'name' , 'tag' => 'twitter:card', 'content' => 'summary'],
+                ]
+            ],
+            'page with twitter_card in page properties and in typoscript' => [
+                2,
+                [
+                    ['type' => 'name' , 'tag' => 'twitter:card', 'content' => 'summary'],
+                ]
+            ],
+            'page with twitter_card in page properties and in typoscript with replace' => [
+                3,
+                [
+                    ['type' => 'name' , 'tag' => 'twitter:card', 'content' => 'summary_large_image'],
+                ]
+            ],
+        ];
+    }
+
+    /**
+     * @test
+     * @dataProvider ensureMetaDataAreCorrectDataProvider
+     * @param int $pageId
+     * @param array $expectedMetaTags
+     */
+    public function ensureMetaDataAreCorrect(int $pageId, array $expectedMetaTags): void
+    {
+        $this->setUpFrontendRootPage(1, ['typo3/sysext/seo/Tests/Functional/Fixtures/page' . $pageId . '.typoscript']);
+
+        // First hit to create a cached version
+        $uncachedResponse = $this->executeFrontendRequest(
+            (new InternalRequest('http://localhost/'))->withQueryParameters([
+                'id' => $pageId,
+            ])
+        );
+        $body = (string)$uncachedResponse->getBody();
+
+        foreach ($expectedMetaTags as $expectedMetaTag) {
+            $this->assertStringContainsString('<meta ' . $expectedMetaTag['type'] . '="' . $expectedMetaTag['tag'] . '" content="' . $expectedMetaTag['content'] . '" />', $body);
+        }
+    }
+}
diff --git a/typo3/sysext/seo/ext_tables.sql b/typo3/sysext/seo/ext_tables.sql
index 557454515fc5..c4c7b4751ec5 100644
--- a/typo3/sysext/seo/ext_tables.sql
+++ b/typo3/sysext/seo/ext_tables.sql
@@ -11,6 +11,7 @@ CREATE TABLE pages (
 	twitter_title varchar(255) DEFAULT '' NOT NULL,
 	twitter_description text,
 	twitter_image int(11) unsigned DEFAULT '0' NOT NULL,
+	twitter_card varchar(255) DEFAULT '' NOT NULL,
 	canonical_link varchar(2048) DEFAULT '' NOT NULL,
 	sitemap_priority decimal(1,1) DEFAULT '0.5' NOT NULL,
 	sitemap_changefreq varchar(10) DEFAULT '' NOT NULL,
-- 
GitLab