Completed
Pull Request — master (#56)
by Alexander
02:56
created

ResourceFactory::resolveResourceKey()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 2

Importance

Changes 0
Metric Value
dl 0
loc 4
c 0
b 0
f 0
cc 2
eloc 2
nc 2
nop 2
ccs 2
cts 2
cp 1
crap 2
rs 10
1
<?php
2
3
namespace Flugg\Responder\Resources;
4
5
use Flugg\Responder\Contracts\Resources\ResourceFactory as ResourceFactoryContract;
6
use Flugg\Responder\Contracts\Resources\ResourceKeyResolver;
0 ignored issues
show
Bug introduced by
This use statement conflicts with another class in this namespace, Flugg\Responder\Resources\ResourceKeyResolver.

Let’s assume that you have a directory layout like this:

.
|-- OtherDir
|   |-- Bar.php
|   `-- Foo.php
`-- SomeDir
    `-- Foo.php

and let’s assume the following content of Bar.php:

// Bar.php
namespace OtherDir;

use SomeDir\Foo; // This now conflicts the class OtherDir\Foo

If both files OtherDir/Foo.php and SomeDir/Foo.php are loaded in the same runtime, you will see a PHP error such as the following:

PHP Fatal error:  Cannot use SomeDir\Foo as Foo because the name is already in use in OtherDir/Foo.php

However, as OtherDir/Foo.php does not necessarily have to be loaded and the error is only triggered if it is loaded before OtherDir/Bar.php, this problem might go unnoticed for a while. In order to prevent this error from surfacing, you must import the namespace with a different alias:

// Bar.php
namespace OtherDir;

use SomeDir\Foo as SomeDirFoo; // There is no conflict anymore.
Loading history...
7
use Flugg\Responder\Contracts\Transformers\TransformerResolver;
8
use Illuminate\Support\Arr;
9
use League\Fractal\Resource\Collection as CollectionResource;
10
use League\Fractal\Resource\Item as ItemResource;
11
use League\Fractal\Resource\NullResource;
12
use League\Fractal\Resource\ResourceInterface;
13
use Traversable;
14
15
/**
16
 * This class is responsible for making Fractal resources from a variety of data types.
17
 *
18
 * @package flugger/laravel-responder
19
 * @author  Alexander Tømmerås <[email protected]>
20
 * @license The MIT License
21
 */
22
class ResourceFactory implements ResourceFactoryContract
23
{
24
    /**
25
     * A service class, used to normalize data.
26
     *
27
     * @var \Flugg\Responder\Resources\DataNormalizer
28
     */
29
    protected $normalizer;
30
31
    /**
32
     * A manager class, used to manage transformers.
33
     *
34
     * @var \Flugg\Responder\Contracts\Transformers\TransformerResolver
35
     */
36
    protected $transformerResolver;
37
38
    /**
39
     * A resolver class, used to resolve resource keys.
40
     *
41
     * @var \Flugg\Responder\Contracts\Resources\ResourceKeyResolver
42
     */
43
    protected $resourceKeyResolver;
44
45
    /**
46
     * Construct the factory class.
47
     *
48
     * @param \Flugg\Responder\Resources\DataNormalizer                   $normalizer
49
     * @param \Flugg\Responder\Contracts\Transformers\TransformerResolver $transformerResolver
50
     * @param \Flugg\Responder\Contracts\Resources\ResourceKeyResolver    $resourceKeyResolver
51
     */
52 6
    public function __construct(DataNormalizer $normalizer, TransformerResolver $transformerResolver, ResourceKeyResolver $resourceKeyResolver)
53
    {
54 6
        $this->normalizer = $normalizer;
55 6
        $this->transformerResolver = $transformerResolver;
56 6
        $this->resourceKeyResolver = $resourceKeyResolver;
57 6
    }
58
59
    /**
60
     * Make resource from the given data.
61
     *
62
     * @param  mixed                                                          $data
63
     * @param  \Flugg\Responder\Transformers\Transformer|string|callable|null $transformer
64
     * @param  string|null                                                    $resourceKey
65
     * @return \League\Fractal\Resource\ResourceInterface
66
     */
67 6
    public function make($data = null, $transformer = null, string $resourceKey = null): ResourceInterface
68
    {
69 6
        if ($data instanceof ResourceInterface) {
70 1
            return $data->setTransformer($this->resolveTransformer($data->getData(), $transformer ?: $data->getTransformer()))
71 1
                ->setResourceKey($this->resolveResourceKey($data->getData(), $resourceKey ?: $data->getResourceKey()));
72 5
        } elseif (is_null($data = $this->normalizer->normalize($data))) {
73 1
            return $this->instatiateResource($data, null, $resourceKey);
74
        }
75
76 4
        $transformer = $this->resolveTransformer($data, $transformer);
77 4
        $resourceKey = $this->resolveResourceKey($data, $resourceKey);
78
79 4
        return $this->instatiateResource($data, $transformer, $resourceKey);
80
    }
81
82
    /**
83
     * Resolve a transformer.
84
     *
85
     * @param  mixed                                                          $data
86
     * @param  \Flugg\Responder\Transformers\Transformer|string|callable|null $transformer
87
     * @return \Flugg\Responder\Transformers\Transformer|callable
88
     */
89 5
    protected function resolveTransformer($data, $transformer)
90
    {
91 5
        if (isset($transformer)) {
92 3
            return $this->transformerResolver->resolve($transformer);
93
        }
94
95 2
        return $this->transformerResolver->resolveFromData($data);
96
    }
97
98
    /**
99
     * Resolve a resource key.
100
     *
101
     * @param  mixed       $data
102
     * @param  string|null $resourceKey
103
     * @return null|string
104
     */
105 5
    protected function resolveResourceKey($data, string $resourceKey = null)
106
    {
107 5
        return isset($resourceKey) ? $resourceKey : $this->resourceKeyResolver->resolve($data);
108
    }
109
110
    /**
111
     * Instatiate a new resource instance.
112
     *
113
     * @param  mixed                                                   $data
114
     * @param  \Flugg\Responder\Transformers\Transformer|callable|null $transformer
115
     * @param  string|null                                             $resourceKey
116
     * @return \League\Fractal\Resource\ResourceInterface
117
     */
118 5
    protected function instatiateResource($data, $transformer = null, string $resourceKey = null): ResourceInterface
119
    {
120 5
        if (is_null($data)) {
121 1
            return new NullResource(null, null, $resourceKey);
122 4
        } elseif ($this->shouldCreateCollection($data)) {
123 1
            return new CollectionResource($data, $transformer, $resourceKey);
124
        }
125
126 3
        return new ItemResource($data, $transformer, $resourceKey);
127
    }
128
129
    /**
130
     * Indicates if the data belongs to a collection resource.
131
     *
132
     * @param  mixed $data
133
     * @return bool
134
     */
135 4
    protected function shouldCreateCollection($data): bool
136
    {
137 4
        if (is_array($data)) {
138 2
            return ! is_scalar(Arr::first($data));
139
        }
140
141 2
        return $data instanceof Traversable;
142
    }
143
}