PageRenderTime 27ms CodeModel.GetById 13ms RepoModel.GetById 0ms app.codeStats 0ms

/Classes/Components/DceContainer/ContainerFactory.php

https://bitbucket.org/jurajsulek/dce
PHP | 224 lines | 150 code | 20 blank | 54 comment | 13 complexity | 42df23ac5932607c4806da9a3ce23aa7 MD5 | raw file
  1. <?php
  2. namespace ArminVieweg\Dce\Components\DceContainer;
  3. /* | This extension is made for TYPO3 CMS and is licensed
  4. * | under GNU General Public License.
  5. * |
  6. * | (c) 2012-2018 Armin Ruediger Vieweg <armin@v.ieweg.de>
  7. */
  8. use ArminVieweg\Dce\Domain\Model\Dce;
  9. use ArminVieweg\Dce\Utility\DatabaseUtility;
  10. use TYPO3\CMS\Core\Utility\GeneralUtility;
  11. /**
  12. * ContainerFactory
  13. * Builds DceContainers, which wrap grouped DCEs
  14. *
  15. * @package ArminVieweg\Dce
  16. */
  17. class ContainerFactory
  18. {
  19. /**
  20. * Contains uids of content elements which can be skipped
  21. *
  22. * @var array
  23. */
  24. protected static $contentElementsToSkip = [];
  25. /**
  26. * @param Dce $dce
  27. * @return Container
  28. */
  29. public static function makeContainer(Dce $dce)
  30. {
  31. $contentObject = $dce->getContentObject();
  32. static::$contentElementsToSkip[] = $contentObject['uid'];
  33. /** @var Container $container */
  34. $container = GeneralUtility::makeInstance(
  35. 'ArminVieweg\Dce\Components\DceContainer\Container',
  36. $dce
  37. );
  38. $contentElements = static::getContentElementsInContainer($dce);
  39. $total = count($contentElements);
  40. foreach ($contentElements as $index => $contentElement) {
  41. try {
  42. /** @var \ArminVieweg\Dce\Domain\Model\Dce $dce */
  43. $dceInstance = clone \ArminVieweg\Dce\Utility\Extbase::bootstrapControllerAction(
  44. 'ArminVieweg',
  45. 'Dce',
  46. 'Dce',
  47. 'renderDce',
  48. 'Dce',
  49. [
  50. 'contentElementUid' => $contentElement['uid'],
  51. 'dceUid' => $dce->getUid()
  52. ],
  53. true
  54. );
  55. } catch (\Exception $exception) {
  56. continue;
  57. }
  58. $dceInstance->setContainerIterator(static::createContainerIteratorArray($index, $total));
  59. $container->addDce($dceInstance);
  60. if (!in_array($contentElement['uid'], static::$contentElementsToSkip)) {
  61. static::$contentElementsToSkip[] = $contentElement['uid'];
  62. }
  63. if (!empty($contentElement['l18n_parent']) &&
  64. !in_array($contentElement['l18n_parent'], static::$contentElementsToSkip)
  65. ) {
  66. static::$contentElementsToSkip[] = $contentElement['l18n_parent'];
  67. }
  68. if (!empty($contentElement['_LOCALIZED_UID']) &&
  69. !in_array($contentElement['_LOCALIZED_UID'], static::$contentElementsToSkip)
  70. ) {
  71. static::$contentElementsToSkip[] = $contentElement['_LOCALIZED_UID'];
  72. }
  73. }
  74. return $container;
  75. }
  76. /**
  77. * Get content elements rows of following content elements in current row
  78. *
  79. * @param Dce $dce
  80. * @return array
  81. */
  82. protected static function getContentElementsInContainer(Dce $dce)
  83. {
  84. $contentObject = $dce->getContentObject();
  85. $sortColumn = $GLOBALS['TCA']['tt_content']['ctrl']['sortby'];
  86. $where = 'pid = ' . $contentObject['pid'] .
  87. ' AND colPos = ' . $contentObject['colPos'] .
  88. ' AND ' . $sortColumn . ' > ' . $contentObject[$sortColumn] .
  89. ' AND uid != ' . $contentObject['uid'];
  90. if (TYPO3_MODE === 'FE') {
  91. $where .= ' AND sys_language_uid = ' . $GLOBALS['TSFE']->sys_language_uid;
  92. $where .= DatabaseUtility::getEnabledFields('tt_content');
  93. } else {
  94. $where .= \TYPO3\CMS\Backend\Utility\BackendUtility::deleteClause('tt_content');
  95. }
  96. if (\TYPO3\CMS\Core\Utility\ExtensionManagementUtility::isLoaded('gridelements')
  97. && $contentObject['tx_gridelements_container'] != '0'
  98. ) {
  99. $where .= ' AND tx_gridelements_container = ' . $contentObject['tx_gridelements_container'];
  100. }
  101. if (TYPO3_MODE === 'FE') {
  102. $where .= ' AND sys_language_uid = ' . $GLOBALS['TSFE']->sys_language_uid;
  103. }
  104. $rawContentElements = DatabaseUtility::getDatabaseConnection()->exec_SELECTgetRows(
  105. '*',
  106. 'tt_content',
  107. $where,
  108. '',
  109. $sortColumn . ' asc',
  110. $dce->getContainerItemLimit() ? $dce->getContainerItemLimit() - 1 : ''
  111. );
  112. array_unshift($rawContentElements, $contentObject);
  113. $resolvedContentElements = static::resolveShortcutElements($rawContentElements);
  114. $contentElementsInContainer = [];
  115. foreach ($resolvedContentElements as $rawContentElement) {
  116. if ($rawContentElement['CType'] !== 'dce_dceuid' . $dce->getUid() ||
  117. ($contentObject['uid'] !== $rawContentElement['uid'] &&
  118. $rawContentElement['tx_dce_new_container'] === '1')
  119. ) {
  120. return $contentElementsInContainer;
  121. }
  122. $contentElementsInContainer[] = $rawContentElement;
  123. }
  124. return $contentElementsInContainer;
  125. }
  126. /**
  127. * Checks if DCE content element should be skipped instead of rendered.
  128. *
  129. * @param array|int $contentElement
  130. * @return bool Returns true when this content element has been rendered already
  131. */
  132. public static function checkContentElementForBeingRendered($contentElement)
  133. {
  134. if (is_array($contentElement)) {
  135. return in_array($contentElement['uid'], static::$contentElementsToSkip);
  136. } elseif (is_integer($contentElement)) {
  137. return in_array($contentElement, static::$contentElementsToSkip);
  138. }
  139. return false;
  140. }
  141. /**
  142. * Clears the content elements to skip. This might be necessary if one page
  143. * should render the same content element twice (using reference e.g.).
  144. *
  145. * @return void
  146. */
  147. public static function clearContentElementsToSkip()
  148. {
  149. static::$contentElementsToSkip = [];
  150. }
  151. /**
  152. * Resolves CType="shortcut" content elements
  153. *
  154. * @param array $rawContentElements array with tt_content rows
  155. * @return array
  156. */
  157. protected static function resolveShortcutElements(array $rawContentElements)
  158. {
  159. $resolvedContentElements = [];
  160. foreach ($rawContentElements as $rawContentElement) {
  161. if ($rawContentElement['CType'] === 'shortcut') {
  162. // resolve records stored with "table_name:uid"
  163. $aLinked = explode(",", $rawContentElement['records']);
  164. foreach ($aLinked as $sLinkedEl) {
  165. $iPos = strrpos($sLinkedEl, "_");
  166. $table = ($iPos !== false) ? substr($sLinkedEl, 0, $iPos) : 'tt_content';
  167. $uid = ($iPos !== false) ? substr($sLinkedEl, $iPos + 1) : '0';
  168. $linkedContentElements = DatabaseUtility::getDatabaseConnection()->exec_SELECTgetRows(
  169. '*',
  170. $table,
  171. 'uid = ' . $uid,
  172. '',
  173. $GLOBALS['TCA'][$table]['ctrl']['sortby'] . ' asc'
  174. );
  175. foreach ($linkedContentElements as $linkedContentElement) {
  176. $resolvedContentElements[] = $linkedContentElement;
  177. }
  178. }
  179. } else {
  180. $resolvedContentElements[] = $rawContentElement;
  181. }
  182. }
  183. return $resolvedContentElements;
  184. }
  185. /**
  186. * Creates iteration array, like fluid's ForViewHelper does.
  187. *
  188. * @param int $index starting with 0
  189. * @param int $total total amount of DCEs in container
  190. * @return array
  191. */
  192. protected static function createContainerIteratorArray($index, $total)
  193. {
  194. return [
  195. 'isOdd' => $index % 2 === 0,
  196. 'isEven' => $index % 2 !== 0,
  197. 'isFirst' => $index === 0,
  198. 'isLast' => $index === $total - 1,
  199. 'cycle' => $index + 1,
  200. 'index' => $index,
  201. 'total' => $total
  202. ];
  203. }
  204. }