8 use pq\Gateway\Table\Reference
;
11 class Map
implements MapInterface
29 * @var PropertyInterface[]
31 private $properties = [];
34 * Create a new object map definition
35 * @param string $class
36 * @param Table $gateway
37 * @param ...PropertyInterface $properties
39 function __construct($class, Table
$gateway, PropertyInterface
...$properties) {
40 $this->class = $class;
41 $this->gateway
= $gateway;
42 foreach ($properties as $property) {
43 $this->addProperty($property);
45 $this->objects
= new ObjectManager($this);
49 * Get the name of the mapped class
57 * Get the object manager
58 * @return ObjectManager
60 function getObjects() {
61 return $this->objects
;
65 * Get the underlying table gateway
68 function getGateway() {
69 return $this->gateway
;
73 * Get the defined properties to map
74 * @return PropertyInterface[]
76 function getProperties() {
77 return $this->properties
;
81 * Add a property to map
82 * @param PropertyInterface $property
85 function addProperty(PropertyInterface
$property) {
86 $property->setContainer($this);
87 $this->properties
[] = $property;
92 * Get all child rows by foreign key
94 * @param string $refName
95 * @param array $objects
98 function allOf(Row
$row, $refName, &$objects = null) {
99 /* apply objectOf to populate the object cache */
100 return $this->gateway
->of($row, $refName)->apply(function($row) use(&$objects) {
101 $objects[] = $this->objects
->asObject($row);
106 * Get the parent row by foreign key
108 * @param string $refName
109 * @param array $objects
112 function refOf(Row
$row, $refName, &$objects = null) {
114 $rel = $row->getTable()->getRelation($this->gateway
->getName(), $refName);
115 // FIXME: check if foreign key points to primary key
116 foreach ($rel as $fgn => $col) {
117 $rid[$col] = $row->$fgn->get();
119 $rid = $this->objects
->serializeRowId($rid);
120 if ($this->objects
->hasObject($rid)) {
121 $object = $this->objects
->getObjectById($rid);
122 $row = $this->objects
->getRow($object);
123 $objects[] = $object;
124 $rowset = new Rowset($this->gateway
);
125 return $rowset->append($row);
127 /* apply objectOf to populate the object cache */
128 return $this->gateway
->by($row, $refName)->apply(function($row) use(&$objects) {
129 $objects[] = $this->objects
->asObject($row);
134 * Get the table relation reference
135 * @param MapInterface $map
136 * @param string $refName
139 function relOf(MapInterface
$map, $refName) {
140 return $map->getGateway()->getRelation(
141 $this->gateway
->getName(), $refName);
145 * Drain the deferred callback queue
146 * @param callable[] $deferred
147 * @param callable $exec
149 private function drain(array $deferred, callable
$exec) {
151 $cb = array_shift($deferred);
152 if (($cb = $exec($cb))) {
159 * Map a row to an object
163 function map(Row
$row) {
165 $object = $this->objects
->asObject($row);
166 foreach ($this->properties
as $property) {
167 if (($cb = $property->read($row, $object))) {
171 $this->drain($deferred, function(callable
$cb) use($row, $object) {
172 return $cb($row, $object);
178 * Map a rowset to an array of objects
179 * @param Rowset $rows
182 function mapAll(Rowset
$rows) {
184 foreach ($rows as $row) {
185 $objects[] = $this->map($row);
192 * @param object $object
194 function unmap($object) {
197 $row = $this->objects
->asRow($object);
198 $upd = $this->objects
->rowId($row, true);
199 foreach ($this->properties
as $property) {
200 if (($cb = $property->write($object, $row))) {
204 foreach ($this->gateway
->getIdentity() as $col) {
205 if (null === $row->$col->get()
206 ||
($row->$col->isExpr() && $row->$col->get()->isNull()))
208 $row->$col = new Expr("DEFAULT");
211 if ($row->isDirty()) {
218 foreach ($this->properties
as $property) {
219 if (($cb = $property->read($row, $object))) {
223 $this->drain($deferred, function($cb) use($object, $row) {
224 return $cb($object, $row);
226 if ($row->isDirty()) {