Completed
Branch master (85eed3)
by
unknown
10:47
created

Factory::createReplyInterpreter()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 8
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 4
CRAP Score 1

Importance

Changes 3
Bugs 0 Features 0
Metric Value
c 3
b 0
f 0
dl 0
loc 8
ccs 4
cts 4
cp 1
rs 9.4285
cc 1
eloc 4
nc 1
nop 2
crap 1
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\Schema\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\Http\Parameters\Parameters;
38
use \Neomerx\JsonApi\Encoder\Parser\ParserManager;
39
use \Neomerx\JsonApi\Http\Headers\AcceptMediaType;
40
use \Neomerx\JsonApi\Http\Parameters\SortParameter;
41
use \Neomerx\JsonApi\Contracts\Schema\LinkInterface;
42
use \Neomerx\JsonApi\Encoder\Parser\ParserEmptyReply;
43
use \Neomerx\JsonApi\Http\Parameters\ParametersParser;
44
use \Neomerx\JsonApi\Encoder\Handlers\ReplyInterpreter;
45
use \Neomerx\JsonApi\Http\Parameters\EncodingParameters;
46
use \Neomerx\JsonApi\Contracts\Schema\ContainerInterface;
47
use \Neomerx\JsonApi\Http\Parameters\SupportedExtensions;
48
use \Neomerx\JsonApi\Contracts\Document\DocumentInterface;
49
use \Neomerx\JsonApi\Contracts\Factories\FactoryInterface;
50
use \Neomerx\JsonApi\Contracts\Codec\CodecMatcherInterface;
51
use \Neomerx\JsonApi\Encoder\Parameters\ParametersAnalyzer;
52
use \Neomerx\JsonApi\Schema\ResourceIdentifierSchemaAdapter;
53
use \Neomerx\JsonApi\Contracts\Http\Headers\HeaderInterface;
54
use \Neomerx\JsonApi\Http\Parameters\RestrictiveQueryChecker;
55
use \Neomerx\JsonApi\Contracts\Schema\SchemaProviderInterface;
56
use \Neomerx\JsonApi\Contracts\Http\Headers\MediaTypeInterface;
57
use \Neomerx\JsonApi\Http\Parameters\RestrictiveHeadersChecker;
58
use \Neomerx\JsonApi\Schema\ResourceIdentifierContainerAdapter;
59
use \Neomerx\JsonApi\Http\Parameters\RestrictiveParametersChecker;
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\Http\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 167
    public function __construct()
81
    {
82 167
        $this->logger = new ProxyLogger();
83 167
    }
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 61
    public function createEncoder(ContainerInterface $container, EncoderOptions $encoderOptions = null)
97
    {
98 61
        $encoder = new Encoder($this, $container, $encoderOptions);
99
100 61
        $encoder->setLogger($this->logger);
101
102 61
        return $encoder;
103
    }
104
105
    /**
106
     * @inheritdoc
107
     */
108 89
    public function createDocument()
