[+TASK] Extbase (Tests): Fixed Extbase unit tests
[Packages/TYPO3.CMS.git] / typo3 / sysext / extbase / Classes / MVC / Web / Routing / UriBuilder.php
index 268fb66..3daf718 100644 (file)
  * @package Extbase
  * @subpackage MVC\Web\Routing
  * @version $Id$
+ * @api
  */
 class Tx_Extbase_MVC_Web_Routing_UriBuilder {
 
        /**
+        * @var Tx_Extbase_Configuration_ConfigurationManagerInterface
+        */
+       protected $configurationManager;
+
+       /**
         * An instance of tslib_cObj
         *
         * @var tslib_cObj
@@ -39,6 +45,12 @@ class Tx_Extbase_MVC_Web_Routing_UriBuilder {
        protected $arguments = array();
 
        /**
+        * Arguments which have been used for building the last URI
+        * @var array
+        */
+       protected $lastArguments = array();
+
+       /**
         * @var string
         */
        protected $section = '';
@@ -83,14 +95,31 @@ class Tx_Extbase_MVC_Web_Routing_UriBuilder {
         */
        protected $useCacheHash = TRUE;
 
+       /**
+        * @var string
+        */
+       protected $format = '';
 
        /**
-        * Constructs this URI Helper
+        * @var string
+        */
+       protected $argumentPrefix = NULL;
+
+       /**
+        * @param Tx_Extbase_Configuration_ConfigurationManagerInterface $configurationManager
+        * @return void
+        */
+       public function injectConfigurationManager(Tx_Extbase_Configuration_ConfigurationManagerInterface $configurationManager) {
+               $this->configurationManager = $configurationManager;
+       }
+
+       /**
+        * Life-cycle method that is called by the DI container as soon as this object is completely built
         *
-        * @param tslib_cObj $contentObject
+        * @return void
         */
-       public function __construct(tslib_cObj $contentObject = NULL) {
-               $this->contentObject = $contentObject !== NULL ? $contentObject : t3lib_div::makeInstance('tslib_cObj');
+       public function initializeObject() {
+               $this->contentObject = $this->configurationManager->getContentObject();
        }
 
        /**
@@ -127,7 +156,7 @@ class Tx_Extbase_MVC_Web_Routing_UriBuilder {
 
        /**
         * @return array
-        * #@api
+        * @api
         */
        public function getArguments() {
                return $this->arguments;
@@ -154,6 +183,26 @@ class Tx_Extbase_MVC_Web_Routing_UriBuilder {
        }
 
        /**
+        * Specifies the format of the target (e.g. "html" or "xml")
+        *
+        * @param string $section
+        * @return Tx_Extbase_MVC_Web_Routing_UriBuilder the current UriBuilder to allow method chaining
+        * @api
+        */
+       public function setFormat($format) {
+               $this->format = $format;
+               return $this;
+       }
+
+       /**
+        * @return string
+        * @api
+        */
+       public function getFormat() {
+               return $this->format;
+       }
+
+       /**
         * If set, the URI is prepended with the current base URI. Defaults to FALSE.
         *
         * @param boolean $createAbsoluteUri
@@ -218,6 +267,24 @@ class Tx_Extbase_MVC_Web_Routing_UriBuilder {
        }
 
        /**
+        * Specifies the prefix to be used for all arguments.
+        *
+        * @param string $argumentPrefix
+        * @return Tx_Extbase_MVC_Web_Routing_UriBuilder the current UriBuilder to allow method chaining
+        */
+       public function setArgumentPrefix($argumentPrefix) {
+               $this->argumentPrefix = (string)$argumentPrefix;
+               return $this;
+       }
+
+       /**
+        * @return string
+        */
+       public function getArgumentPrefix() {
+               return $this->argumentPrefix;
+       }
+
+       /**
         * If set, URIs for pages without access permissions will be created
         *
         * @param boolean $linkAccessRestrictedPages
@@ -322,16 +389,51 @@ class Tx_Extbase_MVC_Web_Routing_UriBuilder {
        }
 
        /**
-        * Creates an URI by making use of the typolink mechanism.
+        * Returns the arguments being used for the last URI being built.
+        * This is only set after build() / uriFor() has been called.
+        *
+        * @return array The last arguments
+        * @author Sebastian Kurf├╝rst <sebastian@typo3.org>
+        */
+       public function getLastArguments() {
+               return $this->lastArguments;
+       }
+
+       /**
+        * Resets all UriBuilder options to their default value
+        *
+        * @return Tx_Extbase_MVC_Web_Routing_UriBuilder the current UriBuilder to allow method chaining
+        * @api
+        */
+       public function reset() {
+               $this->arguments = array();
+               $this->section = '';
+               $this->format = '';
+               $this->createAbsoluteUri = FALSE;
+               $this->addQueryString = FALSE;
+               $this->argumentsToBeExcludedFromQueryString = array();
+               $this->linkAccessRestrictedPages = FALSE;
+               $this->targetPageUid = NULL;
+               $this->targetPageType = 0;
+               $this->noCache = FALSE;
+               $this->useCacheHash = TRUE;
+               $this->argumentPrefix = NULL;
+
+               return $this;
+       }
+
+       /**
+        * Creates an URI used for linking to an Extbase action.
+        * Works in Frontend and Backend mode of TYPO3.
         *
-        * @param integer $pageUid uid of the target page
         * @param string $actionName Name of the action to be called
-        * @param array $controllerArguments Additional query parameters, will be "namespaced"
-        * @param string $controllerName Name of the target controller
-        * @param string $extensionName Name of the target extension, without underscores. If NULL current ExtensionName is used.
-        * @param string $pluginName Name of the target plugin.  If NULL current PluginName is used.
-        * @return string the typolink URI
+        * @param array $controllerArguments Additional query parameters. Will be "namespaced" and merged with $this->arguments.
+        * @param string $controllerName Name of the target controller. If not set, current ControllerName is used.
+        * @param string $extensionName Name of the target extension, without underscores. If not set, current ExtensionName is used.
+        * @param string $pluginName Name of the target plugin. If not set, current PluginName is used.
+        * @return string the rendered URI
         * @api
+        * @see build()
         */
        public function uriFor($actionName = NULL, $controllerArguments = array(), $controllerName = NULL, $extensionName = NULL, $pluginName = NULL) {
                if ($actionName !== NULL) {
@@ -345,11 +447,24 @@ class Tx_Extbase_MVC_Web_Routing_UriBuilder {
                if ($extensionName === NULL) {
                        $extensionName = $this->request->getControllerExtensionName();
                }
+               if ($pluginName === NULL && TYPO3_MODE === 'FE') {
+                       $pluginName = Tx_Extbase_Utility_Extension::getPluginNameByAction($extensionName, $controllerArguments['controller'], $controllerArguments['action']);
+               }
                if ($pluginName === NULL) {
                        $pluginName = $this->request->getPluginName();
                }
-               $argumentPrefix = strtolower('tx_' . $extensionName . '_' . $pluginName);
-               $prefixedControllerArguments = (count($controllerArguments) > 0) ? array($argumentPrefix => $controllerArguments) : array();
+               if ($this->targetPageUid === NULL && TYPO3_MODE === 'FE') {
+                       $this->targetPageUid = Tx_Extbase_Utility_Extension::getTargetPidByPlugin($extensionName, $pluginName);
+               }
+               if ($this->format !== '') {
+                       $controllerArguments['format'] = $this->format;
+               }
+               if ($this->argumentPrefix !== NULL) {
+                       $prefixedControllerArguments = array($this->argumentPrefix => $controllerArguments);
+               } else {
+                       $pluginNamespace = Tx_Extbase_Utility_Extension::getPluginNamespace($extensionName, $pluginName);
+                       $prefixedControllerArguments = array($pluginNamespace => $controllerArguments);
+               }
                $this->arguments = t3lib_div::array_merge_recursive_overrule($this->arguments, $prefixedControllerArguments);
 
                return $this->build();
@@ -375,7 +490,7 @@ class Tx_Extbase_MVC_Web_Routing_UriBuilder {
        /**
         * Builds the URI, backend flavour
         * The resulting URI is relative and starts with "mod.php".
-        * The settings pageUid, pageType, noCache, useCacheHash, linkAccessRestrictedPages, createAbsoluteUri
+        * The settings pageUid, pageType, noCache, useCacheHash & linkAccessRestrictedPages
         * will be ignored in the backend.
         *
         * @return string The URI
@@ -394,10 +509,14 @@ class Tx_Extbase_MVC_Web_Routing_UriBuilder {
                }
                $arguments = t3lib_div::array_merge_recursive_overrule($arguments, $this->arguments);
                $arguments = $this->convertDomainObjectsToIdentityArrays($arguments);
+               $this->lastArguments = $arguments;
                $uri = 'mod.php?' . http_build_query($arguments, NULL, '&');
                if ($this->section !== '') {
                        $uri .= '#' . $this->section;
                }
+               if ($this->createAbsoluteUri === TRUE) {
+                       $uri = $this->request->getBaseURI() . $uri;
+               }
                return $uri;
        }
 
@@ -410,31 +529,14 @@ class Tx_Extbase_MVC_Web_Routing_UriBuilder {
        public function buildFrontendUri() {
                $typolinkConfiguration = $this->buildTypolinkConfiguration();
 
-               $uri = $this->contentObject->typoLink_URL($typolinkConfiguration);
                if ($this->createAbsoluteUri === TRUE) {
-                       $uri = $this->request->getBaseURI() . $uri;
+                       $typolinkConfiguration['forceAbsoluteUrl'] = TRUE;
                }
+
+               $uri = $this->contentObject->typoLink_URL($typolinkConfiguration);
                return $uri;
        }
 
-       /**
-        * Resets all UriBuilder options to their default value
-        *
-        * @return void
-        * @api
-        */
-       public function reset() {
-               $this->arguments = array();
-               $this->section = '';
-               $this->createAbsoluteUri = FALSE;
-               $this->addQueryString = FALSE;
-               $this->argumentsToBeExcludedFromQueryString = array();
-               $this->linkAccessRestrictedPages = FALSE;
-               $this->targetPageUid = NULL;
-               $this->targetPageType = 0;
-               $this->noCache = FALSE;
-               $this->useCacheHash = TRUE;
-       }
 
        /**
         * Builds a TypoLink configuration array from the current settings
@@ -452,7 +554,8 @@ class Tx_Extbase_MVC_Web_Routing_UriBuilder {
 
                if (count($this->arguments) > 0) {
                        $arguments = $this->convertDomainObjectsToIdentityArrays($this->arguments);
-                       $typolinkConfiguration['additionalParams'] = '&' . http_build_query($arguments, NULL, '&');
+                       $this->lastArguments = $arguments;
+                       $typolinkConfiguration['additionalParams'] = t3lib_div::implodeArrayForUrl(NULL, $arguments);
                }
 
                if ($this->addQueryString === TRUE) {
@@ -462,6 +565,7 @@ class Tx_Extbase_MVC_Web_Routing_UriBuilder {
                                        'exclude' => implode(',', $this->argumentsToBeExcludedFromQueryString)
                                );
                        }
+                       // TODO: Support for __hmac and addQueryString!
                }
 
                if ($this->noCache === TRUE) {
@@ -490,8 +594,21 @@ class Tx_Extbase_MVC_Web_Routing_UriBuilder {
         */
        protected function convertDomainObjectsToIdentityArrays(array $arguments) {
                foreach ($arguments as $argumentKey => $argumentValue) {
-                       if ($argumentValue instanceof Tx_Extbase_DomainObject_AbstractEntity) {
-                               $arguments[$argumentKey] = array('uid' => $argumentValue->getUid());
+                       // if we have a LazyLoadingProxy here, make sure to get the real instance for further processing
+                       if ($argumentValue instanceof Tx_Extbase_Persistence_LazyLoadingProxy) {
+                               $argumentValue = $argumentValue->_loadRealInstance();
+                               // also update the value in the arguments array, because the lazyLoaded object could be
+                               // hidden and thus the $argumentValue would be NULL.
+                               $arguments[$argumentKey] = $argumentValue;
+                       }
+                       if ($argumentValue instanceof Tx_Extbase_DomainObject_AbstractDomainObject) {
+                               if ($argumentValue->getUid() !== NULL) {
+                                       $arguments[$argumentKey] = $argumentValue->getUid();
+                               } elseif ($argumentValue instanceof Tx_Extbase_DomainObject_AbstractValueObject) {
+                                       $arguments[$argumentKey] = $this->convertTransientObjectToArray($argumentValue);
+                               } else {
+                                       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);
+                               }
                        } elseif (is_array($argumentValue)) {
                                $arguments[$argumentKey] = $this->convertDomainObjectsToIdentityArrays($argumentValue);
                        }
@@ -499,5 +616,30 @@ class Tx_Extbase_MVC_Web_Routing_UriBuilder {
                return $arguments;
        }
 
+       /**
+        * Converts a given object recursively into an array.
+        *
+        * @param Tx_Extbase_DomainObject_AbstractDomainObject $object
+        * @return void
+        */
+       // TODO Refactore this into convertDomainObjectsToIdentityArrays()
+       public function convertTransientObjectToArray(Tx_Extbase_DomainObject_AbstractDomainObject $object) {
+               $result = array();
+               foreach ($object->_getProperties() as $propertyName => $propertyValue) {
+                       if ($propertyValue instanceof Tx_Extbase_DomainObject_AbstractDomainObject) {
+                               if ($propertyValue->getUid() !== NULL) {
+                                       $result[$propertyName] = $propertyValue->getUid();
+                               } else {
+                                       $result[$propertyName] = $this->convertTransientObjectToArray($propertyValue);
+                               }
+                       } elseif (is_array($propertyValue)) {
+                               $result[$propertyName] = $this->convertDomainObjectsToIdentityArrays($propertyValue);
+                       } else {
+                               $result[$propertyName] = $propertyValue;
+                       }
+               }
+               return $result;
+       }
+
 }
 ?>
\ No newline at end of file