Test Failed
Push — master ( 9e5b01...b40a06 )
by Daniel
05:29
created

CollectionModifier::process()   F

Complexity

Conditions 15
Paths 292

Size

Total Lines 86
Code Lines 57

Duplication

Lines 0
Ratio 0 %

Importance

Changes 2
Bugs 1 Features 0
Metric Value
eloc 57
c 2
b 1
f 0
dl 0
loc 86
rs 3.9333
cc 15
nc 292
nop 3

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
3
namespace Silverback\ApiComponentBundle\DataModifier;
4
5
use ApiPlatform\Core\Api\OperationType;
6
use ApiPlatform\Core\Bridge\Doctrine\Orm\Paginator;
7
use ApiPlatform\Core\DataProvider\ContextAwareCollectionDataProviderInterface;
8
use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface;
9
use ApiPlatform\Core\PathResolver\OperationPathResolverInterface;
10
use ApiPlatform\Core\Util\RequestParser;
11
use Psr\Container\ContainerInterface;
12
use Silverback\ApiComponentBundle\Entity\Component\Collection\Collection;
13
use Symfony\Component\HttpFoundation\Request;
14
use Symfony\Component\HttpFoundation\RequestStack;
15
use Symfony\Component\Serializer\Normalizer\NormalizerInterface;
16
17
class CollectionModifier extends AbstractModifier
18
{
19
    private $resourceMetadataFactory;
20
    private $operationPathResolver;
21
    private $itemNormalizer;
22
    private $requestStack;
23
24
    public function __construct(
25
        ContainerInterface $container,
26
        ResourceMetadataFactoryInterface $resourceMetadataFactory,
27
        OperationPathResolverInterface $operationPathResolver,
28
        NormalizerInterface $itemNormalizer,
29
        RequestStack $requestStack
30
    ) {
31
        parent::__construct($container);
32
        $this->resourceMetadataFactory = $resourceMetadataFactory;
33
        $this->operationPathResolver = $operationPathResolver;
34
        $this->itemNormalizer = $itemNormalizer;
35
        $this->requestStack = $requestStack;
36
    }
37
38
    /**
39
     * @param Collection $collectionEntity
40
     * @param array $context
41
     * @param null|string $format
42
     * @return object|void
43
     */
44
    public function process($collectionEntity, array $context = array(), ?string $format = null)
45
    {
46
        $resourceMetadata = $this->resourceMetadataFactory->create($collectionEntity->getResource());
47
        $requestUri = null;
48
49
        $collectionOperations = $resourceMetadata->getCollectionOperations();
50
        if ($collectionOperations && ($shortName = $resourceMetadata->getShortName())) {
51
            $collectionOperations = array_change_key_case($collectionOperations, CASE_LOWER);
52
            $baseRoute = trim(trim($resourceMetadata->getAttribute('route_prefix', '')), '/');
53
            $methods = ['post', 'get'];
54
            foreach ($methods as $method) {
55
                if (array_key_exists($method, $collectionOperations)) {
56
                    $path = $baseRoute . $this->operationPathResolver->resolveOperationPath(
57
                            $shortName,
58
                            $collectionOperations[$method],
59
                            OperationType::COLLECTION,
60
                            $method
0 ignored issues
show
Unused Code introduced by
The call to ApiPlatform\Core\PathRes...:resolveOperationPath() has too many arguments starting with $method. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

60
                    $path = $baseRoute . $this->operationPathResolver->/** @scrutinizer ignore-call */ resolveOperationPath(

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress. Please note the @ignore annotation hint above.

Loading history...
61
                    );
62
                    $finalPath = preg_replace('/{_format}$/', $format, $path);
63
                    $collectionEntity->addCollectionRoute(
64
                        $method,
65
                        $finalPath
66
                    );
67
                    if ($method === 'get') {
68
                        $requestUri = $finalPath;
69
                    }
70
                }
71
            }
72
        }
73
74
        /** @var ContextAwareCollectionDataProviderInterface $dataProvider */
75
        $dataProvider = $this->container->get(ContextAwareCollectionDataProviderInterface::class);
76
        $isPaginated = (bool) $collectionEntity->getPerPage();
77
78
        if ($request = $this->requestStack->getCurrentRequest()) {
79
            $resetQueryString = false;
80
            // Set the default querystring for the RequestParser class if we have not passed one in the request
81
            if ($defaultQueryString = $collectionEntity->getDefaultQueryString()) {
82
                $qs = $request->server->get('QUERY_STRING');
83
                if (!$qs) {
84
                    $resetQueryString = true;
85
                    $request->server->set('QUERY_STRING', $defaultQueryString);
86
                }
87
            }
88
89
            if (null === $filters = $request->attributes->get('_api_filters')) {
90
                $queryString = RequestParser::getQueryString($request);
91
                $filters = $queryString ? RequestParser::parseRequestParams($queryString) : null;
92
            }
93
94
            if ($resetQueryString) {
95
                $request->server->set('QUERY_STRING', '');
96
            }
97
98
            $dataProviderContext = null === $filters ? [] : ['filters' => $filters];
99
            if ($isPaginated) {
100
                $dataProviderContext['filters'] = $dataProviderContext['filters'] ?? [];
101
                $dataProviderContext['filters'] = array_merge($dataProviderContext['filters'], [
102
                    'pagination' => true,
103
                    'itemsPerPage' => $collectionEntity->getPerPage(),
104
                    '_page' => 1
105
                ]);
106
                $request->attributes->set('_api_pagination', [
107
                    'pagination' => 'true',
108
                    'itemsPerPage' => $collectionEntity->getPerPage()
109
                ]);
110
            }
111
        }
112
113
        /** @var Paginator $collection */
114
        $collection = $dataProvider->getCollection($collectionEntity->getResource(), Request::METHOD_GET, $dataProviderContext);
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $dataProviderContext does not seem to be defined for all execution paths leading up to this point.
Loading history...
115
116
        $forcedContext = [
117
            'resource_class' => $collectionEntity->getResource(),
118
            'request_uri' => $requestUri,
119
            'jsonld_has_context' => false,
120
            'api_sub_level' => null
121
        ];
122
        $mergedContext = array_merge($context, $forcedContext);
123
        $normalizedCollection = $this->itemNormalizer->normalize(
124
            $collection,
125
            $format,
126
            $mergedContext
127
        );
128
        if (\is_array($normalizedCollection)) {
129
            $collectionEntity->setCollection($normalizedCollection);
130
        }
131
    }
132
133
    public function supportsData($data): bool
134
    {
135
        return $data instanceof Collection;
136
    }
137
138
    public static function getSubscribedServices(): array
139
    {
140
        return [
141
            '?' . ContextAwareCollectionDataProviderInterface::class,
142
            RequestStack::class
143
        ];
144
    }
145
}
146