-
Notifications
You must be signed in to change notification settings - Fork 3.4k
/
MiddlewareDispatcher.php
144 lines (130 loc) · 4.12 KB
/
MiddlewareDispatcher.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
<?php
declare(strict_types=1);
/**
* CakePHP(tm) : Rapid Development Framework (https://cakephp.org)
* Copyright (c) Cake Software Foundation, Inc. (https://cakefoundation.org)
*
* Licensed under The MIT License
* For full copyright and license information, please see the LICENSE.txt
* Redistributions of files must retain the above copyright notice
*
* @copyright Copyright (c) Cake Software Foundation, Inc. (https://cakefoundation.org)
* @since 3.3.0
* @license https://opensource.org/licenses/mit-license.php MIT License
*/
namespace Cake\TestSuite;
use Cake\Core\HttpApplicationInterface;
use Cake\Core\PluginApplicationInterface;
use Cake\Http\FlashMessage;
use Cake\Http\Server;
use Cake\Http\ServerRequest;
use Cake\Http\ServerRequestFactory;
use Cake\Routing\Router;
use Cake\Routing\RoutingApplicationInterface;
use Psr\Http\Message\ResponseInterface;
/**
* Dispatches a request capturing the response for integration
* testing purposes into the Cake\Http stack.
*
* @internal
*/
class MiddlewareDispatcher
{
/**
* The application that is being dispatched.
*
* @var \Cake\Core\HttpApplicationInterface
*/
protected $app;
/**
* Constructor
*
* @param \Cake\Core\HttpApplicationInterface $app The test case to run.
*/
public function __construct(HttpApplicationInterface $app)
{
$this->app = $app;
}
/**
* Resolve the provided URL into a string.
*
* @param array|string $url The URL array/string to resolve.
* @return string
*/
public function resolveUrl($url): string
{
// If we need to resolve a Route URL but there are no routes, load routes.
if (is_array($url) && count(Router::getRouteCollection()->routes()) === 0) {
return $this->resolveRoute($url);
}
return Router::url($url);
}
/**
* Convert a URL array into a string URL via routing.
*
* @param array $url The url to resolve
* @return string
*/
protected function resolveRoute(array $url): string
{
// Simulate application bootstrap and route loading.
// We need both to ensure plugins are loaded.
$this->app->bootstrap();
if ($this->app instanceof PluginApplicationInterface) {
$this->app->pluginBootstrap();
}
$builder = Router::createRouteBuilder('/');
if ($this->app instanceof RoutingApplicationInterface) {
$this->app->routes($builder);
}
if ($this->app instanceof PluginApplicationInterface) {
$this->app->pluginRoutes($builder);
}
$out = Router::url($url);
Router::resetRoutes();
return $out;
}
/**
* Create a PSR7 request from the request spec.
*
* @param array $spec The request spec.
* @return \Cake\Http\ServerRequest
*/
protected function _createRequest(array $spec): ServerRequest
{
if (isset($spec['input'])) {
$spec['post'] = [];
$spec['environment']['CAKEPHP_INPUT'] = $spec['input'];
}
$environment = array_merge(
array_merge($_SERVER, ['REQUEST_URI' => $spec['url']]),
$spec['environment']
);
if (strpos($environment['PHP_SELF'], 'phpunit') !== false) {
$environment['PHP_SELF'] = '/';
}
$request = ServerRequestFactory::fromGlobals(
$environment,
$spec['query'],
$spec['post'],
$spec['cookies'],
$spec['files']
);
$request = $request
->withAttribute('session', $spec['session'])
->withAttribute('flash', new FlashMessage($spec['session']));
return $request;
}
/**
* Run a request and get the response.
*
* @param array $requestSpec The request spec to execute.
* @return \Psr\Http\Message\ResponseInterface The generated response.
* @throws \LogicException
*/
public function execute(array $requestSpec): ResponseInterface
{
$server = new Server($this->app);
return $server->run($this->_createRequest($requestSpec));
}
}