Passed
Push — master ( a7bf6b...dea9c6 )
by Arthur
02:21
created

Json::unsetArray()   A

Complexity

Conditions 5
Paths 5

Size

Total Lines 7
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 5
dl 0
loc 7
c 0
b 0
f 0
rs 9.6111
cc 5
nc 5
nop 2
1
<?php
2
3
namespace SoliDry\Helpers;
4
5
use Illuminate\Database\Eloquent\Model;
6
use Illuminate\Http\Request;
0 ignored issues
show
Bug introduced by
This use statement conflicts with another class in this namespace, SoliDry\Helpers\Request. Consider defining an alias.

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 League\Fractal\Manager;
8
use League\Fractal\Resource\Collection;
9
use League\Fractal\Resource\Item;
10
use League\Fractal\Resource\ResourceInterface;
11
use League\Fractal\Serializer\JsonApiSerializer;
12
use SoliDry\Types\ModelsInterface;
13
use SoliDry\Types\PhpInterface;
14
use SoliDry\Types\ApiInterface;
15
use SoliDry\Extension\BaseFormRequest;
16
use SoliDry\Extension\JSONApiInterface;
17
use SoliDry\Transformers\DefaultTransformer;
18
19
class Json
20
{
21
    /**
22
     * @param array $jsonApiArr
23
     *
24
     * @return array
25
     */
26
    public static function getAttributes(array $jsonApiArr) : array
27
    {
28
        return empty($jsonApiArr[ApiInterface::RAML_DATA][ApiInterface::RAML_ATTRS]) ? [] : $jsonApiArr[ApiInterface::RAML_DATA][ApiInterface::RAML_ATTRS];
29
    }
30
31
    /**
32
     * Returns an array of bulk attributes for each element
33
     *
34
     * @param array $jsonApiArr
35
     * @return array
36
     */
37
    public static function getBulkAttributes(array $jsonApiArr) : array
38
    {
39
        return empty($jsonApiArr[ApiInterface::RAML_DATA]) ? [] : $jsonApiArr[ApiInterface::RAML_DATA];
40
    }
41
42
    /**
43
     * @param array $jsonApiArr
44
     *
45
     * @return array
46
     */
47
    public static function getRelationships(array $jsonApiArr) : array
48
    {
49
        return empty($jsonApiArr[ApiInterface::RAML_DATA][ApiInterface::RAML_RELATIONSHIPS]) ? [] : $jsonApiArr[ApiInterface::RAML_DATA][ApiInterface::RAML_RELATIONSHIPS];
50
    }
51
52
    /**
53
     * @param array $jsonApiArr
54
     *
55
     * @return array
56
     */
57
    public static function getData(array $jsonApiArr) : array
58
    {
59
        return empty($jsonApiArr[ApiInterface::RAML_DATA]) ? [] : $jsonApiArr[ApiInterface::RAML_DATA];
60
    }
61
62
    /**
63
     * @param $relations      \Illuminate\Database\Eloquent\Collection
64
     * @param string $entity
65
     * @return array JSON API rels compatible array
66
     */
67
    public static function getRelations($relations, string $entity) : array
68
    {
69
        $jsonArr = [];
70
        if ($relations instanceof \Illuminate\Database\Eloquent\Collection) {
71
            $cnt = count($relations);
72
            if ($cnt > 1) {
73
                foreach ($relations as $v) {
74
                    $attrs     = $v->getAttributes();
75
                    $jsonArr[] = [ApiInterface::RAML_TYPE => $entity,
76
                                  ApiInterface::RAML_ID   => $attrs[ApiInterface::RAML_ID]];
77
                }
78
            } else {
79
                foreach ($relations as $v) {
80
                    $attrs   = $v->getAttributes();
81
                    $jsonArr = [ApiInterface::RAML_TYPE => $entity,
82
                                ApiInterface::RAML_ID   => $attrs[ApiInterface::RAML_ID]];
83
                }
84
            }
85
        } elseif ($relations instanceof Model) {
86
            $attrs   = $relations->getAttributes();
87
            $jsonArr = [ApiInterface::RAML_TYPE => $entity,
88
                        ApiInterface::RAML_ID   => $attrs[ApiInterface::RAML_ID]];
89
        }
90
91
        return $jsonArr;
92
    }
93
94
    /**
95
     * Output errors in JSON API compatible format
96
     * @param array $errors
97
     * @param bool $return
98
     * @return string
99
     */
100
    public static function outputErrors(array $errors, bool $return = false)
101
    {
102
        $arr[JSONApiInterface::CONTENT_ERRORS] = [];
0 ignored issues
show
Comprehensibility Best Practice introduced by
$arr was never initialized. Although not strictly required by PHP, it is generally a good practice to add $arr = array(); before regardless.
Loading history...
103
        if (empty($errors) === false) {
104
            $arr[JSONApiInterface::CONTENT_ERRORS] = $errors;
105
        }
106
        // errors and codes must be clear with readable json
107
        $encoded = self::encode($arr, JSON_NUMERIC_CHECK | JSON_PRETTY_PRINT);
108
        if (false === $return && env('APP_ENV') !== 'dev') {
109
            echo $encoded;
110
            exit(JSONApiInterface::EXIT_STATUS_ERROR);
0 ignored issues
show
Best Practice introduced by
Using exit here is not recommended.

In general, usage of exit should be done with care and only when running in a scripting context like a CLI script.

Loading history...
111
        }
112
        return $encoded;
113
    }
114
115
    /**
116
     *
117
     * @param array $errors
118
     * @return string
119
     */
120
    public function getErrors(array $errors) : string
121
    {
122
        $arr[JSONApiInterface::CONTENT_ERRORS] = [];
0 ignored issues
show
Comprehensibility Best Practice introduced by
$arr was never initialized. Although not strictly required by PHP, it is generally a good practice to add $arr = array(); before regardless.
Loading history...
123
        if (empty($errors) === false) {
124
            $arr[JSONApiInterface::CONTENT_ERRORS] = $errors;
125
        }
126
127
        return self::encode($arr, JSON_NUMERIC_CHECK | JSON_PRETTY_PRINT);
128
    }
129
130
    /**
131
     * Returns composition of relations
132
     *
133
     * @param Request $request
134
     * @param array $data
135
     * @return string
136
     */
137
    public static function prepareSerializedRelations(Request $request, array $data) : string
138
    {
139
        $arr[JSONApiInterface::CONTENT_LINKS] = [
0 ignored issues
show
Comprehensibility Best Practice introduced by
$arr was never initialized. Although not strictly required by PHP, it is generally a good practice to add $arr = array(); before regardless.
Loading history...
140
            JSONApiInterface::CONTENT_SELF => $request->getUri(),
141
        ];
142
143
        $arr[JSONApiInterface::CONTENT_DATA] = $data;
144
145
        return self::encode($arr);
146
    }
147
148
    /**
149
     * @param BaseFormRequest $formRequest
150
     * @param                 $model
151
     * @param string $entity
152
     * @param bool $isCollection
153
     *
154
     * @param array $meta
155
     * @return Collection|Item
156
     */
157
    public static function getResource(BaseFormRequest $formRequest, $model, string $entity, bool $isCollection = false, array $meta = [])
158
    {
159
        $transformer = new DefaultTransformer($formRequest);
160
        if ($isCollection === true) {
161
            $collection = new Collection($model, $transformer, strtolower($entity));
162
            if (empty($meta) === false) {
163
                $collection->setMeta($meta);
164
            }
165
166
            return $collection;
167
        }
168
169
        $item = new Item($model, $transformer, strtolower($entity));
170
        $item->setMeta($meta);
171
172
        return $item;
173
    }
174
175
    /**
176
     * @param ResourceInterface $resource
177
     * @param array $data
178
     * @return string
179
     */
180
    public static function prepareSerializedData(ResourceInterface $resource, $data = ModelsInterface::DEFAULT_DATA) : string
181
    {
182
        if (empty($resource->getData())) { // preventing 3d party libs (League etc) from crash on empty data
183
            return self::encode([
184
                ModelsInterface::PARAM_DATA => []
185
            ]);
186
        }
187
188
        $host    = $_SERVER['HTTP_HOST'];
189
        $manager = new Manager();
190
191
        if (isset($_GET['include'])) {
192
            $manager->parseIncludes($_GET['include']);
193
        }
194
195
        $manager->setSerializer(new JsonApiSerializer($host));
196
        return self::getSelectedData($manager->createData($resource)->toJson(), $data);
197
    }
198
199
    /**
200
     * @param array $array
201
     * @param int $opts
202
     * @return string
203
     */
204
    public static function encode(array $array, int $opts = 0)
205
    {
206
        return json_encode($array, $opts);
207
    }
208
209
    /**
210
     * @param mixed $json
211
     * @return mixed
212
     */
213
    public static function decode($json)
214
    {
215
        return json_decode($json, true);
216
    }
217
218
    /**
219
     * @param string $json
220
     * @param array $data
221
     * @return string
222
     */
223
    private static function getSelectedData(string $json, array $data) : string
224
    {
225
        if (current($data) === PhpInterface::ASTERISK) {// do nothing - grab all fields
226
            return $json;
227
        }
228
229
        $jsonArr = self::decode($json);
230
        $current = current($jsonArr[ApiInterface::RAML_DATA]);
231
232
        if (empty($current[JSONApiInterface::CONTENT_ATTRIBUTES]) === false) {// this is an array of values
233
            self::unsetArray($jsonArr, $data);
234
        } else {// this is just one element
235
            self::unsetObject($jsonArr, $data);
236
        }
237
238
        return self::encode($jsonArr);
239
    }
240
241
    /**
242
     *
243
     * @param array &$json
244
     * @param array $data
245
     */
246
    private static function unsetArray(array &$json, array $data) : void
247
    {
248
        foreach ($json as &$jsonObject) {
249
            foreach ($jsonObject as &$v) {
250
                foreach ($v[JSONApiInterface::CONTENT_ATTRIBUTES] as $key => $attr) {
251
                    if (in_array($key, $data) === false) {
252
                        unset($v[JSONApiInterface::CONTENT_ATTRIBUTES][$key]);
253
                    }
254
                }
255
            }
256
        }
257
    }
258
259
    /**
260
     * @param array $json
261
     * @param array $data
262
     */
263
    private static function unsetObject(array &$json, array $data) : void
264
    {
265
        foreach ($json[JSONApiInterface::CONTENT_DATA][JSONApiInterface::CONTENT_ATTRIBUTES] as $k => $v) {
266
            if (in_array($k, $data) === false) {
267
                unset($json[JSONApiInterface::CONTENT_DATA][JSONApiInterface::CONTENT_ATTRIBUTES][$k]);
268
            }
269
        }
270
    }
271
}