Completed
Branch master (fea354)
by
unknown
02:42
created

Factory::createParameters()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 21
Code Lines 18

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 10
CRAP Score 1

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 21
ccs 10
cts 10
cp 1
rs 9.3142
cc 1
eloc 18
nc 1
nop 8
crap 1

1 Method

Rating   Name   Duplication   Size   Complexity  
A Factory::createHeaderParameters() 0 4 1

How to fix   Many Parameters   

Many Parameters

Methods with many parameters are not only hard to understand, but their parameters also often become inconsistent when you need more, or different data.

There are several approaches to avoid long parameter lists:

1
<?php namespace Neomerx\JsonApi\Factories;
2
3
/**
4
 * Copyright 2015 [email protected] (www.neomerx.com)
5
 *
6
 * Licensed under the Apache License, Version 2.0 (the "License");
7
 * you may not use this file except in compliance with the License.
8
 * You may obtain a copy of the License at
9
 *
10
 * http://www.apache.org/licenses/LICENSE-2.0
11
 *
12
 * Unless required by applicable law or agreed to in writing, software
13
 * distributed under the License is distributed on an "AS IS" BASIS,
14
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
 * See the License for the specific language governing permissions and
16
 * limitations under the License.
17
 */
18
19
use \Closure;
20
use \Psr\Log\LoggerInterface;
21
use \Neomerx\JsonApi\Document\Link;
22
use \Neomerx\JsonApi\Document\Error;
23
use \Neomerx\JsonApi\Encoder\Encoder;
24
use \Neomerx\JsonApi\Schema\Container;
25
use \Neomerx\JsonApi\Document\Document;
26
use \Neomerx\JsonApi\Codec\CodecMatcher;
27
use \Neomerx\JsonApi\Encoder\Stack\Stack;
28
use \Neomerx\JsonApi\Encoder\Parser\Parser;
29
use \Neomerx\JsonApi\Schema\IdentitySchema;
30
use \Neomerx\JsonApi\Schema\ResourceObject;
31
use \Neomerx\JsonApi\Encoder\EncoderOptions;
32
use \Neomerx\JsonApi\Http\Headers\MediaType;
33
use \Neomerx\JsonApi\Encoder\Stack\StackFrame;
34
use \Neomerx\JsonApi\Http\Headers\AcceptHeader;
35
use \Neomerx\JsonApi\Schema\RelationshipObject;
36
use \Neomerx\JsonApi\Encoder\Parser\ParserReply;
37
use \Neomerx\JsonApi\Encoder\Parser\ParserManager;
38
use \Neomerx\JsonApi\Http\Headers\AcceptMediaType;
39
use \Neomerx\JsonApi\Http\Headers\HeaderParameters;
40
use \Neomerx\JsonApi\Encoder\Parser\ParserEmptyReply;
41
use \Neomerx\JsonApi\Contracts\Document\LinkInterface;
42
use \Neomerx\JsonApi\Encoder\Parameters\SortParameter;
43
use \Neomerx\JsonApi\Http\Headers\SupportedExtensions;
44
use \Neomerx\JsonApi\Http\Query\QueryParametersParser;
45
use \Neomerx\JsonApi\Encoder\Handlers\ReplyInterpreter;
46
use \Neomerx\JsonApi\Http\Query\RestrictiveQueryChecker;
47
use \Neomerx\JsonApi\Contracts\Schema\ContainerInterface;
48
use \Neomerx\JsonApi\Http\Headers\HeaderParametersParser;
49
use \Neomerx\JsonApi\Contracts\Document\DocumentInterface;
50
use \Neomerx\JsonApi\Contracts\Factories\FactoryInterface;
51
use \Neomerx\JsonApi\Contracts\Codec\CodecMatcherInterface;
52
use \Neomerx\JsonApi\Encoder\Parameters\EncodingParameters;
53
use \Neomerx\JsonApi\Encoder\Parameters\ParametersAnalyzer;
54
use \Neomerx\JsonApi\Http\Headers\RestrictiveHeadersChecker;
55
use \Neomerx\JsonApi\Schema\ResourceIdentifierSchemaAdapter;
56
use \Neomerx\JsonApi\Contracts\Http\Headers\HeaderInterface;
57
use \Neomerx\JsonApi\Contracts\Schema\SchemaProviderInterface;
58
use \Neomerx\JsonApi\Contracts\Http\Headers\MediaTypeInterface;
59
use \Neomerx\JsonApi\Schema\ResourceIdentifierContainerAdapter;
60
use \Neomerx\JsonApi\Contracts\Http\Headers\AcceptHeaderInterface;
61
use \Neomerx\JsonApi\Contracts\Encoder\Stack\StackReadOnlyInterface;
62
use \Neomerx\JsonApi\Contracts\Encoder\Parser\ParserManagerInterface;
63
use \Neomerx\JsonApi\Contracts\Encoder\Stack\StackFrameReadOnlyInterface;
64
use \Neomerx\JsonApi\Contracts\Encoder\Parameters\EncodingParametersInterface;
65
use \Neomerx\JsonApi\Contracts\Encoder\Parameters\ParametersAnalyzerInterface;
66
67
/**
68
 * @package Neomerx\JsonApi
69
 */
