PageRenderTime 47ms CodeModel.GetById 15ms RepoModel.GetById 1ms app.codeStats 0ms

/main/DAOs/Workers/CommonDaoWorker.class.php

http://github.com/onPHP/onphp-framework
PHP | 505 lines | 407 code | 57 blank | 41 comment | 58 complexity | ebf5c11a46d6bc2d896b34cb7746b8b6 MD5 | raw file
Possible License(s): LGPL-3.0
  1. <?php
  2. /****************************************************************************
  3. * Copyright (C) 2004-2008 by Konstantin V. Arkhipov, Anton E. Lebedevich *
  4. * *
  5. * This program is free software; you can redistribute it and/or modify *
  6. * it under the terms of the GNU Lesser General Public License as *
  7. * published by the Free Software Foundation; either version 3 of the *
  8. * License, or (at your option) any later version. *
  9. * *
  10. ****************************************************************************/
  11. /**
  12. * Tunable (aka manual) caching DAO worker.
  13. *
  14. * @see SmartDaoWorker for auto-caching one.
  15. *
  16. * @ingroup DAOs
  17. **/
  18. class CommonDaoWorker extends BaseDaoWorker
  19. {
  20. /// single object getters
  21. //@{
  22. public function getById($id, $expires = Cache::EXPIRES_MEDIUM)
  23. {
  24. if (
  25. ($expires !== Cache::DO_NOT_CACHE)
  26. && ($object = $this->getCachedById($id))
  27. ) {
  28. if ($object === Cache::NOT_FOUND)
  29. throw new CachedObjectNotFoundException(
  30. "there is no such object for '"
  31. .$this->dao->getObjectName()."' with id=".$id
  32. );
  33. return $this->dao->completeObject($object);
  34. } else {
  35. $query =
  36. $this->dao->
  37. makeSelectHead()->
  38. andWhere(
  39. Expression::eq(
  40. DBField::create(
  41. $this->dao->getIdName(),
  42. $this->dao->getTable()
  43. ),
  44. $id
  45. )
  46. );
  47. if ($expires === Cache::DO_NOT_CACHE) {
  48. $object = $this->fetchObject($query);
  49. } else {
  50. $object = $this->cachedFetchObject($query, $expires, true);
  51. }
  52. if ($object) {
  53. return $object;
  54. } else {
  55. throw new ObjectNotFoundException(
  56. "there is no such object for '".$this->dao->getObjectName()
  57. ."' with query == "
  58. .$query->toDialectString(
  59. DBPool::me()->getByDao($this->dao)->
  60. getDialect()
  61. )
  62. );
  63. }
  64. }
  65. }
  66. public function getByLogic(
  67. LogicalObject $logic, $expires = Cache::DO_NOT_CACHE
  68. )
  69. {
  70. return
  71. $this->getByQuery(
  72. $this->dao->makeSelectHead()->andWhere($logic), $expires
  73. );
  74. }
  75. public function getByQuery(
  76. SelectQuery $query, $expires = Cache::DO_NOT_CACHE
  77. )
  78. {
  79. if (
  80. ($expires !== Cache::DO_NOT_CACHE)
  81. && ($object = $this->getCachedByQuery($query))
  82. ) {
  83. if ($object === Cache::NOT_FOUND)
  84. throw new CachedObjectNotFoundException();
  85. return $this->dao->completeObject($object);
  86. } else {
  87. if ($expires === Cache::DO_NOT_CACHE)
  88. $object = $this->fetchObject($query);
  89. else
  90. $object = $this->cachedFetchObject($query, $expires, false);
  91. if ($object)
  92. return $object;
  93. else
  94. throw new ObjectNotFoundException(
  95. "there is no such object for '".$this->dao->getObjectName()
  96. .(
  97. defined('__LOCAL_DEBUG__')
  98. ?
  99. "' with query == "
  100. .$query->toDialectString(
  101. DBPool::me()->getByDao($this->dao)->
  102. getDialect()
  103. )
  104. : null
  105. )
  106. );
  107. }
  108. }
  109. public function getCustom(
  110. SelectQuery $query, $expires = Cache::DO_NOT_CACHE
  111. )
  112. {
  113. if ($query->getLimit() > 1)
  114. throw new WrongArgumentException(
  115. 'can not handle non-single row queries'
  116. );
  117. $db = DBPool::getByDao($this->dao);
  118. if (
  119. ($expires !== Cache::DO_NOT_CACHE)
  120. && ($object = $this->getCachedByQuery($query))
  121. ) {
  122. if ($object === Cache::NOT_FOUND)
  123. throw new CachedObjectNotFoundException();
  124. return $object;
  125. } elseif ($object = $db->queryRow($query)) {
  126. if ($expires === Cache::DO_NOT_CACHE)
  127. return $object;
  128. else
  129. return $this->cacheByQuery($query, $object, $expires);
  130. } else {
  131. throw new ObjectNotFoundException(
  132. "zero"
  133. .(
  134. defined('__LOCAL_DEBUG__')
  135. ?
  136. "for query == "
  137. .$query->toDialectString(
  138. DBPool::me()->getByDao($this->dao)->
  139. getDialect()
  140. )
  141. : null
  142. )
  143. );
  144. }
  145. }
  146. //@}
  147. /// object's list getters
  148. //@{
  149. public function getListByIds(
  150. array $ids,
  151. $expires = Cache::EXPIRES_MEDIUM
  152. )
  153. {
  154. $list = array();
  155. // dupes, if any, will be resolved later @ ArrayUtils::regularizeList
  156. $ids = array_unique($ids);
  157. if ($expires !== Cache::DO_NOT_CACHE) {
  158. $toFetch = array();
  159. $prefixed = array();
  160. foreach ($ids as $id)
  161. $prefixed[$id] = $this->makeIdKey($id);
  162. if (
  163. $cachedList
  164. = Cache::me()->mark($this->className)->getList($prefixed)
  165. ) {
  166. $proto = $this->dao->getProtoClass();
  167. $proto->beginPrefetch();
  168. foreach ($cachedList as $cached) {
  169. if ($cached && ($cached !== Cache::NOT_FOUND)) {
  170. $list[] = $this->dao->completeObject($cached);
  171. unset($prefixed[$cached->getId()]);
  172. }
  173. }
  174. $proto->endPrefetch($list);
  175. }
  176. $toFetch += array_keys($prefixed);
  177. if ($toFetch) {
  178. try {
  179. $list =
  180. array_merge(
  181. $list,
  182. $this->getListByLogic(
  183. Expression::in(
  184. new DBField(
  185. $this->dao->getIdName(),
  186. $this->dao->getTable()
  187. ),
  188. $toFetch
  189. ),
  190. Cache::DO_NOT_CACHE
  191. )
  192. );
  193. } catch (ObjectNotFoundException $e) {
  194. // nothing to fetch
  195. }
  196. }
  197. } elseif (count($ids)) {
  198. try {
  199. $list =
  200. $this->getListByLogic(
  201. Expression::in(
  202. new DBField(
  203. $this->dao->getIdName(),
  204. $this->dao->getTable()
  205. ),
  206. $ids
  207. ),
  208. Cache::DO_NOT_CACHE
  209. );
  210. } catch (ObjectNotFoundException $e) {/*_*/}
  211. }
  212. return $list;
  213. }
  214. public function getListByQuery(
  215. SelectQuery $query, $expires = Cache::DO_NOT_CACHE
  216. )
  217. {
  218. if (
  219. ($expires !== Cache::DO_NOT_CACHE)
  220. && ($list = $this->getCachedByQuery($query))
  221. ) {
  222. if ($list === Cache::NOT_FOUND)
  223. throw new CachedObjectNotFoundException();
  224. return $list;
  225. } elseif ($list = $this->fetchList($query)) {
  226. if (Cache::DO_NOT_CACHE === $expires) {
  227. return $list;
  228. } else {
  229. return $this->cacheByQuery($query, $list, $expires);
  230. }
  231. } else {
  232. throw new ObjectNotFoundException(
  233. "empty list"
  234. .(
  235. defined('__LOCAL_DEBUG__')
  236. ?
  237. " for such query - "
  238. .$query->toDialectString(
  239. DBPool::me()->getByDao($this->dao)->
  240. getDialect()
  241. )
  242. : null
  243. )
  244. );
  245. }
  246. }
  247. public function getListByLogic(
  248. LogicalObject $logic, $expires = Cache::DO_NOT_CACHE
  249. )
  250. {
  251. return
  252. $this->getListByQuery(
  253. $this->dao->makeSelectHead()->andWhere($logic), $expires
  254. );
  255. }
  256. public function getPlainList($expires = Cache::EXPIRES_MEDIUM)
  257. {
  258. return $this->getListByQuery(
  259. $this->dao->makeSelectHead(), $expires
  260. );
  261. }
  262. public function getTotalCount($expires = Cache::DO_NOT_CACHE)
  263. {
  264. $count = $this->getCustom(
  265. $this->dao->makeTotalCountQuery(), $expires
  266. );
  267. return current($count);
  268. }
  269. //@}
  270. /// custom list getters
  271. //@{
  272. public function getCustomList(
  273. SelectQuery $query, $expires = Cache::DO_NOT_CACHE
  274. )
  275. {
  276. if (
  277. ($expires !== Cache::DO_NOT_CACHE)
  278. && ($list = $this->getCachedByQuery($query))
  279. ) {
  280. if ($list === Cache::NOT_FOUND)
  281. throw new CachedObjectNotFoundException();
  282. return $list;
  283. } elseif ($list = DBPool::getByDao($this->dao)->querySet($query)) {
  284. if (Cache::DO_NOT_CACHE === $expires) {
  285. return $list;
  286. } else {
  287. return $this->cacheByQuery($query, $list, $expires);
  288. }
  289. } else {
  290. throw new ObjectNotFoundException(
  291. "empty list"
  292. .(
  293. defined('__LOCAL_DEBUG__')
  294. ?
  295. " for such query - "
  296. .$query->toDialectString(
  297. DBPool::me()->getByDao($this->dao)->
  298. getDialect()
  299. )
  300. : null
  301. )
  302. );
  303. }
  304. }
  305. public function getCustomRowList(
  306. SelectQuery $query, $expires = Cache::DO_NOT_CACHE
  307. )
  308. {
  309. if ($query->getFieldsCount() !== 1)
  310. throw new WrongArgumentException(
  311. 'you should select only one row when using this method'
  312. );
  313. if (
  314. ($expires !== Cache::DO_NOT_CACHE)
  315. && ($list = $this->getCachedByQuery($query))
  316. ) {
  317. if ($list === Cache::NOT_FOUND)
  318. throw new CachedObjectNotFoundException();
  319. return $list;
  320. } elseif ($list = DBPool::getByDao($this->dao)->queryColumn($query)) {
  321. if (Cache::DO_NOT_CACHE === $expires) {
  322. return $list;
  323. } else {
  324. return $this->cacheByQuery($query, $list, $expires);
  325. }
  326. } else {
  327. throw new ObjectNotFoundException(
  328. "empty list"
  329. .(
  330. defined('__LOCAL_DEBUG__')
  331. ?
  332. " for such query - "
  333. .$query->toDialectString(
  334. DBPool::me()->getByDao($this->dao)->
  335. getDialect()
  336. )
  337. : null
  338. )
  339. );
  340. }
  341. }
  342. //@}
  343. /// query result getters
  344. //@{
  345. public function getQueryResult(
  346. SelectQuery $query, $expires = Cache::DO_NOT_CACHE
  347. )
  348. {
  349. if (
  350. ($expires !== Cache::DO_NOT_CACHE)
  351. && ($list = $this->getCachedByQuery($query))
  352. ) {
  353. return $list;
  354. } else {
  355. $list = $this->fetchList($query);
  356. $count = clone $query;
  357. $count =
  358. DBPool::getByDao($this->dao)->queryRow(
  359. $count->dropFields()->dropOrder()->limit(null, null)->
  360. get(SQLFunction::create('COUNT', '*')->setAlias('count'))
  361. );
  362. return
  363. $this->cacheByQuery(
  364. $query,
  365. $list
  366. ?
  367. QueryResult::create()->
  368. setList($list)->
  369. setCount($count['count'])->
  370. setQuery($query)
  371. :
  372. QueryResult::create(),
  373. $expires
  374. );
  375. }
  376. }
  377. //@}
  378. /// cachers
  379. //@{
  380. protected function cacheById(
  381. Identifiable $object, $expires = Cache::EXPIRES_MEDIUM
  382. )
  383. {
  384. if ($expires !== Cache::DO_NOT_CACHE) {
  385. Cache::me()->mark($this->className)->
  386. add(
  387. $this->makeIdKey($object->getId()),
  388. $object,
  389. $expires
  390. );
  391. }
  392. return $object;
  393. }
  394. protected function cacheByQuery(
  395. SelectQuery $query,
  396. /* Identifiable */ $object,
  397. $expires = Cache::DO_NOT_CACHE
  398. )
  399. {
  400. if ($expires !== Cache::DO_NOT_CACHE) {
  401. Cache::me()->mark($this->className)->
  402. add(
  403. $this->makeQueryKey($query, self::SUFFIX_QUERY),
  404. $object,
  405. $expires
  406. );
  407. }
  408. return $object;
  409. }
  410. protected function cacheListByQuery(
  411. SelectQuery $query,
  412. /* array || Cache::NOT_FOUND */ $array
  413. )
  414. {
  415. throw new UnimplementedFeatureException();
  416. }
  417. //@}
  418. /// erasers
  419. //@{
  420. public function dropById($id)
  421. {
  422. $result = parent::dropById($id);
  423. $this->dao->uncacheLists();
  424. return $result;
  425. }
  426. //@}
  427. /// uncachers
  428. //@{
  429. public function uncacheById($id)
  430. {
  431. $this->dao->uncacheLists();
  432. return parent::uncacheById($id);
  433. }
  434. public function uncacheByIds($ids)
  435. {
  436. foreach ($ids as $id)
  437. parent::uncacheById($id);
  438. return $this->dao->uncacheLists();
  439. }
  440. // quite useless here
  441. public function uncacheLists()
  442. {
  443. // wipes getPlainList result, if any
  444. return $this->uncacheByQuery($this->dao->makeSelectHead());
  445. }
  446. //@}
  447. }
  448. ?>