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