Parcourir la source

Revue de code pour la récupération des articles : ATTENTION GROS CHANGEMENTS, aucune garantie de stabilité et possibles régressions. La recherche dans le contenu des articles fonctionnent et possibilité de rechercher des tags

Marien Fressinaud il y a 13 ans
Parent
commit
9820345eec

+ 3 - 0
app/App_FrontController.php

@@ -28,11 +28,14 @@ class App_FrontController extends FrontController {
 
 	private function loadModels () {
 		include (APP_PATH . '/models/Exception/FeedException.php');
+		include (APP_PATH . '/models/Exception/EntriesGetterException.php');
 		include (APP_PATH . '/models/RSSConfiguration.php');
 		include (APP_PATH . '/models/Days.php');
 		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');
 	}
 
 	private function loadParamsView () {

+ 106 - 164
app/controllers/indexController.php

@@ -6,6 +6,10 @@ class indexController extends ActionController {
 	private $mode = 'all';
 
 	public function indexAction () {
+		if (Request::param ('output', '') == 'rss') {
+			$this->view->_useLayout (false);
+		}
+
 		View::appendScript (Url::display ('/scripts/shortcut.js'));
 		View::appendScript (Url::display (array ('c' => 'javascript', 'a' => 'main')));
 		View::appendScript (Url::display (array ('c' => 'javascript', 'a' => 'actualize')));
@@ -14,109 +18,125 @@ class indexController extends ActionController {
 		$feedDAO = new FeedDAO ();
 		$catDAO = new CategoryDAO ();
 
-		$error = false;
-
-		// pour optimiser
-		$page = Request::param ('page', 1);
-		$entryDAO->_nbItemsPerPage ($this->view->conf->postsPerPage ());
-		$entryDAO->_currentPage ($page);
-
-		// récupération de la catégorie/flux à filtrer
-		$this->initFilter ();
-		// Compte le nombre d'articles non lus en prenant en compte le filtre
-		$this->countNotRead ();
-		// mode de vue (tout ou seulement non lus)
-		$this->initCurrentMode ();
-		// ordre de listage des flux
-		$order = Session::param ('order', $this->view->conf->sortOrder ());
-		// recherche sur les titres (pour le moment)
-		$search = Request::param ('search');
-
-		// Récupère les flux par catégorie, favoris ou tous
-		if ($this->get['type'] == 'all') {
-			$entries = $entryDAO->listEntries ($this->mode, $search, $order);
-			View::prependTitle (Translate::t ('your_rss_feeds') . ' - ');
-		} elseif ($this->get['type'] == 'favoris') {
-			$entries = $entryDAO->listFavorites ($this->mode, $search, $order);
-			View::prependTitle (Translate::t ('your_favorites') . ' - ');
-		} elseif ($this->get['type'] == 'public') {
-			$entries = $entryDAO->listPublic ($this->mode, $search, $order);
-			View::prependTitle (Translate::t ('public') . ' - ');
-		} elseif ($this->get != false) {
-			if ($this->get['type'] == 'c') {
-				$cat = $catDAO->searchById ($this->get['filter']);
-
-				if ($cat) {
-					$entries = $entryDAO->listByCategory ($this->get['filter'], $this->mode, $search, $order);
-					View::prependTitle ($cat->name () . ' - ');
-				} else {
-					$error = true;
-				}
-			} elseif ($this->get['type'] == 'f') {
-				$feed = $feedDAO->searchById ($this->get['filter']);
-
-				if ($feed) {
-					$entries = $entryDAO->listByFeed ($this->get['filter'], $this->mode, $search, $order);
-					$this->view->get_c = $feed->category ();
-					View::prependTitle ($feed->name () . ' - ');
-				} else {
-					$error = true;
+		$this->view->cat_aside = $catDAO->listCategories ();
+		$this->view->nb_favorites = $entryDAO->countFavorites ();
+		$this->view->nb_total = $entryDAO->count ();
+
+		$this->view->get_c = '';
+		$this->view->get_f = '';
+
+		$type = $this->getType ();
+		$error = $this->checkAndProcessType ($type);
+		if (!$error) {
+			$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', '');
+
+			try {
+				$getter = new EntriesGetter ($type, $state, $filter, $order, $nb, $first);
+				$getter->execute ();
+				$entries = $getter->getPaginator ();
+
+				if ($state == 'not_read' && $entries->isEmpty ()) {
+					$this->view->state = 'all';
+					$getter->_state ('all');
+					$getter->execute ();
+					$entries = $getter->getPaginator ();
 				}
-			} else {
-				$error = true;
+
+				$this->view->entryPaginator = $entries;
+			} catch(EntriesGetterException $e) {
+				Log::record ($e->getMessage (), Log::NOTICE);
+				Error::error (
+					404,
+					array ('error' => array (Translate::t ('page_not_found')))
+				);
+			} catch(CurrentPagePaginationException $e) {
+				Error::error (
+					404,
+					array ('error' => array (Translate::t ('page_not_found')))
+				);
 			}
 		} else {
-			$error = true;
-		}
-
-		if ($error) {
 			Error::error (
 				404,
 				array ('error' => array (Translate::t ('page_not_found')))
 			);
-		} else {
-			$this->view->mode = $this->mode;
-			$this->view->order = $order;
-
-			try {
-				$this->view->entryPaginator = $entryDAO->getPaginator ($entries);
-			} catch (CurrentPagePaginationException $e) { }
-
-			$this->view->cat_aside = $catDAO->listCategories ();
-			$this->view->nb_favorites = $entryDAO->countFavorites ();
-			$this->view->nb_total = $entryDAO->count ();
-
-			if (Request::param ('output', '') == 'rss') {
-				$this->view->_useLayout (false);
-			}
 		}
 	}
 
-	public function aboutAction () {
-		View::prependTitle (Translate::t ('about') . ' - ');
-	}
-
-	public function changeModeAction () {
-		$mode = Request::param ('mode');
+	/*
+	 * 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);
 
-		if ($mode == 'not_read') {
-			Session::_param ('mode', 'not_read');
-		} else {
-			Session::_param ('mode', 'all');
+		$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
+			);
 		}
 
-		Request::forward (array (), true);
+		return $type;
 	}
-	public function changeOrderAction () {
-		$order = Request::param ('order');
-
-		if ($order == 'low_to_high') {
-			Session::_param ('order', 'low_to_high');
+	/*
+	 * Vérifie que la catégorie / flux sélectionné existe
+	 * + Initialise correctement les variables de vue get_c et get_f
+	 * + Initialise le titre
+	 */
+	private function checkAndProcessType ($type) {
+		if ($type['type'] == 'all') {
+			View::prependTitle (Translate::t ('your_rss_feeds') . ' - ');
+			$this->view->get_c = $type['type'];
+			return false;
+		} elseif ($type['type'] == 'favoris') {
+			View::prependTitle (Translate::t ('your_favorites') . ' - ');
+			$this->view->get_c = $type['type'];
+			return false;
+		} elseif ($type['type'] == 'public') {
+			View::prependTitle (Translate::t ('public') . ' - ');
+			$this->view->get_c = $type['type'];
+			return false;
+		} elseif ($type['type'] == 'c') {
+			$catDAO = new CategoryDAO ();
+			$cat = $catDAO->searchById ($type['id']);
+			if ($cat) {
+				View::prependTitle ($cat->name () . ' - ');
+				$this->view->get_c = $type['id'];
+				return false;
+			} else {
+				return true;
+			}
+		} elseif ($type['type'] == 'f') {
+			$feedDAO = new FeedDAO ();
+			$feed = $feedDAO->searchById ($type['id']);
+			if ($feed) {
+				View::prependTitle ($feed->name () . ' - ');
+				$this->view->get_f = $type['id'];
+				$this->view->get_c = $feed->category ();
+				return false;
+			} else {
+				return true;
+			}
 		} else {
-			Session::_param ('order', 'high_to_low');
+			return true;
 		}
+	}
 
-		Request::forward (array (), true);
+	public function aboutAction () {
+		View::prependTitle (Translate::t ('about') . ' - ');
 	}
 
 	public function loginAction () {
@@ -153,82 +173,4 @@ class indexController extends ActionController {
 		$this->view->_useLayout (false);
 		Session::_param ('mail');
 	}
-
-	private function initFilter () {
-		$get = Request::param ('get');
-		$this->view->get_c = false;
-		$this->view->get_f = false;
-
-		$typeGet = $get[0];
-		$filter = substr ($get, 2);
-
-		if ($get == 'favoris') {
-			$this->view->get_c = $get;
-
-			$this->get = array (
-				'type' => $get,
-				'filter' => $get
-			);
-		} elseif ($get == 'public') {
-			$this->view->get_c = $get;
-
-			$this->get = array (
-				'type' => $get,
-				'filter' => $get
-			);
-		} elseif ($get == false) {
-			$this->get = array (
-				'type' => 'all',
-				'filter' => 'all'
-			);
-		} else {
-			if ($typeGet == 'f') {
-				$this->view->get_f = $filter;
-
-				$this->get = array (
-					'type' => $typeGet,
-					'filter' => $filter
-				);
-			} elseif ($typeGet == 'c') {
-				$this->view->get_c = $filter;
-
-				$this->get = array (
-					'type' => $typeGet,
-					'filter' => $filter
-				);
-			} else {
-				$this->get = false;
-			}
-		}
-	}
-
-	private function countNotRead () {
-		$entryDAO = new EntryDAO ();
-
-		if ($this->get != false) {
-			if ($this->get['type'] == 'all') {
-				$this->nb_not_read = $this->view->nb_not_read;
-			} elseif ($this->get['type'] == 'favoris') {
-				$this->nb_not_read = $entryDAO->countNotReadFavorites ();
-			} elseif ($this->get['type'] == 'c') {
-				$this->nb_not_read = $entryDAO->countNotReadByCat ($this->get['filter']);
-			} elseif ($this->get['type'] == 'f') {
-				$this->nb_not_read = $entryDAO->countNotReadByFeed ($this->get['filter']);
-			}
-		}
-	}
-
-	private function initCurrentMode () {
-		$default_view = $this->view->conf->defaultView ();
-		$mode = Session::param ('mode');
-		if ($mode == false) {
-			if ($default_view == 'not_read' && $this->nb_not_read < 1) {
-				$mode = 'all';
-			} else {
-				$mode = $default_view;
-			}
-		}
-
-		$this->mode = $mode;
-	}
 }

+ 3 - 3
app/i18n/en.php

@@ -4,7 +4,7 @@ return array (
 	// LAYOUT
 	'login'				=> 'Login',
 	'logout'			=> 'Logout',
-	'search_on_title'		=> 'Search (only on titles)',
+	'search'			=> 'Search words or #tags',
 
 	'configuration'			=> 'Configuration',
 	'general_and_reading'		=> 'General and reading',
@@ -161,8 +161,8 @@ return array (
 	'author'			=> 'Author',
 	'publication_date'		=> 'Date of publication',
 
-	'newer'				=> 'newer',
-	'older'				=> 'older',
+	'load_more'			=> 'Load more articles',
+	'nothing_to_load'		=> 'There is no more articles',
 
 	'rss_feeds_of'			=> 'RSS feed of %s',
 

+ 3 - 3
app/i18n/fr.php

@@ -4,7 +4,7 @@ return array (
 	// LAYOUT
 	'login'				=> 'Connexion',
 	'logout'			=> 'Déconnexion',
-	'search_on_title'		=> 'Rechercher sur les titres',
+	'search'			=> 'Rechercher un terme ou des #tags',
 
 	'configuration'			=> 'Configuration',
 	'general_and_reading'		=> 'Général et lecture',
@@ -161,8 +161,8 @@ return array (
 	'author'			=> 'Auteur',
 	'publication_date'		=> 'Date de publication',
 
-	'newer'				=> 'plus récents',
-	'older'				=> 'plus anciens',
+	'load_more'			=> 'Charger plus d\'articles',
+	'nothing_to_load'		=> 'Il n\'y a pas plus d\'article',
 
 	'rss_feeds_of'			=> 'Flux RSS de %s',
 

+ 7 - 12
app/layout/aside_flux.phtml

@@ -3,21 +3,16 @@
 
 	<ul class="categories">
 		<?php
-			$get = Request::param ('get', '');
-			$search = Request::param ('search', '');
+			$params = Request::params ();
+			$params['output'] = 'rss';
+			if (isset ($params['search'])) {
+				$params['search'] = urlencode ($params['search']);
+			}
 			$url = array (
 				'c' => 'index',
 				'a' => 'index',
-				'params' => array (
-					'output' => 'rss'
-				)
+				'params' => $params
 			);
-			if ($get != '') {
-				$url['params']['get'] = $get;
-			}
-			if ($search != '') {
-				$url['params']['search'] = $search;
-			}
 		?>
 		<?php if (!login_is_conf ($this->conf) || is_logged ()) { ?>
 		<li>
@@ -30,7 +25,7 @@
 
 		<li>
 			<div class="all">
-				<a class="btn<?php echo !$this->get_c ? ' active' : ''; ?>" href="<?php echo _url ('index', 'index'); ?>">
+				<a class="btn<?php echo $this->get_c == 'all' ? ' active' : ''; ?>" href="<?php echo _url ('index', 'index'); ?>">
 					<i class="icon i_all"></i>
 					<?php echo Translate::t ('all_feeds', $this->nb_total); ?>
 					<?php if ($this->nb_not_read > 0) { ?>

+ 13 - 2
app/layout/header.phtml

@@ -15,10 +15,21 @@
 	</div>
 
 	<div class="item search">
-		<form action="<?php echo _url ('index', 'index'); ?>" method="get">
+		<?php
+			$params = Request::params ();
+			if (isset ($params['search'])) {
+				unset ($params['search']);
+			}
+			$url = array (
+				'c' => 'index',
+				'a' => 'index',
+				'params' => $params
+			);
+		?>
+		<form action="<?php echo Url::display ($url); ?>" method="post">
 			<div class="stick">
 				<?php $s = Request::param ('search', ''); ?>
-				<input type="text" name="search" id="search" value="<?php echo $s; ?>" placeholder="<?php echo Translate::t ('search_on_title'); ?>" />
+				<input type="text" name="search" id="search" value="<?php echo $s; ?>" placeholder="<?php echo Translate::t ('search'); ?>" />
 				<button class="btn" type="submit"><i class="icon i_search"></i></button>
 			</div>
 		</form>

+ 47 - 9
app/layout/nav_menu.phtml

@@ -10,7 +10,10 @@
 		if ($this->get_f) {
 			$get = 'f_' . $this->get_f;
 			$string_mark = Translate::t ('mark_feed_read');
-		} elseif ($this->get_c) {
+		} elseif ($this->get_c &&
+		          $this->get_c != 'all' &&
+		          $this->get_c != 'favoris' &&
+		          $this->get_c != 'public') {
 			$get = 'c_' . $this->get_c;
 			$string_mark = Translate::t ('mark_cat_read');
 		}
@@ -39,6 +42,17 @@
 	</div>
 	<?php } ?>
 
+	<?php
+		$params = Request::params ();
+		if (isset ($params['search'])) {
+			$params['search'] = urlencode ($params['search']);
+		}
+		$url = array (
+			'c' => 'index',
+			'a' => 'index',
+			'params' => $params
+		);
+	?>
 	<div class="dropdown">
 		<div id="dropdown-views" class="dropdown-target"></div>
 		<a class="dropdown-toggle btn" href="#dropdown-views"><?php echo Translate::t ('display'); ?> <i class="icon i_down"></i></a>
@@ -46,18 +60,42 @@
 			<li class="dropdown-close"><a href="#close"><i class="icon i_close"></i></a></li>
 
 			<li class="item">
-				<?php if ($this->mode == 'not_read') { ?>
-				<a class="print_all" href="<?php echo _url ('index', 'changeMode', 'mode', 'all'); ?>"><?php echo Translate::t ('show_all_articles'); ?></a>
-				<?php } else { ?>
-				<a class="print_non_read" href="<?php echo _url ('index', 'changeMode', 'mode', 'not_read'); ?>"><?php echo Translate::t ('show_not_reads'); ?></a>
+				<?php
+					if ($this->state == 'not_read') {
+						$url['params']['state'] = 'all';
+				?>
+				<a class="print_all" href="<?php echo Url::display ($url); ?>"><?php echo Translate::t ('show_all_articles'); ?></a>
+				<?php
+					} else {
+						$url['params']['state'] = 'not_read';
+				?>
+				<a class="print_non_read" href="<?php echo Url::display ($url); ?>"><?php echo Translate::t ('show_not_reads'); ?></a>
 				<?php } ?>
 			</li>
 			<li class="separator"></li>
+
+			<?php
+				$params = Request::params ();
+				if (isset ($params['search'])) {
+					$params['search'] = urlencode ($params['search']);
+				}
+				$url = array (
+					'c' => 'index',
+					'a' => 'index',
+					'params' => $params
+				);
+			?>
 			<li class="item">
-				<?php if ($this->order == 'low_to_high') { ?>
-				<a href="<?php echo _url ('index', 'changeOrder', 'order', 'high_to_low'); ?>"><?php echo Translate::t ('older_first'); ?></a>
-				<?php } else { ?>
-				<a href="<?php echo _url ('index', 'changeOrder', 'order', 'low_to_high'); ?>"><?php echo Translate::t ('newer_first'); ?></a>
+				<?php
+					if ($this->order == 'low_to_high') {
+						$url['params']['order'] = 'high_to_low';
+				?>
+				<a href="<?php echo Url::display ($url); ?>"><?php echo Translate::t ('older_first'); ?></a>
+				<?php
+					} else {
+						$url['params']['order'] = 'low_to_high';
+				?>
+				<a href="<?php echo Url::display ($url); ?>"><?php echo Translate::t ('newer_first'); ?></a>
 				<?php } ?>
 			</li>
 		</ul>

+ 144 - 0
app/models/EntriesGetter.php

@@ -0,0 +1,144 @@
+<?php
+
+class EntriesGetter {
+	private $type = array (
+		'type' => '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;
+		HelperEntry::$first = $this->first;
+		HelperEntry::$filter = $this->filter;
+
+		switch ($this->type['type']) {
+		case 'all':
+			list ($this->entries, $this->next) = $entryDAO->listEntries (
+				$this->state,
+				$this->order
+			);
+			break;
+		case 'favoris':
+			list ($this->entries, $this->next) = $entryDAO->listFavorites (
+				$this->state,
+				$this->order
+			);
+			break;
+		case 'public':
+			list ($this->entries, $this->next) = $entryDAO->listPublic (
+				$this->state,
+				$this->order
+			);
+			break;
+		case 'c':
+			list ($this->entries, $this->next) = $entryDAO->listByCategory (
+				$this->type['id'],
+				$this->state,
+				$this->order
+			);
+			break;
+		case 'f':
+			list ($this->entries, $this->next) = $entryDAO->listByFeed (
+				$this->type['id'],
+				$this->state,
+				$this->order
+			);
+			break;
+		default:
+			throw new EntriesGetterException ('Bad type line ' . __LINE__ . ' in file ' . __FILE__);
+		}
+	}
+
+	public function getPaginator () {
+		$paginator = new RSSPaginator ($this->entries, $this->next);
+
+		return $paginator;
+	}
+}

+ 99 - 229
app/models/Entry.php

@@ -377,16 +377,11 @@ class EntryDAO extends Model_pdo {
 		}
 	}
 
-	public function listEntries ($mode, $search = false, $order = 'high_to_low') {
-		$where = ' WHERE priority > 0';
-		if ($mode == 'not_read') {
-			$where .= ' AND is_read=0';
-		}
-
-		$values = array();
-		if ($search) {
-			$values[] = '%'.$search.'%';
-			$where .= ' AND title LIKE ?';
+	public function listWhere ($where, $state, $order, $values = array ()) {
+		if ($state == 'not_read') {
+			$where .= ' AND is_read = 0';
+		} elseif ($state == 'read') {
+			$where .= ' AND is_read = 1';
 		}
 
 		if ($order == 'low_to_high') {
@@ -395,181 +390,28 @@ class EntryDAO extends Model_pdo {
 			$order = '';
 		}
 
-		$sql = 'SELECT COUNT(*) AS count FROM entry e INNER JOIN feed f ON e.id_feed = f.id' . $where;
-		$stm = $this->bd->prepare ($sql);
-		$stm->execute ($values);
-		$res = $stm->fetchAll (PDO::FETCH_ASSOC);
-		$this->nbItems = $res[0]['count'];
-
-		$deb = ($this->currentPage () - 1) * $this->nbItemsPerPage;
-		$fin = $this->nbItemsPerPage;
-
 		$sql = 'SELECT e.* FROM entry e'
 		     . ' INNER JOIN feed f ON e.id_feed = f.id' . $where
-		     . ' ORDER BY date' . $order
-		     . ' LIMIT ' . $deb . ', ' . $fin;
+		     . ' ORDER BY date' . $order;
 		$stm = $this->bd->prepare ($sql);
 		$stm->execute ($values);
 
 		return HelperEntry::daoToEntry ($stm->fetchAll (PDO::FETCH_ASSOC));
 	}
-
-	public function listFavorites ($mode, $search = false, $order = 'high_to_low') {
-		$where = ' WHERE is_favorite=1';
-		if ($mode == 'not_read') {
-			$where .= ' AND is_read=0';
-		}
-
-		$values = array();
-		if ($search) {
-			$values[] = '%'.$search.'%';
-			$where .= ' AND title LIKE ?';
-		}
-
-		if ($order == 'low_to_high') {
-			$order = ' DESC';
-		} else {
-			$order = '';
-		}
-
-		$sql = 'SELECT COUNT(*) AS count FROM entry' . $where;
-		$stm = $this->bd->prepare ($sql);
-		$stm->execute ($values);
-		$res = $stm->fetchAll (PDO::FETCH_ASSOC);
-		$this->nbItems = $res[0]['count'];
-
-		if($this->nbItemsPerPage < 0) {
-			$sql = 'SELECT * FROM entry' . $where
-			     . ' ORDER BY date' . $order;
-		} else {
-			$deb = ($this->currentPage () - 1) * $this->nbItemsPerPage;
-			$fin = $this->nbItemsPerPage;
-
-			$sql = 'SELECT * FROM entry' . $where
-			     . ' ORDER BY date' . $order
-			     . ' LIMIT ' . $deb . ', ' . $fin;
-		}
-		$stm = $this->bd->prepare ($sql);
-
-		$stm->execute ($values);
-
-		return HelperEntry::daoToEntry ($stm->fetchAll (PDO::FETCH_ASSOC));
+	public function listEntries ($state, $order = 'high_to_low') {
+		return $this->listWhere (' WHERE priority > 0', $state, $order);
 	}
-
-	public function listPublic ($mode, $search = false, $order = 'high_to_low') {
-		$where = ' WHERE is_public=1';
-		if ($mode == 'not_read') {
-			$where .= ' AND is_read=0';
-		}
-
-		$values = array();
-		if ($search) {
-			$values[] = '%'.$search.'%';
-			$where .= ' AND title LIKE ?';
-		}
-
-		if ($order == 'low_to_high') {
-			$order = ' DESC';
-		} else {
-			$order = '';
-		}
-
-		$sql = 'SELECT COUNT(*) AS count FROM entry' . $where;
-		$stm = $this->bd->prepare ($sql);
-		$stm->execute ($values);
-		$res = $stm->fetchAll (PDO::FETCH_ASSOC);
-		$this->nbItems = $res[0]['count'];
-
-		if($this->nbItemsPerPage < 0) {
-			$sql = 'SELECT * FROM entry' . $where
-			     . ' ORDER BY date' . $order;
-		} else {
-			$deb = ($this->currentPage () - 1) * $this->nbItemsPerPage;
-			$fin = $this->nbItemsPerPage;
-
-			$sql = 'SELECT * FROM entry' . $where
-			     . ' ORDER BY date' . $order
-			     . ' LIMIT ' . $deb . ', ' . $fin;
-		}
-		$stm = $this->bd->prepare ($sql);
-
-		$stm->execute ($values);
-
-		return HelperEntry::daoToEntry ($stm->fetchAll (PDO::FETCH_ASSOC));
+	public function listFavorites ($state, $order = 'high_to_low') {
+		return $this->listWhere (' WHERE is_favorite = 1', $state, $order);
 	}
-
-	public function listByCategory ($cat, $mode, $search = false, $order = 'high_to_low') {
-		$where = ' WHERE category=?';
-		if ($mode == 'not_read') {
-			$where .= ' AND is_read=0';
-		}
-
-		$values = array ($cat);
-		if ($search) {
-			$values[] = '%'.$search.'%';
-			$where .= ' AND title LIKE ?';
-		}
-
-		if ($order == 'low_to_high') {
-			$order = ' DESC';
-		} else {
-			$order = '';
-		}
-
-		$sql = 'SELECT COUNT(*) AS count FROM entry e INNER JOIN feed f ON e.id_feed = f.id' . $where;
-		$stm = $this->bd->prepare ($sql);
-		$stm->execute ($values);
-		$res = $stm->fetchAll (PDO::FETCH_ASSOC);
-		$this->nbItems = $res[0]['count'];
-
-		$deb = ($this->currentPage () - 1) * $this->nbItemsPerPage;
-		$fin = $this->nbItemsPerPage;
-		$sql = 'SELECT e.* FROM entry e INNER JOIN feed f ON e.id_feed = f.id' . $where
-		     . ' ORDER BY date' . $order
-		     . ' LIMIT ' . $deb . ', ' . $fin;
-
-		$stm = $this->bd->prepare ($sql);
-
-		$stm->execute ($values);
-
-		return HelperEntry::daoToEntry ($stm->fetchAll (PDO::FETCH_ASSOC));
+	public function listPublic ($state, $order = 'high_to_low') {
+		return $this->listWhere (' WHERE is_public = 1', $state, $order);
 	}
-
-	public function listByFeed ($feed, $mode, $search = false, $order = 'high_to_low') {
-		$where = ' WHERE id_feed=?';
-		if ($mode == 'not_read') {
-			$where .= ' AND is_read=0';
-		}
-
-		$values = array($feed);
-		if ($search) {
-			$values[] = '%'.$search.'%';
-			$where .= ' AND title LIKE ?';
-		}
-
-		if ($order == 'low_to_high') {
-			$order = ' DESC';
-		} else {
-			$order = '';
-		}
-
-		$sql = 'SELECT COUNT(*) AS count FROM entry' . $where;
-		$stm = $this->bd->prepare ($sql);
-		$stm->execute ($values);
-		$res = $stm->fetchAll (PDO::FETCH_ASSOC);
-		$this->nbItems = $res[0]['count'];
-
-		$deb = ($this->currentPage () - 1) * $this->nbItemsPerPage;
-		$fin = $this->nbItemsPerPage;
-		$sql = 'SELECT * FROM entry e' . $where
-		     . ' ORDER BY date' . $order
-		     . ' LIMIT ' . $deb . ', ' . $fin;
-
-		$stm = $this->bd->prepare ($sql);
-
-		$stm->execute ($values);
-
-		return HelperEntry::daoToEntry ($stm->fetchAll (PDO::FETCH_ASSOC));
+	public function listByCategory ($cat, $state, $order = 'high_to_low') {
+		return $this->listWhere (' WHERE category = ?', $state, $order, array ($cat));
+	}
+	public function listByFeed ($feed, $state, $order = 'high_to_low') {
+		return $this->listWhere (' WHERE id_feed = ?', $state, $order, array ($feed));
 	}
 
 	public function count () {
@@ -580,7 +422,6 @@ class EntryDAO extends Model_pdo {
 
 		return $res[0]['count'];
 	}
-
 	public function countNotRead () {
 		$sql = 'SELECT COUNT(*) AS count FROM entry e INNER JOIN feed f ON e.id_feed = f.id WHERE is_read=0 AND priority > 0';
 		$stm = $this->bd->prepare ($sql);
@@ -616,7 +457,6 @@ class EntryDAO extends Model_pdo {
 
 		return $res[0]['count'];
 	}
-
 	public function countFavorites () {
 		$sql = 'SELECT COUNT(*) AS count FROM entry WHERE is_favorite=1';
 		$stm = $this->bd->prepare ($sql);
@@ -625,73 +465,103 @@ class EntryDAO extends Model_pdo {
 
 		return $res[0]['count'];
 	}
+}
 
-	// gestion de la pagination directement via le DAO
-	private $nbItemsPerPage = 1;
-	private $currentPage = 1;
-	private $nbItems = 0;
-	public function _nbItemsPerPage ($value) {
-		$this->nbItemsPerPage = $value;
-	}
-	public function _currentPage ($value) {
-		$this->currentPage = $value;
-	}
-	public function currentPage () {
-		if ($this->currentPage < 1) {
-			return 1;
+class HelperEntry {
+	public static $nb = 1;
+	public static $first = '';
+
+	public static $filter = array (
+		'words' => array (),
+		'tags' => array (),
+	);
+
+	public static function daoToEntry ($listDAO) {
+		$list = array ();
+
+		if (!is_array ($listDAO)) {
+			$listDAO = array ($listDAO);
 		}
 
-		$maxPage = ceil ($this->nbItems / $this->nbItemsPerPage);
-		if ($this->currentPage > $maxPage) {
-			return $maxPage;
+		$count = 0;
+		$first_is_found = false;
+		$break_after = false;
+		$next = '';
+		foreach ($listDAO as $key => $dao) {
+			$dao['content'] = unserialize (gzinflate (base64_decode ($dao['content'])));
+			$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;
+				}
+				if ($count >= self::$nb) {
+					$break_after = true;
+				}
+			}
 		}
 
-		return $this->currentPage;
+		unset ($listDAO);
 
+		return array ($list, $next);
 	}
 
-	public function getPaginator ($entries) {
-		$paginator = new Paginator ($entries);
-		$paginator->_nbItems ($this->nbItems);
-		$paginator->_nbItemsPerPage ($this->nbItemsPerPage);
-		$paginator->_currentPage ($this->currentPage ());
+	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'],
+			$dao['is_public']
+		);
 
-		return $paginator;
-	}
-}
+		$entry->_notes ($dao['annotation']);
+		$entry->_lastUpdate ($dao['lastUpdate']);
+		$entry->_tags ($dao['tags']);
 
-class HelperEntry {
-	public static function daoToEntry ($listDAO, $mode = 'all', $favorite = false) {
-		$list = array ();
+		if (isset ($dao['id'])) {
+			$entry->_id ($dao['id']);
+		}
 
-		if (!is_array ($listDAO)) {
-			$listDAO = array ($listDAO);
+		return $entry;
+	}
+
+	private static function tagsMatchEntry ($dao) {
+		$tags = self::$filter['tags'];
+		foreach ($tags as $tag) {
+			if (!in_array ($tag, $dao['tags'])) {
+				return false;
+			}
 		}
 
-		foreach ($listDAO as $key => $dao) {
-			$list[$key] = new Entry (
-				$dao['id_feed'],
-				$dao['guid'],
-				$dao['title'],
-				$dao['author'],
-				unserialize (gzinflate (base64_decode ($dao['content']))),
-				$dao['link'],
-				$dao['date'],
-				$dao['is_read'],
-				$dao['is_favorite'],
-				$dao['is_public']
-			);
-
-			$tags = preg_split('/[\s#]/', $dao['tags']);
-			$list[$key]->_notes ($dao['annotation']);
-			$list[$key]->_lastUpdate ($dao['lastUpdate']);
-			$list[$key]->_tags ($tags);
-
-			if (isset ($dao['id'])) {
-				$list[$key]->_id ($dao['id']);
+		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 &&
+			    strpos (strtolower ($dao['annotation']), $word) === false) {
+				return false;
 			}
 		}
 
-		return $list;
+		return true;
 	}
 }

+ 7 - 0
app/models/Exception/EntriesGetterException.php

@@ -0,0 +1,7 @@
+<?php
+
+class EntriesGetterException extends Exception {
+	public function __construct ($message) {
+		parent::__construct ($message);
+	}
+}

+ 27 - 0
app/models/RSSPaginator.php

@@ -0,0 +1,27 @@
+<?php
+
+class RSSPaginator {
+	private $items = array ();
+	private $next = '';
+
+	public function __construct ($items, $next) {
+		$this->items = $items;
+		$this->next = $next;
+	}
+
+	public function isEmpty () {
+		return empty ($this->items);
+	}
+
+	public function items () {
+		return $this->items;
+	}
+
+	public function render ($view, $getteur) {
+		$view = APP_PATH . '/views/helpers/'.$view;
+
+		if (file_exists ($view)) {
+			include ($view);
+		}
+	}
+}

+ 4 - 25
app/views/helpers/pagination.phtml

@@ -2,36 +2,15 @@
 	$c = Request::controllerName ();
 	$a = Request::actionName ();
 	$params = Request::params ();
-
-	$conf = new RSSConfiguration ();
-	$order = Session::param ('order', $conf->sortOrder ());
-	if ($order == 'low_to_high') {
-		$first_link = Translate::t ('newer');
-		$second_link = Translate::t ('older');
-	} else {
-		$first_link = Translate::t ('older');
-		$second_link = Translate::t ('newer');
-	}
 ?>
 
 <ul class="pagination">
-	<li class="item pager-previous">
-	<?php if ($this->currentPage > 1) { ?>
-	<?php $params[$getteur] = $this->currentPage - 1; ?>
-	<a href="<?php echo Url::display (array ('c' => $c, 'a' => $a, 'params' => $params)); ?>">‹ <?php echo $first_link ?></a>
-	<?php } else { ?>
-	&nbsp;
-	<?php } ?>
-	</li>
-
-	<li class="item pager-current">page <?php echo $this->currentPage; ?> / <?php echo $this->nbPage; ?></li>
-
 	<li class="item pager-next">
-	<?php if ($this->currentPage < $this->nbPage) { ?>
-	<?php $params[$getteur] = $this->currentPage + 1; ?>
-	<a href="<?php echo Url::display (array ('c' => $c, 'a' => $a, 'params' => $params)); ?>"><?php echo $second_link; ?> ›</a>
+	<?php if ($this->next != '') { ?>
+	<?php $params[$getteur] = $this->next; ?>
+	<a href="<?php echo Url::display (array ('c' => $c, 'a' => $a, 'params' => $params)); ?>"><?php echo Translate::t ('load_more'); ?></a>
 	<?php } else { ?>
-	&nbsp;
+	<?php echo Translate::t ('nothing_to_load'); ?>
 	<?php } ?>
 	</li>
 </ul>

+ 3 - 6
app/views/index/index.phtml

@@ -10,8 +10,8 @@ if (Request::param ('output', '') == 'rss') {
 <?php $this->partial ('nav_menu'); ?>
 
 <?php
-if (isset ($this->entryPaginator)) {
-	$items = $this->entryPaginator->items (true);
+if (isset ($this->entryPaginator) && !$this->entryPaginator->isEmpty ()) {
+	$items = $this->entryPaginator->items ();
 ?>
 <div id="stream">
 	<?php
@@ -111,13 +111,10 @@ if (isset ($this->entryPaginator)) {
 	</div>
 	<?php } ?>
 	
-	<?php $this->entryPaginator->render ('pagination.phtml', 'page'); ?>
+	<?php $this->entryPaginator->render ('pagination.phtml', 'next'); ?>
 </div>
 <?php } else { ?>
 <div class="alert alert-warn">
 	<span class="alert-head"><?php echo Translate::t ('no_feed_to_display'); ?></span>
-	<?php if (Session::param ('mode', 'all') == 'not_read') { ?>
-	<a class="print_all" href="<?php echo _url ('index', 'changeMode', 'mode', 'all'); ?>"><?php echo Translate::t ('show_all_articles'); ?></a>
-	<?php }	?>
 </div>
 <?php } ?>