Bläddra i källkod

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 13 år sedan
förälder
incheckning
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 } ?>