[TASK] Move all marker-based logic from cObj to MarkerBasedTemplateService
[Packages/TYPO3.CMS.git] / typo3 / sysext / core / Tests / Unit / Service / MarkerBasedTemplateServiceTest.php
index 76105d8..032c0e3 100644 (file)
@@ -14,382 +14,418 @@ namespace TYPO3\CMS\Core\Tests\Unit\Service;
  * The TYPO3 project - inspiring people to share!
  */
 
+use Prophecy\Argument;
+use Prophecy\Prophecy\ObjectProphecy;
+use TYPO3\CMS\Core\Cache\CacheManager;
+use TYPO3\CMS\Core\Cache\Frontend\FrontendInterface;
 use TYPO3\CMS\Core\Service\MarkerBasedTemplateService;
 use TYPO3\CMS\Core\Utility\GeneralUtility;
 
 /**
  * Unit test for marker utility
  */
-class MarkerBasedTemplateServiceTest extends \TYPO3\CMS\Core\Tests\UnitTestCase {
-
-       /**
-        * @var MarkerBasedTemplateService
-        */
-       protected $templateService;
-
-       public function setUp() {
-               $this->templateService = GeneralUtility::makeInstance(MarkerBasedTemplateService::class);
-       }
-
-       /**
-        * Data provider for getSubpart
-        *
-        * @return array
-        */
-       public function getSubpartDataProvider() {
-               return array(
-                       'No start marker' => array(
-                               '<body>text</body>',
-                               '###SUBPART###',
-                               ''
-                       ),
-                       'No stop marker' => array(
-                               '<body>
+class MarkerBasedTemplateServiceTest extends \TYPO3\TestingFramework\Core\Unit\UnitTestCase
+{
+    /**
+     * @var MarkerBasedTemplateService
+     */
+    protected $templateService;
+
+    /**
+     * @var array A backup of registered singleton instances
+     */
+    protected $singletonInstances = [];
+
+    protected function setUp()
+    {
+        $this->singletonInstances = GeneralUtility::getSingletonInstances();
+
+        /** @var CacheManager|ObjectProphecy $cacheManagerProphecy */
+        $cacheManagerProphecy = $this->prophesize(CacheManager::class);
+        GeneralUtility::setSingletonInstance(CacheManager::class, $cacheManagerProphecy->reveal());
+        $cacheFrontendProphecy = $this->prophesize(FrontendInterface::class);
+        $cacheManagerProphecy->getCache(Argument::cetera())->willReturn($cacheFrontendProphecy->reveal());
+
+        $this->templateService = new MarkerBasedTemplateService();
+    }
+
+    protected function tearDown()
+    {
+        GeneralUtility::purgeInstances();
+        GeneralUtility::resetSingletonInstances($this->singletonInstances);
+        parent::tearDown();
+    }
+
+    /**
+     * Data provider for getSubpart
+     *
+     * @return array
+     */
+    public function getSubpartDataProvider()
+    {
+        return [
+            'No start marker' => [
+                '<body>text</body>',
+                '###SUBPART###',
+                ''
+            ],
+            'No stop marker' => [
+                '<body>
 <!-- ###SUBPART### Start -->
 text
 </body>',
-                               '###SUBPART###',
-                               ''
-                       ),
-                       'Start and stop marker in HTML comment' => array(
-                               '<body>
+                '###SUBPART###',
+                ''
+            ],
+            'Start and stop marker in HTML comment' => [
+                '<body>
 <!-- ###SUBPART### Start -->
 text
 <!-- ###SUBPART### End -->
 </body>',
-                               '###SUBPART###',
-                               '
+                '###SUBPART###',
+                '
 text
 '
-                       ),
-                       'Stop marker in HTML comment' => array(
-                               '<body>
+            ],
+            'Stop marker in HTML comment' => [
+                '<body>
 ###SUBPART###
 text
 <!-- ###SUBPART### End -->
 </body>',
-                               '###SUBPART###',
-                               '
+                '###SUBPART###',
+                '
 text
 '
-                       ),
-                       'Start marker in HTML comment' => array(
-                               '<body>
+            ],
+            'Start marker in HTML comment' => [
+                '<body>
 <!-- ###SUBPART### Start -->
 text
 ###SUBPART###
 </body>',
-                               '###SUBPART###',
-                               '
+                '###SUBPART###',
+                '
 text
 '
-                       ),
-                       'Start and stop marker direct' => array(
-                               '<body>
+            ],
+            'Start and stop marker direct' => [
+                '<body>
 ###SUBPART###
 text
 ###SUBPART###
 </body>',
-                               '###SUBPART###',
-                               '
+                '###SUBPART###',
+                '
 text
 '
-                       ),
-               );
-       }
-
-       /**
-        * @test
-        * @param string $content
-        * @param string $marker
-        * @param string $expected
-        * @dataProvider getSubpartDataProvider
-        */
-       public function getSubpart($content, $marker, $expected) {
-               $this->assertSame($expected, $this->templateService->getSubpart($content, $marker));
-       }
-
-       /**
-        * Data provider for substituteSubpart
-        *
-        * @return array
-        */
-       public function substituteSubpartDataProvider() {
-               return array(
-                       'No start marker' => array(
-                               '<body>text</body>',
-                               '###SUBPART###',
-                               'hello',
-                               FALSE,
-                               FALSE,
-                               '<body>text</body>'
-                       ),
-                       'No stop marker' => array(
-                               '<body>
+            ],
+        ];
+    }
+
+    /**
+     * @test
+     * @param string $content
+     * @param string $marker
+     * @param string $expected
+     * @dataProvider getSubpartDataProvider
+     */
+    public function getSubpart($content, $marker, $expected)
+    {
+        $this->assertSame($expected, $this->templateService->getSubpart($content, $marker));
+    }
+
+    /**
+     * Data provider for substituteSubpart
+     *
+     * @return array
+     */
+    public function substituteSubpartDataProvider()
+    {
+        return [
+            'No start marker' => [
+                '<body>text</body>',
+                '###SUBPART###',
+                'hello',
+                false,
+                false,
+                '<body>text</body>'
+            ],
+            'No stop marker' => [
+                '<body>
 <!-- ###SUBPART### Start -->
 text
 </body>',
-                               '###SUBPART###',
-                               'hello',
-                               FALSE,
-                               FALSE,
-                               '<body>
+                '###SUBPART###',
+                'hello',
+                false,
+                false,
+                '<body>
 <!-- ###SUBPART### Start -->
 text
 </body>',
-                       ),
-                       'Start and stop marker in HTML comment' => array(
-                               '<body>
+            ],
+            'Start and stop marker in HTML comment' => [
+                '<body>
 <!-- ###SUBPART### Start -->
 text
 <!-- ###SUBPART### End -->
 </body>',
-                               '###SUBPART###',
-                               'hello',
-                               FALSE,
-                               FALSE,
-                               '<body>
+                '###SUBPART###',
+                'hello',
+                false,
+                false,
+                '<body>
 hello
 </body>'
-                       ),
-                       'Recursive subpart' => array(
-                               '<body>
+            ],
+            'Recursive subpart' => [
+                '<body>
 <!-- ###SUBPART### Start -->text1<!-- ###SUBPART### End -->
 <!-- ###SUBPART### Start -->text2<!-- ###SUBPART### End -->
 </body>',
-                               '###SUBPART###',
-                               'hello',
-                               TRUE,
-                               FALSE,
-                               '<body>
+                '###SUBPART###',
+                'hello',
+                true,
+                false,
+                '<body>
 hello
 hello
 </body>'
-                       ),
-                       'Keep HTML marker' => array(
-                               '<body>
+            ],
+            'Keep HTML marker' => [
+                '<body>
 <!-- ###SUBPART### Start -->text<!-- ###SUBPART### End -->
 </body>',
-                               '###SUBPART###',
-                               'hello',
-                               FALSE,
-                               TRUE,
-                               '<body>
+                '###SUBPART###',
+                'hello',
+                false,
+                true,
+                '<body>
 <!-- ###SUBPART### Start -->hello<!-- ###SUBPART### End -->
 </body>'
-                       ),
-                       'Keep HTML begin marker' => array(
-                               '<body>
+            ],
+            'Keep HTML begin marker' => [
+                '<body>
 <!-- ###SUBPART### Start -->text###SUBPART###
 </body>',
-                               '###SUBPART###',
-                               'hello',
-                               FALSE,
-                               TRUE,
-                               '<body>
+                '###SUBPART###',
+                'hello',
+                false,
+                true,
+                '<body>
 <!-- ###SUBPART### Start -->hello###SUBPART###
 </body>'
-                       ),
-                       'Keep HTML end marker' => array(
-                               '<body>
+            ],
+            'Keep HTML end marker' => [
+                '<body>
 ###SUBPART###text<!-- ###SUBPART### End -->
 </body>',
-                               '###SUBPART###',
-                               'hello',
-                               FALSE,
-                               TRUE,
-                               '<body>
+                '###SUBPART###',
+                'hello',
+                false,
+                true,
+                '<body>
 ###SUBPART###hello<!-- ###SUBPART### End -->
 </body>'
-                       ),
-                       'Keep plain marker' => array(
-                               '<body>
+            ],
+            'Keep plain marker' => [
+                '<body>
 ###SUBPART###text###SUBPART###
 </body>',
-                               '###SUBPART###',
-                               'hello',
-                               FALSE,
-                               TRUE,
-                               '<body>
+                '###SUBPART###',
+                'hello',
+                false,
+                true,
+                '<body>
 ###SUBPART###hello###SUBPART###
 </body>'
-                       ),
-                       'Wrap around' => array(
-                               '<body>
+            ],
+            'Wrap around' => [
+                '<body>
 ###SUBPART###text###SUBPART###
 </body>',
-                               '###SUBPART###',
-                               array('before-', '-after'),
-                               FALSE,
-                               TRUE,
-                               '<body>
+                '###SUBPART###',
+                ['before-', '-after'],
+                false,
+                true,
+                '<body>
 ###SUBPART###before-text-after###SUBPART###
 </body>'
-                       ),
-               );
-       }
-
-       /**
-        * @test
-        * @param string $content
-        * @param string $marker
-        * @param array $subpartContent
-        * @param bool $recursive
-        * @param bool $keepMarker
-        * @param string $expected
-        * @dataProvider substituteSubpartDataProvider
-        */
-       public function substituteSubpart($content, $marker, $subpartContent, $recursive, $keepMarker, $expected) {
-               $this->assertSame($expected, $this->templateService->substituteSubpart($content, $marker, $subpartContent, $recursive, $keepMarker));
-       }
-
-       /**
-        * Data provider for substituteMarkerArray
-        */
-       public function substituteMarkerArrayDataProvider() {
-               return array(
-                       'Upper case marker' => array(
-                               'This is ###MARKER1### and this is ###MARKER2###',
-                               array('###MARKER1###' => 'marker 1',
-                                       '###MARKER2###' => 'marker 2'),
-                               '',
-                               FALSE,
-                               FALSE,
-                               'This is marker 1 and this is marker 2'
-                       ),
-                       'Lower case marker' => array(
-                               'This is ###MARKER1### and this is ###MARKER2###',
-                               array('###marker1###' => 'marker 1',
-                                       '###marker2###' => 'marker 2'),
-                               '',
-                               TRUE,
-                               FALSE,
-                               'This is marker 1 and this is marker 2'
-                       ),
-                       'Upper case marker without hash mark' => array(
-                               'This is ###MARKER1### and this is ###MARKER2###',
-                               array('MARKER1' => 'marker 1',
-                                       'MARKER2' => 'marker 2'),
-                               '###|###',
-                               FALSE,
-                               FALSE,
-                               'This is marker 1 and this is marker 2'
-                       ),
-                       'Upper case marker with another hash mark' => array(
-                               'This is *MARKER1* and this is *MARKER2*',
-                               array('MARKER1' => 'marker 1',
-                                       'MARKER2' => 'marker 2'),
-                               '*|*',
-                               FALSE,
-                               FALSE,
-                               'This is marker 1 and this is marker 2'
-                       ),
-                       'Upper case marker with unused marker' => array(
-                               'This is ###MARKER1### and this is ###MARKER2### ###UNUSED###',
-                               array('###MARKER1###' => 'marker 1',
-                                       '###MARKER2###' => 'marker 2'),
-                               '',
-                               FALSE,
-                               FALSE,
-                               'This is marker 1 and this is marker 2 ###UNUSED###'
-                       ),
-                       'Upper case marker with unused marker deleted' => array(
-                               'This is ###MARKER1### and this is ###MARKER2### ###UNUSED###',
-                               array('###MARKER1###' => 'marker 1',
-                                       '###MARKER2###' => 'marker 2'),
-                               '',
-                               FALSE,
-                               TRUE,
-                               'This is marker 1 and this is marker 2 '
-                       ),
-               );
-       }
-
-       /**
-        * @test
-        * @dataProvider substituteMarkerArrayDataProvider
-        * @param string $content The content stream, typically HTML template content.
-        * @param array $markContentArray The array of key/value pairs being marker/content values used in the substitution. For each element in this array the function will substitute a marker in the content stream with the content.
-        * @param string $wrap A wrap value - [part 1] | [part 2] - for the markers before substitution
-        * @param bool $uppercase If set, all marker string substitution is done with upper-case markers.
-        * @param bool $deleteUnused If set, all unused marker are deleted.
-        * @param string $expected
-        */
-       public function substituteMarkerArray($content, $markContentArray, $wrap, $uppercase, $deleteUnused, $expected) {
-               $this->assertSame($expected, $this->templateService->substituteMarkerArray($content, $markContentArray, $wrap, $uppercase, $deleteUnused));
-       }
-
-       /**
-        * Data provider for substituteMarker
-        */
-       public function substituteMarkerDataProvider() {
-               return array(
-                       'Single marker' => array(
-                               'This is a ###SAMPLE### text',
-                               '###SAMPLE###',
-                               'simple',
-                               'This is a simple text'
-                       ),
-                       'Double marker' => array(
-                               'This is a ###SAMPLE### text with a ###SAMPLE### content',
-                               '###SAMPLE###',
-                               'simple',
-                               'This is a simple text with a simple content'
-                       ),
-               );
-       }
-
-       /**
-        * @dataProvider substituteMarkerDataProvider
-        * @param string $content The content stream, typically HTML template content.
-        * @param string $marker The marker string, typically on the form "###[the marker string]###
-        * @param mixed $markContent The content to insert instead of the marker string found.
-        * @param string $expected The expected result of the substitution
-        */
-       public function substituteMarker($content, $marker, $markContent, $expected) {
-               $this->assertSame($expected, $this->templateService->substituteMarker($content, $marker, $markContent));
-       }
-
-       /**
-        * Data provider for substituteSubpartArray
-        *
-        * @return array
-        */
-       public function substituteSubpartArrayDataProvider() {
-               return array(
-                       'Substitute multiple subparts at once with plain marker' => array(
-                               '<body>
+            ],
+        ];
+    }
+
+    /**
+     * @test
+     * @param string $content
+     * @param string $marker
+     * @param array $subpartContent
+     * @param bool $recursive
+     * @param bool $keepMarker
+     * @param string $expected
+     * @dataProvider substituteSubpartDataProvider
+     */
+    public function substituteSubpart($content, $marker, $subpartContent, $recursive, $keepMarker, $expected)
+    {
+        $this->assertSame($expected, $this->templateService->substituteSubpart($content, $marker, $subpartContent, $recursive, $keepMarker));
+    }
+
+    /**
+     * Data provider for substituteMarkerArray
+     */
+    public function substituteMarkerArrayDataProvider()
+    {
+        return [
+            'Upper case marker' => [
+                'This is ###MARKER1### and this is ###MARKER2###',
+                ['###MARKER1###' => 'marker 1',
+                    '###MARKER2###' => 'marker 2'],
+                '',
+                false,
+                false,
+                'This is marker 1 and this is marker 2'
+            ],
+            'Lower case marker' => [
+                'This is ###MARKER1### and this is ###MARKER2###',
+                ['###marker1###' => 'marker 1',
+                    '###marker2###' => 'marker 2'],
+                '',
+                true,
+                false,
+                'This is marker 1 and this is marker 2'
+            ],
+            'Upper case marker without hash mark' => [
+                'This is ###MARKER1### and this is ###MARKER2###',
+                ['MARKER1' => 'marker 1',
+                    'MARKER2' => 'marker 2'],
+                '###|###',
+                false,
+                false,
+                'This is marker 1 and this is marker 2'
+            ],
+            'Upper case marker with another hash mark' => [
+                'This is *MARKER1* and this is *MARKER2*',
+                ['MARKER1' => 'marker 1',
+                    'MARKER2' => 'marker 2'],
+                '*|*',
+                false,
+                false,
+                'This is marker 1 and this is marker 2'
+            ],
+            'Upper case marker with unused marker' => [
+                'This is ###MARKER1### and this is ###MARKER2### ###UNUSED###',
+                ['###MARKER1###' => 'marker 1',
+                    '###MARKER2###' => 'marker 2'],
+                '',
+                false,
+                false,
+                'This is marker 1 and this is marker 2 ###UNUSED###'
+            ],
+            'Upper case marker with unused marker deleted' => [
+                'This is ###MARKER1### and this is ###MARKER2### ###UNUSED###',
+                ['###MARKER1###' => 'marker 1',
+                    '###MARKER2###' => 'marker 2'],
+                '',
+                false,
+                true,
+                'This is marker 1 and this is marker 2 '
+            ],
+        ];
+    }
+
+    /**
+     * @test
+     * @dataProvider substituteMarkerArrayDataProvider
+     * @param string $content The content stream, typically HTML template content.
+     * @param array $markContentArray The array of key/value pairs being marker/content values used in the substitution. For each element in this array the function will substitute a marker in the content stream with the content.
+     * @param string $wrap A wrap value - [part 1] | [part 2] - for the markers before substitution
+     * @param bool $uppercase If set, all marker string substitution is done with upper-case markers.
+     * @param bool $deleteUnused If set, all unused marker are deleted.
+     * @param string $expected
+     */
+    public function substituteMarkerArray($content, $markContentArray, $wrap, $uppercase, $deleteUnused, $expected)
+    {
+        $this->assertSame($expected, $this->templateService->substituteMarkerArray($content, $markContentArray, $wrap, $uppercase, $deleteUnused));
+    }
+
+    /**
+     * Data provider for substituteMarker
+     */
+    public function substituteMarkerDataProvider()
+    {
+        return [
+            'Single marker' => [
+                'This is a ###SAMPLE### text',
+                '###SAMPLE###',
+                'simple',
+                'This is a simple text'
+            ],
+            'Double marker' => [
+                'This is a ###SAMPLE### text with a ###SAMPLE### content',
+                '###SAMPLE###',
+                'simple',
+                'This is a simple text with a simple content'
+            ],
+        ];
+    }
+
+    /**
+     * @dataProvider substituteMarkerDataProvider
+     * @param string $content The content stream, typically HTML template content.
+     * @param string $marker The marker string, typically on the form "###[the marker string]###
+     * @param mixed $markContent The content to insert instead of the marker string found.
+     * @param string $expected The expected result of the substitution
+     */
+    public function substituteMarker($content, $marker, $markContent, $expected)
+    {
+        $this->assertSame($expected, $this->templateService->substituteMarker($content, $marker, $markContent));
+    }
+
+    /**
+     * Data provider for substituteSubpartArray
+     *
+     * @return array
+     */
+    public function substituteSubpartArrayDataProvider()
+    {
+        return [
+            'Substitute multiple subparts at once with plain marker' => [
+                '<body>
 ###SUBPART1###text1###SUBPART1###
 ###SUBPART2###text2###SUBPART2###
 </body>',
-                               array ('###SUBPART1###' => 'hello',
-                                       '###SUBPART2###' => 'world'),
-                               '<body>
+                ['###SUBPART1###' => 'hello',
+                    '###SUBPART2###' => 'world'],
+                '<body>
 hello
 world
 </body>'
-                       ),
-               );
-       }
-
-       /**
-        * @test
-        * @param string $content
-        * @param array $subpartsContent
-        * @param string $expected
-        * @dataProvider substituteSubpartArrayDataProvider
-        */
-       public function substituteSubpartArray($content, array $subpartsContent, $expected) {
-               $this->assertSame($expected, $this->templateService->substituteSubpartArray($content, $subpartsContent));
-       }
-
-       /**
-        * Data provider for substituteMarkerAndSubpartArrayRecursiveResolvesMarkersAndSubpartsArray
-        *
-        * @return array
-        */
-       public function substituteMarkerAndSubpartArrayRecursiveResolvesMarkersAndSubpartsArrayDataProvider() {
-               $template = '###SINGLEMARKER1###
+            ],
+        ];
+    }
+
+    /**
+     * @test
+     * @param string $content
+     * @param array $subpartsContent
+     * @param string $expected
+     * @dataProvider substituteSubpartArrayDataProvider
+     */
+    public function substituteSubpartArray($content, array $subpartsContent, $expected)
+    {
+        $this->assertSame($expected, $this->templateService->substituteSubpartArray($content, $subpartsContent));
+    }
+
+    /**
+     * Data provider for substituteMarkerAndSubpartArrayRecursiveResolvesMarkersAndSubpartsArray
+     *
+     * @return array
+     */
+    public function substituteMarkerAndSubpartArrayRecursiveResolvesMarkersAndSubpartsArrayDataProvider()
+    {
+        $template = '###SINGLEMARKER1###
 <!-- ###FOO### begin -->
 <!-- ###BAR### begin -->
 ###SINGLEMARKER2###
@@ -399,7 +435,7 @@ world
 <!-- ###FOOTER### end -->
 <!-- ###FOO### end -->';
 
-               $expected ='Value 1
+        $expected ='Value 1
 
 
 Value 2.1
@@ -413,129 +449,129 @@ Value 3.2
 
 ';
 
-               return array(
-                       'Single marker' => array(
-                               '###SINGLEMARKER###',
-                               array(
-                                       '###SINGLEMARKER###' => 'Value 1'
-                               ),
-                               '',
-                               FALSE,
-                               FALSE,
-                               'Value 1'
-                       ),
-                       'Subpart marker' => array(
-                               $template,
-                               array(
-                                       '###SINGLEMARKER1###' => 'Value 1',
-                                       '###FOO###' => array(
-                                               array(
-                                                       '###BAR###' => array(
-                                                               array(
-                                                                       '###SINGLEMARKER2###' => 'Value 2.1'
-                                                               ),
-                                                               array(
-                                                                       '###SINGLEMARKER2###' => 'Value 2.2'
-                                                               )
-                                                       ),
-                                                       '###FOOTER###' => array(
-                                                               array(
-                                                                       '###SINGLEMARKER3###' => 'Value 3.1'
-                                                               ),
-                                                               array(
-                                                                       '###SINGLEMARKER3###' => 'Value 3.2'
-                                                               )
-                                                       )
-                                               )
-                                       )
-                               ),
-                               '',
-                               FALSE,
-                               FALSE,
-                               $expected
-                       ),
-                       'Subpart marker with wrap' => array(
-                               $template,
-                               array(
-                                       'SINGLEMARKER1' => 'Value 1',
-                                       'FOO' => array(
-                                               array(
-                                                       'BAR' => array(
-                                                               array(
-                                                                       'SINGLEMARKER2' => 'Value 2.1'
-                                                               ),
-                                                               array(
-                                                                       'SINGLEMARKER2' => 'Value 2.2'
-                                                               )
-                                                       ),
-                                                       'FOOTER' => array(
-                                                               array(
-                                                                       'SINGLEMARKER3' => 'Value 3.1'
-                                                               ),
-                                                               array(
-                                                                       'SINGLEMARKER3' => 'Value 3.2'
-                                                               )
-                                                       )
-                                               )
-                                       )
-                               ),
-                               '###|###',
-                               FALSE,
-                               FALSE,
-                               $expected
-                       ),
-                       'Subpart marker with lower marker array keys' => array(
-                               $template,
-                               array(
-                                       '###singlemarker1###' => 'Value 1',
-                                       '###foo###' => array(
-                                               array(
-                                                       '###bar###' => array(
-                                                               array(
-                                                                       '###singlemarker2###' => 'Value 2.1'
-                                                               ),
-                                                               array(
-                                                                       '###singlemarker2###' => 'Value 2.2'
-                                                               )
-                                                       ),
-                                                       '###footer###' => array(
-                                                               array(
-                                                                       '###singlemarker3###' => 'Value 3.1'
-                                                               ),
-                                                               array(
-                                                                       '###singlemarker3###' => 'Value 3.2'
-                                                               )
-                                                       )
-                                               )
-                                       )
-                               ),
-                               '',
-                               TRUE,
-                               FALSE,
-                               $expected
-                       ),
-                       'Subpart marker with unused markers' => array(
-                               $template,
-                               array(
-                                       '###FOO###' => array(
-                                               array(
-                                                       '###BAR###' => array(
-                                                               array(
-                                                                       '###SINGLEMARKER2###' => 'Value 2.1'
-                                                               )
-                                                       ),
-                                                       '###FOOTER###' => array(
-                                                               array(
-                                                                       '###SINGLEMARKER3###' => 'Value 3.1'
-                                                               )
-                                                       )
-                                               )
-                                       )
-                               ),
-                               '',
-                               FALSE,
-                               TRUE,
-                               '
+        return [
+            'Single marker' => [
+                '###SINGLEMARKER###',
+                [
+                    '###SINGLEMARKER###' => 'Value 1'
+                ],
+                '',
+                false,
+                false,
+                'Value 1'
+            ],
+            'Subpart marker' => [
+                $template,
+                [
+                    '###SINGLEMARKER1###' => 'Value 1',
+                    '###FOO###' => [
+                        [
+                            '###BAR###' => [
+                                [
+                                    '###SINGLEMARKER2###' => 'Value 2.1'
+                                ],
+                                [
+                                    '###SINGLEMARKER2###' => 'Value 2.2'
+                                ]
+                            ],
+                            '###FOOTER###' => [
+                                [
+                                    '###SINGLEMARKER3###' => 'Value 3.1'
+                                ],
+                                [
+                                    '###SINGLEMARKER3###' => 'Value 3.2'
+                                ]
+                            ]
+                        ]
+                    ]
+                ],
+                '',
+                false,
+                false,
+                $expected
+            ],
+            'Subpart marker with wrap' => [
+                $template,
+                [
+                    'SINGLEMARKER1' => 'Value 1',
+                    'FOO' => [
+                        [
+                            'BAR' => [
+                                [
+                                    'SINGLEMARKER2' => 'Value 2.1'
+                                ],
+                                [
+                                    'SINGLEMARKER2' => 'Value 2.2'
+                                ]
+                            ],
+                            'FOOTER' => [
+                                [
+                                    'SINGLEMARKER3' => 'Value 3.1'
+                                ],
+                                [
+                                    'SINGLEMARKER3' => 'Value 3.2'
+                                ]
+                            ]
+                        ]
+                    ]
+                ],
+                '###|###',
+                false,
+                false,
+                $expected
+            ],
+            'Subpart marker with lower marker array keys' => [
+                $template,
+                [
+                    '###singlemarker1###' => 'Value 1',
+                    '###foo###' => [
+                        [
+                            '###bar###' => [
+                                [
+                                    '###singlemarker2###' => 'Value 2.1'
+                                ],
+                                [
+                                    '###singlemarker2###' => 'Value 2.2'
+                                ]
+                            ],
+                            '###footer###' => [
+                                [
+                                    '###singlemarker3###' => 'Value 3.1'
+                                ],
+                                [
+                                    '###singlemarker3###' => 'Value 3.2'
+                                ]
+                            ]
+                        ]
+                    ]
+                ],
+                '',
+                true,
+                false,
+                $expected
+            ],
+            'Subpart marker with unused markers' => [
+                $template,
+                [
+                    '###FOO###' => [
+                        [
+                            '###BAR###' => [
+                                [
+                                    '###SINGLEMARKER2###' => 'Value 2.1'
+                                ]
+                            ],
+                            '###FOOTER###' => [
+                                [
+                                    '###SINGLEMARKER3###' => 'Value 3.1'
+                                ]
+                            ]
+                        ]
+                    ]
+                ],
+                '',
+                false,
+                true,
+                '
 
 
 Value 2.1
@@ -544,29 +580,29 @@ Value 2.1
 Value 3.1
 
 '
-                       ),
-                       'Subpart marker with empty subpart' => array(
-                               $template,
-                               array(
-                                       '###SINGLEMARKER1###' => 'Value 1',
-                                       '###FOO###' => array(
-                                               array(
-                                                       '###BAR###' => array(
-                                                               array(
-                                                                       '###SINGLEMARKER2###' => 'Value 2.1'
-                                                               ),
-                                                               array(
-                                                                       '###SINGLEMARKER2###' => 'Value 2.2'
-                                                               )
-                                                       ),
-                                                       '###FOOTER###' => array()
-                                               )
-                                       )
-                               ),
-                               '',
-                               FALSE,
-                               FALSE,
-                               'Value 1
+            ],
+            'Subpart marker with empty subpart' => [
+                $template,
+                [
+                    '###SINGLEMARKER1###' => 'Value 1',
+                    '###FOO###' => [
+                        [
+                            '###BAR###' => [
+                                [
+                                    '###SINGLEMARKER2###' => 'Value 2.1'
+                                ],
+                                [
+                                    '###SINGLEMARKER2###' => 'Value 2.2'
+                                ]
+                            ],
+                            '###FOOTER###' => []
+                        ]
+                    ]
+                ],
+                '',
+                false,
+                false,
+                'Value 1
 
 
 Value 2.1
@@ -575,22 +611,139 @@ Value 2.2
 
 
 '
-                       )
-               );
-       }
-
-       /**
-        * @test
-        * @param string $template
-        * @param array $markersAndSubparts
-        * @param string $wrap
-        * @param bool $uppercase
-        * @param bool $deleteUnused
-        * @param string $expected
-        * @dataProvider substituteMarkerAndSubpartArrayRecursiveResolvesMarkersAndSubpartsArrayDataProvider
-        */
-       public function substituteMarkerAndSubpartArrayRecursiveResolvesMarkersAndSubpartsArray($template, $markersAndSubparts, $wrap, $uppercase, $deleteUnused, $expected) {
-               $this->assertSame($expected, $this->templateService->substituteMarkerAndSubpartArrayRecursive($template, $markersAndSubparts, $wrap, $uppercase, $deleteUnused));
-       }
-
-}
\ No newline at end of file
+            ]
+        ];
+    }
+
+    /**
+     * @test
+     * @param string $template
+     * @param array $markersAndSubparts
+     * @param string $wrap
+     * @param bool $uppercase
+     * @param bool $deleteUnused
+     * @param string $expected
+     * @dataProvider substituteMarkerAndSubpartArrayRecursiveResolvesMarkersAndSubpartsArrayDataProvider
+     */
+    public function substituteMarkerAndSubpartArrayRecursiveResolvesMarkersAndSubpartsArray($template, $markersAndSubparts, $wrap, $uppercase, $deleteUnused, $expected)
+    {
+        $this->assertSame($expected, $this->templateService->substituteMarkerAndSubpartArrayRecursive($template, $markersAndSubparts, $wrap, $uppercase, $deleteUnused));
+    }
+
+    /**
+     * @return array
+     */
+    public function substituteMarkerArrayCachedReturnsExpectedContentDataProvider()
+    {
+        return [
+            'no markers defined' => [
+                'dummy content with ###UNREPLACED### marker',
+                [],
+                [],
+                [],
+                'dummy content with ###UNREPLACED### marker',
+            ],
+            'no markers used' => [
+                'dummy content with no marker',
+                [
+                    '###REPLACED###' => '_replaced_'
+                ],
+                [],
+                [],
+                'dummy content with no marker',
+            ],
+            'one marker' => [
+                'dummy content with ###REPLACED### marker',
+                [
+                    '###REPLACED###' => '_replaced_'
+                ],
+                [],
+                [],
+                'dummy content with _replaced_ marker'
+            ],
+            'one marker with lots of chars' => [
+                'dummy content with ###RE.:##-=_()LACED### marker',
+                [
+                    '###RE.:##-=_()LACED###' => '_replaced_'
+                ],
+                [],
+                [],
+                'dummy content with _replaced_ marker'
+            ],
+            'markers which are special' => [
+                'dummy ###aa##.#######A### ######',
+                [
+                    '###aa##.###' => 'content ',
+                    '###A###' => 'is',
+                    '######' => '-is not considered-'
+                ],
+                [],
+                [],
+                'dummy content #is ######'
+            ],
+            'two markers in content, but more defined' => [
+                'dummy ###CONTENT### with ###REPLACED### marker',
+                [
+                    '###REPLACED###' => '_replaced_',
+                    '###CONTENT###' => 'content',
+                    '###NEVERUSED###' => 'bar'
+                ],
+                [],
+                [],
+                'dummy content with _replaced_ marker'
+            ],
+            'one subpart' => [
+                'dummy content with ###ASUBPART### around some text###ASUBPART###.',
+                [],
+                [
+                    '###ASUBPART###' => 'some other text'
+                ],
+                [],
+                'dummy content with some other text.'
+            ],
+            'one wrapped subpart' => [
+                'dummy content with ###AWRAPPEDSUBPART### around some text###AWRAPPEDSUBPART###.',
+                [],
+                [],
+                [
+                    '###AWRAPPEDSUBPART###' => [
+                        'more content',
+                        'content'
+                    ]
+                ],
+                'dummy content with more content around some textcontent.'
+            ],
+            'one subpart with markers, not replaced recursively' => [
+                'dummy ###CONTENT### with ###ASUBPART### around ###SOME### text###ASUBPART###.',
+                [
+                    '###CONTENT###' => 'content',
+                    '###SOME###' => '-this should never make it into output-',
+                    '###OTHER_NOT_REPLACED###' => '-this should never make it into output-'
+                ],
+                [
+                    '###ASUBPART###' => 'some ###OTHER_NOT_REPLACED### text'
+                ],
+                [],
+                'dummy content with some ###OTHER_NOT_REPLACED### text.'
+            ],
+        ];
+    }
+
+    /**
+     * @test
+     * @dataProvider substituteMarkerArrayCachedReturnsExpectedContentDataProvider
+     *
+     * @param string $content
+     * @param array $markContentArray
+     * @param array $subpartContentArray
+     * @param array $wrappedSubpartContentArray
+     * @param string $expectedContent
+     * @param bool $shouldQueryCache
+     * @param bool $shouldStoreCache
+     */
+    public function substituteMarkerArrayCachedReturnsExpectedContent($content, array $markContentArray, array $subpartContentArray, array $wrappedSubpartContentArray, $expectedContent)
+    {
+        $resultContent = $this->templateService->substituteMarkerArrayCached($content, $markContentArray, $subpartContentArray, $wrappedSubpartContentArray);
+        $this->assertSame($expectedContent, $resultContent);
+    }
+}