Passed
Push — master ( c5bd37...640ffc )
by
unknown
05:22
created

EloquentModelSerializer::toList()   A

Complexity

Conditions 4
Paths 4

Size

Total Lines 19
Code Lines 12

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 12
c 0
b 0
f 0
dl 0
loc 19
rs 9.8666
cc 4
nc 4
nop 3
1
<?php
2
namespace W2w\Laravel\Apie\Plugins\Illuminate\Eloquent;
3
4
use Illuminate\Database\Eloquent\Builder;
5
use Illuminate\Database\Eloquent\Model;
6
use UnexpectedValueException;
7
use W2w\Lib\Apie\Core\SearchFilters\SearchFilterRequest;
8
use W2w\Lib\Apie\Interfaces\ResourceSerializerInterface;
9
10
/**
11
 * Contains logic to serialize from/to Eloquent models. This is placed in a different class for reusability.
12
 */
13
class EloquentModelSerializer
14
{
15
    private $serializer;
16
17
    public function __construct(ResourceSerializerInterface $serializer)
18
    {
19
        $this->serializer = $serializer;
20
    }
21
22
    /**
23
     * Converts a Query builder into a list of resources.
24
     *
25
     * @param Builder                  $builder
26
     * @param string                   $resourceClass
27
     * @param SearchFilterRequest|null $searchFilterRequest
28
     * @return Model[]
29
     */
30
    public function toList(Builder $builder, string $resourceClass, ?SearchFilterRequest $searchFilterRequest): array
31
    {
32
        if (empty($builder->getQuery()->orders) && empty($builder->getQuery()->unionOrders)) {
33
            $builder = $builder->orderBy('id', 'ASC');
34
        }
35
        if ($searchFilterRequest) {
36
            $builder = $builder
37
                ->where($searchFilterRequest->getSearches())
38
                ->skip($searchFilterRequest->getOffset())
39
                ->take($searchFilterRequest->getNumberOfItems());
40
        }
41
42
        $modelInstances = $builder->get();
43
44
        return array_map(
45
            function ($modelInstance) use (&$resourceClass) {
46
                return $this->toResource($modelInstance, $resourceClass);
47
            },
48
            iterator_to_array($modelInstances)
49
        );
50
    }
51
52
    /**
53
     * Converts resource into a eloquent model. The instance returns is always a new entity.
54
     *
55
     * @param mixed $resource
56
     * @param string $modelClass
57
     * @return Model
58
     */
59
    public function toModel($resource, string $modelClass): Model
60
    {
61
        $array = $this->serializer->normalize($resource, 'application/json');
62
        if (!is_array($array)) {
63
            throw new UnexpectedValueException('Resource ' . get_class($resource) . ' was normalized to a non array field');
64
        }
65
        $modelClass::unguard();
66
        try {
67
            $modelInstance = $modelClass::create($array);
68
        } finally {
69
            $modelClass::reguard();
70
        }
71
        return $modelInstance;
72
    }
73
74
    /**
75
     * Maps Eloquent model to a class of $resoureClass
76
     *
77
     * @param Model $eloquentModel
78
     * @param string $resourceClass
79
     * @return mixed
80
     */
81
    public function toResource(Model $eloquentModel, string $resourceClass)
82
    {
83
        return $this->serializer->hydrateWithReflection($eloquentModel->toArray(), $resourceClass);
84
    }
85
86
    /**
87
     * Converts existing resource into a eloquent model. The instance returns is always a new entity.
88
     *
89
     * @param mixed $resource
90
     * @param mixed $id
91
     * @param string $modelClass
92
     * @return Model
93
     */
94
    public function toExistingModel($resource, $id, string $modelClass): Model
95
    {
96
        $resourceClass = get_class($resource);
97
        $modelInstance = $modelClass::where(['id' => $id])->firstOrFail();
98
        $array = $this->serializer->normalize($resource, 'application/json');
99
        if (!is_array($array)) {
100
            throw new UnexpectedValueException('Resource ' . $resourceClass . ' was normalized to a non array field');
101
        }
102
        unset($array['id']);
103
        $modelInstance->unguard();
104
        try {
105
            $modelInstance->fill($array);
106
        } finally {
107
            $modelInstance->reguard();
108
        }
109
        $modelInstance->save();
110
        return $modelInstance;
111
    }
112
}
113