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