-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathModel.php
More file actions
109 lines (100 loc) · 3.64 KB
/
Model.php
File metadata and controls
109 lines (100 loc) · 3.64 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
<?php
declare(strict_types=1);
namespace Fykosak\NetteORM\Model;
use Fykosak\NetteORM\Exceptions\CannotAccessModelException;
use Fykosak\NetteORM\ModelRelationsParser;
use Fykosak\NetteORM\Selection\TypedGroupedSelection;
use Fykosak\NetteORM\Selection\TypedSelection;
use Fykosak\NetteORM\Types\WGS84Point;
use Nette\Database\Table\ActiveRow;
use Nette\MemberAccessException;
abstract class Model extends ActiveRow
{
/**
* @phpstan-param array<string,mixed> $data
* @phpstan-param TypedGroupedSelection<Model>|TypedSelection<Model> $table
*/
final public function __construct(array $data, TypedGroupedSelection|TypedSelection $table)
{
parent::__construct($data, $table);
}
/**
* @phpstan-return TypedGroupedSelection<Model>
*/
public function related(string $key, ?string $throughColumn = null): TypedGroupedSelection
{
$selection = parent::related($key, $throughColumn);
if ($selection instanceof TypedGroupedSelection) {
return $selection;
}
throw new \TypeError(
'$selection must be a instance of TypedGroupedSelection'
);
}
/**
* @throws MemberAccessException|\ReflectionException
*/
public function &__get(string $key): mixed //phpcs:ignore
{
$value = parent::__get($key);
$selfReflection = new \ReflectionClass(static::class);
$docs = ModelRelationsParser::parseModelDoc($selfReflection);
if (!is_null($value) && isset($docs[$key])) {
$item = $docs[$key];
if ($item['type']->isClass()) {
$returnType = $item['reflection'];
if ($value instanceof ActiveRow) {
if ($returnType->isSubclassOf(self::class)) {
$value = $returnType->newInstance($value->toArray(), $value->getTable());
}
} elseif ($returnType->isSubclassOf(\BackedEnum::class)) {
$value = $returnType->getMethod('tryFrom')->invoke($returnType, $value);
} elseif ($returnType->name === WGS84Point::class) {
$value = $returnType->getMethod('fromBytes')->invoke($returnType, $value);
}
}
}
return $value;
}
/**
* @template TModel of Model
* @phpstan-param class-string<TModel> $requestedModel
* @phpstan-return TModel|null
* @throws CannotAccessModelException|\ReflectionException
*/
public function getReferencedModel(string $requestedModel): ?self
{
// model is already instance of desired model
if ($this instanceof $requestedModel) {
return $this;
}
$path = ModelRelationsParser::getPath(
new \ReflectionClass($this),
new \ReflectionClass($requestedModel),
[]
);
$newModel = $this;
if ($path) {
foreach ($path as $item) {
$newModel = $item['type'] === 'property'
? $newModel->{$item['accessor']}
: $newModel->{$item['accessor']}();
if (!$newModel) {
if ($item['nullable']) {
return null;
}
throw new CannotAccessModelException($requestedModel, $this);
}
}
return $newModel;
}
throw new CannotAccessModelException($requestedModel, $this);
}
public static function createFromActiveRow(ActiveRow $row): static
{
if ($row instanceof static) {
return $row;
}
return new static($row->toArray(), $row->getTable());
}
}