EntryDAO.php 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642
  1. <?php
  2. class FreshRSS_EntryDAO extends Minz_ModelPdo {
  3. public function addEntry ($valuesTmp) {
  4. $sql = 'INSERT INTO `' . $this->prefix . 'entry`(id, guid, title, author, content_bin, link, date, is_read, is_favorite, id_feed, tags) '
  5. . 'VALUES(?, ?, ?, ?, COMPRESS(?), ?, ?, ?, ?, ?, ?)';
  6. $stm = $this->bd->prepare ($sql);
  7. $values = array (
  8. $valuesTmp['id'],
  9. substr($valuesTmp['guid'], 0, 760),
  10. substr($valuesTmp['title'], 0, 255),
  11. substr($valuesTmp['author'], 0, 255),
  12. $valuesTmp['content'],
  13. substr($valuesTmp['link'], 0, 1023),
  14. $valuesTmp['date'],
  15. $valuesTmp['is_read'] ? 1 : 0,
  16. $valuesTmp['is_favorite'] ? 1 : 0,
  17. $valuesTmp['id_feed'],
  18. substr($valuesTmp['tags'], 0, 1023),
  19. );
  20. if ($stm && $stm->execute ($values)) {
  21. return $this->bd->lastInsertId();
  22. } else {
  23. $info = $stm->errorInfo();
  24. if ((int)($info[0] / 1000) !== 23) { //Filter out "SQLSTATE Class code 23: Constraint Violation" because of expected duplicate entries
  25. Minz_Log::record ('SQL error ' . $info[0] . ': ' . $info[1] . ' ' . $info[2]
  26. . ' while adding entry in feed ' . $valuesTmp['id_feed'] . ' with title: ' . $valuesTmp['title'], Minz_Log::ERROR);
  27. } /*else {
  28. Minz_Log::record ('SQL error ' . $info[0] . ': ' . $info[1] . ' ' . $info[2]
  29. . ' while adding entry in feed ' . $valuesTmp['id_feed'] . ' with title: ' . $valuesTmp['title'], Minz_Log::DEBUG);
  30. }*/
  31. return false;
  32. }
  33. }
  34. public function addEntryObject($entry, $conf, $feedHistory) {
  35. $existingGuids = array_fill_keys(
  36. $this->listLastGuidsByFeed($entry->feed(), 20), 1
  37. );
  38. $nb_month_old = max($conf->old_entries, 1);
  39. $date_min = time() - (3600 * 24 * 30 * $nb_month_old);
  40. $eDate = $entry->date(true);
  41. if ($feedHistory == -2) {
  42. $feedHistory = $conf->keep_history_default;
  43. }
  44. if (!isset($existingGuids[$entry->guid()]) &&
  45. ($feedHistory != 0 || $eDate >= $date_min)) {
  46. $values = $entry->toArray();
  47. $useDeclaredDate = empty($existingGuids);
  48. $values['id'] = ($useDeclaredDate || $eDate < $date_min) ?
  49. min(time(), $eDate) . uSecString() :
  50. uTimeString();
  51. return $this->addEntry($values);
  52. }
  53. // We don't return Entry object to avoid a research in DB
  54. return -1;
  55. }
  56. public function markFavorite($ids, $is_favorite = true) {
  57. if (!is_array($ids)) {
  58. $ids = array($ids);
  59. }
  60. $sql = 'UPDATE `' . $this->prefix . 'entry` e '
  61. . 'SET e.is_favorite = ? '
  62. . 'WHERE e.id IN (' . str_repeat('?,', count($ids) - 1). '?)';
  63. $values = array ($is_favorite ? 1 : 0);
  64. $values = array_merge($values, $ids);
  65. $stm = $this->bd->prepare ($sql);
  66. if ($stm && $stm->execute ($values)) {
  67. return $stm->rowCount();
  68. } else {
  69. $info = $stm->errorInfo();
  70. Minz_Log::record ('SQL error : ' . $info[2], Minz_Log::ERROR);
  71. return false;
  72. }
  73. }
  74. public function markRead($ids, $is_read = true) {
  75. if (is_array($ids)) {
  76. if (count($ids) < 6) { //Speed heuristics
  77. $affected = 0;
  78. foreach ($ids as $id) {
  79. $affected += $this->markRead($id, $is_read);
  80. }
  81. return $affected;
  82. }
  83. $this->bd->beginTransaction();
  84. $sql = 'UPDATE `' . $this->prefix . 'entry` e '
  85. . 'SET e.is_read = ? '
  86. . 'WHERE e.id IN (' . str_repeat('?,', count($ids) - 1). '?)';
  87. $values = array($is_read ? 1 : 0);
  88. $values = array_merge($values, $ids);
  89. $stm = $this->bd->prepare($sql);
  90. if (!($stm && $stm->execute($values))) {
  91. $info = $stm->errorInfo();
  92. Minz_Log::record('SQL error : ' . $info[2], Minz_Log::ERROR);
  93. $this->bd->rollBack();
  94. return false;
  95. }
  96. $affected = $stm->rowCount();
  97. if ($affected > 0) {
  98. $sql = 'UPDATE `' . $this->prefix . 'feed` f '
  99. . 'INNER JOIN ('
  100. . 'SELECT e.id_feed, '
  101. . 'COUNT(CASE WHEN e.is_read = 0 THEN 1 END) AS nbUnreads, '
  102. . 'COUNT(e.id) AS nbEntries '
  103. . 'FROM `' . $this->prefix . 'entry` e '
  104. . 'GROUP BY e.id_feed'
  105. . ') x ON x.id_feed=f.id '
  106. . 'SET f.cache_nbEntries=x.nbEntries, f.cache_nbUnreads=x.nbUnreads';
  107. $stm = $this->bd->prepare($sql);
  108. if (!($stm && $stm->execute())) {
  109. $info = $stm->errorInfo();
  110. Minz_Log::record('SQL error : ' . $info[2], Minz_Log::ERROR);
  111. $this->bd->rollBack();
  112. return false;
  113. }
  114. }
  115. $this->bd->commit();
  116. return $affected;
  117. } else {
  118. $sql = 'UPDATE `' . $this->prefix . 'entry` e INNER JOIN `' . $this->prefix . 'feed` f ON e.id_feed = f.id '
  119. . 'SET e.is_read = ?,'
  120. . 'f.cache_nbUnreads=f.cache_nbUnreads' . ($is_read ? '-' : '+') . '1 '
  121. . 'WHERE e.id=?';
  122. $values = array($is_read ? 1 : 0, $ids);
  123. $stm = $this->bd->prepare($sql);
  124. if ($stm && $stm->execute($values)) {
  125. return $stm->rowCount();
  126. } else {
  127. $info = $stm->errorInfo();
  128. Minz_Log::record('SQL error : ' . $info[2], Minz_Log::ERROR);
  129. return false;
  130. }
  131. }
  132. }
  133. public function markReadEntries ($idMax = 0, $onlyFavorites = false, $priorityMin = 0) {
  134. if ($idMax == 0) {
  135. $sql = 'UPDATE `' . $this->prefix . 'entry` e INNER JOIN `' . $this->prefix . 'feed` f ON e.id_feed = f.id '
  136. . 'SET e.is_read = 1, f.cache_nbUnreads=0 '
  137. . 'WHERE e.is_read = 0';
  138. if ($onlyFavorites) {
  139. $sql .= ' AND e.is_favorite = 1';
  140. } elseif ($priorityMin >= 0) {
  141. $sql .= ' AND f.priority > ' . intval($priorityMin);
  142. }
  143. $stm = $this->bd->prepare ($sql);
  144. if ($stm && $stm->execute ()) {
  145. return $stm->rowCount();
  146. } else {
  147. $info = $stm->errorInfo();
  148. Minz_Log::record ('SQL error : ' . $info[2], Minz_Log::ERROR);
  149. return false;
  150. }
  151. } else {
  152. $this->bd->beginTransaction ();
  153. $sql = 'UPDATE `' . $this->prefix . 'entry` e INNER JOIN `' . $this->prefix . 'feed` f ON e.id_feed = f.id '
  154. . 'SET e.is_read = 1 '
  155. . 'WHERE e.is_read = 0 AND e.id <= ?';
  156. if ($onlyFavorites) {
  157. $sql .= ' AND e.is_favorite = 1';
  158. } elseif ($priorityMin >= 0) {
  159. $sql .= ' AND f.priority > ' . intval($priorityMin);
  160. }
  161. $values = array ($idMax);
  162. $stm = $this->bd->prepare ($sql);
  163. if (!($stm && $stm->execute ($values))) {
  164. $info = $stm->errorInfo();
  165. Minz_Log::record ('SQL error : ' . $info[2], Minz_Log::ERROR);
  166. $this->bd->rollBack ();
  167. return false;
  168. }
  169. $affected = $stm->rowCount();
  170. if ($affected > 0) {
  171. $sql = 'UPDATE `' . $this->prefix . 'feed` f '
  172. . 'LEFT OUTER JOIN ('
  173. . 'SELECT e.id_feed, '
  174. . 'COUNT(*) AS nbUnreads '
  175. . 'FROM `' . $this->prefix . 'entry` e '
  176. . 'WHERE e.is_read = 0 '
  177. . 'GROUP BY e.id_feed'
  178. . ') x ON x.id_feed=f.id '
  179. . 'SET f.cache_nbUnreads=COALESCE(x.nbUnreads, 0)';
  180. $stm = $this->bd->prepare ($sql);
  181. if (!($stm && $stm->execute ())) {
  182. $info = $stm->errorInfo();
  183. Minz_Log::record ('SQL error : ' . $info[2], Minz_Log::ERROR);
  184. $this->bd->rollBack ();
  185. return false;
  186. }
  187. }
  188. $this->bd->commit ();
  189. return $affected;
  190. }
  191. }
  192. public function markReadCat ($id, $idMax = 0) {
  193. if ($idMax == 0) {
  194. $sql = 'UPDATE `' . $this->prefix . 'entry` e INNER JOIN `' . $this->prefix . 'feed` f ON e.id_feed = f.id '
  195. . 'SET e.is_read = 1, f.cache_nbUnreads=0 '
  196. . 'WHERE f.category = ? AND e.is_read = 0';
  197. $values = array ($id);
  198. $stm = $this->bd->prepare ($sql);
  199. if ($stm && $stm->execute ($values)) {
  200. return $stm->rowCount();
  201. } else {
  202. $info = $stm->errorInfo();
  203. Minz_Log::record ('SQL error : ' . $info[2], Minz_Log::ERROR);
  204. return false;
  205. }
  206. } else {
  207. $this->bd->beginTransaction ();
  208. $sql = 'UPDATE `' . $this->prefix . 'entry` e INNER JOIN `' . $this->prefix . 'feed` f ON e.id_feed = f.id '
  209. . 'SET e.is_read = 1 '
  210. . 'WHERE f.category = ? AND e.is_read = 0 AND e.id <= ?';
  211. $values = array ($id, $idMax);
  212. $stm = $this->bd->prepare ($sql);
  213. if (!($stm && $stm->execute ($values))) {
  214. $info = $stm->errorInfo();
  215. Minz_Log::record ('SQL error : ' . $info[2], Minz_Log::ERROR);
  216. $this->bd->rollBack ();
  217. return false;
  218. }
  219. $affected = $stm->rowCount();
  220. if ($affected > 0) {
  221. $sql = 'UPDATE `' . $this->prefix . 'feed` f '
  222. . 'LEFT OUTER JOIN ('
  223. . 'SELECT e.id_feed, '
  224. . 'COUNT(*) AS nbUnreads '
  225. . 'FROM `' . $this->prefix . 'entry` e '
  226. . 'WHERE e.is_read = 0 '
  227. . 'GROUP BY e.id_feed'
  228. . ') x ON x.id_feed=f.id '
  229. . 'SET f.cache_nbUnreads=COALESCE(x.nbUnreads, 0) '
  230. . 'WHERE f.category = ?';
  231. $values = array ($id);
  232. $stm = $this->bd->prepare ($sql);
  233. if (!($stm && $stm->execute ($values))) {
  234. $info = $stm->errorInfo();
  235. Minz_Log::record ('SQL error : ' . $info[2], Minz_Log::ERROR);
  236. $this->bd->rollBack ();
  237. return false;
  238. }
  239. }
  240. $this->bd->commit ();
  241. return $affected;
  242. }
  243. }
  244. public function markReadCatName($name, $idMax = 0) {
  245. if ($idMax == 0) {
  246. $sql = 'UPDATE `' . $this->prefix . 'entry` e '
  247. . 'INNER JOIN `' . $this->prefix . 'feed` f ON e.id_feed = f.id '
  248. . 'INNER JOIN `' . $this->prefix . 'category` c ON c.id = f.category '
  249. . 'SET e.is_read = 1, f.cache_nbUnreads=0 '
  250. . 'WHERE c.name = ?';
  251. $values = array($name);
  252. $stm = $this->bd->prepare($sql);
  253. if ($stm && $stm->execute($values)) {
  254. return $stm->rowCount();
  255. } else {
  256. $info = $stm->errorInfo();
  257. Minz_Log::record('SQL error : ' . $info[2], Minz_Log::ERROR);
  258. return false;
  259. }
  260. } else {
  261. $this->bd->beginTransaction();
  262. $sql = 'UPDATE `' . $this->prefix . 'entry` e '
  263. . 'INNER JOIN `' . $this->prefix . 'feed` f ON e.id_feed = f.id '
  264. . 'INNER JOIN `' . $this->prefix . 'category` c ON c.id = f.category '
  265. . 'SET e.is_read = 1 '
  266. . 'WHERE c.name = ? AND e.id <= ?';
  267. $values = array($name, $idMax);
  268. $stm = $this->bd->prepare($sql);
  269. if (!($stm && $stm->execute($values))) {
  270. $info = $stm->errorInfo();
  271. Minz_Log::record('SQL error : ' . $info[2], Minz_Log::ERROR);
  272. $this->bd->rollBack();
  273. return false;
  274. }
  275. $affected = $stm->rowCount();
  276. if ($affected > 0) {
  277. $sql = 'UPDATE `' . $this->prefix . 'feed` f '
  278. . 'LEFT OUTER JOIN ('
  279. . 'SELECT e.id_feed, '
  280. . 'COUNT(*) AS nbUnreads '
  281. . 'FROM `' . $this->prefix . 'entry` e '
  282. . 'WHERE e.is_read = 0 '
  283. . 'GROUP BY e.id_feed'
  284. . ') x ON x.id_feed=f.id '
  285. . 'INNER JOIN `' . $this->prefix . 'category` c ON c.id = f.category '
  286. . 'SET f.cache_nbUnreads=COALESCE(x.nbUnreads, 0) '
  287. . 'WHERE c.name = ?';
  288. $values = array($name);
  289. $stm = $this->bd->prepare($sql);
  290. if (!($stm && $stm->execute($values))) {
  291. $info = $stm->errorInfo();
  292. Minz_Log::record('SQL error : ' . $info[2], Minz_Log::ERROR);
  293. $this->bd->rollBack();
  294. return false;
  295. }
  296. }
  297. $this->bd->commit();
  298. return $affected;
  299. }
  300. }
  301. public function markReadFeed ($id, $idMax = 0) {
  302. if ($idMax == 0) {
  303. $sql = 'UPDATE `' . $this->prefix . 'entry` e INNER JOIN `' . $this->prefix . 'feed` f ON e.id_feed = f.id '
  304. . 'SET e.is_read = 1, f.cache_nbUnreads=0 '
  305. . 'WHERE f.id=? AND e.is_read = 0';
  306. $values = array ($id);
  307. $stm = $this->bd->prepare ($sql);
  308. if ($stm && $stm->execute ($values)) {
  309. return $stm->rowCount();
  310. } else {
  311. $info = $stm->errorInfo();
  312. Minz_Log::record ('SQL error : ' . $info[2], Minz_Log::ERROR);
  313. return false;
  314. }
  315. } else {
  316. $this->bd->beginTransaction ();
  317. $sql = 'UPDATE `' . $this->prefix . 'entry` e INNER JOIN `' . $this->prefix . 'feed` f ON e.id_feed = f.id '
  318. . 'SET e.is_read = 1 '
  319. . 'WHERE f.id=? AND e.is_read = 0 AND e.id <= ?';
  320. $values = array ($id, $idMax);
  321. $stm = $this->bd->prepare ($sql);
  322. if (!($stm && $stm->execute ($values))) {
  323. $info = $stm->errorInfo();
  324. Minz_Log::record ('SQL error : ' . $info[2], Minz_Log::ERROR);
  325. $this->bd->rollBack ();
  326. return false;
  327. }
  328. $affected = $stm->rowCount();
  329. if ($affected > 0) {
  330. $sql = 'UPDATE `' . $this->prefix . 'feed` f '
  331. . 'SET f.cache_nbUnreads=f.cache_nbUnreads-' . $affected
  332. . ' WHERE f.id=?';
  333. $values = array ($id);
  334. $stm = $this->bd->prepare ($sql);
  335. if (!($stm && $stm->execute ($values))) {
  336. $info = $stm->errorInfo();
  337. Minz_Log::record ('SQL error : ' . $info[2], Minz_Log::ERROR);
  338. $this->bd->rollBack ();
  339. return false;
  340. }
  341. }
  342. $this->bd->commit ();
  343. return $affected;
  344. }
  345. }
  346. public function searchByGuid ($feed_id, $id) {
  347. // un guid est unique pour un flux donné
  348. $sql = 'SELECT id, guid, title, author, UNCOMPRESS(content_bin) AS content, link, date, is_read, is_favorite, id_feed, tags '
  349. . 'FROM `' . $this->prefix . 'entry` WHERE id_feed=? AND guid=?';
  350. $stm = $this->bd->prepare ($sql);
  351. $values = array (
  352. $feed_id,
  353. $id
  354. );
  355. $stm->execute ($values);
  356. $res = $stm->fetchAll (PDO::FETCH_ASSOC);
  357. $entries = self::daoToEntry ($res);
  358. return isset ($entries[0]) ? $entries[0] : null;
  359. }
  360. public function searchById ($id) {
  361. $sql = 'SELECT id, guid, title, author, UNCOMPRESS(content_bin) AS content, link, date, is_read, is_favorite, id_feed, tags '
  362. . 'FROM `' . $this->prefix . 'entry` WHERE id=?';
  363. $stm = $this->bd->prepare ($sql);
  364. $values = array ($id);
  365. $stm->execute ($values);
  366. $res = $stm->fetchAll (PDO::FETCH_ASSOC);
  367. $entries = self::daoToEntry ($res);
  368. return isset ($entries[0]) ? $entries[0] : null;
  369. }
  370. private function sqlListWhere($type = 'a', $id = '', $state = 'all', $order = 'DESC', $limit = 1, $firstId = '', $filter = '', $date_min = 0, $showOlderUnreadsorFavorites = false, $keepHistoryDefault = 0) {
  371. $where = '';
  372. $joinFeed = false;
  373. $values = array();
  374. switch ($type) {
  375. case 'a':
  376. $where .= 'f.priority > 0 ';
  377. $joinFeed = true;
  378. break;
  379. case 's':
  380. $where .= 'e1.is_favorite = 1 ';
  381. break;
  382. case 'c':
  383. $where .= 'f.category = ? ';
  384. $values[] = intval($id);
  385. $joinFeed = true;
  386. break;
  387. case 'f':
  388. $where .= 'e1.id_feed = ? ';
  389. $values[] = intval($id);
  390. break;
  391. case 'A':
  392. $where .= '1 ';
  393. break;
  394. default:
  395. throw new FreshRSS_EntriesGetter_Exception ('Bad type in Entry->listByType: [' . $type . ']!');
  396. }
  397. switch ($state) {
  398. case 'all':
  399. break;
  400. case 'not_read':
  401. $where .= 'AND e1.is_read = 0 ';
  402. break;
  403. case 'read':
  404. $where .= 'AND e1.is_read = 1 ';
  405. break;
  406. case 'favorite':
  407. $where .= 'AND e1.is_favorite = 1 ';
  408. break;
  409. default:
  410. throw new FreshRSS_EntriesGetter_Exception ('Bad state in Entry->listByType: [' . $state . ']!');
  411. }
  412. switch ($order) {
  413. case 'DESC':
  414. case 'ASC':
  415. break;
  416. default:
  417. throw new FreshRSS_EntriesGetter_Exception ('Bad order in Entry->listByType: [' . $order . ']!');
  418. }
  419. if ($firstId !== '') {
  420. $where .= 'AND e1.id ' . ($order === 'DESC' ? '<=' : '>=') . $firstId . ' ';
  421. }
  422. if (($date_min > 0) && ($type !== 's')) {
  423. $where .= 'AND (e1.id >= ' . $date_min . '000000';
  424. if ($showOlderUnreadsorFavorites) { //Lax date constraint
  425. $where .= ' OR e1.is_read = 0 OR e1.is_favorite = 1 OR (f.keep_history <> 0';
  426. if (intval($keepHistoryDefault) === 0) {
  427. $where .= ' AND f.keep_history <> -2'; //default
  428. }
  429. $where .= ')';
  430. }
  431. $where .= ') ';
  432. $joinFeed = true;
  433. }
  434. $search = '';
  435. if ($filter !== '') {
  436. $filter = trim($filter);
  437. $filter = addcslashes($filter, '\\%_');
  438. if (stripos($filter, 'intitle:') === 0) {
  439. $filter = substr($filter, strlen('intitle:'));
  440. $intitle = true;
  441. } else {
  442. $intitle = false;
  443. }
  444. if (stripos($filter, 'inurl:') === 0) {
  445. $filter = substr($filter, strlen('inurl:'));
  446. $inurl = true;
  447. } else {
  448. $inurl = false;
  449. }
  450. if (stripos($filter, 'author:') === 0) {
  451. $filter = substr($filter, strlen('author:'));
  452. $author = true;
  453. } else {
  454. $author = false;
  455. }
  456. $terms = array_unique(explode(' ', $filter));
  457. sort($terms); //Put #tags first
  458. foreach ($terms as $word) {
  459. $word = trim($word);
  460. if (strlen($word) > 0) {
  461. if ($intitle) {
  462. $search .= 'AND e1.title LIKE ? ';
  463. $values[] = '%' . $word .'%';
  464. } elseif ($inurl) {
  465. $search .= 'AND CONCAT(e1.link, e1.guid) LIKE ? ';
  466. $values[] = '%' . $word .'%';
  467. } elseif ($author) {
  468. $search .= 'AND e1.author LIKE ? ';
  469. $values[] = '%' . $word .'%';
  470. } else {
  471. if ($word[0] === '#' && isset($word[1])) {
  472. $search .= 'AND e1.tags LIKE ? ';
  473. $values[] = '%' . $word .'%';
  474. } else {
  475. $search .= 'AND CONCAT(e1.title, UNCOMPRESS(e1.content_bin)) LIKE ? ';
  476. $values[] = '%' . $word .'%';
  477. }
  478. }
  479. }
  480. }
  481. }
  482. return array($values,
  483. 'SELECT e1.id FROM `' . $this->prefix . 'entry` e1 '
  484. . ($joinFeed ? 'INNER JOIN `' . $this->prefix . 'feed` f ON e1.id_feed = f.id ' : '')
  485. . 'WHERE ' . $where
  486. . $search
  487. . 'ORDER BY e1.id ' . $order
  488. . ($limit > 0 ? ' LIMIT ' . $limit : '')); //TODO: See http://explainextended.com/2009/10/23/mysql-order-by-limit-performance-late-row-lookups/
  489. }
  490. public function listWhere($type = 'a', $id = '', $state = 'all', $order = 'DESC', $limit = 1, $firstId = '', $filter = '', $date_min = 0, $showOlderUnreadsorFavorites = false, $keepHistoryDefault = 0) {
  491. list($values, $sql) = $this->sqlListWhere($type, $id, $state, $order, $limit, $firstId, $filter, $date_min, $showOlderUnreadsorFavorites, $keepHistoryDefault);
  492. $sql = 'SELECT e.id, e.guid, e.title, e.author, UNCOMPRESS(e.content_bin) AS content, e.link, e.date, e.is_read, e.is_favorite, e.id_feed, e.tags '
  493. . 'FROM `' . $this->prefix . 'entry` e '
  494. . 'INNER JOIN ('
  495. . $sql
  496. . ') e2 ON e2.id = e.id '
  497. . 'ORDER BY e.id ' . $order;
  498. $stm = $this->bd->prepare ($sql);
  499. $stm->execute ($values);
  500. return self::daoToEntry ($stm->fetchAll (PDO::FETCH_ASSOC));
  501. }
  502. public function listIdsWhere($type = 'a', $id = '', $state = 'all', $order = 'DESC', $limit = 1, $firstId = '', $filter = '', $date_min = 0, $showOlderUnreadsorFavorites = false, $keepHistoryDefault = 0) { //For API
  503. list($values, $sql) = $this->sqlListWhere($type, $id, $state, $order, $limit, $firstId, $filter, $date_min, $showOlderUnreadsorFavorites, $keepHistoryDefault);
  504. $stm = $this->bd->prepare($sql);
  505. $stm->execute($values);
  506. return $stm->fetchAll(PDO::FETCH_COLUMN, 0);
  507. }
  508. public function listLastGuidsByFeed($id, $n) {
  509. $sql = 'SELECT guid FROM `' . $this->prefix . 'entry` WHERE id_feed=? ORDER BY id DESC LIMIT ' . intval($n);
  510. $stm = $this->bd->prepare ($sql);
  511. $values = array ($id);
  512. $stm->execute ($values);
  513. return $stm->fetchAll (PDO::FETCH_COLUMN, 0);
  514. }
  515. public function countUnreadRead () {
  516. $sql = 'SELECT COUNT(e.id) AS count FROM `' . $this->prefix . 'entry` e INNER JOIN `' . $this->prefix . 'feed` f ON e.id_feed = f.id WHERE priority > 0'
  517. . ' UNION SELECT COUNT(e.id) AS count FROM `' . $this->prefix . 'entry` e INNER JOIN `' . $this->prefix . 'feed` f ON e.id_feed = f.id WHERE priority > 0 AND is_read = 0';
  518. $stm = $this->bd->prepare ($sql);
  519. $stm->execute ();
  520. $res = $stm->fetchAll (PDO::FETCH_COLUMN, 0);
  521. $all = empty($res[0]) ? 0 : $res[0];
  522. $unread = empty($res[1]) ? 0 : $res[1];
  523. return array('all' => $all, 'unread' => $unread, 'read' => $all - $unread);
  524. }
  525. public function count ($minPriority = null) {
  526. $sql = 'SELECT COUNT(e.id) AS count FROM `' . $this->prefix . 'entry` e INNER JOIN `' . $this->prefix . 'feed` f ON e.id_feed = f.id';
  527. if ($minPriority !== null) {
  528. $sql = ' WHERE priority > ' . intval($minPriority);
  529. }
  530. $stm = $this->bd->prepare ($sql);
  531. $stm->execute ();
  532. $res = $stm->fetchAll (PDO::FETCH_COLUMN, 0);
  533. return $res[0];
  534. }
  535. public function countNotRead ($minPriority = null) {
  536. $sql = 'SELECT COUNT(e.id) AS count FROM `' . $this->prefix . 'entry` e INNER JOIN `' . $this->prefix . 'feed` f ON e.id_feed = f.id WHERE is_read = 0';
  537. if ($minPriority !== null) {
  538. $sql = ' AND priority > ' . intval($minPriority);
  539. }
  540. $stm = $this->bd->prepare ($sql);
  541. $stm->execute ();
  542. $res = $stm->fetchAll (PDO::FETCH_COLUMN, 0);
  543. return $res[0];
  544. }
  545. public function countUnreadReadFavorites () {
  546. $sql = 'SELECT COUNT(id) FROM `' . $this->prefix . 'entry` WHERE is_favorite=1'
  547. . ' UNION SELECT COUNT(id) FROM `' . $this->prefix . 'entry` WHERE is_favorite=1 AND is_read = 0';
  548. $stm = $this->bd->prepare ($sql);
  549. $stm->execute ();
  550. $res = $stm->fetchAll (PDO::FETCH_COLUMN, 0);
  551. $all = empty($res[0]) ? 0 : $res[0];
  552. $unread = empty($res[1]) ? 0 : $res[1];
  553. return array('all' => $all, 'unread' => $unread, 'read' => $all - $unread);
  554. }
  555. public function optimizeTable() {
  556. $sql = 'OPTIMIZE TABLE `' . $this->prefix . 'entry`';
  557. $stm = $this->bd->prepare ($sql);
  558. $stm->execute ();
  559. }
  560. public static function daoToEntry ($listDAO) {
  561. $list = array ();
  562. if (!is_array ($listDAO)) {
  563. $listDAO = array ($listDAO);
  564. }
  565. foreach ($listDAO as $key => $dao) {
  566. $entry = new FreshRSS_Entry (
  567. $dao['id_feed'],
  568. $dao['guid'],
  569. $dao['title'],
  570. $dao['author'],
  571. $dao['content'],
  572. $dao['link'],
  573. $dao['date'],
  574. $dao['is_read'],
  575. $dao['is_favorite'],
  576. $dao['tags']
  577. );
  578. if (isset ($dao['id'])) {
  579. $entry->_id ($dao['id']);
  580. }
  581. $list[] = $entry;
  582. }
  583. unset ($listDAO);
  584. return $list;
  585. }
  586. }