CObjectViewHelper.php 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165
  1. <?php
  2. namespace Opentalent\OtTemplating\ViewHelpers;
  3. use TYPO3\CMS\Core\Utility\GeneralUtility;
  4. use TYPO3\CMS\Extbase\Configuration\ConfigurationManagerInterface;
  5. use TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController;
  6. use TYPO3Fluid\Fluid\Core\Rendering\RenderingContextInterface;
  7. use TYPO3Fluid\Fluid\Core\ViewHelper\Exception;
  8. /**
  9. * This view helper is a wrapper for the Fluid/CObjectViewhelper class
  10. * that allow to override the TS setup of the object by given variables
  11. *
  12. * It accepts the same arguments as \TYPO3\CMS\Fluid\ViewHelpers\CObjectViewHelper,
  13. * and an additional argument 'settings'
  14. *
  15. * @see https://docs.typo3.org/p/georgringer/news/master/en-us/Introduction/Index.html
  16. *
  17. * example:
  18. *
  19. * {namespace ot=Opentalent\OtTemplating\ViewHelpers}
  20. *
  21. * <ot:cObject typoscriptObjectPath="lib.tx_ottemplating.widgets.news_list"
  22. * settings="{'settings.defaultPageUid': 1}" />
  23. *
  24. *
  25. * @package Opentalent\OtTemplating\ViewHelpers
  26. */
  27. class CObjectViewHelper extends \TYPO3\CMS\Fluid\ViewHelpers\CObjectViewHelper {
  28. /**
  29. * Initialize arguments.
  30. *
  31. * @throws Exception
  32. */
  33. public function initializeArguments()
  34. {
  35. parent::initializeArguments();
  36. $this->registerArgument(
  37. 'settings',
  38. 'array',
  39. 'For each key in this array, the setup entry will be replaced by the corresponding value',
  40. false,
  41. []
  42. );
  43. }
  44. /**
  45. * <!> This is a copy/paste of the parent method, slighly modified
  46. * to override the $setup variable with the 'settings' argument
  47. *
  48. * Renders the TypoScript object in the given TypoScript setup path.
  49. *
  50. * @param array $arguments
  51. * @param \Closure $renderChildrenClosure
  52. * @param RenderingContextInterface $renderingContext
  53. * @return mixed
  54. * @throws Exception
  55. */
  56. public static function renderStatic(array $arguments, \Closure $renderChildrenClosure, RenderingContextInterface $renderingContext)
  57. {
  58. $data = $renderChildrenClosure();
  59. $typoscriptObjectPath = $arguments['typoscriptObjectPath'];
  60. $currentValueKey = $arguments['currentValueKey'];
  61. $table = $arguments['table'];
  62. $contentObjectRenderer = static::getContentObjectRenderer();
  63. if (!isset($GLOBALS['TSFE']) || !($GLOBALS['TSFE'] instanceof TypoScriptFrontendController)) {
  64. static::simulateFrontendEnvironment();
  65. }
  66. $currentValue = null;
  67. if (is_object($data)) {
  68. $data = \TYPO3\CMS\Extbase\Reflection\ObjectAccess::getGettableProperties($data);
  69. } elseif (is_string($data) || is_numeric($data)) {
  70. $currentValue = (string)$data;
  71. $data = [$data];
  72. }
  73. $contentObjectRenderer->start($data, $table);
  74. if ($currentValue !== null) {
  75. $contentObjectRenderer->setCurrentVal($currentValue);
  76. } elseif ($currentValueKey !== null && isset($data[$currentValueKey])) {
  77. $contentObjectRenderer->setCurrentVal($data[$currentValueKey]);
  78. }
  79. $pathSegments = GeneralUtility::trimExplode('.', $typoscriptObjectPath);
  80. $lastSegment = array_pop($pathSegments);
  81. $setup = static::getConfigurationManager()->getConfiguration(ConfigurationManagerInterface::CONFIGURATION_TYPE_FULL_TYPOSCRIPT);
  82. foreach ($pathSegments as $segment) {
  83. if (!array_key_exists($segment . '.', $setup)) {
  84. throw new Exception(
  85. 'TypoScript object path "' . $typoscriptObjectPath . '" does not exist',
  86. 1253191023
  87. );
  88. }
  89. $setup = $setup[$segment . '.'];
  90. }
  91. if (!isset($setup[$lastSegment])) {
  92. throw new Exception(
  93. 'No Content Object definition found at TypoScript object path "' . $typoscriptObjectPath . '"',
  94. 1540246570
  95. );
  96. }
  97. // <---- Added by Opentalent to override the TS setup
  98. $setup = self::evalConfiguration($setup, $lastSegment, $arguments['settings']);
  99. // ----->
  100. $content = self::renderContentObject($contentObjectRenderer, $setup, $typoscriptObjectPath, $lastSegment);
  101. if (!isset($GLOBALS['TSFE']) || !($GLOBALS['TSFE'] instanceof TypoScriptFrontendController)) {
  102. static::resetFrontendEnvironment();
  103. }
  104. return $content;
  105. }
  106. /**
  107. * Recursively replace any {$var} value in the given configuration
  108. * if 'var' is a key in the 'overrideSetup' array
  109. *
  110. * @param array $setup
  111. * @param string $entry_name
  112. * @param array $override_settings
  113. * @return array
  114. */
  115. private static function evalConfiguration(array $setup, string $entry_name, array $override_settings) {
  116. $entry_setup = $setup[$entry_name . '.'];
  117. foreach ($override_settings as $key => $val) {
  118. $override = [];
  119. $path = explode('.', $key);
  120. foreach (array_reverse($path) as $i => $segment) {
  121. if ($i == 0) {
  122. $override[$segment] = $val;
  123. } else {
  124. $override = [$segment . '.' => $override];
  125. }
  126. }
  127. $entry_setup = self::merge($entry_setup, $override);
  128. }
  129. $setup[$entry_name . '.'] = $entry_setup;
  130. return $setup;
  131. }
  132. /**
  133. * Similar to array_merge_recursive, except that the end nodes of the
  134. * base array is replaced and not merged.
  135. *
  136. * @param $base_array
  137. * @param $override
  138. * @return mixed
  139. */
  140. private static function merge($base_array, $override) {
  141. foreach ($base_array as $key => $val) {
  142. if (!isset($override[$key])) {
  143. continue;
  144. }
  145. if (is_array($val)) {
  146. $base_array[$key] = self::merge($val, $override[$key]);
  147. } else {
  148. $base_array[$key] = $override[$key];
  149. }
  150. }
  151. return $base_array;
  152. }
  153. }