first commit
This commit is contained in:
commit
1218dd1517
12716 files changed
+989233
No files matched your search
@@ -0,0 +1,95 @@
|
||||
<?php
|
||||
namespace TYPO3\CMS\Extbase\Mvc\Web;
|
||||
|
||||
/*
|
||||
* This file is part of the TYPO3 CMS project.
|
||||
*
|
||||
* It is free software; you can redistribute it and/or modify it under
|
||||
* the terms of the GNU General Public License, either version 2
|
||||
* of the License, or any later version.
|
||||
*
|
||||
* For the full copyright and license information, please read the
|
||||
* LICENSE.txt file that was distributed with this source code.
|
||||
*
|
||||
* The TYPO3 project - inspiring people to share!
|
||||
*/
|
||||
|
||||
/**
|
||||
* A request handler which can handle web requests.
|
||||
* @internal only to be used within Extbase, not part of TYPO3 Core API.
|
||||
*/
|
||||
abstract class AbstractRequestHandler implements \TYPO3\CMS\Extbase\Mvc\RequestHandlerInterface
|
||||
{
|
||||
/**
|
||||
* @var \TYPO3\CMS\Extbase\Object\ObjectManagerInterface
|
||||
*/
|
||||
protected $objectManager;
|
||||
|
||||
/**
|
||||
* @var \TYPO3\CMS\Extbase\Mvc\Dispatcher
|
||||
*/
|
||||
protected $dispatcher;
|
||||
|
||||
/**
|
||||
* @var \TYPO3\CMS\Extbase\Mvc\Web\RequestBuilder
|
||||
*/
|
||||
protected $requestBuilder;
|
||||
|
||||
/**
|
||||
* @var \TYPO3\CMS\Extbase\Service\EnvironmentService
|
||||
*/
|
||||
protected $environmentService;
|
||||
|
||||
/**
|
||||
* @param \TYPO3\CMS\Extbase\Mvc\Dispatcher $dispatcher
|
||||
*/
|
||||
public function injectDispatcher(\TYPO3\CMS\Extbase\Mvc\Dispatcher $dispatcher)
|
||||
{
|
||||
$this->dispatcher = $dispatcher;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param \TYPO3\CMS\Extbase\Mvc\Web\RequestBuilder $requestBuilder
|
||||
*/
|
||||
public function injectRequestBuilder(\TYPO3\CMS\Extbase\Mvc\Web\RequestBuilder $requestBuilder)
|
||||
{
|
||||
$this->requestBuilder = $requestBuilder;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param \TYPO3\CMS\Extbase\Object\ObjectManagerInterface $objectManager
|
||||
*/
|
||||
public function injectObjectManager(\TYPO3\CMS\Extbase\Object\ObjectManagerInterface $objectManager)
|
||||
{
|
||||
$this->objectManager = $objectManager;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param \TYPO3\CMS\Extbase\Service\EnvironmentService $environmentService
|
||||
*/
|
||||
public function injectEnvironmentService(\TYPO3\CMS\Extbase\Service\EnvironmentService $environmentService)
|
||||
{
|
||||
$this->environmentService = $environmentService;
|
||||
}
|
||||
|
||||
/**
|
||||
* This request handler can handle any web request.
|
||||
*
|
||||
* @return bool If the request is a web request, TRUE otherwise FALSE
|
||||
*/
|
||||
public function canHandleRequest()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the priority - how eager the handler is to actually handle the
|
||||
* request.
|
||||
*
|
||||
* @return int The priority of the request handler.
|
||||
*/
|
||||
public function getPriority()
|
||||
{
|
||||
return 100;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
<?php
|
||||
namespace TYPO3\CMS\Extbase\Mvc\Web;
|
||||
|
||||
/*
|
||||
* This file is part of the TYPO3 CMS project.
|
||||
*
|
||||
* It is free software; you can redistribute it and/or modify it under
|
||||
* the terms of the GNU General Public License, either version 2
|
||||
* of the License, or any later version.
|
||||
*
|
||||
* For the full copyright and license information, please read the
|
||||
* LICENSE.txt file that was distributed with this source code.
|
||||
*
|
||||
* The TYPO3 project - inspiring people to share!
|
||||
*/
|
||||
|
||||
use TYPO3\CMS\Core\Core\Environment;
|
||||
|
||||
/**
|
||||
* A request handler which can handle web requests invoked by the backend.
|
||||
* @internal only to be used within Extbase, not part of TYPO3 Core API.
|
||||
*/
|
||||
class BackendRequestHandler extends AbstractRequestHandler
|
||||
{
|
||||
/**
|
||||
* Handles the web request. The response will automatically be sent to the client.
|
||||
*
|
||||
* @return \TYPO3\CMS\Extbase\Mvc\Web\Response
|
||||
*/
|
||||
public function handleRequest()
|
||||
{
|
||||
$request = $this->requestBuilder->build();
|
||||
/** @var \TYPO3\CMS\Extbase\Mvc\ResponseInterface $response */
|
||||
$response = $this->objectManager->get(\TYPO3\CMS\Extbase\Mvc\Web\Response::class);
|
||||
$this->dispatcher->dispatch($request, $response);
|
||||
return $response;
|
||||
}
|
||||
|
||||
/**
|
||||
* This request handler can handle a web request invoked by the backend.
|
||||
*
|
||||
* @return bool If we are in backend mode TRUE otherwise FALSE
|
||||
*/
|
||||
public function canHandleRequest()
|
||||
{
|
||||
return $this->environmentService->isEnvironmentInBackendMode() && !Environment::isCli();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,74 @@
|
||||
<?php
|
||||
declare(strict_types = 1);
|
||||
namespace TYPO3\CMS\Extbase\Mvc\Web;
|
||||
|
||||
/*
|
||||
* This file is part of the TYPO3 CMS project.
|
||||
*
|
||||
* It is free software; you can redistribute it and/or modify it under
|
||||
* the terms of the GNU General Public License, either version 2
|
||||
* of the License, or any later version.
|
||||
*
|
||||
* For the full copyright and license information, please read the
|
||||
* LICENSE.txt file that was distributed with this source code.
|
||||
*
|
||||
* The TYPO3 project - inspiring people to share!
|
||||
*/
|
||||
|
||||
use TYPO3\CMS\Core\SingletonInterface;
|
||||
use TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController;
|
||||
use TYPO3\CMS\Frontend\Page\CacheHashCalculator;
|
||||
|
||||
/**
|
||||
* Enforces cHash argument if it is required for a given request
|
||||
* @internal only to be used within Extbase, not part of TYPO3 Core API.
|
||||
*/
|
||||
class CacheHashEnforcer implements SingletonInterface
|
||||
{
|
||||
/**
|
||||
* @var CacheHashCalculator
|
||||
*/
|
||||
protected $cacheHashCalculator;
|
||||
|
||||
/**
|
||||
* @var TypoScriptFrontendController
|
||||
*/
|
||||
protected $typoScriptFrontendController;
|
||||
|
||||
/**
|
||||
* CacheHashEnforcer constructor.
|
||||
*
|
||||
* @param CacheHashCalculator $cacheHashCalculator
|
||||
* @param TypoScriptFrontendController|null $typoScriptFrontendController
|
||||
*/
|
||||
public function __construct(
|
||||
CacheHashCalculator $cacheHashCalculator,
|
||||
TypoScriptFrontendController $typoScriptFrontendController = null
|
||||
) {
|
||||
$this->cacheHashCalculator = $cacheHashCalculator;
|
||||
$this->typoScriptFrontendController = $typoScriptFrontendController ?: $GLOBALS['TSFE'];
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if cHash is required for the current request and calls
|
||||
* TypoScriptFrontendController::reqCHash() if so.
|
||||
* This call will trigger a PageNotFoundException if arguments are required and cHash is not present.
|
||||
*
|
||||
* @param Request $request
|
||||
* @param string $pluginNamespace
|
||||
*/
|
||||
public function enforceForRequest(Request $request, string $pluginNamespace)
|
||||
{
|
||||
$arguments = $request->getArguments();
|
||||
if (is_array($arguments) && count($arguments) > 0) {
|
||||
$parameters = [$pluginNamespace => $arguments];
|
||||
$parameters['id'] = $this->typoScriptFrontendController->id;
|
||||
$relevantParameters = $this->cacheHashCalculator->getRelevantParameters(
|
||||
http_build_query($parameters, '', '&', PHP_QUERY_RFC3986)
|
||||
);
|
||||
if (count($relevantParameters) > 0) {
|
||||
$this->typoScriptFrontendController->reqCHash();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,105 @@
|
||||
<?php
|
||||
namespace TYPO3\CMS\Extbase\Mvc\Web;
|
||||
|
||||
/*
|
||||
* This file is part of the TYPO3 CMS project.
|
||||
*
|
||||
* It is free software; you can redistribute it and/or modify it under
|
||||
* the terms of the GNU General Public License, either version 2
|
||||
* of the License, or any later version.
|
||||
*
|
||||
* For the full copyright and license information, please read the
|
||||
* LICENSE.txt file that was distributed with this source code.
|
||||
*
|
||||
* The TYPO3 project - inspiring people to share!
|
||||
*/
|
||||
|
||||
/**
|
||||
* A request handler which can handle web requests invoked by the frontend.
|
||||
* @internal only to be used within Extbase, not part of TYPO3 Core API.
|
||||
*/
|
||||
class FrontendRequestHandler extends AbstractRequestHandler
|
||||
{
|
||||
/**
|
||||
* @var \TYPO3\CMS\Extbase\Configuration\ConfigurationManagerInterface
|
||||
*/
|
||||
protected $configurationManager;
|
||||
|
||||
/**
|
||||
* @var \TYPO3\CMS\Extbase\Service\ExtensionService
|
||||
*/
|
||||
protected $extensionService;
|
||||
|
||||
/**
|
||||
* @var \TYPO3\CMS\Extbase\Mvc\Web\CacheHashEnforcer
|
||||
*/
|
||||
protected $cacheHashEnforcer;
|
||||
|
||||
/**
|
||||
* @param \TYPO3\CMS\Extbase\Configuration\ConfigurationManagerInterface $configurationManager
|
||||
*/
|
||||
public function injectConfigurationManager(\TYPO3\CMS\Extbase\Configuration\ConfigurationManagerInterface $configurationManager)
|
||||
{
|
||||
$this->configurationManager = $configurationManager;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param \TYPO3\CMS\Extbase\Service\ExtensionService $extensionService
|
||||
*/
|
||||
public function injectExtensionService(\TYPO3\CMS\Extbase\Service\ExtensionService $extensionService)
|
||||
{
|
||||
$this->extensionService = $extensionService;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param \TYPO3\CMS\Extbase\Mvc\Web\CacheHashEnforcer $cacheHashEnforcer
|
||||
*/
|
||||
public function injectCacheHashEnforcer(\TYPO3\CMS\Extbase\Mvc\Web\CacheHashEnforcer $cacheHashEnforcer)
|
||||
{
|
||||
$this->cacheHashEnforcer = $cacheHashEnforcer;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles the web request. The response will automatically be sent to the client.
|
||||
*
|
||||
* @return \TYPO3\CMS\Extbase\Mvc\ResponseInterface|null
|
||||
*/
|
||||
public function handleRequest()
|
||||
{
|
||||
$request = $this->requestBuilder->build();
|
||||
if ($this->extensionService->isActionCacheable(null, null, $request->getControllerName(), $request->getControllerActionName())) {
|
||||
$request->setIsCached(true);
|
||||
} else {
|
||||
$contentObject = $this->configurationManager->getContentObject();
|
||||
if ($contentObject->getUserObjectType() === \TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer::OBJECTTYPE_USER) {
|
||||
$contentObject->convertToUserIntObject();
|
||||
// \TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer::convertToUserIntObject() will recreate the object, so we have to stop the request here
|
||||
return null;
|
||||
}
|
||||
$request->setIsCached(false);
|
||||
}
|
||||
|
||||
if ($this->configurationManager->isFeatureEnabled('requireCHashArgumentForActionArguments')) {
|
||||
$pluginNamespace = $this->extensionService->getPluginNamespace(
|
||||
$request->getControllerExtensionName(),
|
||||
$request->getPluginName()
|
||||
);
|
||||
$this->cacheHashEnforcer->enforceForRequest($request, $pluginNamespace);
|
||||
}
|
||||
|
||||
/** @var \TYPO3\CMS\Extbase\Mvc\ResponseInterface $response */
|
||||
$response = $this->objectManager->get(\TYPO3\CMS\Extbase\Mvc\Web\Response::class);
|
||||
$this->dispatcher->dispatch($request, $response);
|
||||
return $response;
|
||||
}
|
||||
|
||||
/**
|
||||
* This request handler can handle any web request.
|
||||
*
|
||||
* @return bool If the request is a web request, TRUE otherwise FALSE
|
||||
*/
|
||||
public function canHandleRequest()
|
||||
{
|
||||
return $this->environmentService->isEnvironmentInFrontendMode();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
<?php
|
||||
namespace TYPO3\CMS\Extbase\Mvc\Web;
|
||||
|
||||
/*
|
||||
* This file is part of the TYPO3 CMS project.
|
||||
*
|
||||
* It is free software; you can redistribute it and/or modify it under
|
||||
* the terms of the GNU General Public License, either version 2
|
||||
* of the License, or any later version.
|
||||
*
|
||||
* For the full copyright and license information, please read the
|
||||
* LICENSE.txt file that was distributed with this source code.
|
||||
*
|
||||
* The TYPO3 project - inspiring people to share!
|
||||
*/
|
||||
|
||||
/**
|
||||
* Represents a referring web request.
|
||||
*/
|
||||
class ReferringRequest extends Request
|
||||
{
|
||||
/**
|
||||
* Sets the value of the specified argument
|
||||
*
|
||||
* @param string $argumentName Name of the argument to set
|
||||
* @param mixed $value The new value
|
||||
*/
|
||||
public function setArgument($argumentName, $value)
|
||||
{
|
||||
parent::setArgument($argumentName, $value);
|
||||
|
||||
switch ($argumentName) {
|
||||
case '@extension':
|
||||
$this->setControllerExtensionName($value);
|
||||
break;
|
||||
case '@subpackage':
|
||||
$this->setControllerSubpackageKey($value);
|
||||
break;
|
||||
case '@controller':
|
||||
$this->setControllerName($value);
|
||||
break;
|
||||
case '@action':
|
||||
$this->setControllerActionName($value);
|
||||
break;
|
||||
case '@format':
|
||||
$this->setFormat($value);
|
||||
break;
|
||||
case '@vendor':
|
||||
$this->setControllerVendorName($value);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,202 @@
|
||||
<?php
|
||||
namespace TYPO3\CMS\Extbase\Mvc\Web;
|
||||
|
||||
/*
|
||||
* This file is part of the TYPO3 CMS project.
|
||||
*
|
||||
* It is free software; you can redistribute it and/or modify it under
|
||||
* the terms of the GNU General Public License, either version 2
|
||||
* of the License, or any later version.
|
||||
*
|
||||
* For the full copyright and license information, please read the
|
||||
* LICENSE.txt file that was distributed with this source code.
|
||||
*
|
||||
* The TYPO3 project - inspiring people to share!
|
||||
*/
|
||||
|
||||
/**
|
||||
* Represents a web request.
|
||||
*/
|
||||
class Request extends \TYPO3\CMS\Extbase\Mvc\Request
|
||||
{
|
||||
/**
|
||||
* @var \TYPO3\CMS\Extbase\Security\Cryptography\HashService
|
||||
*/
|
||||
protected $hashService;
|
||||
|
||||
/**
|
||||
* @var string The requested representation format
|
||||
*/
|
||||
protected $format = 'html';
|
||||
|
||||
/**
|
||||
* @var string Contains the request method
|
||||
*/
|
||||
protected $method = 'GET';
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
protected $requestUri;
|
||||
|
||||
/**
|
||||
* @var string The base URI for this request - ie. the host and path leading to the index.php
|
||||
*/
|
||||
protected $baseUri;
|
||||
|
||||
/**
|
||||
* @var bool TRUE if the current request is cached, false otherwise.
|
||||
*/
|
||||
protected $isCached = false;
|
||||
|
||||
/**
|
||||
* @var \TYPO3\CMS\Extbase\Configuration\ConfigurationManagerInterface
|
||||
*/
|
||||
protected $configurationManager;
|
||||
|
||||
/**
|
||||
* @var \TYPO3\CMS\Extbase\Service\EnvironmentService
|
||||
*/
|
||||
protected $environmentService;
|
||||
|
||||
/**
|
||||
* @param \TYPO3\CMS\Extbase\Security\Cryptography\HashService $hashService
|
||||
* @internal only to be used within Extbase, not part of TYPO3 Core API.
|
||||
*/
|
||||
public function injectHashService(\TYPO3\CMS\Extbase\Security\Cryptography\HashService $hashService)
|
||||
{
|
||||
$this->hashService = $hashService;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param \TYPO3\CMS\Extbase\Configuration\ConfigurationManagerInterface $configurationManager
|
||||
* @internal only to be used within Extbase, not part of TYPO3 Core API.
|
||||
*/
|
||||
public function injectConfigurationManager(\TYPO3\CMS\Extbase\Configuration\ConfigurationManagerInterface $configurationManager)
|
||||
{
|
||||
$this->configurationManager = $configurationManager;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param \TYPO3\CMS\Extbase\Service\EnvironmentService $environmentService
|
||||
* @internal only to be used within Extbase, not part of TYPO3 Core API.
|
||||
*/
|
||||
public function injectEnvironmentService(\TYPO3\CMS\Extbase\Service\EnvironmentService $environmentService)
|
||||
{
|
||||
$this->environmentService = $environmentService;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the request method
|
||||
*
|
||||
* @param string $method Name of the request method
|
||||
* @throws \TYPO3\CMS\Extbase\Mvc\Exception\InvalidRequestMethodException if the request method is not supported
|
||||
* @internal only to be used within Extbase, not part of TYPO3 Core API.
|
||||
*/
|
||||
public function setMethod($method)
|
||||
{
|
||||
if ($method === '' || strtoupper($method) !== $method) {
|
||||
throw new \TYPO3\CMS\Extbase\Mvc\Exception\InvalidRequestMethodException('The request method "' . $method . '" is not supported.', 1217778382);
|
||||
}
|
||||
$this->method = $method;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the name of the request method
|
||||
*
|
||||
* @return string Name of the request method
|
||||
*/
|
||||
public function getMethod()
|
||||
{
|
||||
return $this->method;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the request URI
|
||||
*
|
||||
* @param string $requestUri URI of this web request
|
||||
* @internal only to be used within Extbase, not part of TYPO3 Core API.
|
||||
*/
|
||||
public function setRequestUri($requestUri)
|
||||
{
|
||||
$this->requestUri = $requestUri;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the request URI
|
||||
*
|
||||
* @return string URI of this web request
|
||||
*/
|
||||
public function getRequestUri()
|
||||
{
|
||||
return $this->requestUri;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the base URI for this request.
|
||||
*
|
||||
* @param string $baseUri New base URI
|
||||
* @internal only to be used within Extbase, not part of TYPO3 Core API.
|
||||
*/
|
||||
public function setBaseUri($baseUri)
|
||||
{
|
||||
$this->baseUri = $baseUri;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the base URI
|
||||
*
|
||||
* @return string Base URI of this web request
|
||||
*/
|
||||
public function getBaseUri()
|
||||
{
|
||||
if ($this->environmentService->isEnvironmentInBackendMode()) {
|
||||
return $this->baseUri . TYPO3_mainDir;
|
||||
}
|
||||
return $this->baseUri;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set if the current request is cached.
|
||||
*
|
||||
* @param bool $isCached
|
||||
* @internal only to be used within Extbase, not part of TYPO3 Core API.
|
||||
*/
|
||||
public function setIsCached($isCached)
|
||||
{
|
||||
$this->isCached = (bool)$isCached;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return whether the current request is a cached request or not.
|
||||
*
|
||||
* @return bool the caching status.
|
||||
* @internal only to be used within Extbase, not part of TYPO3 Core API.
|
||||
*/
|
||||
public function isCached()
|
||||
{
|
||||
return $this->isCached;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a freshly built request object pointing to the Referrer.
|
||||
*
|
||||
* @return ReferringRequest the referring request, or null if no referrer found
|
||||
* @internal only to be used within Extbase, not part of TYPO3 Core API.
|
||||
*/
|
||||
public function getReferringRequest()
|
||||
{
|
||||
if (isset($this->internalArguments['__referrer']['@request'])) {
|
||||
$referrerArray = unserialize($this->hashService->validateAndStripHmac($this->internalArguments['__referrer']['@request']), ['allowed_classes' => false]);
|
||||
$arguments = [];
|
||||
if (isset($this->internalArguments['__referrer']['arguments'])) {
|
||||
// This case is kept for compatibility in 7.6 and 6.2, but will be removed in 8
|
||||
$arguments = unserialize(base64_decode($this->hashService->validateAndStripHmac($this->internalArguments['__referrer']['arguments'])));
|
||||
}
|
||||
$referringRequest = new ReferringRequest();
|
||||
$referringRequest->setArguments(array_replace_recursive($arguments, $referrerArray));
|
||||
return $referringRequest;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,344 @@
|
||||
<?php
|
||||
namespace TYPO3\CMS\Extbase\Mvc\Web;
|
||||
|
||||
/*
|
||||
* This file is part of the TYPO3 CMS project.
|
||||
*
|
||||
* It is free software; you can redistribute it and/or modify it under
|
||||
* the terms of the GNU General Public License, either version 2
|
||||
* of the License, or any later version.
|
||||
*
|
||||
* For the full copyright and license information, please read the
|
||||
* LICENSE.txt file that was distributed with this source code.
|
||||
*
|
||||
* The TYPO3 project - inspiring people to share!
|
||||
*/
|
||||
|
||||
use Psr\Http\Message\ServerRequestInterface;
|
||||
use TYPO3\CMS\Core\Routing\PageArguments;
|
||||
use TYPO3\CMS\Core\Utility\ArrayUtility;
|
||||
use TYPO3\CMS\Core\Utility\Exception\MissingArrayPathException;
|
||||
use TYPO3\CMS\Extbase\Configuration\ConfigurationManagerInterface;
|
||||
use TYPO3\CMS\Extbase\Mvc\Exception as MvcException;
|
||||
|
||||
/**
|
||||
* Builds a web request.
|
||||
* @internal only to be used within Extbase, not part of TYPO3 Core API.
|
||||
*/
|
||||
class RequestBuilder implements \TYPO3\CMS\Core\SingletonInterface
|
||||
{
|
||||
/**
|
||||
* @var \TYPO3\CMS\Extbase\Object\ObjectManagerInterface
|
||||
*/
|
||||
protected $objectManager;
|
||||
|
||||
/**
|
||||
* This is the vendor name of the extension
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $vendorName;
|
||||
|
||||
/**
|
||||
* This is a unique key for a plugin (not the extension key!)
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $pluginName = 'plugin';
|
||||
|
||||
/**
|
||||
* The name of the extension (in UpperCamelCase)
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $extensionName;
|
||||
|
||||
/**
|
||||
* The default controller name
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $defaultControllerName = '';
|
||||
|
||||
/**
|
||||
* The default format of the response object
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $defaultFormat = 'html';
|
||||
|
||||
/**
|
||||
* The allowed actions of the controller. This actions can be called via $_GET and $_POST.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $allowedControllerActions = [];
|
||||
|
||||
/**
|
||||
* @var \TYPO3\CMS\Extbase\Configuration\ConfigurationManagerInterface
|
||||
*/
|
||||
protected $configurationManager;
|
||||
|
||||
/**
|
||||
* @var \TYPO3\CMS\Extbase\Service\ExtensionService
|
||||
*/
|
||||
protected $extensionService;
|
||||
|
||||
/**
|
||||
* @var \TYPO3\CMS\Extbase\Service\EnvironmentService
|
||||
*/
|
||||
protected $environmentService;
|
||||
|
||||
/**
|
||||
* @param \TYPO3\CMS\Extbase\Object\ObjectManagerInterface $objectManager
|
||||
*/
|
||||
public function injectObjectManager(\TYPO3\CMS\Extbase\Object\ObjectManagerInterface $objectManager)
|
||||
{
|
||||
$this->objectManager = $objectManager;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param \TYPO3\CMS\Extbase\Configuration\ConfigurationManagerInterface $configurationManager
|
||||
*/
|
||||
public function injectConfigurationManager(\TYPO3\CMS\Extbase\Configuration\ConfigurationManagerInterface $configurationManager)
|
||||
{
|
||||
$this->configurationManager = $configurationManager;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param \TYPO3\CMS\Extbase\Service\ExtensionService $extensionService
|
||||
*/
|
||||
public function injectExtensionService(\TYPO3\CMS\Extbase\Service\ExtensionService $extensionService)
|
||||
{
|
||||
$this->extensionService = $extensionService;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param \TYPO3\CMS\Extbase\Service\EnvironmentService $environmentService
|
||||
*/
|
||||
public function injectEnvironmentService(\TYPO3\CMS\Extbase\Service\EnvironmentService $environmentService)
|
||||
{
|
||||
$this->environmentService = $environmentService;
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws MvcException
|
||||
*/
|
||||
protected function loadDefaultValues()
|
||||
{
|
||||
$configuration = $this->configurationManager->getConfiguration(ConfigurationManagerInterface::CONFIGURATION_TYPE_FRAMEWORK);
|
||||
if (empty($configuration['extensionName'])) {
|
||||
throw new MvcException('"extensionName" is not properly configured. Request can\'t be dispatched!', 1289843275);
|
||||
}
|
||||
if (empty($configuration['pluginName'])) {
|
||||
throw new MvcException('"pluginName" is not properly configured. Request can\'t be dispatched!', 1289843277);
|
||||
}
|
||||
if (!empty($configuration['vendorName'])) {
|
||||
$this->vendorName = $configuration['vendorName'];
|
||||
} else {
|
||||
$this->vendorName = null;
|
||||
}
|
||||
$this->extensionName = $configuration['extensionName'];
|
||||
$this->pluginName = $configuration['pluginName'];
|
||||
$this->defaultControllerName = (string)current(array_keys($configuration['controllerConfiguration']));
|
||||
$this->allowedControllerActions = [];
|
||||
foreach ($configuration['controllerConfiguration'] as $controllerName => $controllerActions) {
|
||||
$this->allowedControllerActions[$controllerName] = $controllerActions['actions'] ?? null;
|
||||
}
|
||||
if (!empty($configuration['format'])) {
|
||||
$this->defaultFormat = $configuration['format'];
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Builds a web request object from the raw HTTP information and the configuration
|
||||
*
|
||||
* @return \TYPO3\CMS\Extbase\Mvc\Web\Request The web request as an object
|
||||
*/
|
||||
public function build()
|
||||
{
|
||||
$this->loadDefaultValues();
|
||||
$pluginNamespace = $this->extensionService->getPluginNamespace($this->extensionName, $this->pluginName);
|
||||
/** @var \TYPO3\CMS\Core\Http\ServerRequest $typo3Request */
|
||||
$typo3Request = $GLOBALS['TYPO3_REQUEST'] ?? null;
|
||||
if ($typo3Request instanceof ServerRequestInterface) {
|
||||
$queryArguments = $typo3Request->getAttribute('routing');
|
||||
if ($queryArguments instanceof PageArguments) {
|
||||
$getParameters = $queryArguments->get($pluginNamespace) ?? [];
|
||||
} else {
|
||||
$getParameters = $typo3Request->getQueryParams()[$pluginNamespace] ?? [];
|
||||
}
|
||||
$bodyParameters = $typo3Request->getParsedBody()[$pluginNamespace] ?? [];
|
||||
$bodyParameters = is_array($bodyParameters) ? $bodyParameters : [];
|
||||
$parameters = is_array($getParameters) ? $getParameters : [];
|
||||
ArrayUtility::mergeRecursiveWithOverrule($parameters, $bodyParameters);
|
||||
} else {
|
||||
$parameters = \TYPO3\CMS\Core\Utility\GeneralUtility::_GPmerged($pluginNamespace);
|
||||
}
|
||||
|
||||
$files = $this->untangleFilesArray($_FILES);
|
||||
if (is_array($files[$pluginNamespace] ?? null)) {
|
||||
$parameters = array_replace_recursive($parameters, $files[$pluginNamespace]);
|
||||
}
|
||||
|
||||
$controllerName = $this->resolveControllerName($parameters);
|
||||
$actionName = $this->resolveActionName($controllerName, $parameters);
|
||||
/** @var \TYPO3\CMS\Extbase\Mvc\Web\Request $request */
|
||||
$request = $this->objectManager->get(\TYPO3\CMS\Extbase\Mvc\Web\Request::class);
|
||||
if ($this->vendorName !== null) {
|
||||
$request->setControllerVendorName($this->vendorName);
|
||||
}
|
||||
$request->setPluginName($this->pluginName);
|
||||
$request->setControllerExtensionName($this->extensionName);
|
||||
$request->setControllerName($controllerName);
|
||||
$request->setControllerActionName($actionName);
|
||||
// @todo Use Environment
|
||||
$request->setRequestUri(\TYPO3\CMS\Core\Utility\GeneralUtility::getIndpEnv('TYPO3_REQUEST_URL'));
|
||||
$request->setBaseUri(\TYPO3\CMS\Core\Utility\GeneralUtility::getIndpEnv('TYPO3_SITE_URL'));
|
||||
$request->setMethod($this->environmentService->getServerRequestMethod());
|
||||
if (isset($parameters['format']) && is_string($parameters['format']) && $parameters['format'] !== '') {
|
||||
$request->setFormat(filter_var($parameters['format'], FILTER_SANITIZE_STRING));
|
||||
} else {
|
||||
$request->setFormat($this->defaultFormat);
|
||||
}
|
||||
foreach ($parameters as $argumentName => $argumentValue) {
|
||||
$request->setArgument($argumentName, $argumentValue);
|
||||
}
|
||||
return $request;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the current ControllerName extracted from given $parameters.
|
||||
* If no controller is specified, the defaultControllerName will be returned.
|
||||
* If that's not available, an exception is thrown.
|
||||
*
|
||||
* @param array $parameters
|
||||
* @throws \TYPO3\CMS\Extbase\Mvc\Exception\InvalidControllerNameException
|
||||
* @throws MvcException if the controller could not be resolved
|
||||
* @throws \TYPO3\CMS\Core\Error\Http\PageNotFoundException
|
||||
* @return string
|
||||
*/
|
||||
protected function resolveControllerName(array $parameters)
|
||||
{
|
||||
if (!isset($parameters['controller']) || $parameters['controller'] === '') {
|
||||
if (empty($this->defaultControllerName)) {
|
||||
throw new MvcException('The default controller for extension "' . $this->extensionName . '" and plugin "' . $this->pluginName . '" can not be determined. Please check for TYPO3\\CMS\\Extbase\\Utility\\ExtensionUtility::configurePlugin() in your ext_localconf.php.', 1316104317);
|
||||
}
|
||||
return $this->defaultControllerName;
|
||||
}
|
||||
$allowedControllerNames = array_keys($this->allowedControllerActions);
|
||||
if (!in_array($parameters['controller'], $allowedControllerNames)) {
|
||||
$configuration = $this->configurationManager->getConfiguration(ConfigurationManagerInterface::CONFIGURATION_TYPE_FRAMEWORK);
|
||||
if (isset($configuration['mvc']['throwPageNotFoundExceptionIfActionCantBeResolved']) && (bool)$configuration['mvc']['throwPageNotFoundExceptionIfActionCantBeResolved']) {
|
||||
throw new \TYPO3\CMS\Core\Error\Http\PageNotFoundException('The requested resource was not found', 1313857897);
|
||||
}
|
||||
if (isset($configuration['mvc']['callDefaultActionIfActionCantBeResolved']) && (bool)$configuration['mvc']['callDefaultActionIfActionCantBeResolved']) {
|
||||
return $this->defaultControllerName;
|
||||
}
|
||||
throw new \TYPO3\CMS\Extbase\Mvc\Exception\InvalidControllerNameException(
|
||||
'The controller "' . $parameters['controller'] . '" is not allowed by plugin "' . $this->pluginName . '". Please check for TYPO3\\CMS\\Extbase\\Utility\\ExtensionUtility::configurePlugin() in your ext_localconf.php.',
|
||||
1313855173
|
||||
);
|
||||
}
|
||||
return filter_var($parameters['controller'], FILTER_SANITIZE_STRING);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the current actionName extracted from given $parameters.
|
||||
* If no action is specified, the defaultActionName will be returned.
|
||||
* If that's not available or the specified action is not defined in the current plugin, an exception is thrown.
|
||||
*
|
||||
* @param string $controllerName
|
||||
* @param array $parameters
|
||||
* @throws \TYPO3\CMS\Extbase\Mvc\Exception\InvalidActionNameException
|
||||
* @throws MvcException
|
||||
* @throws \TYPO3\CMS\Core\Error\Http\PageNotFoundException
|
||||
* @return string
|
||||
*/
|
||||
protected function resolveActionName($controllerName, array $parameters)
|
||||
{
|
||||
$defaultActionName = is_array($this->allowedControllerActions[$controllerName]) ? current($this->allowedControllerActions[$controllerName]) : '';
|
||||
if (!isset($parameters['action']) || $parameters['action'] === '') {
|
||||
if ($defaultActionName === '') {
|
||||
throw new MvcException('The default action can not be determined for controller "' . $controllerName . '". Please check TYPO3\\CMS\\Extbase\\Utility\\ExtensionUtility::configurePlugin() in your ext_localconf.php.', 1295479651);
|
||||
}
|
||||
return $defaultActionName;
|
||||
}
|
||||
$actionName = $parameters['action'];
|
||||
$allowedActionNames = $this->allowedControllerActions[$controllerName];
|
||||
if (!in_array($actionName, $allowedActionNames)) {
|
||||
$configuration = $this->configurationManager->getConfiguration(ConfigurationManagerInterface::CONFIGURATION_TYPE_FRAMEWORK);
|
||||
if (isset($configuration['mvc']['throwPageNotFoundExceptionIfActionCantBeResolved']) && (bool)$configuration['mvc']['throwPageNotFoundExceptionIfActionCantBeResolved']) {
|
||||
throw new \TYPO3\CMS\Core\Error\Http\PageNotFoundException('The requested resource was not found', 1313857898);
|
||||
}
|
||||
if (isset($configuration['mvc']['callDefaultActionIfActionCantBeResolved']) && (bool)$configuration['mvc']['callDefaultActionIfActionCantBeResolved']) {
|
||||
return $defaultActionName;
|
||||
}
|
||||
throw new \TYPO3\CMS\Extbase\Mvc\Exception\InvalidActionNameException('The action "' . $actionName . '" (controller "' . $controllerName . '") is not allowed by this plugin / module. Please check TYPO3\\CMS\\Extbase\\Utility\\ExtensionUtility::configurePlugin() in your ext_localconf.php / TYPO3\\CMS\\Extbase\\Utility\\ExtensionUtility::configureModule() in your ext_tables.php.', 1313855175);
|
||||
}
|
||||
return filter_var($actionName, FILTER_SANITIZE_STRING);
|
||||
}
|
||||
|
||||
/**
|
||||
* Transforms the convoluted _FILES superglobal into a manageable form.
|
||||
*
|
||||
* @param array $convolutedFiles The _FILES superglobal
|
||||
* @return array Untangled files
|
||||
*/
|
||||
protected function untangleFilesArray(array $convolutedFiles)
|
||||
{
|
||||
$untangledFiles = [];
|
||||
$fieldPaths = [];
|
||||
foreach ($convolutedFiles as $firstLevelFieldName => $fieldInformation) {
|
||||
if (!is_array($fieldInformation['error'])) {
|
||||
$fieldPaths[] = [$firstLevelFieldName];
|
||||
} else {
|
||||
$newFieldPaths = $this->calculateFieldPaths($fieldInformation['error'], $firstLevelFieldName);
|
||||
array_walk($newFieldPaths, function (&$value, $key) {
|
||||
$value = explode('/', $value);
|
||||
});
|
||||
$fieldPaths = array_merge($fieldPaths, $newFieldPaths);
|
||||
}
|
||||
}
|
||||
foreach ($fieldPaths as $fieldPath) {
|
||||
if (count($fieldPath) === 1) {
|
||||
$fileInformation = $convolutedFiles[$fieldPath[0]];
|
||||
} else {
|
||||
$fileInformation = [];
|
||||
foreach ($convolutedFiles[$fieldPath[0]] as $key => $subStructure) {
|
||||
try {
|
||||
$fileInformation[$key] = ArrayUtility::getValueByPath($subStructure, array_slice($fieldPath, 1));
|
||||
} catch (MissingArrayPathException $e) {
|
||||
// do nothing if the path is invalid
|
||||
}
|
||||
}
|
||||
}
|
||||
$untangledFiles = ArrayUtility::setValueByPath($untangledFiles, $fieldPath, $fileInformation);
|
||||
}
|
||||
return $untangledFiles;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an array of all possibles "field paths" for the given array.
|
||||
*
|
||||
* @param array $structure The array to walk through
|
||||
* @param string $firstLevelFieldName
|
||||
* @return array An array of paths (as strings) in the format "key1/key2/key3" ...
|
||||
*/
|
||||
protected function calculateFieldPaths(array $structure, $firstLevelFieldName = null)
|
||||
{
|
||||
$fieldPaths = [];
|
||||
if (is_array($structure)) {
|
||||
foreach ($structure as $key => $subStructure) {
|
||||
$fieldPath = ($firstLevelFieldName !== null ? $firstLevelFieldName . '/' : '') . $key;
|
||||
if (is_array($subStructure)) {
|
||||
foreach ($this->calculateFieldPaths($subStructure) as $subFieldPath) {
|
||||
$fieldPaths[] = $fieldPath . '/' . $subFieldPath;
|
||||
}
|
||||
} else {
|
||||
$fieldPaths[] = $fieldPath;
|
||||
}
|
||||
}
|
||||
}
|
||||
return $fieldPaths;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,341 @@
|
||||
<?php
|
||||
namespace TYPO3\CMS\Extbase\Mvc\Web;
|
||||
|
||||
/*
|
||||
* This file is part of the TYPO3 CMS project.
|
||||
*
|
||||
* It is free software; you can redistribute it and/or modify it under
|
||||
* the terms of the GNU General Public License, either version 2
|
||||
* of the License, or any later version.
|
||||
*
|
||||
* For the full copyright and license information, please read the
|
||||
* LICENSE.txt file that was distributed with this source code.
|
||||
*
|
||||
* The TYPO3 project - inspiring people to share!
|
||||
*/
|
||||
|
||||
use TYPO3\CMS\Core\Page\PageRenderer;
|
||||
use TYPO3\CMS\Core\Utility\GeneralUtility;
|
||||
use TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController;
|
||||
|
||||
/**
|
||||
* A web specific response implementation
|
||||
*/
|
||||
class Response extends \TYPO3\CMS\Extbase\Mvc\Response
|
||||
{
|
||||
/**
|
||||
* The HTTP headers which will be sent in the response
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $headers = [];
|
||||
|
||||
/**
|
||||
* Additional header tags
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $additionalHeaderData = [];
|
||||
|
||||
/**
|
||||
* The HTTP status code
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
protected $statusCode;
|
||||
|
||||
/**
|
||||
* The HTTP status message
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $statusMessage = 'OK';
|
||||
|
||||
/**
|
||||
* The Request which generated the Response
|
||||
*
|
||||
* @var \TYPO3\CMS\Extbase\Mvc\Web\Request
|
||||
*/
|
||||
protected $request;
|
||||
|
||||
/**
|
||||
* The standardized and other important HTTP Status messages
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $statusMessages = [
|
||||
// INFORMATIONAL CODES
|
||||
100 => 'Continue',
|
||||
101 => 'Switching Protocols',
|
||||
102 => 'Processing',
|
||||
103 => 'Early Hints',
|
||||
// SUCCESS CODES
|
||||
200 => 'OK',
|
||||
201 => 'Created',
|
||||
202 => 'Accepted',
|
||||
203 => 'Non-Authoritative Information',
|
||||
204 => 'No Content',
|
||||
205 => 'Reset Content',
|
||||
206 => 'Partial Content',
|
||||
207 => 'Multi-status',
|
||||
208 => 'Already Reported',
|
||||
226 => 'IM Used',
|
||||
// REDIRECTION CODES
|
||||
300 => 'Multiple Choices',
|
||||
301 => 'Moved Permanently',
|
||||
302 => 'Found',
|
||||
303 => 'See Other',
|
||||
304 => 'Not Modified',
|
||||
305 => 'Use Proxy',
|
||||
306 => 'Switch Proxy', // Deprecated
|
||||
307 => 'Temporary Redirect',
|
||||
308 => 'Permanent Redirect',
|
||||
// CLIENT ERROR
|
||||
400 => 'Bad Request',
|
||||
401 => 'Unauthorized',
|
||||
402 => 'Payment Required',
|
||||
403 => 'Forbidden',
|
||||
404 => 'Not Found',
|
||||
405 => 'Method Not Allowed',
|
||||
406 => 'Not Acceptable',
|
||||
407 => 'Proxy Authentication Required',
|
||||
408 => 'Request Timeout',
|
||||
409 => 'Conflict',
|
||||
410 => 'Gone',
|
||||
411 => 'Length Required',
|
||||
412 => 'Precondition Failed',
|
||||
413 => 'Request Entity Too Large',
|
||||
414 => 'URI Too Long',
|
||||
415 => 'Unsupported Media Type',
|
||||
416 => 'Requested range not satisfiable',
|
||||
417 => 'Expectation Failed',
|
||||
418 => 'I\'m a teapot',
|
||||
422 => 'Unprocessable Entity',
|
||||
423 => 'Locked',
|
||||
424 => 'Failed Dependency',
|
||||
425 => 'Unordered Collection',
|
||||
426 => 'Upgrade Required',
|
||||
428 => 'Precondition Required',
|
||||
429 => 'Too Many Requests',
|
||||
431 => 'Request Header Fields Too Large',
|
||||
451 => 'Unavailable For Legal Reasons',
|
||||
// SERVER ERROR
|
||||
500 => 'Internal Server Error',
|
||||
501 => 'Not Implemented',
|
||||
502 => 'Bad Gateway',
|
||||
503 => 'Service Unavailable',
|
||||
504 => 'Gateway Time-out',
|
||||
505 => 'HTTP Version not supported',
|
||||
506 => 'Variant Also Negotiates',
|
||||
507 => 'Insufficient Storage',
|
||||
508 => 'Loop Detected',
|
||||
509 => 'Bandwidth Limit Exceeded',
|
||||
511 => 'Network Authentication Required',
|
||||
];
|
||||
|
||||
/**
|
||||
* @var \TYPO3\CMS\Extbase\Service\EnvironmentService
|
||||
*/
|
||||
protected $environmentService;
|
||||
|
||||
/**
|
||||
* @param \TYPO3\CMS\Extbase\Service\EnvironmentService $environmentService
|
||||
* @internal only to be used within Extbase, not part of TYPO3 Core API.
|
||||
*/
|
||||
public function injectEnvironmentService(\TYPO3\CMS\Extbase\Service\EnvironmentService $environmentService)
|
||||
{
|
||||
$this->environmentService = $environmentService;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the HTTP status code and (optionally) a customized message.
|
||||
*
|
||||
* @param int $code The status code
|
||||
* @param string $message If specified, this message is sent instead of the standard message
|
||||
* @throws \InvalidArgumentException if the specified status code is not valid
|
||||
*/
|
||||
public function setStatus($code, $message = null)
|
||||
{
|
||||
if (!is_int($code)) {
|
||||
throw new \InvalidArgumentException('The HTTP status code must be of type integer, ' . gettype($code) . ' given.', 1220526013);
|
||||
}
|
||||
if ($message === null && !isset($this->statusMessages[$code])) {
|
||||
throw new \InvalidArgumentException('No message found for HTTP status code "' . $code . '".', 1220526014);
|
||||
}
|
||||
$this->statusCode = $code;
|
||||
$this->statusMessage = $message ?? $this->statusMessages[$code];
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns status code and status message.
|
||||
*
|
||||
* @return string The status code and status message, eg. "404 Not Found
|
||||
*/
|
||||
public function getStatus()
|
||||
{
|
||||
return $this->statusCode . ' ' . $this->statusMessage;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the status code, if not set, uses the OK status code 200
|
||||
*
|
||||
* @return int
|
||||
* @internal only use for backend module handling
|
||||
*/
|
||||
public function getStatusCode()
|
||||
{
|
||||
return $this->statusCode ?: 200;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the specified HTTP header
|
||||
*
|
||||
* @param string $name Name of the header, for example "Location", "Content-Description" etc.
|
||||
* @param mixed $value The value of the given header
|
||||
* @param bool $replaceExistingHeader If a header with the same name should be replaced. Default is TRUE.
|
||||
* @throws \InvalidArgumentException
|
||||
*/
|
||||
public function setHeader($name, $value, $replaceExistingHeader = true)
|
||||
{
|
||||
if (stripos($name, 'HTTP') === 0) {
|
||||
throw new \InvalidArgumentException('The HTTP status header must be set via setStatus().', 1220541963);
|
||||
}
|
||||
if ($replaceExistingHeader === true || !isset($this->headers[$name])) {
|
||||
$this->headers[$name] = [$value];
|
||||
} else {
|
||||
$this->headers[$name][] = $value;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the HTTP headers - including the status header - of this web response
|
||||
*
|
||||
* @return string[] The HTTP headers
|
||||
*/
|
||||
public function getHeaders()
|
||||
{
|
||||
$preparedHeaders = [];
|
||||
if ($this->statusCode !== null) {
|
||||
$protocolVersion = $_SERVER['SERVER_PROTOCOL'] ?? 'HTTP/1.0';
|
||||
$statusHeader = $protocolVersion . ' ' . $this->statusCode . ' ' . $this->statusMessage;
|
||||
$preparedHeaders[] = $statusHeader;
|
||||
}
|
||||
foreach ($this->headers as $name => $values) {
|
||||
foreach ($values as $value) {
|
||||
$preparedHeaders[] = $name . ': ' . $value;
|
||||
}
|
||||
}
|
||||
return $preparedHeaders;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the HTTP headers grouped by name without the status header
|
||||
*
|
||||
* @return array all headers set for this request
|
||||
* @internal only used within TYPO3 Core to convert to PSR-7 response headers
|
||||
*/
|
||||
public function getUnpreparedHeaders(): array
|
||||
{
|
||||
return $this->headers;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends the HTTP headers.
|
||||
*
|
||||
* If headers have already been sent, this method fails silently.
|
||||
*/
|
||||
public function sendHeaders()
|
||||
{
|
||||
if (headers_sent() === true) {
|
||||
return;
|
||||
}
|
||||
foreach ($this->getHeaders() as $header) {
|
||||
header($header);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Renders and sends the whole web response
|
||||
*/
|
||||
public function send()
|
||||
{
|
||||
$this->sendHeaders();
|
||||
if ($this->content !== null) {
|
||||
echo $this->getContent();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds an additional header data (something like
|
||||
* '<script src="myext/Resources/JavaScript/my.js" type="text/javascript"></script>'
|
||||
* )
|
||||
*
|
||||
* @TODO The workround and the $request member should be removed again, once the PageRender does support non-cached USER_INTs
|
||||
* @param string $additionalHeaderData The value additional header
|
||||
* @throws \InvalidArgumentException
|
||||
*/
|
||||
public function addAdditionalHeaderData($additionalHeaderData)
|
||||
{
|
||||
if (!is_string($additionalHeaderData)) {
|
||||
throw new \InvalidArgumentException('The additiona header data must be of type String, ' . gettype($additionalHeaderData) . ' given.', 1237370877);
|
||||
}
|
||||
if ($this->request->isCached()) {
|
||||
/** @var PageRenderer $pageRenderer */
|
||||
$pageRenderer = GeneralUtility::makeInstance(PageRenderer::class);
|
||||
$pageRenderer->addHeaderData($additionalHeaderData);
|
||||
} else {
|
||||
$this->additionalHeaderData[] = $additionalHeaderData;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the additional header data
|
||||
*
|
||||
* @return array The additional header data
|
||||
*/
|
||||
public function getAdditionalHeaderData()
|
||||
{
|
||||
return $this->additionalHeaderData;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param \TYPO3\CMS\Extbase\Mvc\Web\Request $request
|
||||
* @internal only to be used within Extbase, not part of TYPO3 Core API.
|
||||
*/
|
||||
public function setRequest(\TYPO3\CMS\Extbase\Mvc\Web\Request $request)
|
||||
{
|
||||
$this->request = $request;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return \TYPO3\CMS\Extbase\Mvc\Web\Request
|
||||
* @internal only to be used within Extbase, not part of TYPO3 Core API.
|
||||
*/
|
||||
public function getRequest()
|
||||
{
|
||||
return $this->request;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends additional headers and returns the content
|
||||
*
|
||||
* @return string|null
|
||||
* @internal only to be used within Extbase, not part of TYPO3 Core API.
|
||||
*/
|
||||
public function shutdown()
|
||||
{
|
||||
if (!empty($this->getAdditionalHeaderData())) {
|
||||
$this->getTypoScriptFrontendController()->additionalHeaderData[] = implode(LF, $this->getAdditionalHeaderData());
|
||||
}
|
||||
$this->sendHeaders();
|
||||
return parent::shutdown();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return TypoScriptFrontendController
|
||||
*/
|
||||
protected function getTypoScriptFrontendController()
|
||||
{
|
||||
return $GLOBALS['TSFE'];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,841 @@
|
||||
<?php
|
||||
namespace TYPO3\CMS\Extbase\Mvc\Web\Routing;
|
||||
|
||||
/*
|
||||
* This file is part of the TYPO3 CMS project.
|
||||
*
|
||||
* It is free software; you can redistribute it and/or modify it under
|
||||
* the terms of the GNU General Public License, either version 2
|
||||
* of the License, or any later version.
|
||||
*
|
||||
* For the full copyright and license information, please read the
|
||||
* LICENSE.txt file that was distributed with this source code.
|
||||
*
|
||||
* The TYPO3 project - inspiring people to share!
|
||||
*/
|
||||
|
||||
use TYPO3\CMS\Backend\Routing\Exception\ResourceNotFoundException;
|
||||
use TYPO3\CMS\Backend\Routing\Exception\RouteNotFoundException;
|
||||
use TYPO3\CMS\Core\Utility\ArrayUtility;
|
||||
use TYPO3\CMS\Core\Utility\GeneralUtility;
|
||||
use TYPO3\CMS\Core\Utility\HttpUtility;
|
||||
use TYPO3\CMS\Extbase\Mvc\Request;
|
||||
use TYPO3\CMS\Extbase\Mvc\Web\Request as WebRequest;
|
||||
|
||||
/**
|
||||
* An URI Builder
|
||||
*/
|
||||
class UriBuilder
|
||||
{
|
||||
/**
|
||||
* @var \TYPO3\CMS\Extbase\Configuration\ConfigurationManagerInterface
|
||||
*/
|
||||
protected $configurationManager;
|
||||
|
||||
/**
|
||||
* @var \TYPO3\CMS\Extbase\Service\ExtensionService
|
||||
*/
|
||||
protected $extensionService;
|
||||
|
||||
/**
|
||||
* An instance of \TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer
|
||||
*
|
||||
* @var \TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer
|
||||
*/
|
||||
protected $contentObject;
|
||||
|
||||
/**
|
||||
* @var Request
|
||||
*/
|
||||
protected $request;
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
protected $arguments = [];
|
||||
|
||||
/**
|
||||
* Arguments which have been used for building the last URI
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $lastArguments = [];
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
protected $section = '';
|
||||
|
||||
/**
|
||||
* @var bool
|
||||
*/
|
||||
protected $createAbsoluteUri = false;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
protected $absoluteUriScheme;
|
||||
|
||||
/**
|
||||
* @var bool
|
||||
*/
|
||||
protected $addQueryString = false;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
protected $addQueryStringMethod;
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
protected $argumentsToBeExcludedFromQueryString = [];
|
||||
|
||||
/**
|
||||
* @var bool
|
||||
*/
|
||||
protected $linkAccessRestrictedPages = false;
|
||||
|
||||
/**
|
||||
* @var int
|
||||
*/
|
||||
protected $targetPageUid;
|
||||
|
||||
/**
|
||||
* @var int
|
||||
*/
|
||||
protected $targetPageType = 0;
|
||||
|
||||
/**
|
||||
* @var bool
|
||||
*/
|
||||
protected $noCache = false;
|
||||
|
||||
/**
|
||||
* @var bool
|
||||
*/
|
||||
protected $useCacheHash = true;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
protected $format = '';
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
protected $argumentPrefix;
|
||||
|
||||
/**
|
||||
* @var \TYPO3\CMS\Extbase\Service\EnvironmentService
|
||||
*/
|
||||
protected $environmentService;
|
||||
|
||||
/**
|
||||
* @param \TYPO3\CMS\Extbase\Configuration\ConfigurationManagerInterface $configurationManager
|
||||
* @internal only to be used within Extbase, not part of TYPO3 Core API.
|
||||
*/
|
||||
public function injectConfigurationManager(\TYPO3\CMS\Extbase\Configuration\ConfigurationManagerInterface $configurationManager)
|
||||
{
|
||||
$this->configurationManager = $configurationManager;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param \TYPO3\CMS\Extbase\Service\ExtensionService $extensionService
|
||||
* @internal only to be used within Extbase, not part of TYPO3 Core API.
|
||||
*/
|
||||
public function injectExtensionService(\TYPO3\CMS\Extbase\Service\ExtensionService $extensionService)
|
||||
{
|
||||
$this->extensionService = $extensionService;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param \TYPO3\CMS\Extbase\Service\EnvironmentService $environmentService
|
||||
* @internal only to be used within Extbase, not part of TYPO3 Core API.
|
||||
*/
|
||||
public function injectEnvironmentService(\TYPO3\CMS\Extbase\Service\EnvironmentService $environmentService)
|
||||
{
|
||||
$this->environmentService = $environmentService;
|
||||
}
|
||||
|
||||
/**
|
||||
* Life-cycle method that is called by the DI container as soon as this object is completely built
|
||||
* @internal only to be used within Extbase, not part of TYPO3 Core API.
|
||||
*/
|
||||
public function initializeObject()
|
||||
{
|
||||
$this->contentObject = $this->configurationManager->getContentObject();
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the current request
|
||||
*
|
||||
* @param Request $request
|
||||
* @return \TYPO3\CMS\Extbase\Mvc\Web\Routing\UriBuilder the current UriBuilder to allow method chaining
|
||||
* @internal only to be used within Extbase, not part of TYPO3 Core API.
|
||||
*/
|
||||
public function setRequest(Request $request)
|
||||
{
|
||||
$this->request = $request;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Request
|
||||
* @internal only to be used within Extbase, not part of TYPO3 Core API.
|
||||
*/
|
||||
public function getRequest()
|
||||
{
|
||||
return $this->request;
|
||||
}
|
||||
|
||||
/**
|
||||
* Additional query parameters.
|
||||
* If you want to "prefix" arguments, you can pass in multidimensional arrays:
|
||||
* array('prefix1' => array('foo' => 'bar')) gets "&prefix1[foo]=bar"
|
||||
*
|
||||
* @param array $arguments
|
||||
* @return \TYPO3\CMS\Extbase\Mvc\Web\Routing\UriBuilder the current UriBuilder to allow method chaining
|
||||
*/
|
||||
public function setArguments(array $arguments)
|
||||
{
|
||||
$this->arguments = $arguments;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function getArguments()
|
||||
{
|
||||
return $this->arguments;
|
||||
}
|
||||
|
||||
/**
|
||||
* If specified, adds a given HTML anchor to the URI (#...)
|
||||
*
|
||||
* @param string $section
|
||||
* @return \TYPO3\CMS\Extbase\Mvc\Web\Routing\UriBuilder the current UriBuilder to allow method chaining
|
||||
*/
|
||||
public function setSection($section)
|
||||
{
|
||||
$this->section = $section;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getSection()
|
||||
{
|
||||
return $this->section;
|
||||
}
|
||||
|
||||
/**
|
||||
* Specifies the format of the target (e.g. "html" or "xml")
|
||||
*
|
||||
* @param string $format
|
||||
* @return \TYPO3\CMS\Extbase\Mvc\Web\Routing\UriBuilder the current UriBuilder to allow method chaining
|
||||
*/
|
||||
public function setFormat($format)
|
||||
{
|
||||
$this->format = $format;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getFormat()
|
||||
{
|
||||
return $this->format;
|
||||
}
|
||||
|
||||
/**
|
||||
* If set, the URI is prepended with the current base URI. Defaults to FALSE.
|
||||
*
|
||||
* @param bool $createAbsoluteUri
|
||||
* @return \TYPO3\CMS\Extbase\Mvc\Web\Routing\UriBuilder the current UriBuilder to allow method chaining
|
||||
*/
|
||||
public function setCreateAbsoluteUri($createAbsoluteUri)
|
||||
{
|
||||
$this->createAbsoluteUri = $createAbsoluteUri;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
public function getCreateAbsoluteUri()
|
||||
{
|
||||
return $this->createAbsoluteUri;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
* @internal only to be used within Extbase, not part of TYPO3 Core API.
|
||||
*/
|
||||
public function getAbsoluteUriScheme()
|
||||
{
|
||||
return $this->absoluteUriScheme;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the scheme that should be used for absolute URIs in FE mode
|
||||
*
|
||||
* @param string $absoluteUriScheme the scheme to be used for absolute URIs
|
||||
* @return \TYPO3\CMS\Extbase\Mvc\Web\Routing\UriBuilder the current UriBuilder to allow method chaining
|
||||
* @internal only to be used within Extbase, not part of TYPO3 Core API.
|
||||
*/
|
||||
public function setAbsoluteUriScheme($absoluteUriScheme)
|
||||
{
|
||||
$this->absoluteUriScheme = $absoluteUriScheme;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* If set, the current query parameters will be merged with $this->arguments. Defaults to FALSE.
|
||||
*
|
||||
* @param bool $addQueryString
|
||||
* @return \TYPO3\CMS\Extbase\Mvc\Web\Routing\UriBuilder the current UriBuilder to allow method chaining
|
||||
* @see TSref/typolink.addQueryString
|
||||
*/
|
||||
public function setAddQueryString($addQueryString)
|
||||
{
|
||||
$this->addQueryString = (bool)$addQueryString;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
public function getAddQueryString()
|
||||
{
|
||||
return $this->addQueryString;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the method to get the addQueryString parameters. Defaults undefined
|
||||
* which results in using QUERY_STRING.
|
||||
*
|
||||
* @param string $addQueryStringMethod
|
||||
* @return \TYPO3\CMS\Extbase\Mvc\Web\Routing\UriBuilder the current UriBuilder to allow method chaining
|
||||
* @see TSref/typolink.addQueryString.method
|
||||
*/
|
||||
public function setAddQueryStringMethod($addQueryStringMethod)
|
||||
{
|
||||
$this->addQueryStringMethod = $addQueryStringMethod;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getAddQueryStringMethod()
|
||||
{
|
||||
return (string)$this->addQueryStringMethod;
|
||||
}
|
||||
|
||||
/**
|
||||
* A list of arguments to be excluded from the query parameters
|
||||
* Only active if addQueryString is set
|
||||
*
|
||||
* @param array $argumentsToBeExcludedFromQueryString
|
||||
* @return \TYPO3\CMS\Extbase\Mvc\Web\Routing\UriBuilder the current UriBuilder to allow method chaining
|
||||
* @see TSref/typolink.addQueryString.exclude
|
||||
* @see setAddQueryString()
|
||||
*/
|
||||
public function setArgumentsToBeExcludedFromQueryString(array $argumentsToBeExcludedFromQueryString)
|
||||
{
|
||||
$this->argumentsToBeExcludedFromQueryString = $argumentsToBeExcludedFromQueryString;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function getArgumentsToBeExcludedFromQueryString()
|
||||
{
|
||||
return $this->argumentsToBeExcludedFromQueryString;
|
||||
}
|
||||
|
||||
/**
|
||||
* Specifies the prefix to be used for all arguments.
|
||||
*
|
||||
* @param string $argumentPrefix
|
||||
* @return \TYPO3\CMS\Extbase\Mvc\Web\Routing\UriBuilder the current UriBuilder to allow method chaining
|
||||
* @internal only to be used within Extbase, not part of TYPO3 Core API.
|
||||
*/
|
||||
public function setArgumentPrefix($argumentPrefix)
|
||||
{
|
||||
$this->argumentPrefix = (string)$argumentPrefix;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
* @internal only to be used within Extbase, not part of TYPO3 Core API.
|
||||
*/
|
||||
public function getArgumentPrefix()
|
||||
{
|
||||
return $this->argumentPrefix;
|
||||
}
|
||||
|
||||
/**
|
||||
* If set, URIs for pages without access permissions will be created
|
||||
*
|
||||
* @param bool $linkAccessRestrictedPages
|
||||
* @return \TYPO3\CMS\Extbase\Mvc\Web\Routing\UriBuilder the current UriBuilder to allow method chaining
|
||||
*/
|
||||
public function setLinkAccessRestrictedPages($linkAccessRestrictedPages)
|
||||
{
|
||||
$this->linkAccessRestrictedPages = (bool)$linkAccessRestrictedPages;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
public function getLinkAccessRestrictedPages()
|
||||
{
|
||||
return $this->linkAccessRestrictedPages;
|
||||
}
|
||||
|
||||
/**
|
||||
* Uid of the target page
|
||||
*
|
||||
* @param int $targetPageUid
|
||||
* @return \TYPO3\CMS\Extbase\Mvc\Web\Routing\UriBuilder the current UriBuilder to allow method chaining
|
||||
*/
|
||||
public function setTargetPageUid($targetPageUid)
|
||||
{
|
||||
$this->targetPageUid = $targetPageUid;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* returns $this->targetPageUid.
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function getTargetPageUid()
|
||||
{
|
||||
return $this->targetPageUid;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the page type of the target URI. Defaults to 0
|
||||
*
|
||||
* @param int $targetPageType
|
||||
* @return \TYPO3\CMS\Extbase\Mvc\Web\Routing\UriBuilder the current UriBuilder to allow method chaining
|
||||
*/
|
||||
public function setTargetPageType($targetPageType)
|
||||
{
|
||||
$this->targetPageType = (int)$targetPageType;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return int
|
||||
* @internal only to be used within Extbase, not part of TYPO3 Core API.
|
||||
*/
|
||||
public function getTargetPageType()
|
||||
{
|
||||
return $this->targetPageType;
|
||||
}
|
||||
|
||||
/**
|
||||
* by default FALSE; if TRUE, &no_cache=1 will be appended to the URI
|
||||
* This overrules the useCacheHash setting
|
||||
*
|
||||
* @param bool $noCache
|
||||
* @return \TYPO3\CMS\Extbase\Mvc\Web\Routing\UriBuilder the current UriBuilder to allow method chaining
|
||||
*/
|
||||
public function setNoCache($noCache)
|
||||
{
|
||||
$this->noCache = (bool)$noCache;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
public function getNoCache()
|
||||
{
|
||||
return $this->noCache;
|
||||
}
|
||||
|
||||
/**
|
||||
* by default TRUE; if FALSE, no cHash parameter will be appended to the URI
|
||||
* If noCache is set, this setting will be ignored.
|
||||
*
|
||||
* @param bool $useCacheHash
|
||||
* @return \TYPO3\CMS\Extbase\Mvc\Web\Routing\UriBuilder the current UriBuilder to allow method chaining
|
||||
*/
|
||||
public function setUseCacheHash($useCacheHash)
|
||||
{
|
||||
$this->useCacheHash = (bool)$useCacheHash;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
public function getUseCacheHash()
|
||||
{
|
||||
return $this->useCacheHash;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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
|
||||
* @internal only to be used within Extbase, not part of TYPO3 Core API.
|
||||
*/
|
||||
public function getLastArguments()
|
||||
{
|
||||
return $this->lastArguments;
|
||||
}
|
||||
|
||||
/**
|
||||
* Resets all UriBuilder options to their default value
|
||||
*
|
||||
* @return \TYPO3\CMS\Extbase\Mvc\Web\Routing\UriBuilder the current UriBuilder to allow method chaining
|
||||
*/
|
||||
public function reset()
|
||||
{
|
||||
$this->arguments = [];
|
||||
$this->section = '';
|
||||
$this->format = '';
|
||||
$this->createAbsoluteUri = false;
|
||||
$this->addQueryString = false;
|
||||
$this->addQueryStringMethod = null;
|
||||
$this->argumentsToBeExcludedFromQueryString = [];
|
||||
$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 string $actionName Name of the action to be called
|
||||
* @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
|
||||
* @see build()
|
||||
*/
|
||||
public function uriFor($actionName = null, $controllerArguments = [], $controllerName = null, $extensionName = null, $pluginName = null)
|
||||
{
|
||||
if ($actionName !== null) {
|
||||
$controllerArguments['action'] = $actionName;
|
||||
}
|
||||
if ($controllerName !== null) {
|
||||
$controllerArguments['controller'] = $controllerName;
|
||||
} else {
|
||||
$controllerArguments['controller'] = $this->request->getControllerName();
|
||||
}
|
||||
if ($extensionName === null) {
|
||||
$extensionName = $this->request->getControllerExtensionName();
|
||||
}
|
||||
if ($pluginName === null && $this->environmentService->isEnvironmentInFrontendMode()) {
|
||||
$pluginName = $this->extensionService->getPluginNameByAction($extensionName, $controllerArguments['controller'], $controllerArguments['action']);
|
||||
}
|
||||
if ($pluginName === null) {
|
||||
$pluginName = $this->request->getPluginName();
|
||||
}
|
||||
if ($this->environmentService->isEnvironmentInFrontendMode() && $this->configurationManager->isFeatureEnabled('skipDefaultArguments')) {
|
||||
$controllerArguments = $this->removeDefaultControllerAndAction($controllerArguments, $extensionName, $pluginName);
|
||||
}
|
||||
if ($this->targetPageUid === null && $this->environmentService->isEnvironmentInFrontendMode()) {
|
||||
$this->targetPageUid = $this->extensionService->getTargetPidByPlugin($extensionName, $pluginName);
|
||||
}
|
||||
if ($this->format !== '') {
|
||||
$controllerArguments['format'] = $this->format;
|
||||
}
|
||||
if ($this->argumentPrefix !== null) {
|
||||
$prefixedControllerArguments = [$this->argumentPrefix => $controllerArguments];
|
||||
} else {
|
||||
$pluginNamespace = $this->extensionService->getPluginNamespace($extensionName, $pluginName);
|
||||
$prefixedControllerArguments = [$pluginNamespace => $controllerArguments];
|
||||
}
|
||||
ArrayUtility::mergeRecursiveWithOverrule($this->arguments, $prefixedControllerArguments);
|
||||
return $this->build();
|
||||
}
|
||||
|
||||
/**
|
||||
* This removes controller and/or action arguments from given controllerArguments
|
||||
* if they are equal to the default controller/action of the target plugin.
|
||||
* Note: This is only active in FE mode and if feature "skipDefaultArguments" is enabled
|
||||
*
|
||||
* @see \TYPO3\CMS\Extbase\Configuration\ConfigurationManagerInterface::isFeatureEnabled()
|
||||
* @param array $controllerArguments the current controller arguments to be modified
|
||||
* @param string $extensionName target extension name
|
||||
* @param string $pluginName target plugin name
|
||||
* @return array
|
||||
*/
|
||||
protected function removeDefaultControllerAndAction(array $controllerArguments, $extensionName, $pluginName)
|
||||
{
|
||||
$defaultControllerName = $this->extensionService->getDefaultControllerNameByPlugin($extensionName, $pluginName);
|
||||
if (isset($controllerArguments['action'])) {
|
||||
$defaultActionName = $this->extensionService->getDefaultActionNameByPluginAndController($extensionName, $pluginName, $controllerArguments['controller']);
|
||||
if ($controllerArguments['action'] === $defaultActionName) {
|
||||
unset($controllerArguments['action']);
|
||||
}
|
||||
}
|
||||
if ($controllerArguments['controller'] === $defaultControllerName) {
|
||||
unset($controllerArguments['controller']);
|
||||
}
|
||||
return $controllerArguments;
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds the URI
|
||||
* Depending on the current context this calls buildBackendUri() or buildFrontendUri()
|
||||
*
|
||||
* @return string The URI
|
||||
* @see buildBackendUri()
|
||||
* @see buildFrontendUri()
|
||||
*/
|
||||
public function build()
|
||||
{
|
||||
if ($this->environmentService->isEnvironmentInBackendMode()) {
|
||||
return $this->buildBackendUri();
|
||||
}
|
||||
return $this->buildFrontendUri();
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds the URI, backend flavour
|
||||
* The resulting URI is relative and starts with "index.php".
|
||||
* The settings pageUid, pageType, noCache, useCacheHash & linkAccessRestrictedPages
|
||||
* will be ignored in the backend.
|
||||
*
|
||||
* @return string The URI
|
||||
* @internal only to be used within Extbase, not part of TYPO3 Core API.
|
||||
*/
|
||||
public function buildBackendUri()
|
||||
{
|
||||
$arguments = [];
|
||||
if ($this->addQueryString === true) {
|
||||
if ($this->addQueryStringMethod) {
|
||||
switch ($this->addQueryStringMethod) {
|
||||
case 'GET':
|
||||
$arguments = GeneralUtility::_GET();
|
||||
break;
|
||||
case 'POST':
|
||||
$arguments = GeneralUtility::_POST();
|
||||
break;
|
||||
case 'GET,POST':
|
||||
$arguments = array_replace_recursive(GeneralUtility::_GET(), GeneralUtility::_POST());
|
||||
break;
|
||||
case 'POST,GET':
|
||||
$arguments = array_replace_recursive(GeneralUtility::_POST(), GeneralUtility::_GET());
|
||||
break;
|
||||
default:
|
||||
// Explode GET vars recursively
|
||||
parse_str(GeneralUtility::getIndpEnv('QUERY_STRING'), $arguments);
|
||||
}
|
||||
} else {
|
||||
$arguments = GeneralUtility::_GET();
|
||||
}
|
||||
foreach ($this->argumentsToBeExcludedFromQueryString as $argumentToBeExcluded) {
|
||||
$argumentArrayToBeExcluded = [];
|
||||
parse_str($argumentToBeExcluded, $argumentArrayToBeExcluded);
|
||||
$arguments = ArrayUtility::arrayDiffAssocRecursive($arguments, $argumentArrayToBeExcluded);
|
||||
}
|
||||
} else {
|
||||
$id = GeneralUtility::_GP('id');
|
||||
// backwards compatibility: check for M parameter
|
||||
// @deprecated since TYPO3 v9, will be removed in TYPO3 v10.0.
|
||||
$route = GeneralUtility::_GP('route') ?: GeneralUtility::_GP('M');
|
||||
if ($id !== null) {
|
||||
$arguments['id'] = $id;
|
||||
}
|
||||
if ($route !== null) {
|
||||
$arguments['route'] = $route;
|
||||
}
|
||||
}
|
||||
ArrayUtility::mergeRecursiveWithOverrule($arguments, $this->arguments);
|
||||
$arguments = $this->convertDomainObjectsToIdentityArrays($arguments);
|
||||
$this->lastArguments = $arguments;
|
||||
$routeName = $arguments['route'] ?? null;
|
||||
unset($arguments['route'], $arguments['token']);
|
||||
$backendUriBuilder = GeneralUtility::makeInstance(\TYPO3\CMS\Backend\Routing\UriBuilder::class);
|
||||
try {
|
||||
if ($this->request instanceof WebRequest && $this->createAbsoluteUri) {
|
||||
$uri = (string)$backendUriBuilder->buildUriFromRoutePath($routeName, $arguments, \TYPO3\CMS\Backend\Routing\UriBuilder::ABSOLUTE_URL);
|
||||
} else {
|
||||
$uri = (string)$backendUriBuilder->buildUriFromRoutePath($routeName, $arguments, \TYPO3\CMS\Backend\Routing\UriBuilder::ABSOLUTE_PATH);
|
||||
}
|
||||
} catch (ResourceNotFoundException $e) {
|
||||
try {
|
||||
if ($this->request instanceof WebRequest && $this->createAbsoluteUri) {
|
||||
$uri = (string)$backendUriBuilder->buildUriFromRoute($routeName, $arguments, \TYPO3\CMS\Backend\Routing\UriBuilder::ABSOLUTE_URL);
|
||||
} else {
|
||||
$uri = (string)$backendUriBuilder->buildUriFromRoute($routeName, $arguments, \TYPO3\CMS\Backend\Routing\UriBuilder::ABSOLUTE_PATH);
|
||||
}
|
||||
} catch (RouteNotFoundException $e) {
|
||||
$uri = '';
|
||||
}
|
||||
}
|
||||
if ($this->section !== '') {
|
||||
$uri .= '#' . $this->section;
|
||||
}
|
||||
return $uri;
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds the URI, frontend flavour
|
||||
*
|
||||
* @return string The URI
|
||||
* @see buildTypolinkConfiguration()
|
||||
* @internal only to be used within Extbase, not part of TYPO3 Core API.
|
||||
*/
|
||||
public function buildFrontendUri()
|
||||
{
|
||||
$typolinkConfiguration = $this->buildTypolinkConfiguration();
|
||||
if ($this->createAbsoluteUri === true) {
|
||||
$typolinkConfiguration['forceAbsoluteUrl'] = true;
|
||||
if ($this->absoluteUriScheme !== null) {
|
||||
$typolinkConfiguration['forceAbsoluteUrl.']['scheme'] = $this->absoluteUriScheme;
|
||||
}
|
||||
}
|
||||
$uri = $this->contentObject->typoLink_URL($typolinkConfiguration);
|
||||
return $uri;
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds a TypoLink configuration array from the current settings
|
||||
*
|
||||
* @return array typolink configuration array
|
||||
* @see TSref/typolink
|
||||
*/
|
||||
protected function buildTypolinkConfiguration()
|
||||
{
|
||||
$typolinkConfiguration = [];
|
||||
$typolinkConfiguration['parameter'] = $this->targetPageUid ?? $GLOBALS['TSFE']->id;
|
||||
if ($this->targetPageType !== 0) {
|
||||
$typolinkConfiguration['parameter'] .= ',' . $this->targetPageType;
|
||||
} elseif ($this->format !== '') {
|
||||
$targetPageType = $this->extensionService->getTargetPageTypeByFormat($this->request->getControllerExtensionName(), $this->format);
|
||||
$typolinkConfiguration['parameter'] .= ',' . $targetPageType;
|
||||
}
|
||||
if (!empty($this->arguments)) {
|
||||
$arguments = $this->convertDomainObjectsToIdentityArrays($this->arguments);
|
||||
$this->lastArguments = $arguments;
|
||||
$typolinkConfiguration['additionalParams'] = HttpUtility::buildQueryString($arguments, '&');
|
||||
}
|
||||
if ($this->addQueryString === true) {
|
||||
$typolinkConfiguration['addQueryString'] = 1;
|
||||
if (!empty($this->argumentsToBeExcludedFromQueryString)) {
|
||||
$typolinkConfiguration['addQueryString.'] = [
|
||||
'exclude' => implode(',', $this->argumentsToBeExcludedFromQueryString)
|
||||
];
|
||||
}
|
||||
if ($this->addQueryStringMethod) {
|
||||
$typolinkConfiguration['addQueryString.']['method'] = $this->addQueryStringMethod;
|
||||
}
|
||||
}
|
||||
if ($this->noCache === true) {
|
||||
$typolinkConfiguration['no_cache'] = 1;
|
||||
} elseif ($this->useCacheHash) {
|
||||
$typolinkConfiguration['useCacheHash'] = 1;
|
||||
}
|
||||
if ($this->section !== '') {
|
||||
$typolinkConfiguration['section'] = $this->section;
|
||||
}
|
||||
if ($this->linkAccessRestrictedPages === true) {
|
||||
$typolinkConfiguration['linkAccessRestrictedPages'] = 1;
|
||||
}
|
||||
return $typolinkConfiguration;
|
||||
}
|
||||
|
||||
/**
|
||||
* Recursively iterates through the specified arguments and turns instances of type \TYPO3\CMS\Extbase\DomainObject\AbstractEntity
|
||||
* into an arrays containing the uid of the domain object.
|
||||
*
|
||||
* @param array $arguments The arguments to be iterated
|
||||
* @throws \TYPO3\CMS\Extbase\Mvc\Exception\InvalidArgumentValueException
|
||||
* @return array The modified arguments array
|
||||
*/
|
||||
protected function convertDomainObjectsToIdentityArrays(array $arguments)
|
||||
{
|
||||
foreach ($arguments as $argumentKey => $argumentValue) {
|
||||
// if we have a LazyLoadingProxy here, make sure to get the real instance for further processing
|
||||
if ($argumentValue instanceof \TYPO3\CMS\Extbase\Persistence\Generic\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 \Iterator) {
|
||||
$argumentValue = $this->convertIteratorToArray($argumentValue);
|
||||
}
|
||||
if ($argumentValue instanceof \TYPO3\CMS\Extbase\DomainObject\AbstractDomainObject) {
|
||||
if ($argumentValue->getUid() !== null) {
|
||||
$arguments[$argumentKey] = $argumentValue->getUid();
|
||||
} elseif ($argumentValue instanceof \TYPO3\CMS\Extbase\DomainObject\AbstractValueObject) {
|
||||
$arguments[$argumentKey] = $this->convertTransientObjectToArray($argumentValue);
|
||||
} else {
|
||||
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);
|
||||
}
|
||||
} elseif (is_array($argumentValue)) {
|
||||
$arguments[$argumentKey] = $this->convertDomainObjectsToIdentityArrays($argumentValue);
|
||||
}
|
||||
}
|
||||
return $arguments;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param \Iterator $iterator
|
||||
* @return array
|
||||
*/
|
||||
protected function convertIteratorToArray(\Iterator $iterator)
|
||||
{
|
||||
if (method_exists($iterator, 'toArray')) {
|
||||
$array = $iterator->toArray();
|
||||
} else {
|
||||
$array = iterator_to_array($iterator);
|
||||
}
|
||||
return $array;
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts a given object recursively into an array.
|
||||
*
|
||||
* @param \TYPO3\CMS\Extbase\DomainObject\AbstractDomainObject $object
|
||||
* @return array
|
||||
* @todo Refactore this into convertDomainObjectsToIdentityArrays()
|
||||
* @internal only to be used within Extbase, not part of TYPO3 Core API.
|
||||
*/
|
||||
public function convertTransientObjectToArray(\TYPO3\CMS\Extbase\DomainObject\AbstractDomainObject $object)
|
||||
{
|
||||
$result = [];
|
||||
foreach ($object->_getProperties() as $propertyName => $propertyValue) {
|
||||
if ($propertyValue instanceof \Iterator) {
|
||||
$propertyValue = $this->convertIteratorToArray($propertyValue);
|
||||
}
|
||||
if ($propertyValue instanceof \TYPO3\CMS\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;
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user