109
    {
110 89
        $document = new Document();
111
112 89
        $document->setLogger($this->logger);
113
114 89
        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 51
    public function createReply($replyType, StackReadOnlyInterface $stack)
136
    {
137 51
        return new ParserReply($replyType, $stack);
138
    }
139
140
    /**
141
     * @inheritdoc
142
     */
143 19
    public function createEmptyReply(
144
        $replyType,
145
        StackReadOnlyInterface $stack
146
    ) {
147 19
        return new ParserEmptyReply($replyType, $stack);
148
    }
149
150
    /**
151
     * @inheritdoc
152
     */
153 57
    public function createParser(ContainerInterface $container, ParserManagerInterface $manager)
154
    {
155 57
        $parser = new Parser($this, $this, $this, $container, $manager);
156
157 57
        $parser->setLogger($this->logger);
158
159 57
        return $parser;
160
    }
161
162
    /**
163
     * @inheritdoc
164
     */
165 55
    public function createManager(ParametersAnalyzerInterface $parameterAnalyzer)
166
    {
167 55
        $manager = new ParserManager($parameterAnalyzer);
168
169 55
        $manager->setLogger($this->logger);
170
171 55
        return $manager;
172
    }
173
174
    /**
175
     * @inheritdoc
176
     */
177 60
    public function createFrame(StackFrameReadOnlyInterface $previous = null)
178
    {
179 60
        return new StackFrame($previous);
180
    }
181
182
    /**
183
     * @inheritdoc
184
     */
185 61
    public function createStack()
186
    {
187 61
        return new Stack($this);
188
    }
189
190
    /**
191
     * @inheritdoc
192
     */
193 55
    public function createReplyInterpreter(DocumentInterface $document, ParametersAnalyzerInterface $parameterAnalyzer)
194
    {
195 55
        $interpreter = new ReplyInterpreter($document, $parameterAnalyzer);
196
197 55
        $interpreter->setLogger($this->logger);
198
199 55
        return $interpreter;
200
    }
201
202
    /**
203
     * @inheritdoc
204
     */
205 40
    public function createEncodingParameters($includePaths = null, array $fieldSets = null)
206
    {
207 40
        return new EncodingParameters($includePaths, $fieldSets);
208
    }
209
210
    /**
211
     * @inheritdoc
212
     */
213 58
    public function createParametersAnalyzer(EncodingParametersInterface $parameters, ContainerInterface $container)
214
    {
215 58
        $analyzer = new ParametersAnalyzer($parameters, $container);
216
217 58
        $analyzer->setLogger($this->logger);
218
219 58
        return $analyzer;
220
    }
221
222
    /**
223
     * @inheritdoc
224
     */
225 1
    public function createMediaType($type, $subType, $parameters = null)
226
    {
227 1
        return new MediaType($type, $subType, $parameters);
228
    }
229
230
    /**
231
     * @inheritdoc
232
     */
233 25
    public function createParameters(
234
        HeaderInterface $contentType,
235
        AcceptHeaderInterface $accept,
236
        $includePaths = null,
237
        array $fieldSets = null,
238
        $sortParameters = null,
239
        array $pagingParameters = null,
240
        array $filteringParameters = null,
241
        array $unrecognizedParams = null
242
    ) {
243 25
        return new Parameters(
244 25
            $contentType,
245 25
            $accept,
246 25
            $includePaths,
247 25
            $fieldSets,
248 25
            $sortParameters,
249 25
            $pagingParameters,
250 25
            $filteringParameters,
251
            $unrecognizedParams
252 25
        );
253
    }
254
255
    /**
256
     * @inheritdoc
257
     */
258 33
    public function createParametersParser()
259
    {
260 33
        $parser = new ParametersParser($this);
261
262 33
        $parser->setLogger($this->logger);
263
264 33
        return $parser;
265
    }
266
267
    /**
268
     * @inheritdoc
269
     */
270 18
    public function createSortParam($sortField, $isAscending)
271
    {
272 18
        return new SortParameter($sortField, $isAscending);
273
    }
274
275
    /**
276
     * @inheritdoc
277
     */
278 1
    public function createSupportedExtensions($extensions = MediaTypeInterface::NO_EXT)
279
    {
280 1
        return new SupportedExtensions($extensions);
281
    }
282
283
    /**
284
     * @inheritdoc
285
     */
286 2
    public function createAcceptMediaType(
287
        $position,
288
        $type,
289
        $subType,
290
        $parameters = null,
291
        $quality = 1.0,
292
        $extensions = null
293
    ) {
294 2
        return new AcceptMediaType($position, $type, $subType, $parameters, $quality, $extensions);
295
    }
296
297
    /**
298
     * @inheritdoc
299
     */
300 2
    public function createAcceptHeader($unsortedMediaTypes)
301
    {
302 2
        return new AcceptHeader($unsortedMediaTypes);
303
    }
304
305
    /**
306
     * @inheritdoc
307
     */
308 16
    public function createHeadersChecker(CodecMatcherInterface $codecMatcher)
309
    {
310 16
        return new RestrictiveHeadersChecker($codecMatcher);
311
    }
312
313
    /**
314
     * @inheritdoc
315
     */
316 16
    public function createQueryChecker(
317
        $allowUnrecognized = true,
318
        array $includePaths = null,
319
        array $fieldSetTypes = null,
320
        array $sortParameters = null,
321
        array $pagingParameters = null,
322
        array $filteringParameters = null
323
    ) {
324 16
        return new RestrictiveQueryChecker(
325 16
            $allowUnrecognized,
326 16
            $includePaths,
327 16
            $fieldSetTypes,
328 16
            $sortParameters,
329 16
            $pagingParameters,
330
            $filteringParameters
331 16
        );
332
    }
333
334
    /**
335
     * @inheritdoc
336
     */
337 16
    public function createParametersChecker(
338
        CodecMatcherInterface $codecMatcher,
339
        $allowUnrecognized = false,
340
        array $includePaths = null,
341
        array $fieldSetTypes = null,
342
        array $sortParameters = null,
343
        array $pagingParameters = null,
344
        array $filteringParameters = null
345
    ) {
346 16
        $headersChecker = $this->createHeadersChecker($codecMatcher);
347 16
        $queryChecker   = $this->createQueryChecker(
348 16
            $allowUnrecognized,
349 16
            $includePaths,
350 16
            $fieldSetTypes,
351 16
            $sortParameters,
352 16
            $pagingParameters,
353
            $filteringParameters
354 16
        );
355
356 16
        return new RestrictiveParametersChecker($headersChecker, $queryChecker);
357
    }
358
359
    /**
360
     * @inheritdoc
361
     */
362 73
    public function createContainer(array $providers = [])
363
    {
364 73
        $container = new Container($this, $providers);
365
366 71
        $container->setLogger($this->logger);
367
368 71
        return $container;
369
    }
370
371
    /**
372
     * @inheritdoc
373
     */
374 72
    public function createResourceObject(
375
        SchemaProviderInterface $schema,
376
        $resource,
377
        $isInArray,
378
        $attributeKeysFilter = null
379
    ) {
380 72
        return new ResourceObject($schema, $resource, $isInArray, $attributeKeysFilter);
381
    }
382
383
    /**
384
     * @inheritdoc
385
     */
386 72
    public function createRelationshipObject($name, $data, $links, $meta, $isShowData, $isRoot)
387
    {
388 72
        return new RelationshipObject($name, $data, $links, $meta, $isShowData, $isRoot);
389
    }
390
391
    /**
392
     * @inheritdoc
393
     */
394 7
    public function createLink($subHref, $meta = null, $treatAsHref = false)
395
    {
396 7
        return new Link($subHref, $meta, $treatAsHref);
397
    }
398
399
    /**
400
     * @inheritdoc
401
     */
402 2
    public function createResourceIdentifierSchemaAdapter(SchemaProviderInterface $schema)
403
    {
404 2
        return new ResourceIdentifierSchemaAdapter($this, $schema);
405
    }
406
407
    /**
408
     * @inheritdoc
409
     */
410 2
    public function createResourceIdentifierContainerAdapter(ContainerInterface $container)
411
    {
412 2
        return new ResourceIdentifierContainerAdapter($this, $container);
413
    }
414
415
    /**
416
     * @inheritdoc
417
     */
418 1
    public function createIdentitySchema(ContainerInterface $container, $classType, Closure $identityClosure)
419
    {
420 1
        return new IdentitySchema($this, $container, $classType, $identityClosure);
421
    }
422
423
    /**
424
     * @inheritdoc
425
     */
426 28
    public function createCodecMatcher()
427
    {
428 28
        return new CodecMatcher();
429
    }
430
}
431