Go to the documentation of this file.00001 <?php
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00017 abstract class GenericDAO extends Singleton implements BaseDAO
00018 {
00019 private $identityMap = array();
00020
00021 abstract public function getTable();
00022 abstract public function getObjectName();
00023
00024 public function makeObject($array, $prefix = null)
00025 {
00026 if (
00027 isset(
00028 $this->identityMap[
00029 $array[$idName = $prefix.$this->getIdName()]
00030 ]
00031 )
00032 ) {
00033 $this->getProtoClass()->skipObjectPrefetching(
00034 $this->identityMap[$array[$idName]]
00035 );
00036
00037 return $this->identityMap[$array[$idName]];
00038 }
00039
00040 return
00041 $this->completeObject(
00042 $this->makeOnlyObject($array, $prefix)
00043 );
00044 }
00045
00046 public function makeOnlyObject($array, $prefix = null)
00047 {
00048
00049
00050 return $this->addObjectToMap(
00051 $this->getProtoClass()->makeOnlyObject(
00052 $this->getObjectName(), $array, $prefix
00053 )
00054 );
00055 }
00056
00057 public function completeObject(Identifiable $object)
00058 {
00059 return $this->getProtoClass()->completeObject(
00060
00061
00062 $this->addObjectToMap($object)
00063 );
00064 }
00065
00072 public function getLinkName()
00073 {
00074 return null;
00075 }
00076
00077 public function getIdName()
00078 {
00079 return 'id';
00080 }
00081
00082 public function getSequence()
00083 {
00084 return $this->getTable().'_id';
00085 }
00086
00090 public function getProtoClass()
00091 {
00092 static $protos = array();
00093
00094 if (!isset($protos[$className = $this->getObjectName()]))
00095 $protos[$className] = call_user_func(array($className, 'proto'));
00096
00097 return $protos[$className];
00098 }
00099
00100 public function getMapping()
00101 {
00102 return $this->getProtoClass()->getMapping();
00103 }
00104
00105 public function getFields()
00106 {
00107 static $fields = array();
00108
00109 $className = $this->getObjectName();
00110
00111 if (!isset($fields[$className])) {
00112 $fields[$className] = array_values($this->getMapping());
00113 }
00114
00115 return $fields[$className];
00116 }
00117
00121 public function makeSelectHead()
00122 {
00123 static $selectHead = array();
00124
00125 if (!isset($selectHead[$className = $this->getObjectName()])) {
00126 $table = $this->getTable();
00127
00128 $object =
00129 OSQL::select()->
00130 from($table);
00131
00132 foreach ($this->getFields() as $field)
00133 $object->get(new DBField($field, $table));
00134
00135 $selectHead[$className] = $object;
00136 }
00137
00138 return clone $selectHead[$className];
00139 }
00140
00144 public function makeTotalCountQuery()
00145 {
00146 return
00147 OSQL::select()->
00148 get(
00149 SQLFunction::create('count', DBValue::create('*'))
00150 )->
00151 from($this->getTable());
00152 }
00153
00155
00156 public function getById($id, $expires = Cache::EXPIRES_MEDIUM)
00157 {
00158 Assert::isScalar($id);
00159 Assert::isNotEmpty($id);
00160
00161 if (isset($this->identityMap[$id]))
00162 return $this->identityMap[$id];
00163
00164 return $this->addObjectToMap(
00165 Cache::worker($this)->getById($id, $expires)
00166 );
00167 }
00168
00169 public function getByLogic(
00170 LogicalObject $logic, $expires = Cache::DO_NOT_CACHE
00171 )
00172 {
00173 return $this->addObjectToMap(
00174 Cache::worker($this)->getByLogic($logic, $expires)
00175 );
00176 }
00177
00178 public function getByQuery(
00179 SelectQuery $query, $expires = Cache::DO_NOT_CACHE
00180 )
00181 {
00182 return $this->addObjectToMap(
00183 Cache::worker($this)->getByQuery($query, $expires)
00184 );
00185 }
00186
00187 public function getCustom(
00188 SelectQuery $query, $expires = Cache::DO_NOT_CACHE
00189 )
00190 {
00191 return Cache::worker($this)->getCustom($query, $expires);
00192 }
00193
00194 public function getListByIds(
00195 array $ids, $expires = Cache::EXPIRES_MEDIUM
00196 )
00197 {
00198 $mapped = $remain = array();
00199
00200 foreach ($ids as $id) {
00201 if (isset($this->identityMap[$id])) {
00202 $mapped[] = $this->identityMap[$id];
00203 } else {
00204 $remain[] = $id;
00205 }
00206 }
00207
00208 if ($remain) {
00209 $list = $this->addObjectListToMap(
00210 Cache::worker($this)->getListByIds($remain, $expires)
00211 );
00212
00213 $mapped = array_merge($mapped, $list);
00214 }
00215
00216 return ArrayUtils::regularizeList($ids, $mapped);
00217 }
00218
00219 public function getListByQuery(
00220 SelectQuery $query, $expires = Cache::DO_NOT_CACHE
00221 )
00222 {
00223 return $this->addObjectListToMap(
00224 Cache::worker($this)->getListByQuery($query, $expires)
00225 );
00226 }
00227
00228 public function getListByLogic(
00229 LogicalObject $logic, $expires = Cache::DO_NOT_CACHE
00230 )
00231 {
00232 return $this->addObjectListToMap(
00233 Cache::worker($this)->getListByLogic($logic, $expires)
00234 );
00235 }
00236
00237 public function getPlainList($expires = Cache::EXPIRES_MEDIUM)
00238 {
00239 return $this->addObjectListToMap(
00240 Cache::worker($this)->getPlainList($expires)
00241 );
00242 }
00243
00244 public function getTotalCount($expires = Cache::DO_NOT_CACHE)
00245 {
00246 return Cache::worker($this)->getTotalCount($expires);
00247 }
00248
00249 public function getCustomList(
00250 SelectQuery $query, $expires = Cache::DO_NOT_CACHE
00251 )
00252 {
00253 return Cache::worker($this)->getCustomList($query, $expires);
00254 }
00255
00256 public function getCustomRowList(
00257 SelectQuery $query, $expires = Cache::DO_NOT_CACHE
00258 )
00259 {
00260 return Cache::worker($this)->getCustomRowList($query, $expires);
00261 }
00262
00263 public function getQueryResult(
00264 SelectQuery $query, $expires = Cache::DO_NOT_CACHE
00265 )
00266 {
00267 return Cache::worker($this)->getQueryResult($query, $expires);
00268 }
00269
00270 public function drop(Identifiable $object)
00271 {
00272 $this->checkObjectType($object);
00273
00274 return $this->dropById($object->getId());
00275 }
00276
00277 public function dropById($id)
00278 {
00279 unset($this->identityMap[$id]);
00280
00281 $count = Cache::worker($this)->dropById($id);
00282
00283 if (1 != $count)
00284 throw new WrongStateException('no object were dropped');
00285
00286 return $count;
00287 }
00288
00289 public function dropByIds(array $ids)
00290 {
00291 foreach ($ids as $id)
00292 unset($this->identityMap[$id]);
00293
00294 $count = Cache::worker($this)->dropByIds($ids);
00295
00296 if ($count != count($ids))
00297 throw new WrongStateException('not all objects were dropped');
00298
00299 return $count;
00300 }
00301
00302 public function uncacheById($id)
00303 {
00304 unset($this->identityMap[$id]);
00305
00306 return Cache::worker($this)->uncacheById($id);
00307 }
00308
00309 public function uncacheByIds($ids)
00310 {
00311 foreach ($ids as $id)
00312 unset($this->identityMap[$id]);
00313
00314 return Cache::worker($this)->uncacheByIds($ids);
00315 }
00316
00317 public function uncacheLists()
00318 {
00319 $this->dropIdentityMap();
00320
00321 return Cache::worker($this)->uncacheLists();
00322 }
00324
00328 public function dropIdentityMap()
00329 {
00330 $this->identityMap = array();
00331
00332 return $this;
00333 }
00334
00335 public function dropObjectIdentityMapById($id)
00336 {
00337 unset($this->identityMap[$id]);
00338
00339 return $this;
00340 }
00341
00342 protected function inject(
00343 InsertOrUpdateQuery $query,
00344 Identifiable $object
00345 )
00346 {
00347 $this->checkObjectType($object);
00348
00349 return $this->doInject(
00350 $this->setQueryFields(
00351 $query->setTable($this->getTable()), $object
00352 ),
00353 $object
00354 );
00355 }
00356
00357 protected function doInject(
00358 InsertOrUpdateQuery $query,
00359 Identifiable $object
00360 )
00361 {
00362 $db = DBPool::getByDao($this);
00363
00364 if (!$db->isQueueActive()) {
00365 $count = $db->queryCount($query);
00366
00367 $this->uncacheById($object->getId());
00368
00369 if ($count !== 1)
00370 throw new WrongStateException(
00371 $count.' rows affected: racy or insane inject happened: '
00372 .$query->toDialectString($db->getDialect())
00373 );
00374 } else {
00375 $db->queryNull($query);
00376
00377 $this->uncacheById($object->getId());
00378 }
00379
00380
00381 return $this->addObjectToMap($object->setId($object->getId()));
00382 }
00383
00384 protected function checkObjectType(Identifiable $object)
00385 {
00386 Assert::isSame(
00387 get_class($object),
00388 $this->getObjectName(),
00389 'strange object given, i can not inject it'
00390 );
00391 }
00392
00393 private function addObjectToMap(Identifiable $object)
00394 {
00395 return $this->identityMap[$object->getId()] = $object;
00396 }
00397
00398 private function addObjectListToMap($list)
00399 {
00400 foreach ($list as $object)
00401 $this->identityMap[$object->getId()] = $object;
00402
00403 return $list;
00404 }
00405 }
00406 ?>