[!!!][FEATURE] Introduce Backend Routing
[Packages/TYPO3.CMS.git] / typo3 / sysext / extbase / Classes / Mvc / Web / Routing / UriBuilder.php
1 <?php
2 namespace TYPO3\CMS\Extbase\Mvc\Web\Routing;
3
4 /*
5 * This file is part of the TYPO3 CMS project.
6 *
7 * It is free software; you can redistribute it and/or modify it under
8 * the terms of the GNU General Public License, either version 2
9 * of the License, or any later version.
10 *
11 * For the full copyright and license information, please read the
12 * LICENSE.txt file that was distributed with this source code.
13 *
14 * The TYPO3 project - inspiring people to share!
15 */
16
17 use TYPO3\CMS\Backend\Utility\BackendUtility;
18 use TYPO3\CMS\Core\Utility\ArrayUtility;
19 use TYPO3\CMS\Core\Utility\GeneralUtility;
20 use TYPO3\CMS\Extbase\Mvc\Request;
21 use TYPO3\CMS\Extbase\Mvc\Web\Request as WebRequest;
22
23 /**
24 * An URI Builder
25 *
26 * @api
27 */
28 class UriBuilder {
29
30 /**
31 * @var \TYPO3\CMS\Extbase\Configuration\ConfigurationManagerInterface
32 */
33 protected $configurationManager;
34
35 /**
36 * @var \TYPO3\CMS\Extbase\Service\ExtensionService
37 */
38 protected $extensionService;
39
40 /**
41 * An instance of \TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer
42 *
43 * @var \TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer
44 */
45 protected $contentObject;
46
47 /**
48 * @var Request
49 */
50 protected $request;
51
52 /**
53 * @var array
54 */
55 protected $arguments = array();
56
57 /**
58 * Arguments which have been used for building the last URI
59 *
60 * @var array
61 */
62 protected $lastArguments = array();
63
64 /**
65 * @var string
66 */
67 protected $section = '';
68
69 /**
70 * @var bool
71 */
72 protected $createAbsoluteUri = FALSE;
73
74 /**
75 * @var string
76 */
77 protected $absoluteUriScheme = NULL;
78
79 /**
80 * @var bool
81 */
82 protected $addQueryString = FALSE;
83
84 /**
85 * @var string
86 */
87 protected $addQueryStringMethod = NULL;
88
89 /**
90 * @var array
91 */
92 protected $argumentsToBeExcludedFromQueryString = array();
93
94 /**
95 * @var bool
96 */
97 protected $linkAccessRestrictedPages = FALSE;
98
99 /**
100 * @var int
101 */
102 protected $targetPageUid = NULL;
103
104 /**
105 * @var int
106 */
107 protected $targetPageType = 0;
108
109 /**
110 * @var bool
111 */
112 protected $noCache = FALSE;
113
114 /**
115 * @var bool
116 */
117 protected $useCacheHash = TRUE;
118
119 /**
120 * @var string
121 */
122 protected $format = '';
123
124 /**
125 * @var string
126 */
127 protected $argumentPrefix = NULL;
128
129 /**
130 * @var \TYPO3\CMS\Extbase\Service\EnvironmentService
131 */
132 protected $environmentService;
133
134 /**
135 * @param \TYPO3\CMS\Extbase\Configuration\ConfigurationManagerInterface $configurationManager
136 */
137 public function injectConfigurationManager(\TYPO3\CMS\Extbase\Configuration\ConfigurationManagerInterface $configurationManager) {
138 $this->configurationManager = $configurationManager;
139 }
140
141 /**
142 * @param \TYPO3\CMS\Extbase\Service\ExtensionService $extensionService
143 */
144 public function injectExtensionService(\TYPO3\CMS\Extbase\Service\ExtensionService $extensionService) {
145 $this->extensionService = $extensionService;
146 }
147
148 /**
149 * @param \TYPO3\CMS\Extbase\Service\EnvironmentService $environmentService
150 */
151 public function injectEnvironmentService(\TYPO3\CMS\Extbase\Service\EnvironmentService $environmentService) {
152 $this->environmentService = $environmentService;
153 }
154
155 /**
156 * Life-cycle method that is called by the DI container as soon as this object is completely built
157 *
158 * @return void
159 */
160 public function initializeObject() {
161 $this->contentObject = $this->configurationManager->getContentObject();
162 }
163
164 /**
165 * Sets the current request
166 *
167 * @param Request $request
168 * @return \TYPO3\CMS\Extbase\Mvc\Web\Routing\UriBuilder the current UriBuilder to allow method chaining
169 */
170 public function setRequest(Request $request) {
171 $this->request = $request;
172 return $this;
173 }
174
175 /**
176 * @return Request
177 */
178 public function getRequest() {
179 return $this->request;
180 }
181
182 /**
183 * Additional query parameters.
184 * If you want to "prefix" arguments, you can pass in multidimensional arrays:
185 * array('prefix1' => array('foo' => 'bar')) gets "&prefix1[foo]=bar"
186 *
187 * @param array $arguments
188 * @return \TYPO3\CMS\Extbase\Mvc\Web\Routing\UriBuilder the current UriBuilder to allow method chaining
189 * @api
190 */
191 public function setArguments(array $arguments) {
192 $this->arguments = $arguments;
193 return $this;
194 }
195
196 /**
197 * @return array
198 * @api
199 */
200 public function getArguments() {
201 return $this->arguments;
202 }
203
204 /**
205 * If specified, adds a given HTML anchor to the URI (#...)
206 *
207 * @param string $section
208 * @return \TYPO3\CMS\Extbase\Mvc\Web\Routing\UriBuilder the current UriBuilder to allow method chaining
209 * @api
210 */
211 public function setSection($section) {
212 $this->section = $section;
213 return $this;
214 }
215
216 /**
217 * @return string
218 * @api
219 */
220 public function getSection() {
221 return $this->section;
222 }
223
224 /**
225 * Specifies the format of the target (e.g. "html" or "xml")
226 *
227 * @param string $format
228 * @return \TYPO3\CMS\Extbase\Mvc\Web\Routing\UriBuilder the current UriBuilder to allow method chaining
229 * @api
230 */
231 public function setFormat($format) {
232 $this->format = $format;
233 return $this;
234 }
235
236 /**
237 * @return string
238 * @api
239 */
240 public function getFormat() {
241 return $this->format;
242 }
243
244 /**
245 * If set, the URI is prepended with the current base URI. Defaults to FALSE.
246 *
247 * @param bool $createAbsoluteUri
248 * @return \TYPO3\CMS\Extbase\Mvc\Web\Routing\UriBuilder the current UriBuilder to allow method chaining
249 * @api
250 */
251 public function setCreateAbsoluteUri($createAbsoluteUri) {
252 $this->createAbsoluteUri = $createAbsoluteUri;
253 return $this;
254 }
255
256 /**
257 * @return bool
258 * @api
259 */
260 public function getCreateAbsoluteUri() {
261 return $this->createAbsoluteUri;
262 }
263
264 /**
265 * @return string
266 */
267 public function getAbsoluteUriScheme() {
268 return $this->absoluteUriScheme;
269 }
270
271 /**
272 * Sets the scheme that should be used for absolute URIs in FE mode
273 *
274 * @param string $absoluteUriScheme the scheme to be used for absolute URIs
275 * @return \TYPO3\CMS\Extbase\Mvc\Web\Routing\UriBuilder the current UriBuilder to allow method chaining
276 */
277 public function setAbsoluteUriScheme($absoluteUriScheme) {
278 $this->absoluteUriScheme = $absoluteUriScheme;
279 return $this;
280 }
281
282 /**
283 * If set, the current query parameters will be merged with $this->arguments. Defaults to FALSE.
284 *
285 * @param bool $addQueryString
286 * @return \TYPO3\CMS\Extbase\Mvc\Web\Routing\UriBuilder the current UriBuilder to allow method chaining
287 * @api
288 * @see TSref/typolink.addQueryString
289 */
290 public function setAddQueryString($addQueryString) {
291 $this->addQueryString = (bool)$addQueryString;
292 return $this;
293 }
294
295 /**
296 * @return bool
297 * @api
298 */
299 public function getAddQueryString() {
300 return $this->addQueryString;
301 }
302
303 /**
304 * Sets the method to get the addQueryString parameters. Defaults undefined
305 * which results in using QUERY_STRING.
306 *
307 * @param string $addQueryStringMethod
308 * @return \TYPO3\CMS\Extbase\Mvc\Web\Routing\UriBuilder the current UriBuilder to allow method chaining
309 * @api
310 * @see TSref/typolink.addQueryString.method
311 */
312 public function setAddQueryStringMethod($addQueryStringMethod) {
313 $this->addQueryStringMethod = $addQueryStringMethod;
314 return $this;
315 }
316
317 /**
318 * @return string
319 * @api
320 */
321 public function getAddQueryStringMethod() {
322 return (string)$this->addQueryStringMethod;
323 }
324
325 /**
326 * A list of arguments to be excluded from the query parameters
327 * Only active if addQueryString is set
328 *
329 * @param array $argumentsToBeExcludedFromQueryString
330 * @return \TYPO3\CMS\Extbase\Mvc\Web\Routing\UriBuilder the current UriBuilder to allow method chaining
331 * @api
332 * @see TSref/typolink.addQueryString.exclude
333 * @see setAddQueryString()
334 */
335 public function setArgumentsToBeExcludedFromQueryString(array $argumentsToBeExcludedFromQueryString) {
336 $this->argumentsToBeExcludedFromQueryString = $argumentsToBeExcludedFromQueryString;
337 return $this;
338 }
339
340 /**
341 * @return array
342 * @api
343 */
344 public function getArgumentsToBeExcludedFromQueryString() {
345 return $this->argumentsToBeExcludedFromQueryString;
346 }
347
348 /**
349 * Specifies the prefix to be used for all arguments.
350 *
351 * @param string $argumentPrefix
352 * @return \TYPO3\CMS\Extbase\Mvc\Web\Routing\UriBuilder the current UriBuilder to allow method chaining
353 */
354 public function setArgumentPrefix($argumentPrefix) {
355 $this->argumentPrefix = (string)$argumentPrefix;
356 return $this;
357 }
358
359 /**
360 * @return string
361 */
362 public function getArgumentPrefix() {
363 return $this->argumentPrefix;
364 }
365
366 /**
367 * If set, URIs for pages without access permissions will be created
368 *
369 * @param bool $linkAccessRestrictedPages
370 * @return \TYPO3\CMS\Extbase\Mvc\Web\Routing\UriBuilder the current UriBuilder to allow method chaining
371 * @api
372 */
373 public function setLinkAccessRestrictedPages($linkAccessRestrictedPages) {
374 $this->linkAccessRestrictedPages = (bool)$linkAccessRestrictedPages;
375 return $this;
376 }
377
378 /**
379 * @return bool
380 * @api
381 */
382 public function getLinkAccessRestrictedPages() {
383 return $this->linkAccessRestrictedPages;
384 }
385
386 /**
387 * Uid of the target page
388 *
389 * @param int $targetPageUid
390 * @return \TYPO3\CMS\Extbase\Mvc\Web\Routing\UriBuilder the current UriBuilder to allow method chaining
391 * @api
392 */
393 public function setTargetPageUid($targetPageUid) {
394 $this->targetPageUid = $targetPageUid;
395 return $this;
396 }
397
398 /**
399 * returns $this->targetPageUid.
400 *
401 * @return int
402 * @api
403 */
404 public function getTargetPageUid() {
405 return $this->targetPageUid;
406 }
407
408 /**
409 * Sets the page type of the target URI. Defaults to 0
410 *
411 * @param int $targetPageType
412 * @return \TYPO3\CMS\Extbase\Mvc\Web\Routing\UriBuilder the current UriBuilder to allow method chaining
413 * @api
414 */
415 public function setTargetPageType($targetPageType) {
416 $this->targetPageType = (int)$targetPageType;
417 return $this;
418 }
419
420 /**
421 * @return int
422 */
423 public function getTargetPageType() {
424 return $this->targetPageType;
425 }
426
427 /**
428 * by default FALSE; if TRUE, &no_cache=1 will be appended to the URI
429 * This overrules the useCacheHash setting
430 *
431 * @param bool $noCache
432 * @return \TYPO3\CMS\Extbase\Mvc\Web\Routing\UriBuilder the current UriBuilder to allow method chaining
433 * @api
434 */
435 public function setNoCache($noCache) {
436 $this->noCache = (bool)$noCache;
437 return $this;
438 }
439
440 /**
441 * @return bool
442 * @api
443 */
444 public function getNoCache() {
445 return $this->noCache;
446 }
447
448 /**
449 * by default TRUE; if FALSE, no cHash parameter will be appended to the URI
450 * If noCache is set, this setting will be ignored.
451 *
452 * @param bool $useCacheHash
453 * @return \TYPO3\CMS\Extbase\Mvc\Web\Routing\UriBuilder the current UriBuilder to allow method chaining
454 * @api
455 */
456 public function setUseCacheHash($useCacheHash) {
457 $this->useCacheHash = (bool)$useCacheHash;
458 return $this;
459 }
460
461 /**
462 * @return bool
463 * @api
464 */
465 public function getUseCacheHash() {
466 return $this->useCacheHash;
467 }
468
469 /**
470 * Returns the arguments being used for the last URI being built.
471 * This is only set after build() / uriFor() has been called.
472 *
473 * @return array The last arguments
474 */
475 public function getLastArguments() {
476 return $this->lastArguments;
477 }
478
479 /**
480 * Resets all UriBuilder options to their default value
481 *
482 * @return \TYPO3\CMS\Extbase\Mvc\Web\Routing\UriBuilder the current UriBuilder to allow method chaining
483 * @api
484 */
485 public function reset() {
486 $this->arguments = array();
487 $this->section = '';
488 $this->format = '';
489 $this->createAbsoluteUri = FALSE;
490 $this->addQueryString = FALSE;
491 $this->addQueryStringMethod = NULL;
492 $this->argumentsToBeExcludedFromQueryString = array();
493 $this->linkAccessRestrictedPages = FALSE;
494 $this->targetPageUid = NULL;
495 $this->targetPageType = 0;
496 $this->noCache = FALSE;
497 $this->useCacheHash = TRUE;
498 $this->argumentPrefix = NULL;
499 return $this;
500 }
501
502 /**
503 * Creates an URI used for linking to an Extbase action.
504 * Works in Frontend and Backend mode of TYPO3.
505 *
506 * @param string $actionName Name of the action to be called
507 * @param array $controllerArguments Additional query parameters. Will be "namespaced" and merged with $this->arguments.
508 * @param string $controllerName Name of the target controller. If not set, current ControllerName is used.
509 * @param string $extensionName Name of the target extension, without underscores. If not set, current ExtensionName is used.
510 * @param string $pluginName Name of the target plugin. If not set, current PluginName is used.
511 * @return string the rendered URI
512 * @api
513 * @see build()
514 */
515 public function uriFor($actionName = NULL, $controllerArguments = array(), $controllerName = NULL, $extensionName = NULL, $pluginName = NULL) {
516 if ($actionName !== NULL) {
517 $controllerArguments['action'] = $actionName;
518 }
519 if ($controllerName !== NULL) {
520 $controllerArguments['controller'] = $controllerName;
521 } else {
522 $controllerArguments['controller'] = $this->request->getControllerName();
523 }
524 if ($extensionName === NULL) {
525 $extensionName = $this->request->getControllerExtensionName();
526 }
527 if ($pluginName === NULL && $this->environmentService->isEnvironmentInFrontendMode()) {
528 $pluginName = $this->extensionService->getPluginNameByAction($extensionName, $controllerArguments['controller'], $controllerArguments['action']);
529 }
530 if ($pluginName === NULL) {
531 $pluginName = $this->request->getPluginName();
532 }
533
534 $this->disableCacheHashForNonCacheableAction($controllerArguments);
535
536 if ($this->environmentService->isEnvironmentInFrontendMode() && $this->configurationManager->isFeatureEnabled('skipDefaultArguments')) {
537 $controllerArguments = $this->removeDefaultControllerAndAction($controllerArguments, $extensionName, $pluginName);
538 }
539 if ($this->targetPageUid === NULL && $this->environmentService->isEnvironmentInFrontendMode()) {
540 $this->targetPageUid = $this->extensionService->getTargetPidByPlugin($extensionName, $pluginName);
541 }
542 if ($this->format !== '') {
543 $controllerArguments['format'] = $this->format;
544 }
545 if ($this->argumentPrefix !== NULL) {
546 $prefixedControllerArguments = array($this->argumentPrefix => $controllerArguments);
547 } else {
548 $pluginNamespace = $this->extensionService->getPluginNamespace($extensionName, $pluginName);
549 $prefixedControllerArguments = array($pluginNamespace => $controllerArguments);
550 }
551 ArrayUtility::mergeRecursiveWithOverrule($this->arguments, $prefixedControllerArguments);
552 return $this->build();
553 }
554
555 /**
556 * Disable cache hash if the action is not cacheable
557 * and pointed to from an already uncached request
558 *
559 * @param array $controllerArguments the current controller arguments
560 * @return void
561 */
562 protected function disableCacheHashForNonCacheableAction(array $controllerArguments) {
563 if (isset($controllerArguments['action']) && $this->getUseCacheHash()) {
564 $actionIsCacheable = $this->extensionService->isActionCacheable(
565 NULL,
566 NULL,
567 $controllerArguments['controller'],
568 $controllerArguments['action']
569 );
570 $isRequestCached = $this->request instanceof WebRequest && $this->request->isCached();
571 $this->setUseCacheHash($isRequestCached || $actionIsCacheable);
572 }
573 }
574
575 /**
576 * This removes controller and/or action arguments from given controllerArguments
577 * if they are equal to the default controller/action of the target plugin.
578 * Note: This is only active in FE mode and if feature "skipDefaultArguments" is enabled
579 *
580 * @see \TYPO3\CMS\Extbase\Configuration\ConfigurationManagerInterface::isFeatureEnabled()
581 * @param array $controllerArguments the current controller arguments to be modified
582 * @param string $extensionName target extension name
583 * @param string $pluginName target plugin name
584 * @return array
585 */
586 protected function removeDefaultControllerAndAction(array $controllerArguments, $extensionName, $pluginName) {
587 $defaultControllerName = $this->extensionService->getDefaultControllerNameByPlugin($extensionName, $pluginName);
588 if (isset($controllerArguments['action'])) {
589 $defaultActionName = $this->extensionService->getDefaultActionNameByPluginAndController($extensionName, $pluginName, $controllerArguments['controller']);
590 if ($controllerArguments['action'] === $defaultActionName) {
591 unset($controllerArguments['action']);
592 }
593 }
594 if ($controllerArguments['controller'] === $defaultControllerName) {
595 unset($controllerArguments['controller']);
596 }
597 return $controllerArguments;
598 }
599
600 /**
601 * Builds the URI
602 * Depending on the current context this calls buildBackendUri() or buildFrontendUri()
603 *
604 * @return string The URI
605 * @api
606 * @see buildBackendUri()
607 * @see buildFrontendUri()
608 */
609 public function build() {
610 if ($this->environmentService->isEnvironmentInBackendMode()) {
611 return $this->buildBackendUri();
612 } else {
613 return $this->buildFrontendUri();
614 }
615 }
616
617 /**
618 * Builds the URI, backend flavour
619 * The resulting URI is relative and starts with "index.php".
620 * The settings pageUid, pageType, noCache, useCacheHash & linkAccessRestrictedPages
621 * will be ignored in the backend.
622 *
623 * @return string The URI
624 */
625 public function buildBackendUri() {
626 if ($this->addQueryString === TRUE) {
627 if ($this->addQueryStringMethod) {
628 switch ($this->addQueryStringMethod) {
629 case 'GET':
630 $arguments = GeneralUtility::_GET();
631 break;
632 case 'POST':
633 $arguments = GeneralUtility::_POST();
634 break;
635 case 'GET,POST':
636 $arguments = array_replace_recursive(GeneralUtility::_GET(), GeneralUtility::_POST());
637 break;
638 case 'POST,GET':
639 $arguments = array_replace_recursive(GeneralUtility::_POST(), GeneralUtility::_GET());
640 break;
641 default:
642 $arguments = GeneralUtility::explodeUrl2Array(GeneralUtility::getIndpEnv('QUERY_STRING'), TRUE);
643 }
644 } else {
645 $arguments = GeneralUtility::_GET();
646 }
647 foreach ($this->argumentsToBeExcludedFromQueryString as $argumentToBeExcluded) {
648 $argumentToBeExcluded = GeneralUtility::explodeUrl2Array($argumentToBeExcluded, TRUE);
649 $arguments = ArrayUtility::arrayDiffAssocRecursive($arguments, $argumentToBeExcluded);
650 }
651 } else {
652 $arguments = array(
653 'M' => GeneralUtility::_GP('M'),
654 'id' => GeneralUtility::_GP('id')
655 );
656 }
657 ArrayUtility::mergeRecursiveWithOverrule($arguments, $this->arguments);
658 $arguments = $this->convertDomainObjectsToIdentityArrays($arguments);
659 $this->lastArguments = $arguments;
660 $moduleName = $arguments['M'];
661 unset($arguments['M'], $arguments['moduleToken']);
662 $backendUriBuilder = GeneralUtility::makeInstance(\TYPO3\CMS\Backend\Routing\UriBuilder::class);
663 if ($this->request instanceof WebRequest && $this->createAbsoluteUri) {
664 $uri = (string)$backendUriBuilder->buildUriFromModule($moduleName, $arguments, \TYPO3\CMS\Backend\Routing\UriBuilder::ABSOLUTE_URL);
665 } else {
666 $uri = (string)$backendUriBuilder->buildUriFromModule($moduleName, $arguments);
667 }
668 if ($this->section !== '') {
669 $uri .= '#' . $this->section;
670 }
671 return $uri;
672 }
673
674 /**
675 * Builds the URI, frontend flavour
676 *
677 * @return string The URI
678 * @see buildTypolinkConfiguration()
679 */
680 public function buildFrontendUri() {
681 $typolinkConfiguration = $this->buildTypolinkConfiguration();
682 if ($this->createAbsoluteUri === TRUE) {
683 $typolinkConfiguration['forceAbsoluteUrl'] = TRUE;
684 if ($this->absoluteUriScheme !== NULL) {
685 $typolinkConfiguration['forceAbsoluteUrl.']['scheme'] = $this->absoluteUriScheme;
686 }
687 }
688 $uri = $this->contentObject->typoLink_URL($typolinkConfiguration);
689 return $uri;
690 }
691
692 /**
693 * Builds a TypoLink configuration array from the current settings
694 *
695 * @return array typolink configuration array
696 * @see TSref/typolink
697 */
698 protected function buildTypolinkConfiguration() {
699 $typolinkConfiguration = array();
700 $typolinkConfiguration['parameter'] = $this->targetPageUid !== NULL ? $this->targetPageUid : $GLOBALS['TSFE']->id;
701 if ($this->targetPageType !== 0) {
702 $typolinkConfiguration['parameter'] .= ',' . $this->targetPageType;
703 } elseif ($this->format !== '') {
704 $targetPageType = $this->extensionService->getTargetPageTypeByFormat($this->request->getControllerExtensionName(), $this->format);
705 $typolinkConfiguration['parameter'] .= ',' . $targetPageType;
706 }
707 if (!empty($this->arguments)) {
708 $arguments = $this->convertDomainObjectsToIdentityArrays($this->arguments);
709 $this->lastArguments = $arguments;
710 $typolinkConfiguration['additionalParams'] = GeneralUtility::implodeArrayForUrl(NULL, $arguments);
711 }
712 if ($this->addQueryString === TRUE) {
713 $typolinkConfiguration['addQueryString'] = 1;
714 if (!empty($this->argumentsToBeExcludedFromQueryString)) {
715 $typolinkConfiguration['addQueryString.'] = array(
716 'exclude' => implode(',', $this->argumentsToBeExcludedFromQueryString)
717 );
718 }
719 if ($this->addQueryStringMethod) {
720 $typolinkConfiguration['addQueryString.']['method'] = $this->addQueryStringMethod;
721 }
722 }
723 if ($this->noCache === TRUE) {
724 $typolinkConfiguration['no_cache'] = 1;
725 } elseif ($this->useCacheHash) {
726 $typolinkConfiguration['useCacheHash'] = 1;
727 }
728 if ($this->section !== '') {
729 $typolinkConfiguration['section'] = $this->section;
730 }
731 if ($this->linkAccessRestrictedPages === TRUE) {
732 $typolinkConfiguration['linkAccessRestrictedPages'] = 1;
733 }
734 return $typolinkConfiguration;
735 }
736
737 /**
738 * Recursively iterates through the specified arguments and turns instances of type \TYPO3\CMS\Extbase\DomainObject\AbstractEntity
739 * into an arrays containing the uid of the domain object.
740 *
741 * @param array $arguments The arguments to be iterated
742 * @throws \TYPO3\CMS\Extbase\Mvc\Exception\InvalidArgumentValueException
743 * @return array The modified arguments array
744 */
745 protected function convertDomainObjectsToIdentityArrays(array $arguments) {
746 foreach ($arguments as $argumentKey => $argumentValue) {
747 // if we have a LazyLoadingProxy here, make sure to get the real instance for further processing
748 if ($argumentValue instanceof \TYPO3\CMS\Extbase\Persistence\Generic\LazyLoadingProxy) {
749 $argumentValue = $argumentValue->_loadRealInstance();
750 // also update the value in the arguments array, because the lazyLoaded object could be
751 // hidden and thus the $argumentValue would be NULL.
752 $arguments[$argumentKey] = $argumentValue;
753 }
754 if ($argumentValue instanceof \TYPO3\CMS\Extbase\DomainObject\AbstractDomainObject) {
755 if ($argumentValue->getUid() !== NULL) {
756 $arguments[$argumentKey] = $argumentValue->getUid();
757 } elseif ($argumentValue instanceof \TYPO3\CMS\Extbase\DomainObject\AbstractValueObject) {
758 $arguments[$argumentKey] = $this->convertTransientObjectToArray($argumentValue);
759 } else {
760 throw new \TYPO3\CMS\Extbase\Mvc\Exception\InvalidArgumentValueException('Could not serialize Domain Object ' . get_class($argumentValue) . '. It is neither an Entity with identity properties set, nor a Value Object.', 1260881688);
761 }
762 } elseif (is_array($argumentValue)) {
763 $arguments[$argumentKey] = $this->convertDomainObjectsToIdentityArrays($argumentValue);
764 }
765 }
766 return $arguments;
767 }
768
769 /**
770 * Converts a given object recursively into an array.
771 *
772 * @param \TYPO3\CMS\Extbase\DomainObject\AbstractDomainObject $object
773 * @return array
774 * @todo Refactore this into convertDomainObjectsToIdentityArrays()
775 */
776 public function convertTransientObjectToArray(\TYPO3\CMS\Extbase\DomainObject\AbstractDomainObject $object) {
777 $result = array();
778 foreach ($object->_getProperties() as $propertyName => $propertyValue) {
779 if ($propertyValue instanceof \TYPO3\CMS\Extbase\DomainObject\AbstractDomainObject) {
780 if ($propertyValue->getUid() !== NULL) {
781 $result[$propertyName] = $propertyValue->getUid();
782 } else {
783 $result[$propertyName] = $this->convertTransientObjectToArray($propertyValue);
784 }
785 } elseif (is_array($propertyValue)) {
786 $result[$propertyName] = $this->convertDomainObjectsToIdentityArrays($propertyValue);
787 } else {
788 $result[$propertyName] = $propertyValue;
789 }
790 }
791 return $result;
792 }
793
794 }