Completed
Push — feature/evo-2472-whoami ( 843346...066c1c )
by
unknown
83:53 queued 67:03
created

RestController   F

Complexity

Total Complexity 49

Size/Duplication

Total Lines 671
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 20

Test Coverage

Coverage 35.62%

Importance

Changes 2
Bugs 0 Features 1
Metric Value
wmc 49
c 2
b 0
f 1
lcom 1
cbo 20
dl 0
loc 671
ccs 78
cts 219
cp 0.3562
rs 3.6755

26 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 21 1
A setTokenStorage() 0 4 1
A setFormDataMapper() 0 4 1
A setJsonPatchValidator() 0 4 1
A setFormValidator() 0 4 1
A getContainer() 0 4 1
A getAction() 0 13 1
A getResponse() 0 4 1
A findRecord() 0 12 2
A getModel() 0 8 2
A setModel() 0 6 1
B serialize() 0 24 4
A getRestUtils() 0 4 1
A allAction() 0 19 3
B postAction() 0 30 1
A deserialize() 0 22 2
A getRouter() 0 4 1
B putAction() 0 49 5
B patchAction() 0 54 6
A deleteAction() 0 12 1
A optionsAction() 0 21 2
B schemaAction() 0 34 4
A getValidator() 0 4 1
A render() 0 4 1
A getRouteName() 0 12 2
A getUser() 0 8 2

How to fix   Complexity   

Complex Class

Complex classes like RestController often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes. You can also have a look at the cohesion graph to spot any un-connected, or weakly-connected components.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use RestController, and based on these observations, apply Extract Interface, too.

1
<?php
2
/**
3
 * basic rest controller
4
 */
5
6
namespace Graviton\RestBundle\Controller;
7
8
use Graviton\DocumentBundle\Service\FormDataMapperInterface;
9
use Graviton\ExceptionBundle\Exception\DeserializationException;
10
use Graviton\ExceptionBundle\Exception\InvalidJsonPatchException;
11
use Graviton\ExceptionBundle\Exception\MalformedInputException;
12
use Graviton\ExceptionBundle\Exception\NotFoundException;
13
use Graviton\ExceptionBundle\Exception\SerializationException;
14
use Graviton\RestBundle\Validator\Form;
15
use Graviton\RestBundle\Model\DocumentModel;
16
use Graviton\RestBundle\Model\PaginatorAwareInterface;
17
use Graviton\SchemaBundle\SchemaUtils;
18
use Graviton\DocumentBundle\Form\Type\DocumentType;
19
use Graviton\RestBundle\Service\RestUtilsInterface;
20
use Knp\Component\Pager\Paginator;
21
use Symfony\Component\DependencyInjection\ContainerInterface;
22
use Symfony\Component\HttpFoundation\Request;
23
use Symfony\Component\HttpFoundation\Response;
24
use Symfony\Component\Routing\Exception\RouteNotFoundException;
25
use Symfony\Component\Form\FormFactory;
26
use Symfony\Bundle\FrameworkBundle\Routing\Router;
27
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorage;
28
use Symfony\Component\Validator\Validator\ValidatorInterface;
29
use Symfony\Bundle\FrameworkBundle\Templating\EngineInterface;
30
use Rs\Json\Patch;
31
use Rs\Json\Patch\InvalidPatchDocumentJsonException;
32
use Rs\Json\Patch\InvalidTargetDocumentJsonException;
33
use Rs\Json\Patch\InvalidOperationException;
34
use Rs\Json\Patch\FailedTestException;
35
use Graviton\RestBundle\Service\JsonPatchValidator;
36
37
/**
38
 * This is a basic rest controller. It should fit the most needs but if you need to add some
39
 * extra functionality you can extend it and overwrite single/all actions.
40
 * You can also extend the model class to add some extra logic before save
41
 *
42
 * @author   List of contributors <https://github.com/libgraviton/graviton/graphs/contributors>
43
 * @license  http://opensource.org/licenses/gpl-license.php GNU Public License
44
 * @link     http://swisscom.ch
45
 */
