1
|
|
|
<?php |
2
|
|
|
namespace Codeception\Module; |
3
|
|
|
|
4
|
|
|
use Codeception\Configuration; |
5
|
|
|
use Codeception\Lib\Framework; |
6
|
|
|
use Codeception\Exception\ModuleRequireException; |
7
|
|
|
use Codeception\Lib\Connector\Symfony as SymfonyConnector; |
8
|
|
|
use Codeception\Lib\Interfaces\DoctrineProvider; |
9
|
|
|
use Codeception\Lib\Interfaces\PartedModule; |
10
|
|
|
use Symfony\Component\Finder\Finder; |
11
|
|
|
use Symfony\Component\DependencyInjection\ContainerInterface; |
12
|
|
|
use Symfony\Component\Finder\SplFileInfo; |
13
|
|
|
use Symfony\Component\VarDumper\Cloner\Data; |
14
|
|
|
|
15
|
|
|
/** |
16
|
|
|
* This module uses Symfony Crawler and HttpKernel to emulate requests and test response. |
17
|
|
|
* |
18
|
|
|
* ## Demo Project |
19
|
|
|
* |
20
|
|
|
* <https://github.com/Codeception/symfony-demo> |
21
|
|
|
* |
22
|
|
|
* ## Config |
23
|
|
|
* |
24
|
|
|
* ### Symfony 4.x |
25
|
|
|
* |
26
|
|
|
* * app_path: 'src' - in Symfony 4 Kernel is located inside `src` |
27
|
|
|
* * environment: 'local' - environment used for load kernel |
28
|
|
|
* * em_service: 'doctrine.orm.entity_manager' - use the stated EntityManager to pair with Doctrine Module. |
29
|
|
|
* * debug: true - turn on/off debug mode |
30
|
|
|
* * cache_router: 'false' - enable router caching between tests in order to [increase performance](http://lakion.com/blog/how-did-we-speed-up-sylius-behat-suite-with-blackfire) |
31
|
|
|
* * rebootable_client: 'true' - reboot client's kernel before each request |
32
|
|
|
* |
33
|
|
|
* #### Example (`functional.suite.yml`) - Symfony 4 Directory Structure |
34
|
|
|
* |
35
|
|
|
* modules: |
36
|
|
|
* enabled: |
37
|
|
|
* - Symfony: |
38
|
|
|
* app_path: 'src' |
39
|
|
|
* environment: 'test' |
40
|
|
|
* |
41
|
|
|
* |
42
|
|
|
* ### Symfony 3.x |
43
|
|
|
* |
44
|
|
|
* * app_path: 'app' - specify custom path to your app dir, where the kernel interface is located. |
45
|
|
|
* * var_path: 'var' - specify custom path to your var dir, where bootstrap cache is located. |
46
|
|
|
* * environment: 'local' - environment used for load kernel |
47
|
|
|
* * em_service: 'doctrine.orm.entity_manager' - use the stated EntityManager to pair with Doctrine Module. |
48
|
|
|
* * debug: true - turn on/off debug mode |
49
|
|
|
* * cache_router: 'false' - enable router caching between tests in order to [increase performance](http://lakion.com/blog/how-did-we-speed-up-sylius-behat-suite-with-blackfire) |
50
|
|
|
* * rebootable_client: 'true' - reboot client's kernel before each request |
51
|
|
|
* |
52
|
|
|
* #### Example (`functional.suite.yml`) - Symfony 3 Directory Structure |
53
|
|
|
* |
54
|
|
|
* modules: |
55
|
|
|
* enabled: |
56
|
|
|
* - Symfony: |
57
|
|
|
* app_path: 'app/front' |
58
|
|
|
* var_path: 'var' |
59
|
|
|
* environment: 'local_test' |
60
|
|
|
* |
61
|
|
|
* |
62
|
|
|
* ### Symfony 2.x |
63
|
|
|
* |
64
|
|
|
* * app_path: 'app' - specify custom path to your app dir, where bootstrap cache and kernel interface is located. |
65
|
|
|
* * environment: 'local' - environment used for load kernel |
66
|
|
|
* * debug: true - turn on/off debug mode |
67
|
|
|
* * em_service: 'doctrine.orm.entity_manager' - use the stated EntityManager to pair with Doctrine Module. |
68
|
|
|
* * cache_router: 'false' - enable router caching between tests in order to [increase performance](http://lakion.com/blog/how-did-we-speed-up-sylius-behat-suite-with-blackfire) |
69
|
|
|
* * rebootable_client: 'true' - reboot client's kernel before each request |
70
|
|
|
* |
71
|
|
|
* ### Example (`functional.suite.yml`) - Symfony 2.x Directory Structure |
72
|
|
|
* |
73
|
|
|
* ``` |
74
|
|
|
* modules: |
75
|
|
|
* - Symfony: |
76
|
|
|
* app_path: 'app/front' |
77
|
|
|
* environment: 'local_test' |
78
|
|
|
* ``` |
79
|
|
|
* |
80
|
|
|
* ## Public Properties |
81
|
|
|
* |
82
|
|
|
* * kernel - HttpKernel instance |
83
|
|
|
* * client - current Crawler instance |
84
|
|
|
* |
85
|
|
|
* ## Parts |
86
|
|
|
* |
87
|
|
|
* * services - allows to use Symfony DIC only with WebDriver or PhpBrowser modules. |
88
|
|
|
* |
89
|
|
|
* Usage example: |
90
|
|
|
* |
91
|
|
|
* ```yaml |
92
|
|
|
* actor: AcceptanceTester |
93
|
|
|
* modules: |
94
|
|
|
* enabled: |
95
|
|
|
* - Symfony: |
96
|
|
|
* part: SERVICES |
97
|
|
|
* - Doctrine2: |
98
|
|
|
* depends: Symfony |
99
|
|
|
* - WebDriver: |
100
|
|
|
* url: http://your-url.com |
101
|
|
|
* browser: phantomjs |
102
|
|
|
* ``` |
103
|
|
|
* |
104
|
|
|
*/ |
105
|
|
|
class Symfony extends Framework implements DoctrineProvider, PartedModule |
106
|
|
|
{ |
107
|
|
|
/** |
108
|
|
|
* @var \Symfony\Component\HttpKernel\Kernel |
109
|
|
|
*/ |
110
|
|
|
public $kernel; |
111
|
|
|
|
112
|
|
|
public $config = [ |
113
|
|
|
'app_path' => 'app', |
114
|
|
|
'var_path' => 'app', |
115
|
|
|
'environment' => 'test', |
116
|
|
|
'debug' => true, |
117
|
|
|
'cache_router' => false, |
118
|
|
|
'em_service' => 'doctrine.orm.entity_manager', |
119
|
|
|
'rebootable_client' => true, |
120
|
|
|
]; |
121
|
|
|
|
122
|
|
|
/** |
123
|
|
|
* @return array |
124
|
|
|
*/ |
125
|
|
|
public function _parts() |
126
|
|
|
{ |
127
|
|
|
return ['services']; |
128
|
|
|
} |
129
|
|
|
|
130
|
|
|
/** |
131
|
|
|
* @var |
132
|
|
|
*/ |
133
|
|
|
protected $kernelClass; |
134
|
|
|
|
135
|
|
|
/** |
136
|
|
|
* Services that should be persistent permanently for all tests |
137
|
|
|
* |
138
|
|
|
* @var array |
139
|
|
|
*/ |
140
|
|
|
protected $permanentServices = []; |
141
|
|
|
|
142
|
|
|
/** |
143
|
|
|
* Services that should be persistent during test execution between kernel reboots |
144
|
|
|
* |
145
|
|
|
* @var array |
146
|
|
|
*/ |
147
|
|
|
protected $persistentServices = []; |
148
|
|
|
|
149
|
|
|
public function _initialize() |
150
|
|
|
{ |
151
|
|
|
|
152
|
|
|
$this->initializeSymfonyCache(); |
153
|
|
|
$this->kernelClass = $this->getKernelClass(); |
154
|
|
|
$maxNestingLevel = 200; // Symfony may have very long nesting level |
155
|
|
|
$xdebugMaxLevelKey = 'xdebug.max_nesting_level'; |
156
|
|
|
if (ini_get($xdebugMaxLevelKey) < $maxNestingLevel) { |
157
|
|
|
ini_set($xdebugMaxLevelKey, $maxNestingLevel); |
158
|
|
|
} |
159
|
|
|
|
160
|
|
|
$this->kernel = new $this->kernelClass($this->config['environment'], $this->config['debug']); |
161
|
|
|
$this->kernel->boot(); |
162
|
|
|
|
163
|
|
|
if ($this->config['cache_router'] === true) { |
164
|
|
|
$this->persistService('router', true); |
165
|
|
|
} |
166
|
|
|
} |
167
|
|
|
|
168
|
|
|
/** |
169
|
|
|
* Require Symfonys bootstrap.php.cache only for PHP Version < 7 |
170
|
|
|
* |
171
|
|
|
* @throws ModuleRequireException |
172
|
|
|
*/ |
173
|
|
|
private function initializeSymfonyCache() |
174
|
|
|
{ |
175
|
|
|
$cache = Configuration::projectDir() . $this->config['var_path'] . DIRECTORY_SEPARATOR . 'bootstrap.php.cache'; |
176
|
|
|
if (PHP_VERSION_ID < 70000 && !file_exists($cache)) { |
177
|
|
|
throw new ModuleRequireException( |
178
|
|
|
__CLASS__, |
179
|
|
|
"Symfony bootstrap file not found in $cache\n \n" . |
180
|
|
|
"Please specify path to bootstrap file using `var_path` config option\n \n" . |
181
|
|
|
"If you are trying to load bootstrap from a Bundle provide path like:\n \n" . |
182
|
|
|
"modules:\n enabled:\n" . |
183
|
|
|
" - Symfony:\n" . |
184
|
|
|
" var_path: '../../app'\n" . |
185
|
|
|
" app_path: '../../app'" |
186
|
|
|
); |
187
|
|
|
} |
188
|
|
|
if (file_exists($cache)) { |
189
|
|
|
require_once $cache; |
190
|
|
|
} |
191
|
|
|
} |
192
|
|
|
|
193
|
|
|
/** |
194
|
|
|
* Initialize new client instance before each test |
195
|
|
|
*/ |
196
|
|
|
public function _before(\Codeception\TestInterface $test) |
197
|
|
|
{ |
198
|
|
|
$this->persistentServices = array_merge($this->persistentServices, $this->permanentServices); |
199
|
|
|
$this->client = new SymfonyConnector($this->kernel, $this->persistentServices, $this->config['rebootable_client']); |
200
|
|
|
} |
201
|
|
|
|
202
|
|
|
/** |
203
|
|
|
* Update permanent services after each test |
204
|
|
|
*/ |
205
|
|
|
public function _after(\Codeception\TestInterface $test) |
206
|
|
|
{ |
207
|
|
|
foreach ($this->permanentServices as $serviceName => $service) { |
208
|
|
|
$this->permanentServices[$serviceName] = $this->grabService($serviceName); |
209
|
|
|
} |
210
|
|
|
parent::_after($test); |
211
|
|
|
} |
212
|
|
|
|
213
|
|
|
/** |
214
|
|
|
* Retrieve Entity Manager. |
215
|
|
|
* |
216
|
|
|
* EM service is retrieved once and then that instance returned on each call |
217
|
|
|
*/ |
218
|
|
|
public function _getEntityManager() |
219
|
|
|
{ |
220
|
|
|
if ($this->kernel === null) { |
221
|
|
|
$this->fail('Symfony2 platform module is not loaded'); |
222
|
|
|
} |
223
|
|
|
if (!isset($this->permanentServices[$this->config['em_service']])) { |
224
|
|
|
// try to persist configured EM |
225
|
|
|
$this->persistService($this->config['em_service'], true); |
226
|
|
|
|
227
|
|
|
if ($this->_getContainer()->has('doctrine')) { |
228
|
|
|
$this->persistService('doctrine', true); |
229
|
|
|
} |
230
|
|
|
if ($this->_getContainer()->has('doctrine.orm.default_entity_manager')) { |
231
|
|
|
$this->persistService('doctrine.orm.default_entity_manager', true); |
232
|
|
|
} |
233
|
|
|
if ($this->_getContainer()->has('doctrine.dbal.backend_connection')) { |
234
|
|
|
$this->persistService('doctrine.dbal.backend_connection', true); |
235
|
|
|
} |
236
|
|
|
} |
237
|
|
|
return $this->permanentServices[$this->config['em_service']]; |
238
|
|
|
} |
239
|
|
|
|
240
|
|
|
/** |
241
|
|
|
* Return container. |
242
|
|
|
* |
243
|
|
|
* @return ContainerInterface |
244
|
|
|
*/ |
245
|
|
|
public function _getContainer() |
246
|
|
|
{ |
247
|
|
|
return $this->kernel->getContainer(); |
248
|
|
|
} |
249
|
|
|
|
250
|
|
|
/** |
251
|
|
|
* Attempts to guess the kernel location. |
252
|
|
|
* |
253
|
|
|
* When the Kernel is located, the file is required. |
254
|
|
|
* |
255
|
|
|
* @return string The Kernel class name |
256
|
|
|
*/ |
257
|
|
|
protected function getKernelClass() |
258
|
|
|
{ |
259
|
|
|
$path = codecept_root_dir() . $this->config['app_path']; |
260
|
|
|
if (!file_exists(codecept_root_dir() . $this->config['app_path'])) { |
261
|
|
|
throw new ModuleRequireException( |
262
|
|
|
__CLASS__, |
263
|
|
|
"Can't load Kernel from $path.\n" |
264
|
|
|
. "Directory does not exists. Use `app_path` parameter to provide valid application path" |
265
|
|
|
); |
266
|
|
|
} |
267
|
|
|
|
268
|
|
|
$finder = new Finder(); |
269
|
|
|
$finder->name('*Kernel.php')->depth('0')->in($path); |
270
|
|
|
$results = iterator_to_array($finder); |
271
|
|
|
if (!count($results)) { |
272
|
|
|
throw new ModuleRequireException( |
273
|
|
|
__CLASS__, |
274
|
|
|
"File with Kernel class was not found at $path. " |
275
|
|
|
. "Specify directory where file with Kernel class for your application is located with `app_path` parameter." |
276
|
|
|
); |
277
|
|
|
} |
278
|
|
|
$file = current($results); |
279
|
|
|
|
280
|
|
|
if (file_exists(codecept_root_dir() . 'vendor' . DIRECTORY_SEPARATOR . 'autoload.php')) { |
281
|
|
|
// ensure autoloader from this dir is loaded |
282
|
|
|
require_once codecept_root_dir() . 'vendor' . DIRECTORY_SEPARATOR . 'autoload.php'; |
283
|
|
|
} |
284
|
|
|
|
285
|
|
|
require_once $file; |
286
|
|
|
|
287
|
|
|
$possibleKernelClasses = [ |
288
|
|
|
'AppKernel', // Symfony Standard |
289
|
|
|
'App\Kernel', // Symfony Flex |
290
|
|
|
]; |
291
|
|
|
foreach ($possibleKernelClasses as $class) { |
292
|
|
|
if (class_exists($class)) { |
293
|
|
|
$refClass = new \ReflectionClass($class); |
294
|
|
|
if ($refClass->getFileName() === $file->getRealpath()) { |
295
|
|
|
return $class; |
296
|
|
|
} |
297
|
|
|
} |
298
|
|
|
} |
299
|
|
|
|
300
|
|
|
throw new ModuleRequireException( |
301
|
|
|
__CLASS__, |
302
|
|
|
"Kernel class was not found in $file. " |
303
|
|
|
. "Specify directory where file with Kernel class for your application is located with `app_path` parameter." |
304
|
|
|
); |
305
|
|
|
} |
306
|
|
|
|
307
|
|
|
/** |
308
|
|
|
* Get service $serviceName and add it to the lists of persistent services. |
309
|
|
|
* If $isPermanent then service becomes persistent between tests |
310
|
|
|
* |
311
|
|
|
* @param string $serviceName |
312
|
|
|
* @param boolean $isPermanent |
313
|
|
|
*/ |
314
|
|
|
public function persistService($serviceName, $isPermanent = false) |
315
|
|
|
{ |
316
|
|
|
$service = $this->grabService($serviceName); |
317
|
|
|
$this->persistentServices[$serviceName] = $service; |
318
|
|
|
if ($isPermanent) { |
319
|
|
|
$this->permanentServices[$serviceName] = $service; |
320
|
|
|
} |
321
|
|
|
if ($this->client) { |
322
|
|
|
$this->client->persistentServices[$serviceName] = $service; |
|
|
|
|
323
|
|
|
} |
324
|
|
|
} |
325
|
|
|
|
326
|
|
|
/** |
327
|
|
|
* Remove service $serviceName from the lists of persistent services. |
328
|
|
|
* |
329
|
|
|
* @param string $serviceName |
330
|
|
|
*/ |
331
|
|
|
public function unpersistService($serviceName) |
332
|
|
|
{ |
333
|
|
|
if (isset($this->persistentServices[$serviceName])) { |
334
|
|
|
unset($this->persistentServices[$serviceName]); |
335
|
|
|
} |
336
|
|
|
if (isset($this->permanentServices[$serviceName])) { |
337
|
|
|
unset($this->permanentServices[$serviceName]); |
338
|
|
|
} |
339
|
|
|
if ($this->client && isset($this->client->persistentServices[$serviceName])) { |
|
|
|
|
340
|
|
|
unset($this->client->persistentServices[$serviceName]); |
341
|
|
|
} |
342
|
|
|
} |
343
|
|
|
|
344
|
|
|
/** |
345
|
|
|
* Invalidate previously cached routes. |
346
|
|
|
*/ |
347
|
|
|
public function invalidateCachedRouter() |
348
|
|
|
{ |
349
|
|
|
$this->unpersistService('router'); |
350
|
|
|
} |
351
|
|
|
|
352
|
|
|
/** |
353
|
|
|
* Opens web page using route name and parameters. |
354
|
|
|
* |
355
|
|
|
* ``` php |
356
|
|
|
* <?php |
357
|
|
|
* $I->amOnRoute('posts.create'); |
358
|
|
|
* $I->amOnRoute('posts.show', array('id' => 34)); |
359
|
|
|
* ?> |
360
|
|
|
* ``` |
361
|
|
|
* |
362
|
|
|
* @param $routeName |
363
|
|
|
* @param array $params |
364
|
|
|
*/ |
365
|
|
|
public function amOnRoute($routeName, array $params = []) |
366
|
|
|
{ |
367
|
|
|
$router = $this->grabService('router'); |
368
|
|
|
if (!$router->getRouteCollection()->get($routeName)) { |
369
|
|
|
$this->fail(sprintf('Route with name "%s" does not exists.', $routeName)); |
370
|
|
|
} |
371
|
|
|
$url = $router->generate($routeName, $params); |
372
|
|
|
$this->amOnPage($url); |
373
|
|
|
} |
374
|
|
|
|
375
|
|
|
/** |
376
|
|
|
* Checks that current url matches route. |
377
|
|
|
* |
378
|
|
|
* ``` php |
379
|
|
|
* <?php |
380
|
|
|
* $I->seeCurrentRouteIs('posts.index'); |
381
|
|
|
* $I->seeCurrentRouteIs('posts.show', array('id' => 8)); |
382
|
|
|
* ?> |
383
|
|
|
* ``` |
384
|
|
|
* |
385
|
|
|
* @param $routeName |
386
|
|
|
* @param array $params |
387
|
|
|
*/ |
388
|
|
|
public function seeCurrentRouteIs($routeName, array $params = []) |
389
|
|
|
{ |
390
|
|
|
$router = $this->grabService('router'); |
391
|
|
|
if (!$router->getRouteCollection()->get($routeName)) { |
392
|
|
|
$this->fail(sprintf('Route with name "%s" does not exists.', $routeName)); |
393
|
|
|
} |
394
|
|
|
|
395
|
|
|
$uri = explode('?', $this->grabFromCurrentUrl())[0]; |
396
|
|
|
try { |
397
|
|
|
$match = $router->match($uri); |
398
|
|
|
} catch (\Symfony\Component\Routing\Exception\ResourceNotFoundException $e) { |
399
|
|
|
$this->fail(sprintf('The "%s" url does not match with any route', $uri)); |
400
|
|
|
} |
401
|
|
|
$expected = array_merge(['_route' => $routeName], $params); |
402
|
|
|
$intersection = array_intersect_assoc($expected, $match); |
403
|
|
|
|
404
|
|
|
$this->assertEquals($expected, $intersection); |
405
|
|
|
} |
406
|
|
|
|
407
|
|
|
/** |
408
|
|
|
* Checks that current url matches route. |
409
|
|
|
* Unlike seeCurrentRouteIs, this can matches without exact route parameters |
410
|
|
|
* |
411
|
|
|
* ``` php |
412
|
|
|
* <?php |
413
|
|
|
* $I->seeCurrentRouteMatches('my_blog_pages'); |
414
|
|
|
* ?> |
415
|
|
|
* ``` |
416
|
|
|
* |
417
|
|
|
* @param $routeName |
418
|
|
|
*/ |
419
|
|
|
public function seeInCurrentRoute($routeName) |
420
|
|
|
{ |
421
|
|
|
$router = $this->grabService('router'); |
422
|
|
|
if (!$router->getRouteCollection()->get($routeName)) { |
423
|
|
|
$this->fail(sprintf('Route with name "%s" does not exists.', $routeName)); |
424
|
|
|
} |
425
|
|
|
|
426
|
|
|
$uri = explode('?', $this->grabFromCurrentUrl())[0]; |
427
|
|
|
try { |
428
|
|
|
$matchedRouteName = $router->match($uri)['_route']; |
429
|
|
|
} catch (\Symfony\Component\Routing\Exception\ResourceNotFoundException $e) { |
430
|
|
|
$this->fail(sprintf('The "%s" url does not match with any route', $uri)); |
431
|
|
|
} |
432
|
|
|
|
433
|
|
|
$this->assertEquals($matchedRouteName, $routeName); |
434
|
|
|
} |
435
|
|
|
|
436
|
|
|
/** |
437
|
|
|
* Checks if any email were sent by last request |
438
|
|
|
* |
439
|
|
|
* @throws \LogicException |
440
|
|
|
*/ |
441
|
|
|
public function seeEmailIsSent() |
442
|
|
|
{ |
443
|
|
|
$profile = $this->getProfile(); |
444
|
|
|
if (!$profile) { |
445
|
|
|
$this->fail('Emails can\'t be tested without Profiler'); |
446
|
|
|
} |
447
|
|
|
if (!$profile->hasCollector('swiftmailer')) { |
448
|
|
|
$this->fail('Emails can\'t be tested without SwiftMailer connector'); |
449
|
|
|
} |
450
|
|
|
|
451
|
|
|
$this->assertGreaterThan(0, $profile->getCollector('swiftmailer')->getMessageCount()); |
452
|
|
|
} |
453
|
|
|
|
454
|
|
|
/** |
455
|
|
|
* Grabs a service from Symfony DIC container. |
456
|
|
|
* Recommended to use for unit testing. |
457
|
|
|
* |
458
|
|
|
* ``` php |
459
|
|
|
* <?php |
460
|
|
|
* $em = $I->grabServiceFromContainer('doctrine'); |
461
|
|
|
* ?> |
462
|
|
|
* ``` |
463
|
|
|
* |
464
|
|
|
* @param $service |
465
|
|
|
* @return mixed |
466
|
|
|
* @part services |
467
|
|
|
* @deprecated Use grabService instead |
468
|
|
|
*/ |
469
|
|
|
public function grabServiceFromContainer($service) |
470
|
|
|
{ |
471
|
|
|
return $this->grabService($service); |
472
|
|
|
} |
473
|
|
|
|
474
|
|
|
/** |
475
|
|
|
* Grabs a service from Symfony DIC container. |
476
|
|
|
* Recommended to use for unit testing. |
477
|
|
|
* |
478
|
|
|
* ``` php |
479
|
|
|
* <?php |
480
|
|
|
* $em = $I->grabService('doctrine'); |
481
|
|
|
* ?> |
482
|
|
|
* ``` |
483
|
|
|
* |
484
|
|
|
* @param $service |
485
|
|
|
* @return mixed |
486
|
|
|
* @part services |
487
|
|
|
*/ |
488
|
|
|
public function grabService($service) |
489
|
|
|
{ |
490
|
|
|
$container = $this->_getContainer(); |
491
|
|
|
if (!$container->has($service)) { |
492
|
|
|
$this->fail("Service $service is not available in container"); |
493
|
|
|
} |
494
|
|
|
return $container->get($service); |
495
|
|
|
} |
496
|
|
|
|
497
|
|
|
/** |
498
|
|
|
* @return \Symfony\Component\HttpKernel\Profiler\Profile |
499
|
|
|
*/ |
500
|
|
|
protected function getProfile() |
501
|
|
|
{ |
502
|
|
|
$container = $this->_getContainer(); |
503
|
|
|
if (!$container->has('profiler')) { |
504
|
|
|
return null; |
505
|
|
|
} |
506
|
|
|
|
507
|
|
|
$profiler = $this->grabService('profiler'); |
508
|
|
|
$response = $this->client->getResponse(); |
509
|
|
|
if (null === $response) { |
510
|
|
|
$this->fail("You must perform a request before using this method."); |
511
|
|
|
} |
512
|
|
|
return $profiler->loadProfileFromResponse($response); |
513
|
|
|
} |
514
|
|
|
|
515
|
|
|
/** |
516
|
|
|
* @param $url |
517
|
|
|
*/ |
518
|
|
|
protected function debugResponse($url) |
519
|
|
|
{ |
520
|
|
|
parent::debugResponse($url); |
521
|
|
|
|
522
|
|
|
if ($profile = $this->getProfile()) { |
523
|
|
|
if ($profile->hasCollector('security')) { |
524
|
|
|
if ($profile->getCollector('security')->isAuthenticated()) { |
525
|
|
|
$roles = $profile->getCollector('security')->getRoles(); |
526
|
|
|
|
527
|
|
|
if ($roles instanceof Data) { |
528
|
|
|
$roles = $this->extractRawRoles($roles); |
529
|
|
|
} |
530
|
|
|
|
531
|
|
|
$this->debugSection( |
532
|
|
|
'User', |
533
|
|
|
$profile->getCollector('security')->getUser() |
534
|
|
|
. ' [' . implode(',', $roles) . ']' |
535
|
|
|
); |
536
|
|
|
} else { |
537
|
|
|
$this->debugSection('User', 'Anonymous'); |
538
|
|
|
} |
539
|
|
|
} |
540
|
|
|
if ($profile->hasCollector('swiftmailer')) { |
541
|
|
|
$messages = $profile->getCollector('swiftmailer')->getMessageCount(); |
542
|
|
|
if ($messages) { |
543
|
|
|
$this->debugSection('Emails', $messages . ' sent'); |
544
|
|
|
} |
545
|
|
|
} |
546
|
|
|
if ($profile->hasCollector('timer')) { |
547
|
|
|
$this->debugSection('Time', $profile->getCollector('timer')->getTime()); |
548
|
|
|
} |
549
|
|
|
} |
550
|
|
|
} |
551
|
|
|
|
552
|
|
|
/** |
553
|
|
|
* @param Data $data |
554
|
|
|
* @return array |
555
|
|
|
*/ |
556
|
|
|
private function extractRawRoles(Data $data) |
557
|
|
|
{ |
558
|
|
|
if ($this->dataRevealsValue($data)) { |
559
|
|
|
$roles = $data->getValue(); |
560
|
|
|
} else { |
561
|
|
|
$raw = $data->getRawData(); |
562
|
|
|
$roles = isset($raw[1]) ? $raw[1] : []; |
563
|
|
|
} |
564
|
|
|
|
565
|
|
|
return $roles; |
566
|
|
|
} |
567
|
|
|
|
568
|
|
|
/** |
569
|
|
|
* Returns a list of recognized domain names. |
570
|
|
|
* |
571
|
|
|
* @return array |
572
|
|
|
*/ |
573
|
|
|
protected function getInternalDomains() |
574
|
|
|
{ |
575
|
|
|
$internalDomains = []; |
576
|
|
|
|
577
|
|
|
$routes = $this->grabService('router')->getRouteCollection(); |
578
|
|
|
/* @var \Symfony\Component\Routing\Route $route */ |
579
|
|
|
foreach ($routes as $route) { |
580
|
|
|
if (!is_null($route->getHost())) { |
581
|
|
|
$compiled = $route->compile(); |
582
|
|
|
if (!is_null($compiled->getHostRegex())) { |
583
|
|
|
$internalDomains[] = $compiled->getHostRegex(); |
584
|
|
|
} |
585
|
|
|
} |
586
|
|
|
} |
587
|
|
|
|
588
|
|
|
return array_unique($internalDomains); |
589
|
|
|
} |
590
|
|
|
|
591
|
|
|
/** |
592
|
|
|
* Reboot client's kernel. |
593
|
|
|
* Can be used to manually reboot kernel when 'rebootable_client' => false |
594
|
|
|
* |
595
|
|
|
* ``` php |
596
|
|
|
* <?php |
597
|
|
|
* ... |
598
|
|
|
* perform some requests |
599
|
|
|
* ... |
600
|
|
|
* $I->rebootClientKernel(); |
601
|
|
|
* ... |
602
|
|
|
* perform other requests |
603
|
|
|
* ... |
604
|
|
|
* |
605
|
|
|
* ?> |
606
|
|
|
* ``` |
607
|
|
|
* |
608
|
|
|
*/ |
609
|
|
|
public function rebootClientKernel() |
610
|
|
|
{ |
611
|
|
|
if ($this->client) { |
612
|
|
|
$this->client->rebootKernel(); |
613
|
|
|
} |
614
|
|
|
} |
615
|
|
|
|
616
|
|
|
/** |
617
|
|
|
* Public API from Data changed from Symfony 3.2 to 3.3. |
618
|
|
|
* |
619
|
|
|
* @param \Symfony\Component\VarDumper\Cloner\Data $data |
620
|
|
|
* |
621
|
|
|
* @return bool |
622
|
|
|
*/ |
623
|
|
|
private function dataRevealsValue(Data $data) |
624
|
|
|
{ |
625
|
|
|
return method_exists($data, 'getValue'); |
626
|
|
|
} |
627
|
|
|
} |
628
|
|
|
|
An attempt at access to an undefined property has been detected. This may either be a typographical error or the property has been renamed but there are still references to its old name.
If you really want to allow access to undefined properties, you can define magic methods to allow access. See the php core documentation on Overloading.