onPHP

main/UnifiedContainer/UnifiedContainer.class.php Source File

 

UnifiedContainer.class.php

Go to the documentation of this file.
00001 <?php
00002 /***************************************************************************
00003  *   Copyright (C) 2005-2008 by Konstantin V. Arkhipov                     *
00004  *                                                                         *
00005  *   This program is free software; you can redistribute it and/or modify  *
00006  *   it under the terms of the GNU Lesser General Public License as        *
00007  *   published by the Free Software Foundation; either version 3 of the    *
00008  *   License, or (at your option) any later version.                       *
00009  *                                                                         *
00010  ***************************************************************************/
00011 /* $Id: UnifiedContainer.class.php 5209 2008-06-17 12:39:25Z voxus $ */
00012 
00013 /*
00014     UnifiedContainer:
00015 
00016         child's and parent's field names:
00017             abstract public function getChildIdField()
00018             abstract public function getParentIdField()
00019 
00020         all we need from outer world:
00021             public function __construct(
00022                 Identifiable $parent, UnifiedContainer $dao, $lazy = true
00023             )
00024 
00025         if you want to apply Criteria's "filter":
00026             public function setCriteria(Criteria $criteria)
00027 
00028         first you should fetch whatever you want:
00029             public function fetch()
00030 
00031         then you can get it:
00032             public function getList()
00033         
00034         set you modified list:
00035             public function setList($list)
00036 
00037         finally, sync fetched data and stored one:
00038             public function save()
00039 
00040     OneToManyLinked <- UnifiedContainer:
00041 
00042         indicates whether child can be free (parent_id nullable):
00043             protected function isUnlinkable()
00044 
00045     ManyToManyLinked <- UnifiedContainer:
00046 
00047         helper's table name:
00048             abstract public function getHelperTable()
00049 
00050         id field name at parent's primary table:
00051             protected function getParentTableIdField()
00052 */
00053 
00061     abstract class UnifiedContainer
00062     {
00063         protected $worker   = null;
00064         protected $parent   = null;
00065         
00066         protected $dao      = null;
00067         
00068         protected $lazy     = true;
00069         protected $fetched  = false;
00070 
00071         protected $list     = array();
00072         protected $clones   = array();
00073         
00074         // sleep state
00075         protected $workerClass  = null;
00076         protected $daoClass     = null;
00077         
00078         abstract public function getParentIdField();
00079         abstract public function getChildIdField();
00080         
00081         public function __construct(
00082             Identifiable $parent, GenericDAO $dao, $lazy = true
00083         )
00084         {
00085             Assert::isBoolean($lazy);
00086             
00087             $this->parent   = $parent;
00088             $this->lazy     = $lazy;
00089             $this->dao      = $dao;
00090             
00091             Assert::isInstance($dao->getObjectName(), 'Identifiable');
00092         }
00093         
00094         public function __sleep()
00095         {
00096             $this->daoClass = get_class($this->dao);
00097             $this->workerClass = get_class($this->worker);
00098             return array('workerClass', 'daoClass', 'parent', 'lazy');
00099         }
00100         
00101         public function __wakeup()
00102         {
00103             $this->dao = Singleton::getInstance($this->daoClass);
00104             $this->worker = new $this->workerClass($this);
00105         }
00106         
00107         public function getParentObject()
00108         {
00109             return $this->parent;
00110         }
00111         
00115         public function getDao()
00116         {
00117             return $this->dao;
00118         }
00119         
00120         public function isLazy()
00121         {
00122             return $this->lazy;
00123         }
00124         
00125         public function isFetched()
00126         {
00127             return $this->fetched;
00128         }
00129         
00134         public function setCriteria(Criteria $criteria)
00135         {
00136             Assert::isTrue(
00137                 $criteria->getDao() === null
00138                 || (
00139                     $criteria->getDao() === $this->dao
00140                 ),
00141                 "criteria's dao doesn't match container's one"
00142             );
00143             
00144             if (!$criteria->getDao())
00145                 $criteria->setDao($this->dao);
00146             
00147             $this->worker->setCriteria($criteria);
00148             
00149             return $this;
00150         }
00151         
00155         public function getCriteria()
00156         {
00157             return $this->worker->getCriteria();
00158         }
00159         
00164         public function setList($list)
00165         {
00166             Assert::isArray($list);
00167             
00168             $this->list = $list;
00169             
00170             return $this;
00171         }
00172         
00176         public function mergeList(array $list)
00177         {
00178             Assert::isArray($list);
00179             
00180             return $this->importList($list);
00181         }
00182 
00183         public function getList()
00184         {
00185             if (!$this->list && !$this->isFetched())
00186                 $this->fetch();
00187             
00188             return $this->list;
00189         }
00190         
00191         public function getCount()
00192         {
00193             if (!$this->isFetched() && $this->parent->getId()) {
00194                 $row = $this->dao->getCustom($this->worker->makeCountQuery());
00195                 
00196                 return $row['count'];
00197             }
00198             
00199             return count($this->list);
00200         }
00201         
00206         public function fetch()
00207         {
00208             if (!$this->parent->getId())
00209                 throw new WrongStateException(
00210                     'save parent object first'
00211                 );
00212             
00213             try {
00214                 $this->fetchList();
00215             } catch (ObjectNotFoundException $e) {
00216                 // yummy
00217             }
00218             
00219             $this->fetched = true;
00220             
00221             return $this;
00222         }
00223         
00228         public function save()
00229         {
00230             Assert::isArray(
00231                 $this->list,
00232                 "that's not an array :-/"
00233             );
00234 
00235             if (!$this->fetched)
00236                 throw new WrongStateException(
00237                     'do not want to save non-fetched collection'
00238                 );
00239             
00240             $list   = $this->list;
00241             $clones = $this->clones;
00242             
00243             $ids = $insert = $delete = $update = array();
00244             
00245             if ($this->lazy) {
00246                 foreach ($list as $id) {
00247                     if (!isset($clones[$id]))
00248                         $insert[] = $ids[$id] = $id;
00249                     else
00250                         $ids[$id] = $id;
00251                 }
00252                 
00253                 foreach ($clones as $id) {
00254                     if (!isset($ids[$id]))
00255                         $delete[] = $id;
00256                 }
00257             } else {
00258                 foreach ($list as $object) {
00259                     $id = $object->getId();
00260                     
00261                     if (null === $id) {
00262                         $insert[] = $object;
00263                     } elseif (
00264                         isset($clones[$id])
00265                         && (
00266                             ($object !== $clones[$id])
00267                             || ($object != $clones[$id])
00268                         )
00269                     ) {
00270                         $update[] = $object;
00271                     } elseif (!isset($clones[$id])) {
00272                         $insert[] = $object;
00273                     }
00274                     
00275                     if (null !== $id)
00276                         $ids[$id] = $object;
00277                 }
00278                 
00279                 foreach ($clones as $id => $object) {
00280                     if (!isset($ids[$id]))
00281                         $delete[] = $object;
00282                 }
00283             }
00284 
00285             $db = DBPool::getByDao($this->getDao());
00286             
00287             if (!$db->inTransaction()) {
00288                 $outerQueue = $db->isQueueActive();
00289                 
00290                 if (!$outerQueue)
00291                     $db->queueStart();
00292                 
00293                 $db->begin();
00294                 
00295                 try {
00296                     $this->worker->sync($insert, $update, $delete);
00297                     
00298                     $db->commit();
00299                     
00300                     if (!$outerQueue)
00301                         $db->queueFlush();
00302                 } catch (DatabaseException $e) {
00303                     if (!$outerQueue)
00304                         $db->queueDrop()->queueStop();
00305                     
00306                     $db->rollback();
00307                     
00308                     throw $e;
00309                 }
00310             } else {
00311                 $this->worker->sync($insert, $update, $delete);
00312             }
00313             
00314             $this->clones = array();
00315             $this->syncClones();
00316             $this->dao->uncacheLists();
00317 
00318             return $this;
00319         }
00320 
00324         public function clean()
00325         {
00326             $this->list = $this->clones = array();
00327             
00328             $this->fetched = false;
00329             
00330             return $this;
00331         }
00332         
00336         public function dropList()
00337         {
00338             $this->worker->dropList();
00339             
00340             $this->clean();
00341             
00342             return $this;
00343         }
00344         
00345         /* void */ public static function destroy(UnifiedContainer $container)
00346         {
00347             unset($container->worker, $container);
00348         }
00349         
00350         protected function fetchList()
00351         {
00352             $query = $this->worker->makeFetchQuery();
00353             
00354             if ($this->lazy)
00355                 $list = $this->dao->getCustomRowList($query);
00356             else
00357                 $list = $this->dao->getListByQuery($query);
00358             
00359             $this->list = array();
00360             
00361             return $this->importList($list);
00362         }
00363         
00367         private function importList(array $list)
00368         {
00369             if ($this->lazy) {
00370                 foreach ($list as $id)
00371                     $this->list[$id] = $id;
00372             } else {
00373                 $this->list = array_merge($this->list, $list);
00374             }
00375 
00376             $this->syncClones();
00377             
00378             $this->fetched = true;
00379             
00380             return $this;
00381         }
00382     
00386         private function syncClones()
00387         {
00388             if ($this->lazy) {
00389                 foreach ($this->list as $id) {
00390                     $this->clones[$id] = $id;
00391                 }
00392             } else {
00393                 foreach ($this->list as $object) {
00394                     // don't track unsaved objects
00395                     if ($id = $object->getId())
00396                         $this->clones[$id] = clone $object;
00397                 }
00398             }
00399             
00400             return $this;
00401         }
00402     }
00403 ?>

generated by doxygen-1.5.5
for onPHP at Tue Jun 17 16:42:55 2008