Completed
Push — master ( 08635e...dd4786 )
by Nil
10:03
created

Laravel5JsonApiServiceProvider   A

Complexity

Total Complexity 18

Size/Duplication

Total Lines 141
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 5

Importance

Changes 1
Bugs 0 Features 0
Metric Value
wmc 18
c 1
b 0
f 0
lcom 1
cbo 5
dl 0
loc 141
rs 10

7 Methods

Rating   Name   Duplication   Size   Complexity  
A boot() 0 4 1
A register() 0 19 1
B parseRoutes() 0 25 5
A setUrlWithReflection() 0 11 2
B setJsonApiRelationships() 0 19 6
A calculateRoute() 0 11 2
A provides() 0 4 1
1
<?php
2
3
/**
4
 * Author: Nil Portugués Calderó <[email protected]>
5
 * Date: 8/15/15
6
 * Time: 5:45 PM.
7
 *
8
 * For the full copyright and license information, please view the LICENSE
9
 * file that was distributed with this source code.
10
 */
11
12
namespace NilPortugues\Laravel5\JsonApi;
13
14
use Illuminate\Support\Facades\Cache;
15
use Illuminate\Support\ServiceProvider;
16
use NilPortugues\Api\JsonApi\JsonApiTransformer;
17
use NilPortugues\Api\Mapping\Mapping;
18
use NilPortugues\Laravel5\JsonApi\Mapper\Mapper;
19
use ReflectionClass;
20
21
class Laravel5JsonApiServiceProvider extends ServiceProvider
22
{
23
    const PATH = '/../../../config/jsonapi.php';
24
25
    /**
26
     * Indicates if loading of the provider is deferred.
27
     *
28
     * @var bool
29
     */
30
    protected $defer = false;
31
32
    /**
33
     * Bootstrap the application events.
34
     */
35
    public function boot()
36
    {
37
        $this->publishes([__DIR__.self::PATH => config('jsonapi.php')]);
38
    }
39
40
    /**
41
     * Register the service provider.
42
     */
43
    public function register()
44
    {
45
        $this->mergeConfigFrom(__DIR__.self::PATH, 'jsonapi');
46
        $this->app->singleton(
47
            JsonApiSerializer::class,
48
            function ($app) {
49
50
                $mapping = $app['config']->get('jsonapi');
51
                $key = md5(json_encode($mapping));
52
53
                return Cache::rememberForever(
54
                    $key,
55
                    function () use ($mapping) {
56
                        return new JsonApiSerializer(new JsonApiTransformer(self::parseRoutes(new Mapper($mapping))));
57
                    }
58
                );
59
            }
60
        );
61
    }
62
63
    /**
64
     * @param Mapper $mapper
65
     *
66
     * @return Mapper
67
     */
68
    private static function parseRoutes(Mapper $mapper)
69
    {
70
        foreach ($mapper->getClassMap() as &$mapping) {
0 ignored issues
show
Bug introduced by
The expression $mapper->getClassMap() cannot be used as a reference.

Let?s assume that you have the following foreach statement:

foreach ($array as &$itemValue) { }

$itemValue is assigned by reference. This is possible because the expression (in the example $array) can be used as a reference target.

However, if we were to replace $array with something different like the result of a function call as in

foreach (getArray() as &$itemValue) { }

then assigning by reference is not possible anymore as there is no target that could be modified.

Available Fixes

1. Do not assign by reference
foreach (getArray() as $itemValue) { }
2. Assign to a local variable first
$array = getArray();
foreach ($array as &$itemValue) {}
3. Return a reference
function &getArray() { $array = array(); return $array; }

foreach (getArray() as &$itemValue) { }
Loading history...
71
            $mappingClass = new \ReflectionClass($mapping);
72
73
            self::setUrlWithReflection($mapping, $mappingClass, 'resourceUrlPattern');
74
            self::setUrlWithReflection($mapping, $mappingClass, 'selfUrl');
75
            $mappingProperty = $mappingClass->getProperty('otherUrls');
76
            $mappingProperty->setAccessible(true);
77
78
            $otherUrls = (array) $mappingProperty->getValue($mapping);
79
            if (!empty($otherUrls)) {
80
                foreach ($otherUrls as &$url) {
81
                    if (!empty($url['name'])) {
82
                        $url = self::calculateRoute($url);
83
                    }
84
                }
85
            }
86
            $mappingProperty->setValue($mapping, $otherUrls);
87
88
            self::setJsonApiRelationships($mappingClass, $mapping);
89
        }
90
91
        return $mapper;
92
    }
93
94
    /**
95
     * @param Mapping         $mapping
96
     * @param ReflectionClass $mappingClass
97
     * @param string          $property
98
     */
99
    private static function setUrlWithReflection(Mapping $mapping, ReflectionClass $mappingClass, $property)
100
    {
101
        $mappingProperty = $mappingClass->getProperty($property);
102
        $mappingProperty->setAccessible(true);
103
        $value = $mappingProperty->getValue($mapping);
104
105
        if (!empty($value['name'])) {
106
            $route = self::calculateRoute($value);
107
            $mappingProperty->setValue($mapping, $route);
108
        }
109
    }
110
111
    /**
112
     * @param ReflectionClass $mappingClass
113
     * @param                 $mapping
114
     */
115
    private static function setJsonApiRelationships(ReflectionClass $mappingClass, $mapping)
116
    {
117
        $mappingProperty = $mappingClass->getProperty('relationshipSelfUrl');
118
        $mappingProperty->setAccessible(true);
119
120
        $relationshipSelfUrl = (array) $mappingProperty->getValue($mapping);
121
        if (!empty($relationshipSelfUrl)) {
122
            foreach ($relationshipSelfUrl as &$urlMember) {
123
                if (!empty($urlMember)) {
124
                    foreach ($urlMember as &$url) {
125
                        if (!empty($url['name'])) {
126
                            $url = self::calculateRoute($url);
127
                        }
128
                    }
129
                }
130
            }
131
        }
132
        $mappingProperty->setValue($mapping, $relationshipSelfUrl);
133
    }
134
135
    /**
136
     * @param array $value
137
     *
138
     * @return mixed|string
139
     */
140
    private static function calculateRoute(array $value)
141
    {
142
        $route = urldecode(route($value['name']));
143
144
        if (!empty($value['as_id'])) {
145
            preg_match_all('/{(.*?)}/', $route, $matches);
146
            $route = str_replace($matches[0], '{'.$value['as_id'].'}', $route);
147
        }
148
149
        return $route;
150
    }
151
152
    /**
153
     * Get the services provided by the provider.
154
     *
155
     * @return array
156
     */
157
    public function provides()
158
    {
159
        return ['jsonapi'];
160
    }
161
}
162