Chris@0: Chris@0: * Chris@0: * For the full copyright and license information, please view the LICENSE Chris@0: * file that was distributed with this source code. Chris@0: */ Chris@0: Chris@0: namespace Symfony\Component\HttpKernel; Chris@0: Chris@0: use Symfony\Component\BrowserKit\Client as BaseClient; Chris@17: use Symfony\Component\BrowserKit\CookieJar; Chris@17: use Symfony\Component\BrowserKit\History; Chris@0: use Symfony\Component\BrowserKit\Request as DomRequest; Chris@0: use Symfony\Component\BrowserKit\Response as DomResponse; Chris@0: use Symfony\Component\HttpFoundation\File\UploadedFile; Chris@0: use Symfony\Component\HttpFoundation\Request; Chris@0: use Symfony\Component\HttpFoundation\Response; Chris@0: Chris@0: /** Chris@0: * Client simulates a browser and makes requests to a Kernel object. Chris@0: * Chris@0: * @author Fabien Potencier Chris@0: * Chris@14: * @method Request|null getRequest() A Request instance Chris@0: * @method Response|null getResponse() A Response instance Chris@0: */ Chris@0: class Client extends BaseClient Chris@0: { Chris@0: protected $kernel; Chris@14: private $catchExceptions = true; Chris@0: Chris@0: /** Chris@0: * @param HttpKernelInterface $kernel An HttpKernel instance Chris@0: * @param array $server The server parameters (equivalent of $_SERVER) Chris@0: * @param History $history A History instance to store the browser history Chris@0: * @param CookieJar $cookieJar A CookieJar instance to store the cookies Chris@0: */ Chris@17: public function __construct(HttpKernelInterface $kernel, array $server = [], History $history = null, CookieJar $cookieJar = null) Chris@0: { Chris@0: // These class properties must be set before calling the parent constructor, as it may depend on it. Chris@0: $this->kernel = $kernel; Chris@0: $this->followRedirects = false; Chris@0: Chris@0: parent::__construct($server, $history, $cookieJar); Chris@0: } Chris@0: Chris@0: /** Chris@14: * Sets whether to catch exceptions when the kernel is handling a request. Chris@14: * Chris@14: * @param bool $catchExceptions Whether to catch exceptions Chris@14: */ Chris@14: public function catchExceptions($catchExceptions) Chris@14: { Chris@14: $this->catchExceptions = $catchExceptions; Chris@14: } Chris@14: Chris@14: /** Chris@0: * Makes a request. Chris@0: * Chris@0: * @return Response A Response instance Chris@0: */ Chris@0: protected function doRequest($request) Chris@0: { Chris@14: $response = $this->kernel->handle($request, HttpKernelInterface::MASTER_REQUEST, $this->catchExceptions); Chris@0: Chris@0: if ($this->kernel instanceof TerminableInterface) { Chris@0: $this->kernel->terminate($request, $response); Chris@0: } Chris@0: Chris@0: return $response; Chris@0: } Chris@0: Chris@0: /** Chris@0: * Returns the script to execute when the request must be insulated. Chris@0: * Chris@0: * @return string Chris@0: */ Chris@0: protected function getScript($request) Chris@0: { Chris@17: $kernel = var_export(serialize($this->kernel), true); Chris@17: $request = var_export(serialize($request), true); Chris@17: Chris@14: $errorReporting = error_reporting(); Chris@0: Chris@14: $requires = ''; Chris@14: foreach (get_declared_classes() as $class) { Chris@14: if (0 === strpos($class, 'ComposerAutoloaderInit')) { Chris@14: $r = new \ReflectionClass($class); Chris@17: $file = \dirname(\dirname($r->getFileName())).'/autoload.php'; Chris@14: if (file_exists($file)) { Chris@17: $requires .= 'require_once '.var_export($file, true).";\n"; Chris@14: } Chris@14: } Chris@14: } Chris@14: Chris@14: if (!$requires) { Chris@14: throw new \RuntimeException('Composer autoloader not found.'); Chris@14: } Chris@0: Chris@0: $code = <<getHandleScript(); Chris@0: } Chris@0: Chris@0: protected function getHandleScript() Chris@0: { Chris@0: return <<<'EOF' Chris@0: $response = $kernel->handle($request); Chris@0: Chris@0: if ($kernel instanceof Symfony\Component\HttpKernel\TerminableInterface) { Chris@0: $kernel->terminate($request, $response); Chris@0: } Chris@0: Chris@0: echo serialize($response); Chris@0: EOF; Chris@0: } Chris@0: Chris@0: /** Chris@0: * Converts the BrowserKit request to a HttpKernel request. Chris@0: * Chris@0: * @return Request A Request instance Chris@0: */ Chris@0: protected function filterRequest(DomRequest $request) Chris@0: { Chris@0: $httpRequest = Request::create($request->getUri(), $request->getMethod(), $request->getParameters(), $request->getCookies(), $request->getFiles(), $request->getServer(), $request->getContent()); Chris@0: Chris@0: foreach ($this->filterFiles($httpRequest->files->all()) as $key => $value) { Chris@0: $httpRequest->files->set($key, $value); Chris@0: } Chris@0: Chris@0: return $httpRequest; Chris@0: } Chris@0: Chris@0: /** Chris@0: * Filters an array of files. Chris@0: * Chris@0: * This method created test instances of UploadedFile so that the move() Chris@0: * method can be called on those instances. Chris@0: * Chris@0: * If the size of a file is greater than the allowed size (from php.ini) then Chris@0: * an invalid UploadedFile is returned with an error set to UPLOAD_ERR_INI_SIZE. Chris@0: * Chris@0: * @see UploadedFile Chris@0: * Chris@0: * @return array An array with all uploaded files marked as already moved Chris@0: */ Chris@0: protected function filterFiles(array $files) Chris@0: { Chris@17: $filtered = []; Chris@0: foreach ($files as $key => $value) { Chris@17: if (\is_array($value)) { Chris@0: $filtered[$key] = $this->filterFiles($value); Chris@0: } elseif ($value instanceof UploadedFile) { Chris@0: if ($value->isValid() && $value->getSize() > UploadedFile::getMaxFilesize()) { Chris@0: $filtered[$key] = new UploadedFile( Chris@0: '', Chris@0: $value->getClientOriginalName(), Chris@0: $value->getClientMimeType(), Chris@0: 0, Chris@0: UPLOAD_ERR_INI_SIZE, Chris@0: true Chris@0: ); Chris@0: } else { Chris@0: $filtered[$key] = new UploadedFile( Chris@0: $value->getPathname(), Chris@0: $value->getClientOriginalName(), Chris@0: $value->getClientMimeType(), Chris@0: $value->getClientSize(), Chris@0: $value->getError(), Chris@0: true Chris@0: ); Chris@0: } Chris@0: } Chris@0: } Chris@0: Chris@0: return $filtered; Chris@0: } Chris@0: Chris@0: /** Chris@0: * Converts the HttpKernel response to a BrowserKit response. Chris@0: * Chris@0: * @return DomResponse A DomResponse instance Chris@0: */ Chris@0: protected function filterResponse($response) Chris@0: { Chris@0: // this is needed to support StreamedResponse Chris@0: ob_start(); Chris@0: $response->sendContent(); Chris@0: $content = ob_get_clean(); Chris@0: Chris@14: return new DomResponse($content, $response->getStatusCode(), $response->headers->all()); Chris@0: } Chris@0: }