[FEATURE] Add SiteProcessor 61/59761/16
authorGeorg Ringer <georg.ringer@gmail.com>
Wed, 20 Feb 2019 11:04:31 +0000 (12:04 +0100)
committerBenni Mack <benni@typo3.org>
Fri, 1 Mar 2019 13:02:33 +0000 (14:02 +0100)
The SiteProcessor can be used to retrieve all properties of the site entity.
This is especially useful if the site configuration is extended with custom
configurations.

Resolves: #87748
Releases: master, 9.5
Change-Id: I650bc9745ca3f0236072aeab9f186b1ea24313e7
Reviewed-on: https://review.typo3.org/c/59761
Tested-by: TYPO3com <noreply@typo3.com>
Tested-by: Jürgen Venne <venne@schaffrath-digital.de>
Tested-by: Guido Schmechel <guido.schmechel@brandung.de>
Tested-by: Benni Mack <benni@typo3.org>
Reviewed-by: Jürgen Venne <venne@schaffrath-digital.de>
Reviewed-by: Guido Schmechel <guido.schmechel@brandung.de>
Reviewed-by: Benni Mack <benni@typo3.org>
typo3/sysext/core/Documentation/Changelog/9.5.x/Feature-87748-AddSiteProcessor.rst [new file with mode: 0644]
typo3/sysext/frontend/Classes/DataProcessing/SiteProcessor.php [new file with mode: 0644]
typo3/sysext/frontend/Tests/Unit/DataProcessing/SiteProcessorTest.php [new file with mode: 0644]

