CommonDaoWorker.class.php

Go to the documentation of this file.
00001 <?php
00002 /****************************************************************************
00003  *   Copyright (C) 2004-2008 by Konstantin V. Arkhipov, Anton E. Lebedevich *
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 
00019     class CommonDaoWorker extends BaseDaoWorker
00020     {
00022 
00023         public function getById($id, $expires = Cache::EXPIRES_MEDIUM)
00024         {
00025             if (
00026                 ($expires !== Cache::DO_NOT_CACHE)
00027                 && ($object = $this->getCachedById($id))
00028             ) {
00029                 if ($object === Cache::NOT_FOUND)
00030                     throw new CachedObjectNotFoundException();
00031                 
00032                 return $this->dao->completeObject($object);
00033             } else {
00034                 $query =
00035                     $this->dao->
00036                         makeSelectHead()->
00037                         andWhere(
00038                             Expression::eq(
00039                                 DBField::create(
00040                                     $this->dao->getIdName(),
00041                                     $this->dao->getTable()
00042                                 ),
00043                                 $id
00044                             )
00045                         );
00046                 
00047                 if ($expires === Cache::DO_NOT_CACHE) {
00048                     $object = $this->fetchObject($query);
00049                 } else {
00050                     $object = $this->cachedFetchObject($query, $expires, true);
00051                 }
00052                 
00053                 if ($object) {
00054                     return $object;
00055                 } else {
00056                     throw new ObjectNotFoundException(
00057                         "there is no such object for '".$this->dao->getObjectName()
00058                         .(
00059                             defined('__LOCAL_DEBUG__')
00060                                 ?
00061                                     "' with query == "
00062                                     .$query->toDialectString(
00063                                         DBPool::me()->getByDao($this->dao)->
00064                                             getDialect()
00065                                     )
00066                                 : null
00067                         )
00068                     );
00069                 }
00070             }
00071         }
00072         
00073         public function getByLogic(
00074             LogicalObject $logic, $expires = Cache::DO_NOT_CACHE
00075         )
00076         {
00077             return
00078                 $this->getByQuery(
00079                     $this->dao->makeSelectHead()->andWhere($logic), $expires
00080                 );
00081         }
00082         
00083         public function getByQuery(
00084             SelectQuery $query, $expires = Cache::DO_NOT_CACHE
00085         )
00086         {
00087             if (
00088                 ($expires !== Cache::DO_NOT_CACHE)
00089                 && ($object = $this->getCachedByQuery($query))
00090             ) {
00091                 if ($object === Cache::NOT_FOUND)
00092                     throw new CachedObjectNotFoundException();
00093                 
00094                 return $this->dao->completeObject($object);
00095             } else {
00096                 if ($expires === Cache::DO_NOT_CACHE)
00097                     $object = $this->fetchObject($query);
00098                 else
00099                     $object = $this->cachedFetchObject($query, $expires, false);
00100                 
00101                 if ($object)
00102                     return $object;
00103                 else
00104                     throw new ObjectNotFoundException(
00105                         "there is no such object for '".$this->dao->getObjectName()
00106                             .(
00107                                 defined('__LOCAL_DEBUG__')
00108                                     ?
00109                                         "' with query == "
00110                                         .$query->toDialectString(
00111                                             DBPool::me()->getByDao($this->dao)->
00112                                                 getDialect()
00113                                         )
00114                                     : null
00115                             )
00116                     );
00117             }
00118         }
00119         
00120         public function getCustom(
00121             SelectQuery $query, $expires = Cache::DO_NOT_CACHE
00122         )
00123         {
00124             if ($query->getLimit() > 1)
00125                 throw new WrongArgumentException(
00126                     'can not handle non-single row queries'
00127                 );
00128             
00129             $db = DBPool::getByDao($this->dao);
00130             
00131             if (
00132                 ($expires !== Cache::DO_NOT_CACHE)
00133                 && ($object = $this->getCachedByQuery($query))
00134             ) {
00135                 if ($object === Cache::NOT_FOUND)
00136                     throw new CachedObjectNotFoundException();
00137                 
00138                 return $object;
00139                 
00140             } elseif ($object = $db->queryRow($query)) {
00141                 if ($expires === Cache::DO_NOT_CACHE)
00142                     return $object;
00143                 else
00144                     return $this->cacheByQuery($query, $object, $expires);
00145             } else {
00146                 throw new ObjectNotFoundException(
00147                     "zero"
00148                     .(
00149                         defined('__LOCAL_DEBUG__')
00150                             ?
00151                                 "for query == "
00152                                 .$query->toDialectString(
00153                                     DBPool::me()->getByDao($this->dao)->
00154                                         getDialect()
00155                                 )
00156                             : null
00157                     )
00158                 );
00159             }
00160         }
00162         
00164 
00165         public function getListByIds(
00166             array $ids,
00167             $expires = Cache::EXPIRES_MEDIUM
00168         )
00169         {
00170             $list = array();
00171             
00172             // dupes, if any, will be resolved later @ ArrayUtils::regularizeList
00173             $ids = array_unique($ids);
00174             
00175             if ($expires !== Cache::DO_NOT_CACHE) {
00176                 $toFetch = array();
00177                 $prefixed = array();
00178                 
00179                 foreach ($ids as $id)
00180                     $prefixed[$id] = $this->makeIdKey($id);
00181                 
00182                 if (
00183                     $cachedList
00184                         = Cache::me()->mark($this->className)->getList($prefixed)
00185                 ) {
00186                     $proto = $this->dao->getProtoClass();
00187                     
00188                     $proto->beginPrefetch();
00189                     
00190                     foreach ($cachedList as $cached) {
00191                         if ($cached && ($cached !== Cache::NOT_FOUND)) {
00192                             $list[] = $this->dao->completeObject($cached);
00193                             
00194                             unset($prefixed[$cached->getId()]);
00195                         }
00196                     }
00197                     
00198                     $proto->endPrefetch($list);
00199                 }
00200                 
00201                 $toFetch += array_keys($prefixed);
00202                 
00203                 if ($toFetch) {
00204                     try {
00205                         $list =
00206                             array_merge(
00207                                 $list,
00208                                 $this->getListByLogic(
00209                                     Expression::in(
00210                                         new DBField(
00211                                             $this->dao->getIdName(),
00212                                             $this->dao->getTable()
00213                                         ),
00214                                         $toFetch
00215                                     ),
00216                                     Cache::DO_NOT_CACHE
00217                                 )
00218                             );
00219                     } catch (ObjectNotFoundException $e) {
00220                         // nothing to fetch
00221                     }
00222                 }
00223             } elseif (count($ids)) {
00224                 try {
00225                     $list =
00226                         $this->getListByLogic(
00227                             Expression::in(
00228                                 new DBField(
00229                                     $this->dao->getIdName(),
00230                                     $this->dao->getTable()
00231                                 ),
00232                                 $ids
00233                             ),
00234                             Cache::DO_NOT_CACHE
00235                         );
00236                 } catch (ObjectNotFoundException $e) {/*_*/}
00237             }
00238             
00239             return $list;
00240         }
00241         
00242         public function getListByQuery(
00243             SelectQuery $query, $expires = Cache::DO_NOT_CACHE
00244         )
00245         {
00246             if (
00247                 ($expires !== Cache::DO_NOT_CACHE)
00248                 && ($list = $this->getCachedByQuery($query))
00249             ) {
00250                 if ($list === Cache::NOT_FOUND)
00251                     throw new CachedObjectNotFoundException();
00252                 
00253                 return $list;
00254             } elseif ($list = $this->fetchList($query)) {
00255                 if (Cache::DO_NOT_CACHE === $expires) {
00256                     return $list;
00257                 } else {
00258                     return $this->cacheByQuery($query, $list, $expires);
00259                 }
00260             } else {
00261                 throw new ObjectNotFoundException(
00262                     "empty list"
00263                     .(
00264                         defined('__LOCAL_DEBUG__')
00265                             ?
00266                                 " for such query - "
00267                                 .$query->toDialectString(
00268                                     DBPool::me()->getByDao($this->dao)->
00269                                         getDialect()
00270                                 )
00271                             : null
00272                     )
00273                 );
00274             }
00275         }
00276         
00277         public function getListByLogic(
00278             LogicalObject $logic, $expires = Cache::DO_NOT_CACHE
00279         )
00280         {
00281             return
00282                 $this->getListByQuery(
00283                     $this->dao->makeSelectHead()->andWhere($logic), $expires
00284                 );
00285         }
00286         
00287         public function getPlainList($expires = Cache::EXPIRES_MEDIUM)
00288         {
00289             return $this->getListByQuery(
00290                 $this->dao->makeSelectHead(), $expires
00291             );
00292         }
00293         
00294         public function getTotalCount($expires = Cache::DO_NOT_CACHE)
00295         {
00296             $count = $this->getCustom(
00297                 $this->dao->makeTotalCountQuery(), $expires
00298             );
00299             
00300             return current($count);
00301         }
00303         
00305 
00306         public function getCustomList(
00307             SelectQuery $query, $expires = Cache::DO_NOT_CACHE
00308         )
00309         {
00310             if (
00311                 ($expires !== Cache::DO_NOT_CACHE)
00312                 && ($list = $this->getCachedByQuery($query))
00313             ) {
00314                 if ($list === Cache::NOT_FOUND)
00315                     throw new CachedObjectNotFoundException();
00316                 
00317                 return $list;
00318             } elseif ($list = DBPool::getByDao($this->dao)->querySet($query)) {
00319                 if (Cache::DO_NOT_CACHE === $expires) {
00320                     return $list;
00321                 } else {
00322                     return $this->cacheByQuery($query, $list, $expires);
00323                 }
00324             } else {
00325                 throw new ObjectNotFoundException(
00326                     "empty list"
00327                     .(
00328                         defined('__LOCAL_DEBUG__')
00329                             ?
00330                                 " for such query - "
00331                                 .$query->toDialectString(
00332                                     DBPool::me()->getByDao($this->dao)->
00333                                         getDialect()
00334                                 )
00335                             : null
00336                     )
00337                 );
00338             }
00339         }
00340         
00341         public function getCustomRowList(
00342             SelectQuery $query, $expires = Cache::DO_NOT_CACHE
00343         )
00344         {
00345             if ($query->getFieldsCount() !== 1)
00346                 throw new WrongArgumentException(
00347                     'you should select only one row when using this method'
00348                 );
00349             
00350             if (
00351                 ($expires !== Cache::DO_NOT_CACHE)
00352                 && ($list = $this->getCachedByQuery($query))
00353             ) {
00354                 if ($list === Cache::NOT_FOUND)
00355                     throw new CachedObjectNotFoundException();
00356                 
00357                 return $list;
00358             } elseif ($list = DBPool::getByDao($this->dao)->queryColumn($query)) {
00359                 if (Cache::DO_NOT_CACHE === $expires) {
00360                     return $list;
00361                 } else {
00362                     return $this->cacheByQuery($query, $list, $expires);
00363                 }
00364             } else {
00365                 throw new ObjectNotFoundException(
00366                     "empty list"
00367                     .(
00368                         defined('__LOCAL_DEBUG__')
00369                             ?
00370                                 " for such query - "
00371                                 .$query->toDialectString(
00372                                     DBPool::me()->getByDao($this->dao)->
00373                                         getDialect()
00374                                 )
00375                             : null
00376                     )
00377                 );
00378             }
00379         }
00381         
00383 
00384         public function getQueryResult(
00385             SelectQuery $query, $expires = Cache::DO_NOT_CACHE
00386         )
00387         {
00388             if (
00389                 ($expires !== Cache::DO_NOT_CACHE)
00390                 && ($list = $this->getCachedByQuery($query))
00391             ) {
00392                 return $list;
00393             } else {
00394                 $list = $this->fetchList($query);
00395                 
00396                 $count = clone $query;
00397                 
00398                 $count =
00399                     DBPool::getByDao($this->dao)->queryRow(
00400                         $count->dropFields()->dropOrder()->limit(null, null)->
00401                         get(SQLFunction::create('COUNT', '*')->setAlias('count'))
00402                     );
00403                 
00404                 return
00405                     $this->cacheByQuery(
00406                         $query,
00407                         
00408                         $list
00409                             ?
00410                                 QueryResult::create()->
00411                                 setList($list)->
00412                                 setCount($count['count'])->
00413                                 setQuery($query)
00414                             :
00415                                 QueryResult::create(),
00416                         
00417                         $expires
00418                     );
00419             }
00420         }
00422         
00424 
00425         protected function cacheById(
00426             Identifiable $object, $expires = Cache::EXPIRES_MEDIUM
00427         )
00428         {
00429             if ($expires !== Cache::DO_NOT_CACHE) {
00430                 
00431                 Cache::me()->mark($this->className)->
00432                     add(
00433                         $this->makeIdKey($object->getId()),
00434                         $object,
00435                         $expires
00436                     );
00437             }
00438             
00439             return $object;
00440         }
00441         
00442         protected function cacheByQuery(
00443             SelectQuery $query,
00444             /* Identifiable */ $object,
00445             $expires = Cache::DO_NOT_CACHE
00446         )
00447         {
00448             if ($expires !== Cache::DO_NOT_CACHE) {
00449             
00450                 Cache::me()->mark($this->className)->
00451                     add(
00452                         $this->makeQueryKey($query, self::SUFFIX_QUERY),
00453                         $object,
00454                         $expires
00455                     );
00456             }
00457             
00458             return $object;
00459         }
00460         
00461         protected function cacheListByQuery(
00462             SelectQuery $query,
00463             /* array || Cache::NOT_FOUND */ $array
00464         )
00465         {
00466             throw new UnimplementedFeatureException();
00467         }
00469         
00471 
00472         public function dropById($id)
00473         {
00474             $result = parent::dropById($id);
00475             
00476             $this->dao->uncacheLists();
00477             
00478             return $result;
00479         }
00481         
00483 
00484         public function uncacheById($id)
00485         {
00486             $this->dao->uncacheLists();
00487             
00488             return parent::uncacheById($id);
00489         }
00490         
00491         public function uncacheByIds($ids)
00492         {
00493             foreach ($ids as $id)
00494                 parent::uncacheById($id);
00495             
00496             return $this->dao->uncacheLists();
00497         }
00498         
00499         // quite useless here
00500         public function uncacheLists()
00501         {
00502             // wipes getPlainList result, if any
00503             return $this->uncacheByQuery($this->dao->makeSelectHead());
00504         }
00506     }
00507 ?>