Passed
Push — master ( 92408f...e57c2f )
by
unknown
02:50
created

EloquentModelSerializer::toResource()   A

Complexity

Conditions 1
Paths 2

Size

Total Lines 15
Code Lines 10

Duplication

Lines 0
Ratio 0 %

Importance

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