[TASK] Add framework for frontend rendering functional tests
[Packages/TYPO3.CMS.git] / typo3 / sysext / core / Tests / Functional / Framework / Frontend / Hook / ContentObjectRendererWatcher.php
1 <?php
2 namespace TYPO3\CMS\Core\Tests\Functional\Framework\Frontend\Hook;
3
4 /***************************************************************
5 * Copyright notice
6 *
7 * (c) 2014 Oliver Hader <oliver.hader@typo3.org>
8 * All rights reserved
9 *
10 * This script is part of the TYPO3 project. The TYPO3 project is
11 * free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2 of the License, or
14 * (at your option) any later version.
15 *
16 * The GNU General Public License can be found at
17 * http://www.gnu.org/copyleft/gpl.html.
18 *
19 * This script is distributed in the hope that it will be useful,
20 * but WITHOUT ANY WARRANTY; without even the implied warranty of
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 * GNU General Public License for more details.
23 *
24 * This copyright notice MUST APPEAR in all copies of the script!
25 ***************************************************************/
26
27 use TYPO3\CMS\Core\Tests\Functional\Framework\Frontend\RenderLevel;
28 use TYPO3\CMS\Core\Tests\Functional\Framework\Frontend\RenderElement;
29
30 /**
31 * Watcher for the content object rendering process
32 */
33 class ContentObjectRendererWatcher implements \TYPO3\CMS\Frontend\ContentObject\ContentObjectPostInitHookInterface, \TYPO3\CMS\Core\SingletonInterface {
34
35 /**
36 * @var RenderLevel
37 */
38 protected $renderLevel;
39
40 /**
41 * @var RenderElement
42 */
43 protected $nextParentRenderElement;
44
45 /**
46 * @var array
47 */
48 protected $nextParentConfiguration;
49
50 /**
51 * Holds parent objects (cObj) locally
52 * to avoid spl_object_hash() reassignments.
53 *
54 * @var array
55 */
56 protected $localParentObjects = array();
57
58 /**
59 * @param string $name
60 * @param NULL|array $configuration
61 * @param string $typoScriptKey
62 * @param \TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer $parentObject
63 * @return string
64 */
65 public function cObjGetSingleExt($name, $configuration, $typoScriptKey, \TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer $parentObject) {
66 $this->localParentObjects[] = $parentObject;
67 $this->nextParentRenderElement = NULL;
68 $this->nextParentConfiguration = NULL;
69
70 if (($foundRenderElement = $this->renderLevel->findRenderElement($parentObject)) !== NULL) {
71 $this->nextParentRenderElement = $foundRenderElement;
72 $this->nextParentConfiguration = $configuration;
73 if (!empty($configuration['table'])) {
74 $this->nextParentRenderElement->addExpectedTableName($configuration['table']);
75 }
76 }
77
78 $contentObject = $parentObject->getContentObject($name);
79 if ($contentObject) {
80 $contentObject->render($configuration);
81 }
82
83 return '';
84 }
85
86 /**
87 * Hook for post processing the initialization of ContentObjectRenderer
88 *
89 * @param \TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer $parentObject Parent content object
90 */
91 public function postProcessContentObjectInitialization(\TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer &$parentObject) {
92 $this->localParentObjects[] = $parentObject;
93
94 if (!isset($this->renderLevel)) {
95 $this->renderLevel = RenderLevel::create($parentObject);
96 $this->renderLevel->add($parentObject);
97 } elseif (($foundRenderLevel = $this->renderLevel->findRenderLevel($parentObject)) !== NULL) {
98 $foundRenderLevel->add($parentObject);
99 } elseif ($this->nextParentRenderElement !== NULL) {
100 $level = $this->nextParentRenderElement->add($parentObject);
101 $level->add($parentObject);
102 if (!empty($this->nextParentConfiguration['watcher.']['parentRecordField'])) {
103 $level->setParentRecordField($this->nextParentConfiguration['watcher.']['parentRecordField']);
104 }
105 $this->nextParentRenderElement = NULL;
106 $this->nextParentConfiguration = NULL;
107 }
108 }
109
110 /**
111 * @param string $query
112 * @param string $fromTable
113 */
114 public function addQuery($query, $fromTable) {
115 if ($this->nextParentRenderElement === NULL) {
116 return;
117 }
118
119 $this->nextParentRenderElement->addQuery($query, $fromTable);
120 }
121
122 /**
123 * @param array $parameters
124 * @param \TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController $frontendController
125 */
126 public function show(array $parameters, \TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController $frontendController) {
127 if (!isset($this->renderLevel) || empty($parameters['enableOutput']) || !empty($frontendController->content)) {
128 return;
129 }
130
131 $tableFields = NULL;
132 if (!empty($this->getFrontendController()->tmpl->setup['watcher.']['tableFields.'])) {
133 $tableFields = $this->getFrontendController()->tmpl->setup['watcher.']['tableFields.'];
134 foreach ($tableFields as &$fieldList) {
135 $fieldList = \TYPO3\CMS\Core\Utility\GeneralUtility::trimExplode(',', $fieldList, TRUE);
136 }
137 unset($fieldList);
138 }
139
140 $structureData = $this->renderLevel->structureData($tableFields);
141
142 $result = array(
143 'structure' => $structureData,
144 'structurePaths' => $this->getStructurePaths($structureData),
145 'records' => $this->renderLevel->mergeData($tableFields),
146 'queries' => $this->renderLevel->mergeQueries(),
147 );
148
149 $frontendController->content = json_encode($result);
150 }
151
152 /**
153 * @param array $structureData
154 * @param array $currentStructurePaths
155 * @return array
156 */
157 protected function getStructurePaths(array $structureData, array $currentStructurePaths = array()) {
158 $structurePaths = array();
159
160 foreach ($structureData as $recordIdentifier => $recordData) {
161 $structurePaths[$recordIdentifier][] = $currentStructurePaths;
162 foreach ($recordData as $fieldName => $fieldValue) {
163 if (!is_array($fieldValue)) {
164 continue;
165 }
166
167 $nestedStructurePaths = $this->getStructurePaths(
168 $fieldValue,
169 array_merge($currentStructurePaths, array($recordIdentifier, $fieldName))
170 );
171
172 foreach ($nestedStructurePaths as $nestedRecordIdentifier => $nestedStructurePathDetails) {
173 $structurePaths[$nestedRecordIdentifier] = array_merge(
174 (array)$structurePaths[$nestedRecordIdentifier],
175 $nestedStructurePathDetails
176 );
177 }
178 }
179 }
180
181 return $structurePaths;
182 }
183
184 /**
185 * @return \TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController
186 */
187 protected function getFrontendController() {
188 return $GLOBALS['TSFE'];
189 }
190
191 }