[BUGFIX] Support dots in page.meta 06/31406/2
authorMarkus Klein <klein.t3@mfc-linz.at>
Sat, 28 Jun 2014 14:56:36 +0000 (16:56 +0200)
committerAnja Leichsenring <aleichsenring@ab-softlab.de>
Sun, 6 Jul 2014 18:09:57 +0000 (20:09 +0200)
The parsing of the meta tag TypoScript configuration does a too greedy
check on dots and hence breaks support for examples like DC.author.

Fix this by completely refactoring the meta tag generation and add unit
tests.

Resolves: #59890
Releases: 6.3, 6.2
Change-Id: Id534efff30903d96aee1677989d1bd6d3dd1644b
Reviewed-on: https://review.typo3.org/31406
Reviewed-by: Anja Leichsenring
Tested-by: Anja Leichsenring
typo3/sysext/frontend/Classes/Page/PageGenerator.php
typo3/sysext/frontend/Tests/Unit/Page/Fixtures/PageGeneratorFixture.php [new file with mode: 0644]
typo3/sysext/frontend/Tests/Unit/Page/PageGeneratorTest.php [new file with mode: 0644]

index 6f6e1fb..10bf462 100644 (file)
@@ -15,6 +15,8 @@ namespace TYPO3\CMS\Frontend\Page;
  */
 
 use TYPO3\CMS\Core\Utility\GeneralUtility;
+use TYPO3\CMS\Extbase\Service\TypoScriptService;
+use TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer;
 
 /**
  * Class for starting TypoScript page generation
@@ -750,29 +752,15 @@ class PageGenerator {
                }
                static::generatePageTitle();
 
-               // Add ending slash only to documents rendered as xhtml
-               $endingSlash = $GLOBALS['TSFE']->xhtmlVersion ? ' /' : '';
-               $pageRenderer->addMetaTag('<meta name="generator" content="TYPO3 ' . TYPO3_branch . ' CMS"' . $endingSlash . '>');
-               $conf = $GLOBALS['TSFE']->pSetup['meta.'];
-               if (is_array($conf)) {
-                       foreach ($conf as $theKey => $theValue) {
-                               // Only if 1) the property is set but not the value itself, 2) the value and/or any property
-                               if (!strstr($theKey, '.') || !isset($conf[substr($theKey, 0, -1)])) {
-                                       if (strstr($theKey, '.')) {
-                                               $theKey = substr($theKey, 0, -1);
-                                       }
-                                       $val = $GLOBALS['TSFE']->cObj->stdWrap($conf[$theKey], $conf[$theKey . '.']);
-                                       $key = $theKey;
-                                       if (trim($val)) {
-                                               $a = 'name';
-                                               if (strtolower($key) === 'refresh' || !empty($conf[($theKey . '.')]['httpEquivalent'])) {
-                                                       $a = 'http-equiv';
-                                               }
-                                               $pageRenderer->addMetaTag('<meta ' . $a . '="' . $key . '" content="' . htmlspecialchars(trim($val)) . '"' . $endingSlash . '>');
-                                       }
-                               }
-                       }
+               $metaTagsHtml = static::generateMetaTagHtml(
+                       isset($GLOBALS['TSFE']->pSetup['meta.']) ? $GLOBALS['TSFE']->pSetup['meta.'] : array(),
+                       $GLOBALS['TSFE']->xhtmlVersion,
+                       $GLOBALS['TSFE']->cObj
+               );
+               foreach ($metaTagsHtml as $metaTag) {
+                       $pageRenderer->addMetaTag($metaTag);
                }
+
                unset($GLOBALS['TSFE']->additionalHeaderData['JSCode']);
                unset($GLOBALS['TSFE']->additionalHeaderData['JSImgCode']);
                if (is_array($GLOBALS['TSFE']->config['INTincScript'])) {
@@ -1124,4 +1112,41 @@ class PageGenerator {
                        $GLOBALS['TSFE']->getPageRenderer()->setTitle($titleTagContent);
                }
        }
+
+       /**
+        * Generate meta tags from meta tag TypoScript
+        *
+        * @param array $metaTagTypoScript TypoScript configuration for meta tags (e.g. $GLOBALS['TSFE']->pSetup['meta.'])
+        * @param bool $xhtml Whether xhtml tag-style should be used. (e.g. pass $GLOBALS['TSFE']->xhtmlVersion here)
+        * @param ContentObjectRenderer $cObj
+        * @return array Array of HTML meta tags
+        */
+       static protected function generateMetaTagHtml(array $metaTagTypoScript, $xhtml, ContentObjectRenderer $cObj) {
+               // Add ending slash only to documents rendered as xhtml
+               $endingSlash = $xhtml ? ' /' : '';
+
+               $metaTags = array(
+                       '<meta name="generator" content="TYPO3 ' . TYPO3_branch . ' CMS"' . $endingSlash . '>'
+               );
+
+               /** @var TypoScriptService $typoScriptService */
+               $typoScriptService = GeneralUtility::makeInstance('TYPO3\\CMS\\Extbase\\Service\\TypoScriptService');
+               $conf = $typoScriptService->convertTypoScriptArrayToPlainArray($metaTagTypoScript);
+               foreach ($conf as $key => $properties) {
+                       if (is_array($properties)) {
+                               $nodeValue = isset($properties['_typoScriptNodeValue']) ? $properties['_typoScriptNodeValue'] : '';
+                               $value = trim($cObj->stdWrap($nodeValue, $metaTagTypoScript[$key . '.']));
+                       } else {
+                               $value = $properties;
+                       }
+                       if ($value !== '') {
+                               $attribute = 'name';
+                               if ( (is_array($properties) && !empty($properties['httpEquivalent'])) || strtolower($key) === 'refresh') {
+                                       $attribute = 'http-equiv';
+                               }
+                               $metaTags[] = '<meta ' . $attribute . '="' . $key . '" content="' . htmlspecialchars($value) . '"' . $endingSlash . '>';
+                       }
+               }
+               return $metaTags;
+       }
 }
