From 32306a78d2e53bbbc864f3eabda9a2f1a3dd2322 Mon Sep 17 00:00:00 2001 From: Alexandre Alapetite Date: Sat, 16 Nov 2013 21:03:25 +0100 Subject: SQL : grosse mise à jour avec mise en cache du nombre d'articles lus/non-lus MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Mise en cache du nombre d'articles lus et non-lus par flux, via `f.cache_nbEntries, f.cache_nbUnreads` pour de biens meilleures performances * Implémente https://github.com/marienfressinaud/FreshRSS/issues/268 * Révision de la plupart des requêtes de modification en conséquence * En cas d'affichage `not_read`, évite de faire une requête si on sait déjà qu'il n'y a pas d'article non lu et fait directement un affichage `all`. * Appelle `cleanOldEntries` seulement une fois de temps en temps aléatoirement (1 fois sur 30 actuellement) pour économiser les ressources, et avant les insertions pour plus de robustesse. * Utilisation des transactions lors de mises à jour multiples et liées * Lors de requêtes de modifications, retourne le nombre de lignes impactées plutôt qu'un booléen en cas de succès * Suppression de code oublié relatif à is_public qui n'est plus utilisé --- app/models/EntriesGetter.php | 8 -------- 1 file changed, 8 deletions(-) (limited to 'app/models/EntriesGetter.php') diff --git a/app/models/EntriesGetter.php b/app/models/EntriesGetter.php index 803aad732..ce026f252 100644 --- a/app/models/EntriesGetter.php +++ b/app/models/EntriesGetter.php @@ -117,14 +117,6 @@ class EntriesGetter { $sqlLimit ); break; - case 'public': - list ($this->entries, $this->next) = $entryDAO->listPublic ( - $this->state, - $this->order, - $this->first, - $sqlLimit - ); - break; case 'c': list ($this->entries, $this->next) = $entryDAO->listByCategory ( $this->type['id'], -- cgit v1.2.3 From 37ce14c093c3dd009bcd7b627c5e819ac88dd5b7 Mon Sep 17 00:00:00 2001 From: Alexandre Alapetite Date: Sat, 30 Nov 2013 17:21:26 +0100 Subject: Recherche côté SQL avec LIKE MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Premier essai de recherche côté base de données (à améliorer) https://github.com/marienfressinaud/FreshRSS/issues/204 Pour l'instant fait avec du LIKE et pas d'indexation texte complet. * Suppression de EntriesGetter car le code est devenu plus simple grâce au filtrage côté SQL * Uniformisation de get_c à une lettre ('all' devient 'a','favoris' devient 's' - pour "starred") pour simplifier le code * low_to_high par DESC, high_to_low par ASC * Réduction du nombre de créations de *DAO dans indexController * Refactorisation de checkAndProcessType() Pas encore trop testé... --- app/App_FrontController.php | 1 - app/controllers/configureController.php | 4 +- app/controllers/indexController.php | 254 +++++++++++++++----------------- app/layout/aside_flux.phtml | 4 +- app/layout/nav_menu.phtml | 13 +- app/models/EntriesGetter.php | 148 ------------------- app/models/Entry.php | 213 ++++++++++---------------- app/models/RSSConfiguration.php | 8 +- app/views/configure/display.phtml | 4 +- 9 files changed, 214 insertions(+), 435 deletions(-) delete mode 100644 app/models/EntriesGetter.php (limited to 'app/models/EntriesGetter.php') diff --git a/app/App_FrontController.php b/app/App_FrontController.php index 40e31f549..d701e2944 100644 --- a/app/App_FrontController.php +++ b/app/App_FrontController.php @@ -33,7 +33,6 @@ class App_FrontController extends FrontController { include (APP_PATH . '/models/Category.php'); include (APP_PATH . '/models/Feed.php'); include (APP_PATH . '/models/Entry.php'); - include (APP_PATH . '/models/EntriesGetter.php'); include (APP_PATH . '/models/RSSPaginator.php'); include (APP_PATH . '/models/Log_Model.php'); } diff --git a/app/controllers/configureController.php b/app/controllers/configureController.php index af6140b5d..424e3834a 100755 --- a/app/controllers/configureController.php +++ b/app/controllers/configureController.php @@ -158,12 +158,12 @@ class configureController extends ActionController { $language = Request::param ('language', 'en'); $nb = Request::param ('posts_per_page', 10); $mode = Request::param ('view_mode', 'normal'); - $view = Request::param ('default_view', 'all'); + $view = Request::param ('default_view', 'a'); $auto_load_more = Request::param ('auto_load_more', 'no'); $display = Request::param ('display_posts', 'no'); $onread_jump_next = Request::param ('onread_jump_next', 'no'); $lazyload = Request::param ('lazyload', 'no'); - $sort = Request::param ('sort_order', 'low_to_high'); + $sort = Request::param ('sort_order', 'DESC'); $old = Request::param ('old_entries', 3); $mail = Request::param ('mail_login', false); $anon = Request::param ('anon_access', 'no'); diff --git a/app/controllers/indexController.php b/app/controllers/indexController.php index 8e6abd682..cf0e5024a 100755 --- a/app/controllers/indexController.php +++ b/app/controllers/indexController.php @@ -3,19 +3,29 @@ class indexController extends ActionController { private $get = false; private $nb_not_read_cat = 0; + private $entryDAO; + private $feedDAO; + private $catDAO; + + function __construct($router) { + parent::__construct($router); + $this->entryDAO = new EntryDAO (); + $this->feedDAO = new FeedDAO (); + $this->catDAO = new CategoryDAO (); + } public function indexAction () { $output = Request::param ('output'); $token = $this->view->conf->token(); $token_param = Request::param ('token', ''); - $token_is_ok = ($token != '' && $token == $token_param); + $token_is_ok = ($token != '' && $token === $token_param); // check if user is log in if(login_is_conf ($this->view->conf) && !is_logged() && - $this->view->conf->anonAccess() == 'no' && - !($output == 'rss' && $token_is_ok)) { + $this->view->conf->anonAccess() === 'no' && + !($output === 'rss' && $token_is_ok)) { return; } @@ -26,7 +36,7 @@ class indexController extends ActionController { $params['search'] = urlencode ($params['search']); } if (login_is_conf($this->view->conf) && - $this->view->conf->anonAccess() == 'no' && + $this->view->conf->anonAccess() === 'no' && $token != '') { $params['token'] = $token; } @@ -38,32 +48,25 @@ class indexController extends ActionController { $this->view->rss_title = View::title(); - if ($output == 'rss') { + if ($output === 'rss') { // no layout for RSS output $this->view->_useLayout (false); header('Content-Type: application/rss+xml; charset=utf-8'); } else { View::appendScript (Url::display ('/scripts/shortcut.js?' . @filemtime(PUBLIC_PATH . '/scripts/shortcut.js'))); - if ($output == 'global') { + if ($output === 'global') { View::appendScript (Url::display ('/scripts/global_view.js?' . @filemtime(PUBLIC_PATH . '/scripts/global_view.js'))); } } - $entryDAO = new EntryDAO (); - $feedDAO = new FeedDAO (); - $catDAO = new CategoryDAO (); - - $this->view->cat_aside = $catDAO->listCategories (); - $this->view->nb_favorites = $entryDAO->countUnreadReadFavorites (); + $this->view->cat_aside = $this->catDAO->listCategories (); + $this->view->nb_favorites = $this->entryDAO->countUnreadReadFavorites (); $this->view->currentName = ''; $this->view->get_c = ''; $this->view->get_f = ''; - $type = $this->getType (); - $error = $this->checkAndProcessType ($type); - // mise à jour des titres $this->view->nb_not_read = HelperCategory::CountUnreads($this->view->cat_aside, 1); if ($this->view->nb_not_read > 0) { @@ -77,63 +80,73 @@ class indexController extends ActionController { ($this->nb_not_read_cat > 0 ? ' (' . $this->nb_not_read_cat . ')' : '') ); - if (!$error) { - // On récupère les différents éléments de filtrage - $this->view->state = $state = Request::param ('state', $this->view->conf->defaultView ()); - $filter = Request::param ('search', ''); - $this->view->order = $order = Request::param ('order', $this->view->conf->sortOrder ()); - $nb = Request::param ('nb', $this->view->conf->postsPerPage ()); - $first = Request::param ('next', ''); - - if ($state === 'not_read') { //Any unread article in this category at all? - switch ($type['type']) { - case 'all': - $hasUnread = $this->view->nb_not_read > 0; - break; - case 'favoris': - $hasUnread = $this->view->nb_favorites['unread'] > 0; - break; - case 'c': - $hasUnread = (!isset($this->view->cat_aside[$type['id']])) || ($this->view->cat_aside[$type['id']]->nbNotRead() > 0); - break; - case 'f': - $myFeed = HelperCategory::findFeed($this->view->cat_aside, $type['id']); - $hasUnread = ($myFeed === null) || ($myFeed->nbNotRead() > 0); - break; - default: - $hasUnread = true; - break; - } - if (!$hasUnread) { - $this->view->state = $state = 'all'; - } + $get = Request::param ('get', 'a'); + $getType = $get[0]; + $getId = substr ($get, 2); + if (!$this->checkAndProcessType ($getType, $getId)) { + Minz_Log::record ('Not found [' . $getType . '][' . $getId . ']', Minz_Log::DEBUG); + Error::error ( + 404, + array ('error' => array (Translate::t ('page_not_found'))) + ); + return; + } + + // On récupère les différents éléments de filtrage + $this->view->state = $state = Request::param ('state', $this->view->conf->defaultView ()); + $filter = Request::param ('search', ''); + if (!empty($filter)) { + $state = 'all'; //Search always in read and unread articles + } + $this->view->order = $order = Request::param ('order', $this->view->conf->sortOrder ()); + $nb = Request::param ('nb', $this->view->conf->postsPerPage ()); + $first = Request::param ('next', ''); + + if ($state === 'not_read') { //Any unread article in this category at all? + switch ($getType) { + case 'a': + $hasUnread = $this->view->nb_not_read > 0; + break; + case 's': + $hasUnread = $this->view->nb_favorites['unread'] > 0; + break; + case 'c': + $hasUnread = (!isset($this->view->cat_aside[$getId])) || ($this->view->cat_aside[$getId]->nbNotRead() > 0); + break; + case 'f': + $myFeed = HelperCategory::findFeed($this->view->cat_aside, $getId); + $hasUnread = ($myFeed === null) || ($myFeed->nbNotRead() > 0); + break; + default: + $hasUnread = true; + break; } + if (!$hasUnread) { + $this->view->state = $state = 'all'; + } + } - try { - // EntriesGetter permet de déporter la complexité du filtrage - $getter = new EntriesGetter ($type, $state, $filter, $order, $nb, $first); - $getter->execute (); - $entries = $getter->getPaginator (); - - // Si on a récupéré aucun article "non lus" - // on essaye de récupérer tous les articles - if ($state === 'not_read' && $entries->isEmpty ()) { //TODO: Remove in v0.8 - Minz_Log::record ('Conflicting information about nbNotRead!', Minz_Log::DEBUG); - $this->view->state = 'all'; - $getter->_state ('all'); - $getter->execute (); - $entries = $getter->getPaginator (); - } + try { + $entries = $this->entryDAO->listWhere($getType, $getId, $state, $order, $nb + 1, $first, $filter); + + // Si on a récupéré aucun article "non lus" + // on essaye de récupérer tous les articles + if ($state === 'not_read' && empty($entries)) { //TODO: Remove in v0.8 + Minz_Log::record ('Conflicting information about nbNotRead!', Minz_Log::DEBUG); + $this->view->state = 'all'; + $entries = $this->entryDAO->listWhere($getType, $getId, 'all', $order, $nb, $first, $filter); + } - $this->view->entryPaginator = $entries; - } catch (EntriesGetterException $e) { - Minz_Log::record ($e->getMessage (), Minz_Log::NOTICE); - Error::error ( - 404, - array ('error' => array (Translate::t ('page_not_found'))) - ); + if (count($entries) <= $nb) { + $next = ''; + } else { //We have more elements for pagination + $lastEntry = array_pop($entries); + $next = $lastEntry->id(); } - } else { + + $this->view->entryPaginator = new RSSPaginator ($entries, $next); + } catch (EntriesGetterException $e) { + Minz_Log::record ($e->getMessage (), Minz_Log::NOTICE); Error::error ( 404, array ('error' => array (Translate::t ('page_not_found'))) @@ -141,79 +154,50 @@ class indexController extends ActionController { } } - /* - * Détermine le type d'article à récupérer : - * "tous", "favoris", "public", "catégorie" ou "flux" - */ - private function getType () { - $get = Request::param ('get', 'all'); - $typeGet = $get[0]; - $id = substr ($get, 2); - - $type = null; - if ($get == 'all' || $get == 'favoris' || $get == 'public') { - $type = array ( - 'type' => $get, - 'id' => $get - ); - } elseif ($typeGet == 'f' || $typeGet == 'c') { - $type = array ( - 'type' => $typeGet, - 'id' => $id - ); - } - - return $type; - } /* * Vérifie que la catégorie / flux sélectionné existe * + Initialise correctement les variables de vue get_c et get_f * + Met à jour la variable $this->nb_not_read_cat */ - private function checkAndProcessType ($type) { - if ($type['type'] == 'all') { - $this->view->currentName = Translate::t ('your_rss_feeds'); - $this->view->get_c = $type['type']; - return false; - } elseif ($type['type'] == 'favoris') { - $this->view->currentName = Translate::t ('your_favorites'); - $this->view->get_c = $type['type']; - return false; - } elseif ($type['type'] == 'public') { - $this->view->currentName = Translate::t ('public'); - $this->view->get_c = $type['type']; - return false; - } elseif ($type['type'] == 'c') { - $cat = isset($this->view->cat_aside[$type['id']]) ? $this->view->cat_aside[$type['id']] : null; - if ($cat === null) { - $catDAO = new CategoryDAO (); - $cat = $catDAO->searchById ($type['id']); - } - if ($cat) { - $this->view->currentName = $cat->name (); - $this->nb_not_read_cat = $cat->nbNotRead (); - $this->view->get_c = $type['id']; - return false; - } else { + private function checkAndProcessType ($getType, $getId) { + switch ($getType) { + case 'a': + $this->view->currentName = Translate::t ('your_rss_feeds'); + $this->view->get_c = $getType; return true; - } - } elseif ($type['type'] == 'f') { - $feed = HelperCategory::findFeed($this->view->cat_aside, $type['id']); - if (empty($feed)) { - $feedDAO = new FeedDAO (); - $feed = $feedDAO->searchById ($type['id']); - } - if ($feed) { - $this->view->currentName = $feed->name (); - $this->nb_not_read_cat = $feed->nbNotRead (); - $this->view->get_f = $type['id']; - $this->view->get_c = $feed->category (); - return false; - } else { + case 's': + $this->view->currentName = Translate::t ('your_favorites'); + $this->view->get_c = $getType; return true; - } - } else { - return true; + case 'c': + $cat = isset($this->view->cat_aside[$getId]) ? $this->view->cat_aside[$getId] : null; + if ($cat === null) { + $cat = $this->catDAO->searchById ($getId); + } + if ($cat) { + $this->view->currentName = $cat->name (); + $this->nb_not_read_cat = $cat->nbNotRead (); + $this->view->get_c = $getId; + return true; + } else { + return false; + } + case 'f': + $feed = HelperCategory::findFeed($this->view->cat_aside, $getId); + if (empty($feed)) { + $feed = $this->feedDAO->searchById ($getId); + } + if ($feed) { + $this->view->currentName = $feed->name (); + $this->nb_not_read_cat = $feed->nbNotRead (); + $this->view->get_f = $getId; + $this->view->get_c = $feed->category (); + return true; + } else { + return false; + } + default: + return false; } } @@ -270,7 +254,7 @@ class indexController extends ActionController { curl_close ($ch); $res = json_decode ($result, true); - if ($res['status'] == 'okay' && $res['email'] == $this->view->conf->mailLogin ()) { + if ($res['status'] === 'okay' && $res['email'] === $this->view->conf->mailLogin ()) { Session::_param ('mail', $res['email']); invalidateHttpCache(); } else { diff --git a/app/layout/aside_flux.phtml b/app/layout/aside_flux.phtml index 918a44e01..ce5ded230 100644 --- a/app/layout/aside_flux.phtml +++ b/app/layout/aside_flux.phtml @@ -15,7 +15,7 @@
  • - + @@ -24,7 +24,7 @@
  • - + nb_favorites['all']); ?> diff --git a/app/layout/nav_menu.phtml b/app/layout/nav_menu.phtml index 0b95b4b02..289fe6542 100644 --- a/app/layout/nav_menu.phtml +++ b/app/layout/nav_menu.phtml @@ -11,9 +11,8 @@ $get = 'f_' . $this->get_f; $string_mark = Translate::t ('mark_feed_read'); } elseif ($this->get_c && - $this->get_c != 'all' && - $this->get_c != 'favoris' && - $this->get_c != 'public') { + $this->get_c != 'a' && + $this->get_c != 's') { $get = 'c_' . $this->get_c; $string_mark = Translate::t ('mark_cat_read'); } @@ -34,7 +33,7 @@ $anotherUnreadId = $cat->id (); if ($foundCurrent) break; } - $nextGet = empty ($anotherUnreadId) ? 'all' : 'c_' . $anotherUnreadId; + $nextGet = empty ($anotherUnreadId) ? 'a' : 'c_' . $anotherUnreadId; break; case 'f': foreach ($this->cat_aside as $cat) { @@ -149,15 +148,15 @@
  • order == 'low_to_high') { - $url_order['params']['order'] = 'high_to_low'; + if ($this->order === 'DESC') { + $url_order['params']['order'] = 'ASC'; ?> diff --git a/app/models/EntriesGetter.php b/app/models/EntriesGetter.php deleted file mode 100644 index ce026f252..000000000 --- a/app/models/EntriesGetter.php +++ /dev/null @@ -1,148 +0,0 @@ - 'all', - 'id' => 'all' - ); - private $state = 'all'; - private $filter = array ( - 'words' => array (), - 'tags' => array (), - ); - private $order = 'high_to_low'; - private $entries = array (); - - private $nb = 1; - private $first = ''; - private $next = ''; - - public function __construct ($type, $state, $filter, $order, $nb, $first = '') { - $this->_type ($type); - $this->_state ($state); - $this->_filter ($filter); - $this->_order ($order); - $this->nb = $nb; - $this->first = $first; - } - - public function type () { - return $this->type; - } - public function state () { - return $this->state; - } - public function filter () { - return $this->filter; - } - public function order () { - return $this->order; - } - public function entries () { - return $this->entries; - } - - public function _type ($value) { - if (!is_array ($value) || - !isset ($value['type']) || - !isset ($value['id'])) { - throw new EntriesGetterException ('Bad type line ' . __LINE__ . ' in file ' . __FILE__); - } - - $type = $value['type']; - $id = $value['id']; - - if ($type != 'all' && $type != 'favoris' && $type != 'public' && $type != 'c' && $type != 'f') { - throw new EntriesGetterException ('Bad type line ' . __LINE__ . ' in file ' . __FILE__); - } - - if (($type == 'all' || $type == 'favoris' || $type == 'public') && - ($type != $id)) { - throw new EntriesGetterException ('Bad type line ' . __LINE__ . ' in file ' . __FILE__); - } - - $this->type = $value; - } - public function _state ($value) { - if ($value != 'all' && $value != 'not_read' && $value != 'read') { - throw new EntriesGetterException ('Bad state line ' . __LINE__ . ' in file ' . __FILE__); - } - - $this->state = $value; - } - public function _filter ($value) { - $value = trim ($value); - $terms = explode (' ', $value); - - foreach ($terms as $word) { - if (!empty ($word) && $word[0] == '#' && isset ($word[1])) { - $tag = substr ($word, 1); - $this->filter['tags'][$tag] = $tag; - } elseif (!empty ($word)) { - $this->filter['words'][$word] = $word; - } - } - } - public function _order ($value) { - if ($value != 'high_to_low' && $value != 'low_to_high') { - throw new EntriesGetterException ('Bad order line ' . __LINE__ . ' in file ' . __FILE__); - } - - $this->order = $value; - } - - public function execute () { - $entryDAO = new EntryDAO (); - - HelperEntry::$nb = $this->nb; //TODO: Update: Now done in SQL - HelperEntry::$first = $this->first; //TODO: Update: Now done in SQL - HelperEntry::$filter = $this->filter; - - $sqlLimit = (empty ($this->filter['words']) && empty ($this->filter['tags'])) ? $this->nb : ''; //Disable SQL LIMIT optimisation during search //TODO: Do better! - - switch ($this->type['type']) { - case 'all': - list ($this->entries, $this->next) = $entryDAO->listEntries ( - $this->state, - $this->order, - $this->first, - $sqlLimit - ); - break; - case 'favoris': - list ($this->entries, $this->next) = $entryDAO->listFavorites ( - $this->state, - $this->order, - $this->first, - $sqlLimit - ); - break; - case 'c': - list ($this->entries, $this->next) = $entryDAO->listByCategory ( - $this->type['id'], - $this->state, - $this->order, - $this->first, - $sqlLimit - ); - break; - case 'f': - list ($this->entries, $this->next) = $entryDAO->listByFeed ( - $this->type['id'], - $this->state, - $this->order, - $this->first, - $sqlLimit - ); - break; - default: - throw new EntriesGetterException ('Bad type line ' . __LINE__ . ' in file ' . __FILE__); - } - } - - public function getPaginator () { - $paginator = new RSSPaginator ($this->entries, $this->next); - - return $paginator; - } -} diff --git a/app/models/Entry.php b/app/models/Entry.php index 894985ece..915fbccc8 100755 --- a/app/models/Entry.php +++ b/app/models/Entry.php @@ -15,7 +15,7 @@ class Entry extends Model { private $tags; public function __construct ($feed = '', $guid = '', $title = '', $author = '', $content = '', - $link = '', $pubdate = 0, $is_read = false, $is_favorite = false) { + $link = '', $pubdate = 0, $is_read = false, $is_favorite = false, $tags = '') { $this->_guid ($guid); $this->_title ($title); $this->_author ($author); @@ -25,7 +25,7 @@ class Entry extends Model { $this->_isRead ($is_read); $this->_isFavorite ($is_favorite); $this->_feed ($feed); - $this->_tags (array ()); + $this->_tags (preg_split('/[\s#]/', $tags)); } public function id () { @@ -81,11 +81,7 @@ class Entry extends Model { } public function tags ($inString = false) { if ($inString) { - if (!empty ($this->tags)) { - return '#' . implode(' #', $this->tags); - } else { - return ''; - } + return empty ($this->tags) ? '' : '#' . implode(' #', $this->tags); } else { return $this->tags; } @@ -110,8 +106,8 @@ class Entry extends Model { $this->link = $value; } public function _date ($value) { - if (is_int (intval ($value))) { - $this->date = $value; + if (is_int ($value)) { + $this->date = intval ($value); } else { $this->date = time (); } @@ -448,13 +444,8 @@ class EntryDAO extends Model_pdo { $stm->execute ($values); $res = $stm->fetchAll (PDO::FETCH_ASSOC); - list ($entry, $next) = HelperEntry::daoToEntry ($res); - - if (isset ($entry[0])) { - return $entry[0]; - } else { - return false; - } + $entries = HelperEntry::daoToEntry ($res); + return isset ($entries[0]) ? $entries[0] : false; } public function searchById ($id) { @@ -466,60 +457,79 @@ class EntryDAO extends Model_pdo { $stm->execute ($values); $res = $stm->fetchAll (PDO::FETCH_ASSOC); - list ($entry, $next) = HelperEntry::daoToEntry ($res); - - if (isset ($entry[0])) { - return $entry[0]; - } else { - return false; + $entries = HelperEntry::daoToEntry ($res); + return isset ($entries[0]) ? $entries[0] : false; + } + + public function listWhere($type = 'a', $id = '', $state = 'all', $order = 'DESC', $limit = 1, $firstId = -1, $filter = '') { + $where = ''; + $values = array(); + switch ($type) { + case 'a': + $where .= 'priority > 0 '; + break; + case 's': + $where .= 'is_favorite = 1 '; + break; + case 'c': + $where .= 'category = ? '; + $values[] = intval($id); + break; + case 'f': + $where .= 'id_feed = ? '; + $values[] = intval($id); + break; + default: + throw new EntriesGetterException ('Bad type in Entry->listByType: [' . $type . ']!'); } - } - - private function listWhere ($where, $state, $order, $limitFromId = '', $limitCount = '', $values = array ()) { - if ($state === 'not_read') { - $where .= ' AND is_read = 0'; - } elseif ($state === 'read') { - $where .= ' AND is_read = 1'; + switch ($state) { + case 'all': + break; + case 'not_read': + $where .= 'AND is_read = 0 '; + break; + case 'read': + $where .= 'AND is_read = 1 '; + break; + default: + throw new EntriesGetterException ('Bad state in Entry->listByType: [' . $state . ']!'); } - if (!empty($limitFromId)) { - $where .= ' AND e.id ' . ($order === 'low_to_high' ? '<=' : '>=') . $limitFromId; + switch ($order) { + case 'DESC': + case 'ASC': + break; + default: + throw new EntriesGetterException ('Bad order in Entry->listByType: [' . $order . ']!'); } - - if ($order === 'low_to_high') { - $order = ' DESC'; - } else { - $order = ''; + if ($firstId > 0) { + $where .= 'AND e.id ' . ($order === 'DESC' ? '<=' : '>=') . $firstId . ' '; + } + $terms = explode(' ', trim($filter)); + sort($terms); //Put #tags first + foreach ($terms as $word) { + if (!empty($word)) { + if ($word[0] === '#' && isset($word[1])) { + $where .= 'AND tags LIKE "%' . $word . '%" '; + } elseif (!empty($word)) { + $where .= 'AND (e.title LIKE "%' . $word . '%" OR UNCOMPRESS(e.content_bin) LIKE "%' . $word . '%") '; + } + } } $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 ' . 'FROM `' . $this->prefix . 'entry` e ' - . 'INNER JOIN `' . $this->prefix . 'feed` f ON e.id_feed = f.id ' . $where - . ' ORDER BY e.id' . $order; + . 'INNER JOIN `' . $this->prefix . 'feed` f ON e.id_feed = f.id WHERE ' . $where + . 'ORDER BY e.id ' . $order; - if (empty($limitCount)) { - $limitCount = 20000; //TODO: FIXME: Hack temporaire en attendant la recherche côté base-de-données + if ($limit > 0) { + $sql .= ' LIMIT ' . $limit; //TODO: See http://explainextended.com/2009/10/23/mysql-order-by-limit-performance-late-row-lookups/ } - //if (!empty($limitCount)) { - $sql .= ' LIMIT ' . ($limitCount + 2); //TODO: See http://explainextended.com/2009/10/23/mysql-order-by-limit-performance-late-row-lookups/ - //} $stm = $this->bd->prepare ($sql); $stm->execute ($values); return HelperEntry::daoToEntry ($stm->fetchAll (PDO::FETCH_ASSOC)); } - public function listEntries ($state, $order = 'high_to_low', $limitFromId = '', $limitCount = '') { - return $this->listWhere ('WHERE priority > 0', $state, $order, $limitFromId, $limitCount); - } - public function listFavorites ($state, $order = 'high_to_low', $limitFromId = '', $limitCount = '') { - return $this->listWhere ('WHERE is_favorite = 1', $state, $order, $limitFromId, $limitCount); - } - public function listByCategory ($cat, $state, $order = 'high_to_low', $limitFromId = '', $limitCount = '') { - return $this->listWhere ('WHERE category = ?', $state, $order, $limitFromId, $limitCount, array ($cat)); - } - public function listByFeed ($feed, $state, $order = 'high_to_low', $limitFromId = '', $limitCount = '') { - return $this->listWhere ('WHERE id_feed = ?', $state, $order, $limitFromId, $limitCount, array ($feed)); - } public function listLastGuidsByFeed($id, $n) { $sql = 'SELECT guid FROM `' . $this->prefix . 'entry` WHERE id_feed=? ORDER BY id DESC LIMIT ' . intval($n); @@ -579,14 +589,6 @@ class EntryDAO extends Model_pdo { } class HelperEntry { - public static $nb = 1; - public static $first = ''; - - public static $filter = array ( - 'words' => array (), - 'tags' => array (), - ); - public static function daoToEntry ($listDAO) { $list = array (); @@ -594,80 +596,27 @@ class HelperEntry { $listDAO = array ($listDAO); } - $count = 0; - $first_is_found = false; - $break_after = false; - $next = ''; foreach ($listDAO as $key => $dao) { - $dao['tags'] = preg_split('/[\s#]/', $dao['tags']); - - if (self::tagsMatchEntry ($dao) && - self::searchMatchEntry ($dao)) { - if ($break_after) { - $next = $dao['id']; - break; - } - if ($first_is_found || $dao['id'] == self::$first || self::$first == '') { - $list[$key] = self::createEntry ($dao); - - $count++; - $first_is_found = true; //TODO: Update: Now done in SQL - } - if ($count >= self::$nb) { - $break_after = true; - } + $entry = new Entry ( + $dao['id_feed'], + $dao['guid'], + $dao['title'], + $dao['author'], + $dao['content'], + $dao['link'], + $dao['date'], + $dao['is_read'], + $dao['is_favorite'], + $dao['tags'] + ); + if (isset ($dao['id'])) { + $entry->_id ($dao['id']); } + $list[] = $entry; } unset ($listDAO); - return array ($list, $next); - } - - private static function createEntry ($dao) { - $entry = new Entry ( - $dao['id_feed'], - $dao['guid'], - $dao['title'], - $dao['author'], - $dao['content'], - $dao['link'], - $dao['date'], - $dao['is_read'], - $dao['is_favorite'] - ); - - $entry->_tags ($dao['tags']); - - if (isset ($dao['id'])) { - $entry->_id ($dao['id']); - } - - return $entry; - } - - private static function tagsMatchEntry ($dao) { - $tags = self::$filter['tags']; - foreach ($tags as $tag) { - if (!in_array ($tag, $dao['tags'])) { - return false; - } - } - - return true; - } - private static function searchMatchEntry ($dao) { - $words = self::$filter['words']; - - foreach ($words as $word) { - $word = strtolower ($word); - if (strpos (strtolower ($dao['title']), $word) === false && - strpos (strtolower ($dao['content']), $word) === false && - strpos (strtolower ($dao['link']), $word) === false) { - return false; - } - } - - return true; + return $list; } } diff --git a/app/models/RSSConfiguration.php b/app/models/RSSConfiguration.php index 37f26b1dd..007c1c0f5 100755 --- a/app/models/RSSConfiguration.php +++ b/app/models/RSSConfiguration.php @@ -213,11 +213,7 @@ class RSSConfiguration extends Model { } } public function _sortOrder ($value) { - if ($value == 'high_to_low') { - $this->sort_order = 'high_to_low'; - } else { - $this->sort_order = 'low_to_high'; - } + $this->sort_order = $value === 'ASC' ? 'ASC' : 'DESC'; } public function _oldEntries ($value) { if (is_int (intval ($value)) && $value > 0) { @@ -334,7 +330,7 @@ class RSSConfigurationDAO extends Model_array { public $display_posts = 'no'; public $onread_jump_next = 'yes'; public $lazyload = 'yes'; - public $sort_order = 'low_to_high'; + public $sort_order = 'DESC'; public $old_entries = 3; public $shortcuts = array ( 'mark_read' => 'r', diff --git a/app/views/configure/display.phtml b/app/views/configure/display.phtml index 52fd80185..90416145a 100644 --- a/app/views/configure/display.phtml +++ b/app/views/configure/display.phtml @@ -73,8 +73,8 @@
    -- cgit v1.2.3