JsonImporter   A
last analyzed

Complexity

Total Complexity 21

Size/Duplication

Total Lines 96
Duplicated Lines 0 %

Test Coverage

Coverage 100%

Importance

Changes 2
Bugs 0 Features 0
Metric Value
eloc 38
dl 0
loc 96
ccs 50
cts 50
cp 1
rs 10
c 2
b 0
f 0
wmc 21

10 Methods

Rating   Name   Duplication   Size   Complexity  
A import() 0 7 2
A __construct() 0 3 1
A importFromJson() 0 3 1
A getRelationObject() 0 16 3
A importChildrenIfImportable() 0 7 2
A importRelations() 0 9 2
A importAttributes() 0 5 2
A wrap() 0 3 3
A convertObjectsToArray() 0 11 4
A addParentKeyToChildren() 0 7 1
1
<?php
2
3
namespace MathieuTu\JsonSyncer\Helpers;
4
5
use BadMethodCallException;
6
use Illuminate\Database\Eloquent\Model;
7
use Illuminate\Database\Eloquent\Relations\HasOneOrMany;
8
use Illuminate\Support\Arr;
9
use Illuminate\Support\Str;
10
use MathieuTu\JsonSyncer\Contracts\JsonImportable;
11
use MathieuTu\JsonSyncer\Exceptions\UnknownAttributeException;
12
13
class JsonImporter
14
{
15
    private JsonImportable $importable;
16
17 16
    public function __construct(JsonImportable $importable)
18
    {
19 16
        $this->importable = $importable;
20 16
    }
21
22 16
    public static function importFromJson(JsonImportable $importable, $objects): void
23
    {
24 16
        (new static($importable))->import($objects);
25 14
    }
26
27 16
    public function import($objects): void
28
    {
29 16
        $objects = $this->convertObjectsToArray($objects);
30
31 15
        foreach ($objects as $attributes) {
32 15
            $object = $this->importAttributes($attributes);
33 14
            $this->importRelations($object, $attributes);
34
        }
35 14
    }
36
37 16
    protected function convertObjectsToArray($objects): array
38
    {
39 16
        if (is_string($objects)) {
40 3
            $objects = json_decode($objects, true, 512, JSON_THROW_ON_ERROR);
41
        }
42
43 15
        if (is_object($objects) && method_exists($objects, 'toArray')) {
44 1
            $objects = $objects->toArray();
45
        }
46
47 15
        return $this->wrap((array)$objects);
48
    }
49
50 15
    protected function wrap(array $objects): array
51
    {
52 15
        return (empty($objects) || is_array(reset($objects))) ? $objects : [$objects];
53
    }
54
55 15
    protected function importAttributes($attributes): JsonImportable
56
    {
57 15
        $attributes = Arr::only($attributes, $this->importable->getJsonImportableAttributes());
58
59 15
        return $this->importable instanceof Model ? $this->importable->create($attributes) : $this->importable;
0 ignored issues
show
Bug introduced by
The method create() does not exist on MathieuTu\JsonSyncer\Contracts\JsonImportable. Since it exists in all sub-types, consider adding an abstract or default implementation to MathieuTu\JsonSyncer\Contracts\JsonImportable. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

59
        return $this->importable instanceof Model ? $this->importable->/** @scrutinizer ignore-call */ create($attributes) : $this->importable;
Loading history...
60
    }
61
62 14
    protected function importRelations($object, $attributes): void
63
    {
64 14
        $relationsNames = array_intersect(array_keys($attributes), $this->importable->getJsonImportableRelations());
65
66 14
        foreach ($relationsNames as $relationName) {
67 14
            $children = $this->convertObjectsToArray($attributes[$relationName]);
68 14
            $relation = $this->getRelationObject($object, $relationName);
69
70 14
            $this->importChildrenIfImportable($relation, $children);
71
        }
72 14
    }
73
74 14
    protected function importChildrenIfImportable(HasOneOrMany $relation, array $children): void
75
    {
76 14
        $childClass = $relation->getRelated();
77 14
        if ($childClass instanceof JsonImportable) {
78 13
            $children = $this->addParentKeyToChildren($children, $relation);
79
80 13
            $childClass->importFromJson($children);
81
        }
82 14
    }
83
84 13
    protected function addParentKeyToChildren(array $children, HasOneOrMany $relation): array
85
    {
86 13
        return array_map(function ($object) use ($relation) {
87 11
            $object[$relation->getForeignKeyName()] = $relation->getParentKey();
88
89 11
            return $object;
90 13
        }, $children);
91
    }
92
93 14
    protected function getRelationObject($object, $relationName): HasOneOrMany
94
    {
95 14
        $relationName = Str::camel($relationName);
96
97
        try {
98 14
            $relation = $object->$relationName();
99
100 14
            if (!$relation instanceof HasOneOrMany) {
101 1
                throw new BadMethodCallException();
102
            }
103
104 14
            return $relation;
105 2
        } catch (BadMethodCallException $e) {
106 2
            $class = get_class($object);
107
108 2
            throw new UnknownAttributeException("Unknown attribute or HasOneorMany relation '$relationName' in '$class'.");
109
        }
110
    }
111
}
112