Raised DBAL version from 1.1.5 to 1.1.6
[Packages/TYPO3.CMS.git] / typo3 / sysext / extbase / Classes / MVC / Web / Routing / UriBuilder.php
1 <?php
2 /* *
3 * This script is part of the TYPO3 project - inspiring people to share! *
4 * *
5 * TYPO3 is free software; you can redistribute it and/or modify it under *
6 * the terms of the GNU General Public License version 2 as published by *
7 * the Free Software Foundation. *
8 * *
9 * This script is distributed in the hope that it will be useful, but *
10 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHAN- *
11 * TABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General *
12 * Public License for more details. *
13 * */
14
15 /**
16 * An URI Builder
17 *
18 * @package Extbase
19 * @subpackage MVC\Web\Routing
20 * @version $Id: UriBuilder.php 2184 2010-04-08 14:59:58Z jocrau $
21 * @api
22 */
23 class Tx_Extbase_MVC_Web_Routing_UriBuilder {
24
25 /**
26 * An instance of tslib_cObj
27 *
28 * @var tslib_cObj
29 */
30 protected $contentObject;
31
32 /**
33 * @var Tx_Extbase_MVC_Web_Request
34 */
35 protected $request;
36
37 /**
38 * @var array
39 */
40 protected $arguments = array();
41
42 /**
43 * Arguments which have been used for building the last URI
44 * @var array
45 */
46 protected $lastArguments = array();
47
48 /**
49 * @var string
50 */
51 protected $section = '';
52
53 /**
54 * @var boolean
55 */
56 protected $createAbsoluteUri = FALSE;
57
58 /**
59 * @var boolean
60 */
61 protected $addQueryString = FALSE;
62
63 /**
64 * @var array
65 */
66 protected $argumentsToBeExcludedFromQueryString = array();
67
68 /**
69 * @var boolean
70 */
71 protected $linkAccessRestrictedPages = FALSE;
72
73 /**
74 * @var integer
75 */
76 protected $targetPageUid = NULL;
77
78 /**
79 * @var integer
80 */
81 protected $targetPageType = 0;
82
83 /**
84 * @var boolean
85 */
86 protected $noCache = FALSE;
87
88 /**
89 * @var boolean
90 */
91 protected $useCacheHash = TRUE;
92
93 /**
94 * @var string
95 */
96 protected $format = '';
97
98 /**
99 * Constructs this URI Helper
100 *
101 * @param tslib_cObj $contentObject
102 */
103 public function __construct(tslib_cObj $contentObject = NULL) {
104 $this->contentObject = $contentObject !== NULL ? $contentObject : t3lib_div::makeInstance('tslib_cObj');
105 }
106
107 /**
108 * Sets the current request
109 *
110 * @param Tx_Extbase_MVC_Web_Request $request
111 * @return Tx_Extbase_MVC_Web_Routing_UriBuilder the current UriBuilder to allow method chaining
112 */
113 public function setRequest(Tx_Extbase_MVC_Web_Request $request) {
114 $this->request = $request;
115 return $this;
116 }
117
118 /**
119 * @return Tx_Extbase_MVC_Web_Request
120 */
121 public function getRequest() {
122 return $this->request;
123 }
124
125 /**
126 * Additional query parameters.
127 * If you want to "prefix" arguments, you can pass in multidimensional arrays:
128 * array('prefix1' => array('foo' => 'bar')) gets "&prefix1[foo]=bar"
129 *
130 * @param array $arguments
131 * @return Tx_Extbase_MVC_Web_Routing_UriBuilder the current UriBuilder to allow method chaining
132 * @api
133 */
134 public function setArguments(array $arguments) {
135 $this->arguments = $arguments;
136 return $this;
137 }
138
139 /**
140 * @return array
141 * @api
142 */
143 public function getArguments() {
144 return $this->arguments;
145 }
146
147 /**
148 * If specified, adds a given HTML anchor to the URI (#...)
149 *
150 * @param string $section
151 * @return Tx_Extbase_MVC_Web_Routing_UriBuilder the current UriBuilder to allow method chaining
152 * @api
153 */
154 public function setSection($section) {
155 $this->section = $section;
156 return $this;
157 }
158
159 /**
160 * @return string
161 * @api
162 */
163 public function getSection() {
164 return $this->section;
165 }
166
167 /**
168 * Specifies the format of the target (e.g. "html" or "xml")
169 *
170 * @param string $section
171 * @return Tx_Extbase_MVC_Web_Routing_UriBuilder the current UriBuilder to allow method chaining
172 * @api
173 */
174 public function setFormat($format) {
175 $this->format = $format;
176 return $this;
177 }
178
179 /**
180 * @return string
181 * @api
182 */
183 public function getFormat() {
184 return $this->format;
185 }
186
187 /**
188 * If set, the URI is prepended with the current base URI. Defaults to FALSE.
189 *
190 * @param boolean $createAbsoluteUri
191 * @return Tx_Extbase_MVC_Web_Routing_UriBuilder the current UriBuilder to allow method chaining
192 * @api
193 */
194 public function setCreateAbsoluteUri($createAbsoluteUri) {
195 $this->createAbsoluteUri = $createAbsoluteUri;
196 return $this;
197 }
198
199 /**
200 * @return boolean
201 * @api
202 */
203 public function getCreateAbsoluteUri() {
204 return $this->createAbsoluteUri;
205 }
206
207 /**
208 * If set, the current query parameters will be merged with $this->arguments. Defaults to FALSE.
209 *
210 * @param boolean $addQueryString
211 * @return Tx_Extbase_MVC_Web_Routing_UriBuilder the current UriBuilder to allow method chaining
212 * @api
213 * @see TSref/typolink.addQueryString
214 */
215 public function setAddQueryString($addQueryString) {
216 $this->addQueryString = (boolean)$addQueryString;
217 return $this;
218 }
219
220 /**
221 * @return boolean
222 * @api
223 */
224 public function getAddQueryString() {
225 return $this->addQueryString;
226 }
227
228 /**
229 * A list of arguments to be excluded from the query parameters
230 * Only active if addQueryString is set
231 *
232 * @param array $argumentsToBeExcludedFromQueryString
233 * @return Tx_Extbase_MVC_Web_Routing_UriBuilder the current UriBuilder to allow method chaining
234 * @api
235 * @see TSref/typolink.addQueryString.exclude
236 * @see setAddQueryString()
237 */
238 public function setArgumentsToBeExcludedFromQueryString(array $argumentsToBeExcludedFromQueryString) {
239 $this->argumentsToBeExcludedFromQueryString = $argumentsToBeExcludedFromQueryString;
240 return $this;
241 }
242
243 /**
244 * @return array
245 * @api
246 */
247 public function getArgumentsToBeExcludedFromQueryString() {
248 return $this->argumentsToBeExcludedFromQueryString;
249 }
250
251 /**
252 * If set, URIs for pages without access permissions will be created
253 *
254 * @param boolean $linkAccessRestrictedPages
255 * @return Tx_Extbase_MVC_Web_Routing_UriBuilder the current UriBuilder to allow method chaining
256 * @api
257 */
258 public function setLinkAccessRestrictedPages($linkAccessRestrictedPages) {
259 $this->linkAccessRestrictedPages = (boolean)$linkAccessRestrictedPages;
260 return $this;
261 }
262
263 /**
264 * @return boolean
265 * @api
266 */
267 public function getLinkAccessRestrictedPages() {
268 return $this->linkAccessRestrictedPages;
269 }
270
271 /**
272 * Uid of the target page
273 *
274 * @param integer $pageUid
275 * @return Tx_Extbase_MVC_Web_Routing_UriBuilder the current UriBuilder to allow method chaining
276 * @api
277 */
278 public function setTargetPageUid($targetPageUid) {
279 $this->targetPageUid = $targetPageUid;
280 return $this;
281 }
282
283 /**
284 * returns $this->targetPageUid.
285 *
286 * @return integer
287 * @api
288 */
289 public function getTargetPageUid() {
290 return $this->targetPageUid;
291 }
292
293 /**
294 * Sets the page type of the target URI. Defaults to 0
295 *
296 * @param integer $pageType
297 * @return Tx_Extbase_MVC_Web_Routing_UriBuilder the current UriBuilder to allow method chaining
298 * @api
299 */
300 public function setTargetPageType($targetPageType) {
301 $this->targetPageType = (integer)$targetPageType;
302 return $this;
303 }
304
305 /**
306 * @return integer
307 * @api
308 */
309 public function getTargetPageType() {
310 return $this->targetPageType;
311 }
312
313 /**
314 * by default FALSE; if TRUE, &no_cache=1 will be appended to the URI
315 * This overrules the useCacheHash setting
316 *
317 * @param boolean $noCache
318 * @return Tx_Extbase_MVC_Web_Routing_UriBuilder the current UriBuilder to allow method chaining
319 * @api
320 */
321 public function setNoCache($noCache) {
322 $this->noCache = (boolean)$noCache;
323 return $this;
324 }
325
326 /**
327 * @return boolean
328 * @api
329 */
330 public function getNoCache() {
331 return $this->noCache;
332 }
333
334 /**
335 * by default TRUE; if FALSE, no cHash parameter will be appended to the URI
336 * If noCache is set, this setting will be ignored.
337 *
338 * @param boolean $useCacheHash
339 * @return Tx_Extbase_MVC_Web_Routing_UriBuilder the current UriBuilder to allow method chaining
340 * @api
341 */
342 public function setUseCacheHash($useCacheHash) {
343 $this->useCacheHash = (boolean)$useCacheHash;
344 return $this;
345 }
346
347 /**
348 * @return boolean
349 * @api
350 */
351 public function getUseCacheHash() {
352 return $this->useCacheHash;
353 }
354
355 /**
356 * Returns the arguments being used for the last URI being built.
357 * This is only set after build() / uriFor() has been called.
358 *
359 * @return array The last arguments
360 * @author Sebastian Kurf├╝rst <sebastian@typo3.org>
361 */
362 public function getLastArguments() {
363 return $this->lastArguments;
364 }
365
366 /**
367 * Resets all UriBuilder options to their default value
368 *
369 * @return Tx_Extbase_MVC_Web_Routing_UriBuilder the current UriBuilder to allow method chaining
370 * @api
371 */
372 public function reset() {
373 $this->arguments = array();
374 $this->section = '';
375 $this->format = '';
376 $this->createAbsoluteUri = FALSE;
377 $this->addQueryString = FALSE;
378 $this->argumentsToBeExcludedFromQueryString = array();
379 $this->linkAccessRestrictedPages = FALSE;
380 $this->targetPageUid = NULL;
381 $this->targetPageType = 0;
382 $this->noCache = FALSE;
383 $this->useCacheHash = TRUE;
384
385 return $this;
386 }
387
388 /**
389 * Creates an URI used for linking to an Extbase action.
390 * Works in Frondend and Backend mode of TYPO3.
391 *
392 * @param string $actionName Name of the action to be called
393 * @param array $controllerArguments Additional query parameters. Will be "namespaced" and merged with $this->arguments.
394 * @param string $controllerName Name of the target controller. If not set, current ControllerName is used.
395 * @param string $extensionName Name of the target extension, without underscores. If not set, current ExtensionName is used.
396 * @param string $pluginName Name of the target plugin. If not set, current PluginName is used.
397 * @return string the rendered URI
398 * @api
399 * @see build()
400 */
401 public function uriFor($actionName = NULL, $controllerArguments = array(), $controllerName = NULL, $extensionName = NULL, $pluginName = NULL) {
402 if ($actionName !== NULL) {
403 $controllerArguments['action'] = $actionName;
404 }
405 if ($controllerName !== NULL) {
406 $controllerArguments['controller'] = $controllerName;
407 } else {
408 $controllerArguments['controller'] = $this->request->getControllerName();
409 }
410 if ($extensionName === NULL) {
411 $extensionName = $this->request->getControllerExtensionName();
412 }
413 if ($pluginName === NULL) {
414 $pluginName = $this->request->getPluginName();
415 }
416 if ($this->format !== '') {
417 $controllerArguments['format'] = $this->format;
418 }
419 $argumentPrefix = strtolower('tx_' . $extensionName . '_' . $pluginName);
420 $prefixedControllerArguments = array($argumentPrefix => $controllerArguments);
421 $this->arguments = t3lib_div::array_merge_recursive_overrule($this->arguments, $prefixedControllerArguments);
422
423 return $this->build();
424 }
425
426 /**
427 * Builds the URI
428 * Depending on the current context this calls buildBackendUri() or buildFrontendUri()
429 *
430 * @return string The URI
431 * @api
432 * @see buildBackendUri()
433 * @see buildFrontendUri()
434 */
435 public function build() {
436 if (TYPO3_MODE === 'BE') {
437 return $this->buildBackendUri();
438 } else {
439 return $this->buildFrontendUri();
440 }
441 }
442
443 /**
444 * Builds the URI, backend flavour
445 * The resulting URI is relative and starts with "mod.php".
446 * The settings pageUid, pageType, noCache, useCacheHash & linkAccessRestrictedPages
447 * will be ignored in the backend.
448 *
449 * @return string The URI
450 */
451 public function buildBackendUri() {
452 if ($this->addQueryString === TRUE) {
453 $arguments = t3lib_div::_GET();
454 foreach($this->argumentsToBeExcludedFromQueryString as $argumentToBeExcluded) {
455 unset($arguments[$argumentToBeExcluded]);
456 }
457 } else {
458 $arguments = array(
459 'M' => t3lib_div::_GET('M'),
460 'id' => t3lib_div::_GET('id')
461 );
462 }
463 $arguments = t3lib_div::array_merge_recursive_overrule($arguments, $this->arguments);
464 $arguments = $this->convertDomainObjectsToIdentityArrays($arguments);
465 $this->lastArguments = $arguments;
466 $uri = 'mod.php?' . http_build_query($arguments, NULL, '&');
467 if ($this->section !== '') {
468 $uri .= '#' . $this->section;
469 }
470 if ($this->createAbsoluteUri === TRUE) {
471 $uri = $this->request->getBaseURI() . $uri;
472 }
473 return $uri;
474 }
475
476 /**
477 * Builds the URI, frontend flavour
478 *
479 * @return string The URI
480 * @see buildTypolinkConfiguration()
481 */
482 public function buildFrontendUri() {
483 $typolinkConfiguration = $this->buildTypolinkConfiguration();
484
485 $uri = $this->contentObject->typoLink_URL($typolinkConfiguration);
486 $uri = ltrim($uri, '/');
487 if ($this->createAbsoluteUri === TRUE) {
488 $uri = $this->request->getBaseURI() . $uri;
489 }
490 return $uri;
491 }
492
493
494 /**
495 * Builds a TypoLink configuration array from the current settings
496 *
497 * @return array typolink configuration array
498 * @see TSref/typolink
499 */
500 protected function buildTypolinkConfiguration() {
501 $typolinkConfiguration = array();
502
503 $typolinkConfiguration['parameter'] = $this->targetPageUid !== NULL ? $this->targetPageUid : $GLOBALS['TSFE']->id;
504 if ($this->targetPageType !== 0) {
505 $typolinkConfiguration['parameter'] .= ',' . $this->targetPageType;
506 }
507
508 if (count($this->arguments) > 0) {
509 $arguments = $this->convertDomainObjectsToIdentityArrays($this->arguments);
510 $this->lastArguments = $arguments;
511 $typolinkConfiguration['additionalParams'] = t3lib_div::implodeArrayForUrl(NULL, $arguments);
512 }
513
514 if ($this->addQueryString === TRUE) {
515 $typolinkConfiguration['addQueryString'] = 1;
516 if (count($this->argumentsToBeExcludedFromQueryString) > 0) {
517 $typolinkConfiguration['addQueryString.'] = array(
518 'exclude' => implode(',', $this->argumentsToBeExcludedFromQueryString)
519 );
520 }
521 // TODO: Support for __hmac and addQueryString!
522 }
523
524 if ($this->noCache === TRUE) {
525 $typolinkConfiguration['no_cache'] = 1;
526 } elseif ($this->useCacheHash) {
527 $typolinkConfiguration['useCacheHash'] = 1;
528 }
529
530 if ($this->section !== '') {
531 $typolinkConfiguration['section'] = $this->section;
532 }
533
534 if ($this->linkAccessRestrictedPages === TRUE) {
535 $typolinkConfiguration['linkAccessRestrictedPages'] = 1;
536 }
537
538 return $typolinkConfiguration;
539 }
540
541 /**
542 * Recursively iterates through the specified arguments and turns instances of type Tx_Extbase_DomainObject_AbstractEntity
543 * into an arrays containing the uid of the domain object.
544 *
545 * @param array $arguments The arguments to be iterated
546 * @return array The modified arguments array
547 */
548 protected function convertDomainObjectsToIdentityArrays(array $arguments) {
549 foreach ($arguments as $argumentKey => $argumentValue) {
550 if ($argumentValue instanceof Tx_Extbase_DomainObject_AbstractDomainObject) {
551 if ($argumentValue->getUid() !== NULL) {
552 $arguments[$argumentKey] = $argumentValue->getUid();
553 } elseif ($argumentValue instanceof Tx_Extbase_DomainObject_AbstractValueObject) {
554 $arguments[$argumentKey] = $this->convertTransientObjectToArray($argumentValue);
555 } else {
556 throw new Tx_Extbase_MVC_Exception_InvalidArgumentValue('Could not serialize Domain Object ' . get_class($argumentValue) . '. It is neither an Entity with identity properties set, nor a Value Object.', 1260881688);
557 }
558 } elseif (is_array($argumentValue)) {
559 $arguments[$argumentKey] = $this->convertDomainObjectsToIdentityArrays($argumentValue);
560 }
561 }
562 return $arguments;
563 }
564
565 /**
566 * Converts a given object recursively into an array.
567 *
568 * @param Tx_Extbase_DomainObject_AbstractDomainObject $object
569 * @return void
570 */
571 // TODO Refactore this into convertDomainObjectsToIdentityArrays()
572 public function convertTransientObjectToArray(Tx_Extbase_DomainObject_AbstractDomainObject $object) {
573 $result = array();
574 foreach ($object->_getProperties() as $propertyName => $propertyValue) {
575 if ($propertyValue instanceof Tx_Extbase_DomainObject_AbstractDomainObject) {
576 if ($propertyValue->getUid() !== NULL) {
577 $result[$propertyName] = $propertyValue->getUid();
578 } else {
579 $result[$propertyName] = $this->convertTransientObjectToArray($propertyValue);
580 }
581 } elseif (is_array($propertyValue)) {
582 $result[$propertyName] = $this->convertDomainObjectsToIdentityArrays($propertyValue);
583 } else {
584 $result[$propertyName] = $propertyValue;
585 }
586 }
587 return $result;
588 }
589
590 }
591 ?>