TYPO3 API  SVNRelease
UriBuilder.php
Go to the documentation of this file.
00001 <?php
00002 /*                                                                        *
00003  * This script is part of the TYPO3 project - inspiring people to share!  *
00004  *                                                                        *
00005  * TYPO3 is free software; you can redistribute it and/or modify it under *
00006  * the terms of the GNU General Public License version 2 as published by  *
00007  * the Free Software Foundation.                                          *
00008  *                                                                        *
00009  * This script is distributed in the hope that it will be useful, but     *
00010  * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHAN-    *
00011  * TABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General      *
00012  * Public License for more details.                                       *
00013  *                                                                        */
00014 
00015 /**
00016  * An URI Builder
00017  *
00018  * @package Extbase
00019  * @subpackage MVC\Web\Routing
00020  * @version $Id: UriBuilder.php 2184 2010-04-08 14:59:58Z jocrau $
00021  * @api
00022  */
00023 class Tx_Extbase_MVC_Web_Routing_UriBuilder {
00024 
00025     /**
00026      * @var Tx_Extbase_Configuration_ConfigurationManagerInterface
00027      */
00028     protected $configurationManager;
00029 
00030     /**
00031      * An instance of tslib_cObj
00032      *
00033      * @var tslib_cObj
00034      */
00035     protected $contentObject;
00036 
00037     /**
00038      * @var Tx_Extbase_MVC_Web_Request
00039      */
00040     protected $request;
00041 
00042     /**
00043      * @var array
00044      */
00045     protected $arguments = array();
00046 
00047     /**
00048      * Arguments which have been used for building the last URI
00049      * @var array
00050      */
00051     protected $lastArguments = array();
00052 
00053     /**
00054      * @var string
00055      */
00056     protected $section = '';
00057 
00058     /**
00059      * @var boolean
00060      */
00061     protected $createAbsoluteUri = FALSE;
00062 
00063     /**
00064      * @var boolean
00065      */
00066     protected $addQueryString = FALSE;
00067 
00068     /**
00069      * @var array
00070      */
00071     protected $argumentsToBeExcludedFromQueryString = array();
00072 
00073     /**
00074      * @var boolean
00075      */
00076     protected $linkAccessRestrictedPages = FALSE;
00077 
00078     /**
00079      * @var integer
00080      */
00081     protected $targetPageUid = NULL;
00082 
00083     /**
00084      * @var integer
00085      */
00086     protected $targetPageType = 0;
00087 
00088     /**
00089      * @var boolean
00090      */
00091     protected $noCache = FALSE;
00092 
00093     /**
00094      * @var boolean
00095      */
00096     protected $useCacheHash = TRUE;
00097 
00098     /**
00099      * @var string
00100      */
00101     protected $format = '';
00102 
00103     /**
00104      * @var string
00105      */
00106     protected $argumentPrefix = NULL;
00107 
00108     /**
00109      * @param Tx_Extbase_Configuration_ConfigurationManagerInterface $configurationManager
00110      * @return void
00111      */
00112     public function injectConfigurationManager(Tx_Extbase_Configuration_ConfigurationManagerInterface $configurationManager) {
00113         $this->configurationManager = $configurationManager;
00114     }
00115 
00116     /**
00117      * Life-cycle method that is called by the DI container as soon as this object is completely built
00118      *
00119      * @return void
00120      */
00121     public function initializeObject() {
00122         $this->contentObject = $this->configurationManager->getContentObject();
00123     }
00124 
00125     /**
00126      * Sets the current request
00127      *
00128      * @param Tx_Extbase_MVC_Web_Request $request
00129      * @return Tx_Extbase_MVC_Web_Routing_UriBuilder the current UriBuilder to allow method chaining
00130      */
00131     public function setRequest(Tx_Extbase_MVC_Web_Request $request) {
00132         $this->request = $request;
00133         return $this;
00134     }
00135 
00136     /**
00137      * @return Tx_Extbase_MVC_Web_Request
00138      */
00139     public function getRequest() {
00140         return $this->request;
00141     }
00142 
00143     /**
00144      * Additional query parameters.
00145      * If you want to "prefix" arguments, you can pass in multidimensional arrays:
00146      * array('prefix1' => array('foo' => 'bar')) gets "&prefix1[foo]=bar"
00147      *
00148      * @param array $arguments
00149      * @return Tx_Extbase_MVC_Web_Routing_UriBuilder the current UriBuilder to allow method chaining
00150      * @api
00151      */
00152     public function setArguments(array $arguments) {
00153         $this->arguments = $arguments;
00154         return $this;
00155     }
00156 
00157     /**
00158      * @return array
00159      * @api
00160      */
00161     public function getArguments() {
00162         return $this->arguments;
00163     }
00164 
00165     /**
00166      * If specified, adds a given HTML anchor to the URI (#...)
00167      *
00168      * @param string $section
00169      * @return Tx_Extbase_MVC_Web_Routing_UriBuilder the current UriBuilder to allow method chaining
00170      * @api
00171      */
00172     public function setSection($section) {
00173         $this->section = $section;
00174         return $this;
00175     }
00176 
00177     /**
00178      * @return string
00179      * @api
00180      */
00181     public function getSection() {
00182         return $this->section;
00183     }
00184 
00185     /**
00186      * Specifies the format of the target (e.g. "html" or "xml")
00187      *
00188      * @param string $section
00189      * @return Tx_Extbase_MVC_Web_Routing_UriBuilder the current UriBuilder to allow method chaining
00190      * @api
00191      */
00192     public function setFormat($format) {
00193         $this->format = $format;
00194         return $this;
00195     }
00196 
00197     /**
00198      * @return string
00199      * @api
00200      */
00201     public function getFormat() {
00202         return $this->format;
00203     }
00204 
00205     /**
00206      * If set, the URI is prepended with the current base URI. Defaults to FALSE.
00207      *
00208      * @param boolean $createAbsoluteUri
00209      * @return Tx_Extbase_MVC_Web_Routing_UriBuilder the current UriBuilder to allow method chaining
00210      * @api
00211      */
00212     public function setCreateAbsoluteUri($createAbsoluteUri) {
00213         $this->createAbsoluteUri = $createAbsoluteUri;
00214         return $this;
00215     }
00216 
00217     /**
00218      * @return boolean
00219      * @api
00220      */
00221     public function getCreateAbsoluteUri() {
00222         return $this->createAbsoluteUri;
00223     }
00224 
00225     /**
00226      * If set, the current query parameters will be merged with $this->arguments. Defaults to FALSE.
00227      *
00228      * @param boolean $addQueryString
00229      * @return Tx_Extbase_MVC_Web_Routing_UriBuilder the current UriBuilder to allow method chaining
00230      * @api
00231      * @see TSref/typolink.addQueryString
00232      */
00233     public function setAddQueryString($addQueryString) {
00234         $this->addQueryString = (boolean)$addQueryString;
00235         return $this;
00236     }
00237 
00238     /**
00239      * @return boolean
00240      * @api
00241      */
00242     public function getAddQueryString() {
00243         return $this->addQueryString;
00244     }
00245 
00246     /**
00247      * A list of arguments to be excluded from the query parameters
00248      * Only active if addQueryString is set
00249      *
00250      * @param array $argumentsToBeExcludedFromQueryString
00251      * @return Tx_Extbase_MVC_Web_Routing_UriBuilder the current UriBuilder to allow method chaining
00252      * @api
00253      * @see TSref/typolink.addQueryString.exclude
00254      * @see setAddQueryString()
00255      */
00256     public function setArgumentsToBeExcludedFromQueryString(array $argumentsToBeExcludedFromQueryString) {
00257         $this->argumentsToBeExcludedFromQueryString = $argumentsToBeExcludedFromQueryString;
00258         return $this;
00259     }
00260 
00261     /**
00262      * @return array
00263      * @api
00264      */
00265     public function getArgumentsToBeExcludedFromQueryString() {
00266         return $this->argumentsToBeExcludedFromQueryString;
00267     }
00268 
00269     /**
00270      * Specifies the prefix to be used for all arguments.
00271      *
00272      * @param string $argumentPrefix
00273      * @return Tx_Extbase_MVC_Web_Routing_UriBuilder the current UriBuilder to allow method chaining
00274      */
00275     public function setArgumentPrefix($argumentPrefix) {
00276         $this->argumentPrefix = (string)$argumentPrefix;
00277         return $this;
00278     }
00279 
00280     /**
00281      * @return string
00282      */
00283     public function getArgumentPrefix() {
00284         return $this->argumentPrefix;
00285     }
00286 
00287     /**
00288      * If set, URIs for pages without access permissions will be created
00289      *
00290      * @param boolean $linkAccessRestrictedPages
00291      * @return Tx_Extbase_MVC_Web_Routing_UriBuilder the current UriBuilder to allow method chaining
00292      * @api
00293      */
00294     public function setLinkAccessRestrictedPages($linkAccessRestrictedPages) {
00295         $this->linkAccessRestrictedPages = (boolean)$linkAccessRestrictedPages;
00296         return $this;
00297     }
00298 
00299     /**
00300      * @return boolean
00301      * @api
00302      */
00303     public function getLinkAccessRestrictedPages() {
00304         return $this->linkAccessRestrictedPages;
00305     }
00306 
00307     /**
00308      * Uid of the target page
00309      *
00310      * @param integer $pageUid
00311      * @return Tx_Extbase_MVC_Web_Routing_UriBuilder the current UriBuilder to allow method chaining
00312      * @api
00313      */
00314     public function setTargetPageUid($targetPageUid) {
00315         $this->targetPageUid = $targetPageUid;
00316         return $this;
00317     }
00318 
00319     /**
00320      * returns $this->targetPageUid.
00321      *
00322      * @return integer
00323      * @api
00324      */
00325     public function getTargetPageUid() {
00326         return $this->targetPageUid;
00327     }
00328 
00329     /**
00330      * Sets the page type of the target URI. Defaults to 0
00331      *
00332      * @param integer $pageType
00333      * @return Tx_Extbase_MVC_Web_Routing_UriBuilder the current UriBuilder to allow method chaining
00334      * @api
00335      */
00336     public function setTargetPageType($targetPageType) {
00337         $this->targetPageType = (integer)$targetPageType;
00338         return $this;
00339     }
00340 
00341     /**
00342      * @return integer
00343      * @api
00344      */
00345     public function getTargetPageType() {
00346         return $this->targetPageType;
00347     }
00348 
00349     /**
00350      * by default FALSE; if TRUE, &no_cache=1 will be appended to the URI
00351      * This overrules the useCacheHash setting
00352      *
00353      * @param boolean $noCache
00354      * @return Tx_Extbase_MVC_Web_Routing_UriBuilder the current UriBuilder to allow method chaining
00355      * @api
00356      */
00357     public function setNoCache($noCache) {
00358         $this->noCache = (boolean)$noCache;
00359         return $this;
00360     }
00361 
00362     /**
00363      * @return boolean
00364      * @api
00365      */
00366     public function getNoCache() {
00367         return $this->noCache;
00368     }
00369 
00370     /**
00371      * by default TRUE; if FALSE, no cHash parameter will be appended to the URI
00372      * If noCache is set, this setting will be ignored.
00373      *
00374      * @param boolean $useCacheHash
00375      * @return Tx_Extbase_MVC_Web_Routing_UriBuilder the current UriBuilder to allow method chaining
00376      * @api
00377      */
00378     public function setUseCacheHash($useCacheHash) {
00379         $this->useCacheHash = (boolean)$useCacheHash;
00380         return $this;
00381     }
00382 
00383     /**
00384      * @return boolean
00385      * @api
00386      */
00387     public function getUseCacheHash() {
00388         return $this->useCacheHash;
00389     }
00390 
00391     /**
00392      * Returns the arguments being used for the last URI being built.
00393      * This is only set after build() / uriFor() has been called.
00394      *
00395      * @return array The last arguments
00396      * @author Sebastian Kurfürst <sebastian@typo3.org>
00397      */
00398     public function getLastArguments() {
00399         return $this->lastArguments;
00400     }
00401 
00402     /**
00403      * Resets all UriBuilder options to their default value
00404      *
00405      * @return Tx_Extbase_MVC_Web_Routing_UriBuilder the current UriBuilder to allow method chaining
00406      * @api
00407      */
00408     public function reset() {
00409         $this->arguments = array();
00410         $this->section = '';
00411         $this->format = '';
00412         $this->createAbsoluteUri = FALSE;
00413         $this->addQueryString = FALSE;
00414         $this->argumentsToBeExcludedFromQueryString = array();
00415         $this->linkAccessRestrictedPages = FALSE;
00416         $this->targetPageUid = NULL;
00417         $this->targetPageType = 0;
00418         $this->noCache = FALSE;
00419         $this->useCacheHash = TRUE;
00420         $this->argumentPrefix = NULL;
00421 
00422         return $this;
00423     }
00424 
00425     /**
00426      * Creates an URI used for linking to an Extbase action.
00427      * Works in Frontend and Backend mode of TYPO3.
00428      *
00429      * @param string $actionName Name of the action to be called
00430      * @param array $controllerArguments Additional query parameters. Will be "namespaced" and merged with $this->arguments.
00431      * @param string $controllerName Name of the target controller. If not set, current ControllerName is used.
00432      * @param string $extensionName Name of the target extension, without underscores. If not set, current ExtensionName is used.
00433      * @param string $pluginName Name of the target plugin. If not set, current PluginName is used.
00434      * @return string the rendered URI
00435      * @api
00436      * @see build()
00437      */
00438     public function uriFor($actionName = NULL, $controllerArguments = array(), $controllerName = NULL, $extensionName = NULL, $pluginName = NULL) {
00439         if ($actionName !== NULL) {
00440             $controllerArguments['action'] = $actionName;
00441         }
00442         if ($controllerName !== NULL) {
00443             $controllerArguments['controller'] = $controllerName;
00444         } else {
00445             $controllerArguments['controller'] = $this->request->getControllerName();
00446         }
00447         if ($extensionName === NULL) {
00448             $extensionName = $this->request->getControllerExtensionName();
00449         }
00450         if ($pluginName === NULL && TYPO3_MODE === 'FE') {
00451             $pluginName = Tx_Extbase_Utility_Extension::getPluginNameByAction($extensionName, $controllerArguments['controller'], $controllerArguments['action']);
00452         }
00453         if ($pluginName === NULL) {
00454             $pluginName = $this->request->getPluginName();
00455         }
00456         if ($this->targetPageUid === NULL && TYPO3_MODE === 'FE') {
00457             $this->targetPageUid = Tx_Extbase_Utility_Extension::getTargetPidByPlugin($extensionName, $pluginName);
00458         }
00459         if ($this->format !== '') {
00460             $controllerArguments['format'] = $this->format;
00461         }
00462         if ($this->argumentPrefix !== NULL) {
00463             $prefixedControllerArguments = array($this->argumentPrefix => $controllerArguments);
00464         } else {
00465             $pluginNamespace = Tx_Extbase_Utility_Extension::getPluginNamespace($extensionName, $pluginName);
00466             $prefixedControllerArguments = array($pluginNamespace => $controllerArguments);
00467         }
00468         $this->arguments = t3lib_div::array_merge_recursive_overrule($this->arguments, $prefixedControllerArguments);
00469 
00470         if ($actionName !== NULL
00471             && $this->useCacheHash === TRUE
00472             && !Tx_Extbase_Utility_Extension::isActionCacheable($extensionName, $pluginName, $controllerArguments['controller'], $actionName)) {
00473                 $this->setUseCacheHash(FALSE);
00474         }
00475 
00476         return $this->build();
00477     }
00478 
00479     /**
00480      * Builds the URI
00481      * Depending on the current context this calls buildBackendUri() or buildFrontendUri()
00482      *
00483      * @return string The URI
00484      * @api
00485      * @see buildBackendUri()
00486      * @see buildFrontendUri()
00487      */
00488     public function build() {
00489         if (TYPO3_MODE === 'BE') {
00490             return $this->buildBackendUri();
00491         } else {
00492             return $this->buildFrontendUri();
00493         }
00494     }
00495 
00496     /**
00497      * Builds the URI, backend flavour
00498      * The resulting URI is relative and starts with "mod.php".
00499      * The settings pageUid, pageType, noCache, useCacheHash & linkAccessRestrictedPages
00500      * will be ignored in the backend.
00501      *
00502      * @return string The URI
00503      */
00504     public function buildBackendUri() {
00505         if ($this->addQueryString === TRUE) {
00506             $arguments = t3lib_div::_GET();
00507             foreach($this->argumentsToBeExcludedFromQueryString as $argumentToBeExcluded) {
00508                 unset($arguments[$argumentToBeExcluded]);
00509             }
00510         } else {
00511             $arguments = array(
00512                 'M' => t3lib_div::_GET('M'),
00513                 'id' => t3lib_div::_GET('id')
00514             );
00515         }
00516         $arguments = t3lib_div::array_merge_recursive_overrule($arguments, $this->arguments);
00517         $arguments = $this->convertDomainObjectsToIdentityArrays($arguments);
00518         $this->lastArguments = $arguments;
00519         $uri = 'mod.php?' . http_build_query($arguments, NULL, '&');
00520         if ($this->section !== '') {
00521             $uri .= '#' . $this->section;
00522         }
00523         if ($this->createAbsoluteUri === TRUE) {
00524             $uri = $this->request->getBaseURI() . $uri;
00525         }
00526         return $uri;
00527     }
00528 
00529     /**
00530      * Builds the URI, frontend flavour
00531      *
00532      * @return string The URI
00533      * @see buildTypolinkConfiguration()
00534      */
00535     public function buildFrontendUri() {
00536         $typolinkConfiguration = $this->buildTypolinkConfiguration();
00537 
00538         if ($this->createAbsoluteUri === TRUE) {
00539             $typolinkConfiguration['forceAbsoluteUrl'] = TRUE;
00540         }
00541 
00542         $uri = $this->contentObject->typoLink_URL($typolinkConfiguration);
00543         return $uri;
00544     }
00545 
00546 
00547     /**
00548      * Builds a TypoLink configuration array from the current settings
00549      *
00550      * @return array typolink configuration array
00551      * @see TSref/typolink
00552      */
00553     protected function buildTypolinkConfiguration() {
00554         $typolinkConfiguration = array();
00555 
00556         $typolinkConfiguration['parameter'] = $this->targetPageUid !== NULL ? $this->targetPageUid : $GLOBALS['TSFE']->id;
00557         if ($this->targetPageType !== 0) {
00558             $typolinkConfiguration['parameter'] .= ',' . $this->targetPageType;
00559         }
00560 
00561         if (count($this->arguments) > 0) {
00562             $arguments = $this->convertDomainObjectsToIdentityArrays($this->arguments);
00563             $this->lastArguments = $arguments;
00564             $typolinkConfiguration['additionalParams'] = t3lib_div::implodeArrayForUrl(NULL, $arguments);
00565         }
00566 
00567         if ($this->addQueryString === TRUE) {
00568             $typolinkConfiguration['addQueryString'] = 1;
00569             if (count($this->argumentsToBeExcludedFromQueryString) > 0) {
00570                 $typolinkConfiguration['addQueryString.'] = array(
00571                     'exclude' => implode(',', $this->argumentsToBeExcludedFromQueryString)
00572                 );
00573             }
00574             // TODO: Support for __hmac and addQueryString!
00575         }
00576 
00577         if ($this->noCache === TRUE) {
00578             $typolinkConfiguration['no_cache'] = 1;
00579         } elseif ($this->useCacheHash) {
00580             $typolinkConfiguration['useCacheHash'] = 1;
00581         }
00582 
00583         if ($this->section !== '') {
00584             $typolinkConfiguration['section'] = $this->section;
00585         }
00586 
00587         if ($this->linkAccessRestrictedPages === TRUE) {
00588             $typolinkConfiguration['linkAccessRestrictedPages'] = 1;
00589         }
00590 
00591         return $typolinkConfiguration;
00592     }
00593 
00594     /**
00595      * Recursively iterates through the specified arguments and turns instances of type Tx_Extbase_DomainObject_AbstractEntity
00596      * into an arrays containing the uid of the domain object.
00597      *
00598      * @param array $arguments The arguments to be iterated
00599      * @return array The modified arguments array
00600      */
00601     protected function convertDomainObjectsToIdentityArrays(array $arguments) {
00602         foreach ($arguments as $argumentKey => $argumentValue) {
00603             // if we have a LazyLoadingProxy here, make sure to get the real instance for further processing
00604             if ($argumentValue instanceof Tx_Extbase_Persistence_LazyLoadingProxy) {
00605                 $argumentValue = $argumentValue->_loadRealInstance();
00606                 // also update the value in the arguments array, because the lazyLoaded object could be
00607                 // hidden and thus the $argumentValue would be NULL.
00608                 $arguments[$argumentKey] = $argumentValue;
00609             }
00610             if ($argumentValue instanceof Tx_Extbase_DomainObject_AbstractDomainObject) {
00611                 if ($argumentValue->getUid() !== NULL) {
00612                     $arguments[$argumentKey] = $argumentValue->getUid();
00613                 } elseif ($argumentValue instanceof Tx_Extbase_DomainObject_AbstractValueObject) {
00614                     $arguments[$argumentKey] = $this->convertTransientObjectToArray($argumentValue);
00615                 } else {
00616                     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);
00617                 }
00618             } elseif (is_array($argumentValue)) {
00619                 $arguments[$argumentKey] = $this->convertDomainObjectsToIdentityArrays($argumentValue);
00620             }
00621         }
00622         return $arguments;
00623     }
00624 
00625     /**
00626      * Converts a given object recursively into an array.
00627      *
00628      * @param Tx_Extbase_DomainObject_AbstractDomainObject $object
00629      * @return void
00630      */
00631     // TODO Refactore this into convertDomainObjectsToIdentityArrays()
00632     public function convertTransientObjectToArray(Tx_Extbase_DomainObject_AbstractDomainObject $object) {
00633         $result = array();
00634         foreach ($object->_getProperties() as $propertyName => $propertyValue) {
00635             if ($propertyValue instanceof Tx_Extbase_DomainObject_AbstractDomainObject) {
00636                 if ($propertyValue->getUid() !== NULL) {
00637                     $result[$propertyName] = $propertyValue->getUid();
00638                 } else {
00639                     $result[$propertyName] = $this->convertTransientObjectToArray($propertyValue);
00640                 }
00641             } elseif (is_array($propertyValue)) {
00642                 $result[$propertyName] = $this->convertDomainObjectsToIdentityArrays($propertyValue);
00643             } else {
00644                 $result[$propertyName] = $propertyValue;
00645             }
00646         }
00647         return $result;
00648     }
00649 
00650 }
00651 ?>