diff --git a/typo3/sysext/frontend/Tests/Unit/Page/Fixtures/PageGeneratorFixture.php b/typo3/sysext/frontend/Tests/Unit/Page/Fixtures/PageGeneratorFixture.php
new file mode 100644 (file)
index 0000000..6ab980a
--- /dev/null
@@ -0,0 +1,37 @@
+<?php
+namespace TYPO3\CMS\Frontend\Tests\Unit\Page\Fixtures;
+
+/**
+ * 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\ContentObject\ContentObjectRenderer;
+use TYPO3\CMS\Frontend\Page\PageGenerator;
+
+/**
+ * Fixture for PageGenerator
+ *
+ * @author Markus Klein <klein.t3@mfc-linz.at>
+ */
+class PageGeneratorFixture extends PageGenerator {
+
+       /**
+        * Public accessor for generateMetaTagHtml
+        *
+        * @param array $metaTagTypoScript TypoScript configuration for meta tags (e.g. $GLOBALS['TSFE']->pSetup['meta.'])
+        * @param bool $xhtml Whether xhtml tag-style should be used. (e.g. pass $GLOBALS['TSFE']->xhtmlVersion here)
+        * @param ContentObjectRenderer $cObj
+        * @return array Array of HTML meta tags
+        */
+       public function callGenerateMetaTagHtml(array $metaTagTypoScript, $xhtml, ContentObjectRenderer $cObj) {
+               return self::generateMetaTagHtml($metaTagTypoScript, $xhtml, $cObj);
+       }
+}
\ No newline at end of file
diff --git a/typo3/sysext/frontend/Tests/Unit/Page/PageGeneratorTest.php b/typo3/sysext/frontend/Tests/Unit/Page/PageGeneratorTest.php
new file mode 100644 (file)
index 0000000..1760849
--- /dev/null
@@ -0,0 +1,147 @@
+<?php
+namespace TYPO3\CMS\Frontend\Tests\Unit\Page;
+
+/**
+ * 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\ContentObject\ContentObjectRenderer;
+use TYPO3\CMS\Frontend\Tests\Unit\Page\Fixtures\PageGeneratorFixture;
+
+/**
+ * Test case
+ *
+ * @author Markus Klein <klein.t3@mfc-linz.at>
+ */
+class PageGeneratorTest extends \TYPO3\CMS\Core\Tests\UnitTestCase {
+
+       /**
+        * @var PageGeneratorFixture
+        */
+       protected $pageGeneratorFixture;
+
+       /**
+        * @var ContentObjectRenderer
+        */
+       protected $contentObjectRenderer;
+
+       /**
+        * Set up the helper objects
+        */
+       protected function setUp() {
+               $this->pageGeneratorFixture = new PageGeneratorFixture();
+               $this->contentObjectRenderer = new ContentObjectRenderer();
+       }
+
+       /**
+        * @return array
+        */
+       public function generateMetaTagHtmlGeneratesCorrectTagsDataProvider() {
+               return array(
+                       'simple meta' => array(
+                               array(
+                                       'author' => 'Markus Klein',
+                               ),
+                               FALSE,
+                               array(
+                                       '<meta name="generator" content="TYPO3 ' . TYPO3_branch . ' CMS">',
+                                       '<meta name="author" content="Markus Klein">',
+                               )
+                       ),
+                       'simple meta xhtml' => array(
+                               array(
+                                       'author' => 'Markus Klein',
+                               ),
+                               TRUE,
+                               array(
+                                       '<meta name="generator" content="TYPO3 ' . TYPO3_branch . ' CMS" />',
+                                       '<meta name="author" content="Markus Klein" />',
+                               )
+                       ),
+                       'meta with nested stdWrap' => array(
+                               array(
+                                       'author' => 'Markus ',
+                                   'author.' => array('stdWrap.' => array('wrap' => '|Klein'))
+                               ),
+                               FALSE,
+                               array(
+                                       '<meta name="generator" content="TYPO3 ' . TYPO3_branch . ' CMS">',
+                                       '<meta name="author" content="Markus Klein">',
+                               )
+                       ),
+                       'httpEquivalent meta' => array(
+                               array(
+                                       'X-UA-Compatible' => 'IE=edge,chrome=1',
+                                   'X-UA-Compatible.' => array('httpEquivalent' => 1)
+                               ),
+                               FALSE,
+                           array(
+                                   '<meta name="generator" content="TYPO3 ' . TYPO3_branch . ' CMS">',
+                                       '<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">'
+                           )
+                       ),
+                   'httpEquivalent meta xhtml' => array(
+                               array(
+                                       'X-UA-Compatible' => 'IE=edge,chrome=1',
+                                       'X-UA-Compatible.' => array('httpEquivalent' => 1)
+                               ),
+                               TRUE,
+                               array(
+                                       '<meta name="generator" content="TYPO3 ' . TYPO3_branch . ' CMS" />',
+                                       '<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" />'
+                               )
+                   ),
+                   'refresh meta' => array(
+                               array(
+                                       'refresh' => '10',
+                               ),
+                               FALSE,
+                               array(
+                                       '<meta name="generator" content="TYPO3 ' . TYPO3_branch . ' CMS">',
+                                       '<meta http-equiv="refresh" content="10">',
+                               )
+                       ),
+                   'meta with dot' => array(
+                           array(
+                                   'DC.author' => 'Markus Klein',
+                           ),
+                           FALSE,
+                           array(
+                                   '<meta name="generator" content="TYPO3 ' . TYPO3_branch . ' CMS">',
+                                   '<meta name="DC.author" content="Markus Klein">',
+                           )
+                   ),
+                   'meta with colon' => array(
+                           array(
+                                   'OG:title' => 'Magic Tests',
+                           ),
+                           FALSE,
+                           array(
+                                   '<meta name="generator" content="TYPO3 ' . TYPO3_branch . ' CMS">',
+                                   '<meta name="OG:title" content="Magic Tests">',
+                           )
+                   ),
+               );
+       }
+
+       /**
+        * @test
+        * @dataProvider generateMetaTagHtmlGeneratesCorrectTagsDataProvider
+        *
+        * @param array $typoScript
+        * @param bool $xhtml
+        * @param array $expectedTags
+        */
+       public function generateMetaTagHtmlGeneratesCorrectTags(array $typoScript, $xhtml, array $expectedTags) {
+               $result = $this->pageGeneratorFixture->callGenerateMetaTagHtml($typoScript, $xhtml, $this->contentObjectRenderer);
+               $this->assertSame($expectedTags, $result);
+       }
+}