# CustomizableDaoSynchronizer.class.php

Go to the documentation of this file.

    00001 <?php
    00002 /***************************************************************************
    00003  *   Copyright (C) 2009 by Ivan Y. Khvostishkov                            *
    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
    00015     class CustomizableDaoSynchronizer
    00016     {
    00017         protected $dryRun           = false;
    00018         protected $reallyDelete     = false;
    00019
    00020         protected $master           = null;
    00021         protected $slave            = null;
    00022
    00023         private $masterProjection   = null;
    00024         private $slaveProjection    = null;
    00025
    00026         private $masterKeyProperty  = 'id';
    00027         private $slaveKeyProperty   = 'id';
    00028
    00029         private $totalUpdated       = 0;
    00030         private $totalInserted      = 0;
    00031         private $totalDeleted       = 0;
    00032
    00036         public static function create()
    00037         {
    00038             return new self;
    00039         }
    00040
    00044         public function setDryRun($dryRun)
    00045         {
    00046             $this->dryRun = $dryRun;
    00047
    00048             return $this;
    00049         }
    00050
    00051         public function isDryRun()
    00052         {
    00053             return $this->dryRun;
    00054         }
    00055
    00059         public function setReallyDelete($reallyDelete)
    00060         {
    00061             $this->reallyDelete = $reallyDelete;
    00062
    00063             return $this;
    00064         }
    00065
    00066         public function isReallyDelete()
    00067         {
    00068             return $this->reallyDelete;
    00069         }
    00070
    00074         public function setMaster(GenericDAO $master)
    00075         {
    00076             $this->master = $master;
    00077
    00078             return $this;
    00079         }
    00080
    00084         public function getMaster()
    00085         {
    00086             return $this->master;
    00087         }
    00088
    00092         public function setSlave(GenericDAO $slave)
    00093         {
    00094             $this->slave = $slave;
    00095
    00096             return $this;
    00097         }
    00098
    00102         public function getSlave()
    00103         {
    00104             return $this->slave;
    00105         }
    00106
    00110         public function setMasterKeyProperty($masterKeyProperty)
    00111         {
    00112             $this->masterKeyProperty = $masterKeyProperty;
    00113
    00114             return $this;
    00115         }
    00116
    00117         public function getMasterKeyProperty()
    00118         {
    00119             return $this->masterKeyProperty;
    00120         }
    00121
    00125         public function setSlaveKeyProperty($slaveKeyProperty)
    00126         {
    00127             $this->slaveKeyProperty = $slaveKeyProperty;
    00128
    00129             return $this;
    00130         }
    00131
    00132         public function getSlaveKeyProperty()
    00133         {
    00134             return $this->slaveKeyProperty;
    00135         }
    00136
    00140         public function setMasterProjection(ObjectProjection $masterProjection)
    00141         {
    00142             $this->masterProjection = $masterProjection;
    00143
    00144             return $this;
    00145         }
    00146
    00150         public function getMasterProjection()
    00151         {
    00152             return $this->masterProjection;
    00153         }
    00154
    00158         public function setSlaveProjection(ObjectProjection $slaveProjection)
    00159         {
    00160             $this->slaveProjection = $slaveProjection;
    00161
    00162             return $this;
    00163         }
    00164
    00168         public function getSlaveProjection()
    00169         {
    00170             return $this->slaveProjection;
    00171         }
    00172
    00176         public function run()
    00177         {
    00178             $masterIterator = new DaoIterator();
    00179             $slaveIterator = new DaoIterator();
    00180
    00181             $masterIterator->setDao($this->master);
    00182             $slaveIterator->setDao($this->slave);
    00183
    00184             if ($this->masterKeyProperty)
    00185                 $masterIterator->setKeyProperty($this->masterKeyProperty);
    00186
    00187             if ($this->slaveKeyProperty)
    00188                 $slaveIterator->setKeyProperty($this->slaveKeyProperty);
    00189
    00190             if ($this->masterProjection)
    00191                 $masterIterator->setProjection($this->masterProjection);
    00192
    00193             if ($this->slaveProjection)
    00194                 $slaveIterator->setProjection($this->slaveProjection);
    00195
    00196             $this->totalDeleted = 0;
    00197             $this->totalInserted = 0;
    00198             $this->totalUpdated = 0;
    00199
    00200             while ($masterIterator->valid() || $slaveIterator->valid()) {
    00201                 $masterObject = $masterIterator->current();
    00202                 $slaveObject = $slaveIterator->current();
    00203
    00204                 $masterObject = $this->convertMasterObjectToSlave($masterObject);
    00205
    00206                 $masterGetter = 'get'.ucfirst($this->masterKeyProperty);
    00207                 $slaveGetter = 'get'.ucfirst($this->slaveKeyProperty);
    00208
    00209                 if (
    00210                     $masterObject && $slaveObject
    00211                     && (
    00212                         $masterObject->$masterGetter()
    00213                             == $slaveObject->$slaveGetter()
    00214                     )
    00215                 ) {
    00216                     if ($this->sync($slaveObject, $masterObject))
    00217                         $this->totalUpdated++;
    00218
    00219                     $masterIterator->next();
    00220                     $slaveIterator->next();
    00221                 } elseif (
    00222                     !$masterObject
    00223                     || (
    00224                         $slaveObject
    00225                         && $this->compareKeys(
    00226                             $masterObject->$masterGetter(),
    00227                             $slaveObject->$slaveGetter()
    00228                         ) > 0
    00229                     )
    00230                 ) {
    00231                     if ($this->delete($slaveObject))
    00232                         $this->totalDeleted++;
    00233
    00234                     $slaveIterator->next();
    00235                 } elseif (
    00236                     !$slaveObject
    00237                     || (
    00238                         $masterObject
    00239                         && $this->compareKeys(
    00240                             $masterObject->$masterGetter(),
    00241                             $slaveObject->$slaveGetter()
    00242                         ) < 0
    00243                     )
    00244                 ) {
    00245                     if ($this->insert($masterObject))
    00246                         $this->totalInserted++;
    00247
    00248                     $masterIterator->next();
    00249
    00250                 } else {
    00251                     Assert::isUnreachable('how did you get here?');
    00252                 }
    00253             }
    00254
    00255             return $this;
    00256         }
    00257
    00258         public function getTotalInserted()
    00259         {
    00260             return $this->totalInserted;
    00261         }
    00262
    00263         public function getTotalDeleted()
    00264         {
    00265             return $this->totalDeleted;
    00266         }
    00267
    00268         public function getTotalUpdated()
    00269         {
    00270             return $this->totalUpdated;
    00271         }
    00272
    00273         protected function sync($old, $object)
    00274         {
    00275             if (!$this->dryRun)
    00276                 $this->slave->merge($object);
    00277
    00278             return true;
    00279         }
    00280
    00281         protected function delete($slaveObject)
    00282         {
    00283             $slaveGetter = 'get'.ucfirst($this->slaveKeyProperty);
    00284
    00285             Assert::methodExists($slaveObject, $slaveGetter);
    00286
    00287             if (!$this->dryRun && $this->reallyDelete)
    00288                 $this->slave->dropById($slaveObject->$slaveGetter());
    00289
    00290             return true;
    00291         }
    00292
    00293         protected function insert($masterObject)
    00294         {
    00295             if (!$this->dryRun)
    00296                 $this->slave->import($masterObject);
    00297
    00298             return true;
    00299         }
    00300
    00301         protected function compareKeys($min, $sub)
    00302         {
    00303             if ($min > $sub)
    00304                 return 1;
    00305             elseif ($min < $sub)
    00306                 return -1;
    00307
    00308             return 0;
    00309         }
    00310
    00311         private function convertMasterObjectToSlave($masterObject)
    00312         {
    00313             if (
    00314                 $masterObject
    00315                 && (
    00316                     call_user_func(
    00317                         array($this->slave->getObjectName(), 'create')
    00318                     )
    00319                     instanceof SynchronizableObject
    00320                 )
    00321             )
    00322                 $masterObject = call_user_func(
    00323                     array(
    00324                         $this->slave->getObjectName(),
    00325                         'createFromMasterObject'
    00326                     ),
    00327                     $masterObject
    00328                 );
    00329
    00330             return $masterObject;
    00331         }
    00332     }
    00333 ?>