8 use pq\Gateway\Table\Reference
;
11 class Map
implements MapInterface
29 * @var PropertyInterface[]
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 $this->properties
= $properties;
43 foreach ($properties as $property) {
44 $property->setContainer($this);
46 $this->objects
= new ObjectManager($this);
50 * Get the name of the mapped class
58 * Get the object manager
59 * @return ObjectManager
61 function getObjects() {
62 return $this->objects
;
66 * Get the underlying table gateway
69 function getGateway() {
70 return $this->gateway
;
74 * Get the defined properties to map
75 * @return PropertyInterface[]
77 function getProperties() {
78 return $this->properties
;
82 * Add a property to map
83 * @param PropertyInterface $property
86 function addProperty(PropertyInterface
$property) {
87 $property->setContainer($this);
88 $this->properties
[] = $property;
93 * Get all child rows by foreign key
95 * @param string $refName
96 * @param array $objects
99 function allOf(Row
$row, $refName, &$objects = null) {
100 /* apply objectOf to populate the object cache */
101 return $this->gateway
->of($row, $refName)->apply(function($row) use(&$objects) {
102 $objects[] = $this->objects
->asObject($row);
107 * Get the parent row by foreign key
109 * @param string $refName
110 * @param array $objects
113 function refOf(Row
$row, $refName, &$objects = null) {
115 $rel = $row->getTable()->getRelation($this->gateway
->getName(), $refName);
116 // FIXME: check if foreign key points to primary key
117 foreach ($rel as $fgn => $col) {
118 $rid[$col] = $row->$fgn->get();
120 $rid = $this->objects
->serializeRowId($rid);
121 if ($this->objects
->hasObject($rid)) {
122 $object = $this->objects
->getObjectById($rid);
123 $row = $this->objects
->getRow($object);
124 $objects[] = $object;
125 $rowset = new Rowset($this->gateway
);
126 return $rowset->append($row);
128 /* apply objectOf to populate the object cache */
129 return $this->gateway
->by($row, $refName)->apply(function($row) use(&$objects) {
130 $objects[] = $this->objects
->asObject($row);
135 * Get the table relation reference
136 * @param MapInterface $map
137 * @param string $refName
140 function relOf(MapInterface
$map, $refName) {
141 return $map->getGateway()->getRelation(
142 $this->gateway
->getName(), $refName);
146 * Drain the deferred callback queue
147 * @param callable[] $deferred
148 * @param callable $exec
150 private function drain(array $deferred, callable
$exec) {
152 $cb = array_shift($deferred);
153 if (($cb = $exec($cb))) {
160 * Map a row to an object
164 function map(Row
$row) {
166 $object = $this->objects
->asObject($row);
167 foreach ($this->properties
as $property) {
168 if (($cb = $property->read($row, $object))) {
172 $this->drain($deferred, function(callable
$cb) use($row, $object) {
173 return $cb($row, $object);
179 * Map a rowset to an array of objects
180 * @param Rowset $rows
183 function mapAll(Rowset
$rows) {
185 foreach ($rows as $row) {
186 $objects[] = $this->map($row);
193 * @param object $object
195 function unmap($object) {
198 $row = $this->objects
->asRow($object);
199 $upd = $this->objects
->rowId($row, true);
200 foreach ($this->properties
as $property) {
201 if (($cb = $property->write($object, $row))) {
205 foreach ($this->gateway
->getIdentity() as $col) {
206 if (null === $row->$col->get()
207 ||
($row->$col->isExpr() && $row->$col->get()->isNull()))
209 $row->$col = new Expr("DEFAULT");
212 if ($row->isDirty()) {
219 foreach ($this->properties
as $property) {
220 if (($cb = $property->read($row, $object))) {
224 $this->drain($deferred, function($cb) use($object, $row) {
225 return $cb($object, $row);
227 if ($row->isDirty()) {