Go to the documentation of this file.00001 <?php
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00060 abstract class UnifiedContainer
00061 {
00062 protected $worker = null;
00063 protected $parent = null;
00064
00065 protected $dao = null;
00066
00067 protected $lazy = true;
00068 protected $fetched = false;
00069
00070 protected $list = array();
00071 protected $clones = array();
00072
00073
00074 protected $workerClass = null;
00075 protected $daoClass = null;
00076
00077 protected $comparator = null;
00078
00079 abstract public function getParentIdField();
00080 abstract public function getChildIdField();
00081
00082 public function __construct(
00083 Identifiable $parent, GenericDAO $dao, $lazy = true
00084 )
00085 {
00086 Assert::isBoolean($lazy);
00087
00088 $this->parent = $parent;
00089 $this->lazy = $lazy;
00090 $this->dao = $dao;
00091
00092 Assert::isInstance($dao->getObjectName(), 'Identifiable');
00093
00094 $this->comparator = SerializedObjectComparator::me();
00095 }
00096
00097 public function __sleep()
00098 {
00099 $this->daoClass = get_class($this->dao);
00100 $this->workerClass = get_class($this->worker);
00101 return array('workerClass', 'daoClass', 'parent', 'lazy');
00102 }
00103
00104 public function __wakeup()
00105 {
00106 $this->dao = Singleton::getInstance($this->daoClass);
00107 $this->worker = new $this->workerClass($this);
00108 }
00109
00110 public function getParentObject()
00111 {
00112 return $this->parent;
00113 }
00114
00118 public function getDao()
00119 {
00120 return $this->dao;
00121 }
00122
00123 public function isLazy()
00124 {
00125 return $this->lazy;
00126 }
00127
00128 public function isFetched()
00129 {
00130 return $this->fetched;
00131 }
00132
00137 public function setCriteria(Criteria $criteria)
00138 {
00139 Assert::isTrue(
00140 $criteria->getDao() === null
00141 || (
00142 $criteria->getDao() === $this->dao
00143 ),
00144 "criteria's dao doesn't match container's one"
00145 );
00146
00147 if (!$criteria->getDao())
00148 $criteria->setDao($this->dao);
00149
00150 $this->worker->setCriteria($criteria);
00151
00152 return $this;
00153 }
00154
00158 public function getCriteria()
00159 {
00160 return $this->worker->getCriteria();
00161 }
00162
00163 public function setObjectComparator(Comparator $comparator)
00164 {
00165 $this->comparator = $comparator;
00166
00167 return $this;
00168 }
00169
00174 public function setList($list)
00175 {
00176 Assert::isArray($list);
00177
00178 $this->list = $list;
00179
00180 return $this;
00181 }
00182
00186 public function mergeList(array $list)
00187 {
00188 if ($this->lazy) {
00189 foreach ($list as $id)
00190 $this->list[$id] = $id;
00191 } else {
00192 $this->list = array_merge($this->list, $list);
00193 }
00194
00195 $this->fetched = true;
00196
00197 return $this;
00198 }
00199
00200 public function getList()
00201 {
00202 if (!$this->list && !$this->isFetched())
00203 $this->fetch();
00204
00205 return $this->list;
00206 }
00207
00208 public function getCount()
00209 {
00210 if (!$this->isFetched() && $this->parent->getId()) {
00211 $row = $this->dao->getCustom($this->worker->makeCountQuery());
00212
00213 return current($row);
00214 }
00215
00216 return count($this->list);
00217 }
00218
00223 public function fetch()
00224 {
00225 if (!$this->parent->getId())
00226 throw new WrongStateException(
00227 'save parent object first'
00228 );
00229
00230 try {
00231 $this->fetchList();
00232 } catch (ObjectNotFoundException $e) {
00233
00234 }
00235
00236 $this->fetched = true;
00237
00238 return $this;
00239 }
00240
00245 public function save()
00246 {
00247 Assert::isArray(
00248 $this->list,
00249 "that's not an array :-/"
00250 );
00251
00252 if (!$this->fetched)
00253 throw new WrongStateException(
00254 'do not want to save non-fetched collection'
00255 );
00256
00257 $list = $this->list;
00258 $clones = $this->clones;
00259
00260 $ids = $insert = $delete = $update = array();
00261
00262 if ($this->lazy) {
00263 foreach ($list as $id) {
00264 if (!isset($clones[$id]))
00265 $insert[] = $ids[$id] = $id;
00266 else
00267 $ids[$id] = $id;
00268 }
00269
00270 foreach ($clones as $id) {
00271 if (!isset($ids[$id]))
00272 $delete[] = $id;
00273 }
00274 } else {
00275 foreach ($list as $object) {
00276 $id = $object->getId();
00277
00278 if (null === $id) {
00279 $insert[] = $object;
00280 } elseif (
00281 isset($clones[$id])
00282
00283
00284
00285 && ($this->comparator->compare($object, $clones[$id]) <> 0)
00286 ) {
00287 $update[] = $object;
00288 } elseif (!isset($clones[$id])) {
00289 $insert[] = $object;
00290 }
00291
00292 if (null !== $id)
00293 $ids[$id] = $object;
00294 }
00295
00296 foreach ($clones as $id => $object) {
00297 if (!isset($ids[$id]))
00298 $delete[] = $object;
00299 }
00300 }
00301
00302 $db = DBPool::getByDao($this->getDao());
00303
00304 if (!$db->inTransaction()) {
00305 $outerQueue = $db->isQueueActive();
00306
00307 if (!$outerQueue)
00308 $db->queueStart();
00309
00310 $db->begin();
00311
00312 try {
00313 $this->worker->sync($insert, $update, $delete);
00314
00315 $db->commit();
00316
00317 if (!$outerQueue)
00318 $db->queueFlush();
00319 } catch (DatabaseException $e) {
00320 if (!$outerQueue)
00321 $db->queueDrop()->queueStop();
00322
00323 $db->rollback();
00324
00325 throw $e;
00326 }
00327 } else {
00328 $this->worker->sync($insert, $update, $delete);
00329 }
00330
00331 $this->clones = array();
00332 $this->syncClones();
00333 $this->dao->uncacheLists();
00334
00335 return $this;
00336 }
00337
00341 public function clean()
00342 {
00343 $this->list = $this->clones = array();
00344
00345 $this->fetched = false;
00346
00347 return $this;
00348 }
00349
00353 public function dropList()
00354 {
00355 $this->worker->dropList();
00356
00357 $this->clean();
00358
00359 return $this;
00360 }
00361
00362 public static function destroy(UnifiedContainer $container)
00363 {
00364 unset($container->worker, $container);
00365 }
00366
00367 protected function fetchList()
00368 {
00369 $query = $this->worker->makeFetchQuery();
00370
00371 if ($this->lazy) {
00372 $list = $this->dao->getCustomRowList($query);
00373
00374
00375 if (
00376 isset($list[0])
00377 && is_array($list[0])
00378 ) {
00379 $newList = array();
00380
00381 foreach ($list as $key => $value)
00382 $newList[] = $value[$this->getChildIdField()];
00383
00384 $list = $newList;
00385 }
00386 } else
00387 $list = $this->dao->getListByQuery($query);
00388
00389 $this->list = array();
00390
00391 return $this->importList($list);
00392 }
00393
00397 private function importList(array $list)
00398 {
00399 $this->mergeList($list);
00400
00401 $this->syncClones();
00402
00403 return $this;
00404 }
00405
00409 private function syncClones()
00410 {
00411 if ($this->lazy) {
00412 foreach ($this->list as $id) {
00413 $this->clones[$id] = $id;
00414 }
00415 } else {
00416 foreach ($this->list as $object) {
00417
00418 if ($id = $object->getId())
00419 $this->clones[$id] = clone $object;
00420 }
00421 }
00422
00423 return $this;
00424 }
00425 }
00426 ?>