EngineAsArgumentInKernelControllerTest   A
last analyzed

Complexity

Total Complexity 12

Size/Duplication

Total Lines 232
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 24

Importance

Changes 0
Metric Value
wmc 12
lcom 1
cbo 24
dl 0
loc 232
rs 10
c 0
b 0
f 0

12 Methods

Rating   Name   Duplication   Size   Complexity  
A testCanBeCreated() 0 8 1
A testKernelInterface() 0 8 1
A FrameworkReturnsResponse() 0 8 1
B testControllerResponse() 0 59 1
A testContainerCanBeCreated() 0 8 1
A testContainerInterface() 0 8 1
A ComponentReturnsResponse() 0 39 1
A configureRoutes() 0 7 1
A loadRoutes() 0 7 1
A configureJustHelloRoutes() 0 12 1
A loadJustHelloRoutes() 0 7 1
A container() 0 47 1
1
<?php
2
3
/*
4
 * This file is part of the Symfony-Util package.
5
 *
6
 * (c) Jean-Bernard Addor
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
use PHPUnit\Framework\TestCase;
13
use Symfony\Bridge\Twig\TwigEngine;
14
// use Symfony\Bundle\FrameworkBundle\Controller\ControllerResolver; // Do not know how to configure this.
15
use Symfony\Component\DependencyInjection\ContainerBuilder;
16
use Symfony\Component\EventDispatcher\EventDispatcher;
17
use Symfony\Component\HttpFoundation\Request;
18
use Symfony\Component\HttpFoundation\RequestStack;
19
use Symfony\Component\HttpFoundation\Response;
20
use Symfony\Component\HttpKernel\Controller\ArgumentResolver;
21
use Symfony\Component\HttpKernel\Controller\ArgumentResolver\DefaultValueResolver;
22
use Symfony\Component\HttpKernel\Controller\ArgumentResolver\RequestAttributeValueResolver;
23
use Symfony\Component\HttpKernel\Controller\ArgumentResolver\RequestValueResolver;
24
use Symfony\Component\HttpKernel\Controller\ArgumentResolver\ServiceValueResolver;
25
use Symfony\Component\HttpKernel\Controller\ArgumentResolver\SessionValueResolver;
26
use Symfony\Component\HttpKernel\Controller\ArgumentResolver\VariadicValueResolver;
27
use Symfony\Component\HttpKernel\Controller\ContainerControllerResolver;
28
use Symfony\Component\HttpKernel\Controller\ControllerResolver;
29
use Symfony\Component\HttpKernel\ControllerMetadata\ArgumentMetadataFactory;
30
use Symfony\Component\HttpKernel\DependencyInjection\ControllerArgumentValueResolverPass;
31
use Symfony\Component\HttpKernel\DependencyInjection\RegisterControllerArgumentLocatorsPass;
32
use Symfony\Component\HttpKernel\EventListener\ResponseListener;
33
use Symfony\Component\HttpKernel\EventListener\RouterListener;
34
use Symfony\Component\HttpKernel\HttpKernel;
35
use Symfony\Component\Routing\Matcher\UrlMatcher; // != Symfony\Bundle\FrameworkBundle\Routing\Router
36
use Symfony\Component\Routing\Matcher\UrlMatcherInterface;
37
use Symfony\Component\Routing\RequestContext;
38
use Symfony\Component\Routing\RouteCollectionBuilder;
39
use Symfony\Component\Templating\EngineInterface;
40
use Symfony\Component\Templating\TemplateNameParser;
41
use Symfony\Component\Templating\TemplateNameParserInterface;
42
use SymfonyUtil\Controller\EngineAsArgumentController;
43
use Tests\Component\AppKernel;
0 ignored issues
show
Bug introduced by
This use statement conflicts with another class in this namespace, AppKernel.

Let’s assume that you have a directory layout like this:

.
|-- OtherDir
|   |-- Bar.php
|   `-- Foo.php
`-- SomeDir
    `-- Foo.php

and let’s assume the following content of Bar.php:

// Bar.php
namespace OtherDir;

use SomeDir\Foo; // This now conflicts the class OtherDir\Foo

If both files OtherDir/Foo.php and SomeDir/Foo.php are loaded in the same runtime, you will see a PHP error such as the following:

PHP Fatal error:  Cannot use SomeDir\Foo as Foo because the name is already in use in OtherDir/Foo.php

However, as OtherDir/Foo.php does not necessarily have to be loaded and the error is only triggered if it is loaded before OtherDir/Bar.php, this problem might go unnoticed for a while. In order to prevent this error from surfacing, you must import the namespace with a different alias:

// Bar.php
namespace OtherDir;

use SomeDir\Foo as SomeDirFoo; // There is no conflict anymore.
Loading history...
44
use Tests\Component\EngineAsArgumentFrameworkController;
45
46
final class EngineAsArgumentInKernelControllerTest extends TestCase
47
{
48
    public function testCanBeCreated()
49
    {
50
        $this->assertInstanceOf(
51
            // ...::class, // 5.4 < php
52
            'Symfony\Component\HttpKernel\Kernel',
53
            new AppKernel('dev', true)
54
        );
55
    }
56
57
    public function testKernelInterface()
58
    {
59
        $this->assertInstanceOf(
60
            // ...::class, // 5.4 < php
61
            'Symfony\Component\HttpKernel\KernelInterface',
62
            new AppKernel('dev', true)
63
        );
64
    }
65
66
    public function FrameworkReturnsResponse() // failling: no more a test
67
    {
68
        $this->assertInstanceOf(
69
            // Response::class, // 5.4 < php
70
            'Symfony\Component\HttpFoundation\Response',
71
            (new AppKernel('dev', true))->handle(Request::create('/', 'GET'))
72
        );
73
    }
74
75
    public function testControllerResponse()
76
    { // From: https://symfony.com/doc/current/create_framework/unit_testing.html
77
        // TODO: Try with a real matcher
78
        // TODO: Use real controller to be tested!
79
        $matcher = $this->createMock(UrlMatcherInterface::class);
80
        // use getMock() on PHPUnit 5.3 or below
81
        // $matcher = $this->getMock(UrlMatcherInterface::class);
82
83
        $matcher
84
            ->expects($this->once())
85
            ->method('match')
86
            // ->will($this->returnValue([
87
            ->willReturn([
88
                '_route' => 'foo',
89
                'name' => 'Fabien',
90
                '_controller' => function ($name) {
91
                    return new Response('Hello '.$name);
92
                },
93
            // ]))
94
            ])
95
        ;
96
        $matcher
97
            ->expects($this->once())
98
            ->method('getContext')
99
            // ->will($this->returnValue($this->createMock(RequestContext::class)))
100
            ->willReturn($this->createMock(RequestContext::class))
101
        ;
102
103
        $c = $this->container();
104
        $c->compile();
105
        $requestStack = new RequestStack();
106
        $dispatcher = new EventDispatcher();
107
        $dispatcher->addSubscriber(new RouterListener(
108
            $matcher,
109
            $requestStack
110
        )); // Returns nothing.
111
        $dispatcher->addSubscriber(new ResponseListener('UTF-8'));
112
        $response = (new HttpKernel(
113
            $dispatcher,
114
            new ContainerControllerResolver($c),
115
            // new ControllerResolver(),
116
            $requestStack,
117
            new ArgumentResolver(
118
                new ArgumentMetadataFactory(),
119
                [
120
                    new RequestAttributeValueResolver(),
121
                    new RequestValueResolver(),
122
                    new SessionValueResolver(),
123
                    new ServiceValueResolver($c),
124
                    new DefaultValueResolver(),
125
                    new VariadicValueResolver(),
126
                ]
127
            )
128
        // ))->handle(Request::create('/', 'GET'));
129
        ))->handle(new Request());
130
131
        $this->assertSame(200, $response->getStatusCode());
132
        $this->assertContains('Hello Fabien', $response->getContent());
133
    }
134
135
    public function testContainerCanBeCreated()
136
    {
137
        $this->assertInstanceOf(
138
            // ...::class, // 5.4 < php
139
            'Symfony\Component\DependencyInjection\ContainerBuilder',
140
            $this->container()
141
        );
142
    }
143
144
    public function testContainerInterface()
145
    {
146
        $this->assertInstanceOf(
147
            // ...::class, // 5.4 < php
148
            'psr\Container\ContainerInterface',
149
            $this->container()
150
        );
151
    }
152
153
    public function ComponentReturnsResponse() // Not yet a test!
154
    {
155
        // TODO: Use real controller to be tested!
156
        $c = $this->container();
157
        $c->compile();
158
        $requestStack = new RequestStack();
159
        $dispatcher = new EventDispatcher();
160
        $dispatcher->addSubscriber(new RouterListener(
161
            new UrlMatcher(
162
                // $this->loadJustHelloRoutes(),
163
                $this->loadRoutes(),
164
                new RequestContext()
165
            ),
166
            $requestStack
167
        ));
168
        $dispatcher->addSubscriber(new ResponseListener('UTF-8'));
169
170
        $this->assertInstanceOf(
171
            // Response::class, // 5.4 < php
172
            'Symfony\Component\HttpFoundation\Response',
173
            (new HttpKernel(
174
                $dispatcher,
175
                new ContainerControllerResolver($c),
176
                // new ControllerResolver(),
177
                $requestStack,
178
                new ArgumentResolver(
179
                    new ArgumentMetadataFactory(),
180
                    [
181
                        new RequestAttributeValueResolver(),
182
                        new RequestValueResolver(),
183
                        new SessionValueResolver(),
184
                        new ServiceValueResolver($c),
185
                        new DefaultValueResolver(),
186
                        new VariadicValueResolver(),
187
                    ]
188
                )
189
            ))->handle(Request::create('/', 'GET'))
190
        );
191
    }
192
193
    private function configureRoutes(RouteCollectionBuilder $routes)
194
    { // from Symfony\Bundle\FrameworkBundle\Kernel\MicroKernelTrait
195
        $routes->add('/', EngineAsArgumentController::class, 'index'); // .'::__invoke'
196
        // $routes->add('/', EngineAsArgumentFrameworkController::class, 'index'); // .'::__invoke'
197
        //^ It should be tested if the actually used controller resolver can resolve this!
198
        //^ Returns Symfony/Component/Routing/Route .
199
    }
200
201
    private function loadRoutes(LoaderInterface $loader = null)
202
    { // from Symfony\Bundle\FrameworkBundle\Kernel\MicroKernelTrait
203
        $routes = new RouteCollectionBuilder($loader);
204
        $this->configureRoutes($routes);
205
206
        return $routes->build();
207
    }
208
209
    private function configureJustHelloRoutes(RouteCollectionBuilder $routes)
210
    { // from Symfony\Bundle\FrameworkBundle\Kernel\MicroKernelTrait
211
        $routes->add(
212
            '/',
213
            function () {
0 ignored issues
show
Documentation introduced by
function () { return...on\Response('Hello'); } is of type object<Closure>, but the function expects a string.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
214
                return new Response('Hello');
215
            },
216
            'index'
217
        ); // .'::__invoke'
218
        //^ It should be tested if the actually used controller resolver can resolve this!
219
        //^ Returns Symfony/Component/Routing/Route .
220
    }
221
222
    private function loadJustHelloRoutes(LoaderInterface $loader = null)
0 ignored issues
show
Unused Code introduced by
This method is not used, and could be removed.
Loading history...
223
    { // from Symfony\Bundle\FrameworkBundle\Kernel\MicroKernelTrait
224
        $routes = new RouteCollectionBuilder($loader);
225
        $this->configureJustHelloRoutes($routes);
226
227
        return $routes->build();
228
    }
229
230
    private function container()
231
    {
232
        $c = new ContainerBuilder();
233
        // https://symfony.com/doc/current/service_container.html
234
235
        $c->autowire(TemplateNameParser::class)
236
            ->setAutoconfigured(true)
237
            ->setPublic(false);
238
        $c->setAlias(TemplateNameParserInterface::class, TemplateNameParser::class);
239
240
        $c->autowire(Twig_Loader_Array::class, Twig_Loader_Array::class)
241
            ->setArgument('$templates', ['index.html.twig' => 'Hello Component!'])
242
            ->setAutoconfigured(true)
243
            ->setPublic(false);
244
        $c->setAlias(Twig_LoaderInterface::class, Twig_Loader_Array::class);
245
246
        $c->autowire(Twig_Environment::class, Twig_Environment::class)
247
            ->setAutoconfigured(true)
248
            ->setPublic(false);
249
        $c->setAlias(Twig\Environment::class, Twig_Environment::class);
250
251
        $c->autowire(TwigEngine::class)
252
            ->setAutoconfigured(true)
253
            ->setPublic(false);
254
        $c->setAlias(EngineInterface::class, TwigEngine::class);
255
        $c->setAlias('templating', TwigEngine::class); // Read Symfony source code to understand!
256
257
        // Unit Testing
258
        // $c->autowire('test.client', Client::class)
259
        //     ->setPublic(true); // Public needed!
260
261
        //Controllers
262
        $c->autowire(EngineAsArgumentController::class)
263
            ->setAutoconfigured(true)
264
            ->addTag('controller.service_arguments')
265
            ->setPublic(true); // Checking if needed...
266
267
        $c->autowire(EngineAsArgumentFrameworkController::class)
268
            ->setAutoconfigured(true)
269
            ->addTag('controller.service_arguments')
270
            ->setPublic(true); // Checking if needed...
271
272
        $c->addCompilerPass(new ControllerArgumentValueResolverPass());
273
        $c->addCompilerPass(new RegisterControllerArgumentLocatorsPass());
274
275
        return $c;
276
    }
277
}
278
279
// http://api.symfony.com/3.3/Symfony/Bridge/Twig/TwigEngine.html
280
// http://api.symfony.com/3.3/Symfony/Bundle/TwigBundle/TwigEngine.html
281