SchemaRelationAttribute::isCollection()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 1
eloc 1
c 1
b 0
f 0
nc 1
nop 0
dl 0
loc 3
rs 10
1
<?php
2
3
namespace Ipag\Sdk\Model\Schema;
4
5
use Closure;
6
use Ipag\Sdk\Model\Model;
7
use Ipag\Sdk\Model\Schema\Exception\SchemaAttributeParseException;
8
9
/**
10
 * @codeCoverageIgnore
11
 */
12
class SchemaRelationAttribute extends SchemaAttribute
13
{
14
    protected string $relationClass;
15
    protected bool $many;
16
17
    public function __construct(Schema $schema, string $name, string $class)
18
    {
19
        parent::__construct($schema, $name);
20
        $this->relationClass = $class;
21
        $this->many = false;
22
    }
23
24
    //
25
26
    public function getAbsoluteName(): string
27
    {
28
        $path = parent::getAbsoluteName();
29
        $path .= $this->isCollection() ? '[]' : '';
30
        return $path;
31
    }
32
33
    private function getRelationClass(): string
34
    {
35
        return $this->relationClass;
36
    }
37
38
    private function newRelationClass(): Model
39
    {
40
        $relationClass = $this->getRelationClass();
41
        $instance = new $relationClass();
42
43
        if (!$instance instanceof Model) {
44
            throw new SchemaAttributeParseException($this, "Could not create a new relation instance, should be a Model-based class");
45
        }
46
47
        return $instance;
48
    }
49
50
    private function getFactory(): Closure
51
    {
52
        $relationClass = $this->getRelationClass();
53
54
        return function ($e) use ($relationClass) {
55
            if ($e instanceof $relationClass) {
56
                return $e;
57
            }
58
59
            if (!is_array($e)) {
60
                throw new SchemaAttributeParseException($this, "Provided value '{$e}' cannot be parsed into {$relationClass}.");
61
            }
62
63
            return $this->newRelationClass()
64
                ->setIdentifier($this->getName())
65
                ->setSchemaName($this->getAbsoluteName())
66
                ->fill($e);
67
        };
68
    }
69
70
    //
71
72
    public function isCollection(): bool
73
    {
74
        return $this->many;
75
    }
76
77
    public function many(bool $value = true): self
78
    {
79
        $this->many = $value;
80
        return $this;
81
    }
82
83
    //
84
85
    public function parseContextual($value)
86
    {
87
        $factory = $this->getFactory();
88
89
        if ($this->isCollection()) {
90
            if (!is_iterable($value)) {
91
                throw new SchemaAttributeParseException($this, "Provided value '$value' is not an iterable, expected a collection.");
92
            }
93
94
            if (!is_array($value)) {
95
                $value = iterator_to_array($value);
96
            }
97
98
            if (!array_is_list($value)) {
99
                throw new SchemaAttributeParseException($this, "Provided value is not a list.");
100
            }
101
102
            return array_map($factory, $value);
103
        }
104
105
        if (is_array($value) || is_object($value)) {
106
            return $factory($value);
107
        }
108
109
        throw new SchemaAttributeParseException($this, "Provided value '$value' cannot be parsed.");
110
    }
111
112
    public function serialize($value)
113
    {
114
        if (is_null($value)) {
115
            return null;
116
        }
117
118
        if (is_iterable($value)) {
119
            if (!is_array($value)) {
120
                $value = iterator_to_array($value);
121
            }
122
123
            return array_map(fn(Model $model) => $model->jsonSerialize(), $value);
124
        }
125
126
        return $value->jsonSerialize();
127
    }
128
129
    //
130
131
    public static function from(Schema $schema, string $name, string $class = Model::class): self
132
    {
133
        return new static($schema, $name, $class);
134
    }
135
}