-
Notifications
You must be signed in to change notification settings - Fork 3
Expand file tree
/
Copy pathTransit.php
More file actions
126 lines (108 loc) · 3.3 KB
/
Transit.php
File metadata and controls
126 lines (108 loc) · 3.3 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
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
<?php
declare(strict_types=1);
namespace Atlas\Transit;
use Atlas\Mapper\RecordSet;
use Atlas\Orm\Atlas;
use Atlas\Transit\Handler\HandlerLocator;
use Atlas\Transit\Inflector\Inflector;
use Atlas\Transit\Inflector\CamelCase;
use Atlas\Transit\Inflector\SnakeCase;
use Atlas\Transit\Reflection\ReflectionLocator;
use Closure;
use ReflectionParameter;
use ReflectionProperty;
use SplObjectStorage;
class Transit
{
protected $atlas;
protected $handlerLocator;
protected $plan;
public static function new(
Atlas $atlas,
string $sourceNamespace,
string $sourceCasingClass = SnakeCase::CLASS,
string $domainCasingClass = CamelCase::CLASS
) {
return new static(
$atlas,
new HandlerLocator(
$atlas,
new ReflectionLocator(
$sourceNamespace,
new Inflector(
new $sourceCasingClass(),
new $domainCasingClass()
)
)
)
);
}
public function __construct(
Atlas $atlas,
HandlerLocator $handlerLocator
) {
$this->atlas = $atlas;
$this->handlerLocator = $handlerLocator;
$this->plan = new SplObjectStorage();
}
public function getAtlas() : Atlas
{
return $this->atlas;
}
public function select(string $domainClass, array $whereEquals = []) : TransitSelect
{
$handler = $this->handlerLocator->get($domainClass);
return new TransitSelect(
$this->atlas->select($handler->getMapperClass(), $whereEquals),
$handler
);
}
// PLAN TO insert/update
public function store(object $domain) : void
{
if ($this->plan->contains($domain)) {
$this->plan->detach($domain);
}
$this->plan->attach($domain, 'updateSource');
}
// PLAN TO delete
public function discard(object $domain) : void
{
if ($this->plan->contains($domain)) {
$this->plan->detach($domain);
}
$this->plan->attach($domain, 'deleteSource');
}
public function persist() : void
{
$refresh = new SplObjectStorage();
foreach ($this->plan as $domain) {
$handler = $this->handlerLocator->get($domain);
$method = $this->plan->getInfo();
if (null === $method) {
continue;
}
try {
$source = $handler->$method($domain, $refresh);
if ($source instanceof RecordSet) {
$this->atlas->persistRecordSet($source);
} else {
$this->atlas->persist($source);
}
} catch (\Exception $exception) {
$this->plan->setInfo(null);
throw $exception;
}
}
foreach ($refresh as $domain) {
$handler = $this->handlerLocator->get($domain);
$handler->refreshDomain($domain, $refresh);
}
// unset/detach deleted as we go
// and: how to associate records, esp. failed records, with
// domain objects? or do we care about the domain objects at
// this point?
// reset the plan
$this->plan = new SplObjectStorage();
}
}