46
class RestController
47
{
48
    /**
49
     * @var DocumentModel
50
     */
51
    private $model;
52
53
    /**
54
     * @var ContainerInterface service_container
55
     */
56
    private $container;
57
58
    /**
59
     * @var Response
60
     */
61
    private $response;
62
63
    /**
64
     * @var FormFactory
65
     */
66
    private $formFactory;
67
68
    /**
69
     * @var DocumentType
70
     */
71
    private $formType;
72
73
    /**
74
     * @var RestUtilsInterface
75
     */
76
    private $restUtils;
77
78
    /**
79
     * @var SchemaUtils
80
     */
81
    private $schemaUtils;
82
83
    /**
84
     * @var FormDataMapperInterface
85
     */
86
    protected $formDataMapper;
87
88
    /**
89
     * @var Router
90
     */
91
    private $router;
92
93
    /**
94
     * @var ValidatorInterface
95
     */
96
    private $validator;
97
98
    /**
99
     * @var EngineInterface
100
     */
101
    private $templating;
102
103
    /**
104
     * @var JsonPatchValidator
105
     */
106
    private $jsonPatchValidator;
107
108
    /**
109
     * @var Form
110
     */
111
    protected $formValidator;
112
113
    /**
114
     * @var TokenStorage
115
     */
116
    protected $tokenStorage;
117
118
    /**
119
     * @param Response           $response    Response
120
     * @param RestUtilsInterface $restUtils   Rest utils
121
     * @param Router             $router      Router
122
     * @param ValidatorInterface $validator   Validator
123
     * @param EngineInterface    $templating  Templating
124
     * @param FormFactory        $formFactory form factory
125
     * @param DocumentType       $formType    generic form
126
     * @param ContainerInterface $container   Container
127
     * @param SchemaUtils        $schemaUtils Schema utils
128
     */
129 2
    public function __construct(
130
        Response $response,
131
        RestUtilsInterface $restUtils,
132
        Router $router,
133
        ValidatorInterface $validator,
134
        EngineInterface $templating,
135
        FormFactory $formFactory,
136
        DocumentType $formType,
137
        ContainerInterface $container,
138
        SchemaUtils $schemaUtils
139
    ) {
140 2
        $this->response = $response;
141 2
        $this->restUtils = $restUtils;
142 2
        $this->router = $router;
143 2
        $this->validator = $validator;
144 2
        $this->templating = $templating;
145 2
        $this->formFactory = $formFactory;
146 2
        $this->formType = $formType;
147 2
        $this->container = $container;
148 2
        $this->schemaUtils = $schemaUtils;
149 2
    }
150
151
    /**
152
     * Setter for the tokenStorage
153
     *
154
     * @param TokenStorage $tokenStorage The token storage
155
     * @return void
156 2
     */
157
    public function setTokenStorage(TokenStorage $tokenStorage)
158 2
    {
159 2
        $this->tokenStorage = $tokenStorage;
160
    }
161
162
    /**
163
     * Set form data mapper
164
     *
165
     * @param FormDataMapperInterface $formDataMapper Form data mapper
166
     * @return void
167 2
     */
168
    public function setFormDataMapper(FormDataMapperInterface $formDataMapper)
169 2
    {
170 2
        $this->formDataMapper = $formDataMapper;
171
    }
172
173
    /**
174
     * @param JsonPatchValidator $jsonPatchValidator Service for validation json patch
175
     * @return void
176 2
     */
177
    public function setJsonPatchValidator(JsonPatchValidator $jsonPatchValidator)
178 2
    {
179 2
        $this->jsonPatchValidator = $jsonPatchValidator;
180
    }
181
182
    /**
183
     * Defines the Form validator to be used.
184
     *
185
     * @param Form $validator Validator to be used
186
     *
187
     * @return void
188 2
     */
189
    public function setFormValidator(Form $validator)
190 2
    {
191 2
        $this->formValidator = $validator;
192
    }
193
194
    /**
195
     * Get the container object
196
     *
197
     * @return \Symfony\Component\DependencyInjection\ContainerInterface
198
     *
199
     * @obsolete
200
     */
201
    public function getContainer()
202
    {
203
        return $this->container;
204
    }
205
206
    /**
207
     * Returns a single record
208
     *
209
     * @param Request $request Current http request
210
     * @param string  $id      ID of record
211
     *
212
     * @return \Symfony\Component\HttpFoundation\Response $response Response with result or error
213 1
     */
214
    public function getAction(Request $request, $id)
215 1
    {
216 1
        $response = $this->getResponse()
217
            ->setStatusCode(Response::HTTP_OK);
218 1
219
        $record = $this->findRecord($id);
220 1
221 1
        return $this->render(
222 1
            'GravitonRestBundle:Main:index.json.twig',
223
            ['response' => $this->serialize($record)],
224 1
            $response
225
        );
226
    }
227
228
    /**
229
     * Get the response object
230
     *
231
     * @return \Symfony\Component\HttpFoundation\Response $response Response object
232 2
     */
233
    public function getResponse()
234 2
    {
235
        return $this->response;
236
    }
237
238
    /**
239
     * Get a single record from database or throw an exception if it doesn't exist
240
     *
241
     * @param mixed $id Record id
242
     *
243
     * @throws \Graviton\ExceptionBundle\Exception\NotFoundException
244
     *
245
     * @return object $record Document object
246 1
     */
247
    protected function findRecord($id)
248 1
    {
249
        $response = $this->getResponse();
250 1
251
        if (!($record = $this->getModel()->find($id))) {
252
            $e = new NotFoundException("Entry with id " . $id . " not found!");
253
            $e->setResponse($response);
254
            throw $e;
255
        }
256 1
257
        return $record;
258
    }
259
260
    /**
261
     * Return the model
262
     *
263
     * @throws \Exception in case no model was defined.
264
     *
265
     * @return DocumentModel $model Model
266 2
     */
267
    public function getModel()
268 2
    {
269
        if (!$this->model) {
270
            throw new \Exception('No model is set for this controller');
271
        }
272 2
273
        return $this->model;
274
    }
275
276
    /**
277
     * Set the model class
278
     *
279
     * @param DocumentModel $model Model class
280
     *
281
     * @return self
282 2
     */
283
    public function setModel(DocumentModel $model)
284 2
    {
285
        $this->model = $model;
286 2
287
        return $this;
288
    }
289
290
    /**
291
     * Serialize the given record and throw an exception if something went wrong
292
     *
293
     * @param object|object[] $result Record(s)
294
     *
295
     * @throws \Graviton\ExceptionBundle\Exception\SerializationException
296
     *
297
     * @return string $content Json content
298 2
     */
299
    protected function serialize($result)
300 2
    {
301
        $response = $this->getResponse();
302
303
        try {
304
            // array is serialized as an object {"0":{...},"1":{...},...} when data contains an empty objects
305 2
            // we serialize each item because we can assume this bug affects only root array element
306 1
            if (is_array($result) && array_keys($result) === range(0, count($result) - 1)) {
307 1
                $result = array_map(
308 1
                    function ($item) {
309 1
                        return $this->getRestUtils()->serializeContent($item);
310
                    },
311 1
                    $result
312 1
                );
313
                return '['.implode(',', $result).']';
314
            }
315 1
316
            return $this->getRestUtils()->serializeContent($result);
0 ignored issues
show
Bug introduced by
It seems like $result defined by parameter $result on line 299 can also be of type array; however, Graviton\RestBundle\Serv...ils::serializeContent() does only seem to accept object, maybe add an additional type check?

This check looks at variables that have been passed in as parameters and are passed out again to other methods.

If the outgoing method call has stricter type requirements than the method itself, an issue is raised.

An additional type check may prevent trouble.

Loading history...
317
        } catch (\Exception $e) {
318
            $exception = new SerializationException($e);
319
            $exception->setResponse($response);
320
            throw $exception;
321
        }
322
    }
323
324
    /**
325
     * Get RestUtils service
326
     *
327
     * @return \Graviton\RestBundle\Service\RestUtils
328 2
     */
329
    public function getRestUtils()
330 2
    {
331
        return $this->restUtils;
332
    }
333
334
    /**
335
     * Returns all records
336
     *
337
     * @param Request $request Current http request
338
     *
339
     * @return \Symfony\Component\HttpFoundation\Response $response Response with result or error
340 1
     */
341
    public function allAction(Request $request)
342 1
    {
343 1
        $model = $this->getModel();
344
        $user = $this->getUser();
345 1
346
        if ($model instanceof PaginatorAwareInterface && !$model->hasPaginator()) {
347
            $paginator = new Paginator();
348
            $model->setPaginator($paginator);
349
        }
350 1
351 1
        $response = $this->getResponse()
352
            ->setStatusCode(Response::HTTP_OK);
353 1
354 1
        return $this->render(
355 1
            'GravitonRestBundle:Main:index.json.twig',
356
            ['response' => $this->serialize($model->findAll($request, $user))],
357 1
            $response
358
        );
359
    }
360
361
    /**
362
     * Writes a new Entry to the database
363
     *
364
     * @param Request $request Current http request
365
     *
366
     * @return \Symfony\Component\HttpFoundation\Response $response Result of action with data (if successful)
367
     */
368
    public function postAction(Request $request)
369
    {
370
        // Get the response object from container
371
        $response = $this->getResponse();
372
        $model = $this->getModel();
373
374
        $this->formValidator->checkJsonRequest($request, $response);
375
        $record = $this->formValidator->checkForm(
376
            $this->formValidator->getForm($request, $model),
377
            $model,
378
            $this->formDataMapper,
379
            $request->getContent()
0 ignored issues
show
Bug introduced by
It seems like $request->getContent() targeting Symfony\Component\HttpFo...n\Request::getContent() can also be of type resource; however, Graviton\RestBundle\Validator\Form::checkForm() does only seem to accept string, maybe add an additional type check?

This check looks at variables that are passed out again to other methods.

If the outgoing method call has stricter type requirements than the method itself, an issue is raised.

An additional type check may prevent trouble.

Loading history...
380
        );
381
382
        // Insert the new record
383
        $record = $this->getModel()->insertRecord($record);
384
385
        // store id of new record so we dont need to reparse body later when needed
386
        $request->attributes->set('id', $record->getId());
387
388
        // Set status code
389
        $response->setStatusCode(Response::HTTP_CREATED);
390
391
        $response->headers->set(
392
            'Location',
393
            $this->getRouter()->generate($this->getRouteName($request), array('id' => $record->getId()))
394
        );
395
396
        return $response;
397
    }
398
399
    /**
400
     * Deserialize the given content throw an exception if something went wrong
401
     *
402
     * @param string $content       Request content
403
     * @param string $documentClass Document class
404
     *
405
     * @throws DeserializationException
406
     *
407
     * @return object $record Document
408
     */
409
    protected function deserialize($content, $documentClass)
410
    {
411
        $response = $this->getResponse();
412
413
        try {
414
            $record = $this->getRestUtils()->deserializeContent(
415
                $content,
416
                $documentClass
417
            );
418
        } catch (\Exception $e) {
419
            // pass the previous exception in this case to get the error message in the handler
420
            // http://php.net/manual/de/exception.getprevious.php
421
            $exception = new DeserializationException("Deserialization failed", $e);
422
423
            // at the moment, the response has to be set on the exception object.
424
            // try to refactor this and return the graviton.rest.response if none is set...
425
            $exception->setResponse($response);
426
            throw $exception;
427
        }
428
429
        return $record;
430
    }
431
432
    /**
433
     * Get the router from the dic
434
     *
435
     * @return Router
436 1
     */
437
    public function getRouter()
438 1
    {
439
        return $this->router;
440
    }
441
442
    /**
443
     * Update a record
444
     *
445
     * @param Number  $id      ID of record
446
     * @param Request $request Current http request
447
     *
448
     * @throws MalformedInputException
449
     *
450
     * @return Response $response Result of action with data (if successful)
451
     */
452
    public function putAction($id, Request $request)
453
    {
454
        $response = $this->getResponse();
455
        $model = $this->getModel();
456
457
        $this->formValidator->checkJsonRequest($request, $response);
458
459
        $record = $this->formValidator->checkForm(
460
            $this->formValidator->getForm($request, $model),
461
            $model,
462
            $this->formDataMapper,
463
            $request->getContent()
0 ignored issues
show
Bug introduced by
It seems like $request->getContent() targeting Symfony\Component\HttpFo...n\Request::getContent() can also be of type resource; however, Graviton\RestBundle\Validator\Form::checkForm() does only seem to accept string, maybe add an additional type check?

This check looks at variables that are passed out again to other methods.

If the outgoing method call has stricter type requirements than the method itself, an issue is raised.

An additional type check may prevent trouble.

Loading history...
464
        );
465
466
        // does it really exist??
467
        $upsert = false;
468
        try {
469
            $this->findRecord($id);
470
        } catch (NotFoundException $e) {
471
            // who cares, we'll upsert it
472
            $upsert = true;
473
        }
474
475
        // handle missing 'id' field in input to a PUT operation
476
        // if it is settable on the document, let's set it and move on.. if not, inform the user..
477
        if ($record->getId() != $id) {
478
            // try to set it..
479
            if (is_callable(array($record, 'setId'))) {
480
                $record->setId($id);
481
            } else {
482
                throw new MalformedInputException('No ID was supplied in the request payload.');
483
            }
484
        }
485
486
        // And update the record, if everything is ok
487
        if ($upsert) {
488
            $this->getModel()->insertRecord($record);
489
        } else {
490
            $this->getModel()->updateRecord($id, $record);
491
        }
492
493
        // Set status code
494
        $response->setStatusCode(Response::HTTP_NO_CONTENT);
495
496
        // store id of new record so we dont need to reparse body later when needed
497
        $request->attributes->set('id', $record->getId());
498
499
        return $response;
500
    }
501
502
    /**
503
     * Patch a record
504
     *
505
     * @param Number  $id      ID of record
506
     * @param Request $request Current http request
507
     *
508
     * @throws MalformedInputException
509
     *
510
     * @return Response $response Result of action with data (if successful)
511
     */
512
    public function patchAction($id, Request $request)
513
    {
514
        $response = $this->getResponse();
515
        $this->formValidator->checkJsonRequest($request, $response);
516
517
        // Check JSON Patch request
518
        $this->formValidator->checkJsonPatchRequest(json_decode($request->getContent(), 1));
519
520
        // Find record && apply $ref converter
521
        $record = $this->findRecord($id);
522
        $jsonDocument = $this->serialize($record);
523
524
        // Check/validate JSON Patch
525
        if (!$this->jsonPatchValidator->validate($jsonDocument, $request->getContent())) {
0 ignored issues
show
Bug introduced by
It seems like $request->getContent() targeting Symfony\Component\HttpFo...n\Request::getContent() can also be of type resource; however, Graviton\RestBundle\Serv...chValidator::validate() does only seem to accept string, maybe add an additional type check?

This check looks at variables that are passed out again to other methods.

If the outgoing method call has stricter type requirements than the method itself, an issue is raised.

An additional type check may prevent trouble.

Loading history...
526
            throw new InvalidJsonPatchException($this->jsonPatchValidator->getException()->getMessage());
527
        }
528
529
        try {
530
            // Apply JSON patches
531
            $patch = new Patch($jsonDocument, $request->getContent());
0 ignored issues
show
Bug introduced by
It seems like $request->getContent() targeting Symfony\Component\HttpFo...n\Request::getContent() can also be of type resource; however, Rs\Json\Patch::__construct() does only seem to accept string, maybe add an additional type check?

This check looks at variables that are passed out again to other methods.

If the outgoing method call has stricter type requirements than the method itself, an issue is raised.

An additional type check may prevent trouble.

Loading history...
532
            $patchedDocument = $patch->apply();
533
        } catch (InvalidPatchDocumentJsonException $e) {
534
            throw new InvalidJsonPatchException($e->getMessage());
535
        } catch (InvalidTargetDocumentJsonException $e) {
536
            throw new InvalidJsonPatchException($e->getMessage());
537
        } catch (InvalidOperationException $e) {
538
            throw new InvalidJsonPatchException($e->getMessage());
539
        } catch (FailedTestException $e) {
540
            throw new InvalidJsonPatchException($e->getMessage());
541
        }
542
543
        // Validate result object
544
        $model = $this->getModel();
545
        $record = $this->formValidator->checkForm(
546
            $this->formValidator->getForm($request, $model),
547
            $model,
548
            $this->formDataMapper,
549
            $patchedDocument
550
        );
551
552
        // Update object
553
        $this->getModel()->updateRecord($id, $record);
554
555
        // Set status code
556
        $response->setStatusCode(Response::HTTP_OK);
557
558
        // Set Content-Location header
559
        $response->headers->set(
560
            'Content-Location',
561
            $this->getRouter()->generate($this->getRouteName($request), array('id' => $record->getId()))
562
        );
563
564
        return $response;
565
    }
566
567
    /**
568
     * Deletes a record
569
     *
570
     * @param Number $id ID of record
571
     *
572
     * @return Response $response Result of the action
573 1
     */
574
    public function deleteAction($id)
575 1
    {
576
        $response = $this->getResponse();
577
578 1
        // does this record exist?
579
        $this->findRecord($id);
580 1
581 1
        $this->getModel()->deleteRecord($id);
582
        $response->setStatusCode(Response::HTTP_NO_CONTENT);
583 1
584
        return $response;
585
    }
586
587
    /**
588
     * Return OPTIONS results.
589
     *
590
     * @param Request $request Current http request
591
     *
592
     * @throws SerializationException
593
     * @return \Symfony\Component\HttpFoundation\Response $response Result of the action
594
     */
595
    public function optionsAction(Request $request)
596
    {
597
        list($app, $module, , $modelName) = explode('.', $request->attributes->get('_route'));
598
599
        $response = $this->response;
600
        $response->setStatusCode(Response::HTTP_OK);
601
602
        // enabled methods for CorsListener
603
        $corsMethods = 'GET, POST, PUT, PATCH, DELETE, OPTIONS';
604
        try {
605
            $router = $this->getRouter();
606
            // if post route is available we assume everything is readable
607
            $router->generate(implode('.', array($app, $module, 'rest', $modelName, 'post')));
608
        } catch (RouteNotFoundException $exception) {
609
            // only allow read methods
610
            $corsMethods = 'GET, OPTIONS';
611
        }
612
        $request->attributes->set('corsMethods', $corsMethods);
613
614
        return $response;
615
    }
616
617
618
    /**
619
     * Return schema GET results.
620
     *
621
     * @param Request $request Current http request
622
     * @param string  $id      ID of record
623
     *
624
     * @throws SerializationException
625
     * @return \Symfony\Component\HttpFoundation\Response $response Result of the action
626
     */
627
    public function schemaAction(Request $request, $id = null)
628
    {
629
        $request->attributes->set('schemaRequest', true);
630
631
        list($app, $module, , $modelName, $schemaType) = explode('.', $request->attributes->get('_route'));
632
633
        $response = $this->response;
634
        $response->setStatusCode(Response::HTTP_OK);
635
        $response->setPublic();
636
637
        if (!$id && $schemaType != 'canonicalIdSchema') {
0 ignored issues
show
Bug Best Practice introduced by
The expression $id of type string|null is loosely compared to false; this is ambiguous if the string can be empty. You might want to explicitly use === null instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For string values, the empty string '' is a special case, in particular the following results might be unexpected:

''   == false // true
''   == null  // true
'ab' == false // false
'ab' == null  // false

// It is often better to use strict comparison
'' === false // false
'' === null  // false
Loading history...
638
            $schema = $this->schemaUtils->getCollectionSchema($modelName, $this->getModel());
639
        } else {
640
            $schema = $this->schemaUtils->getModelSchema($modelName, $this->getModel());
641
        }
642
643
        // enabled methods for CorsListener
644
        $corsMethods = 'GET, POST, PUT, PATCH, DELETE, OPTIONS';
645
        try {
646
            $router = $this->getRouter();
647
            // if post route is available we assume everything is readable
648
            $router->generate(implode('.', array($app, $module, 'rest', $modelName, 'post')));
649
        } catch (RouteNotFoundException $exception) {
650
            // only allow read methods
651
            $corsMethods = 'GET, OPTIONS';
652
        }
653
        $request->attributes->set('corsMethods', $corsMethods);
654
655
        return $this->render(
656
            'GravitonRestBundle:Main:index.json.twig',
657
            ['response' => $this->serialize($schema)],
658
            $response
659
        );
660
    }
661
662
    /**
663
     * Get the validator
664
     *
665
     * @return ValidatorInterface
666
     */
667
    public function getValidator()
668
    {
669
        return $this->validator;
670
    }
671
672
    /**
673
     * Renders a view.
674
     *
675
     * @param string   $view       The view name
676
     * @param array    $parameters An array of parameters to pass to the view
677
     * @param Response $response   A response instance
678
     *
679
     * @return Response A Response instance
680 2
     */
681
    public function render($view, array $parameters = array(), Response $response = null)
682 2
    {
683
        return $this->templating->renderResponse($view, $parameters, $response);
684
    }
685
686
    /**
687
     * @param Request $request request
688
     * @return string
689
     */
690
    private function getRouteName(Request $request)
691
    {
692
        $routeName = $request->get('_route');
693
        $routeParts = explode('.', $routeName);
694
        $routeType = end($routeParts);
695
696
        if ($routeType == 'post') {
697
            $routeName = substr($routeName, 0, -4) . 'get';
698
        }
699
700
        return $routeName;
701
    }
702
703
    /**
704
     * Get the user who's logged in
705
     *
706
     * @return Mixed | false
707 1
     */
708
    public function getUser()
709 1
    {
710 1
        if ($token = $this->tokenStorage->getToken()) {
711
            return $token->getUser()->getUser();
712
        }
713
714
        return false;
715
    }
716
}
717