70
class Factory implements FactoryInterface
71
{
72
    /**
73
     * @var LoggerInterface
74
     */
75
    protected $logger;
76
77
    /**
78
     * Constructor.
79
     */
80 173
    public function __construct()
81
    {
82 173
        $this->logger = new ProxyLogger();
83 173
    }
84
85
    /**
86
     * @inheritdoc
87
     */
88 2
    public function setLogger(LoggerInterface $logger)
89
    {
90 2
        $this->logger->setLogger($logger);
0 ignored issues
show
Bug introduced by
It seems like you code against a concrete implementation and not the interface Psr\Log\LoggerInterface as the method setLogger() does only exist in the following implementations of said interface: Neomerx\JsonApi\Factories\ProxyLogger.

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...
91 2
    }
92
93
    /**
94
     * @inheritdoc
95
     */
96 64
    public function createEncoder(ContainerInterface $container, EncoderOptions $encoderOptions = null)
97
    {
98 64
        $encoder = new Encoder($this, $container, $encoderOptions);
99
100 64
        $encoder->setLogger($this->logger);
101
102 64
        return $encoder;
103
    }
104
105
    /**
106
     * @inheritdoc
107
     */
108 92
    public function createDocument()
109
    {
110 92
        $document = new Document();
111
112 92
        $document->setLogger($this->logger);
113
114 92
        return $document;
115
    }
116
117
    /**
118
     * @inheritdoc
119
     */
120 3
    public function createError(
121
        $idx = null,
122
        LinkInterface $aboutLink = null,
123
        $status = null,
124
        $code = null,
125
        $title = null,
126
        $detail = null,
127
        $source = null,
128
        array $meta = null
129
    ) {
130 3
        return new Error($idx, $aboutLink, $status, $code, $title, $detail, $source, $meta);
131
    }
132
    /**
133
     * @inheritdoc
134
     */
135 54
    public function createReply($replyType, StackReadOnlyInterface $stack)
136
    {
137 54
        return new ParserReply($replyType, $stack);
138
    }
139
140
    /**
141
     * @inheritdoc
142
     */
143 21
    public function createEmptyReply(
144
        $replyType,
145
        StackReadOnlyInterface $stack
146
    ) {
147 21
        return new ParserEmptyReply($replyType, $stack);
148
    }
149
150
    /**
151
     * @inheritdoc
152
     */
153 60
    public function createParser(ContainerInterface $container, ParserManagerInterface $manager)
154
    {
155 60
        $parser = new Parser($this, $this, $this, $container, $manager);
156
157 60
        $parser->setLogger($this->logger);
158
159 60
        return $parser;
160
    }
161
162
    /**
163
     * @inheritdoc
164
     */
165 58
    public function createManager(ParametersAnalyzerInterface $parameterAnalyzer)
166
    {
167 58
        $manager = new ParserManager($parameterAnalyzer);
168
169 58
        $manager->setLogger($this->logger);
170
171 58
        return $manager;
172
    }
173
174
    /**
175
     * @inheritdoc
176
     */
177 63
    public function createFrame(StackFrameReadOnlyInterface $previous = null)
178
    {
179 63
        return new StackFrame($previous);
180
    }
181
182
    /**
183
     * @inheritdoc
184
     */
185 64
    public function createStack()
186
    {
187 64
        return new Stack($this);
188
    }
189
190
    /**
191
     * @inheritdoc
192
     */
193 58
    public function createReplyInterpreter(DocumentInterface $document, ParametersAnalyzerInterface $parameterAnalyzer)
194
    {
195 58
        $interpreter = new ReplyInterpreter($document, $parameterAnalyzer);
196
197 58
        $interpreter->setLogger($this->logger);
198
199 58
        return $interpreter;
200
    }
201
202
    /**
203
     * @inheritdoc
204
     */
205 61
    public function createParametersAnalyzer(EncodingParametersInterface $parameters, ContainerInterface $container)
206
    {
207 61
        $analyzer = new ParametersAnalyzer($parameters, $container);
208
209 61
        $analyzer->setLogger($this->logger);
210
211 61
        return $analyzer;
212
    }
213
214
    /**
215
     * @inheritdoc
216
     */
217 1
    public function createMediaType($type, $subType, $parameters = null)
218
    {
219 1
        return new MediaType($type, $subType, $parameters);
220
    }
221
222
    /**
223
     * @inheritdoc
224
     */
225 60
    public function createQueryParameters(
226
        $includePaths = null,
227
        array $fieldSets = null,
228
        $sortParameters = null,
229
        array $pagingParameters = null,
230
        array $filteringParameters = null,
231
        array $unrecognizedParams = null
232
    ) {
233 60
        return new EncodingParameters(
234 60
            $includePaths,
235 60
            $fieldSets,
236 60
            $sortParameters,
237 60
            $pagingParameters,
238 60
            $filteringParameters,
239
            $unrecognizedParams
240 60
        );
241
    }
242
243
    /**
244
     * @inheritdoc
245
     */
246 10
    public function createHeaderParameters($method, AcceptHeaderInterface $accept, HeaderInterface $contentType)
247
    {
248 10
        return new HeaderParameters($method, $accept, $contentType);
249
    }
250
251
    /**
252
     * @inheritdoc
253
     */
254 23
    public function createQueryParametersParser()
255
    {
256 23
        $parser = new QueryParametersParser($this);
257
258 23
        $parser->setLogger($this->logger);
259
260 23
        return $parser;
261
    }
262
263
    /**
264
     * @inheritdoc
265
     */
266 12
    public function createHeaderParametersParser()
267
    {
268 12
        $parser = new HeaderParametersParser($this);
269
270 12
        $parser->setLogger($this->logger);
271
272 12
        return $parser;
273
    }
274
275
    /**
276
     * @inheritdoc
277
     */
278 14
    public function createSortParam($sortField, $isAscending)
279
    {
280 14
        return new SortParameter($sortField, $isAscending);
281
    }
282
283
    /**
284
     * @inheritdoc
285
     */
286 1
    public function createSupportedExtensions($extensions = MediaTypeInterface::NO_EXT)
287
    {
288 1
        return new SupportedExtensions($extensions);
289
    }
290
291
    /**
292
     * @inheritdoc
293
     */
294 2
    public function createAcceptMediaType(
295
        $position,
296
        $type,
297
        $subType,
298
        $parameters = null,
299
        $quality = 1.0,
300
        $extensions = null
301
    ) {
302 2
        return new AcceptMediaType($position, $type, $subType, $parameters, $quality, $extensions);
303
    }
304
305
    /**
306
     * @inheritdoc
307
     */
308 2
    public function createAcceptHeader($unsortedMediaTypes)
309
    {
310 2
        return new AcceptHeader($unsortedMediaTypes);
311
    }
312
313
    /**
314
     * @inheritdoc
315
     */
316 6
    public function createHeadersChecker(CodecMatcherInterface $codecMatcher)
317
    {
318 6
        return new RestrictiveHeadersChecker($codecMatcher);
319
    }
320
321
    /**
322
     * @inheritdoc
323
     */
324 12
    public function createQueryChecker(
325
        $allowUnrecognized = true,
326
        array $includePaths = null,
327
        array $fieldSetTypes = null,
328
        array $sortParameters = null,
329
        array $pagingParameters = null,
330
        array $filteringParameters = null
331
    ) {
332 12
        return new RestrictiveQueryChecker(
333 12
            $allowUnrecognized,
334 12
            $includePaths,
335 12
            $fieldSetTypes,
336 12
            $sortParameters,
337 12
            $pagingParameters,
338
            $filteringParameters
339 12
        );
340
    }
341
342
    /**
343
     * @inheritdoc
344
     */
345 77
    public function createContainer(array $providers = [])
346
    {
347 77
        $container = new Container($this, $providers);
348
349 75
        $container->setLogger($this->logger);
350
351 75
        return $container;
352
    }
353
354
    /**
355
     * @inheritdoc
356
     */
357 75
    public function createResourceObject(
358
        SchemaProviderInterface $schema,
359
        $resource,
360
        $isInArray,
361
        $attributeKeysFilter = null
362
    ) {
363 75
        return new ResourceObject($schema, $resource, $isInArray, $attributeKeysFilter);
364
    }
365
366
    /**
367
     * @inheritdoc
368
     */
369 75
    public function createRelationshipObject($name, $data, $links, $meta, $isShowData, $isRoot)
370
    {
371 75
        return new RelationshipObject($name, $data, $links, $meta, $isShowData, $isRoot);
372
    }
373
374
    /**
375
     * @inheritdoc
376
     */
377 52
    public function createLink($subHref, $meta = null, $treatAsHref = false)
378
    {
379 52
        return new Link($subHref, $meta, $treatAsHref);
380
    }
381
382
    /**
383
     * @inheritdoc
384
     */
385 2
    public function createResourceIdentifierSchemaAdapter(SchemaProviderInterface $schema)
386
    {
387 2
        return new ResourceIdentifierSchemaAdapter($this, $schema);
388
    }
389
390
    /**
391
     * @inheritdoc
392
     */
393 2
    public function createResourceIdentifierContainerAdapter(ContainerInterface $container)
394
    {
395 2
        return new ResourceIdentifierContainerAdapter($this, $container);
396
    }
397
398
    /**
399
     * @inheritdoc
400
     */
401 1
    public function createIdentitySchema(ContainerInterface $container, $classType, Closure $identityClosure)
402
    {
403 1
        return new IdentitySchema($this, $container, $classType, $identityClosure);
404
    }
405
406
    /**
407
     * @inheritdoc
408
     */
409 18
    public function createCodecMatcher()
410
    {
411 18
        return new CodecMatcher();
412
    }
413
}
414