00001 <?php
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00016 abstract class ProtoDAO extends GenericDAO
00017 {
00018 public function fetchCollections(
00019 $collections, $list
00020 )
00021 {
00022 $ids = ArrayUtils::getIdsArray($list);
00023
00024 $mainId = DBField::create(
00025 $this->getIdName(),
00026 $this->getTable()
00027 );
00028
00029 foreach ($collections as $path => $info) {
00030 $lazy = $info['lazy'];
00031
00032 $query =
00033 OSQL::select()->get($mainId)->
00034 from($this->getTable());
00035
00036 if ($criteria = $info['criteria']) {
00037 $query = $criteria->setDao($this)->fillSelectQuery($query);
00038 }
00039
00040 $proto = reset($list)->proto();
00041
00042 $this->processPath($proto, $path, $query, $this->getTable());
00043
00044 $query->andWhere(
00045 Expression::in($mainId, $ids)
00046 );
00047
00048 $propertyPath = $info['propertyPath'];
00049
00050 $property = $propertyPath->getFinalProperty();
00051 $proto = $propertyPath->getFinalProto();
00052 $dao = $propertyPath->getFinalDao();
00053
00054 $selfName = $this->getObjectName();
00055 $self = new $selfName;
00056 $getter = 'get'.ucfirst($property->getName());
00057
00058 Assert::isTrue(
00059 $property->getRelationId() == MetaRelation::ONE_TO_MANY
00060 || $property->getRelationId() == MetaRelation::MANY_TO_MANY
00061 );
00062
00063 $table = $dao->getJoinName($property->getColumnName());
00064
00065 $id = $this->getIdName();
00066 $collection = array();
00067
00068 if ($lazy) {
00069 if ($property->getRelationId() == MetaRelation::MANY_TO_MANY) {
00070 $childId = $self->$getter()->getChildIdField();
00071 } else {
00072 $childId = $dao->getIdName();
00073 }
00074
00075 $alias = 'cid';
00076
00077 $field = DBField::create($childId);
00078
00079 $query->get($field, $alias);
00080
00081 if (!$property->isRequired())
00082 $query->andWhere(Expression::notNull($field));
00083
00084 try {
00085 $rows = $dao->getCustomList($query);
00086
00087 foreach ($rows as $row)
00088 if (!empty($row[$alias]))
00089 $collection[$row[$id]][] = $row[$alias];
00090
00091 } catch (ObjectNotFoundException $e) {}
00092 } else {
00093 $prefix = $table.'_';
00094
00095 foreach ($dao->getFields() as $field) {
00096 $query->get(
00097 DBField::create(
00098 $field, $table
00099 ),
00100 $prefix.$field
00101 );
00102 }
00103
00104 if (!$property->isRequired()) {
00105 $query->andWhere(
00106 Expression::notNull(
00107 DBField::create($dao->getIdName(), $table)
00108 )
00109 );
00110 }
00111
00112 try {
00113
00114
00115 $rows = $dao->getCustomList($query);
00116
00117 foreach ($rows as $row) {
00118 $collection[$row[$id]][] =
00119 $dao->makeObject($row, $prefix);
00120 }
00121 } catch (ObjectNotFoundException $e) {}
00122 }
00123
00124 $method = 'fill'.ucfirst($property->getName());
00125
00126 Assert::isTrue(
00127 method_exists(reset($list), $method),
00128 'can not find filler method'
00129 );
00130
00131 foreach ($list as $object) {
00132 if (!empty($collection[$object->getId()]))
00133 $object->$method($collection[$object->getId()], $lazy);
00134 else
00135 $object->$method(array(), $lazy);
00136 }
00137 }
00138
00139 return $list;
00140 }
00141
00142 private function processPath(
00143 AbstractProtoClass $proto,
00144 $probablyPath,
00145 JoinCapableQuery $query,
00146 $table,
00147 $parentRequired = true,
00148 $prefix = null
00149 )
00150 {
00151 $path = explode('.', $probablyPath);
00152
00153 try {
00154 $property = $proto->getPropertyByName($path[0]);
00155 } catch (MissingElementException $e) {
00156
00157 return new DBValue($probablyPath);
00158 }
00159
00160 unset($path[0]);
00161
00162 Assert::isTrue(
00163 $property->getRelationId() != null
00164 && !$property->isGenericType()
00165 );
00166
00167 $propertyDao = call_user_func(
00168 array(
00169 $property->getClassName(),
00170 'dao'
00171 )
00172 );
00173
00174 Assert::isNotNull(
00175 $propertyDao,
00176 'can not find target dao for "'.$property->getName().'" property'
00177 .' at "'.get_class($proto).'"'
00178 );
00179
00180 $alias = $propertyDao->getJoinName(
00181 $property->getColumnName(),
00182 $prefix
00183 );
00184
00185 if (
00186 $property->getRelationId() == MetaRelation::ONE_TO_MANY
00187 || $property->getRelationId() == MetaRelation::MANY_TO_MANY
00188 ) {
00189 $remoteName = $property->getClassName();
00190 $selfName = $this->getObjectName();
00191 $self = new $selfName;
00192 $getter = 'get'.ucfirst($property->getName());
00193 $dao = call_user_func(array($remoteName, 'dao'));
00194
00195 if ($property->getRelationId() == MetaRelation::MANY_TO_MANY) {
00196 $helperTable = $self->$getter()->getHelperTable();
00197 $helperAlias = $helperTable;
00198
00199 if (!$query->hasJoinedTable($helperAlias)) {
00200 $logic =
00201 Expression::eq(
00202 DBField::create(
00203 $this->getIdName(),
00204 $table
00205 ),
00206
00207 DBField::create(
00208 $self->$getter()->getParentIdField(),
00209 $helperAlias
00210 )
00211 );
00212
00213 if ($property->isRequired())
00214 $query->join($helperTable, $logic, $helperAlias);
00215 else
00216 $query->leftJoin($helperTable, $logic, $helperAlias);
00217 }
00218
00219 $logic =
00220 Expression::eq(
00221 DBField::create(
00222 $propertyDao->getIdName(),
00223 $alias
00224 ),
00225
00226 DBField::create(
00227 $self->$getter()->getChildIdField(),
00228 $helperAlias
00229 )
00230 );
00231 } else {
00232 $logic =
00233 Expression::eq(
00234 DBField::create(
00235 $self->$getter()->getParentIdField(),
00236 $alias
00237 ),
00238
00239 DBField::create(
00240 $this->getIdName(),
00241 $table
00242 )
00243 );
00244 }
00245
00246 if (!$query->hasJoinedTable($alias)) {
00247 if ($property->isRequired() && $parentRequired)
00248 $query->join($dao->getTable(), $logic, $alias);
00249 else
00250 $query->leftJoin($dao->getTable(), $logic, $alias);
00251 }
00252 } else {
00253
00254
00255 if (
00256 isset($path[1])
00257 && (count($path) == 1)
00258 && ($path[1] == $propertyDao->getIdName())
00259 )
00260 return
00261 new DBField(
00262 $property->getColumnName(),
00263 $table
00264 );
00265
00266 if (!$query->hasJoinedTable($alias)) {
00267 $logic =
00268 Expression::eq(
00269 DBField::create(
00270 $property->getColumnName(),
00271 $table
00272 ),
00273
00274 DBField::create(
00275 $propertyDao->getIdName(),
00276 $alias
00277 )
00278 );
00279
00280 if ($property->isRequired() && $parentRequired)
00281 $query->join($propertyDao->getTable(), $logic, $alias);
00282 else
00283 $query->leftJoin($propertyDao->getTable(), $logic, $alias);
00284 }
00285 }
00286
00287 return $propertyDao->guessAtom(
00288 implode('.', $path),
00289 $query,
00290 $alias,
00291 $property->isRequired() && $parentRequired,
00292 $propertyDao->getJoinPrefix($property->getColumnName(), $prefix)
00293 );
00294 }
00295
00296 public function guessAtom(
00297 $atom,
00298 JoinCapableQuery $query,
00299 $table = null,
00300 $parentRequired = true,
00301 $prefix = null
00302 )
00303 {
00304 if ($table === null)
00305 $table = $this->getTable();
00306
00307 if (is_string($atom)) {
00308 if (strpos($atom, '.') !== false) {
00309 return
00310 $this->processPath(
00311 call_user_func(
00312 array($this->getObjectName(), 'proto')
00313 ),
00314 $atom,
00315 $query,
00316 $table,
00317 $parentRequired,
00318 $prefix
00319 );
00320 } elseif (
00321 array_key_exists(
00322 $atom,
00323 $mapping = $this->getMapping()
00324 )
00325 ) {
00326
00327 if (!$mapping[$atom])
00328 return new DBField($atom, $table);
00329
00330 return new DBField($mapping[$atom], $table);
00331 } elseif (
00332 ($query instanceof SelectQuery)
00333 && $query->hasAliasInside($atom)
00334 ) {
00335 return new DBField($atom);
00336 }
00337 } elseif ($atom instanceof MappableObject)
00338 return $atom->toMapped($this, $query);
00339 elseif (
00340 ($atom instanceof DBValue)
00341 || ($atom instanceof DBField)
00342 ) {
00343 return $atom;
00344 }
00345
00346 return new DBValue($atom);
00347 }
00348 }
00349 ?>