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