diff --git a/typo3/sysext/core/Documentation/Changelog/9.5.x/Feature-87748-AddSiteProcessor.rst b/typo3/sysext/core/Documentation/Changelog/9.5.x/Feature-87748-AddSiteProcessor.rst
new file mode 100644 (file)
index 0000000..9994775
--- /dev/null
@@ -0,0 +1,33 @@
+.. include:: ../../Includes.txt
+
+===================================
+Feature: #87748 - Add SiteProcessor
+===================================
+
+See :issue:`87748`
+
+Description
+===========
+
+A new Site Processor has been introduced which can be used to fetch data from the site entity
+
+.. code-block:: typoscript
+
+   tt_content.mycontent.20 = FLUIDTEMPLATE
+   tt_content.mycontent.20 {
+      file = EXT:myextension/Resources/Private/Templates/ContentObjects/MyContent.html
+
+      dataProcessing.10 = TYPO3\CMS\Frontend\DataProcessing\SiteProcessor
+      dataProcessing.10 {
+         as = site
+      }
+   }
+
+In the Fluid template the properties of the site entity can be accessed
+
+.. code-block:: html
+
+   <p>{site.rootPageId}</p>
+   <p>{site.someCustomConfiguration}</p>
+
+.. index:: Fluid, Frontend, ext:frontend
diff --git a/typo3/sysext/frontend/Classes/DataProcessing/SiteProcessor.php b/typo3/sysext/frontend/Classes/DataProcessing/SiteProcessor.php
new file mode 100644 (file)
index 0000000..17b47b1
--- /dev/null
@@ -0,0 +1,85 @@
+<?php
+declare(strict_types = 1);
+namespace TYPO3\CMS\Frontend\DataProcessing;
+
+/*
+ * 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\Core\Exception\SiteNotFoundException;
+use TYPO3\CMS\Core\Routing\SiteMatcher;
+use TYPO3\CMS\Core\Site\Entity\SiteInterface;
+use TYPO3\CMS\Core\Utility\GeneralUtility;
+use TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer;
+use TYPO3\CMS\Frontend\ContentObject\DataProcessorInterface;
+
+/**
+ * Fetch the site object containing all information about the current site
+ *
+ * Example TypoScript configuration:
+ *
+ * 10 = TYPO3\CMS\Frontend\DataProcessing\SiteProcessor
+ * 10 {
+ *   as = site
+ * }
+ *
+ * where "as" names the variable containing the site object
+ */
+class SiteProcessor implements DataProcessorInterface
+{
+
+    /**
+     * @param ContentObjectRenderer $cObj The data of the content element or page
+     * @param array $contentObjectConfiguration The configuration of Content Object
+     * @param array $processorConfiguration The configuration of this processor
+     * @param array $processedData Key/value store of processed data (e.g. to be passed to a Fluid View)
+     * @return array the processed data as key/value store
+     */
+    public function process(ContentObjectRenderer $cObj, array $contentObjectConfiguration, array $processorConfiguration, array $processedData): array
+    {
+        $targetVariableName = $cObj->stdWrapValue('as', $processorConfiguration, 'site');
+        $processedData[$targetVariableName] = $this->getCurrentSite();
+        return $processedData;
+    }
+
+    /**
+     * Returns the currently configured "site" if a site is configured (= resolved) in the current request.
+     *
+     * @return SiteInterface|null
+     */
+    protected function getCurrentSite(): ?SiteInterface
+    {
+        try {
+            return $this->getMatcher()->matchByPageId($this->getCurrentPageId());
+        } catch (SiteNotFoundException $e) {
+            // Do nothing
+        }
+
+        return null;
+    }
+
+    /**
+     * @return SiteMatcher
+     */
+    protected function getMatcher(): SiteMatcher
+    {
+        return GeneralUtility::makeInstance(SiteMatcher::class);
+    }
+
+    /**
+     * @return int
+     */
+    protected function getCurrentPageId(): int
+    {
+        return (int)$GLOBALS['TSFE']->id;
+    }
+}
diff --git a/typo3/sysext/frontend/Tests/Unit/DataProcessing/SiteProcessorTest.php b/typo3/sysext/frontend/Tests/Unit/DataProcessing/SiteProcessorTest.php
new file mode 100644 (file)
index 0000000..e821ec8
--- /dev/null
@@ -0,0 +1,71 @@
+<?php
+declare(strict_types = 1);
+
+namespace TYPO3\CMS\Frontend\Tests\Unit\DataProcessing;
+
+/*
+ * 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\Core\Exception\SiteNotFoundException;
+use TYPO3\CMS\Core\Routing\SiteMatcher;
+use TYPO3\CMS\Core\Site\Entity\Site;
+use TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer;
+use TYPO3\CMS\Frontend\DataProcessing\SiteProcessor;
+use TYPO3\TestingFramework\Core\Unit\UnitTestCase;
+
+/**
+ * Testcase
+ */
+class SiteProcessorTest extends UnitTestCase
+{
+
+    /**
+     * @test
+     */
+    public function siteIsRetrieved(): void
+    {
+        $processorConfiguration = ['as' => 'variable'];
+        $mockedContentObjectRenderer = $this->getAccessibleMock(ContentObjectRenderer::class, ['stdWrapValue'], [], '', false);
+        $mockedContentObjectRenderer->expects($this->any())->method('stdWrapValue')->with('as', $processorConfiguration, 'site')->willReturn('variable');
+
+        $site = new Site('site123', 123, []);
+
+        $subject = $this->getAccessibleMock(SiteProcessor::class, ['getCurrentSite'], []);
+        $subject->expects($this->any())->method('getCurrentSite')->willReturn($site);
+
+        $processedData = $subject->process($mockedContentObjectRenderer, [], $processorConfiguration, []);
+
+        $this->assertEquals($site, $processedData['variable']);
+    }
+
+    /**
+     * @test
+     */
+    public function nullIsProvidedIfSiteCouldNotBeRetrieved(): void
+    {
+        $processorConfiguration = ['as' => 'variable'];
+        $mockedContentObjectRenderer = $this->getAccessibleMock(ContentObjectRenderer::class, ['stdWrapValue'], [], '', false);
+        $mockedContentObjectRenderer->expects($this->any())->method('stdWrapValue')->with('as', $processorConfiguration, 'site')->willReturn('variable');
+
+        $matcherMock = $this->getMockBuilder(SiteMatcher::class)->disableOriginalConstructor()->getMock();
+        $matcherMock->expects($this->any())->method('matchByPageId')->willThrowException(new SiteNotFoundException('message', 1550670118));
+
+        $subject = $this->getAccessibleMock(SiteProcessor::class, ['getMatcher', 'getCurrentPageId'], []);
+        $subject->expects($this->any())->method('getMatcher')->willReturn($matcherMock);
+        $subject->expects($this->any())->method('getCurrentPageId')->willReturn(1);
+
+        $processedData = $subject->process($mockedContentObjectRenderer, [], $processorConfiguration, []);
+
+        $this->assertNull($processedData['variable']);
+    }
+}