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@0: use Symfony\Component\BrowserKit\Request as DomRequest; Chris@0: use Symfony\Component\BrowserKit\Response as DomResponse; Chris@0: use Symfony\Component\BrowserKit\Cookie as DomCookie; Chris@0: use Symfony\Component\BrowserKit\History; Chris@0: use Symfony\Component\BrowserKit\CookieJar; 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@0: * @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@0: Chris@0: /** Chris@0: * Constructor. 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@0: public function __construct(HttpKernelInterface $kernel, array $server = array(), 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@0: * Makes a request. Chris@0: * Chris@0: * @param Request $request A Request instance Chris@0: * Chris@0: * @return Response A Response instance Chris@0: */ Chris@0: protected function doRequest($request) Chris@0: { Chris@0: $response = $this->kernel->handle($request); 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: * @param Request $request A Request instance Chris@0: * Chris@0: * @return string Chris@0: */ Chris@0: protected function getScript($request) Chris@0: { Chris@0: $kernel = str_replace("'", "\\'", serialize($this->kernel)); Chris@0: $request = str_replace("'", "\\'", serialize($request)); Chris@0: Chris@0: $r = new \ReflectionClass('\\Symfony\\Component\\ClassLoader\\ClassLoader'); Chris@0: $requirePath = str_replace("'", "\\'", $r->getFileName()); Chris@0: $symfonyPath = str_replace("'", "\\'", dirname(dirname(dirname(__DIR__)))); Chris@0: $errorReporting = error_reporting(); Chris@0: Chris@0: $code = <<addPrefix('Symfony', '$symfonyPath'); Chris@0: \$loader->register(); Chris@0: Chris@0: \$kernel = unserialize('$kernel'); Chris@0: \$request = unserialize('$request'); Chris@0: EOF; Chris@0: Chris@0: return $code.$this->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: * @param DomRequest $request A DomRequest instance 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: * @param array $files An array of files 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@0: $filtered = array(); Chris@0: foreach ($files as $key => $value) { Chris@0: 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: * @param Response $response A Response instance Chris@0: * Chris@0: * @return DomResponse A DomResponse instance Chris@0: */ Chris@0: protected function filterResponse($response) Chris@0: { Chris@0: $headers = $response->headers->all(); Chris@0: if ($response->headers->getCookies()) { Chris@0: $cookies = array(); Chris@0: foreach ($response->headers->getCookies() as $cookie) { Chris@0: $cookies[] = new DomCookie($cookie->getName(), $cookie->getValue(), $cookie->getExpiresTime(), $cookie->getPath(), $cookie->getDomain(), $cookie->isSecure(), $cookie->isHttpOnly()); Chris@0: } Chris@0: $headers['Set-Cookie'] = $cookies; Chris@0: } 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@0: return new DomResponse($content, $response->getStatusCode(), $headers); Chris@0: } Chris@0: }