Completed
Push — standalone ( 6b9ae2...5a4b99 )
by Philip
03:07
created

RestResourceController::getPropertyAccessor()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 0
Metric Value
dl 0
loc 4
ccs 0
cts 2
cp 0
rs 10
c 0
b 0
f 0
cc 1
eloc 2
nc 1
nop 0
crap 2
1
<?php
2
3
namespace Dontdrinkandroot\RestBundle\Controller;
4
5
use Doctrine\Common\Util\Inflector;
6
use Doctrine\ORM\EntityManagerInterface;
7
use Doctrine\ORM\Tools\Pagination\Paginator;
8
use Dontdrinkandroot\RestBundle\Metadata\Annotation\Right;
9
use Dontdrinkandroot\RestBundle\Metadata\ClassMetadata;
10
use Dontdrinkandroot\RestBundle\Metadata\PropertyMetadata;
11
use Dontdrinkandroot\RestBundle\Service\Normalizer;
12
use Dontdrinkandroot\RestBundle\Service\RestRequestParser;
13
use Dontdrinkandroot\Service\CrudServiceInterface;
14
use Metadata\MetadataFactoryInterface;
15
use Symfony\Component\DependencyInjection\ContainerAwareInterface;
16
use Symfony\Component\DependencyInjection\ContainerAwareTrait;
17
use Symfony\Component\HttpFoundation\JsonResponse;
18
use Symfony\Component\HttpFoundation\Request;
19
use Symfony\Component\HttpFoundation\RequestStack;
20
use Symfony\Component\HttpFoundation\Response;
21
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
22
use Symfony\Component\PropertyAccess\PropertyAccessorInterface;
23
use Symfony\Component\Security\Core\Authorization\AuthorizationCheckerInterface;
24
use Symfony\Component\Security\Core\Exception\AccessDeniedException;
25
use Symfony\Component\Validator\ConstraintViolationInterface;
26
use Symfony\Component\Validator\ConstraintViolationListInterface;
27
use Symfony\Component\Validator\Validator\ValidatorInterface;
28
29
class RestResourceController implements ContainerAwareInterface, RestResourceControllerInterface
30
{
31
    use ContainerAwareTrait;
32
33
    /**
34
     * {@inheritdoc}
35
     */
36 8
    public function listAction(Request $request)
37
    {
38 8
        $page = $request->query->get('page', 1);
39 8
        $perPage = $request->query->get('perPage', 50);
40
41 8
        $this->assertListGranted();
42
43 6
        $listResult = $this->listEntities($page, $perPage);
44
45 6
        $response = new JsonResponse();
46
47 6
        if ($listResult instanceof Paginator) {
48 6
            $entities = $listResult->getIterator()->getArrayCopy();
0 ignored issues
show
Bug introduced by
It seems like you code against a concrete implementation and not the interface Traversable as the method getArrayCopy() does only exist in the following implementations of said interface: ArrayIterator, ArrayObject, DoctrineTest\Instantiato...tAsset\ArrayObjectAsset, DoctrineTest\Instantiato...lizableArrayObjectAsset, DoctrineTest\Instantiato...ceptionArrayObjectAsset, DoctrineTest\Instantiato...sset\WakeUpNoticesAsset, Issue523, RecursiveArrayIterator, Symfony\Component\Finder...rator\InnerNameIterator, Symfony\Component\Finder...rator\InnerSizeIterator, Symfony\Component\Finder...rator\InnerTypeIterator, Symfony\Component\Finder...or\MockFileListIterator, Symfony\Component\Proper...ss\PropertyPathIterator.

Let’s take a look at an example:

interface User
{
    /** @return string */
    public function getPassword();
}

class MyUser implements User
{
    public function getPassword()
    {
        // return something
    }

    public function getDisplayName()
    {
        // return some name.
    }
}

class AuthSystem
{
    public function authenticate(User $user)
    {
        $this->logger->info(sprintf('Authenticating %s.', $user->getDisplayName()));
        // do something.
    }
}

In the above example, the authenticate() method works fine as long as you just pass instances of MyUser. However, if you now also want to pass a different implementation of User which does not have a getDisplayName() method, the code will break.

Available Fixes

  1. Change the type-hint for the parameter:

    class AuthSystem
    {
        public function authenticate(MyUser $user) { /* ... */ }
    }
    
  2. Add an additional type-check:

    class AuthSystem
    {
        public function authenticate(User $user)
        {
            if ($user instanceof MyUser) {
                $this->logger->info(/** ... */);
            }
    
            // or alternatively
            if ( ! $user instanceof MyUser) {
                throw new \LogicException(
                    '$user must be an instance of MyUser, '
                   .'other instances are not supported.'
                );
            }
    
        }
    }
    
Note: PHP Analyzer uses reverse abstract interpretation to narrow down the types inside the if block in such a case.
  1. Add the method to the interface:

    interface User
    {
        /** @return string */
        public function getPassword();
    
        /** @return string */
        public function getDisplayName();
    }
    
Loading history...
49 6
            $total = $listResult->count();
50 6
            $this->addPaginationHeaders($response, $page, $perPage, $total);
51
        } else {
52
            $entities = $listResult;
53
        }
54
55 6
        $content = $this->getNormalizer()->normalize($entities, $this->parseIncludes($request));
56
57 6
        $response->setData($content);
58
59 6
        return $response;
60
    }
61
62
    /**
63
     * {@inheritdoc}
64
     */
65 2
    public function postAction(Request $request)
66
    {
67 2
        $this->assertPostGranted();
68
        $entity = $this->getRequestParser()->parseEntity($request, $this->getEntityClass());
69
        $entity = $this->postProcessPostedEntity($entity);
70
71
        $errors = $this->getValidator()->validate($entity);
72
        if ($errors->count() > 0) {
73
            return new JsonResponse($this->parseConstraintViolations($errors), Response::HTTP_BAD_REQUEST);
74
        }
75
76
        $entity = $this->createEntity($entity);
77
78
        $content = $this->getNormalizer()->normalize($entity);
79
80
        return new JsonResponse($content, Response::HTTP_CREATED);
81
    }
82
83
    /**
84
     * {@inheritdoc}
85
     */
86 10
    public function getAction(Request $request, $id)
87
    {
88 10
        $entity = $this->fetchEntity($id);
89 10
        $this->assertGetGranted($entity);
90
91 8
        $content = $this->getNormalizer()->normalize($entity, $this->parseIncludes($request, ['details']));
92
93 8
        return new JsonResponse($content);
94
    }
95
96
    /**
97
     * {@inheritdoc}
98
     */
99 6
    public function putAction(Request $request, $id)
100
    {
101 6
        $entity = $this->fetchEntity($id);
102 6
        $this->assertPutGranted($entity);
103 2
        $entity = $this->getRequestParser()->parseEntity($request, $this->getEntityClass(), $entity);
104 2
        $entity = $this->postProcessPuttedEntity($entity);
105
106 2
        $errors = $this->getValidator()->validate($entity);
107 2
        if ($errors->count() > 0) {
108
            return new JsonResponse($this->parseConstraintViolations($errors), Response::HTTP_BAD_REQUEST);
109
        }
110
111 2
        $entity = $this->updateEntity($entity);
112
113 2
        $content = $this->getNormalizer()->normalize($entity);
114
115 2
        return new JsonResponse($content);
116
    }
117
118
    /**
119
     * {@inheritdoc}
120
     */
121 2
    public function deleteAction(Request $request, $id)
122
    {
123 2
        $entity = $this->fetchEntity($id);
124 2
        $this->assertDeleteGranted($entity);
125
        $this->getService()->remove($entity);
126
127
        return new JsonResponse(null, Response::HTTP_NO_CONTENT);
128
    }
129
130
    /**
131
     * {@inheritdoc}
132
     */
133 6
    public function listSubresourceAction(Request $request, $id)
134
    {
135 6
        $page = $request->query->get('page', 1);
136 6
        $perPage = $request->query->get('perPage', 50);
137
138 6
        $subresource = $this->getSubresource();
139 6
        $entity = $this->fetchEntity($id);
140 6
        $this->assertSubresourceListGranted($entity, $subresource);
141
142 6
        $listResult = $this->listSubresource($entity, $subresource, $page, $perPage);
143
144 6
        $response = new JsonResponse();
145
146 6
        if ($listResult instanceof Paginator) {
147 6
            $entities = $listResult->getIterator()->getArrayCopy();
0 ignored issues
show
Bug introduced by
It seems like you code against a concrete implementation and not the interface Traversable as the method getArrayCopy() does only exist in the following implementations of said interface: ArrayIterator, ArrayObject, DoctrineTest\Instantiato...tAsset\ArrayObjectAsset, DoctrineTest\Instantiato...lizableArrayObjectAsset, DoctrineTest\Instantiato...ceptionArrayObjectAsset, DoctrineTest\Instantiato...sset\WakeUpNoticesAsset, Issue523, RecursiveArrayIterator, Symfony\Component\Finder...rator\InnerNameIterator, Symfony\Component\Finder...rator\InnerSizeIterator, Symfony\Component\Finder...rator\InnerTypeIterator, Symfony\Component\Finder...or\MockFileListIterator, Symfony\Component\Proper...ss\PropertyPathIterator.

Let’s take a look at an example:

interface User
{
    /** @return string */
    public function getPassword();
}

class MyUser implements User
{
    public function getPassword()
    {
        // return something
    }

    public function getDisplayName()
    {
        // return some name.
    }
}

class AuthSystem
{
    public function authenticate(User $user)
    {
        $this->logger->info(sprintf('Authenticating %s.', $user->getDisplayName()));
        // do something.
    }
}

In the above example, the authenticate() method works fine as long as you just pass instances of MyUser. However, if you now also want to pass a different implementation of User which does not have a getDisplayName() method, the code will break.

Available Fixes

  1. Change the type-hint for the parameter:

    class AuthSystem
    {
        public function authenticate(MyUser $user) { /* ... */ }
    }
    
  2. Add an additional type-check:

    class AuthSystem
    {
        public function authenticate(User $user)
        {
            if ($user instanceof MyUser) {
                $this->logger->info(/** ... */);
            }
    
            // or alternatively
            if ( ! $user instanceof MyUser) {
                throw new \LogicException(
                    '$user must be an instance of MyUser, '
                   .'other instances are not supported.'
                );
            }
    
        }
    }
    
Note: PHP Analyzer uses reverse abstract interpretation to narrow down the types inside the if block in such a case.
  1. Add the method to the interface:

    interface User
    {
        /** @return string */
        public function getPassword();
    
        /** @return string */
        public function getDisplayName();
    }
    
Loading history...
148 6
            $total = $listResult->count();
149 6
            $this->addPaginationHeaders($response, $page, $perPage, $total);
150
        } else {
151
            $entities = $listResult;
152
        }
153
154 6
        $content = $this->getNormalizer()->normalize($entities, $this->parseIncludes($request));
155
156 6
        $response->setData($content);
157
158 6
        return $response;
159
    }
160
161
    /**
162
     * {@inheritdoc}
163
     */
164 4
    public function postSubresourceAction(Request $request, $id)
165
    {
166 4
        $subresource = $this->getSubresource();
167 4
        $parent = $this->fetchEntity($id);
168 4
        $this->assertSubresourcePostGranted($parent, $subresource);
169 2
        $entity = $this->getRequestParser()->parseEntity(
170
            $request,
171 2
            $this->getSubResourceEntityClass($subresource)
172
        );
173 2
        $entity = $this->postProcessSubResourcePostedEntity($subresource, $entity, $parent);
174
175 2
        $errors = $this->getValidator()->validate($entity);
176
177 2
        if ($errors->count() > 0) {
178
            return new JsonResponse($this->parseConstraintViolations($errors), Response::HTTP_BAD_REQUEST);
179
        }
180
181 2
        $entity = $this->createSubResource($parent, $subresource, $entity);
182
183 2
        $content = $this->getNormalizer()->normalize($entity, ['details']);
184
185 2
        return new JsonResponse($content, Response::HTTP_CREATED);
186
    }
187
188
    /**
189
     * {@inheritdoc}
190
     */
191 2
    public function putSubresourceAction(Request $request, $id, $subId)
192
    {
193 2
        $subresource = $this->getSubresource();
194 2
        $parent = $this->fetchEntity($id);
195 2
        $this->assertSubresourcePutGranted($parent, $subresource);
196 2
        $this->getService()->addToCollection($parent, $subresource, $subId);
197
198 2
        return new JsonResponse(null, Response::HTTP_NO_CONTENT);
199
    }
200
201
    /**
202
     * {@inheritdoc}
203
     */
204 2
    public function deleteSubresourceAction(Request $request, $id, $subId)
205
    {
206 2
        $subresource = $this->getSubresource();
207 2
        $parent = $this->fetchEntity($id);
208 2
        $this->assertSubresourceDeleteGranted($parent, $subresource);
209 2
        $this->getService()->removeFromCollection($parent, $subresource, $subId);
210
211 2
        return new JsonResponse(null, Response::HTTP_NO_CONTENT);
212
    }
213
214
    /**
215
     * @return CrudServiceInterface
216
     */
217 34
    protected function getService(): CrudServiceInterface
218
    {
219 34
        $serviceId = $this->getServiceId();
220 34
        if (null === $serviceId) {
221 32
            $entityClass = $this->getEntityClass();
222 32
            if (null === $entityClass) {
223
                throw new \RuntimeException('No service or entity class given');
224
            }
225
            /** @var EntityManagerInterface $entityManager */
226 32
            $entityManager = $this->container->get('doctrine.orm.entity_manager');
227 32
            $repository = $entityManager->getRepository($entityClass);
228 32
            if (!$repository instanceof CrudServiceInterface) {
229
                throw new \RuntimeException(
230
                    'Your Entity Repository needs to be an instance of ' . CrudServiceInterface::class . '.'
231
                );
232
            }
233
234 32
            return $repository;
235
        } else {
236
            /** @var CrudServiceInterface $service */
237 2
            $service = $this->container->get($serviceId);
238
239 2
            return $service;
240
        }
241
    }
242
243
    /**
244
     * @param object $entity
245
     *
246
     * @return object
247
     */
248
    protected function postProcessPostedEntity($entity)
249
    {
250
        return $entity;
251
    }
252
253
    /**
254
     * @param object $entity
255
     *
256
     * @return object
257
     */
258 2
    protected function postProcessPuttedEntity($entity)
259
    {
260 2
        return $entity;
261
    }
262
263
    /**
264
     * @param string $subresource
265
     * @param object $parent
266
     * @param object $entity
267
     *
268
     * @return object
269
     */
270 2
    protected function postProcessSubResourcePostedEntity($subresource, $entity, $parent)
2 ignored issues
show
Unused Code introduced by
The parameter $subresource is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
Unused Code introduced by
The parameter $parent is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
271
    {
272 2
        return $entity;
273
    }
274
275 28
    protected function fetchEntity($id)
276
    {
277 28
        $entity = $this->getService()->find($id);
278 28
        if (null === $entity) {
279
            throw new NotFoundHttpException();
280
        }
281
282 28
        return $entity;
283
    }
284
285
    /**
286
     * @param int $page
287
     * @param int $perPage
288
     *
289
     * @return Paginator|array
290
     */
291 6
    protected function listEntities(int $page = 1, int $perPage = 50)
292
    {
293 6
        return $this->getService()->findAllPaginated($page, $perPage);
294
    }
295
296
    protected function createEntity($entity)
297
    {
298
        return $this->getService()->create($entity);
299
    }
300
301 2
    protected function updateEntity($entity)
302
    {
303 2
        return $this->getService()->update($entity);
304
    }
305
306
    /**
307
     * @param object $entity
308
     * @param string $property
309
     * @param int    $page
310
     * @param int    $perPage
311
     *
312
     * @return Paginator|array
313
     */
314 6
    protected function listSubresource($entity, string $property, int $page = 1, int $perPage = 50)
315
    {
316 6
        return $this->getService()->findAssociationPaginated($entity, $property, $page, $perPage);
317
    }
318
319 38
    protected function getEntityClass()
320
    {
321 38
        return $this->getCurrentRequest()->attributes->get('_entityClass');
322
    }
323
324
    protected function getShortName()
325
    {
326
        return Inflector::tableize($this->getClassMetadata()->reflection->getShortName());
327
    }
328
329 34
    protected function getServiceId()
330
    {
331 34
        return $this->getCurrentRequest()->attributes->get('_service');
332
    }
333
334 38
    protected function getCurrentRequest()
335
    {
336 38
        return $this->getRequestStack()->getCurrentRequest();
337
    }
338
339 8
    protected function assertListGranted()
340
    {
341 8
        $classMetadata = $this->getClassMetadata();
342 8
        $right = $classMetadata->getListRight();
343 8
        if (null === $right) {
344 4
            return;
345
        }
346
347 4
        $this->denyAccessUnlessGranted($right->attributes);
348 2
    }
349
350 2
    protected function assertPostGranted()
351
    {
352 2
        $classMetadata = $this->getClassMetadata();
353 2
        $right = $classMetadata->getPostRight();
354 2
        if (null === $right) {
355 2
            throw new AccessDeniedException();
356
        }
357
358
        $this->denyAccessUnlessGranted($right->attributes);
359
    }
360
361 10
    protected function assertGetGranted($entity)
362
    {
363 10
        $classMetadata = $this->getClassMetadata();
364 10
        $right = $classMetadata->getGetRight();
365 10
        if (null === $right) {
366 4
            return;
367
        }
368
369 6
        $this->assertRightGranted($entity, $right);
370 4
    }
371
372 6
    protected function assertPutGranted($entity)
373
    {
374 6
        $classMetadata = $this->getClassMetadata();
375 6
        $right = $classMetadata->getPutRight();
376 6
        if (null === $right) {
377 2
            throw new AccessDeniedException();
378
        }
379
380 4
        $this->assertRightGranted($entity, $right);
381 2
    }
382
383 2
    protected function assertDeleteGranted($entity)
384
    {
385 2
        $classMetadata = $this->getClassMetadata();
386 2
        $right = $classMetadata->getDeleteRight();
387 2
        if (null === $right) {
388 2
            throw new AccessDeniedException();
389
        }
390
391
        $this->assertRightGranted($entity, $right);
392
    }
393
394 6
    protected function assertSubresourceListGranted($entity, $subresource)
395
    {
396 6
        $classMetadata = $this->getClassMetadata();
397
        /** @var PropertyMetadata $propertyMetadata */
398 6
        $propertyMetadata = $classMetadata->propertyMetadata[$subresource];
399 6
        $right = $propertyMetadata->getSubResourceListRight();
400 6
        if (null === $right) {
401 6
            return;
402
        }
403
404
        $this->assertRightGranted($entity, $right);
405
    }
406
407 4
    protected function assertSubresourcePostGranted($entity, $subresource)
408
    {
409 4
        $classMetadata = $this->getClassMetadata();
410
        /** @var PropertyMetadata $propertyMetadata */
411 4
        $propertyMetadata = $classMetadata->propertyMetadata[$subresource];
412 4
        $right = $propertyMetadata->getSubResourcePostRight();
413 4
        if (null === $right) {
414
            throw new AccessDeniedException();
415
        }
416
417 4
        $this->assertRightGranted($entity, $right);
418 2
    }
419
420 2
    protected function assertSubresourcePutGranted($entity, $subresource)
421
    {
422 2
        $classMetadata = $this->getClassMetadata();
423
        /** @var PropertyMetadata $propertyMetadata */
424 2
        $propertyMetadata = $classMetadata->propertyMetadata[$subresource];
425 2
        $right = $propertyMetadata->getSubResourcePutRight();
426 2
        if (null === $right) {
427
            throw new AccessDeniedException();
428
        }
429
430 2
        $this->assertRightGranted($entity, $right);
431 2
    }
432
433 2
    protected function assertSubresourceDeleteGranted($entity, $subresource)
434
    {
435 2
        $classMetadata = $this->getClassMetadata();
436
        /** @var PropertyMetadata $propertyMetadata */
437 2
        $propertyMetadata = $classMetadata->propertyMetadata[$subresource];
438 2
        $right = $propertyMetadata->getSubResourceDeleteRight();
439 2
        if (null === $right) {
440
            throw new AccessDeniedException();
441
        }
442
443 2
        $this->assertRightGranted($entity, $right);
444 2
    }
445
446
    /**
447
     * @return ClassMetadata
448
     */
449 38
    protected function getClassMetadata()
450
    {
451 38
        $metaDataFactory = $this->getMetadataFactory();
452
        /** @var ClassMetadata $classMetaData */
453 38
        $classMetaData = $metaDataFactory->getMetadataForClass($this->getEntityClass());
454
455 38
        return $classMetaData;
456
    }
457
458 2
    protected function getSubResourceEntityClass($subresource)
459
    {
460
        /** @var PropertyMetadata $propertyMetadata */
461 2
        $propertyMetadata = $this->getClassMetadata()->propertyMetadata[$subresource];
462
463 2
        return $propertyMetadata->getTargetClass();
464
    }
465
466
    protected function resolveSubject($entity, $propertyPath)
467
    {
468
        if ('this' === $propertyPath) {
469
            return $entity;
470
        }
471
        $propertyAccessor = $this->getPropertyAccessor();
472
473
        return $propertyAccessor->getValue($entity, $propertyPath);
474
    }
475
476
    /**
477
     * @param object $entity
478
     * @param Right  $right
479
     */
480 18
    protected function assertRightGranted($entity, Right $right)
481
    {
482 18
        $propertyPath = $right->propertyPath;
483 18
        if (null === $propertyPath) {
484 18
            $this->denyAccessUnlessGranted($right->attributes);
485
        } else {
486
            $subject = $this->resolveSubject($entity, $propertyPath);
487
            $this->denyAccessUnlessGranted($right->attributes, $subject);
488
        }
489 12
    }
490
491
    /**
492
     * @param object $parent
493
     * @param string $subresource
494
     * @param object $entity
495
     *
496
     * @return
497
     */
498 2
    protected function createSubResource($parent, $subresource, $entity)
499
    {
500 2
        return $this->getService()->createAssociation($parent, $subresource, $entity);
501
    }
502
503
    /**
504
     * @return string|null
505
     */
506 10
    protected function getSubresource()
507
    {
508 10
        return $this->getCurrentRequest()->attributes->get('_subresource');
509
    }
510
511 20
    protected function parseIncludes(Request $request, array $defaultIncludes = [])
512
    {
513 20
        $includeString = $request->query->get('include');
514 20
        if (empty($includeString)) {
515 18
            return $defaultIncludes;
516
        }
517
518 2
        return explode(',', $includeString);
519
    }
520
521
    private function parseConstraintViolations(ConstraintViolationListInterface $errors)
522
    {
523
        $data = [];
524
        /** @var ConstraintViolationInterface $error */
525
        foreach ($errors as $error) {
526
            $data[] = [
527
                'propertyPath' => $error->getPropertyPath(),
528
                'message'      => $error->getMessage(),
529
                'value'        => $error->getInvalidValue()
530
            ];
531
        }
532
533
        return $data;
534
    }
535
536 12
    private function addPaginationHeaders(Response $response, int $page, int $perPage, int $total)
537
    {
538 12
        $response->headers->add(
539
            [
540 12
                'x-pagination-current-page' => $page,
541 12
                'x-pagination-per-page'     => $perPage,
542 12
                'x-pagination-total'        => $total,
543 12
                'x-pagination-total-pages'  => (int)(($total - 1) / $perPage + 1)
544
            ]
545
        );
546 12
    }
547
548 22
    protected function denyAccessUnlessGranted($attributes, $object = null, $message = 'Access Denied.')
549
    {
550 22
        if (!$this->getAuthorizationChecker()->isGranted($attributes, $object)) {
551 8
            throw new AccessDeniedException($message);
552
        }
553 14
    }
554
555
    /**
556
     * @return Normalizer
557
     */
558 24
    protected function getNormalizer()
559
    {
560 24
        return $this->container->get('ddr_rest.normalizer');
561
    }
562
563
    /**
564
     * @return ValidatorInterface
565
     */
566 4
    protected function getValidator()
567
    {
568 4
        return $this->container->get('validator');
569
    }
570
571
    /**
572
     * @return RestRequestParser
573
     */
574 4
    protected function getRequestParser()
575
    {
576 4
        return $this->container->get('ddr.rest.parser.request');
577
    }
578
579
    /**
580
     * @return RequestStack
581
     */
582 38
    protected function getRequestStack()
583
    {
584 38
        return $this->container->get('request_stack');
585
    }
586
587
    /**
588
     * @return MetadataFactoryInterface
589
     */
590 38
    protected function getMetadataFactory()
591
    {
592 38
        return $this->container->get('ddr_rest.metadata.factory');
593
    }
594
595
    /**
596
     * @return PropertyAccessorInterface
597
     */
598
    protected function getPropertyAccessor()
599
    {
600
        return $this->container->get('property_accessor');
601
    }
602
603
    /**
604
     * @return AuthorizationCheckerInterface
605
     */
606 22
    protected function getAuthorizationChecker()
607
    {
608 22
        return $this->container->get('security.authorization_checker');
609
    }
610
}
611