onPHP

main/Criteria/Criteria.class.php Source File

 

Criteria.class.php

Go to the documentation of this file.
00001 <?php
00002 /****************************************************************************
00003  *   Copyright (C) 2006-2007 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 General Public License as published by   *
00007  *   the Free Software Foundation; either version 2 of the License, or      *
00008  *   (at your option) any later version.                                    *
00009  *                                                                          *
00010  ****************************************************************************/
00011 /* $Id: Criteria.class.php 3202 2007-04-30 19:01:43Z voxus $ */
00012 
00018     final class Criteria implements Stringable, DialectString
00019     {
00020         private $dao        = null;
00021         private $daoClass   = null;
00022         private $logic      = null;
00023         private $order      = null;
00024         private $strategy   = null;
00025         private $projection = null;
00026         
00027         private $distinct   = false;
00028         
00029         private $limit  = null;
00030         private $offset = null;
00031         
00032         private $collections = array();
00033         
00034         // dao-like behaviour: will throw ObjectNotFoundException when 'false'
00035         private $silent = true;
00036         
00040         public static function create(/* StorableDAO */ $dao = null)
00041         {
00042             return new self($dao);
00043         }
00044         
00045         public function __construct(/* StorableDAO */ $dao = null)
00046         {
00047             if ($dao)
00048                 Assert::isTrue($dao instanceof StorableDAO);
00049             
00050             $this->dao = $dao;
00051             $this->logic = Expression::andBlock();
00052             $this->order = new OrderChain();
00053             
00054             if ($dao instanceof ComplexBuilderDAO)
00055                 $this->strategy = FetchStrategy::join();
00056             else
00057                 $this->strategy = FetchStrategy::cascade();
00058         }
00059         
00060         public function __clone()
00061         {
00062             $this->logic = clone $this->logic;
00063             $this->order = clone $this->order;
00064         }
00065         
00066         public function __sleep()
00067         {
00068             $this->daoClass = get_class($this->dao);
00069             
00070             $vars = get_object_vars($this);
00071             unset($vars['dao']);
00072             return array_keys($vars);
00073         }
00074         
00075         public function __wakeup()
00076         {
00077             $this->dao = Singleton::getInstance($this->daoClass);
00078         }
00079         
00083         public function getDao()
00084         {
00085             return $this->dao;
00086         }
00087         
00091         public function setDao(StorableDAO $dao)
00092         {
00093             if ($this->strategy->getId() == FetchStrategy::JOIN)
00094                 Assert::isTrue(
00095                     $dao instanceof ComplexBuilderDAO,
00096                     'your DAO does not support join fetch strategy'
00097                 );
00098             
00099             $this->dao = $dao;
00100             
00101             return $this;
00102         }
00103         
00107         public function getLogic()
00108         {
00109             return $this->logic;
00110         }
00111         
00115         public function add(LogicalObject $logic)
00116         {
00117             $this->logic->expAnd($logic);
00118             
00119             return $this;
00120         }
00121         
00125         public function getOrder()
00126         {
00127             return $this->order;
00128         }
00129         
00133         public function addOrder(/* MapableObject */ $order)
00134         {
00135             if (!$order instanceof MappableObject)
00136                 $order = new OrderBy($order);
00137             
00138             $this->order->add($order);
00139             
00140             return $this;
00141         }
00142         
00146         public function dropOrder()
00147         {
00148             $this->order = new OrderChain();
00149             
00150             return $this;
00151         }
00152         
00153         public function getLimit()
00154         {
00155             return $this->limit;
00156         }
00157         
00161         public function setLimit($limit)
00162         {
00163             $this->limit = $limit;
00164             
00165             return $this;
00166         }
00167         
00168         public function getOffset()
00169         {
00170             return $this->offset;
00171         }
00172         
00176         public function setOffset($offset)
00177         {
00178             $this->offset = $offset;
00179             
00180             return $this;
00181         }
00182         
00186         public function getFetchStrategy()
00187         {
00188             return $this->strategy;
00189         }
00190         
00194         public function setFetchStrategy(FetchStrategy $strategy)
00195         {
00196             if (
00197                 $this->dao
00198                 && ($strategy->getId() == FetchStrategy::JOIN)
00199             ) {
00200                 Assert::isTrue(
00201                     $this->dao instanceof ComplexBuilderDAO,
00202                     'your DAO does not support join fetch strategy'
00203                 );
00204             }
00205             
00206             $this->strategy = $strategy;
00207             
00208             return $this;
00209         }
00210         
00214         public function setProjection(ObjectProjection $chain)
00215         {
00216             $this->projection = $chain;
00217             
00218             return $this;
00219         }
00220         
00224         public function getProjection()
00225         {
00226             return $this->projection;
00227         }
00228         
00232         public function dropProjection()
00233         {
00234             $this->projection = null;
00235             
00236             return $this;
00237         }
00238         
00242         public function setDistinct($orly = true)
00243         {
00244             $this->distinct = ($orly === true);
00245             
00246             return $this;
00247         }
00248         
00249         public function isDistinct()
00250         {
00251             return $this->distinct;
00252         }
00253         
00254         public function isSilent()
00255         {
00256             return $this->silent;
00257         }
00258         
00262         public function setSilent($silent)
00263         {
00264             Assert::isBoolean($silent);
00265             
00266             $this->silent = $silent;
00267             
00268             return $this;
00269         }
00270         
00274         public function fetchCollection(
00275             $path, // to collection
00276             $lazy = false, // fetching mode
00277             /* Criteria */ $criteria = null
00278         )
00279         {
00280             Assert::isBoolean($lazy);
00281             Assert::isTrue(
00282                 ($criteria === null)
00283                 || ($criteria instanceof Criteria)
00284             );
00285             
00286             $this->collections[$path]['lazy'] = $lazy;
00287             $this->collections[$path]['criteria'] = $criteria;
00288             $this->collections[$path]['propertyPath']
00289                 = new PropertyPath($this->dao->getObjectName(), $path);
00290             
00291             return $this;
00292         }
00293         
00294         public function get()
00295         {
00296             try {
00297                 $list = array($this->dao->getByQuery($this->toSelectQuery()));
00298             } catch (ObjectNotFoundException $e) {
00299                 if (!$this->isSilent())
00300                     throw $e;
00301                 
00302                 return null;
00303             }
00304             
00305             if (!$this->collections)
00306                 return reset($list);
00307             
00308             $list = $this->dao->fetchCollections($this->collections, $list);
00309             
00310             return reset($list);
00311         }
00312         
00313         public function getList()
00314         {
00315             try {
00316                 $list = $this->dao->getListByQuery($this->toSelectQuery());
00317             } catch (ObjectNotFoundException $e) {
00318                 if (!$this->isSilent())
00319                     throw $e;
00320                 
00321                 return array();
00322             }
00323             
00324             if (!$this->collections)
00325                 return $list;
00326             
00327             return $this->dao->fetchCollections($this->collections, $list);
00328         }
00329         
00333         public function getResult()
00334         {
00335             try {
00336                 $result = $this->dao->getQueryResult($this->toSelectQuery());
00337             } catch (ObjectNotFoundException $e) {
00338                 if (!$this->isSilent())
00339                     throw $e;
00340                 
00341                 return new QueryResult();
00342             }
00343             
00344             if (!$this->collections)
00345                 return $result;
00346             
00347             return $result->setList(
00348                 $this->dao->fetchCollections(
00349                     $this->collections,
00350                     $result->getList()
00351                 )
00352             );
00353         }
00354         
00355         public function getCustom()
00356         {
00357             try {
00358                 return $this->dao->getCustom($this->toSelectQuery());
00359             } catch (ObjectNotFoundException $e) {
00360                 if (!$this->isSilent())
00361                     throw $e;
00362                 
00363                 return null;
00364             }
00365         }
00366         
00367         public function getCustomList()
00368         {
00369             try {
00370                 return $this->dao->getCustomList($this->toSelectQuery());
00371             } catch (ObjectNotFoundException $e) {
00372                 if (!$this->isSilent())
00373                     throw $e;
00374                 
00375                 return array();
00376             }
00377         }
00378         
00379         public function getPropertyList()
00380         {
00381             try {
00382                 return $this->dao->getCustomRowList($this->toSelectQuery());
00383             } catch (ObjectNotFoundException $e) {
00384                 if (!$this->isSilent())
00385                     throw $e;
00386                 
00387                 return array();
00388             }
00389         }
00390         
00391         public function toString()
00392         {
00393             return $this->toDialectString(
00394                 $this->dao
00395                     ? DBPool::getByDao($this->dao)->getDialect()
00396                     : ImaginaryDialect::me()
00397             );
00398         }
00399         
00400         public function toDialectString(Dialect $dialect)
00401         {
00402             return $this->toSelectQuery()->toDialectString($dialect);
00403         }
00404         
00408         public function toSelectQuery()
00409         {
00410             Assert::isNotNull($this->dao, 'DAO not set');
00411             
00412             if ($this->projection) {
00413                 $query =
00414                     $this->getProjection()->process(
00415                         $this,
00416                         OSQL::select()->from($this->dao->getTable())
00417                     );
00418             } else
00419                 $query = $this->dao->makeSelectHead();
00420             
00421             $query->
00422                 limit($this->limit, $this->offset)->
00423                 setFetchStrategyId($this->strategy->getId());
00424             
00425             if ($this->distinct)
00426                 $query->distinct();
00427             
00428             if ($this->logic->getSize()) {
00429                 $query->
00430                     andWhere(
00431                         $this->logic->toMapped($this->dao, $query)
00432                     );
00433             }
00434             
00435             if ($this->order) {
00436                 $query->setOrderChain($this->order->toMapped($this->dao, $query));
00437             }
00438             
00439             if (
00440                 !$this->projection
00441                 && $this->strategy->getId() == FetchStrategy::JOIN
00442             ) {
00443                 $this->joinProperties($query, $this->dao, $this->dao->getTable(), true);
00444             }
00445 
00446             return $query;
00447         }
00448         
00449         private function joinProperties(
00450             SelectQuery $query,
00451             ComplexBuilderDAO $parentDao,
00452             $parentTable,
00453             $parentRequired,
00454             $prefix = null
00455         )
00456         {
00457             $proto = call_user_func(array($parentDao->getObjectName(), 'proto'));
00458             
00459             foreach ($proto->getPropertyList() as $property) {
00460                 if (
00461                     $property->getRelationId() == MetaRelation::ONE_TO_ONE
00462                     && !$property->isGenericType()
00463                     && !$property->getFetchStrategyId() == FetchStrategy::CASCADE
00464                 ) {
00465                     if (
00466                         is_subclass_of(
00467                             $property->getClassName(),
00468                             'Enumeration'
00469                         )
00470                     ) {
00471                         $query->get(
00472                             new DBField(
00473                                 $property->getColumnName(),
00474                                 $parentTable
00475                             )
00476                         );
00477                         
00478                         continue;
00479                     }
00480                     
00481                     $propertyDao = call_user_func(
00482                         array($property->getClassName(), 'dao')
00483                     );
00484                     
00485                     $tableAlias = $propertyDao->getJoinName(
00486                         $property->getColumnName(),
00487                         $prefix
00488                     );
00489                     
00490                     $fields = $propertyDao->getFields();
00491                     
00492                     if (!$query->hasJoinedTable($tableAlias)) {
00493                         $logic =
00494                             Expression::eq(
00495                                 DBField::create(
00496                                     $property->getColumnName(),
00497                                     $parentTable
00498                                 ),
00499                                 
00500                                 DBField::create(
00501                                     $propertyDao->getIdName(),
00502                                     $tableAlias
00503                                 )
00504                             );
00505                         
00506                         if ($property->isRequired() && $parentRequired)
00507                             $query->join($propertyDao->getTable(), $logic, $tableAlias);
00508                         else
00509                             $query->leftJoin($propertyDao->getTable(), $logic, $tableAlias);
00510                     }
00511                     
00512                     foreach ($fields as $field) {
00513                         $query->get(
00514                             new DBField($field, $tableAlias),
00515                             $propertyDao->getJoinPrefix($property->getColumnName(), $prefix)
00516                                 .$field
00517                         );
00518                     }
00519                     
00520                     $this->joinProperties(
00521                         $query, 
00522                         $propertyDao, 
00523                         $tableAlias, 
00524                         $property->isRequired() && $parentRequired,
00525                         $propertyDao->getJoinPrefix($property->getColumnName(), $prefix)
00526                     );
00527                 }
00528             }
00529         }
00530         
00534         private function getProto()
00535         {
00536             return
00537                 call_user_func(
00538                     array($this->dao->getObjectName(), 'proto')
00539                 );
00540         }
00541     }
00542 ?>

generated by doxygen-1.5.1
for onPHP at Mon Apr 30 23:10:10 2007