# 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 ?>