cleanups
[m6w6/pq-gateway] / lib / pq / Mapper / ObjectManager.php
diff --git a/lib/pq/Mapper/ObjectManager.php b/lib/pq/Mapper/ObjectManager.php
new file mode 100644 (file)
index 0000000..557d494
--- /dev/null
@@ -0,0 +1,133 @@
+<?php
+
+namespace pq\Mapper;
+
+use OutOfBoundsException;
+use pq\Exception\BadMethodCallException;
+use pq\Gateway\Row;
+
+class ObjectManager
+{
+       private $map;
+       private $obj = [];
+       private $row = [];
+
+       function __construct(MapInterface $map) {
+               $this->map = $map;
+       }
+
+       function reset() {
+               $this->obj = [];
+               $this->row = [];
+       }
+
+       function rowId(Row $row, $check = false) {
+               try {
+                       $identity = $row->getIdentity();
+               } catch (OutOfBoundsException $e) {
+                       return false;
+               }
+               return $this->serializeRowId($identity, $check);
+       }
+
+       function objectId($object) {
+               return spl_object_hash($object);
+       }
+
+       function extractRowId($object) {
+               $id = [];
+               foreach ($this->map->getGateway()->getIdentity() as $col) {
+                       foreach ($this->map->getProperties() as $property) {
+                               if ($property->exposes($col)) {
+                                       $id[$col] = $property->extract($object);
+                               }
+                       }
+               }
+               return $this->serializeRowId($id, true);
+       }
+
+       function serializeRowId($identity, $check = false) {
+               if (is_scalar($identity)) {
+                       return $identity;
+               }
+
+               if ($check && !isset($identity)) {
+                       return false;
+               }
+
+               if (is_array($identity)) {
+                       if ($check && array_search(null, $identity, true)) {
+                               return false;
+                       }
+                       /* one level is better than no level */
+                       asort($identity);
+               }
+               return json_encode($identity);
+       }
+
+       function hasObject($row_id) {
+               return isset($this->obj[$row_id]);
+       }
+
+       function createObject(Row $row) {
+               $rid = $this->rowId($row);
+               $cls = $this->map->getClass();
+               $obj = new $cls;
+               $oid = $this->objectId($obj);
+               $this->obj[$rid] = $obj;
+               $this->row[$oid] = $row;
+               return $obj;
+       }
+
+       function resetObject(Row $row) {
+               unset($this->obj[$this->rowId($row)]);
+       }
+
+       function getObject(Row $row) {
+               $id = $this->rowId($row);
+               return $this->getObjectById($id);
+       }
+
+       function getObjectById($row_id) {
+               if (!$this->hasObject($row_id)) {
+                       throw new BadMethodCallException("Object of row with id $row_id does not exist");
+               }
+               return $this->obj[$row_id];
+       }
+
+       function asObject(Row $row){
+               return $this->hasObject($this->rowId($row))
+                       ? $this->getObject($row)
+                       : $this->createObject($row);
+       }
+
+       function hasRow($obj_id) {
+               return isset($this->row[$obj_id]);
+       }
+
+       function createRow($object) {
+               $oid = $this->objectId($object);
+               $row = new Row($this->map->getGateway());
+               $this->row[$oid] = $row;
+               return $row;
+       }
+
+       function resetRow($object) {
+               unset($this->row [$this->objectId($object)]);
+       }
+       
+       function getRow($object) {
+               $id = $this->objectId($object);
+
+               if (!$this->hasRow($id)) {
+                       throw new BadMethodCallException("Row for object with id $id does not exist");
+               }
+               return $this->row[$id];
+       }
+
+       function asRow($object) {
+               return $this->hasRow($this->objectId($object))
+                       ? $this->getRow($object)
+                       : $this->createRow($object);
+       }
+}
\ No newline at end of file