first test
[m6w6/pq-gateway] / lib / pq / Mapper / ObjectManager.php
1 <?php
2
3 namespace pq\Mapper;
4
5 use OutOfBoundsException;
6 use pq\Exception\BadMethodCallException;
7 use pq\Gateway\Row;
8
9 class ObjectManager
10 {
11 /**
12 * @var MapInterface
13 */
14 private $map;
15
16 /**
17 * @var object[]
18 */
19 private $obj = [];
20
21 /**
22 * @var Row[]
23 */
24 private $row = [];
25
26 /**
27 * Create a new ObjectManager for a mapping
28 * @param MapInterface $map
29 */
30 function __construct(MapInterface $map) {
31 $this->map = $map;
32 }
33
34 /**
35 * Get the map
36 * @return MapInterface
37 */
38 function getMap() {
39 return $this->map;
40 }
41
42 /**
43 * Reset all managed objects
44 */
45 function reset() {
46 $this->obj = [];
47 $this->row = [];
48 }
49
50 /**
51 * Get the serialized row identity
52 *
53 * When $check is true, the identity will only be serialized if all columns
54 * of the primary key are set.
55 *
56 * @param Row $row
57 * @param bool $check
58 * @return string|false serialized row id or false on failure
59 */
60 function rowId(Row $row, $check = false) {
61 try {
62 $identity = $row->getIdentity();
63 } catch (OutOfBoundsException $e) {
64 return false;
65 }
66 return $this->serializeRowId($identity, $check);
67 }
68
69 /**
70 * Get an object's identity
71 * @param object $object
72 * @return string
73 */
74 function objectId($object) {
75 return spl_object_hash($object);
76 }
77
78 /**
79 * Extract a row's identity from a mapped object
80 * @param object $object
81 * @return string serialized row identity
82 */
83 function extractRowId($object) {
84 $id = [];
85 foreach ($this->map->getGateway()->getIdentity() as $col) {
86 foreach ($this->map->getProperties() as $property) {
87 if ($property->exposes($col)) {
88 $id[$col] = $property->extract($object);
89 }
90 }
91 }
92 return $this->serializeRowId($id, true);
93 }
94
95 /**
96 * Serialize a row's identity
97 * @param mixed $identity
98 * @param bool $check
99 * @return string|false the serialized row identity or false on failure
100 */
101 function serializeRowId($identity, $check = false) {
102 if (is_scalar($identity)) {
103 return $identity;
104 }
105
106 if ($check && !isset($identity)) {
107 return false;
108 }
109
110 if (is_array($identity)) {
111 if ($check && array_search(null, $identity, true)) {
112 return false;
113 }
114 /* one level is better than no level */
115 asort($identity);
116 }
117 return json_encode($identity);
118 }
119
120 /**
121 * Check whether a mapped object is already cached in the manager
122 * @param string $row_id
123 * @return bool
124 */
125 function hasObject($row_id) {
126 return isset($this->obj[$row_id]);
127 }
128
129 /**
130 * Create a mapped object from $row
131 * @param Row $row
132 * @return object
133 */
134 function createObject(Row $row) {
135 $rid = $this->rowId($row);
136 $cls = $this->map->getClass();
137 $obj = new $cls;
138 $oid = $this->objectId($obj);
139 $this->obj[$rid] = $obj;
140 $this->row[$oid] = $row;
141 return $obj;
142 }
143
144 /**
145 * Forget the mapped object of $row
146 * @param Row $row
147 */
148 function resetObject(Row $row) {
149 unset($this->obj[$this->rowId($row)]);
150 }
151
152 /**
153 * Get the mapped object of $row
154 * @param Row $row
155 * @return object
156 */
157 function getObject(Row $row) {
158 $id = $this->rowId($row);
159 return $this->getObjectById($id);
160 }
161
162 /**
163 * Get the mapped object of $row
164 * @param string $row_id
165 * @return object
166 * @throws BadMethodCallException
167 */
168 function getObjectById($row_id) {
169 if (!$this->hasObject($row_id)) {
170 throw new BadMethodCallException("Object of row with id $row_id does not exist");
171 }
172 return $this->obj[$row_id];
173 }
174
175 /**
176 * Check for a mapped object of $row, and create if necessary
177 * @param Row $row
178 * @return object
179 */
180 function asObject(Row $row){
181 return $this->hasObject($this->rowId($row))
182 ? $this->getObject($row)
183 : $this->createObject($row);
184 }
185
186 /**
187 * Check whether a row for a mapped object exists
188 * @param string $obj_id
189 * @return Row
190 */
191 function hasRow($obj_id) {
192 return isset($this->row[$obj_id]);
193 }
194
195 /**
196 * Initialize a Row from a mapped object
197 * @param object $object
198 * @return Row
199 */
200 function createRow($object) {
201 $oid = $this->objectId($object);
202 $row = new Row($this->map->getGateway());
203 $this->row[$oid] = $row;
204 return $row;
205 }
206
207 /**
208 * Forget about a row of a mapped object
209 * @param object $object
210 */
211 function resetRow($object) {
212 unset($this->row [$this->objectId($object)]);
213 }
214
215 /**
216 * Get the row of a mapped object
217 * @param object $object
218 * @return Row
219 * @throws BadMethodCallException
220 */
221 function getRow($object) {
222 $id = $this->objectId($object);
223
224 if (!$this->hasRow($id)) {
225 throw new BadMethodCallException("Row for object with id $id does not exist");
226 }
227 return $this->row[$id];
228 }
229
230 /**
231 * Check for a row of a mapped object, create from object if neccessary
232 * @param object $object
233 * @return Row
234 */
235 function asRow($object) {
236 return $this->hasRow($this->objectId($object))
237 ? $this->getRow($object)
238 : $this->createRow($object);
239 }
240 }