324710bb8ac0d537e69ea3a9c84befe79ac03804
[yaffs-website] / http-kernel / Client.php
1 <?php
2
3 /*
4  * This file is part of the Symfony package.
5  *
6  * (c) Fabien Potencier <fabien@symfony.com>
7  *
8  * For the full copyright and license information, please view the LICENSE
9  * file that was distributed with this source code.
10  */
11
12 namespace Symfony\Component\HttpKernel;
13
14 use Symfony\Component\BrowserKit\Client as BaseClient;
15 use Symfony\Component\BrowserKit\CookieJar;
16 use Symfony\Component\BrowserKit\History;
17 use Symfony\Component\BrowserKit\Request as DomRequest;
18 use Symfony\Component\BrowserKit\Response as DomResponse;
19 use Symfony\Component\HttpFoundation\File\UploadedFile;
20 use Symfony\Component\HttpFoundation\Request;
21 use Symfony\Component\HttpFoundation\Response;
22
23 /**
24  * Client simulates a browser and makes requests to a Kernel object.
25  *
26  * @author Fabien Potencier <fabien@symfony.com>
27  *
28  * @method Request|null  getRequest()  A Request instance
29  * @method Response|null getResponse() A Response instance
30  */
31 class Client extends BaseClient
32 {
33     protected $kernel;
34     private $catchExceptions = true;
35
36     /**
37      * @param HttpKernelInterface $kernel    An HttpKernel instance
38      * @param array               $server    The server parameters (equivalent of $_SERVER)
39      * @param History             $history   A History instance to store the browser history
40      * @param CookieJar           $cookieJar A CookieJar instance to store the cookies
41      */
42     public function __construct(HttpKernelInterface $kernel, array $server = array(), History $history = null, CookieJar $cookieJar = null)
43     {
44         // These class properties must be set before calling the parent constructor, as it may depend on it.
45         $this->kernel = $kernel;
46         $this->followRedirects = false;
47
48         parent::__construct($server, $history, $cookieJar);
49     }
50
51     /**
52      * Sets whether to catch exceptions when the kernel is handling a request.
53      *
54      * @param bool $catchExceptions Whether to catch exceptions
55      */
56     public function catchExceptions($catchExceptions)
57     {
58         $this->catchExceptions = $catchExceptions;
59     }
60
61     /**
62      * Makes a request.
63      *
64      * @return Response A Response instance
65      */
66     protected function doRequest($request)
67     {
68         $response = $this->kernel->handle($request, HttpKernelInterface::MASTER_REQUEST, $this->catchExceptions);
69
70         if ($this->kernel instanceof TerminableInterface) {
71             $this->kernel->terminate($request, $response);
72         }
73
74         return $response;
75     }
76
77     /**
78      * Returns the script to execute when the request must be insulated.
79      *
80      * @return string
81      */
82     protected function getScript($request)
83     {
84         $kernel = var_export(serialize($this->kernel), true);
85         $request = var_export(serialize($request), true);
86
87         $errorReporting = error_reporting();
88
89         $requires = '';
90         foreach (get_declared_classes() as $class) {
91             if (0 === strpos($class, 'ComposerAutoloaderInit')) {
92                 $r = new \ReflectionClass($class);
93                 $file = \dirname(\dirname($r->getFileName())).'/autoload.php';
94                 if (file_exists($file)) {
95                     $requires .= 'require_once '.var_export($file, true).";\n";
96                 }
97             }
98         }
99
100         if (!$requires) {
101             throw new \RuntimeException('Composer autoloader not found.');
102         }
103
104         $code = <<<EOF
105 <?php
106
107 error_reporting($errorReporting);
108
109 $requires
110
111 \$kernel = unserialize($kernel);
112 \$request = unserialize($request);
113 EOF;
114
115         return $code.$this->getHandleScript();
116     }
117
118     protected function getHandleScript()
119     {
120         return <<<'EOF'
121 $response = $kernel->handle($request);
122
123 if ($kernel instanceof Symfony\Component\HttpKernel\TerminableInterface) {
124     $kernel->terminate($request, $response);
125 }
126
127 echo serialize($response);
128 EOF;
129     }
130
131     /**
132      * Converts the BrowserKit request to a HttpKernel request.
133      *
134      * @return Request A Request instance
135      */
136     protected function filterRequest(DomRequest $request)
137     {
138         $httpRequest = Request::create($request->getUri(), $request->getMethod(), $request->getParameters(), $request->getCookies(), $request->getFiles(), $request->getServer(), $request->getContent());
139
140         foreach ($this->filterFiles($httpRequest->files->all()) as $key => $value) {
141             $httpRequest->files->set($key, $value);
142         }
143
144         return $httpRequest;
145     }
146
147     /**
148      * Filters an array of files.
149      *
150      * This method created test instances of UploadedFile so that the move()
151      * method can be called on those instances.
152      *
153      * If the size of a file is greater than the allowed size (from php.ini) then
154      * an invalid UploadedFile is returned with an error set to UPLOAD_ERR_INI_SIZE.
155      *
156      * @see UploadedFile
157      *
158      * @return array An array with all uploaded files marked as already moved
159      */
160     protected function filterFiles(array $files)
161     {
162         $filtered = array();
163         foreach ($files as $key => $value) {
164             if (\is_array($value)) {
165                 $filtered[$key] = $this->filterFiles($value);
166             } elseif ($value instanceof UploadedFile) {
167                 if ($value->isValid() && $value->getSize() > UploadedFile::getMaxFilesize()) {
168                     $filtered[$key] = new UploadedFile(
169                         '',
170                         $value->getClientOriginalName(),
171                         $value->getClientMimeType(),
172                         0,
173                         UPLOAD_ERR_INI_SIZE,
174                         true
175                     );
176                 } else {
177                     $filtered[$key] = new UploadedFile(
178                         $value->getPathname(),
179                         $value->getClientOriginalName(),
180                         $value->getClientMimeType(),
181                         $value->getClientSize(),
182                         $value->getError(),
183                         true
184                     );
185                 }
186             }
187         }
188
189         return $filtered;
190     }
191
192     /**
193      * Converts the HttpKernel response to a BrowserKit response.
194      *
195      * @return DomResponse A DomResponse instance
196      */
197     protected function filterResponse($response)
198     {
199         // this is needed to support StreamedResponse
200         ob_start();
201         $response->sendContent();
202         $content = ob_get_clean();
203
204         return new DomResponse($content, $response->getStatusCode(), $response->headers->all());
205     }
206 }