entryController.php 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227
  1. <?php
  2. declare(strict_types=1);
  3. /**
  4. * Controller to handle every entry actions.
  5. */
  6. class FreshRSS_entry_Controller extends FreshRSS_ActionController {
  7. /**
  8. * JavaScript request or not.
  9. */
  10. private bool $ajax = false;
  11. /**
  12. * This action is called before every other action in that class. It is
  13. * the common boilerplate for every action. It is triggered by the
  14. * underlying framework.
  15. */
  16. public function firstAction(): void {
  17. if (!FreshRSS_Auth::hasAccess()) {
  18. Minz_Error::error(403);
  19. }
  20. // If ajax request, we do not print layout
  21. $this->ajax = Minz_Request::paramBoolean('ajax');
  22. if ($this->ajax) {
  23. $this->view->_layout(null);
  24. Minz_Request::_param('ajax');
  25. }
  26. }
  27. /**
  28. * Mark one or several entries as read (or not!).
  29. *
  30. * If request concerns several entries, it MUST be a POST request.
  31. * If request concerns several entries, only mark them as read is available.
  32. *
  33. * Parameters are:
  34. * - id (default: false)
  35. * - get (default: false) /(c_\d+|f_\d+|s|a)/
  36. * - nextGet (default: $get)
  37. * - idMax (default: 0)
  38. * - is_read (default: true)
  39. */
  40. public function readAction(): void {
  41. $id = Minz_Request::param('id');
  42. $get = Minz_Request::paramString('get');
  43. $next_get = Minz_Request::paramString('nextGet') ?: $get;
  44. $id_max = Minz_Request::paramString('idMax') ?: '0';
  45. $is_read = Minz_Request::paramTernary('is_read') ?? true;
  46. FreshRSS_Context::$search = new FreshRSS_BooleanSearch(Minz_Request::paramString('search'));
  47. FreshRSS_Context::$state = Minz_Request::paramInt('state');
  48. if (FreshRSS_Context::isStateEnabled(FreshRSS_Entry::STATE_FAVORITE)) {
  49. FreshRSS_Context::$state = FreshRSS_Entry::STATE_FAVORITE;
  50. } elseif (FreshRSS_Context::isStateEnabled(FreshRSS_Entry::STATE_NOT_FAVORITE)) {
  51. FreshRSS_Context::$state = FreshRSS_Entry::STATE_NOT_FAVORITE;
  52. } else {
  53. FreshRSS_Context::$state = 0;
  54. }
  55. $params = [];
  56. $this->view->tagsForEntries = [];
  57. $entryDAO = FreshRSS_Factory::createEntryDao();
  58. if ($id == false) {
  59. // id is false? It MUST be a POST request!
  60. if (!Minz_Request::isPost()) {
  61. Minz_Request::bad(_t('feedback.access.not_found'), ['c' => 'index', 'a' => 'index']);
  62. return;
  63. }
  64. if (!$get) {
  65. // No get? Mark all entries as read (from $id_max)
  66. $entryDAO->markReadEntries($id_max, false, FreshRSS_Feed::PRIORITY_MAIN_STREAM, FreshRSS_Feed::PRIORITY_IMPORTANT, null, 0, $is_read);
  67. } else {
  68. $type_get = $get[0];
  69. $get = (int)substr($get, 2);
  70. switch($type_get) {
  71. case 'c':
  72. $entryDAO->markReadCat($get, $id_max, FreshRSS_Context::$search, FreshRSS_Context::$state, $is_read);
  73. break;
  74. case 'f':
  75. $entryDAO->markReadFeed($get, $id_max, FreshRSS_Context::$search, FreshRSS_Context::$state, $is_read);
  76. break;
  77. case 's':
  78. $entryDAO->markReadEntries($id_max, true, null, FreshRSS_Feed::PRIORITY_IMPORTANT,
  79. FreshRSS_Context::$search, FreshRSS_Context::$state, $is_read);
  80. break;
  81. case 'a':
  82. $entryDAO->markReadEntries($id_max, false, FreshRSS_Feed::PRIORITY_MAIN_STREAM, FreshRSS_Feed::PRIORITY_IMPORTANT,
  83. FreshRSS_Context::$search, FreshRSS_Context::$state, $is_read);
  84. break;
  85. case 'i':
  86. $entryDAO->markReadEntries($id_max, false, FreshRSS_Feed::PRIORITY_IMPORTANT, null,
  87. FreshRSS_Context::$search, FreshRSS_Context::$state, $is_read);
  88. break;
  89. case 't':
  90. $entryDAO->markReadTag($get, $id_max, FreshRSS_Context::$search, FreshRSS_Context::$state, $is_read);
  91. break;
  92. case 'T':
  93. $entryDAO->markReadTag(0, $id_max, FreshRSS_Context::$search, FreshRSS_Context::$state, $is_read);
  94. break;
  95. }
  96. if ($next_get !== 'a') {
  97. // Redirect to the correct page (category, feed or starred)
  98. // Not "a" because it is the default value if nothing is given.
  99. $params['get'] = $next_get;
  100. }
  101. }
  102. } else {
  103. $ids = is_array($id) ? $id : [$id];
  104. $entryDAO->markRead($ids, $is_read);
  105. $tagDAO = FreshRSS_Factory::createTagDao();
  106. $tagsForEntries = $tagDAO->getTagsForEntries($ids) ?: [];
  107. $tags = [];
  108. foreach ($tagsForEntries as $line) {
  109. $tags['t_' . $line['id_tag']][] = $line['id_entry'];
  110. }
  111. $this->view->tagsForEntries = $tags;
  112. }
  113. if (!$this->ajax) {
  114. Minz_Request::good(
  115. $is_read ? _t('feedback.sub.articles.marked_read') : _t('feedback.sub.articles.marked_unread'),
  116. [
  117. 'c' => 'index',
  118. 'a' => 'index',
  119. 'params' => $params,
  120. ]
  121. );
  122. }
  123. }
  124. /**
  125. * This action marks an entry as favourite (bookmark) or not.
  126. *
  127. * Parameter is:
  128. * - id (default: false)
  129. * - is_favorite (default: true)
  130. * If id is false, nothing happened.
  131. */
  132. public function bookmarkAction(): void {
  133. $id = Minz_Request::paramString('id');
  134. $is_favourite = Minz_Request::paramTernary('is_favorite') ?? true;
  135. if ($id != '') {
  136. $entryDAO = FreshRSS_Factory::createEntryDao();
  137. $entryDAO->markFavorite($id, $is_favourite);
  138. }
  139. if (!$this->ajax) {
  140. Minz_Request::forward([
  141. 'c' => 'index',
  142. 'a' => 'index',
  143. ], true);
  144. }
  145. }
  146. /**
  147. * This action optimizes database to reduce its size.
  148. *
  149. * This action should be reached by a POST request.
  150. *
  151. * @todo move this action in configure controller.
  152. * @todo call this action through web-cron when available
  153. */
  154. public function optimizeAction(): void {
  155. $url_redirect = [
  156. 'c' => 'configure',
  157. 'a' => 'archiving',
  158. ];
  159. if (!Minz_Request::isPost()) {
  160. Minz_Request::forward($url_redirect, true);
  161. }
  162. if (function_exists('set_time_limit')) {
  163. @set_time_limit(300);
  164. }
  165. $databaseDAO = FreshRSS_Factory::createDatabaseDAO();
  166. $databaseDAO->optimize();
  167. $feedDAO = FreshRSS_Factory::createFeedDao();
  168. $feedDAO->updateCachedValues();
  169. invalidateHttpCache();
  170. Minz_Request::good(_t('feedback.admin.optimization_complete'), $url_redirect);
  171. }
  172. /**
  173. * This action purges old entries from feeds.
  174. *
  175. * @todo should be a POST request
  176. * @todo should be in feedController
  177. */
  178. public function purgeAction(): void {
  179. if (function_exists('set_time_limit')) {
  180. @set_time_limit(300);
  181. }
  182. $feedDAO = FreshRSS_Factory::createFeedDao();
  183. $feeds = $feedDAO->listFeeds();
  184. $nb_total = 0;
  185. invalidateHttpCache();
  186. $feedDAO->beginTransaction();
  187. foreach ($feeds as $feed) {
  188. $nb_total += ($feed->cleanOldEntries() ?: 0);
  189. }
  190. $feedDAO->updateCachedValues();
  191. $feedDAO->commit();
  192. $databaseDAO = FreshRSS_Factory::createDatabaseDAO();
  193. $databaseDAO->minorDbMaintenance();
  194. invalidateHttpCache();
  195. Minz_Request::good(_t('feedback.sub.purge_completed', $nb_total), [
  196. 'c' => 'configure',
  197. 'a' => 'archiving',
  198. ]);
  199. }
  200. }