From a4fc7becb8553198d132633d775989c89c8116cd Mon Sep 17 00:00:00 2001 From: Alexandre Alapetite Date: Mon, 11 Nov 2013 17:40:28 +0100 Subject: Décode les entités HTML en conservant les entités XML MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit N'ayant pas trouvé comment régler SimplePie pour ne pas avoir d'entités HTML comme `é`, voici un patch qui les décode en sortie de SimplePie tout en conservant les entités XML comme `&`. Contribue à https://github.com/marienfressinaud/FreshRSS/issues/247 --- app/models/Feed.php | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) (limited to 'app/models') diff --git a/app/models/Feed.php b/app/models/Feed.php index 7f53d7be8..41750d43e 100644 --- a/app/models/Feed.php +++ b/app/models/Feed.php @@ -241,12 +241,22 @@ class Feed extends Model { } } } + static function html_only_entity_decode($text) { + static $htmlEntitiesOnly = null; + if ($htmlEntitiesOnly === null) { + $htmlEntitiesOnly = array_flip(array_diff( + get_html_translation_table(HTML_ENTITIES, ENT_NOQUOTES, 'UTF-8'), //Decode HTML entities + get_html_translation_table(HTML_SPECIALCHARS, ENT_NOQUOTES, 'UTF-8') //Preserve XML entities + )); + } + return strtr($text, $htmlEntitiesOnly); + } private function loadEntries ($feed) { $entries = array (); foreach ($feed->get_items () as $item) { - $title = strip_tags($item->get_title ()); - $author = $item->get_author (); + $title = self::html_only_entity_decode (strip_tags ($item->get_title ())); + $author = self::html_only_entity_decode ($item->get_author ()); $link = $item->get_permalink (); $date = strtotime ($item->get_date ()); @@ -255,11 +265,12 @@ class Feed extends Model { $tags = array (); if (!is_null ($tags_tmp)) { foreach ($tags_tmp as $tag) { - $tags[] = $tag->get_label (); + $tags[] = self::html_only_entity_decode ($tag->get_label ()); } } - $content = $item->get_content (); + $content = self::html_only_entity_decode ($item->get_content ()); + $elinks = array(); foreach ($item->get_enclosures() as $enclosure) { $elink = $enclosure->get_link(); -- cgit v1.2.3 From 396fefeae1f53f09a24e8f7ad891d44124008182 Mon Sep 17 00:00:00 2001 From: Alexandre Alapetite Date: Mon, 11 Nov 2013 20:56:47 +0100 Subject: MySQL : Longueurs maximum des champs texte MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Ajout de sécurités pour ne pas dépasser les longueurs de texte déclarées dans MySQL (varchar ou text selon les champs) --- app/models/Entry.php | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'app/models') diff --git a/app/models/Entry.php b/app/models/Entry.php index 99edf94b4..94cb6f774 100755 --- a/app/models/Entry.php +++ b/app/models/Entry.php @@ -179,16 +179,16 @@ class Entry extends Model { public function toArray () { return array ( 'id' => $this->id (), - 'guid' => $this->guid (), - 'title' => $this->title (), - 'author' => $this->author (), - 'content' => $this->content (), - 'link' => $this->link (), + 'guid' => substr($this->guid (), 0, 65535), + 'title' => substr($this->title (), 0, 255), + 'author' => substr($this->author (), 0, 255), + 'content' => substr($this->content (), 0, 65535), + 'link' => substr($this->link (), 0, 65535), 'date' => $this->date (true), 'is_read' => $this->isRead (), 'is_favorite' => $this->isFavorite (), 'id_feed' => $this->feed (), - 'tags' => $this->tags (true) + 'tags' => substr($this->tags (true), 0, 65535), ); } } -- cgit v1.2.3 From 5af7c472ed406693d19daf6899ad5ea615840740 Mon Sep 17 00:00:00 2001 From: Alexandre Alapetite Date: Mon, 11 Nov 2013 22:19:37 +0100 Subject: MySQL : changements mineurs de types MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit D'autres changements de types, toujours sans modification de comportement, mais plus efficace. En particulier char(6) plutôt que varchar(6) pour les identifiants en attendant un entier, et varchar plutôt que text dans des champs généralement courts et souvent retournés par les requêtes les plus importantes --- app/models/Entry.php | 22 +++++++++++----------- app/models/Feed.php | 8 ++++---- public/install.php | 26 +++++++++++++------------- 3 files changed, 28 insertions(+), 28 deletions(-) (limited to 'app/models') diff --git a/app/models/Entry.php b/app/models/Entry.php index 94cb6f774..d03c3a3c1 100755 --- a/app/models/Entry.php +++ b/app/models/Entry.php @@ -179,16 +179,16 @@ class Entry extends Model { public function toArray () { return array ( 'id' => $this->id (), - 'guid' => substr($this->guid (), 0, 65535), - 'title' => substr($this->title (), 0, 255), - 'author' => substr($this->author (), 0, 255), - 'content' => substr($this->content (), 0, 65535), - 'link' => substr($this->link (), 0, 65535), + 'guid' => $this->guid (), + 'title' => $this->title (), + 'author' => $this->author (), + 'content' => $this->content (), + 'link' => $this->link (), 'date' => $this->date (true), 'is_read' => $this->isRead (), 'is_favorite' => $this->isFavorite (), 'id_feed' => $this->feed (), - 'tags' => substr($this->tags (true), 0, 65535), + 'tags' => $this->tags (true), ); } } @@ -200,16 +200,16 @@ class EntryDAO extends Model_pdo { $values = array ( $valuesTmp['id'], - $valuesTmp['guid'], - $valuesTmp['title'], - $valuesTmp['author'], + substr($valuesTmp['guid'], 0, 511), + substr($valuesTmp['title'], 0, 255), + substr($valuesTmp['author'], 0, 255), base64_encode (gzdeflate (serialize ($valuesTmp['content']))), - $valuesTmp['link'], + substr($valuesTmp['link'], 0, 1023), $valuesTmp['date'], $valuesTmp['is_read'], $valuesTmp['is_favorite'], $valuesTmp['id_feed'], - $valuesTmp['tags'], + substr($valuesTmp['tags'], 0, 1023), ); if ($stm && $stm->execute ($values)) { diff --git a/app/models/Feed.php b/app/models/Feed.php index 41750d43e..c6ebc9caf 100644 --- a/app/models/Feed.php +++ b/app/models/Feed.php @@ -309,11 +309,11 @@ class FeedDAO extends Model_pdo { $values = array ( $valuesTmp['id'], - $valuesTmp['url'], + substr($valuesTmp['url'], 0, 511), $valuesTmp['category'], - $valuesTmp['name'], - $valuesTmp['website'], - $valuesTmp['description'], + substr($valuesTmp['name'], 0, 255), + substr($valuesTmp['website'], 0, 255), + substr($valuesTmp['description'], 0, 1023), $valuesTmp['lastUpdate'], base64_encode ($valuesTmp['httpAuth']), ); diff --git a/public/install.php b/public/install.php index ec7d50fbd..dd9846fe5 100644 --- a/public/install.php +++ b/public/install.php @@ -11,7 +11,7 @@ if (isset ($_GET['step'])) { define ('SQL_REQ_CREATE_DB', 'CREATE DATABASE %s DEFAULT CHARACTER SET utf8 COLLATE utf8_unicode_ci;'); define ('SQL_REQ_CAT', 'CREATE TABLE IF NOT EXISTS `%scategory` ( - `id` varchar(6) NOT NULL, + `id` char(6) NOT NULL, `name` varchar(255) NOT NULL, `color` varchar(7) NOT NULL, PRIMARY KEY (`id`), @@ -19,16 +19,16 @@ define ('SQL_REQ_CAT', 'CREATE TABLE IF NOT EXISTS `%scategory` ( );'); define ('SQL_REQ_FEED', 'CREATE TABLE IF NOT EXISTS `%sfeed` ( - `id` varchar(6) NOT NULL, - `url` text NOT NULL, - `category` varchar(6) DEFAULT \'000000\', + `id` char(6) NOT NULL, + `url` varchar(511) NOT NULL, + `category` char(6) DEFAULT \'000000\', `name` varchar(255) NOT NULL, - `website` text NOT NULL, - `description` text NOT NULL, + `website` varchar(255) NOT NULL, + `description` varchar(1023) NOT NULL, `lastUpdate` int(11) NOT NULL, `priority` tinyint NOT NULL DEFAULT \'10\', - `pathEntries` varchar(500) DEFAULT NULL, - `httpAuth` varchar(500) DEFAULT NULL, + `pathEntries` varchar(511) DEFAULT NULL, + `httpAuth` varchar(511) DEFAULT NULL, `error` boolean NOT NULL DEFAULT \'0\', `keep_history` boolean NOT NULL DEFAULT \'0\', PRIMARY KEY (`id`), @@ -39,17 +39,17 @@ define ('SQL_REQ_FEED', 'CREATE TABLE IF NOT EXISTS `%sfeed` ( );'); define ('SQL_REQ_ENTRY', 'CREATE TABLE IF NOT EXISTS `%sentry` ( - `id` varchar(6) NOT NULL, - `guid` text NOT NULL, + `id` char(6) NOT NULL, + `guid` varchar(511) NOT NULL, `title` varchar(255) NOT NULL, `author` varchar(255) NOT NULL, `content` text NOT NULL, - `link` text NOT NULL, + `link` varchar(1023) NOT NULL, `date` int(11) NOT NULL, `is_read` boolean NOT NULL DEFAULT \'0\', `is_favorite` boolean NOT NULL DEFAULT \'0\', - `id_feed` varchar(6) NOT NULL, - `tags` text NOT NULL, + `id_feed` char(6) NOT NULL, + `tags` varchar(1023) NOT NULL, PRIMARY KEY (`id`), FOREIGN KEY (`id_feed`) REFERENCES %sfeed(id) ON DELETE CASCADE ON UPDATE CASCADE, INDEX (`is_favorite`), -- cgit v1.2.3 From 94c5f41f6d663114bfac9390fc9eb72605a9e8ce Mon Sep 17 00:00:00 2001 From: Alexandre Alapetite Date: Mon, 11 Nov 2013 22:27:11 +0100 Subject: MySQL : protection longueurs catégories MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/models/Category.php | 4 ++-- public/install.php | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) (limited to 'app/models') diff --git a/app/models/Category.php b/app/models/Category.php index 7659e68f6..419284130 100755 --- a/app/models/Category.php +++ b/app/models/Category.php @@ -95,8 +95,8 @@ class CategoryDAO extends Model_pdo { $values = array ( $valuesTmp['id'], - $valuesTmp['name'], - $valuesTmp['color'], + substr($valuesTmp['name'], 0, 255), + substr($valuesTmp['color'], 0, 7), ); if ($stm && $stm->execute ($values)) { diff --git a/public/install.php b/public/install.php index dd9846fe5..7dde53e20 100644 --- a/public/install.php +++ b/public/install.php @@ -13,7 +13,7 @@ define ('SQL_REQ_CREATE_DB', 'CREATE DATABASE %s DEFAULT CHARACTER SET utf8 COLL define ('SQL_REQ_CAT', 'CREATE TABLE IF NOT EXISTS `%scategory` ( `id` char(6) NOT NULL, `name` varchar(255) NOT NULL, - `color` varchar(7) NOT NULL, + `color` char(7) NOT NULL, PRIMARY KEY (`id`), INDEX (`name`) );'); @@ -26,7 +26,7 @@ define ('SQL_REQ_FEED', 'CREATE TABLE IF NOT EXISTS `%sfeed` ( `website` varchar(255) NOT NULL, `description` varchar(1023) NOT NULL, `lastUpdate` int(11) NOT NULL, - `priority` tinyint NOT NULL DEFAULT \'10\', + `priority` tinyint(2) NOT NULL DEFAULT \'10\', `pathEntries` varchar(511) DEFAULT NULL, `httpAuth` varchar(511) DEFAULT NULL, `error` boolean NOT NULL DEFAULT \'0\', -- cgit v1.2.3 From 14342603a05b64294762c45798debe3a66db26eb Mon Sep 17 00:00:00 2001 From: Alexandre Alapetite Date: Tue, 12 Nov 2013 18:41:31 +0100 Subject: Suppression de requêtes de catégorie et de flux MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Suppression de requêtes inutiles en utilisant mieux les données déjà reçues. * Change la signature de `CategoryDAO->listCategories ($prePopulateFeeds = true, $details = false)` pour ne pas charger de détails inutiles pour la vue principale (comme feed.description, feed.url...). * C'est la requête la plus importante. Suite de https://github.com/marienfressinaud/FreshRSS/pull/180 --- app/controllers/configureController.php | 5 +---- app/models/Category.php | 31 ++++++++++++++++++++++--------- app/models/Feed.php | 33 +++++++++++++++++---------------- 3 files changed, 40 insertions(+), 29 deletions(-) (limited to 'app/models') diff --git a/app/controllers/configureController.php b/app/controllers/configureController.php index 4c1930d31..e9e049f98 100755 --- a/app/controllers/configureController.php +++ b/app/controllers/configureController.php @@ -84,7 +84,7 @@ class configureController extends ActionController { $this->view->flux = false; if ($id != false) { - $this->view->flux = $feedDAO->searchById ($id); + $this->view->flux = $this->view->feeds[$id]; if (!$this->view->flux) { Error::error ( @@ -92,9 +92,6 @@ class configureController extends ActionController { array ('error' => array (Translate::t ('page_not_found'))) ); } else { - $catDAO = new CategoryDAO (); - $this->view->categories = $catDAO->listCategories (false); - if (Request::isPost () && $this->view->flux) { $name = Request::param ('name', ''); $hist = Request::param ('keep_history', 'no'); diff --git a/app/models/Category.php b/app/models/Category.php index 419284130..9b36b3bcc 100755 --- a/app/models/Category.php +++ b/app/models/Category.php @@ -175,12 +175,13 @@ class CategoryDAO extends Model_pdo { } } - public function listCategories ($prePopulateFeeds = true) { + public function listCategories ($prePopulateFeeds = true, $details = false) { if ($prePopulateFeeds) { - $sql = 'SELECT c.id AS c_id, c.name AS c_name, c.color AS c_color, ' + $sql = 'SELECT c.id AS c_id, c.name AS c_name, ' + . ($details ? 'c.color AS c_color, ' : '') . 'COUNT(CASE WHEN e.is_read = 0 THEN 1 END) AS nbNotRead, ' . 'COUNT(e.id) AS nbEntries, ' - . 'f.* ' + . ($details ? 'f.* ' : 'f.id, f.name, f.website, f.priority, f.error ') . 'FROM ' . $this->prefix . 'category c ' . 'LEFT OUTER JOIN ' . $this->prefix . 'feed f ON f.category = c.id ' . 'LEFT OUTER JOIN ' . $this->prefix . 'entry e ON e.id_feed = f.id ' @@ -270,6 +271,18 @@ class HelperCategory { return null; } + public static function CountUnreads($categories, $minPriority = 0) { + $n = 0; + foreach ($categories as $category) { + foreach ($category->feeds () as $feed) { + if ($feed->priority () >= $minPriority) { + $n += $feed->nbNotRead(); + } + } + } + return $n; + } + public static function daoToCategoryPrepopulated ($listDAO) { $list = array (); @@ -284,11 +297,11 @@ class HelperCategory { // End of the current category, we add it to the $list $cat = new Category ( $previousLine['c_name'], - $previousLine['c_color'], - HelperFeed::daoToFeed ($feedsDao) + isset($previousLine['c_color']) ? $previousLine['c_color'] : '', + HelperFeed::daoToFeed ($feedsDao, $previousLine['c_id']) ); $cat->_id ($previousLine['c_id']); - $list[] = $cat; + $list[$previousLine['c_id']] = $cat; $feedsDao = array(); //Prepare for next category } @@ -301,11 +314,11 @@ class HelperCategory { if ($previousLine != null) { $cat = new Category ( $previousLine['c_name'], - $previousLine['c_color'], - HelperFeed::daoToFeed ($feedsDao) + isset($previousLine['c_color']) ? $previousLine['c_color'] : '', + HelperFeed::daoToFeed ($feedsDao, $previousLine['c_id']) ); $cat->_id ($previousLine['c_id']); - $list[] = $cat; + $list[$previousLine['c_id']] = $cat; } return $list; diff --git a/app/models/Feed.php b/app/models/Feed.php index c6ebc9caf..75dff01b7 100644 --- a/app/models/Feed.php +++ b/app/models/Feed.php @@ -533,7 +533,7 @@ class FeedDAO extends Model_pdo { } class HelperFeed { - public static function daoToFeed ($listDAO) { + public static function daoToFeed ($listDAO, $catID = null) { $list = array (); if (!is_array ($listDAO)) { @@ -541,33 +541,34 @@ class HelperFeed { } foreach ($listDAO as $key => $dao) { - if (empty ($dao['url'])) { + if (!isset ($dao['name'])) { continue; } if (isset ($dao['id'])) { $key = $dao['id']; } - $list[$key] = new Feed ($dao['url'], false); - $list[$key]->_category ($dao['category']); - $list[$key]->_name ($dao['name']); - $list[$key]->_website ($dao['website']); - $list[$key]->_description ($dao['description']); - $list[$key]->_lastUpdate ($dao['lastUpdate']); - $list[$key]->_priority ($dao['priority']); - $list[$key]->_pathEntries ($dao['pathEntries']); - $list[$key]->_httpAuth (base64_decode ($dao['httpAuth'])); - $list[$key]->_error ($dao['error']); - $list[$key]->_keepHistory ($dao['keep_history']); + $myFeed = new Feed (isset($dao['url']) ? $dao['url'] : '', false); + $myFeed->_category ($catID === null ? $dao['category'] : $catID); + $myFeed->_name ($dao['name']); + $myFeed->_website ($dao['website']); + $myFeed->_description (isset($dao['description']) ? $dao['description'] : ''); + $myFeed->_lastUpdate (isset($dao['lastUpdate']) ? $dao['lastUpdate'] : 0); + $myFeed->_priority ($dao['priority']); + $myFeed->_pathEntries (isset($dao['pathEntries']) ? $dao['pathEntries'] : ''); + $myFeed->_httpAuth (isset($dao['httpAuth']) ? base64_decode ($dao['httpAuth']) : ''); + $myFeed->_error ($dao['error']); + $myFeed->_keepHistory (isset($dao['keep_history']) ? $dao['keep_history'] : ''); if (isset ($dao['nbNotRead'])) { - $list[$key]->_nbNotRead ($dao['nbNotRead']); + $myFeed->_nbNotRead ($dao['nbNotRead']); } if (isset ($dao['nbEntries'])) { - $list[$key]->_nbEntries ($dao['nbEntries']); + $myFeed->_nbEntries ($dao['nbEntries']); } if (isset ($dao['id'])) { - $list[$key]->_id ($dao['id']); + $myFeed->_id ($dao['id']); } + $list[$key] = $myFeed; } return $list; -- cgit v1.2.3 From 3f93866f38aff6b9f10d57472bf0ccf16d268499 Mon Sep 17 00:00:00 2001 From: Alexandre Alapetite Date: Tue, 12 Nov 2013 18:49:18 +0100 Subject: SQL : Optimisation vitesse MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Optimisation de la vitesse de quelques requêtes, surtout après les essais d'INDEX. Suite de https://github.com/marienfressinaud/FreshRSS/issues/254 Note pour plus tard : il faudra supprimer les INDEX inutilisés. --- app/layout/aside_flux.phtml | 2 +- app/models/Entry.php | 47 +++++++++++++++++++-------------------------- public/install.php | 2 +- 3 files changed, 22 insertions(+), 29 deletions(-) (limited to 'app/models') diff --git a/app/layout/aside_flux.phtml b/app/layout/aside_flux.phtml index 511bb4564..87e2c000d 100644 --- a/app/layout/aside_flux.phtml +++ b/app/layout/aside_flux.phtml @@ -24,7 +24,7 @@ diff --git a/app/models/Entry.php b/app/models/Entry.php index d03c3a3c1..5c6b379d8 100755 --- a/app/models/Entry.php +++ b/app/models/Entry.php @@ -449,42 +449,35 @@ class EntryDAO extends Model_pdo { } public function countUnreadRead () { - $sql = 'SELECT is_read, COUNT(*) AS count FROM ' . $this->prefix . 'entry e INNER JOIN ' . $this->prefix . 'feed f ON e.id_feed = f.id WHERE priority > 0 GROUP BY is_read'; + $sql = 'SELECT COUNT(e.id) AS count FROM ' . $this->prefix . 'entry e INNER JOIN ' . $this->prefix . 'feed f ON e.id_feed = f.id WHERE priority > 0' + . ' UNION SELECT COUNT(e.id) AS count FROM ' . $this->prefix . 'entry e INNER JOIN ' . $this->prefix . 'feed f ON e.id_feed = f.id WHERE priority > 0 AND is_read = 0'; $stm = $this->bd->prepare ($sql); $stm->execute (); - $res = $stm->fetchAll (PDO::FETCH_ASSOC); - - $readUnread = array('unread' => 0, 'read' => 0); - foreach ($res as $line) { - switch (intval($line['is_read'])) { - case 0: $readUnread['unread'] = intval($line['count']); break; - case 1: $readUnread['read'] = intval($line['count']); break; - } - } - return $readUnread; + $res = $stm->fetchAll (PDO::FETCH_COLUMN, 0); + return array('total' => $res[0], 'unread' => $res[1], 'read' => $res[0] - $res[1]); } - public function count () { //Deprecated: use countUnreadRead() instead - $unreadRead = $this->countUnreadRead (); //This makes better use of caching - return $unreadRead['unread'] + $unreadRead['read']; + public function count () { + $sql = 'SELECT COUNT(e.id) AS count FROM ' . $this->prefix . 'entry e INNER JOIN ' . $this->prefix . 'feed f ON e.id_feed = f.id WHERE priority > 0'; + $stm = $this->bd->prepare ($sql); + $stm->execute (); + $res = $stm->fetchAll (PDO::FETCH_COLUMN, 0); + return $res[0]; } - public function countNotRead () { //Deprecated: use countUnreadRead() instead - $unreadRead = $this->countUnreadRead (); //This makes better use of caching - return $unreadRead['unread']; + public function countNotRead () { + $sql = 'SELECT COUNT(e.id) AS count FROM ' . $this->prefix . 'entry e INNER JOIN ' . $this->prefix . 'feed f ON e.id_feed = f.id WHERE priority > 0 AND is_read = 0'; + $stm = $this->bd->prepare ($sql); + $stm->execute (); + $res = $stm->fetchAll (PDO::FETCH_COLUMN, 0); + return $res[0]; } public function countUnreadReadFavorites () { - $sql = 'SELECT is_read, COUNT(*) AS count FROM ' . $this->prefix . 'entry WHERE is_favorite=1 GROUP BY is_read'; + $sql = 'SELECT COUNT(id) FROM ' . $this->prefix . 'entry WHERE is_favorite=1' + . ' UNION SELECT COUNT(id) FROM ' . $this->prefix . 'entry WHERE is_favorite=1 AND is_read = 0'; $stm = $this->bd->prepare ($sql); $stm->execute (); - $res = $stm->fetchAll (PDO::FETCH_ASSOC); - $readUnread = array('unread' => 0, 'read' => 0); - foreach ($res as $line) { - switch (intval($line['is_read'])) { - case 0: $readUnread['unread'] = intval($line['count']); break; - case 1: $readUnread['read'] = intval($line['count']); break; - } - } - return $readUnread; + $res = $stm->fetchAll (PDO::FETCH_COLUMN, 0); + return array('all' => $res[0], 'unread' => $res[1], 'read' => $res[0] - $res[1]); } public function optimizeTable() { diff --git a/public/install.php b/public/install.php index 7dde53e20..0dfe77c57 100644 --- a/public/install.php +++ b/public/install.php @@ -24,7 +24,7 @@ define ('SQL_REQ_FEED', 'CREATE TABLE IF NOT EXISTS `%sfeed` ( `category` char(6) DEFAULT \'000000\', `name` varchar(255) NOT NULL, `website` varchar(255) NOT NULL, - `description` varchar(1023) NOT NULL, + `description` text NOT NULL, `lastUpdate` int(11) NOT NULL, `priority` tinyint(2) NOT NULL DEFAULT \'10\', `pathEntries` varchar(511) DEFAULT NULL, -- cgit v1.2.3 From 4c5e9d0dd828ec9da44b0f178edd73b7213d6d20 Mon Sep 17 00:00:00 2001 From: Alexandre Alapetite Date: Tue, 12 Nov 2013 22:37:25 +0100 Subject: Cohérence htmlspecialchars MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Le texte dans la base de données est en htmlspecialchars(UTF-8) (c'est-à-dire avec `<>&'"` encodés) mais maintenant sans autre entité HTML depuis https://github.com/marienfressinaud/FreshRSS/commit/a4fc7becb8553198d132633d775989c89c8116cd Ce patch supprime les htmlspecialchars qui faisaient du double-encodage, et en modifie d'autres en entrée. --- app/layout/aside_feed.phtml | 2 +- app/layout/aside_flux.phtml | 4 ++-- app/layout/layout.phtml | 2 +- app/models/Entry.php | 2 +- app/views/helpers/view/global_view.phtml | 4 ++-- app/views/helpers/view/normal_view.phtml | 3 +-- app/views/helpers/view/reader_view.phtml | 2 +- app/views/helpers/view/rss_view.phtml | 2 +- lib/minz/Request.php | 7 +++++-- 9 files changed, 15 insertions(+), 13 deletions(-) (limited to 'app/models') diff --git a/app/layout/aside_feed.phtml b/app/layout/aside_feed.phtml index 3cfce61c5..49767740b 100644 --- a/app/layout/aside_feed.phtml +++ b/app/layout/aside_feed.phtml @@ -54,7 +54,7 @@
  • ✇ - name (), ENT_NOQUOTES, 'UTF-8'); ?> + name (); ?>
  • diff --git a/app/layout/aside_flux.phtml b/app/layout/aside_flux.phtml index 87e2c000d..9471f1f7e 100644 --- a/app/layout/aside_flux.phtml +++ b/app/layout/aside_flux.phtml @@ -35,7 +35,7 @@
  • get_c == $cat->id ()) { $c_active = true; } ?> @@ -51,7 +51,7 @@ ✇ - name(), ENT_NOQUOTES, 'UTF-8'); ?> + name(); ?>
  • diff --git a/app/layout/layout.phtml b/app/layout/layout.phtml index 9d4147887..adcc74871 100644 --- a/app/layout/layout.phtml +++ b/app/layout/layout.phtml @@ -19,7 +19,7 @@ rss_url)) { ?> - + diff --git a/app/models/Entry.php b/app/models/Entry.php index 5c6b379d8..e40cb5992 100755 --- a/app/models/Entry.php +++ b/app/models/Entry.php @@ -409,7 +409,7 @@ class EntryDAO extends Model_pdo { } $sql = 'SELECT e.* FROM ' . $this->prefix . 'entry e' - . ' INNER JOIN ' . $this->prefix . 'feed f ON e.id_feed = f.id' . $where + . ' INNER JOIN ' . $this->prefix . 'feed f ON e.id_feed = f.id' . $where . ' ORDER BY e.date' . $order . ', e.id' . $order; if (empty($limitCount)) { diff --git a/app/views/helpers/view/global_view.phtml b/app/views/helpers/view/global_view.phtml index fc55ed8ba..0eb29b11a 100644 --- a/app/views/helpers/view/global_view.phtml +++ b/app/views/helpers/view/global_view.phtml @@ -10,7 +10,7 @@
    @@ -22,7 +22,7 @@ 0 ? '' : ''; ?> - name(), ENT_NOQUOTES, 'UTF-8'); ?> + name(); ?> 0 ? ' (' . $not_read . ')' : ''; ?> 0 ? '' : ''; ?> diff --git a/app/views/helpers/view/normal_view.phtml b/app/views/helpers/view/normal_view.phtml index 173fbad9a..faa52179a 100644 --- a/app/views/helpers/view/normal_view.phtml +++ b/app/views/helpers/view/normal_view.phtml @@ -46,7 +46,7 @@ if (isset ($this->entryPaginator) && !$this->entryPaginator->isEmpty ()) { $feed = HelperCategory::findFeed($this->cat_aside, $item->feed ()); //We most likely already have the feed object in cache if (empty($feed)) $feed = $item->feed (true); ?> -
  • ✇ name(), ENT_NOQUOTES, 'UTF-8'); ?>
  • +
  • ✇ name(); ?>
  • title (); ?>
  • conf->toplineDate ()) { ?>
  • date (); ?> 
  • conf->toplineLink ()) { ?> @@ -65,7 +65,6 @@ if (isset ($this->entryPaginator) && !$this->entryPaginator->isEmpty ()) { } ?>
    -
      conf) || is_logged ()) { ?> conf->bottomlineRead ()) { ?>
    •  
    • diff --git a/app/views/helpers/view/reader_view.phtml b/app/views/helpers/view/reader_view.phtml index f808990f7..9b8ec6cde 100644 --- a/app/views/helpers/view/reader_view.phtml +++ b/app/views/helpers/view/reader_view.phtml @@ -16,7 +16,7 @@ if (isset ($this->entryPaginator) && !$this->entryPaginator->isEmpty ()) { if (empty($feed)) $feed = $item->feed (true); ?> - ✇ name(), ENT_NOQUOTES, 'UTF-8'); ?> + ✇ name(); ?>

      title (); ?>

      diff --git a/app/views/helpers/view/rss_view.phtml b/app/views/helpers/view/rss_view.phtml index 9358ef2a5..e34f3b8b5 100755 --- a/app/views/helpers/view/rss_view.phtml +++ b/app/views/helpers/view/rss_view.phtml @@ -12,7 +12,7 @@ $items = $this->entryPaginator->items (); foreach ($items as $item) { ?> - <?php echo htmlspecialchars(html_entity_decode($item->title (), ENT_NOQUOTES, 'UTF-8'), ENT_NOQUOTES, 'UTF-8'); ?> + <?php echo $item->title (); ?> link (); ?> author (); ?> diff --git a/lib/minz/Request.php b/lib/minz/Request.php index ffddbe6ad..3e508d8f1 100644 --- a/lib/minz/Request.php +++ b/lib/minz/Request.php @@ -29,15 +29,18 @@ class Request { public static function params () { return self::$params; } + static function htmlspecialchars_utf8 ($p) { + return htmlspecialchars($p, ENT_QUOTES, 'UTF-8'); + } public static function param ($key, $default = false, $specialchars = false) { if (isset (self::$params[$key])) { $p = self::$params[$key]; if(is_object($p) || $specialchars) { return $p; } elseif(is_array($p)) { - return array_map('htmlspecialchars', $p); //TODO: Should use explicit UTF-8 + return array_map('self::htmlspecialchars_utf8', $p); } else { - return htmlspecialchars($p, ENT_NOQUOTES, 'UTF-8'); + return self::htmlspecialchars_utf8($p); } } else { return $default; -- cgit v1.2.3 From d654b34fa7c1f5a09ec8c9bf2b82b43bf5efaa7d Mon Sep 17 00:00:00 2001 From: Alexandre Alapetite Date: Wed, 13 Nov 2013 21:32:50 +0100 Subject: Affichage du nombre total d'article sur la page de configuration MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit https://github.com/marienfressinaud/FreshRSS/issues/263 Style à améliorer éventuellement --- app/controllers/configureController.php | 3 +++ app/models/Entry.php | 14 ++++++++++---- app/views/configure/display.phtml | 5 +++-- 3 files changed, 16 insertions(+), 6 deletions(-) (limited to 'app/models') diff --git a/app/controllers/configureController.php b/app/controllers/configureController.php index e9e049f98..815f3f5f4 100755 --- a/app/controllers/configureController.php +++ b/app/controllers/configureController.php @@ -259,6 +259,9 @@ class configureController extends ActionController { $this->view->themes = RSSThemes::get(); View::prependTitle (Translate::t ('general_and_reading_management') . ' - '); + + $entryDAO = new EntryDAO (); + $this->view->nb_total = $entryDAO->count (); } public function importExportAction () { diff --git a/app/models/Entry.php b/app/models/Entry.php index e40cb5992..c6715a431 100755 --- a/app/models/Entry.php +++ b/app/models/Entry.php @@ -456,15 +456,21 @@ class EntryDAO extends Model_pdo { $res = $stm->fetchAll (PDO::FETCH_COLUMN, 0); return array('total' => $res[0], 'unread' => $res[1], 'read' => $res[0] - $res[1]); } - public function count () { - $sql = 'SELECT COUNT(e.id) AS count FROM ' . $this->prefix . 'entry e INNER JOIN ' . $this->prefix . 'feed f ON e.id_feed = f.id WHERE priority > 0'; + public function count ($minPriority = null) { + $sql = 'SELECT COUNT(e.id) AS count FROM ' . $this->prefix . 'entry e INNER JOIN ' . $this->prefix . 'feed f ON e.id_feed = f.id'; + if ($minPriority !== null) { + $sql = ' WHERE priority > ' . intval($minPriority); + } $stm = $this->bd->prepare ($sql); $stm->execute (); $res = $stm->fetchAll (PDO::FETCH_COLUMN, 0); return $res[0]; } - public function countNotRead () { - $sql = 'SELECT COUNT(e.id) AS count FROM ' . $this->prefix . 'entry e INNER JOIN ' . $this->prefix . 'feed f ON e.id_feed = f.id WHERE priority > 0 AND is_read = 0'; + public function countNotRead ($minPriority = null) { + $sql = 'SELECT COUNT(e.id) AS count FROM ' . $this->prefix . 'entry e INNER JOIN ' . $this->prefix . 'feed f ON e.id_feed = f.id WHERE is_read = 0'; + if ($minPriority !== null) { + $sql = ' AND priority > ' . intval($minPriority); + } $stm = $this->bd->prepare ($sql); $stm->execute (); $res = $stm->fetchAll (PDO::FETCH_COLUMN, 0); diff --git a/app/views/configure/display.phtml b/app/views/configure/display.phtml index 20d1e7089..22fc72f1b 100644 --- a/app/views/configure/display.phtml +++ b/app/views/configure/display.phtml @@ -204,9 +204,10 @@ -- cgit v1.2.3 From 803cd05a58c93b91dc73db32fd95cc11372aa82f Mon Sep 17 00:00:00 2001 From: Alexandre Alapetite Date: Wed, 13 Nov 2013 22:47:26 +0100 Subject: Amélioration vitesse lecture des logs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/models/Log_Model.php | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) (limited to 'app/models') diff --git a/app/models/Log_Model.php b/app/models/Log_Model.php index 5c280fa7a..988996c9d 100644 --- a/app/models/Log_Model.php +++ b/app/models/Log_Model.php @@ -29,19 +29,18 @@ class LogDAO extends Model_txt { public function __construct () { parent::__construct (LOG_PATH . '/application.log', 'r+'); } - + public function lister () { $logs = array (); - - $i = 0; while (($line = $this->readLine ()) !== false) { - $logs[$i] = new Log_Model (); - $logs[$i]->_date (preg_replace ("'\[(.*?)\] \[(.*?)\] --- (.*?)'U", "\\1", $line)); - $logs[$i]->_level (preg_replace ("'\[(.*?)\] \[(.*?)\] --- (.*?)'U", "\\2", $line)); - $logs[$i]->_info (preg_replace ("'\[(.*?)\] \[(.*?)\] --- (.*?)'U", "\\3", $line)); - $i++; + if (preg_match ('/^\[([^\[]+)\] \[([^\[]+)\] --- (.*)$/', $line, $matches)) { + $myLog = new Log_Model (); + $myLog->_date ($matches[1]); + $myLog->_level ($matches[2]); + $myLog->_info ($matches[3]); + $logs[] = $myLog; + } } - return $logs; } } \ No newline at end of file -- cgit v1.2.3 From 3744df6866857d6bcdac76e916586411f1d605ac Mon Sep 17 00:00:00 2001 From: Alexandre Alapetite Date: Fri, 15 Nov 2013 19:00:02 +0100 Subject: Url absolues pour les balises video, audio, source, track Corrige https://github.com/marienfressinaud/FreshRSS/issues/267 --- app/models/Feed.php | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) (limited to 'app/models') diff --git a/app/models/Feed.php b/app/models/Feed.php index 75dff01b7..407614f9f 100644 --- a/app/models/Feed.php +++ b/app/models/Feed.php @@ -212,6 +212,24 @@ class Feed extends Model { 'onload', 'onunload', 'onclick', 'ondblclick', 'onmousedown', 'onmouseup', 'onmouseover', 'onmousemove', 'onmouseout', 'onfocus', 'onblur', 'onkeypress', 'onkeydown', 'onkeyup', 'onselect', 'onchange'))); + $feed->set_url_replacements(array( + 'a' => 'href', + 'area' => 'href', + 'audio' => 'src', + 'blockquote' => 'cite', + 'del' => 'cite', + 'form' => 'action', + 'img' => array( + 'longdesc', + 'src' + ), + 'input' => 'src', + 'ins' => 'cite', + 'q' => 'cite', + 'source' => 'src', + 'track' => 'src', + 'video' => 'src', + )); $feed->init (); if ($feed->error ()) { -- cgit v1.2.3 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/controllers/entryController.php | 14 +-- app/controllers/feedController.php | 22 +++- app/controllers/indexController.php | 27 ++++- app/models/Category.php | 11 +- app/models/EntriesGetter.php | 8 -- app/models/Entry.php | 228 ++++++++++++++++++++++++++++-------- app/models/Feed.php | 84 +++++++------ lib/minz/dao/Model_pdo.php | 10 ++ public/install.php | 24 ++-- 9 files changed, 294 insertions(+), 134 deletions(-) (limited to 'app/models') diff --git a/app/controllers/entryController.php b/app/controllers/entryController.php index 1ba9cc3cd..4d2d92c1b 100755 --- a/app/controllers/entryController.php +++ b/app/controllers/entryController.php @@ -43,28 +43,27 @@ class entryController extends ActionController { $entryDAO = new EntryDAO (); if ($id == false) { if (!$get) { - $entryDAO->markReadEntries ($is_read, $dateMax); + $entryDAO->markReadEntries ($dateMax); } else { $typeGet = $get[0]; $get = substr ($get, 2); if ($typeGet == 'c') { - $entryDAO->markReadCat ($get, $is_read, $dateMax); + $entryDAO->markReadCat ($get, $dateMax); $this->params = array ('get' => $nextGet); } elseif ($typeGet == 'f') { - $entryDAO->markReadFeed ($get, $is_read, $dateMax); + $entryDAO->markReadFeed ($get, $dateMax); $this->params = array ('get' => $nextGet); } } - // notif $notif = array ( 'type' => 'good', 'content' => Translate::t ('feeds_marked_read') ); Session::_param ('notification', $notif); } else { - $entryDAO->updateEntry ($id, array ('is_read' => $is_read)); + $entryDAO->markRead ($id, $is_read); } } @@ -74,10 +73,7 @@ class entryController extends ActionController { $id = Request::param ('id'); if ($id) { $entryDAO = new EntryDAO (); - $values = array ( - 'is_favorite' => (bool)(Request::param ('is_favorite')), - ); - $entryDAO->updateEntry ($id, $values); + $entryDAO->markFavorite ($id, Request::param ('is_favorite')); } } diff --git a/app/controllers/feedController.php b/app/controllers/feedController.php index 76fca8828..0ba82631c 100755 --- a/app/controllers/feedController.php +++ b/app/controllers/feedController.php @@ -33,6 +33,7 @@ class feedController extends ActionController { $pass = Request::param ('password'); $params = array (); + $transactionStarted = false; try { $feed = new Feed ($url); $feed->_category ($cat); @@ -79,6 +80,8 @@ class feedController extends ActionController { $nb_month_old = $this->view->conf->oldEntries (); $date_min = time () - (60 * 60 * 24 * 30 * $nb_month_old); + $transactionStarted = true; + $feedDAO->beginTransaction (); // on ajoute les articles en masse sans vérification foreach ($entries as $entry) { if ($entry->date (true) >= $date_min || @@ -87,6 +90,9 @@ class feedController extends ActionController { $entryDAO->addEntry ($values); } } + $feedDAO->updateLastUpdate ($feed->id ()); + $feedDAO->commit (); + $transactionStarted = false; // ok, ajout terminé $notif = array ( @@ -121,6 +127,9 @@ class feedController extends ActionController { ); Session::_param ('notification', $notif); } + if ($transactionStarted) { + $feedDAO->rollBack (); + } Request::forward (array ('c' => 'configure', 'a' => 'feed', 'params' => $params), true); } @@ -149,6 +158,13 @@ class feedController extends ActionController { // on calcule la date des articles les plus anciens qu'on accepte $nb_month_old = $this->view->conf->oldEntries (); $date_min = time () - (60 * 60 * 24 * 30 * $nb_month_old); + if (rand(0, 30) === 1) { + Minz_Log::record ('CleanOldEntries', Minz_Log::NOTICE); //TODO: Remove + if ($entryDAO->cleanOldEntries ($date_min) > 0) { + Minz_Log::record ('UpdateCachedValues', Minz_Log::NOTICE); //TODO: Remove + $feedDAO->updateCachedValues (); + } + } $i = 0; $flux_update = 0; @@ -165,6 +181,7 @@ class feedController extends ActionController { // car demanderait plus de ressources // La BDD refusera l'ajout de son côté car l'id doit être // unique + $feedDAO->beginTransaction (); foreach ($entries as $entry) { if ((!isset ($existingIds[$entry->id ()])) && ($entry->date (true) >= $date_min || @@ -176,10 +193,11 @@ class feedController extends ActionController { // on indique que le flux vient d'être mis à jour en BDD $feedDAO->updateLastUpdate ($feed->id ()); + $feedDAO->commit (); $flux_update++; } catch (FeedException $e) { Minz_Log::record ($e->getMessage (), Minz_Log::ERROR); - $feedDAO->isInError ($feed->id ()); + $feedDAO->updateLastUpdate ($feed->id (), 1); } // On arrête à 10 flux pour ne pas surcharger le serveur @@ -190,8 +208,6 @@ class feedController extends ActionController { } } - $entryDAO->cleanOldEntries ($nb_month_old); - $url = array (); if ($flux_update === 1) { // on a mis un seul flux à jour diff --git a/app/controllers/indexController.php b/app/controllers/indexController.php index 7b5dbd264..10c29bc7b 100755 --- a/app/controllers/indexController.php +++ b/app/controllers/indexController.php @@ -90,6 +90,30 @@ class indexController extends ActionController { $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'; + } + } + try { // EntriesGetter permet de déporter la complexité du filtrage $getter = new EntriesGetter ($type, $state, $filter, $order, $nb, $first); @@ -98,7 +122,8 @@ class indexController extends ActionController { // 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 ()) { + if ($state === 'not_read' && $entries->isEmpty ()) { //TODO: Remove in v0.8 + Minz_Log::record ('Conflicting information about nbNotRead!', Minz_Log::NOTICE); //TODO: Consider adding a Minz_Log::DEBUG level $this->view->state = 'all'; $getter->_state ('all'); $getter->execute (); diff --git a/app/models/Category.php b/app/models/Category.php index 9b36b3bcc..6e61b5a0e 100755 --- a/app/models/Category.php +++ b/app/models/Category.php @@ -100,7 +100,7 @@ class CategoryDAO extends Model_pdo { ); if ($stm && $stm->execute ($values)) { - return true; + return $stm->rowCount(); } else { $info = $stm->errorInfo(); Minz_Log::record ('SQL error : ' . $info[2], Minz_Log::ERROR); @@ -119,7 +119,7 @@ class CategoryDAO extends Model_pdo { ); if ($stm && $stm->execute ($values)) { - return true; + return $stm->rowCount(); } else { $info = $stm->errorInfo(); Minz_Log::record ('SQL error : ' . $info[2], Minz_Log::ERROR); @@ -134,7 +134,7 @@ class CategoryDAO extends Model_pdo { $values = array ($id); if ($stm && $stm->execute ($values)) { - return true; + return $stm->rowCount(); } else { $info = $stm->errorInfo(); Minz_Log::record ('SQL error : ' . $info[2], Minz_Log::ERROR); @@ -179,12 +179,9 @@ class CategoryDAO extends Model_pdo { if ($prePopulateFeeds) { $sql = 'SELECT c.id AS c_id, c.name AS c_name, ' . ($details ? 'c.color AS c_color, ' : '') - . 'COUNT(CASE WHEN e.is_read = 0 THEN 1 END) AS nbNotRead, ' - . 'COUNT(e.id) AS nbEntries, ' - . ($details ? 'f.* ' : 'f.id, f.name, f.website, f.priority, f.error ') + . ($details ? 'f.* ' : 'f.id, f.name, f.website, f.priority, f.error, f.cache_nbEntries, f.cache_nbUnreads ') . 'FROM ' . $this->prefix . 'category c ' . 'LEFT OUTER JOIN ' . $this->prefix . 'feed f ON f.category = c.id ' - . 'LEFT OUTER JOIN ' . $this->prefix . 'entry e ON e.id_feed = f.id ' . 'GROUP BY f.id ' . 'ORDER BY c.name, f.name'; $stm = $this->bd->prepare ($sql); 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'], diff --git a/app/models/Entry.php b/app/models/Entry.php index c6715a431..8b817cc14 100755 --- a/app/models/Entry.php +++ b/app/models/Entry.php @@ -213,17 +213,17 @@ class EntryDAO extends Model_pdo { ); if ($stm && $stm->execute ($values)) { - return true; + return $stm->rowCount(); } else { $info = $stm->errorInfo(); if ((int)($info[0] / 1000) !== 23) { //Filter out "SQLSTATE Class code 23: Constraint Violation" because of expected duplicate entries - Minz_Log::record ('SQL error ' . $info[0] . ': ' . $info[1] . ' ' . $info[2], Minz_Log::NOTICE); //TODO: Consider adding a Minz_Log::DEBUG level + Minz_Log::record ('SQL error ' . $info[0] . ': ' . $info[1] . ' ' . $info[2], Minz_Log::ERROR); } return false; } } - public function updateEntry ($id, $valuesTmp) { + /*public function updateEntry ($id, $valuesTmp) { if (isset ($valuesTmp['content'])) { $valuesTmp['content'] = base64_encode (gzdeflate (serialize ($valuesTmp['content']))); } @@ -243,73 +243,201 @@ class EntryDAO extends Model_pdo { $values[] = $id; if ($stm && $stm->execute ($values)) { - return true; + return $stm->rowCount(); } else { $info = $stm->errorInfo(); Minz_Log::record ('SQL error : ' . $info[2], Minz_Log::ERROR); return false; } - } - - public function markReadEntries ($read, $dateMax = 0) { - $sql = 'UPDATE ' . $this->prefix . 'entry e INNER JOIN ' . $this->prefix . 'feed f ON e.id_feed = f.id SET is_read = ? WHERE priority > 0'; - - $values = array ($read); - if ($dateMax > 0) { - $sql .= ' AND date < ?'; - $values[] = $dateMax; - } - + }*/ + public function markFavorite ($id, $is_favorite = true) { + $sql = 'UPDATE ' . $this->prefix . 'entry e ' + . 'SET e.is_favorite = ? ' + . 'WHERE e.id=?'; + $values = array ($is_favorite ? 1 : 0, $id); $stm = $this->bd->prepare ($sql); if ($stm && $stm->execute ($values)) { - return true; + return $stm->rowCount(); } else { $info = $stm->errorInfo(); Minz_Log::record ('SQL error : ' . $info[2], Minz_Log::ERROR); return false; } } - public function markReadCat ($id, $read, $dateMax = 0) { - $sql = 'UPDATE ' . $this->prefix . 'entry e INNER JOIN ' . $this->prefix . 'feed f ON e.id_feed = f.id SET is_read = ? WHERE category = ?'; - - $values = array ($read, $id); - if ($dateMax > 0) { - $sql .= ' AND date < ?'; - $values[] = $dateMax; - } - + public function markRead ($id, $is_read = true) { + $sql = 'UPDATE ' . $this->prefix . 'entry e INNER JOIN ' . $this->prefix . 'feed f ON e.id_feed = f.id ' + . 'SET e.is_read = ?,' + . 'f.cache_nbUnreads=f.cache_nbUnreads' . ($is_read ? '-' : '+') . '1 ' + . 'WHERE e.id=?'; + $values = array ($is_read ? 1 : 0, $id); $stm = $this->bd->prepare ($sql); if ($stm && $stm->execute ($values)) { - return true; + return $stm->rowCount(); } else { $info = $stm->errorInfo(); Minz_Log::record ('SQL error : ' . $info[2], Minz_Log::ERROR); return false; } } - public function markReadFeed ($id, $read, $dateMax = 0) { - $sql = 'UPDATE ' . $this->prefix . 'entry SET is_read = ? WHERE id_feed = ?'; + public function markReadEntries ($dateMax = 0) { + if ($dateMax === 0) { + $sql = 'UPDATE ' . $this->prefix . 'entry e INNER JOIN ' . $this->prefix . 'feed f ON e.id_feed = f.id ' + . 'SET e.is_read = 1, f.cache_nbUnreads=0 ' + . 'WHERE e.is_read = 0 AND f.priority > 0'; + $stm = $this->bd->prepare ($sql); + if ($stm && $stm->execute ()) { + return $stm->rowCount(); + } else { + $info = $stm->errorInfo(); + Minz_Log::record ('SQL error : ' . $info[2], Minz_Log::ERROR); + return false; + } + } else { + $this->bd->beginTransaction (); + + $sql = 'UPDATE ' . $this->prefix . 'entry e INNER JOIN ' . $this->prefix . 'feed f ON e.id_feed = f.id ' + . 'SET e.is_read = 1 ' + . 'WHERE e.is_read = 0 AND e.date < ? AND f.priority > 0'; + $values = array ($dateMax); + $stm = $this->bd->prepare ($sql); + if (!($stm && $stm->execute ($values))) { + $info = $stm->errorInfo(); + Minz_Log::record ('SQL error : ' . $info[2], Minz_Log::ERROR); + $this->bd->rollBack (); + return false; + } + $affected = $stm->rowCount(); + + if ($affected > 0) { + $sql = 'UPDATE freshrss_feed f ' + . 'LEFT OUTER JOIN (' + . 'SELECT e.id_feed, ' + . 'COUNT(*) AS nbUnreads ' + . 'FROM freshrss_entry e ' + . 'WHERE e.is_read = 0 ' + . 'GROUP BY e.id_feed' + . ') x ON x.id_feed=f.id ' + . 'SET f.cache_nbUnreads=COALESCE(x.nbUnreads, 0)'; + $stm = $this->bd->prepare ($sql); + if (!($stm && $stm->execute ())) { + $info = $stm->errorInfo(); + Minz_Log::record ('SQL error : ' . $info[2], Minz_Log::ERROR); + $this->bd->rollBack (); + return false; + } + } - $values = array ($read, $id); - if ($dateMax > 0) { - $sql .= ' AND date < ?'; - $values[] = $dateMax; + $this->bd->commit (); + return $affected; } + } + public function markReadCat ($id, $dateMax = 0) { + if ($dateMax === 0) { + $sql = 'UPDATE ' . $this->prefix . 'entry e INNER JOIN ' . $this->prefix . 'feed f ON e.id_feed = f.id ' + . 'SET e.is_read = 1, f.cache_nbUnreads=0 ' + . 'WHERE f.category = ? AND e.is_read = 0'; + $values = array ($id); + $stm = $this->bd->prepare ($sql); + if ($stm && $stm->execute ($values)) { + return $stm->rowCount(); + } else { + $info = $stm->errorInfo(); + Minz_Log::record ('SQL error : ' . $info[2], Minz_Log::ERROR); + return false; + } + } else { + $this->bd->beginTransaction (); + + $sql = 'UPDATE ' . $this->prefix . 'entry e INNER JOIN ' . $this->prefix . 'feed f ON e.id_feed = f.id ' + . 'SET e.is_read = 1 ' + . 'WHERE f.category = ? AND e.is_read = 0 AND e.date < ?'; + $values = array ($id, $dateMax); + $stm = $this->bd->prepare ($sql); + if (!($stm && $stm->execute ($values))) { + $info = $stm->errorInfo(); + Minz_Log::record ('SQL error : ' . $info[2], Minz_Log::ERROR); + $this->bd->rollBack (); + return false; + } + $affected = $stm->rowCount(); + + if ($affected > 0) { + $sql = 'UPDATE freshrss_feed f ' + . 'LEFT OUTER JOIN (' + . 'SELECT e.id_feed, ' + . 'COUNT(*) AS nbUnreads ' + . 'FROM freshrss_entry e ' + . 'WHERE e.is_read = 0 ' + . 'GROUP BY e.id_feed' + . ') x ON x.id_feed=f.id ' + . 'SET f.cache_nbUnreads=COALESCE(x.nbUnreads, 0) ' + . 'WHERE f.category = ?'; + $values = array ($id); + $stm = $this->bd->prepare ($sql); + if (!($stm && $stm->execute ($values))) { + $info = $stm->errorInfo(); + Minz_Log::record ('SQL error : ' . $info[2], Minz_Log::ERROR); + $this->bd->rollBack (); + return false; + } + } - $stm = $this->bd->prepare ($sql); - - if ($stm && $stm->execute ($values)) { - return true; + $this->bd->commit (); + return $affected; + } + } + public function markReadFeed ($id, $dateMax = 0) { + if ($dateMax === 0) { + $sql = 'UPDATE ' . $this->prefix . 'entry e INNER JOIN ' . $this->prefix . 'feed f ON e.id_feed = f.id ' + . 'SET e.is_read = 1, f.cache_nbUnreads=0 ' + . 'WHERE f.id=? AND e.is_read = 0'; + $values = array ($id); + $stm = $this->bd->prepare ($sql); + if ($stm && $stm->execute ($values)) { + return $stm->rowCount(); + } else { + $info = $stm->errorInfo(); + Minz_Log::record ('SQL error : ' . $info[2], Minz_Log::ERROR); + return false; + } } else { - $info = $stm->errorInfo(); - Minz_Log::record ('SQL error : ' . $info[2], Minz_Log::ERROR); - return false; + $this->bd->beginTransaction (); + + $sql = 'UPDATE ' . $this->prefix . 'entry e INNER JOIN ' . $this->prefix . 'feed f ON e.id_feed = f.id ' + . 'SET e.is_read = 1 ' + . 'WHERE f.id=? AND e.is_read = 0 AND e.date < ?'; + $values = array ($id, $dateMax); + $stm = $this->bd->prepare ($sql); + if (!($stm && $stm->execute ($values))) { + $info = $stm->errorInfo(); + Minz_Log::record ('SQL error : ' . $info[2], Minz_Log::ERROR); + $this->bd->rollBack (); + return false; + } + $affected = $stm->rowCount(); + + if ($affected > 0) { + $sql = 'UPDATE ' . $this->prefix . 'feed f ' + . 'SET f.cache_nbUnreads=f.cache_nbUnreads-' . $affected + . ' WHERE f.id=?'; + $values = array ($id); + $stm = $this->bd->prepare ($sql); + if (!($stm && $stm->execute ($values))) { + $info = $stm->errorInfo(); + Minz_Log::record ('SQL error : ' . $info[2], Minz_Log::ERROR); + $this->bd->rollBack (); + return false; + } + } + + $this->bd->commit (); + return $affected; } } - public function updateEntries ($valuesTmp) { + /*public function updateEntries ($valuesTmp) { if (isset ($valuesTmp['content'])) { $valuesTmp['content'] = base64_encode (gzdeflate (serialize ($valuesTmp['content']))); } @@ -328,25 +456,24 @@ class EntryDAO extends Model_pdo { } if ($stm && $stm->execute ($values)) { - return true; + return $stm->rowCount(); } else { $info = $stm->errorInfo(); Minz_Log::record ('SQL error : ' . $info[2], Minz_Log::ERROR); return false; } - } + }*/ - public function cleanOldEntries ($nb_month) { - $date = 60 * 60 * 24 * 30 * $nb_month; + public function cleanOldEntries ($date_min) { $sql = 'DELETE e.* FROM ' . $this->prefix . 'entry e INNER JOIN ' . $this->prefix . 'feed f ON e.id_feed = f.id WHERE e.date <= ? AND e.is_favorite = 0 AND f.keep_history = 0'; $stm = $this->bd->prepare ($sql); $values = array ( - time () - $date + $date_min ); if ($stm && $stm->execute ($values)) { - return true; + return $stm->rowCount(); } else { $info = $stm->errorInfo(); Minz_Log::record ('SQL error : ' . $info[2], Minz_Log::ERROR); @@ -393,16 +520,16 @@ class EntryDAO extends Model_pdo { } private function listWhere ($where, $state, $order, $limitFromId = '', $limitCount = '', $values = array ()) { - if ($state == 'not_read') { + if ($state === 'not_read') { $where .= ' AND is_read = 0'; - } elseif ($state == 'read') { + } elseif ($state === 'read') { $where .= ' AND is_read = 1'; } if (!empty($limitFromId)) { //TODO: Consider using LPAD(e.date, 11) //CONCAT is for cases when many entries have the same date $where .= ' AND CONCAT(e.date, e.id) ' . ($order === 'low_to_high' ? '<=' : '>=') . ' (SELECT CONCAT(s.date, s.id) FROM ' . $this->prefix . 'entry s WHERE s.id = "' . $limitFromId . '")'; } - if ($order == 'low_to_high') { + if ($order === 'low_to_high') { $order = ' DESC'; } else { $order = ''; @@ -430,9 +557,6 @@ class EntryDAO extends Model_pdo { public function listFavorites ($state, $order = 'high_to_low', $limitFromId = '', $limitCount = '') { return $this->listWhere (' WHERE is_favorite = 1', $state, $order, $limitFromId, $limitCount); } - public function listPublic ($state, $order = 'high_to_low', $limitFromId = '', $limitCount = '') { - return $this->listWhere (' WHERE is_public = 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)); } diff --git a/app/models/Feed.php b/app/models/Feed.php index 407614f9f..ae3a9af83 100644 --- a/app/models/Feed.php +++ b/app/models/Feed.php @@ -337,7 +337,7 @@ class FeedDAO extends Model_pdo { ); if ($stm && $stm->execute ($values)) { - return true; + return $stm->rowCount(); } else { $info = $stm->errorInfo(); Minz_Log::record ('SQL error : ' . $info[2], Minz_Log::ERROR); @@ -365,7 +365,7 @@ class FeedDAO extends Model_pdo { $values[] = $id; if ($stm && $stm->execute ($values)) { - return true; + return $stm->rowCount(); } else { $info = $stm->errorInfo(); Minz_Log::record ('SQL error : ' . $info[2], Minz_Log::ERROR); @@ -373,34 +373,23 @@ class FeedDAO extends Model_pdo { } } - public function updateLastUpdate ($id) { - $sql = 'UPDATE ' . $this->prefix . 'feed SET lastUpdate=?, error=0 WHERE id=?'; - $stm = $this->bd->prepare ($sql); - - $values = array ( - time (), - $id - ); + public function updateLastUpdate ($id, $inError = 0) { + $sql = 'UPDATE ' . $this->prefix . 'feed f ' //2 sub-requests with FOREIGN KEY(e.id_feed), INDEX(e.is_read) faster than 1 request with GROUP BY or CASE + . 'SET f.cache_nbEntries=(SELECT COUNT(e1.id) FROM ' . $this->prefix . 'entry e1 WHERE e1.id_feed=f.id),' + . 'f.cache_nbUnreads=(SELECT COUNT(e2.id) FROM ' . $this->prefix . 'entry e2 WHERE e2.id_feed=f.id AND e2.is_read=0),' + . 'lastUpdate=?, error=? ' + . 'WHERE f.id=?'; - if ($stm && $stm->execute ($values)) { - return true; - } else { - $info = $stm->errorInfo(); - Minz_Log::record ('SQL error : ' . $info[2], Minz_Log::ERROR); - return false; - } - } - - public function isInError ($id) { - $sql = 'UPDATE ' . $this->prefix . 'feed SET error=1 WHERE id=?'; $stm = $this->bd->prepare ($sql); $values = array ( - $id + time (), + $inError, + $id, ); if ($stm && $stm->execute ($values)) { - return true; + return $stm->rowCount(); } else { $info = $stm->errorInfo(); Minz_Log::record ('SQL error : ' . $info[2], Minz_Log::ERROR); @@ -424,7 +413,7 @@ class FeedDAO extends Model_pdo { ); if ($stm && $stm->execute ($values)) { - return true; + return $stm->rowCount(); } else { $info = $stm->errorInfo(); Minz_Log::record ('SQL error : ' . $info[2], Minz_Log::ERROR); @@ -439,7 +428,7 @@ class FeedDAO extends Model_pdo { $values = array ($id); if ($stm && $stm->execute ($values)) { - return true; + return $stm->rowCount(); } else { $info = $stm->errorInfo(); Minz_Log::record ('SQL error : ' . $info[2], Minz_Log::ERROR); @@ -453,7 +442,7 @@ class FeedDAO extends Model_pdo { $values = array ($id); if ($stm && $stm->execute ($values)) { - return true; + return $stm->rowCount(); } else { $info = $stm->errorInfo(); Minz_Log::record ('SQL error : ' . $info[2], Minz_Log::ERROR); @@ -521,15 +510,6 @@ class FeedDAO extends Model_pdo { return HelperFeed::daoToFeed ($stm->fetchAll (PDO::FETCH_ASSOC)); } - public function count () { //Is this used? - $sql = 'SELECT COUNT(*) AS count FROM ' . $this->prefix . 'feed'; - $stm = $this->bd->prepare ($sql); - $stm->execute (); - $res = $stm->fetchAll (PDO::FETCH_ASSOC); - - return $res[0]['count']; - } - public function countEntries ($id) { $sql = 'SELECT COUNT(*) AS count FROM ' . $this->prefix . 'entry WHERE id_feed=?'; $stm = $this->bd->prepare ($sql); @@ -539,8 +519,8 @@ class FeedDAO extends Model_pdo { return $res[0]['count']; } - public function countNotRead ($id) { //Is this used? - $sql = 'SELECT COUNT(*) AS count FROM ' . $this->prefix . 'entry WHERE is_read=0 AND id_feed=?'; + public function countNotRead ($id) { + $sql = 'SELECT COUNT(*) AS count FROM ' . $this->prefix . 'entry WHERE id_feed=? AND is_read=0'; $stm = $this->bd->prepare ($sql); $values = array ($id); $stm->execute ($values); @@ -548,6 +528,28 @@ class FeedDAO extends Model_pdo { return $res[0]['count']; } + public function updateCachedValues () { //For one single feed, call updateLastUpdate($id) + $sql = 'UPDATE freshrss_feed f ' + . 'INNER JOIN (' + . 'SELECT e.id_feed, ' + . 'COUNT(CASE WHEN e.is_read = 0 THEN 1 END) AS nbUnreads, ' + . 'COUNT(e.id) AS nbEntries ' + . 'FROM freshrss_entry e ' + . 'GROUP BY e.id_feed' + . ') x ON x.id_feed=f.id ' + . 'SET f.cache_nbEntries=x.nbEntries, f.cache_nbUnreads=x.nbUnreads'; + $stm = $this->bd->prepare ($sql); + + $values = array ($feed_id); + + if ($stm && $stm->execute ($values)) { + return $stm->rowCount(); + } else { + $info = $stm->errorInfo(); + Minz_Log::record ('SQL error : ' . $info[2], Minz_Log::ERROR); + return false; + } + } } class HelperFeed { @@ -577,12 +579,8 @@ class HelperFeed { $myFeed->_httpAuth (isset($dao['httpAuth']) ? base64_decode ($dao['httpAuth']) : ''); $myFeed->_error ($dao['error']); $myFeed->_keepHistory (isset($dao['keep_history']) ? $dao['keep_history'] : ''); - if (isset ($dao['nbNotRead'])) { - $myFeed->_nbNotRead ($dao['nbNotRead']); - } - if (isset ($dao['nbEntries'])) { - $myFeed->_nbEntries ($dao['nbEntries']); - } + $myFeed->_nbNotRead ($dao['cache_nbUnreads']); + $myFeed->_nbEntries ($dao['cache_nbEntries']); if (isset ($dao['id'])) { $myFeed->_id ($dao['id']); } diff --git a/lib/minz/dao/Model_pdo.php b/lib/minz/dao/Model_pdo.php index a91a4fa00..dd75153be 100755 --- a/lib/minz/dao/Model_pdo.php +++ b/lib/minz/dao/Model_pdo.php @@ -71,6 +71,16 @@ class Model_pdo { ); } } + + public function beginTransaction() { + $this->bd->beginTransaction(); + } + public function commit() { + $this->bd->commit(); + } + public function rollBack() { + $this->bd->rollBack(); + } } class FreshPDO extends PDO { diff --git a/public/install.php b/public/install.php index 457605224..47856b6a7 100644 --- a/public/install.php +++ b/public/install.php @@ -15,7 +15,7 @@ define ('SQL_REQ_CAT', 'CREATE TABLE IF NOT EXISTS `%scategory` ( `name` varchar(255) NOT NULL, `color` char(7) NOT NULL, PRIMARY KEY (`id`), - INDEX (`name`) + INDEX (`name`) //v0.7 );'); define ('SQL_REQ_FEED', 'CREATE TABLE IF NOT EXISTS `%sfeed` ( @@ -26,16 +26,18 @@ define ('SQL_REQ_FEED', 'CREATE TABLE IF NOT EXISTS `%sfeed` ( `website` varchar(255) NOT NULL, `description` text NOT NULL, `lastUpdate` int(11) NOT NULL, - `priority` tinyint(2) NOT NULL DEFAULT \'10\', + `priority` tinyint(2) NOT NULL DEFAULT 10, `pathEntries` varchar(511) DEFAULT NULL, `httpAuth` varchar(511) DEFAULT NULL, - `error` boolean NOT NULL DEFAULT \'0\', - `keep_history` boolean NOT NULL DEFAULT \'0\', + `error` boolean NOT NULL DEFAULT 0, + `keep_history` boolean NOT NULL DEFAULT 0, + `cache_nbEntries` int NOT NULL DEFAULT 0, //v0.7 + `cache_nbUnreads` int NOT NULL DEFAULT 0, //v0.7 PRIMARY KEY (`id`), FOREIGN KEY (`category`) REFERENCES %scategory(id) ON DELETE SET NULL ON UPDATE CASCADE, - INDEX (`name`), - INDEX (`priority`), - INDEX (`keep_history`) + INDEX (`name`), //v0.7 + INDEX (`priority`), //v0.7 + INDEX (`keep_history`) //v0.7 );'); define ('SQL_REQ_ENTRY', 'CREATE TABLE IF NOT EXISTS `%sentry` ( @@ -46,14 +48,14 @@ define ('SQL_REQ_ENTRY', 'CREATE TABLE IF NOT EXISTS `%sentry` ( `content` text NOT NULL, `link` varchar(1023) NOT NULL, `date` int(11) NOT NULL, - `is_read` boolean NOT NULL DEFAULT \'0\', - `is_favorite` boolean NOT NULL DEFAULT \'0\', + `is_read` boolean NOT NULL DEFAULT 0, + `is_favorite` boolean NOT NULL DEFAULT 0, `id_feed` char(6) NOT NULL, `tags` varchar(1023) NOT NULL, PRIMARY KEY (`id`), FOREIGN KEY (`id_feed`) REFERENCES %sfeed(id) ON DELETE CASCADE ON UPDATE CASCADE, - INDEX (`is_favorite`), - INDEX (`is_read`) + INDEX (`is_favorite`), //v0.7 + INDEX (`is_read`) //v0.7 );'); -- cgit v1.2.3 From ac857ca7431f8d1ac562e085c8ef672bd10de9c8 Mon Sep 17 00:00:00 2001 From: Alexandre Alapetite Date: Sun, 17 Nov 2013 00:40:49 +0100 Subject: Correction html_only_entity_decode author --- app/models/Feed.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'app/models') diff --git a/app/models/Feed.php b/app/models/Feed.php index ae3a9af83..628b63df9 100644 --- a/app/models/Feed.php +++ b/app/models/Feed.php @@ -274,7 +274,7 @@ class Feed extends Model { foreach ($feed->get_items () as $item) { $title = self::html_only_entity_decode (strip_tags ($item->get_title ())); - $author = self::html_only_entity_decode ($item->get_author ()); + $author = $item->get_author (); $link = $item->get_permalink (); $date = strtotime ($item->get_date ()); @@ -304,7 +304,7 @@ class Feed extends Model { $this->id (), $item->get_id (), !is_null ($title) ? $title : '', - !is_null ($author) ? $author->name : '', + !is_null ($author) ? self::html_only_entity_decode ($author->name) : '', !is_null ($content) ? $content : '', !is_null ($link) ? $link : '', $date ? $date : time () -- cgit v1.2.3 From a532a023633ac692bd573d4ec29b7871e8e4c19f Mon Sep 17 00:00:00 2001 From: Alexandre Alapetite Date: Sun, 17 Nov 2013 01:11:32 +0100 Subject: Useragent MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Exemple : `FreshRSS/0.7 (Linux; http://marienfressinaud.github.io/FreshRSS/) SimplePie/1.3.1` Voir https://github.com/marienfressinaud/FreshRSS/issues/271 pour le numéro de version --- app/models/Feed.php | 1 + 1 file changed, 1 insertion(+) (limited to 'app/models') diff --git a/app/models/Feed.php b/app/models/Feed.php index 628b63df9..d76d4cd0e 100644 --- a/app/models/Feed.php +++ b/app/models/Feed.php @@ -194,6 +194,7 @@ class Feed extends Model { ); } else { $feed = new SimplePie (); + $feed->set_useragent(Translate::t ('freshrss') . '/' . '0.7' . ' (' . PHP_OS . '; http://marienfressinaud.github.io/FreshRSS/) ' . SIMPLEPIE_NAME . '/' . SIMPLEPIE_VERSION); $url = str_replace ('&', '&', $this->url); if ($this->httpAuth != '') { $url = preg_replace ('#((.+)://)(.+)#', '${1}' . $this->httpAuth . '@${3}', $url); -- cgit v1.2.3 From b8c4afadf4bff7ac282ac5933eedccb1c666d873 Mon Sep 17 00:00:00 2001 From: Alexandre Alapetite Date: Sun, 17 Nov 2013 01:35:06 +0100 Subject: Nouveau fichier constants.php MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit En particulier pour stocker le numéro de version de FreshRSS utilisé entre autres par https://github.com/marienfressinaud/FreshRSS/issues/174 et centraliser les constantes de chemins Implémente https://github.com/marienfressinaud/FreshRSS/issues/271 --- actualize_script.php | 8 +------- app/models/Feed.php | 2 +- app/views/index/about.phtml | 2 +- constants.php | 10 ++++++++++ public/index.php | 7 +------ 5 files changed, 14 insertions(+), 15 deletions(-) create mode 100644 constants.php (limited to 'app/models') diff --git a/actualize_script.php b/actualize_script.php index 45b2938cb..65f9360a0 100755 --- a/actualize_script.php +++ b/actualize_script.php @@ -1,11 +1,5 @@ set_useragent(Translate::t ('freshrss') . '/' . '0.7' . ' (' . PHP_OS . '; http://marienfressinaud.github.io/FreshRSS/) ' . SIMPLEPIE_NAME . '/' . SIMPLEPIE_VERSION); + $feed->set_useragent(Translate::t ('freshrss') . '/' . FRESHRSS_VERSION . ' (' . PHP_OS . '; ' . FRESHRSS_WEBSITE . ') ' . SIMPLEPIE_NAME . '/' . SIMPLEPIE_VERSION); $url = str_replace ('&', '&', $this->url); if ($this->httpAuth != '') { $url = preg_replace ('#((.+)://)(.+)#', '${1}' . $this->httpAuth . '@${3}', $url); diff --git a/app/views/index/about.phtml b/app/views/index/about.phtml index ca1254053..fa799154b 100644 --- a/app/views/index/about.phtml +++ b/app/views/index/about.phtml @@ -5,7 +5,7 @@
      -
      http://marienfressinaud.github.io/FreshRSS/
      +
      Marien Fressinaud -
      diff --git a/constants.php b/constants.php new file mode 100644 index 000000000..260f01986 --- /dev/null +++ b/constants.php @@ -0,0 +1,10 @@ + Date: Sun, 17 Nov 2013 02:56:30 +0100 Subject: Réorganisation des fichiers utilisateur MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Implémente https://github.com/marienfressinaud/FreshRSS/issues/248 --- README.md | 2 +- actualize_script.php | 2 +- app/configuration/.gitignore | 1 - app/controllers/entryController.php | 2 +- app/controllers/indexController.php | 4 +-- app/i18n/en.php | 2 +- app/i18n/fr.php | 2 +- app/layout/layout.phtml | 2 +- app/models/Feed.php | 2 +- app/models/RSSConfiguration.php | 2 +- cache/.gitignore | 1 - constants.php | 13 ++++++---- data/.gitignore | 6 +++++ lib/lib_rss.php | 6 ++--- lib/minz/Configuration.php | 10 ++++---- lib/minz/dao/Model_pdo.php | 6 ++--- log/.gitignore | 1 - public/data/.gitignore | 4 --- public/data/grey.gif | Bin 56 -> 0 bytes public/index.php | 8 +++--- public/install.php | 47 ++++++++++++++++++------------------ public/themes/icons/grey.gif | Bin 0 -> 56 bytes 22 files changed, 61 insertions(+), 62 deletions(-) delete mode 100644 app/configuration/.gitignore delete mode 100644 cache/.gitignore create mode 100644 data/.gitignore delete mode 100644 log/.gitignore delete mode 100644 public/data/.gitignore delete mode 100644 public/data/grey.gif create mode 100644 public/themes/icons/grey.gif (limited to 'app/models') diff --git a/README.md b/README.md index 00df693e6..fb0b9e61e 100644 --- a/README.md +++ b/README.md @@ -36,7 +36,7 @@ Privilégiez pour cela des demandes sur GitHub # Sécurité et conseils 1. Pour une meilleure sécurité, faites en sorte que seul le répertoire `./public` soit accessible par le navigateur. Faites pointer un sous-domaine sur le répertoire `./public` par exemple -2. Dans tous les cas, assurez-vous que `./app/configuration/application.ini` ne puisse pas être téléchargé ! +2. Dans tous les cas, assurez-vous que `./data/application.ini` ne puisse pas être téléchargé ! 3. Le fichier de log peut être utile à lire si vous avez des soucis 4. Le fichier `./public/index.php` défini les chemins d'accès aux répertoires clés de l'application. Si vous les bougez, tout se passe ici. 5. Vous pouvez ajouter une tâche CRON sur le script d'actualisation des flux. Il s'agit d'un script PHP à exécuter avec la commande `php`. Par exemple, pour exécuter le script toutes les heures : diff --git a/actualize_script.php b/actualize_script.php index 65f9360a0..bc1d108bd 100755 --- a/actualize_script.php +++ b/actualize_script.php @@ -20,4 +20,4 @@ $front_controller = new App_FrontController (); $front_controller->init (); Session::_param('mail', true); // permet de se passer de la phase de connexion $front_controller->run (); -touch(PUBLIC_PATH . '/data/touch.txt'); +touch(DATA_PATH . '/touch.txt'); diff --git a/app/configuration/.gitignore b/app/configuration/.gitignore deleted file mode 100644 index 72e8ffc0d..000000000 --- a/app/configuration/.gitignore +++ /dev/null @@ -1 +0,0 @@ -* diff --git a/app/controllers/entryController.php b/app/controllers/entryController.php index 4d2d92c1b..8016d719f 100755 --- a/app/controllers/entryController.php +++ b/app/controllers/entryController.php @@ -84,7 +84,7 @@ class entryController extends ActionController { $entryDAO = new EntryDAO(); $entryDAO->optimizeTable(); - touch(PUBLIC_PATH . '/data/touch.txt'); + touch(DATA_PATH . '/touch.txt'); $notif = array ( 'type' => 'good', diff --git a/app/controllers/indexController.php b/app/controllers/indexController.php index 224d6fb9e..392abd3e1 100755 --- a/app/controllers/indexController.php +++ b/app/controllers/indexController.php @@ -277,7 +277,7 @@ class indexController extends ActionController { $res = json_decode ($result, true); if ($res['status'] == 'okay' && $res['email'] == $this->view->conf->mailLogin ()) { Session::_param ('mail', $res['email']); - touch(PUBLIC_PATH . '/data/touch.txt'); + touch(DATA_PATH . '/touch.txt'); } else { $res = array (); $res['status'] = 'failure'; @@ -290,6 +290,6 @@ class indexController extends ActionController { public function logoutAction () { $this->view->_useLayout (false); Session::_param ('mail'); - touch(PUBLIC_PATH . '/data/touch.txt'); + touch(DATA_PATH . '/touch.txt'); } } diff --git a/app/i18n/en.php b/app/i18n/en.php index eca1dd6d5..8243756bd 100644 --- a/app/i18n/en.php +++ b/app/i18n/en.php @@ -283,7 +283,7 @@ return array ( 'dom_is_nok' => 'You haven’t the necessary to browse the DOM (php-xml package can be useful)', 'cache_is_ok' => 'Permissions on cache directory are good', 'log_is_ok' => 'Permissions on logs directory are good', - 'conf_is_ok' => 'Permissions on configuration directory are good', + 'favicons_is_ok' => 'Permissions on favicons directory are good', 'data_is_ok' => 'Permissions on data directory are good', 'file_is_nok' => 'Check permissions on %s directory. HTTP server must have rights to write into', 'fix_errors_before' => 'Fix errors before skip to the next step.', diff --git a/app/i18n/fr.php b/app/i18n/fr.php index 2cddd4083..8040a6a44 100644 --- a/app/i18n/fr.php +++ b/app/i18n/fr.php @@ -283,7 +283,7 @@ return array ( 'dom_is_nok' => 'Vous ne disposez pas du nécessaire pour parcourir le DOM (voir du côté du paquet php-xml ?)', 'cache_is_ok' => 'Les droits sur le répertoire de cache sont bons', 'log_is_ok' => 'Les droits sur le répertoire des logs sont bons', - 'conf_is_ok' => 'Les droits sur le répertoire de configuration sont bons', + 'favicons_is_ok' => 'Les droits sur le répertoire des favicons sont bons', 'data_is_ok' => 'Les droits sur le répertoire de data sont bons', 'file_is_nok' => 'Veuillez vérifier les droits sur le répertoire %s. Le serveur HTTP doit être capable d’écrire dedans', 'fix_errors_before' => 'Veuillez corriger les erreurs avant de passer à l’étape suivante.', diff --git a/app/layout/layout.phtml b/app/layout/layout.phtml index ba4df4834..4232b714d 100644 --- a/app/layout/layout.phtml +++ b/app/layout/layout.phtml @@ -32,7 +32,7 @@ notification)) { - touch(PUBLIC_PATH . '/data/touch.txt', time() + 1); + touch(DATA_PATH . '/touch.txt', time() + 1); ?>
      notification['content']; ?> diff --git a/app/models/Feed.php b/app/models/Feed.php index 2618d023f..adc8e1677 100644 --- a/app/models/Feed.php +++ b/app/models/Feed.php @@ -100,7 +100,7 @@ class Feed extends Model { return $this->nbNotRead; } public function favicon () { - $file = '/data/favicons/' . $this->id () . '.ico'; + $file = '/favicons/' . $this->id () . '.ico'; $favicon_url = Url::display ($file); if (!file_exists (PUBLIC_PATH . $file)) { diff --git a/app/models/RSSConfiguration.php b/app/models/RSSConfiguration.php index e79fd933b..f8379a625 100755 --- a/app/models/RSSConfiguration.php +++ b/app/models/RSSConfiguration.php @@ -348,7 +348,7 @@ class RSSConfigurationDAO extends Model_array { public $bottomline_link = 'yes'; public function __construct () { - parent::__construct (PUBLIC_PATH . '/data/Configuration.array.php'); + parent::__construct (DATA_PATH . '/Configuration.array.php'); // TODO : simplifier ce code, une boucle for() devrait suffir ! if (isset ($this->array['language'])) { diff --git a/cache/.gitignore b/cache/.gitignore deleted file mode 100644 index 72e8ffc0d..000000000 --- a/cache/.gitignore +++ /dev/null @@ -1 +0,0 @@ -* diff --git a/constants.php b/constants.php index 260f01986..05d60b242 100644 --- a/constants.php +++ b/constants.php @@ -3,8 +3,11 @@ define('FRESHRSS_VERSION', '0.7-dev'); define('FRESHRSS_WEBSITE', 'http://marienfressinaud.github.io/FreshRSS/'); // Constantes de chemins -define ('PUBLIC_PATH', realpath (dirname (__FILE__) . '/public')); -define ('LIB_PATH', realpath (dirname (__FILE__) . '/lib')); -define ('APP_PATH', realpath (dirname (__FILE__) . '/app')); -define ('LOG_PATH', realpath (dirname (__FILE__) . '/log')); -define ('CACHE_PATH', realpath (dirname (__FILE__) . '/cache')); +define ('FRESHRSS_PATH', realpath (dirname (__FILE__))); +define ('PUBLIC_PATH', FRESHRSS_PATH . '/public'); +define ('DATA_PATH', FRESHRSS_PATH . '/data'); +define ('LIB_PATH', FRESHRSS_PATH . '/lib'); +define ('APP_PATH', FRESHRSS_PATH . '/app'); + +define ('LOG_PATH', DATA_PATH . '/log'); +define ('CACHE_PATH', DATA_PATH . '/cache'); diff --git a/data/.gitignore b/data/.gitignore new file mode 100644 index 000000000..0e407f099 --- /dev/null +++ b/data/.gitignore @@ -0,0 +1,6 @@ +cache +log +application.ini +Configuration.array.php +*.sqlite +touch.txt \ No newline at end of file diff --git a/lib/lib_rss.php b/lib/lib_rss.php index e4518ab4b..33f8641e1 100644 --- a/lib/lib_rss.php +++ b/lib/lib_rss.php @@ -168,9 +168,9 @@ function get_content_by_parsing ($url, $path) { /* Télécharge le favicon d'un site, le place sur le serveur et retourne l'URL */ function dowload_favicon ($website, $id) { $url = 'http://g.etfv.co/' . $website; - $favicons_dir = PUBLIC_PATH . '/data/favicons'; + $favicons_dir = PUBLIC_PATH . '/favicons'; $dest = $favicons_dir . '/' . $id . '.ico'; - $favicon_url = '/data/favicons/' . $id . '.ico'; + $favicon_url = '/favicons/' . $id . '.ico'; if (!is_dir ($favicons_dir)) { if (!mkdir ($favicons_dir, 0755, true)) { @@ -211,7 +211,7 @@ function dowload_favicon ($website, $id) { function lazyimg($content) { return preg_replace( '/]+?)src=[\'"]([^"\']+)[\'"]([^>]*)>/i', - '', + '', $content ); } diff --git a/lib/minz/Configuration.php b/lib/minz/Configuration.php index b296ec378..bdd6af0fb 100755 --- a/lib/minz/Configuration.php +++ b/lib/minz/Configuration.php @@ -8,7 +8,7 @@ * La classe Configuration permet de gérer la configuration de l'application */ class Configuration { - const CONF_PATH_NAME = '/configuration/application.ini'; + const CONF_PATH_NAME = '/application.ini'; /** * VERSION est la version actuelle de MINZ @@ -111,21 +111,21 @@ class Configuration { * @exception BadConfigurationException si CONF_PATH_NAME mal formaté */ private static function parseFile () { - if (!file_exists (APP_PATH . self::CONF_PATH_NAME)) { + if (!file_exists (DATA_PATH . self::CONF_PATH_NAME)) { throw new FileNotExistException ( - APP_PATH . self::CONF_PATH_NAME, + DATA_PATH . self::CONF_PATH_NAME, MinzException::ERROR ); } $ini_array = parse_ini_file ( - APP_PATH . self::CONF_PATH_NAME, + DATA_PATH . self::CONF_PATH_NAME, true ); if (!$ini_array) { throw new PermissionDeniedException ( - APP_PATH . self::CONF_PATH_NAME, + DATA_PATH . self::CONF_PATH_NAME, MinzException::ERROR ); } diff --git a/lib/minz/dao/Model_pdo.php b/lib/minz/dao/Model_pdo.php index dd75153be..beeb65ea8 100755 --- a/lib/minz/dao/Model_pdo.php +++ b/lib/minz/dao/Model_pdo.php @@ -49,9 +49,7 @@ class Model_pdo { PDO::MYSQL_ATTR_INIT_COMMAND => 'SET NAMES utf8' ); } elseif($type == 'sqlite') { - $string = $type - . ':/' . PUBLIC_PATH - . '/data/' . $db['base'] . '.sqlite'; //TODO: DEBUG UTF-8 http://www.siteduzero.com/forum/sujet/sqlite-connexion-utf-8-18797 + $string = $type . ':/' . DATA_PATH . $db['base'] . '.sqlite'; //TODO: DEBUG UTF-8 http://www.siteduzero.com/forum/sujet/sqlite-connexion-utf-8-18797 } $this->bd = new FreshPDO ( @@ -86,7 +84,7 @@ class Model_pdo { class FreshPDO extends PDO { private static function check($statement) { if (preg_match('/^(?:UPDATE|INSERT|DELETE)/i', $statement)) { - touch(PUBLIC_PATH . '/data/touch.txt'); + touch(DATA_PATH . '/touch.txt'); } } diff --git a/log/.gitignore b/log/.gitignore deleted file mode 100644 index 72e8ffc0d..000000000 --- a/log/.gitignore +++ /dev/null @@ -1 +0,0 @@ -* diff --git a/public/data/.gitignore b/public/data/.gitignore deleted file mode 100644 index 8498bc17e..000000000 --- a/public/data/.gitignore +++ /dev/null @@ -1,4 +0,0 @@ -favicons -Configuration.array.php -*.sqlite -touch.txt \ No newline at end of file diff --git a/public/data/grey.gif b/public/data/grey.gif deleted file mode 100644 index c7212bc1f..000000000 Binary files a/public/data/grey.gif and /dev/null differ diff --git a/public/index.php b/public/index.php index bda585592..d989bc11d 100755 --- a/public/index.php +++ b/public/index.php @@ -20,16 +20,16 @@ require('../constants.php'); -if (file_exists (PUBLIC_PATH . '/install.php')) { +if (file_exists ('install.php')) { include ('install.php'); } else { session_cache_limiter(''); require (LIB_PATH . '/http-conditional.php'); $dateLastModification = max( - @filemtime(PUBLIC_PATH . '/data/touch.txt'), + @filemtime(DATA_PATH . '/touch.txt'), @filemtime(LOG_PATH . '/application.log'), - @filemtime(PUBLIC_PATH . '/data/Configuration.array.php'), - @filemtime(APP_PATH . '/configuration/application.ini') + @filemtime(DATA_PATH . '/Configuration.array.php'), + @filemtime(DATA_PATH . '/application.ini') ); if (httpConditional($dateLastModification, 0, 0, false, false, true)) { exit(); //No need to send anything diff --git a/public/install.php b/public/install.php index 4c0da0ce5..085a412ff 100644 --- a/public/install.php +++ b/public/install.php @@ -166,7 +166,7 @@ function saveStep2 () { . small_hash ($_SESSION['base_url'] . $_SESSION['sel']); } - $file_data = PUBLIC_PATH . '/data/Configuration.array.php'; + $file_data = DATA_PATH . '/Configuration.array.php'; $f = fopen ($file_data, 'w'); writeLine ($f, ' $php ? 'ok' : 'ko', @@ -276,11 +276,11 @@ function checkStep1 () { 'curl' => $curl ? 'ok' : 'ko', 'pdo-mysql' => $pdo ? 'ok' : 'ko', 'dom' => $dom ? 'ok' : 'ko', + 'data' => $data ? 'ok' : 'ko', 'cache' => $cache ? 'ok' : 'ko', 'log' => $log ? 'ok' : 'ko', - 'configuration' => $conf ? 'ok' : 'ko', - 'data' => $data ? 'ok' : 'ko', - 'all' => $php && $minz && $curl && $pdo && $dom && $cache && $log && $conf && $data ? 'ok' : 'ko' + 'favicons' => $favicons ? 'ok' : 'ko', + 'all' => $php && $minz && $curl && $pdo && $dom && $data && $cache && $log && $favicons ? 'ok' : 'ko' ); } function checkStep2 () { @@ -289,7 +289,7 @@ function checkStep2 () { isset ($_SESSION['title']) && isset ($_SESSION['old_entries']) && isset ($_SESSION['mail_login']); - $data = file_exists (PUBLIC_PATH . '/data/Configuration.array.php'); + $data = file_exists (DATA_PATH . '/Configuration.array.php'); return array ( 'conf' => $conf ? 'ok' : 'ko', @@ -298,7 +298,7 @@ function checkStep2 () { ); } function checkStep3 () { - $conf = file_exists (APP_PATH . '/configuration/application.ini'); + $conf = file_exists (DATA_PATH . '/application.ini'); $bd = isset ($_SESSION['bd_type']) && isset ($_SESSION['bd_host']) && isset ($_SESSION['bd_user']) && @@ -337,8 +337,7 @@ function checkBD () { // on écrase la précédente connexion en sélectionnant la nouvelle BDD $str = 'mysql:host=' . $_SESSION['bd_host'] . ';dbname=' . $_SESSION['bd_name']; } elseif($_SESSION['bd_type'] == 'sqlite') { - $str = 'sqlite:' . PUBLIC_PATH - . '/data/' . $_SESSION['bd_name'] . '.sqlite'; + $str = 'sqlite:' . DATA_PATH . $_SESSION['bd_name'] . '.sqlite'; } $c = new PDO ($str, @@ -370,8 +369,8 @@ function checkBD () { $error = true; } - if ($error && file_exists (APP_PATH . '/configuration/application.ini')) { - unlink (APP_PATH . '/configuration/application.ini'); + if ($error && file_exists (DATA_PATH . '/application.ini')) { + unlink (DATA_PATH . '/application.ini'); } return !$error; @@ -448,28 +447,28 @@ function printStep1 () {

      + +

      + +

      + +

      -

      +

      -

      - - - -

      - -

      +

      - -

      + +

      -

      +

      diff --git a/public/themes/icons/grey.gif b/public/themes/icons/grey.gif new file mode 100644 index 000000000..c7212bc1f Binary files /dev/null and b/public/themes/icons/grey.gif differ -- cgit v1.2.3 From 9ec13c6c32ad0f8fb50f100e6ae127abe1535ccc Mon Sep 17 00:00:00 2001 From: Alexandre Alapetite Date: Sun, 17 Nov 2013 15:24:30 +0100 Subject: Début de multi-utilisateurs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Préparation de https://github.com/marienfressinaud/FreshRSS/issues/126 Suite de https://github.com/marienfressinaud/FreshRSS/issues/248 Nécessite un script de mise à jour https://github.com/marienfressinaud/FreshRSS/issues/255 Install.php n'est pas encore testé https://github.com/marienfressinaud/FreshRSS/issues/273 --- app/i18n/en.php | 3 ++- app/i18n/fr.php | 3 ++- app/models/Entry.php | 8 ++++---- app/models/Feed.php | 4 ++-- app/models/RSSConfiguration.php | 3 ++- data/.gitignore | 2 +- lib/minz/Configuration.php | 12 ++++++++++++ lib/minz/dao/Model_pdo.php | 3 ++- public/index.php | 1 - public/install.php | 20 +++++++++++++++----- 10 files changed, 42 insertions(+), 17 deletions(-) (limited to 'app/models') diff --git a/app/i18n/en.php b/app/i18n/en.php index 8243756bd..e5aec3bc1 100644 --- a/app/i18n/en.php +++ b/app/i18n/en.php @@ -151,7 +151,8 @@ return array ( 'language' => 'Language', 'delete_articles_every' => 'Remove articles every', 'month' => 'months', - 'persona_connection_email' => 'Login mail address (use Persona)', + 'default_user' => 'Username of the default user (maximum 16 alphanumeric characters)', + 'persona_connection_email' => 'Login mail address (use Mozilla Persona)', 'allow_anonymous' => 'Allow anonymous reading', 'auth_token' => 'Authentication token', 'explain_token' => 'Allows to access RSS output without authentication.
      %s?token=%s', diff --git a/app/i18n/fr.php b/app/i18n/fr.php index 8040a6a44..8bffd5287 100644 --- a/app/i18n/fr.php +++ b/app/i18n/fr.php @@ -151,7 +151,8 @@ return array ( 'language' => 'Langue', 'delete_articles_every' => 'Supprimer les articles tous les', 'month' => 'mois', - 'persona_connection_email' => 'Adresse courriel de connexion (utilise Persona)', + 'default_user' => 'Nom de l’utilisateur par défaut (16 caractères alphanumériques maximum)', + 'persona_connection_email' => 'Adresse courriel de connexion (utilise Mozilla Persona)', 'allow_anonymous' => 'Autoriser la lecture anonyme', 'auth_token' => 'Jeton d’identification', 'explain_token' => 'Permet d’accéder à la sortie RSS sans besoin de s’authentifier.
      %s?output=rss&token=%s', diff --git a/app/models/Entry.php b/app/models/Entry.php index 8b817cc14..c4856af8b 100755 --- a/app/models/Entry.php +++ b/app/models/Entry.php @@ -311,11 +311,11 @@ class EntryDAO extends Model_pdo { $affected = $stm->rowCount(); if ($affected > 0) { - $sql = 'UPDATE freshrss_feed f ' + $sql = 'UPDATE ' . $this->prefix . 'feed f ' . 'LEFT OUTER JOIN (' . 'SELECT e.id_feed, ' . 'COUNT(*) AS nbUnreads ' - . 'FROM freshrss_entry e ' + . 'FROM ' . $this->prefix . 'entry e ' . 'WHERE e.is_read = 0 ' . 'GROUP BY e.id_feed' . ') x ON x.id_feed=f.id ' @@ -364,11 +364,11 @@ class EntryDAO extends Model_pdo { $affected = $stm->rowCount(); if ($affected > 0) { - $sql = 'UPDATE freshrss_feed f ' + $sql = 'UPDATE ' . $this->prefix . 'feed f ' . 'LEFT OUTER JOIN (' . 'SELECT e.id_feed, ' . 'COUNT(*) AS nbUnreads ' - . 'FROM freshrss_entry e ' + . 'FROM ' . $this->prefix . 'entry e ' . 'WHERE e.is_read = 0 ' . 'GROUP BY e.id_feed' . ') x ON x.id_feed=f.id ' diff --git a/app/models/Feed.php b/app/models/Feed.php index adc8e1677..549603664 100644 --- a/app/models/Feed.php +++ b/app/models/Feed.php @@ -530,12 +530,12 @@ class FeedDAO extends Model_pdo { return $res[0]['count']; } public function updateCachedValues () { //For one single feed, call updateLastUpdate($id) - $sql = 'UPDATE freshrss_feed f ' + $sql = 'UPDATE ' . $this->prefix . 'feed f ' . 'INNER JOIN (' . 'SELECT e.id_feed, ' . 'COUNT(CASE WHEN e.is_read = 0 THEN 1 END) AS nbUnreads, ' . 'COUNT(e.id) AS nbEntries ' - . 'FROM freshrss_entry e ' + . 'FROM ' . $this->prefix . 'entry e ' . 'GROUP BY e.id_feed' . ') x ON x.id_feed=f.id ' . 'SET f.cache_nbEntries=x.nbEntries, f.cache_nbUnreads=x.nbUnreads'; diff --git a/app/models/RSSConfiguration.php b/app/models/RSSConfiguration.php index f8379a625..9604bee1d 100755 --- a/app/models/RSSConfiguration.php +++ b/app/models/RSSConfiguration.php @@ -348,7 +348,7 @@ class RSSConfigurationDAO extends Model_array { public $bottomline_link = 'yes'; public function __construct () { - parent::__construct (DATA_PATH . '/Configuration.array.php'); + parent::__construct (DATA_PATH . Configuration::currentUser () . '_user.php'); // TODO : simplifier ce code, une boucle for() devrait suffir ! if (isset ($this->array['language'])) { @@ -441,5 +441,6 @@ class RSSConfigurationDAO extends Model_array { } $this->writeFile($this->array); + touch(DATA_PATH . '/touch.txt'); } } diff --git a/data/.gitignore b/data/.gitignore index 0e407f099..9c60990ac 100644 --- a/data/.gitignore +++ b/data/.gitignore @@ -1,6 +1,6 @@ cache log application.ini -Configuration.array.php +*_user.php *.sqlite touch.txt \ No newline at end of file diff --git a/lib/minz/Configuration.php b/lib/minz/Configuration.php index bdd6af0fb..5be2ea63d 100755 --- a/lib/minz/Configuration.php +++ b/lib/minz/Configuration.php @@ -50,6 +50,8 @@ class Configuration { private static $language = 'en'; private static $cache_enabled = false; private static $delay_cache = 3600; + private static $default_user = ''; + private static $current_user = ''; private static $db = array ( 'host' => false, @@ -88,6 +90,12 @@ class Configuration { public static function dataBase () { return self::$db; } + public static function defaultUser () { + return self::$default_user; + } + public static function currentUser () { + return self::$current_user; + } /** * Initialise les variables de configuration @@ -193,6 +201,10 @@ class Configuration { if (isset ($general['delay_cache'])) { self::$delay_cache = $general['delay_cache']; } + if (isset ($general['default_user'])) { + self::$default_user = $general['default_user']; + self::$current_user = self::$default_user; + } // Base de données $db = false; diff --git a/lib/minz/dao/Model_pdo.php b/lib/minz/dao/Model_pdo.php index beeb65ea8..810e69847 100755 --- a/lib/minz/dao/Model_pdo.php +++ b/lib/minz/dao/Model_pdo.php @@ -60,7 +60,8 @@ class Model_pdo { ); self::$sharedBd = $this->bd; - $this->prefix = $db['prefix']; + $userPrefix = Configuration::currentUser (); + $this->prefix = $db['prefix'] . (empty($userPrefix) ? '' : ($userPrefix . '_')); self::$sharedPrefix = $this->prefix; } catch (Exception $e) { throw new PDOConnectionException ( diff --git a/public/index.php b/public/index.php index d989bc11d..108853fb7 100755 --- a/public/index.php +++ b/public/index.php @@ -28,7 +28,6 @@ if (file_exists ('install.php')) { $dateLastModification = max( @filemtime(DATA_PATH . '/touch.txt'), @filemtime(LOG_PATH . '/application.log'), - @filemtime(DATA_PATH . '/Configuration.array.php'), @filemtime(DATA_PATH . '/application.ini') ); if (httpConditional($dateLastModification, 0, 0, false, false, true)) { diff --git a/public/install.php b/public/install.php index 085a412ff..42f2d2651 100644 --- a/public/install.php +++ b/public/install.php @@ -159,6 +159,7 @@ function saveStep2 () { $_SESSION['old_entries'] = 3; } $_SESSION['mail_login'] = addslashes ($_POST['mail_login']); + $_SESSION['default_user'] = substr(0, 16, preg_replace ('/[^a-zA-Z0-9]/', '', $_POST['default_user'])); $token = ''; if ($_SESSION['mail_login']) { @@ -166,7 +167,7 @@ function saveStep2 () { . small_hash ($_SESSION['base_url'] . $_SESSION['sel']); } - $file_data = DATA_PATH . '/Configuration.array.php'; + $file_data = DATA_PATH . '/' . $_SESSION['default_user'] . '_user.php'; $f = fopen ($file_data, 'w'); writeLine ($f, ' $conf ? 'ok' : 'ko', @@ -512,6 +515,13 @@ function printStep2 () {
      +
      + +
      + +
      +
      +
      @@ -586,14 +596,14 @@ function printStep3 () {
      - +
      - +
      -- cgit v1.2.3 From 40a0829483e4ec15e5af2b5f539a7ff249ffbd06 Mon Sep 17 00:00:00 2001 From: Alexandre Alapetite Date: Sun, 17 Nov 2013 15:31:25 +0100 Subject: Bug chemin dans RSSConfigurationDAO --- app/models/RSSConfiguration.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'app/models') diff --git a/app/models/RSSConfiguration.php b/app/models/RSSConfiguration.php index 9604bee1d..f31985de1 100755 --- a/app/models/RSSConfiguration.php +++ b/app/models/RSSConfiguration.php @@ -348,7 +348,7 @@ class RSSConfigurationDAO extends Model_array { public $bottomline_link = 'yes'; public function __construct () { - parent::__construct (DATA_PATH . Configuration::currentUser () . '_user.php'); + parent::__construct (DATA_PATH . '/' . Configuration::currentUser () . '_user.php'); // TODO : simplifier ce code, une boucle for() devrait suffir ! if (isset ($this->array['language'])) { -- cgit v1.2.3 From 86bede27704e55ab21dc019dadf0b34c2a66c098 Mon Sep 17 00:00:00 2001 From: Alexandre Alapetite Date: Sun, 17 Nov 2013 18:12:15 +0100 Subject: Corrections install.php MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Première version fonctionnelle https://github.com/marienfressinaud/FreshRSS/issues/273 --- app/models/Entry.php | 8 ++++++-- public/install.php | 9 +++++---- 2 files changed, 11 insertions(+), 6 deletions(-) (limited to 'app/models') diff --git a/app/models/Entry.php b/app/models/Entry.php index c4856af8b..052e5abff 100755 --- a/app/models/Entry.php +++ b/app/models/Entry.php @@ -578,7 +578,9 @@ class EntryDAO extends Model_pdo { $stm = $this->bd->prepare ($sql); $stm->execute (); $res = $stm->fetchAll (PDO::FETCH_COLUMN, 0); - return array('total' => $res[0], 'unread' => $res[1], 'read' => $res[0] - $res[1]); + $all = empty($res[0]) ? 0 : $res[0]; + $unread = empty($res[1]) ? 0 : $res[1]; + return array('all' => $all, 'unread' => $unread, 'read' => $all - $unread); } public function count ($minPriority = null) { $sql = 'SELECT COUNT(e.id) AS count FROM ' . $this->prefix . 'entry e INNER JOIN ' . $this->prefix . 'feed f ON e.id_feed = f.id'; @@ -607,7 +609,9 @@ class EntryDAO extends Model_pdo { $stm = $this->bd->prepare ($sql); $stm->execute (); $res = $stm->fetchAll (PDO::FETCH_COLUMN, 0); - return array('all' => $res[0], 'unread' => $res[1], 'read' => $res[0] - $res[1]); + $all = empty($res[0]) ? 0 : $res[0]; + $unread = empty($res[1]) ? 0 : $res[1]; + return array('all' => $all, 'unread' => $unread, 'read' => $all - $unread); } public function optimizeTable() { diff --git a/public/install.php b/public/install.php index ba8fe3675..c35d52f29 100644 --- a/public/install.php +++ b/public/install.php @@ -159,7 +159,7 @@ function saveStep2 () { $_SESSION['old_entries'] = 3; } $_SESSION['mail_login'] = addslashes ($_POST['mail_login']); - $_SESSION['default_user'] = substr(0, 16, preg_replace ('/[^a-zA-Z0-9]/', '', $_POST['default_user'])); + $_SESSION['default_user'] = substr(preg_replace ('/[^a-zA-Z0-9]/', '', $_POST['default_user']), 0, 16); $token = ''; if ($_SESSION['mail_login']) { @@ -293,7 +293,8 @@ function checkStep2 () { isset ($_SESSION['old_entries']) && isset ($_SESSION['mail_login']) && isset ($_SESSION['default_user']); - $data = file_exists (DATA_PATH . '/' . $_SESSION['default_user'] . '_user.php'); + $defaultUser = empty($_POST['default_user']) ? $_SESSION['default_user'] : $_POST['default_user']; + $data = file_exists (DATA_PATH . '/' . $defaultUser . '_user.php'); return array ( 'conf' => $conf ? 'ok' : 'ko', @@ -561,11 +562,11 @@ function printStep3 () {
      -- cgit v1.2.3 From ff1803e61aea1fbec607cf11acebf4106f5bbdc9 Mon Sep 17 00:00:00 2001 From: Alexis Degrugillier Date: Sun, 17 Nov 2013 15:23:48 -0500 Subject: Ajout d'un raccourci pour refermer un article. https://github.com/marienfressinaud/FreshRSS/issues/256 --- app/controllers/configureController.php | 2 +- app/i18n/en.php | 1 + app/i18n/fr.php | 1 + app/models/RSSConfiguration.php | 3 ++- app/views/configure/shortcut.phtml | 7 +++++++ app/views/helpers/javascript_vars.phtml | 3 ++- public/scripts/main.js | 7 +++++++ 7 files changed, 21 insertions(+), 3 deletions(-) (limited to 'app/models') diff --git a/app/controllers/configureController.php b/app/controllers/configureController.php index 2856bb89f..51b0ebaca 100755 --- a/app/controllers/configureController.php +++ b/app/controllers/configureController.php @@ -337,7 +337,7 @@ class configureController extends ActionController { 'f10', 'f11', 'f12'); $this->view->list_keys = $list_keys; $list_names = array ('mark_read', 'mark_favorite', 'go_website', 'next_entry', - 'prev_entry', 'next_page', 'prev_page'); + 'prev_entry', 'next_page', 'prev_page', 'collapse_entry'); if (Request::isPost ()) { $shortcuts = Request::param ('shortcuts'); diff --git a/app/i18n/en.php b/app/i18n/en.php index e5aec3bc1..fd312520f 100644 --- a/app/i18n/en.php +++ b/app/i18n/en.php @@ -119,6 +119,7 @@ return array ( 'shift_for_first' => '+ shift to skip to the first article of page', 'next_page' => 'Skip to the next page', 'previous_page' => 'Skip to the previous page', + 'collapse_article' => 'Collapse current article', 'file_to_import' => 'File to import', 'import' => 'Import', diff --git a/app/i18n/fr.php b/app/i18n/fr.php index 8bffd5287..8223c1de5 100644 --- a/app/i18n/fr.php +++ b/app/i18n/fr.php @@ -119,6 +119,7 @@ return array ( 'shift_for_first' => '+ shift pour passer au premier article de la page', 'next_page' => 'Passer à la page suivante', 'previous_page' => 'Passer à la page précédente', + 'collapse_article' => 'Refermer l\'article courant', 'file_to_import' => 'Fichier à importer', 'import' => 'Importer', diff --git a/app/models/RSSConfiguration.php b/app/models/RSSConfiguration.php index f31985de1..8a8acafcb 100755 --- a/app/models/RSSConfiguration.php +++ b/app/models/RSSConfiguration.php @@ -323,7 +323,8 @@ class RSSConfigurationDAO extends Model_array { 'mark_favorite' => 'f', 'go_website' => 'space', 'next_entry' => 'j', - 'prev_entry' => 'k' + 'prev_entry' => 'k', + 'collapse_entry' => 'c', ); public $mail_login = ''; public $mark_when = array ( diff --git a/app/views/configure/shortcut.phtml b/app/views/configure/shortcut.phtml index 01e66adb4..37aa3accc 100644 --- a/app/views/configure/shortcut.phtml +++ b/app/views/configure/shortcut.phtml @@ -54,6 +54,13 @@
      +
      + +
      + +
      +
      +
      diff --git a/app/views/helpers/javascript_vars.phtml b/app/views/helpers/javascript_vars.phtml index 58cb3c5ac..e9deaf71c 100644 --- a/app/views/helpers/javascript_vars.phtml +++ b/app/views/helpers/javascript_vars.phtml @@ -16,7 +16,8 @@ 'mark_favorite:"', $s['mark_favorite'], '",', 'go_website:"', $s['go_website'], '",', 'prev_entry:"', $s['prev_entry'], '",', - 'next_entry:"', $s['next_entry'], '"', + 'next_entry:"', $s['next_entry'], '",', + 'collapse_entry:"', $s['collapse_entry'], '"', "},\n"; $mail = Session::param ('mail', 'null'); diff --git a/public/scripts/main.js b/public/scripts/main.js index 2794e2913..b798f918c 100644 --- a/public/scripts/main.js +++ b/public/scripts/main.js @@ -214,6 +214,10 @@ function next_entry() { } } +function collapse_entry() { + $(".flux.active").removeClass("active"); +} + function inMarkViewport(flux, box_to_follow, relative_follow) { var top = flux.position().top; if (relative_follow) { @@ -319,6 +323,9 @@ function init_shortcuts() { }, { 'disable_in_input': true }); + shortcut.add(shortcuts.collapse_entry, function () { + collapse_entry(); + }); // Touches de navigation shortcut.add(shortcuts.prev_entry, prev_entry, { -- cgit v1.2.3 From 082246d13f524aa646d5aedf49ae7e3b6c621d6c Mon Sep 17 00:00:00 2001 From: Alexandre Alapetite Date: Mon, 18 Nov 2013 09:53:25 +0100 Subject: Raccourcis : tolère l'ajout de nouveaux MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Tolère l'ajout de nouveaux inconnus des versions précédents de FreshRSS, et plus robuste en cas de mauvais fichier de configuration utilisateur. --- app/models/RSSConfiguration.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'app/models') diff --git a/app/models/RSSConfiguration.php b/app/models/RSSConfiguration.php index 8a8acafcb..741dd84a1 100755 --- a/app/models/RSSConfiguration.php +++ b/app/models/RSSConfiguration.php @@ -380,7 +380,7 @@ class RSSConfigurationDAO extends Model_array { $this->old_entries = $this->array['old_entries']; } if (isset ($this->array['shortcuts'])) { - $this->shortcuts = $this->array['shortcuts']; + $this->shortcuts = array_merge ($this->shortcuts, $this->array['shortcuts']); } if (isset ($this->array['mail_login'])) { $this->mail_login = $this->array['mail_login']; -- cgit v1.2.3 From e2d4f1a7214591a47a46272a7a62e320eea029ce Mon Sep 17 00:00:00 2001 From: Alexandre Alapetite Date: Mon, 18 Nov 2013 23:04:43 +0100 Subject: SQL : identifiant entier automatique pour les catégories et les flux MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Implémentation de https://github.com/marienfressinaud/FreshRSS/issues/262 La catégorie par défaut à le numéro 1. Les numéros de catégories et de flux sont automatiques (1, 2, 3...) L'installeur semble marcher. --- app/controllers/feedController.php | 2 +- app/layout/aside_feed.phtml | 2 +- app/models/Category.php | 17 ++++++----------- app/models/Entry.php | 9 ++++++--- app/models/Feed.php | 13 ++++--------- lib/SimplePie/SimplePie/Parser.php | 3 +-- public/install.php | 8 ++++---- 7 files changed, 23 insertions(+), 31 deletions(-) (limited to 'app/models') diff --git a/app/controllers/feedController.php b/app/controllers/feedController.php index 5c905e6da..73d13063d 100755 --- a/app/controllers/feedController.php +++ b/app/controllers/feedController.php @@ -175,7 +175,7 @@ class feedController extends ActionController { $entries = $feed->entries (); //For this feed, check last n entry IDs already in database - $existingIds = array_fill_keys ($entryDAO->listLastIdsByFeed ($feed->id (), count($entries) + 2), 1); + $existingIds = array_fill_keys ($entryDAO->listLastIdsByFeed ($feed->id (), count($entries) + 10), 1); // ajout des articles en masse sans se soucier des erreurs // On ne vérifie pas que l'article n'est pas déjà en BDD diff --git a/app/layout/aside_feed.phtml b/app/layout/aside_feed.phtml index 49767740b..f737d1e31 100644 --- a/app/layout/aside_feed.phtml +++ b/app/layout/aside_feed.phtml @@ -16,7 +16,7 @@
    • - +
    • @@ -53,7 +53,7 @@ @@ -73,7 +73,7 @@ if (login_is_conf ($this->conf) && !is_logged ()) { ?>
      - +
      diff --git a/app/layout/layout.phtml b/app/layout/layout.phtml index eb0f8b484..ac0031355 100644 --- a/app/layout/layout.phtml +++ b/app/layout/layout.phtml @@ -36,7 +36,7 @@ ?>
      notification['content']; ?> - +
      diff --git a/app/layout/nav_entries.phtml b/app/layout/nav_entries.phtml index 306c1536d..0811fe8fa 100644 --- a/app/layout/nav_entries.phtml +++ b/app/layout/nav_entries.phtml @@ -1,5 +1,5 @@ \ No newline at end of file diff --git a/app/layout/nav_menu.phtml b/app/layout/nav_menu.phtml index 38a5a14a3..890f80f64 100644 --- a/app/layout/nav_menu.phtml +++ b/app/layout/nav_menu.phtml @@ -1,8 +1,8 @@
      diff --git a/app/views/configure/feed.phtml b/app/views/configure/feed.phtml index 8fecec36f..1fb0368de 100644 --- a/app/views/configure/feed.phtml +++ b/app/views/configure/feed.phtml @@ -29,21 +29,21 @@
      - +
      - +
      @@ -85,7 +85,7 @@
      - +
      @@ -94,7 +94,7 @@
      - +
      diff --git a/app/views/entry/bookmark.phtml b/app/views/entry/bookmark.phtml index 8ce39629b..d175e10ed 100755 --- a/app/views/entry/bookmark.phtml +++ b/app/views/entry/bookmark.phtml @@ -12,4 +12,4 @@ $url = Url::display (array ( 'params' => Request::params (), )); -echo json_encode (array ('url' => str_ireplace ('&', '&', $url), 'icon' => icon(Request::param ('is_favorite') ? 'non-starred' : 'starred'))); +echo json_encode (array ('url' => str_ireplace ('&', '&', $url), 'icon' => RSSThemes::icon(Request::param ('is_favorite') ? 'non-starred' : 'starred'))); diff --git a/app/views/entry/read.phtml b/app/views/entry/read.phtml index 224651e58..e909d47f4 100755 --- a/app/views/entry/read.phtml +++ b/app/views/entry/read.phtml @@ -12,4 +12,4 @@ $url = Url::display (array ( 'params' => Request::params (), )); -echo json_encode (array ('url' => str_ireplace ('&', '&', $url), 'icon' => icon(Request::param ('is_read') ? 'unread' : 'read'))); +echo json_encode (array ('url' => str_ireplace ('&', '&', $url), 'icon' => RSSThemes::icon(Request::param ('is_read') ? 'unread' : 'read'))); diff --git a/app/views/helpers/view/global_view.phtml b/app/views/helpers/view/global_view.phtml index f34d368f9..ac17d608a 100644 --- a/app/views/helpers/view/global_view.phtml +++ b/app/views/helpers/view/global_view.phtml @@ -32,5 +32,5 @@
      conf->displayPosts () === 'no' ? ' class="hide_posts"' : ''; ?>> - +
      \ No newline at end of file diff --git a/app/views/helpers/view/normal_view.phtml b/app/views/helpers/view/normal_view.phtml index 033eed5b1..31bd19036 100644 --- a/app/views/helpers/view/normal_view.phtml +++ b/app/views/helpers/view/normal_view.phtml @@ -42,13 +42,13 @@ if (isset ($this->entryPaginator) && !$this->entryPaginator->isEmpty ()) { if ($this->conf->toplineRead ()) { ?>
    • isRead () ? 'read' : 'unread'); ?>isRead () ? 'read' : 'unread'); ?>
    • conf->toplineFavorite ()) { ?>
    • isFavorite () ? 'starred' : 'non-starred'); ?>isFavorite () ? 'starred' : 'non-starred'); ?>
    • entryPaginator) && !$this->entryPaginator->isEmpty ()) {
    • ✇ name(); ?>
    • title (); ?>
    • conf->toplineDate ()) { ?>
    • date (); ?> 
    • - conf->toplineLink ()) { ?> + conf->toplineLink ()) { ?>
    @@ -79,13 +79,13 @@ if (isset ($this->entryPaginator) && !$this->entryPaginator->isEmpty ()) { if ($this->conf->bottomlineRead ()) { ?>
  • isRead () ? 'read' : 'unread'); ?>isRead () ? 'read' : 'unread'); ?>
  • conf->bottomlineFavorite ()) { ?>
  • isFavorite () ? 'starred' : 'non-starred'); ?>isFavorite () ? 'starred' : 'non-starred'); ?>
  • @@ -97,7 +97,7 @@ if (isset ($this->entryPaginator) && !$this->entryPaginator->isEmpty ()) { ?> diff --git a/lib/lib_rss.php b/lib/lib_rss.php index 8e58e4048..3c03f4281 100644 --- a/lib/lib_rss.php +++ b/lib/lib_rss.php @@ -230,33 +230,3 @@ function lazyimg($content) { $content ); } - -function icon($name) { - static $alts = array( - 'add' => '✚', - 'all' => '☰', - 'bookmark' => '★', - 'category' => '☷', - 'category-white' => '☷', - 'close' => '❌', - 'configure' => '⚙', - 'down' => '▽', - 'favorite' => '★', - 'help' => 'ⓘ', - 'link' => '↗', - 'login' => '🔒', - 'logout' => '🔓', - 'next' => '⏩', - 'non-starred' => '☆', - 'prev' => '⏪', - 'read' => '☑', - 'unread' => '☐', - 'refresh' => '🔃', //↻ - 'search' => '🔍', - 'share' => '♺', - 'starred' => '★', - 'tag' => '⚐', - 'up' => '△', - ); - return '' . $alts[$name] . ''; -} -- cgit v1.2.3 From eae19e13634593d919811f527eff9e1efd34c03b Mon Sep 17 00:00:00 2001 From: Alexandre Alapetite Date: Sun, 24 Nov 2013 23:05:06 +0100 Subject: Refactorise RSSThemes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Évite de charger les informations de tous les thèmes lorsque ce n'est pas nécessaire (c.à.d. en dehors de la page de configuration). * Permettra de choisir des icônes différentes selon les thèmes sans nécessairement passer par une CSS. * Contribue à https://github.com/marienfressinaud/FreshRSS/issues/284 --- app/App_FrontController.php | 1 - app/models/RSSConfiguration.php | 1 + app/models/RSSThemes.php | 69 +++++++++++++++++++++++------------------ 3 files changed, 40 insertions(+), 31 deletions(-) (limited to 'app/models') diff --git a/app/App_FrontController.php b/app/App_FrontController.php index b1e6787dc..1f270c0b1 100644 --- a/app/App_FrontController.php +++ b/app/App_FrontController.php @@ -11,7 +11,6 @@ class App_FrontController extends FrontController { $this->loadModels (); Session::init (); - RSSThemes::init (); Translate::init (); $this->loadParamsView (); diff --git a/app/models/RSSConfiguration.php b/app/models/RSSConfiguration.php index 741dd84a1..ef562bdcb 100755 --- a/app/models/RSSConfiguration.php +++ b/app/models/RSSConfiguration.php @@ -49,6 +49,7 @@ class RSSConfiguration extends Model { $this->_markWhen ($confDAO->mark_when); $this->_urlShaarli ($confDAO->url_shaarli); $this->_theme ($confDAO->theme); + RSSThemes::setThemeId ($confDAO->theme); $this->_anonAccess ($confDAO->anon_access); $this->_token ($confDAO->token); $this->_autoLoadMore ($confDAO->auto_load_more); diff --git a/app/models/RSSThemes.php b/app/models/RSSThemes.php index 54420048b..6e4ddbf6d 100644 --- a/app/models/RSSThemes.php +++ b/app/models/RSSThemes.php @@ -1,48 +1,50 @@ '⚐', 'up' => '△', ); - $alt = isset($alts[$name]) ? $alts[$name] : '?'; + if (!isset($alts[$name])) { + return ''; + } + + $url = $name . '.svg'; + $url = isset(self::$themeIcons[$url]) ? (self::$themeIconsUrl . $url) : + (self::$defaultIconsUrl . $url); + return '' . $alts[$name] . ''; - //return '' . $alts[$name] . ''; + //return '' . $alts[$name] . ''; } } -- cgit v1.2.3 From ab26cb6ed8904bb873e0ae4b874aed3f3a0fdb48 Mon Sep 17 00:00:00 2001 From: Alexandre Alapetite Date: Mon, 25 Nov 2013 00:40:35 +0100 Subject: Accessibilité sans images (expérimentation) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Expérimentation : utilisation de vraies images à la place des icônes générées en CSS. Permet de fournir un texte alternatif affiché en cas de non-chargement de l'image (par choix ou problème réseau par exemple). Meilleure sémantique (plutôt que le tag i détourné). Implémente https://github.com/marienfressinaud/FreshRSS/issues/284 Il est toujours possible de changer d'icônes selon les thèmes grâce à RSSThemes.php --- app/models/RSSThemes.php | 4 +- public/scripts/main.js | 10 +++- public/themes/default/freshrss.css | 2 +- public/themes/default/global.css | 83 ---------------------------------- public/themes/flat-design/freshrss.css | 2 +- public/themes/flat-design/global.css | 77 ------------------------------- 6 files changed, 13 insertions(+), 165 deletions(-) (limited to 'app/models') diff --git a/app/models/RSSThemes.php b/app/models/RSSThemes.php index 6e4ddbf6d..3fd0b2ea1 100644 --- a/app/models/RSSThemes.php +++ b/app/models/RSSThemes.php @@ -82,7 +82,7 @@ class RSSThemes extends Model { $url = isset(self::$themeIcons[$url]) ? (self::$themeIconsUrl . $url) : (self::$defaultIconsUrl . $url); - return '' . $alts[$name] . ''; - //return '' . $alts[$name] . ''; + //return '' . $alts[$name] . ''; + return '' . $alts[$name] . ''; } } diff --git a/public/scripts/main.js b/public/scripts/main.js index e21483f28..6d8389a44 100644 --- a/public/scripts/main.js +++ b/public/scripts/main.js @@ -286,7 +286,15 @@ function init_column_categories() { return; } $('#aside_flux').on('click', '.category>a.dropdown-toggle', function () { - $(this).children().toggleClass("i_down").toggleClass("i_up").text($(this).hasClass("i_up") ? "△" : "▽"); + $(this).children().each(function() { + if (this.alt === '▽') { + this.src = this.src.replace('/icons/down.', '/icons/up.'); + this.alt = '△'; + } else { + this.src = this.src.replace('/icons/up.', '/icons/down.'); + this.alt = '▽'; + } + }); $(this).parent().next(".feeds").slideToggle(); return false; }); diff --git a/public/themes/default/freshrss.css b/public/themes/default/freshrss.css index 78f76dd83..7d30c1806 100644 --- a/public/themes/default/freshrss.css +++ b/public/themes/default/freshrss.css @@ -18,6 +18,7 @@ } .logo { display: inline-block; + font-size: 48px; height: 32px; width: 32px; padding: 10px; @@ -253,7 +254,6 @@ .item.manage { width: 40px; white-space: nowrap; - font-size: 0px; text-align: center; } .flux_header .item.website { diff --git a/public/themes/default/global.css b/public/themes/default/global.css index b5cae66db..2004a1936 100644 --- a/public/themes/default/global.css +++ b/public/themes/default/global.css @@ -480,92 +480,9 @@ input, select, textarea { /* ICÔNES */ .icon { - font-size: 0; display: inline-block; width: 16px; height: 16px; vertical-align: middle; line-height: 16px; - background: center center no-repeat; } - .i_refresh { - background-image: url("../icons/refresh.svg"); - } - .i_bookmark { - background-image: url("../icons/starred.svg"); - } - .i_not_bookmark { - background-image: url("../icons/unstarred.svg"); - } - .i_read { - background-image: url("../icons/read.svg"); - } - .i_unread { - background-image: url("../icons/unread.svg"); - } - .i_all { - background-image: url("../icons/all.svg"); - } - .i_close { - background-image: url("../icons/close.svg"); - } - .i_search { - background-image: url("../icons/search.svg"); - } - .i_configure { - background-image: url("../icons/configure.svg"); - } - .i_login { - background-image: url("../icons/login.svg"); - } - .i_logout { - background-image: url("../icons/logout.svg"); - } - .i_add { - background-image: url("../icons/add.svg"); - } - .i_link { - background-image: url("../icons/link.svg"); - } - .i_down { - background-image: url("../icons/down.svg"); - } - .i_up { - background-image: url("../icons/up.svg"); - } - .i_next { - background-image: url("../icons/next.svg"); - } - .i_prev { - background-image: url("../icons/prev.svg"); - } - .i_help { - background-image: url("../icons/help.svg"); - } - .i_note { - background-image: url("../icons/note.svg"); - } - .i_note_empty { - background-image: url("../icons/note_empty.svg"); - } - .i_category { - background-image: url("../icons/category.svg"); - } - .i_category-white { - background-image: url("../icons/category-white.svg"); - } - .i_rss { - background-image: url("../icons/rss.svg"); - } - .i_share { - background-image: url("../icons/share.svg"); - } - .i_starred { - background-image: url("../icons/starred.svg"); - } - .i_non-starred { - background-image: url("../icons/non-starred.svg"); - } - .i_tag { - background-image: url("../icons/tag.svg"); - } diff --git a/public/themes/flat-design/freshrss.css b/public/themes/flat-design/freshrss.css index 602845ef1..04c61085b 100644 --- a/public/themes/flat-design/freshrss.css +++ b/public/themes/flat-design/freshrss.css @@ -21,6 +21,7 @@ body { } .logo { display: inline-block; + font-size: 48px; height: 32px; width: 32px; padding: 10px; @@ -236,7 +237,6 @@ body { .item.manage { width: 40px; white-space: nowrap; - font-size: 0px; text-align: center; } .flux_header .item.website { diff --git a/public/themes/flat-design/global.css b/public/themes/flat-design/global.css index 0c731f74b..c53ec863c 100644 --- a/public/themes/flat-design/global.css +++ b/public/themes/flat-design/global.css @@ -472,86 +472,9 @@ input, select, textarea { /* ICÔNES */ .icon { - font-size: 0; display: inline-block; width: 16px; height: 16px; vertical-align: middle; line-height: 16px; - background: center center no-repeat; } - .i_refresh { - background-image: url("icons/refresh.svg"); - } - .i_bookmark { - background-image: url("../icons/starred.svg"); - } - .i_not_bookmark { - background-image: url("../icons/unstarred.svg"); - } - .i_read { - background-image: url("../icons/read.svg"); - } - .i_unread { - background-image: url("../icons/unread.svg"); - } - .i_all { - background-image: url("icons/all.svg"); - } - .i_close { - background-image: url("icons/close.svg"); - } - .i_search { - background-image: url("icons/search.svg"); - } - .i_configure { - background-image: url("icons/configure.svg"); - } - .i_login { - background-image: url("../icons/login.svg"); - } - .i_logout { - background-image: url("../icons/logout.svg"); - } - .i_add { - background-image: url("icons/add.svg"); - } - .i_link { - background-image: url("../icons/link.svg"); - } - .i_down { - background-image: url("icons/down.svg"); - } - .i_up { - background-image: url("icons/up.svg"); - } - .i_next { - background-image: url("icons/next.svg"); - } - .i_prev { - background-image: url("icons/prev.svg"); - } - .i_help { - background-image: url("../icons/help.svg"); - } - .i_category { - background-image: url("../icons/category-white.svg"); - } - .i_category-white { - background-image: url("../icons/category-white.svg"); - } - .i_rss { - background-image: url("../icons/rss.svg"); - } - .i_share { - background-image: url("../icons/share.svg"); - } - .i_starred { - background-image: url("../icons/starred.svg"); - } - .i_non-starred { - background-image: url("../icons/non-starred.svg"); - } - .i_tag { - background-image: url("../icons/tag.svg"); - } -- cgit v1.2.3 From 03081fe9a21a3746ba3dac689f449b7ff3254f95 Mon Sep 17 00:00:00 2001 From: Alexandre Alapetite Date: Mon, 25 Nov 2013 17:59:07 +0100 Subject: Ajout du mode global pour icon() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Oublié dans https://github.com/marienfressinaud/FreshRSS/commit/eae19e13634593d919811f527eff9e1efd34c03b --- app/models/RSSThemes.php | 1 - app/views/helpers/javascript_vars.phtml | 4 ++++ public/scripts/global_view.js | 2 +- 3 files changed, 5 insertions(+), 2 deletions(-) (limited to 'app/models') diff --git a/app/models/RSSThemes.php b/app/models/RSSThemes.php index 3fd0b2ea1..7a6deaf3c 100644 --- a/app/models/RSSThemes.php +++ b/app/models/RSSThemes.php @@ -82,7 +82,6 @@ class RSSThemes extends Model { $url = isset(self::$themeIcons[$url]) ? (self::$themeIconsUrl . $url) : (self::$defaultIconsUrl . $url); - //return '' . $alts[$name] . ''; return '' . $alts[$name] . ''; } } diff --git a/app/views/helpers/javascript_vars.phtml b/app/views/helpers/javascript_vars.phtml index e9deaf71c..ddebfd876 100644 --- a/app/views/helpers/javascript_vars.phtml +++ b/app/views/helpers/javascript_vars.phtml @@ -20,6 +20,10 @@ 'collapse_entry:"', $s['collapse_entry'], '"', "},\n"; + if (Request::param ('output') === 'global') { + echo "iconClose='", RSSThemes::icon('close'), "',\n"; + } + $mail = Session::param ('mail', 'null'); if ($mail != 'null') { $mail = '"' . $mail . '"'; diff --git a/public/scripts/global_view.js b/public/scripts/global_view.js index 14fad9525..0cdcdd3fa 100644 --- a/public/scripts/global_view.js +++ b/public/scripts/global_view.js @@ -30,7 +30,7 @@ function load_panel(link) { function init_close_panel() { $("#panel .close").click(function () { - $("#panel").html(''); + $("#panel").html('' + window.iconClose + ''); init_close_panel(); $("#panel").slideToggle(); $("#overlay").fadeOut(); -- cgit v1.2.3 From 6130ba6157fc214579a0466ec122a8f085224415 Mon Sep 17 00:00:00 2001 From: Alexandre Alapetite Date: Tue, 26 Nov 2013 23:52:53 +0100 Subject: SQL : utilisation de (id_feed, guid) pour l'unicité MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Préparation avant https://github.com/marienfressinaud/FreshRSS/issues/202 --- app/controllers/feedController.php | 15 ++++++--------- app/models/Entry.php | 6 +++--- app/models/Feed.php | 2 +- 3 files changed, 10 insertions(+), 13 deletions(-) (limited to 'app/models') diff --git a/app/controllers/feedController.php b/app/controllers/feedController.php index 9ce38a03f..174cd9519 100755 --- a/app/controllers/feedController.php +++ b/app/controllers/feedController.php @@ -174,17 +174,14 @@ class feedController extends ActionController { $feed->load (); $entries = $feed->entries (); - //For this feed, check last n entry IDs already in database - $existingIds = array_fill_keys ($entryDAO->listLastIdsByFeed ($feed->id (), count($entries) + 10), 1); - - // ajout des articles en masse sans se soucier des erreurs - // On ne vérifie pas que l'article n'est pas déjà en BDD - // car demanderait plus de ressources - // La BDD refusera l'ajout de son côté car l'id doit être - // unique + //For this feed, check last n entry GUIDs already in database + $existingGuids = array_fill_keys ($entryDAO->listLastGuidsByFeed ($feed->id (), count($entries) + 10), 1); + + // On ne vérifie strictement que l'article n'est pas déjà en BDD + // La BDD refusera l'ajout car (id_feed, guid) doit être unique $feedDAO->beginTransaction (); foreach ($entries as $entry) { - if ((!isset ($existingIds[$entry->id ()])) && + if ((!isset ($existingGuids[$entry->guid ()])) && ($entry->date (true) >= $date_min || $feed->keepHistory ())) { $values = $entry->toArray (); diff --git a/app/models/Entry.php b/app/models/Entry.php index e2493e266..abf381a9b 100755 --- a/app/models/Entry.php +++ b/app/models/Entry.php @@ -565,9 +565,9 @@ class EntryDAO extends Model_pdo { 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 listLastIdsByFeed($id, $n) { - $sql = 'SELECT id FROM ' . $this->prefix . 'entry WHERE id_feed=? ORDER BY date DESC LIMIT ' . intval($n); + + public function listLastGuidsByFeed($id, $n) { + $sql = 'SELECT guid FROM ' . $this->prefix . 'entry WHERE id_feed=? ORDER BY date DESC LIMIT ' . intval($n); $stm = $this->bd->prepare ($sql); $values = array ($id); $stm->execute ($values); diff --git a/app/models/Feed.php b/app/models/Feed.php index 822f6e703..d1d85d838 100644 --- a/app/models/Feed.php +++ b/app/models/Feed.php @@ -191,7 +191,7 @@ class Feed extends Model { } else { $feed = new SimplePie (); $feed->set_useragent(Translate::t ('freshrss') . '/' . FRESHRSS_VERSION . ' (' . PHP_OS . '; ' . FRESHRSS_WEBSITE . ') ' . SIMPLEPIE_NAME . '/' . SIMPLEPIE_VERSION); - $url = str_replace ('&', '&', $this->url); + $url = htmlspecialchars_decode ($this->url, ENT_QUOTES); if ($this->httpAuth != '') { $url = preg_replace ('#((.+)://)(.+)#', '${1}' . $this->httpAuth . '@${3}', $url); } -- cgit v1.2.3 From 4355d8447f8e9073f4d96a35b280bad5ba793e32 Mon Sep 17 00:00:00 2001 From: Alexandre Alapetite Date: Wed, 27 Nov 2013 22:50:00 +0100 Subject: SQL : Passe e.id en bigint plutôt que char(6) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Contribue à https://github.com/marienfressinaud/FreshRSS/issues/202 e.id est généré à l'insertion par microtime(true). --- app/models/Entry.php | 12 ++++-------- public/install.php | 4 ++-- 2 files changed, 6 insertions(+), 10 deletions(-) (limited to 'app/models') diff --git a/app/models/Entry.php b/app/models/Entry.php index abf381a9b..c5ff6ab60 100755 --- a/app/models/Entry.php +++ b/app/models/Entry.php @@ -2,7 +2,7 @@ class Entry extends Model { - private $id = null; + private $id = 0; private $guid; private $title; private $author; @@ -29,11 +29,7 @@ class Entry extends Model { } public function id () { - if(is_null($this->id)) { - return small_hash ($this->guid . Configuration::selApplication ()); - } else { - return $this->id; - } + return $this->id; } public function guid () { return $this->guid; @@ -195,11 +191,11 @@ class Entry extends Model { class EntryDAO extends Model_pdo { public function addEntry ($valuesTmp) { - $sql = 'INSERT INTO ' . $this->prefix . 'entry(id, guid, title, author, content, link, date, is_read, is_favorite, id_feed, tags) VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)'; + $sql = 'INSERT INTO ' . $this->prefix . 'entry(id, guid, title, author, content, link, date, is_read, is_favorite, id_feed, tags) VALUES(CAST(? * 1000000 AS SIGNED INTEGER), ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)'; $stm = $this->bd->prepare ($sql); $values = array ( - $valuesTmp['id'], + microtime(true), substr($valuesTmp['guid'], 0, 760), substr($valuesTmp['title'], 0, 255), substr($valuesTmp['author'], 0, 255), diff --git a/public/install.php b/public/install.php index 7709bb350..252403196 100644 --- a/public/install.php +++ b/public/install.php @@ -44,7 +44,7 @@ define ('SQL_REQ_FEED', 'CREATE TABLE IF NOT EXISTS `%sfeed` ( ) DEFAULT CHARACTER SET utf8 COLLATE utf8_unicode_ci;'); define ('SQL_REQ_ENTRY', 'CREATE TABLE IF NOT EXISTS `%sentry` ( - `id` char(6) NOT NULL, + `id` bigint NOT NULL, -- v0.7 `guid` varchar(760) CHARACTER SET latin1 NOT NULL, -- Maximum for UNIQUE is 767B `title` varchar(255) NOT NULL, `author` varchar(255) NOT NULL, @@ -60,7 +60,7 @@ define ('SQL_REQ_ENTRY', 'CREATE TABLE IF NOT EXISTS `%sentry` ( UNIQUE KEY (`id_feed`,`guid`), -- v0.7 INDEX (`is_favorite`), -- v0.7 INDEX (`is_read`), -- v0.7 - INDEX (`date`) -- v0.7 //TODO: remove after https://github.com/marienfressinaud/FreshRSS/issues/202 + INDEX (`date`) -- v0.7 //Consider removing after https://github.com/marienfressinaud/FreshRSS/issues/202 ) DEFAULT CHARACTER SET utf8 COLLATE utf8_unicode_ci;'); -- cgit v1.2.3 From 7f6eb66405b4c4429fb7c22082a958646c6ef05c Mon Sep 17 00:00:00 2001 From: Alexandre Alapetite Date: Wed, 27 Nov 2013 23:49:51 +0100 Subject: Suite de e.id en bigint MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Contribue à https://github.com/marienfressinaud/FreshRSS/issues/202 --- app/models/Entry.php | 8 ++++++++ app/models/Feed.php | 2 +- 2 files changed, 9 insertions(+), 1 deletion(-) (limited to 'app/models') diff --git a/app/models/Entry.php b/app/models/Entry.php index c5ff6ab60..636e67e75 100755 --- a/app/models/Entry.php +++ b/app/models/Entry.php @@ -57,6 +57,14 @@ class Entry extends Model { return timestamptodate ($this->date); } } + public function dateAdded ($raw = false) { + $date = intval(substr($this->id, 0, -6)); + if ($raw) { + return $date; + } else { + return timestamptodate ($date); + } + } public function isRead () { return $this->is_read; } diff --git a/app/models/Feed.php b/app/models/Feed.php index d1d85d838..8927551d6 100644 --- a/app/models/Feed.php +++ b/app/models/Feed.php @@ -310,7 +310,7 @@ class Feed extends Model { // permet de récupérer le contenu des flux tronqués $entry->loadCompleteContent($this->pathEntries()); - $entries[$entry->id ()] = $entry; + $entries[] = $entry; } $this->entries = $entries; -- cgit v1.2.3 From ee2c1a8c7888ef16d76a0c03ff2040aaa8a11a94 Mon Sep 17 00:00:00 2001 From: Alexandre Alapetite Date: Thu, 28 Nov 2013 01:42:06 +0100 Subject: Classement par date d'ajout e.id (expérimentation) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Expérimentation : classement par date d'ajout dans la base plutôt que selon la date déclarée par le flux (qui est parfois fausse dans le passé, dans le futur, ou absente). Quelques conséquences : * Les flux avec des dates erronées ne sont plus un problème * Lorsqu'on fait "marquer tout comme lu", les articles arrivés pendant la lecture ne sont plus indûment marqués comme lus * Les articles ont tendance à être plus regroupés par flux lorsqu'on les affiche par catégorie * Si un utilisateur n'utilise pas de cron et n'utilise pas FreshRSS pendant plusieurs jours, lors du rafraîchissement, les nouveaux articles seront dans "Aujourd'hui" (à interpréter donc comme les articles reçus aujourd'hui, et non comme déclarés comme étant publiés aujourd'hui) * La pagination est plus efficace Termine l'implémentation de https://github.com/marienfressinaud/FreshRSS/issues/202 --- app/controllers/entryController.php | 8 +++--- app/controllers/feedController.php | 11 ++++++++ app/layout/nav_menu.phtml | 11 ++++---- app/models/Entry.php | 50 ++++++++++++++++++------------------- app/models/Feed.php | 10 -------- app/models/RSSPaginator.php | 4 +++ 6 files changed, 50 insertions(+), 44 deletions(-) (limited to 'app/models') diff --git a/app/controllers/entryController.php b/app/controllers/entryController.php index 8016d719f..fa34ad429 100755 --- a/app/controllers/entryController.php +++ b/app/controllers/entryController.php @@ -36,23 +36,23 @@ class entryController extends ActionController { $is_read = Request::param ('is_read'); $get = Request::param ('get'); $nextGet = Request::param ('nextGet', $get); - $dateMax = Request::param ('dateMax', 0); + $idMax = Request::param ('idMax', 0); $is_read = !!$is_read; $entryDAO = new EntryDAO (); if ($id == false) { if (!$get) { - $entryDAO->markReadEntries ($dateMax); + $entryDAO->markReadEntries ($idMax); } else { $typeGet = $get[0]; $get = substr ($get, 2); if ($typeGet == 'c') { - $entryDAO->markReadCat ($get, $dateMax); + $entryDAO->markReadCat ($get, $idMax); $this->params = array ('get' => $nextGet); } elseif ($typeGet == 'f') { - $entryDAO->markReadFeed ($get, $dateMax); + $entryDAO->markReadFeed ($get, $idMax); $this->params = array ('get' => $nextGet); } } diff --git a/app/controllers/feedController.php b/app/controllers/feedController.php index 8b3667668..cd252b086 100755 --- a/app/controllers/feedController.php +++ b/app/controllers/feedController.php @@ -20,6 +20,15 @@ class feedController extends ActionController { $this->catDAO->checkDefault (); } + private static function entryDateComparer($e1, $e2) { + $d1 = $e1->date(true); + $d2 = $e2->date(true); + if ($d1 === $d2) { + return 0; + } + return ($d1 < $d2) ? -1 : 1; + } + public function addAction () { if (Request::isPost ()) { $url = Request::param ('url_rss'); @@ -75,6 +84,7 @@ class feedController extends ActionController { } else { $entryDAO = new EntryDAO (); $entries = $feed->entries (); + usort($entries, 'self::entryDateComparer'); // on calcule la date des articles les plus anciens qu'on accepte $nb_month_old = $this->view->conf->oldEntries (); @@ -173,6 +183,7 @@ class feedController extends ActionController { try { $feed->load (); $entries = $feed->entries (); + usort($entries, 'self::entryDateComparer'); //For this feed, check last n entry GUIDs already in database $existingGuids = array_fill_keys ($entryDAO->listLastGuidsByFeed ($feed->id (), count($entries) + 10), 1); diff --git a/app/layout/nav_menu.phtml b/app/layout/nav_menu.phtml index 890f80f64..0b95b4b02 100644 --- a/app/layout/nav_menu.phtml +++ b/app/layout/nav_menu.phtml @@ -18,6 +18,8 @@ $string_mark = Translate::t ('mark_cat_read'); } $nextGet = $get; + $p = $this->entryPaginator->peek(); + $idMax = $p === null ? '0' : $p->id(); if (($this->conf->onread_jump_next () === 'yes') && (strlen ($get) > 2)) { $anotherUnreadId = ''; $foundCurrent = false; @@ -53,7 +55,7 @@ break; } } - $markReadUrl = _url ('entry', 'read', 'is_read', 1, 'get', $get, 'nextGet', $nextGet); + $markReadUrl = _url ('entry', 'read', 'is_read', 1, 'get', $get, 'nextGet', $nextGet, 'idMax', $idMax); Session::_param ('markReadUrl', $markReadUrl); ?> @@ -69,12 +71,11 @@
  • -
  • -
  • +
  • +
  • diff --git a/app/models/Entry.php b/app/models/Entry.php index 636e67e75..80e8d7b6e 100755 --- a/app/models/Entry.php +++ b/app/models/Entry.php @@ -140,17 +140,17 @@ class Entry extends Model { } public function isDay ($day) { - $date = getdate (); - $today = mktime (0, 0, 0, $date['mon'], $date['mday'], $date['year']); + $date = $this->dateAdded(true); + $today = strtotime('today'); $yesterday = $today - 86400; - if ($day == Days::TODAY && - $this->date >= $today && $this->date < $today + 86400) { + if ($day === Days::TODAY && + $date >= $today && $date < $today + 86400) { return true; - } elseif ($day == Days::YESTERDAY && - $this->date >= $yesterday && $this->date < $yesterday + 86400) { + } elseif ($day === Days::YESTERDAY && + $date >= $yesterday && $date < $yesterday + 86400) { return true; - } elseif ($day == Days::BEFORE_YESTERDAY && $this->date < $yesterday) { + } elseif ($day === Days::BEFORE_YESTERDAY && $date < $yesterday) { return true; } else { return false; @@ -287,8 +287,8 @@ class EntryDAO extends Model_pdo { return false; } } - public function markReadEntries ($dateMax = 0) { - if ($dateMax === 0) { + public function markReadEntries ($idMax = 0) { + if ($idMax === 0) { $sql = 'UPDATE ' . $this->prefix . 'entry e INNER JOIN ' . $this->prefix . 'feed f ON e.id_feed = f.id ' . 'SET e.is_read = 1, f.cache_nbUnreads=0 ' . 'WHERE e.is_read = 0 AND f.priority > 0'; @@ -305,8 +305,8 @@ class EntryDAO extends Model_pdo { $sql = 'UPDATE ' . $this->prefix . 'entry e INNER JOIN ' . $this->prefix . 'feed f ON e.id_feed = f.id ' . 'SET e.is_read = 1 ' - . 'WHERE e.is_read = 0 AND e.date < ? AND f.priority > 0'; - $values = array ($dateMax); + . 'WHERE e.is_read = 0 AND e.id <= ? AND f.priority > 0'; + $values = array ($idMax); $stm = $this->bd->prepare ($sql); if (!($stm && $stm->execute ($values))) { $info = $stm->errorInfo(); @@ -339,8 +339,8 @@ class EntryDAO extends Model_pdo { return $affected; } } - public function markReadCat ($id, $dateMax = 0) { - if ($dateMax === 0) { + public function markReadCat ($id, $idMax = 0) { + if ($idMax === 0) { $sql = 'UPDATE ' . $this->prefix . 'entry e INNER JOIN ' . $this->prefix . 'feed f ON e.id_feed = f.id ' . 'SET e.is_read = 1, f.cache_nbUnreads=0 ' . 'WHERE f.category = ? AND e.is_read = 0'; @@ -358,8 +358,8 @@ class EntryDAO extends Model_pdo { $sql = 'UPDATE ' . $this->prefix . 'entry e INNER JOIN ' . $this->prefix . 'feed f ON e.id_feed = f.id ' . 'SET e.is_read = 1 ' - . 'WHERE f.category = ? AND e.is_read = 0 AND e.date < ?'; - $values = array ($id, $dateMax); + . 'WHERE f.category = ? AND e.is_read = 0 AND e.id <= ?'; + $values = array ($id, $idMax); $stm = $this->bd->prepare ($sql); if (!($stm && $stm->execute ($values))) { $info = $stm->errorInfo(); @@ -394,8 +394,8 @@ class EntryDAO extends Model_pdo { return $affected; } } - public function markReadFeed ($id, $dateMax = 0) { - if ($dateMax === 0) { + public function markReadFeed ($id, $idMax = 0) { + if ($idMax === 0) { $sql = 'UPDATE ' . $this->prefix . 'entry e INNER JOIN ' . $this->prefix . 'feed f ON e.id_feed = f.id ' . 'SET e.is_read = 1, f.cache_nbUnreads=0 ' . 'WHERE f.id=? AND e.is_read = 0'; @@ -413,8 +413,8 @@ class EntryDAO extends Model_pdo { $sql = 'UPDATE ' . $this->prefix . 'entry e INNER JOIN ' . $this->prefix . 'feed f ON e.id_feed = f.id ' . 'SET e.is_read = 1 ' - . 'WHERE f.id=? AND e.is_read = 0 AND e.date < ?'; - $values = array ($id, $dateMax); + . 'WHERE f.id=? AND e.is_read = 0 AND e.id <= ?'; + $values = array ($id, $idMax); $stm = $this->bd->prepare ($sql); if (!($stm && $stm->execute ($values))) { $info = $stm->errorInfo(); @@ -471,11 +471,11 @@ class EntryDAO extends Model_pdo { }*/ public function cleanOldEntries ($date_min) { - $sql = 'DELETE e.* FROM ' . $this->prefix . 'entry e INNER JOIN ' . $this->prefix . 'feed f ON e.id_feed = f.id WHERE e.date <= ? AND e.is_favorite = 0 AND f.keep_history = 0'; + $sql = 'DELETE e.* FROM ' . $this->prefix . 'entry e INNER JOIN ' . $this->prefix . 'feed f ON e.id_feed = f.id WHERE e.id <= ? AND e.is_favorite = 0 AND f.keep_history = 0'; $stm = $this->bd->prepare ($sql); $values = array ( - $date_min + $date_min . '000000' ); if ($stm && $stm->execute ($values)) { @@ -531,8 +531,8 @@ class EntryDAO extends Model_pdo { } elseif ($state === 'read') { $where .= ' AND is_read = 1'; } - if (!empty($limitFromId)) { //TODO: Consider using LPAD(e.date, 11) //CONCAT is for cases when many entries have the same date - $where .= ' AND CONCAT(e.date, e.id) ' . ($order === 'low_to_high' ? '<=' : '>=') . ' (SELECT CONCAT(s.date, s.id) FROM ' . $this->prefix . 'entry s WHERE s.id = "' . $limitFromId . '")'; + if (!empty($limitFromId)) { + $where .= ' AND e.id ' . ($order === 'low_to_high' ? '<=' : '>=') . $limitFromId; } if ($order === 'low_to_high') { @@ -543,7 +543,7 @@ class EntryDAO extends Model_pdo { $sql = 'SELECT e.* FROM ' . $this->prefix . 'entry e' . ' INNER JOIN ' . $this->prefix . 'feed f ON e.id_feed = f.id' . $where - . ' ORDER BY e.date' . $order . ', e.id' . $order; + . ' ORDER BY e.id' . $order; if (empty($limitCount)) { $limitCount = 20000; //TODO: FIXME: Hack temporaire en attendant la recherche côté base-de-données @@ -571,7 +571,7 @@ class EntryDAO extends Model_pdo { } public function listLastGuidsByFeed($id, $n) { - $sql = 'SELECT guid FROM ' . $this->prefix . 'entry WHERE id_feed=? ORDER BY date DESC LIMIT ' . intval($n); + $sql = 'SELECT guid FROM ' . $this->prefix . 'entry WHERE id_feed=? ORDER BY id DESC LIMIT ' . intval($n); $stm = $this->bd->prepare ($sql); $values = array ($id); $stm->execute ($values); diff --git a/app/models/Feed.php b/app/models/Feed.php index 8927551d6..da1a029a8 100644 --- a/app/models/Feed.php +++ b/app/models/Feed.php @@ -256,16 +256,6 @@ class Feed extends Model { } } } - static function html_only_entity_decode($text) { - static $htmlEntitiesOnly = null; - if ($htmlEntitiesOnly === null) { - $htmlEntitiesOnly = array_flip(array_diff( - get_html_translation_table(HTML_ENTITIES, ENT_NOQUOTES, 'UTF-8'), //Decode HTML entities - get_html_translation_table(HTML_SPECIALCHARS, ENT_NOQUOTES, 'UTF-8') //Preserve XML entities - )); - } - return strtr($text, $htmlEntitiesOnly); - } private function loadEntries ($feed) { $entries = array (); diff --git a/app/models/RSSPaginator.php b/app/models/RSSPaginator.php index 86b4b5cac..60d2a06ac 100644 --- a/app/models/RSSPaginator.php +++ b/app/models/RSSPaginator.php @@ -23,6 +23,10 @@ class RSSPaginator { return $this->next; } + public function peek () { + return empty($this->items) ? null : $this->items[0]; + } + public function render ($view, $getteur) { $view = APP_PATH . '/views/helpers/'.$view; -- cgit v1.2.3 From dcd6f3ef16f7e698ef1aa8c5bdd5a1e2c85021c9 Mon Sep 17 00:00:00 2001 From: Alexandre Alapetite Date: Thu, 28 Nov 2013 10:05:58 +0100 Subject: e.id utilise la date déclarée pour les nouveaux flux MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Contribue à https://github.com/marienfressinaud/FreshRSS/issues/202 --- app/controllers/feedController.php | 3 +++ app/models/Entry.php | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) (limited to 'app/models') diff --git a/app/controllers/feedController.php b/app/controllers/feedController.php index cd252b086..2bbd5ab49 100755 --- a/app/controllers/feedController.php +++ b/app/controllers/feedController.php @@ -97,6 +97,7 @@ class feedController extends ActionController { if ($entry->date (true) >= $date_min || $feed->keepHistory ()) { $values = $entry->toArray (); + $values['id'] = min(time(), $entry->date (true)) . '.' . rand(0, 999999); $entryDAO->addEntry ($values); } } @@ -196,6 +197,8 @@ class feedController extends ActionController { ($entry->date (true) >= $date_min || $feed->keepHistory ())) { $values = $entry->toArray (); + //Use declared date at first import, otherwise use discovery date + $values['id'] = empty($existingGuids) ? min(time(), $entry->date (true)) . '.' . rand(0, 999999) : microtime(true); $entryDAO->addEntry ($values); } } diff --git a/app/models/Entry.php b/app/models/Entry.php index 80e8d7b6e..f8ec1287c 100755 --- a/app/models/Entry.php +++ b/app/models/Entry.php @@ -203,7 +203,7 @@ class EntryDAO extends Model_pdo { $stm = $this->bd->prepare ($sql); $values = array ( - microtime(true), + $valuesTmp['id'], substr($valuesTmp['guid'], 0, 760), substr($valuesTmp['title'], 0, 255), substr($valuesTmp['author'], 0, 255), -- cgit v1.2.3 From d6a685b0d06c39c9da8fbbc9e720ccb17147be28 Mon Sep 17 00:00:00 2001 From: Marien Fressinaud Date: Thu, 28 Nov 2013 13:26:11 +0100 Subject: Ajout options partage Poche et Diaspora MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Le partage n'est pas encore possible mais on peut préciser les urls dans la configuration Voir #175 --- app/controllers/configureController.php | 8 +++++++- app/i18n/en.php | 13 +++++++----- app/i18n/fr.php | 13 +++++++----- app/models/RSSConfiguration.php | 36 +++++++++++++++++++++++++++++++++ app/views/configure/sharing.phtml | 28 ++++++++++++++++++++++++- 5 files changed, 86 insertions(+), 12 deletions(-) (limited to 'app/models') diff --git a/app/controllers/configureController.php b/app/controllers/configureController.php index b50b243cf..31885d30e 100755 --- a/app/controllers/configureController.php +++ b/app/controllers/configureController.php @@ -270,11 +270,17 @@ class configureController extends ActionController { public function sharingAction () { if (Request::isPost ()) { $urlShaarli = Request::param ('shaarli', ''); + $urlPoche = Request::param ('poche', ''); + $urlDiaspora = Request::param ('diaspora', ''); $this->view->conf->_urlShaarli ($urlShaarli); + $this->view->conf->_urlPoche ($urlPoche); + $this->view->conf->_urlDiaspora ($urlDiaspora); $values = array ( - 'url_shaarli' => $this->view->conf->urlShaarli () + 'url_shaarli' => $this->view->conf->urlShaarli (), + 'url_poche' => $this->view->conf->urlPoche (), + 'url_diaspora' => $this->view->conf->urlDiaspora () ); $confDAO = new RSSConfigurationDAO (); diff --git a/app/i18n/en.php b/app/i18n/en.php index b8bfebba9..06c439283 100644 --- a/app/i18n/en.php +++ b/app/i18n/en.php @@ -167,15 +167,17 @@ return array ( 'display_articles_unfolded' => 'Show articles unfolded by default', 'after_onread' => 'After marked as read,', 'jump_next' => 'jump to next unread sibling', - 'reading_icons' => 'Reading icons', - 'top_line' => 'Top line', - 'bottom_line' => 'Bottom line', + 'reading_icons' => 'Reading icons', + 'top_line' => 'Top line', + 'bottom_line' => 'Bottom line', 'img_with_lazyload' => 'Use "lazy load" mode to load pictures', 'auto_read_when' => 'Mark as read when', 'article_selected' => 'article is selected', 'article_open_on_website' => 'article is opened on its original website', 'scroll' => 'page scrolls', 'your_shaarli' => 'Your Shaarli', + 'your_poche' => 'Your Poche', + 'your_diaspora_pod' => 'Your Diaspora* pod', 'sharing' => 'Sharing', 'share' => 'Share', 'by_email' => 'By mail', @@ -183,6 +185,7 @@ return array ( 'optimize_bdd' => 'Optimize database', 'optimize_todo_sometimes' => 'To do occasionally to reduce size of database', 'theme' => 'Theme', + 'more_information' => 'More information', 'article' => 'Article', 'title' => 'Title', @@ -218,7 +221,7 @@ return array ( 'logs' => 'Logs', 'logs_empty' => 'Log file is empty', - 'clear_logs' => 'Clear the logs', + 'clear_logs' => 'Clear the logs', 'forbidden_access' => 'Forbidden access', 'forbidden_access_description' => 'Access is password protected, please to read your feeds.', @@ -287,7 +290,7 @@ return array ( 'dom_is_nok' => 'You haven’t the necessary to browse the DOM (php-xml package can be useful)', 'cache_is_ok' => 'Permissions on cache directory are good', 'log_is_ok' => 'Permissions on logs directory are good', - 'favicons_is_ok' => 'Permissions on favicons directory are good', + 'favicons_is_ok' => 'Permissions on favicons directory are good', 'data_is_ok' => 'Permissions on data directory are good', 'file_is_nok' => 'Check permissions on %s directory. HTTP server must have rights to write into', 'fix_errors_before' => 'Fix errors before skip to the next step.', diff --git a/app/i18n/fr.php b/app/i18n/fr.php index bb32382a5..1cc24a516 100644 --- a/app/i18n/fr.php +++ b/app/i18n/fr.php @@ -167,15 +167,17 @@ return array ( 'display_articles_unfolded' => 'Afficher les articles dépliés par défaut', 'after_onread' => 'Après marqué comme lu,', 'jump_next' => 'sauter au prochain voisin non lu', - 'reading_icons' => 'Icônes de lecture', - 'top_line' => 'Ligne du haut', - 'bottom_line' => 'Ligne du bas', + 'reading_icons' => 'Icônes de lecture', + 'top_line' => 'Ligne du haut', + 'bottom_line' => 'Ligne du bas', 'img_with_lazyload' => 'Utiliser le mode “chargement différé” pour les images', 'auto_read_when' => 'Marquer comme lu lorsque', 'article_selected' => 'l’article est sélectionné', 'article_open_on_website' => 'l’article est ouvert sur le site d’origine', 'scroll' => 'au défilement de la page', 'your_shaarli' => 'Votre Shaarli', + 'your_poche' => 'Votre Poche', + 'your_diaspora_pod' => 'Votre pod Diaspora*', 'sharing' => 'Partage', 'share' => 'Partager', 'by_email' => 'Par mail', @@ -183,6 +185,7 @@ return array ( 'optimize_bdd' => 'Optimiser la base de données', 'optimize_todo_sometimes' => 'À faire de temps en temps pour réduire la taille de la BDD', 'theme' => 'Thème', + 'more_information' => 'Plus d’informations', 'article' => 'Article', 'title' => 'Titre', @@ -218,7 +221,7 @@ return array ( 'logs' => 'Logs', 'logs_empty' => 'Les logs sont vides', - 'clear_logs' => 'Effacer les logs', + 'clear_logs' => 'Effacer les logs', 'forbidden_access' => 'Accès interdit', 'forbidden_access_description' => 'L’accès est protégé par un mot de passe, veuillez pour accéder aux flux.', @@ -287,7 +290,7 @@ return array ( 'dom_is_nok' => 'Vous ne disposez pas du nécessaire pour parcourir le DOM (voir du côté du paquet php-xml ?)', 'cache_is_ok' => 'Les droits sur le répertoire de cache sont bons', 'log_is_ok' => 'Les droits sur le répertoire des logs sont bons', - 'favicons_is_ok' => 'Les droits sur le répertoire des favicons sont bons', + 'favicons_is_ok' => 'Les droits sur le répertoire des favicons sont bons', 'data_is_ok' => 'Les droits sur le répertoire de data sont bons', 'file_is_nok' => 'Veuillez vérifier les droits sur le répertoire %s. Le serveur HTTP doit être capable d’écrire dedans', 'fix_errors_before' => 'Veuillez corriger les erreurs avant de passer à l’étape suivante.', diff --git a/app/models/RSSConfiguration.php b/app/models/RSSConfiguration.php index ef562bdcb..e6adf5c51 100755 --- a/app/models/RSSConfiguration.php +++ b/app/models/RSSConfiguration.php @@ -18,6 +18,8 @@ class RSSConfiguration extends Model { private $mail_login = ''; private $mark_when = array (); private $url_shaarli = ''; + private $url_poche = ''; + private $url_diaspora = ''; private $theme; private $anon_access; private $token; @@ -48,6 +50,8 @@ class RSSConfiguration extends Model { $this->_mailLogin ($confDAO->mail_login); $this->_markWhen ($confDAO->mark_when); $this->_urlShaarli ($confDAO->url_shaarli); + $this->_urlPoche ($confDAO->url_poche); + $this->_urlDiaspora ($confDAO->url_diaspora); $this->_theme ($confDAO->theme); RSSThemes::setThemeId ($confDAO->theme); $this->_anonAccess ($confDAO->anon_access); @@ -116,6 +120,12 @@ class RSSConfiguration extends Model { public function urlShaarli () { return $this->url_shaarli; } + public function urlPoche () { + return $this->url_poche; + } + public function urlDiaspora () { + return $this->url_diaspora; + } public function theme () { return $this->theme; } @@ -257,6 +267,24 @@ class RSSConfiguration extends Model { $this->url_shaarli = ''; } } + public function _urlPoche ($value) { + if (filter_var ($value, FILTER_VALIDATE_URL)) { + $this->url_poche = $value; + } elseif (version_compare(PHP_VERSION, '5.3.3', '<') && (strpos($value, '-') > 0) && ($value === filter_var($value, FILTER_SANITIZE_URL))) { //PHP bug #51192 + $this->url_poche = $value; + } else { + $this->url_poche = ''; + } + } + public function _urlDiaspora ($value) { + if (filter_var ($value, FILTER_VALIDATE_URL)) { + $this->url_diaspora = $value; + } elseif (version_compare(PHP_VERSION, '5.3.3', '<') && (strpos($value, '-') > 0) && ($value === filter_var($value, FILTER_SANITIZE_URL))) { //PHP bug #51192 + $this->url_diaspora = $value; + } else { + $this->url_diaspora = ''; + } + } public function _theme ($value) { $this->theme = $value; } @@ -334,6 +362,8 @@ class RSSConfigurationDAO extends Model_array { 'scroll' => 'no' ); public $url_shaarli = ''; + public $url_poche = ''; + public $url_diaspora = ''; public $theme = 'default'; public $anon_access = 'no'; public $token = ''; @@ -392,6 +422,12 @@ class RSSConfigurationDAO extends Model_array { if (isset ($this->array['url_shaarli'])) { $this->url_shaarli = $this->array['url_shaarli']; } + if (isset ($this->array['url_poche'])) { + $this->url_poche = $this->array['url_poche']; + } + if (isset ($this->array['url_diaspora'])) { + $this->url_diaspora = $this->array['url_diaspora']; + } if (isset ($this->array['theme'])) { $this->theme = $this->array['theme']; } diff --git a/app/views/configure/sharing.phtml b/app/views/configure/sharing.phtml index e28122b00..0345b9a8d 100644 --- a/app/views/configure/sharing.phtml +++ b/app/views/configure/sharing.phtml @@ -6,9 +6,35 @@
    - +
    + + +
    +
    + +
    + +
    + + + +
    +
    + +
    + +
    + + +
    -- cgit v1.2.3 From 1e9ccb1da9f38ca983258b983e156d56a2887bc9 Mon Sep 17 00:00:00 2001 From: Marien Fressinaud Date: Thu, 28 Nov 2013 15:30:24 +0100 Subject: Ajoute options pour désactiver partage MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Possibilité de désactiver le partage Twitter, G+, FB et email Refactorisation de certaines parties du code --- app/controllers/configureController.php | 24 ++++---- app/i18n/en.php | 11 +++- app/i18n/fr.php | 11 +++- app/models/RSSConfiguration.php | 95 +++++++++++++++----------------- app/views/configure/sharing.phtml | 22 +++++++- app/views/helpers/view/normal_view.phtml | 63 +++++++++++---------- 6 files changed, 126 insertions(+), 100 deletions(-) (limited to 'app/models') diff --git a/app/controllers/configureController.php b/app/controllers/configureController.php index 31885d30e..d4a821b66 100755 --- a/app/controllers/configureController.php +++ b/app/controllers/configureController.php @@ -269,22 +269,18 @@ class configureController extends ActionController { public function sharingAction () { if (Request::isPost ()) { - $urlShaarli = Request::param ('shaarli', ''); - $urlPoche = Request::param ('poche', ''); - $urlDiaspora = Request::param ('diaspora', ''); - - $this->view->conf->_urlShaarli ($urlShaarli); - $this->view->conf->_urlPoche ($urlPoche); - $this->view->conf->_urlDiaspora ($urlDiaspora); - - $values = array ( - 'url_shaarli' => $this->view->conf->urlShaarli (), - 'url_poche' => $this->view->conf->urlPoche (), - 'url_diaspora' => $this->view->conf->urlDiaspora () - ); + $this->view->conf->_sharing (array ( + 'shaarli' => Request::param ('shaarli', ''), + 'poche' => Request::param ('poche', ''), + 'diaspora' => Request::param ('diaspora', ''), + 'twitter' => Request::param ('twitter', 'no') === 'yes', + 'g+' => Request::param ('g+', 'no') === 'yes', + 'facebook' => Request::param ('facebook', 'no') === 'yes', + 'email' => Request::param ('email', 'no') === 'yes', + )); $confDAO = new RSSConfigurationDAO (); - $confDAO->update ($values); + $confDAO->update ($this->view->conf->sharing ()); Session::_param ('conf', $this->view->conf); // notif diff --git a/app/i18n/en.php b/app/i18n/en.php index 06c439283..fdfe865f3 100644 --- a/app/i18n/en.php +++ b/app/i18n/en.php @@ -180,12 +180,19 @@ return array ( 'your_diaspora_pod' => 'Your Diaspora* pod', 'sharing' => 'Sharing', 'share' => 'Share', - 'by_email' => 'By mail', - 'on_shaarli' => 'On your Shaarli', + 'by_email' => 'By email', 'optimize_bdd' => 'Optimize database', 'optimize_todo_sometimes' => 'To do occasionally to reduce size of database', 'theme' => 'Theme', 'more_information' => 'More information', + 'activate_sharing' => 'Activate sharing', + 'shaarli' => 'Shaarli', + 'poche' => 'Poche', + 'diaspora' => 'Diaspora*', + 'twitter' => 'Twitter', + 'g+' => 'Google+', + 'facebook' => 'Facebook', + 'email' => 'Email', 'article' => 'Article', 'title' => 'Title', diff --git a/app/i18n/fr.php b/app/i18n/fr.php index 1cc24a516..c2a9a030f 100644 --- a/app/i18n/fr.php +++ b/app/i18n/fr.php @@ -180,12 +180,19 @@ return array ( 'your_diaspora_pod' => 'Votre pod Diaspora*', 'sharing' => 'Partage', 'share' => 'Partager', - 'by_email' => 'Par mail', - 'on_shaarli' => 'Sur votre Shaarli', + 'by_email' => 'Par courriel', 'optimize_bdd' => 'Optimiser la base de données', 'optimize_todo_sometimes' => 'À faire de temps en temps pour réduire la taille de la BDD', 'theme' => 'Thème', 'more_information' => 'Plus d’informations', + 'activate_sharing' => 'Activer le partage', + 'shaarli' => 'Shaarli', + 'poche' => 'Poche', + 'diaspora' => 'Diaspora*', + 'twitter' => 'Twitter', + 'g+' => 'Google+', + 'facebook' => 'Facebook', + 'email' => 'Courriel', 'article' => 'Article', 'title' => 'Titre', diff --git a/app/models/RSSConfiguration.php b/app/models/RSSConfiguration.php index e6adf5c51..458362586 100755 --- a/app/models/RSSConfiguration.php +++ b/app/models/RSSConfiguration.php @@ -17,9 +17,7 @@ class RSSConfiguration extends Model { private $shortcuts = array (); private $mail_login = ''; private $mark_when = array (); - private $url_shaarli = ''; - private $url_poche = ''; - private $url_diaspora = ''; + private $sharing = array (); private $theme; private $anon_access; private $token; @@ -49,9 +47,7 @@ class RSSConfiguration extends Model { $this->_shortcuts ($confDAO->shortcuts); $this->_mailLogin ($confDAO->mail_login); $this->_markWhen ($confDAO->mark_when); - $this->_urlShaarli ($confDAO->url_shaarli); - $this->_urlPoche ($confDAO->url_poche); - $this->_urlDiaspora ($confDAO->url_diaspora); + $this->_sharing ($confDAO->sharing); $this->_theme ($confDAO->theme); RSSThemes::setThemeId ($confDAO->theme); $this->_anonAccess ($confDAO->anon_access); @@ -117,14 +113,13 @@ class RSSConfiguration extends Model { public function markWhenScroll () { return $this->mark_when['scroll']; } - public function urlShaarli () { - return $this->url_shaarli; - } - public function urlPoche () { - return $this->url_poche; - } - public function urlDiaspora () { - return $this->url_diaspora; + public function sharing ($key = false) { + if ($key === false) { + return $this->sharing; + } elseif (isset ($this->sharing[$key])) { + return $this->sharing[$key]; + } + return false; } public function theme () { return $this->theme; @@ -258,31 +253,25 @@ class RSSConfiguration extends Model { $this->mark_when['site'] = $values['site']; $this->mark_when['scroll'] = $values['scroll']; } - public function _urlShaarli ($value) { - if (filter_var ($value, FILTER_VALIDATE_URL)) { - $this->url_shaarli = $value; - } elseif (version_compare(PHP_VERSION, '5.3.3', '<') && (strpos($value, '-') > 0) && ($value === filter_var($value, FILTER_SANITIZE_URL))) { //PHP bug #51192 - $this->url_shaarli = $value; - } else { - $this->url_shaarli = ''; - } - } - public function _urlPoche ($value) { - if (filter_var ($value, FILTER_VALIDATE_URL)) { - $this->url_poche = $value; - } elseif (version_compare(PHP_VERSION, '5.3.3', '<') && (strpos($value, '-') > 0) && ($value === filter_var($value, FILTER_SANITIZE_URL))) { //PHP bug #51192 - $this->url_poche = $value; - } else { - $this->url_poche = ''; - } - } - public function _urlDiaspora ($value) { - if (filter_var ($value, FILTER_VALIDATE_URL)) { - $this->url_diaspora = $value; - } elseif (version_compare(PHP_VERSION, '5.3.3', '<') && (strpos($value, '-') > 0) && ($value === filter_var($value, FILTER_SANITIZE_URL))) { //PHP bug #51192 - $this->url_diaspora = $value; - } else { - $this->url_diaspora = ''; + public function _sharing ($values) { + $are_url = array ('shaarli', 'poche', 'diaspora'); + foreach ($values as $key => $value) { + if (in_array($key, $are_url)) { + $is_url = ( + filter_var ($value, FILTER_VALIDATE_URL) || + (version_compare(PHP_VERSION, '5.3.3', '<') && + (strpos($value, '-') > 0) && + ($value === filter_var($value, FILTER_SANITIZE_URL))) + ); //PHP bug #51192 + + if (!$is_url) { + $value = ''; + } + } elseif(!is_bool ($value)) { + $value = true; + } + + $this->sharing[$key] = $value; } } public function _theme ($value) { @@ -361,9 +350,15 @@ class RSSConfigurationDAO extends Model_array { 'site' => 'yes', 'scroll' => 'no' ); - public $url_shaarli = ''; - public $url_poche = ''; - public $url_diaspora = ''; + public $sharing = array ( + 'shaarli' => '', + 'poche' => '', + 'diaspora' => '', + 'twitter' => true, + 'g+' => true, + 'facebook' => true, + 'email' => true + ); public $theme = 'default'; public $anon_access = 'no'; public $token = ''; @@ -411,7 +406,9 @@ class RSSConfigurationDAO extends Model_array { $this->old_entries = $this->array['old_entries']; } if (isset ($this->array['shortcuts'])) { - $this->shortcuts = array_merge ($this->shortcuts, $this->array['shortcuts']); + $this->shortcuts = array_merge ( + $this->shortcuts, $this->array['shortcuts'] + ); } if (isset ($this->array['mail_login'])) { $this->mail_login = $this->array['mail_login']; @@ -419,14 +416,10 @@ class RSSConfigurationDAO extends Model_array { if (isset ($this->array['mark_when'])) { $this->mark_when = $this->array['mark_when']; } - if (isset ($this->array['url_shaarli'])) { - $this->url_shaarli = $this->array['url_shaarli']; - } - if (isset ($this->array['url_poche'])) { - $this->url_poche = $this->array['url_poche']; - } - if (isset ($this->array['url_diaspora'])) { - $this->url_diaspora = $this->array['url_diaspora']; + if (isset ($this->array['sharing'])) { + $this->sharing = array_merge ( + $this->sharing, $this->array['sharing'] + ); } if (isset ($this->array['theme'])) { $this->theme = $this->array['theme']; diff --git a/app/views/configure/sharing.phtml b/app/views/configure/sharing.phtml index 0345b9a8d..38abf9ad4 100644 --- a/app/views/configure/sharing.phtml +++ b/app/views/configure/sharing.phtml @@ -10,7 +10,7 @@
    - +
    @@ -21,7 +21,7 @@
    - +
    @@ -32,12 +32,28 @@
    - +
    +
    + +
    + + + +
    +
    +
    diff --git a/app/views/helpers/view/normal_view.phtml b/app/views/helpers/view/normal_view.phtml index d4343eb13..41b5d4176 100644 --- a/app/views/helpers/view/normal_view.phtml +++ b/app/views/helpers/view/normal_view.phtml @@ -12,7 +12,17 @@ if (isset ($this->entryPaginator) && !$this->entryPaginator->isEmpty ()) { $display_today = true; $display_yesterday = true; $display_others = true; + + $logged = !login_is_conf ($this->conf) || is_logged (); + $shaarli = $logged && $this->conf->sharing ('shaarli'); + $poche = $logged && $this->conf->sharing ('poche'); + $diaspora = $logged && $this->conf->sharing ('diaspora'); + $twitter = $this->conf->sharing ('twitter'); + $google_plus = $this->conf->sharing ('g+'); + $facebook = $this->conf->sharing ('facebook'); + $email = $this->conf->sharing ('email'); ?> + isDay (Days::TODAY)) { ?> @@ -91,68 +101,65 @@ if (isset ($this->entryPaginator) && !$this->entryPaginator->isEmpty ()) { } ?>
  • conf->bottomlineSharing ()) { + if ($this->conf->bottomlineSharing () && ( + $shaarli || $poche || $diaspora || $twitter || + $google_plus || $facebook || $email + )) { $link = urlencode ($item->link ()); $title = urlencode ($item->title () . ' - ' . $feed->name ()); ?> - +
  • conf->bottomlineTags () ? $item->tags() : null; -- cgit v1.2.3 From 3f63195c5f2a5dcb1d11b974dd2357b161e377c5 Mon Sep 17 00:00:00 2001 From: Marien Fressinaud Date: Thu, 28 Nov 2013 18:57:22 +0100 Subject: Première version pour imprimer les articles MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Voir #122 --- app/controllers/configureController.php | 1 + app/i18n/en.php | 1 + app/i18n/fr.php | 1 + app/models/RSSConfiguration.php | 3 ++- app/views/configure/sharing.phtml | 2 +- app/views/helpers/view/normal_view.phtml | 7 +++++++ public/scripts/main.js | 16 ++++++++++++++++ 7 files changed, 29 insertions(+), 2 deletions(-) (limited to 'app/models') diff --git a/app/controllers/configureController.php b/app/controllers/configureController.php index d4a821b66..4c9ceebbc 100755 --- a/app/controllers/configureController.php +++ b/app/controllers/configureController.php @@ -277,6 +277,7 @@ class configureController extends ActionController { 'g+' => Request::param ('g+', 'no') === 'yes', 'facebook' => Request::param ('facebook', 'no') === 'yes', 'email' => Request::param ('email', 'no') === 'yes', + 'print' => Request::param ('print', 'no') === 'yes' )); $confDAO = new RSSConfigurationDAO (); diff --git a/app/i18n/en.php b/app/i18n/en.php index fdfe865f3..4de7bc94d 100644 --- a/app/i18n/en.php +++ b/app/i18n/en.php @@ -193,6 +193,7 @@ return array ( 'g+' => 'Google+', 'facebook' => 'Facebook', 'email' => 'Email', + 'print' => 'Print', 'article' => 'Article', 'title' => 'Title', diff --git a/app/i18n/fr.php b/app/i18n/fr.php index c2a9a030f..67a3a1836 100644 --- a/app/i18n/fr.php +++ b/app/i18n/fr.php @@ -193,6 +193,7 @@ return array ( 'g+' => 'Google+', 'facebook' => 'Facebook', 'email' => 'Courriel', + 'print' => 'Imprimer', 'article' => 'Article', 'title' => 'Titre', diff --git a/app/models/RSSConfiguration.php b/app/models/RSSConfiguration.php index 458362586..c36548e6f 100755 --- a/app/models/RSSConfiguration.php +++ b/app/models/RSSConfiguration.php @@ -357,7 +357,8 @@ class RSSConfigurationDAO extends Model_array { 'twitter' => true, 'g+' => true, 'facebook' => true, - 'email' => true + 'email' => true, + 'print' => true ); public $theme = 'default'; public $anon_access = 'no'; diff --git a/app/views/configure/sharing.phtml b/app/views/configure/sharing.phtml index 855b8536e..311910297 100644 --- a/app/views/configure/sharing.phtml +++ b/app/views/configure/sharing.phtml @@ -42,7 +42,7 @@
    diff --git a/app/views/helpers/view/normal_view.phtml b/app/views/helpers/view/normal_view.phtml index 99e4bedc7..1a977bafe 100644 --- a/app/views/helpers/view/normal_view.phtml +++ b/app/views/helpers/view/normal_view.phtml @@ -21,6 +21,7 @@ if (isset ($this->entryPaginator) && !$this->entryPaginator->isEmpty ()) { $google_plus = $this->conf->sharing ('g+'); $facebook = $this->conf->sharing ('facebook'); $email = $this->conf->sharing ('email'); + $print = $this->conf->sharing ('print'); ?> @@ -156,6 +157,12 @@ if (isset ($this->entryPaginator) && !$this->entryPaginator->isEmpty ()) { + +
  • + + + +
  • diff --git a/public/scripts/main.js b/public/scripts/main.js index d54937600..c2a3b3912 100644 --- a/public/scripts/main.js +++ b/public/scripts/main.js @@ -623,6 +623,21 @@ function init_confirm_action() { }); } +function init_print_action() { + $('.print-article').click(function () { + + var content = $(".flux.current .content"); + var tmp_window = window.open(); + tmp_window.document.writeln(content.html()); + tmp_window.document.close(); + tmp_window.focus(); + tmp_window.print(); + tmp_window.close(); + + return false; + }); +} + function init_all() { if (!(window.$ && window.url_freshrss && ((!full_lazyload) || $.fn.lazyload))) { if (window.console) { @@ -647,6 +662,7 @@ function init_all() { init_persona(); } init_confirm_action(); + init_print_action(); if (window.console) { console.log('FreshRSS init done.'); } -- cgit v1.2.3 From 7cdc477c45a84bde56f5253ce34924f164e6ca0a Mon Sep 17 00:00:00 2001 From: Alexandre Alapetite Date: Thu, 28 Nov 2013 20:59:31 +0100 Subject: touch en microsecondes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Passage en microsecondes pour le touch (gestion du cache) pour éviter les problèmes en particulier dans le cas de requêtes de moins d'une seconde. Nouvelle fonction invalidateHttpCache() pour plus facilement changer de méthode de contrôle de fraîcheur de cache. Devrait résoudre https://github.com/marienfressinaud/FreshRSS/issues/296 --- actualize_script.php | 2 +- app/controllers/entryController.php | 2 +- app/controllers/indexController.php | 4 ++-- app/layout/layout.phtml | 2 +- app/models/RSSConfiguration.php | 2 +- lib/lib_rss.php | 4 ++++ lib/minz/dao/Model_pdo.php | 2 +- public/index.php | 7 ++++--- 8 files changed, 15 insertions(+), 10 deletions(-) (limited to 'app/models') diff --git a/actualize_script.php b/actualize_script.php index bc1d108bd..942070ccc 100755 --- a/actualize_script.php +++ b/actualize_script.php @@ -20,4 +20,4 @@ $front_controller = new App_FrontController (); $front_controller->init (); Session::_param('mail', true); // permet de se passer de la phase de connexion $front_controller->run (); -touch(DATA_PATH . '/touch.txt'); +invalidateHttpCache(); diff --git a/app/controllers/entryController.php b/app/controllers/entryController.php index fa34ad429..d92eb0ed3 100755 --- a/app/controllers/entryController.php +++ b/app/controllers/entryController.php @@ -84,7 +84,7 @@ class entryController extends ActionController { $entryDAO = new EntryDAO(); $entryDAO->optimizeTable(); - touch(DATA_PATH . '/touch.txt'); + invalidateHttpCache(); $notif = array ( 'type' => 'good', diff --git a/app/controllers/indexController.php b/app/controllers/indexController.php index e4462e543..8e6abd682 100755 --- a/app/controllers/indexController.php +++ b/app/controllers/indexController.php @@ -272,7 +272,7 @@ class indexController extends ActionController { $res = json_decode ($result, true); if ($res['status'] == 'okay' && $res['email'] == $this->view->conf->mailLogin ()) { Session::_param ('mail', $res['email']); - touch(DATA_PATH . '/touch.txt'); + invalidateHttpCache(); } else { $res = array (); $res['status'] = 'failure'; @@ -285,6 +285,6 @@ class indexController extends ActionController { public function logoutAction () { $this->view->_useLayout (false); Session::_param ('mail'); - touch(DATA_PATH . '/touch.txt'); + invalidateHttpCache(); } } diff --git a/app/layout/layout.phtml b/app/layout/layout.phtml index c53b28841..9b502275c 100644 --- a/app/layout/layout.phtml +++ b/app/layout/layout.phtml @@ -32,7 +32,7 @@ notification)) { - touch(DATA_PATH . '/touch.txt'); + invalidateHttpCache(); ?>
    notification['content']; ?> diff --git a/app/models/RSSConfiguration.php b/app/models/RSSConfiguration.php index c36548e6f..fe6cd48d3 100755 --- a/app/models/RSSConfiguration.php +++ b/app/models/RSSConfiguration.php @@ -473,6 +473,6 @@ class RSSConfigurationDAO extends Model_array { } $this->writeFile($this->array); - touch(DATA_PATH . '/touch.txt'); + invalidateHttpCache(); } } diff --git a/lib/lib_rss.php b/lib/lib_rss.php index 3c03f4281..5a74bfd0a 100644 --- a/lib/lib_rss.php +++ b/lib/lib_rss.php @@ -230,3 +230,7 @@ function lazyimg($content) { $content ); } + +function invalidateHttpCache() { + file_put_contents(DATA_PATH . '/touch.txt', microtime(true)); +} diff --git a/lib/minz/dao/Model_pdo.php b/lib/minz/dao/Model_pdo.php index 545f59e81..48c81d082 100755 --- a/lib/minz/dao/Model_pdo.php +++ b/lib/minz/dao/Model_pdo.php @@ -85,7 +85,7 @@ class Model_pdo { class FreshPDO extends PDO { private static function check($statement) { if (preg_match('/^(?:UPDATE|INSERT|DELETE)/i', $statement)) { - touch(DATA_PATH . '/touch.txt'); + invalidateHttpCache(); } } diff --git a/public/index.php b/public/index.php index 9bf4fc073..cabd836d5 100755 --- a/public/index.php +++ b/public/index.php @@ -27,10 +27,11 @@ if (file_exists ('install.php')) { if (!file_exists(DATA_PATH . '/no-cache.txt')) { require (LIB_PATH . '/http-conditional.php'); $dateLastModification = max( - @filemtime(DATA_PATH . '/touch.txt') - 1, - @filemtime(LOG_PATH . '/application.log') - 1, - @filemtime(DATA_PATH . '/application.ini') - 1 + @filemtime(DATA_PATH . '/touch.txt'), + @filemtime(LOG_PATH . '/application.log'), + @filemtime(DATA_PATH . '/application.ini') ); + $_SERVER['QUERY_STRING'] .= '&utime=' . file_get_contents(DATA_PATH . '/touch.txt'); if (httpConditional($dateLastModification, 0, 0, false, false, true)) { exit(); //No need to send anything } -- cgit v1.2.3 From e8f170f5e35759fa1189d6e7272ca24b3568079d Mon Sep 17 00:00:00 2001 From: Alexandre Alapetite Date: Thu, 28 Nov 2013 22:05:20 +0100 Subject: Protection des requêtes SQL MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Corrige https://github.com/marienfressinaud/FreshRSS/issues/294 --- app/models/Category.php | 24 ++++++++++---------- app/models/Entry.php | 58 ++++++++++++++++++++++++------------------------- app/models/Feed.php | 34 ++++++++++++++--------------- 3 files changed, 58 insertions(+), 58 deletions(-) (limited to 'app/models') diff --git a/app/models/Category.php b/app/models/Category.php index a01034f4e..5915132f4 100755 --- a/app/models/Category.php +++ b/app/models/Category.php @@ -86,7 +86,7 @@ class Category extends Model { class CategoryDAO extends Model_pdo { public function addCategory ($valuesTmp) { - $sql = 'INSERT INTO ' . $this->prefix . 'category (name, color) VALUES(?, ?)'; + $sql = 'INSERT INTO `' . $this->prefix . 'category` (name, color) VALUES(?, ?)'; $stm = $this->bd->prepare ($sql); $values = array ( @@ -104,7 +104,7 @@ class CategoryDAO extends Model_pdo { } public function updateCategory ($id, $valuesTmp) { - $sql = 'UPDATE ' . $this->prefix . 'category SET name=?, color=? WHERE id=?'; + $sql = 'UPDATE `' . $this->prefix . 'category` SET name=?, color=? WHERE id=?'; $stm = $this->bd->prepare ($sql); $values = array ( @@ -123,7 +123,7 @@ class CategoryDAO extends Model_pdo { } public function deleteCategory ($id) { - $sql = 'DELETE FROM ' . $this->prefix . 'category WHERE id=?'; + $sql = 'DELETE FROM `' . $this->prefix . 'category` WHERE id=?'; $stm = $this->bd->prepare ($sql); $values = array ($id); @@ -138,7 +138,7 @@ class CategoryDAO extends Model_pdo { } public function searchById ($id) { - $sql = 'SELECT * FROM ' . $this->prefix . 'category WHERE id=?'; + $sql = 'SELECT * FROM `' . $this->prefix . 'category` WHERE id=?'; $stm = $this->bd->prepare ($sql); $values = array ($id); @@ -154,7 +154,7 @@ class CategoryDAO extends Model_pdo { } } public function searchByName ($name) { - $sql = 'SELECT * FROM ' . $this->prefix . 'category WHERE name=?'; + $sql = 'SELECT * FROM `' . $this->prefix . 'category` WHERE name=?'; $stm = $this->bd->prepare ($sql); $values = array ($name); @@ -175,15 +175,15 @@ class CategoryDAO extends Model_pdo { $sql = 'SELECT c.id AS c_id, c.name AS c_name, ' . ($details ? 'c.color AS c_color, ' : '') . ($details ? 'f.* ' : 'f.id, f.name, f.website, f.priority, f.error, f.cache_nbEntries, f.cache_nbUnreads ') - . 'FROM ' . $this->prefix . 'category c ' - . 'LEFT OUTER JOIN ' . $this->prefix . 'feed f ON f.category = c.id ' + . 'FROM `' . $this->prefix . 'category` c ' + . 'LEFT OUTER JOIN `' . $this->prefix . 'feed` f ON f.category = c.id ' . 'GROUP BY f.id ' . 'ORDER BY c.name, f.name'; $stm = $this->bd->prepare ($sql); $stm->execute (); return HelperCategory::daoToCategoryPrepopulated ($stm->fetchAll (PDO::FETCH_ASSOC)); } else { - $sql = 'SELECT * FROM ' . $this->prefix . 'category ORDER BY name'; + $sql = 'SELECT * FROM `' . $this->prefix . 'category` ORDER BY name'; $stm = $this->bd->prepare ($sql); $stm->execute (); return HelperCategory::daoToCategory ($stm->fetchAll (PDO::FETCH_ASSOC)); @@ -191,7 +191,7 @@ class CategoryDAO extends Model_pdo { } public function getDefault () { - $sql = 'SELECT * FROM ' . $this->prefix . 'category WHERE id=1'; + $sql = 'SELECT * FROM `' . $this->prefix . 'category` WHERE id=1'; $stm = $this->bd->prepare ($sql); $stm->execute (); @@ -222,7 +222,7 @@ class CategoryDAO extends Model_pdo { } public function count () { - $sql = 'SELECT COUNT(*) AS count FROM ' . $this->prefix . 'category'; + $sql = 'SELECT COUNT(*) AS count FROM `' . $this->prefix . 'category`'; $stm = $this->bd->prepare ($sql); $stm->execute (); $res = $stm->fetchAll (PDO::FETCH_ASSOC); @@ -231,7 +231,7 @@ class CategoryDAO extends Model_pdo { } public function countFeed ($id) { - $sql = 'SELECT COUNT(*) AS count FROM ' . $this->prefix . 'feed WHERE category=?'; + $sql = 'SELECT COUNT(*) AS count FROM `' . $this->prefix . 'feed` WHERE category=?'; $stm = $this->bd->prepare ($sql); $values = array ($id); $stm->execute ($values); @@ -241,7 +241,7 @@ class CategoryDAO extends Model_pdo { } public function countNotRead ($id) { - $sql = 'SELECT COUNT(*) AS count FROM ' . $this->prefix . 'entry e INNER JOIN ' . $this->prefix . 'feed f ON e.id_feed = f.id WHERE category=? AND e.is_read=0'; + $sql = 'SELECT COUNT(*) AS count FROM `' . $this->prefix . 'entry` e INNER JOIN `' . $this->prefix . 'feed` f ON e.id_feed = f.id WHERE category=? AND e.is_read=0'; $stm = $this->bd->prepare ($sql); $values = array ($id); $stm->execute ($values); diff --git a/app/models/Entry.php b/app/models/Entry.php index f8ec1287c..739c2a582 100755 --- a/app/models/Entry.php +++ b/app/models/Entry.php @@ -199,7 +199,7 @@ class Entry extends Model { class EntryDAO extends Model_pdo { public function addEntry ($valuesTmp) { - $sql = 'INSERT INTO ' . $this->prefix . 'entry(id, guid, title, author, content, link, date, is_read, is_favorite, id_feed, tags) VALUES(CAST(? * 1000000 AS SIGNED INTEGER), ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)'; + $sql = 'INSERT INTO `' . $this->prefix . 'entry`(id, guid, title, author, content, link, date, is_read, is_favorite, id_feed, tags) VALUES(CAST(? * 1000000 AS SIGNED INTEGER), ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)'; $stm = $this->bd->prepare ($sql); $values = array ( @@ -242,7 +242,7 @@ class EntryDAO extends Model_pdo { } $set = substr ($set, 0, -2); - $sql = 'UPDATE ' . $this->prefix . 'entry SET ' . $set . ' WHERE id=?'; + $sql = 'UPDATE `' . $this->prefix . 'entry` SET ' . $set . ' WHERE id=?'; $stm = $this->bd->prepare ($sql); foreach ($valuesTmp as $v) { @@ -259,7 +259,7 @@ class EntryDAO extends Model_pdo { } }*/ public function markFavorite ($id, $is_favorite = true) { - $sql = 'UPDATE ' . $this->prefix . 'entry e ' + $sql = 'UPDATE `' . $this->prefix . 'entry` e ' . 'SET e.is_favorite = ? ' . 'WHERE e.id=?'; $values = array ($is_favorite ? 1 : 0, $id); @@ -273,7 +273,7 @@ class EntryDAO extends Model_pdo { } } public function markRead ($id, $is_read = true) { - $sql = 'UPDATE ' . $this->prefix . 'entry e INNER JOIN ' . $this->prefix . 'feed f ON e.id_feed = f.id ' + $sql = 'UPDATE `' . $this->prefix . 'entry` e INNER JOIN `' . $this->prefix . 'feed` f ON e.id_feed = f.id ' . 'SET e.is_read = ?,' . 'f.cache_nbUnreads=f.cache_nbUnreads' . ($is_read ? '-' : '+') . '1 ' . 'WHERE e.id=?'; @@ -289,7 +289,7 @@ class EntryDAO extends Model_pdo { } public function markReadEntries ($idMax = 0) { if ($idMax === 0) { - $sql = 'UPDATE ' . $this->prefix . 'entry e INNER JOIN ' . $this->prefix . 'feed f ON e.id_feed = f.id ' + $sql = 'UPDATE `' . $this->prefix . 'entry` e INNER JOIN `' . $this->prefix . 'feed` f ON e.id_feed = f.id ' . 'SET e.is_read = 1, f.cache_nbUnreads=0 ' . 'WHERE e.is_read = 0 AND f.priority > 0'; $stm = $this->bd->prepare ($sql); @@ -303,7 +303,7 @@ class EntryDAO extends Model_pdo { } else { $this->bd->beginTransaction (); - $sql = 'UPDATE ' . $this->prefix . 'entry e INNER JOIN ' . $this->prefix . 'feed f ON e.id_feed = f.id ' + $sql = 'UPDATE `' . $this->prefix . 'entry` e INNER JOIN `' . $this->prefix . 'feed` f ON e.id_feed = f.id ' . 'SET e.is_read = 1 ' . 'WHERE e.is_read = 0 AND e.id <= ? AND f.priority > 0'; $values = array ($idMax); @@ -317,11 +317,11 @@ class EntryDAO extends Model_pdo { $affected = $stm->rowCount(); if ($affected > 0) { - $sql = 'UPDATE ' . $this->prefix . 'feed f ' + $sql = 'UPDATE `' . $this->prefix . 'feed` f ' . 'LEFT OUTER JOIN (' . 'SELECT e.id_feed, ' . 'COUNT(*) AS nbUnreads ' - . 'FROM ' . $this->prefix . 'entry e ' + . 'FROM `' . $this->prefix . 'entry` e ' . 'WHERE e.is_read = 0 ' . 'GROUP BY e.id_feed' . ') x ON x.id_feed=f.id ' @@ -341,7 +341,7 @@ class EntryDAO extends Model_pdo { } public function markReadCat ($id, $idMax = 0) { if ($idMax === 0) { - $sql = 'UPDATE ' . $this->prefix . 'entry e INNER JOIN ' . $this->prefix . 'feed f ON e.id_feed = f.id ' + $sql = 'UPDATE `' . $this->prefix . 'entry` e INNER JOIN `' . $this->prefix . 'feed` f ON e.id_feed = f.id ' . 'SET e.is_read = 1, f.cache_nbUnreads=0 ' . 'WHERE f.category = ? AND e.is_read = 0'; $values = array ($id); @@ -356,7 +356,7 @@ class EntryDAO extends Model_pdo { } else { $this->bd->beginTransaction (); - $sql = 'UPDATE ' . $this->prefix . 'entry e INNER JOIN ' . $this->prefix . 'feed f ON e.id_feed = f.id ' + $sql = 'UPDATE `' . $this->prefix . 'entry` e INNER JOIN `' . $this->prefix . 'feed` f ON e.id_feed = f.id ' . 'SET e.is_read = 1 ' . 'WHERE f.category = ? AND e.is_read = 0 AND e.id <= ?'; $values = array ($id, $idMax); @@ -370,11 +370,11 @@ class EntryDAO extends Model_pdo { $affected = $stm->rowCount(); if ($affected > 0) { - $sql = 'UPDATE ' . $this->prefix . 'feed f ' + $sql = 'UPDATE `' . $this->prefix . 'feed` f ' . 'LEFT OUTER JOIN (' . 'SELECT e.id_feed, ' . 'COUNT(*) AS nbUnreads ' - . 'FROM ' . $this->prefix . 'entry e ' + . 'FROM `' . $this->prefix . 'entry` e ' . 'WHERE e.is_read = 0 ' . 'GROUP BY e.id_feed' . ') x ON x.id_feed=f.id ' @@ -396,7 +396,7 @@ class EntryDAO extends Model_pdo { } public function markReadFeed ($id, $idMax = 0) { if ($idMax === 0) { - $sql = 'UPDATE ' . $this->prefix . 'entry e INNER JOIN ' . $this->prefix . 'feed f ON e.id_feed = f.id ' + $sql = 'UPDATE `' . $this->prefix . 'entry` e INNER JOIN `' . $this->prefix . 'feed` f ON e.id_feed = f.id ' . 'SET e.is_read = 1, f.cache_nbUnreads=0 ' . 'WHERE f.id=? AND e.is_read = 0'; $values = array ($id); @@ -411,7 +411,7 @@ class EntryDAO extends Model_pdo { } else { $this->bd->beginTransaction (); - $sql = 'UPDATE ' . $this->prefix . 'entry e INNER JOIN ' . $this->prefix . 'feed f ON e.id_feed = f.id ' + $sql = 'UPDATE `' . $this->prefix . 'entry` e INNER JOIN `' . $this->prefix . 'feed` f ON e.id_feed = f.id ' . 'SET e.is_read = 1 ' . 'WHERE f.id=? AND e.is_read = 0 AND e.id <= ?'; $values = array ($id, $idMax); @@ -425,7 +425,7 @@ class EntryDAO extends Model_pdo { $affected = $stm->rowCount(); if ($affected > 0) { - $sql = 'UPDATE ' . $this->prefix . 'feed f ' + $sql = 'UPDATE `' . $this->prefix . 'feed` f ' . 'SET f.cache_nbUnreads=f.cache_nbUnreads-' . $affected . ' WHERE f.id=?'; $values = array ($id); @@ -454,7 +454,7 @@ class EntryDAO extends Model_pdo { } $set = substr ($set, 0, -2); - $sql = 'UPDATE ' . $this->prefix . 'entry SET ' . $set; + $sql = 'UPDATE `' . $this->prefix . 'entry` SET ' . $set; $stm = $this->bd->prepare ($sql); foreach ($valuesTmp as $v) { @@ -471,7 +471,7 @@ class EntryDAO extends Model_pdo { }*/ public function cleanOldEntries ($date_min) { - $sql = 'DELETE e.* FROM ' . $this->prefix . 'entry e INNER JOIN ' . $this->prefix . 'feed f ON e.id_feed = f.id WHERE e.id <= ? AND e.is_favorite = 0 AND f.keep_history = 0'; + $sql = 'DELETE e.* FROM `' . $this->prefix . 'entry` e INNER JOIN `' . $this->prefix . 'feed` f ON e.id_feed = f.id WHERE e.id <= ? AND e.is_favorite = 0 AND f.keep_history = 0'; $stm = $this->bd->prepare ($sql); $values = array ( @@ -489,7 +489,7 @@ class EntryDAO extends Model_pdo { public function searchByGuid ($feed_id, $id) { // un guid est unique pour un flux donné - $sql = 'SELECT * FROM ' . $this->prefix . 'entry WHERE id_feed=? AND guid=?'; + $sql = 'SELECT * FROM `' . $this->prefix . 'entry` WHERE id_feed=? AND guid=?'; $stm = $this->bd->prepare ($sql); $values = array ( @@ -509,7 +509,7 @@ class EntryDAO extends Model_pdo { } public function searchById ($id) { - $sql = 'SELECT * FROM ' . $this->prefix . 'entry WHERE id=?'; + $sql = 'SELECT * FROM `' . $this->prefix . 'entry` WHERE id=?'; $stm = $this->bd->prepare ($sql); $values = array ($id); @@ -541,8 +541,8 @@ class EntryDAO extends Model_pdo { $order = ''; } - $sql = 'SELECT e.* FROM ' . $this->prefix . 'entry e' - . ' INNER JOIN ' . $this->prefix . 'feed f ON e.id_feed = f.id' . $where + $sql = 'SELECT e.* FROM `' . $this->prefix . 'entry` e' + . ' INNER JOIN `' . $this->prefix . 'feed` f ON e.id_feed = f.id' . $where . ' ORDER BY e.id' . $order; if (empty($limitCount)) { @@ -571,7 +571,7 @@ class EntryDAO extends Model_pdo { } public function listLastGuidsByFeed($id, $n) { - $sql = 'SELECT guid FROM ' . $this->prefix . 'entry WHERE id_feed=? ORDER BY id DESC LIMIT ' . intval($n); + $sql = 'SELECT guid FROM `' . $this->prefix . 'entry` WHERE id_feed=? ORDER BY id DESC LIMIT ' . intval($n); $stm = $this->bd->prepare ($sql); $values = array ($id); $stm->execute ($values); @@ -579,8 +579,8 @@ class EntryDAO extends Model_pdo { } public function countUnreadRead () { - $sql = 'SELECT COUNT(e.id) AS count FROM ' . $this->prefix . 'entry e INNER JOIN ' . $this->prefix . 'feed f ON e.id_feed = f.id WHERE priority > 0' - . ' UNION SELECT COUNT(e.id) AS count FROM ' . $this->prefix . 'entry e INNER JOIN ' . $this->prefix . 'feed f ON e.id_feed = f.id WHERE priority > 0 AND is_read = 0'; + $sql = 'SELECT COUNT(e.id) AS count FROM `' . $this->prefix . 'entry` e INNER JOIN `' . $this->prefix . 'feed` f ON e.id_feed = f.id WHERE priority > 0' + . ' UNION SELECT COUNT(e.id) AS count FROM `' . $this->prefix . 'entry` e INNER JOIN `' . $this->prefix . 'feed` f ON e.id_feed = f.id WHERE priority > 0 AND is_read = 0'; $stm = $this->bd->prepare ($sql); $stm->execute (); $res = $stm->fetchAll (PDO::FETCH_COLUMN, 0); @@ -589,7 +589,7 @@ class EntryDAO extends Model_pdo { return array('all' => $all, 'unread' => $unread, 'read' => $all - $unread); } public function count ($minPriority = null) { - $sql = 'SELECT COUNT(e.id) AS count FROM ' . $this->prefix . 'entry e INNER JOIN ' . $this->prefix . 'feed f ON e.id_feed = f.id'; + $sql = 'SELECT COUNT(e.id) AS count FROM `' . $this->prefix . 'entry` e INNER JOIN `' . $this->prefix . 'feed` f ON e.id_feed = f.id'; if ($minPriority !== null) { $sql = ' WHERE priority > ' . intval($minPriority); } @@ -599,7 +599,7 @@ class EntryDAO extends Model_pdo { return $res[0]; } public function countNotRead ($minPriority = null) { - $sql = 'SELECT COUNT(e.id) AS count FROM ' . $this->prefix . 'entry e INNER JOIN ' . $this->prefix . 'feed f ON e.id_feed = f.id WHERE is_read = 0'; + $sql = 'SELECT COUNT(e.id) AS count FROM `' . $this->prefix . 'entry` e INNER JOIN `' . $this->prefix . 'feed` f ON e.id_feed = f.id WHERE is_read = 0'; if ($minPriority !== null) { $sql = ' AND priority > ' . intval($minPriority); } @@ -610,8 +610,8 @@ class EntryDAO extends Model_pdo { } public function countUnreadReadFavorites () { - $sql = 'SELECT COUNT(id) FROM ' . $this->prefix . 'entry WHERE is_favorite=1' - . ' UNION SELECT COUNT(id) FROM ' . $this->prefix . 'entry WHERE is_favorite=1 AND is_read = 0'; + $sql = 'SELECT COUNT(id) FROM `' . $this->prefix . 'entry` WHERE is_favorite=1' + . ' UNION SELECT COUNT(id) FROM `' . $this->prefix . 'entry` WHERE is_favorite=1 AND is_read = 0'; $stm = $this->bd->prepare ($sql); $stm->execute (); $res = $stm->fetchAll (PDO::FETCH_COLUMN, 0); @@ -621,7 +621,7 @@ class EntryDAO extends Model_pdo { } public function optimizeTable() { - $sql = 'OPTIMIZE TABLE ' . $this->prefix . 'entry'; + $sql = 'OPTIMIZE TABLE `' . $this->prefix . 'entry`'; $stm = $this->bd->prepare ($sql); $stm->execute (); } diff --git a/app/models/Feed.php b/app/models/Feed.php index da1a029a8..5914b05f0 100644 --- a/app/models/Feed.php +++ b/app/models/Feed.php @@ -309,7 +309,7 @@ class Feed extends Model { class FeedDAO extends Model_pdo { public function addFeed ($valuesTmp) { - $sql = 'INSERT INTO ' . $this->prefix . 'feed (url, category, name, website, description, lastUpdate, priority, httpAuth, error, keep_history) VALUES(?, ?, ?, ?, ?, ?, 10, ?, 0, 0)'; + $sql = 'INSERT INTO `' . $this->prefix . 'feed` (url, category, name, website, description, lastUpdate, priority, httpAuth, error, keep_history) VALUES(?, ?, ?, ?, ?, ?, 10, ?, 0, 0)'; $stm = $this->bd->prepare ($sql); $values = array ( @@ -342,7 +342,7 @@ class FeedDAO extends Model_pdo { } $set = substr ($set, 0, -2); - $sql = 'UPDATE ' . $this->prefix . 'feed SET ' . $set . ' WHERE id=?'; + $sql = 'UPDATE `' . $this->prefix . 'feed` SET ' . $set . ' WHERE id=?'; $stm = $this->bd->prepare ($sql); foreach ($valuesTmp as $v) { @@ -360,9 +360,9 @@ class FeedDAO extends Model_pdo { } public function updateLastUpdate ($id, $inError = 0) { - $sql = 'UPDATE ' . $this->prefix . 'feed f ' //2 sub-requests with FOREIGN KEY(e.id_feed), INDEX(e.is_read) faster than 1 request with GROUP BY or CASE - . 'SET f.cache_nbEntries=(SELECT COUNT(e1.id) FROM ' . $this->prefix . 'entry e1 WHERE e1.id_feed=f.id),' - . 'f.cache_nbUnreads=(SELECT COUNT(e2.id) FROM ' . $this->prefix . 'entry e2 WHERE e2.id_feed=f.id AND e2.is_read=0),' + $sql = 'UPDATE `' . $this->prefix . 'feed` f ' //2 sub-requests with FOREIGN KEY(e.id_feed), INDEX(e.is_read) faster than 1 request with GROUP BY or CASE + . 'SET f.cache_nbEntries=(SELECT COUNT(e1.id) FROM `' . $this->prefix . 'entry` e1 WHERE e1.id_feed=f.id),' + . 'f.cache_nbUnreads=(SELECT COUNT(e2.id) FROM `' . $this->prefix . 'entry` e2 WHERE e2.id_feed=f.id AND e2.is_read=0),' . 'lastUpdate=?, error=? ' . 'WHERE f.id=?'; @@ -390,7 +390,7 @@ class FeedDAO extends Model_pdo { $newCat = $catDAO->getDefault (); } - $sql = 'UPDATE ' . $this->prefix . 'feed SET category=? WHERE category=?'; + $sql = 'UPDATE `' . $this->prefix . 'feed` SET category=? WHERE category=?'; $stm = $this->bd->prepare ($sql); $values = array ( @@ -408,7 +408,7 @@ class FeedDAO extends Model_pdo { } public function deleteFeed ($id) { - $sql = 'DELETE FROM ' . $this->prefix . 'feed WHERE id=?'; + $sql = 'DELETE FROM `' . $this->prefix . 'feed` WHERE id=?'; $stm = $this->bd->prepare ($sql); $values = array ($id); @@ -422,7 +422,7 @@ class FeedDAO extends Model_pdo { } } public function deleteFeedByCategory ($id) { - $sql = 'DELETE FROM ' . $this->prefix . 'feed WHERE category=?'; + $sql = 'DELETE FROM `' . $this->prefix . 'feed` WHERE category=?'; $stm = $this->bd->prepare ($sql); $values = array ($id); @@ -437,7 +437,7 @@ class FeedDAO extends Model_pdo { } public function searchById ($id) { - $sql = 'SELECT * FROM ' . $this->prefix . 'feed WHERE id=?'; + $sql = 'SELECT * FROM `' . $this->prefix . 'feed` WHERE id=?'; $stm = $this->bd->prepare ($sql); $values = array ($id); @@ -453,7 +453,7 @@ class FeedDAO extends Model_pdo { } } public function searchByUrl ($url) { - $sql = 'SELECT * FROM ' . $this->prefix . 'feed WHERE url=?'; + $sql = 'SELECT * FROM `' . $this->prefix . 'feed` WHERE url=?'; $stm = $this->bd->prepare ($sql); $values = array ($url); @@ -470,7 +470,7 @@ class FeedDAO extends Model_pdo { } public function listFeeds () { - $sql = 'SELECT * FROM ' . $this->prefix . 'feed ORDER BY name'; + $sql = 'SELECT * FROM `' . $this->prefix . 'feed` ORDER BY name'; $stm = $this->bd->prepare ($sql); $stm->execute (); @@ -478,7 +478,7 @@ class FeedDAO extends Model_pdo { } public function listFeedsOrderUpdate () { - $sql = 'SELECT * FROM ' . $this->prefix . 'feed ORDER BY lastUpdate'; + $sql = 'SELECT * FROM `' . $this->prefix . 'feed` ORDER BY lastUpdate'; $stm = $this->bd->prepare ($sql); $stm->execute (); @@ -486,7 +486,7 @@ class FeedDAO extends Model_pdo { } public function listByCategory ($cat) { - $sql = 'SELECT * FROM ' . $this->prefix . 'feed WHERE category=? ORDER BY name'; + $sql = 'SELECT * FROM `' . $this->prefix . 'feed` WHERE category=? ORDER BY name'; $stm = $this->bd->prepare ($sql); $values = array ($cat); @@ -497,7 +497,7 @@ class FeedDAO extends Model_pdo { } public function countEntries ($id) { - $sql = 'SELECT COUNT(*) AS count FROM ' . $this->prefix . 'entry WHERE id_feed=?'; + $sql = 'SELECT COUNT(*) AS count FROM `' . $this->prefix . 'entry` WHERE id_feed=?'; $stm = $this->bd->prepare ($sql); $values = array ($id); $stm->execute ($values); @@ -506,7 +506,7 @@ class FeedDAO extends Model_pdo { return $res[0]['count']; } public function countNotRead ($id) { - $sql = 'SELECT COUNT(*) AS count FROM ' . $this->prefix . 'entry WHERE id_feed=? AND is_read=0'; + $sql = 'SELECT COUNT(*) AS count FROM `' . $this->prefix . 'entry` WHERE id_feed=? AND is_read=0'; $stm = $this->bd->prepare ($sql); $values = array ($id); $stm->execute ($values); @@ -515,12 +515,12 @@ class FeedDAO extends Model_pdo { return $res[0]['count']; } public function updateCachedValues () { //For one single feed, call updateLastUpdate($id) - $sql = 'UPDATE ' . $this->prefix . 'feed f ' + $sql = 'UPDATE `' . $this->prefix . 'feed` f ' . 'INNER JOIN (' . 'SELECT e.id_feed, ' . 'COUNT(CASE WHEN e.is_read = 0 THEN 1 END) AS nbUnreads, ' . 'COUNT(e.id) AS nbEntries ' - . 'FROM ' . $this->prefix . 'entry e ' + . 'FROM `' . $this->prefix . 'entry` e ' . 'GROUP BY e.id_feed' . ') x ON x.id_feed=f.id ' . 'SET f.cache_nbEntries=x.nbEntries, f.cache_nbUnreads=x.nbUnreads'; -- cgit v1.2.3 From a3f6bf966acf08be852a42c9dc24f001d17e7b16 Mon Sep 17 00:00:00 2001 From: Marien Fressinaud Date: Thu, 28 Nov 2013 22:45:36 +0100 Subject: Corrige bug URL favicons Corrige #278 --- app/models/Feed.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'app/models') diff --git a/app/models/Feed.php b/app/models/Feed.php index da1a029a8..7405768be 100644 --- a/app/models/Feed.php +++ b/app/models/Feed.php @@ -100,7 +100,8 @@ class Feed extends Model { $favicon_url = Url::display ($file); if (!file_exists (PUBLIC_PATH . $file)) { - $favicon_url = dowload_favicon ($this->website (), $this->id ()); + $base_url = dowload_favicon ($this->website (), $this->id ()); + $favicon_url = Url::display ($base_url); } return $favicon_url; -- cgit v1.2.3 From dd61248d319e3f74a3670f5e15bc1e1ab2c2ae1a Mon Sep 17 00:00:00 2001 From: Marien Fressinaud Date: Thu, 28 Nov 2013 22:50:34 +0100 Subject: Correction download_favicon MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit En fait renvoyer l'url ne servait à rien puisque c'était la même De plus il y avait une faute de typo dans le nom de la fonction Voir #278 --- app/models/Feed.php | 3 +-- lib/lib_rss.php | 5 +---- 2 files changed, 2 insertions(+), 6 deletions(-) (limited to 'app/models') diff --git a/app/models/Feed.php b/app/models/Feed.php index d4ff00e21..2260f6fdf 100644 --- a/app/models/Feed.php +++ b/app/models/Feed.php @@ -100,8 +100,7 @@ class Feed extends Model { $favicon_url = Url::display ($file); if (!file_exists (PUBLIC_PATH . $file)) { - $base_url = dowload_favicon ($this->website (), $this->id ()); - $favicon_url = Url::display ($base_url); + download_favicon ($this->website (), $this->id ()); } return $favicon_url; diff --git a/lib/lib_rss.php b/lib/lib_rss.php index 5a74bfd0a..08e65a45f 100644 --- a/lib/lib_rss.php +++ b/lib/lib_rss.php @@ -181,11 +181,10 @@ function get_content_by_parsing ($url, $path) { } /* Télécharge le favicon d'un site, le place sur le serveur et retourne l'URL */ -function dowload_favicon ($website, $id) { +function download_favicon ($website, $id) { $url = 'http://g.etfv.co/' . $website; $favicons_dir = PUBLIC_PATH . '/favicons'; $dest = $favicons_dir . '/' . $id . '.ico'; - $favicon_url = '/favicons/' . $id . '.ico'; if (!is_dir ($favicons_dir)) { if (!mkdir ($favicons_dir, 0755, true)) { @@ -214,8 +213,6 @@ function dowload_favicon ($website, $id) { curl_close ($c); } - - return $favicon_url; } /** -- cgit v1.2.3 From 69662117a31bed413d71a4636257fcd44a51384d Mon Sep 17 00:00:00 2001 From: Marien Fressinaud Date: Thu, 28 Nov 2013 23:46:56 +0100 Subject: Ajoute raccourci load more MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Permet de charger les articles suivants en appuyant sur "m" (par défaut) --- app/controllers/configureController.php | 3 ++- app/models/RSSConfiguration.php | 1 + app/views/configure/shortcut.phtml | 7 +++++++ app/views/helpers/javascript_vars.phtml | 3 ++- public/scripts/main.js | 6 ++++++ 5 files changed, 18 insertions(+), 2 deletions(-) (limited to 'app/models') diff --git a/app/controllers/configureController.php b/app/controllers/configureController.php index 4c9ceebbc..af6140b5d 100755 --- a/app/controllers/configureController.php +++ b/app/controllers/configureController.php @@ -373,7 +373,8 @@ class configureController extends ActionController { 'f10', 'f11', 'f12'); $this->view->list_keys = $list_keys; $list_names = array ('mark_read', 'mark_favorite', 'go_website', 'next_entry', - 'prev_entry', 'next_page', 'prev_page', 'collapse_entry'); + 'prev_entry', 'next_page', 'prev_page', 'collapse_entry', + 'load_more'); if (Request::isPost ()) { $shortcuts = Request::param ('shortcuts'); diff --git a/app/models/RSSConfiguration.php b/app/models/RSSConfiguration.php index fe6cd48d3..37f26b1dd 100755 --- a/app/models/RSSConfiguration.php +++ b/app/models/RSSConfiguration.php @@ -343,6 +343,7 @@ class RSSConfigurationDAO extends Model_array { 'next_entry' => 'j', 'prev_entry' => 'k', 'collapse_entry' => 'c', + 'load_more' => 'm' ); public $mail_login = ''; public $mark_when = array ( diff --git a/app/views/configure/shortcut.phtml b/app/views/configure/shortcut.phtml index 37aa3accc..ac33a869a 100644 --- a/app/views/configure/shortcut.phtml +++ b/app/views/configure/shortcut.phtml @@ -61,6 +61,13 @@
    +
    + +
    + +
    +
    +
    diff --git a/app/views/helpers/javascript_vars.phtml b/app/views/helpers/javascript_vars.phtml index ddebfd876..d6c2550f5 100644 --- a/app/views/helpers/javascript_vars.phtml +++ b/app/views/helpers/javascript_vars.phtml @@ -17,7 +17,8 @@ 'go_website:"', $s['go_website'], '",', 'prev_entry:"', $s['prev_entry'], '",', 'next_entry:"', $s['next_entry'], '",', - 'collapse_entry:"', $s['collapse_entry'], '"', + 'collapse_entry:"', $s['collapse_entry'], '",', + 'load_more:"', $s['load_more'], '"', "},\n"; if (Request::param ('output') === 'global') { diff --git a/public/scripts/main.js b/public/scripts/main.js index 022d0091b..89effc884 100644 --- a/public/scripts/main.js +++ b/public/scripts/main.js @@ -381,6 +381,12 @@ function init_shortcuts() { }, { 'disable_in_input': true }); + + shortcut.add(shortcuts.load_more, function () { + load_more_posts(); + }, { + 'disable_in_input': true + }); } function init_stream_delegates(divStream) { -- cgit v1.2.3 From e98b7ab13ec414d1c5c3c3d1d6a7c9995ebf4fea Mon Sep 17 00:00:00 2001 From: Alexandre Alapetite Date: Sat, 30 Nov 2013 13:15:54 +0100 Subject: SQL : compression côté base de données (attention, perte de compatibilité) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Ça y est, j'ai tout cassé... Contribue à https://github.com/marienfressinaud/FreshRSS/issues/204 Compatible MySQL 5.0. Commentaires souhaités avant l'implémentation de la recherche côté base de données. Pour l'instant, je n'ai pas fait de script de mise à jour, car la manière précédente `base64_encode(gzdeflate(serialize($content)))` est difficile à traiter côté MySQL et nécessite une boucle en PHP. Avec la nouvelle approche de ce patch, nous pourrons plus facilement changer d'avis sans perte de compatibilité. --- README.md | 2 +- app/models/Entry.php | 82 +++++++++------------------------------------ app/models/Feed.php | 22 ++++++++++++ app/models/RSSPaginator.php | 2 +- public/install.php | 13 ++++--- 5 files changed, 48 insertions(+), 73 deletions(-) (limited to 'app/models') diff --git a/README.md b/README.md index fb0b9e61e..fb4793e2d 100644 --- a/README.md +++ b/README.md @@ -22,7 +22,7 @@ Privilégiez pour cela des demandes sur GitHub * PHP 5.2+ (PHP 5.3.3+ recommandé) * Requis : [libxml](http://php.net/xml), [cURL](http://php.net/curl), [PDO_MySQL](http://php.net/pdo-mysql) * Recommandés : [Zlib](http://php.net/zlib), [mbstring](http://php.net/mbstring), [iconv](http://php.net/iconv) -* MySQL 5.0.3+ (SQLite à venir) +* MySQL 5.0.3+ (ou SQLite 3.7.4+ à venir) * Un navigateur Web récent tel Firefox, Chrome, Opera, Safari, Internet Explorer 9+ * Fonctionne aussi sur mobile diff --git a/app/models/Entry.php b/app/models/Entry.php index 739c2a582..894985ece 100755 --- a/app/models/Entry.php +++ b/app/models/Entry.php @@ -199,7 +199,8 @@ class Entry extends Model { class EntryDAO extends Model_pdo { public function addEntry ($valuesTmp) { - $sql = 'INSERT INTO `' . $this->prefix . 'entry`(id, guid, title, author, content, link, date, is_read, is_favorite, id_feed, tags) VALUES(CAST(? * 1000000 AS SIGNED INTEGER), ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)'; + $sql = 'INSERT INTO `' . $this->prefix . 'entry`(id, guid, title, author, content_bin, link, date, is_read, is_favorite, id_feed, tags) ' + . 'VALUES(CAST(? * 1000000 AS SIGNED INTEGER), ?, ?, ?, COMPRESS(?), ?, ?, ?, ?, ?, ?)'; $stm = $this->bd->prepare ($sql); $values = array ( @@ -207,7 +208,7 @@ class EntryDAO extends Model_pdo { substr($valuesTmp['guid'], 0, 760), substr($valuesTmp['title'], 0, 255), substr($valuesTmp['author'], 0, 255), - base64_encode (gzdeflate (serialize ($valuesTmp['content']))), + $valuesTmp['content'], substr($valuesTmp['link'], 0, 1023), $valuesTmp['date'], $valuesTmp['is_read'], @@ -231,33 +232,6 @@ class EntryDAO extends Model_pdo { } } - /*public function updateEntry ($id, $valuesTmp) { - if (isset ($valuesTmp['content'])) { - $valuesTmp['content'] = base64_encode (gzdeflate (serialize ($valuesTmp['content']))); - } - - $set = ''; - foreach ($valuesTmp as $key => $v) { - $set .= $key . '=?, '; - } - $set = substr ($set, 0, -2); - - $sql = 'UPDATE `' . $this->prefix . 'entry` SET ' . $set . ' WHERE id=?'; - $stm = $this->bd->prepare ($sql); - - foreach ($valuesTmp as $v) { - $values[] = $v; - } - $values[] = $id; - - if ($stm && $stm->execute ($values)) { - return $stm->rowCount(); - } else { - $info = $stm->errorInfo(); - Minz_Log::record ('SQL error : ' . $info[2], Minz_Log::ERROR); - return false; - } - }*/ public function markFavorite ($id, $is_favorite = true) { $sql = 'UPDATE `' . $this->prefix . 'entry` e ' . 'SET e.is_favorite = ? ' @@ -443,35 +417,9 @@ class EntryDAO extends Model_pdo { } } - /*public function updateEntries ($valuesTmp) { - if (isset ($valuesTmp['content'])) { - $valuesTmp['content'] = base64_encode (gzdeflate (serialize ($valuesTmp['content']))); - } - - $set = ''; - foreach ($valuesTmp as $key => $v) { - $set .= $key . '=?, '; - } - $set = substr ($set, 0, -2); - - $sql = 'UPDATE `' . $this->prefix . 'entry` SET ' . $set; - $stm = $this->bd->prepare ($sql); - - foreach ($valuesTmp as $v) { - $values[] = $v; - } - - if ($stm && $stm->execute ($values)) { - return $stm->rowCount(); - } else { - $info = $stm->errorInfo(); - Minz_Log::record ('SQL error : ' . $info[2], Minz_Log::ERROR); - return false; - } - }*/ - public function cleanOldEntries ($date_min) { - $sql = 'DELETE e.* FROM `' . $this->prefix . 'entry` e INNER JOIN `' . $this->prefix . 'feed` f ON e.id_feed = f.id WHERE e.id <= ? AND e.is_favorite = 0 AND f.keep_history = 0'; + $sql = 'DELETE e.* FROM `' . $this->prefix . 'entry` e INNER JOIN `' . $this->prefix . 'feed` f ON e.id_feed = f.id ' + . 'WHERE e.id <= ? AND e.is_favorite = 0 AND f.keep_history = 0'; $stm = $this->bd->prepare ($sql); $values = array ( @@ -489,7 +437,8 @@ class EntryDAO extends Model_pdo { public function searchByGuid ($feed_id, $id) { // un guid est unique pour un flux donné - $sql = 'SELECT * FROM `' . $this->prefix . 'entry` WHERE id_feed=? AND guid=?'; + $sql = 'SELECT id, guid, title, author, UNCOMPRESS(content_bin) AS content, link, date, is_read, is_favorite, id_feed, tags ' + . 'FROM `' . $this->prefix . 'entry` WHERE id_feed=? AND guid=?'; $stm = $this->bd->prepare ($sql); $values = array ( @@ -509,7 +458,8 @@ class EntryDAO extends Model_pdo { } public function searchById ($id) { - $sql = 'SELECT * FROM `' . $this->prefix . 'entry` WHERE id=?'; + $sql = 'SELECT id, guid, title, author, UNCOMPRESS(content_bin) AS content, link, date, is_read, is_favorite, id_feed, tags ' + . 'FROM `' . $this->prefix . 'entry` WHERE id=?'; $stm = $this->bd->prepare ($sql); $values = array ($id); @@ -541,8 +491,9 @@ class EntryDAO extends Model_pdo { $order = ''; } - $sql = 'SELECT e.* FROM `' . $this->prefix . 'entry` e' - . ' INNER JOIN `' . $this->prefix . 'feed` f ON e.id_feed = f.id' . $where + $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; if (empty($limitCount)) { @@ -558,16 +509,16 @@ class EntryDAO extends Model_pdo { 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); + 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); + 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)); + 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)); + return $this->listWhere ('WHERE id_feed = ?', $state, $order, $limitFromId, $limitCount, array ($feed)); } public function listLastGuidsByFeed($id, $n) { @@ -648,7 +599,6 @@ class HelperEntry { $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) && diff --git a/app/models/Feed.php b/app/models/Feed.php index 2260f6fdf..954d1d45c 100644 --- a/app/models/Feed.php +++ b/app/models/Feed.php @@ -408,6 +408,16 @@ class FeedDAO extends Model_pdo { } public function deleteFeed ($id) { + /*//For MYISAM (MySQL 5.5-) without FOREIGN KEY + $sql = 'DELETE FROM `' . $this->prefix . 'entry` WHERE id_feed=?'; + $stm = $this->bd->prepare ($sql); + $values = array ($id); + if (!($stm && $stm->execute ($values))) { + $info = $stm->errorInfo(); + Minz_Log::record ('SQL error : ' . $info[2], Minz_Log::ERROR); + return false; + }*/ + $sql = 'DELETE FROM `' . $this->prefix . 'feed` WHERE id=?'; $stm = $this->bd->prepare ($sql); @@ -422,6 +432,18 @@ class FeedDAO extends Model_pdo { } } public function deleteFeedByCategory ($id) { + /*//For MYISAM (MySQL 5.5-) without FOREIGN KEY + $sql = 'DELETE FROM `' . $this->prefix . 'entry` e ' + . 'INNER JOIN `' . $this->prefix . 'feed` f ON e.id_feed = f.id ' + . 'WHERE f.category=?'; + $stm = $this->bd->prepare ($sql); + $values = array ($id); + if (!($stm && $stm->execute ($values))) { + $info = $stm->errorInfo(); + Minz_Log::record ('SQL error : ' . $info[2], Minz_Log::ERROR); + return false; + }*/ + $sql = 'DELETE FROM `' . $this->prefix . 'feed` WHERE category=?'; $stm = $this->bd->prepare ($sql); diff --git a/app/models/RSSPaginator.php b/app/models/RSSPaginator.php index 60d2a06ac..39146f1ba 100644 --- a/app/models/RSSPaginator.php +++ b/app/models/RSSPaginator.php @@ -24,7 +24,7 @@ class RSSPaginator { } public function peek () { - return empty($this->items) ? null : $this->items[0]; + return isset($this->items[0]) ? $this->items[0] : null; } public function render ($view, $getteur) { diff --git a/public/install.php b/public/install.php index 764d152f5..0701c8c1f 100644 --- a/public/install.php +++ b/public/install.php @@ -18,7 +18,8 @@ define ('SQL_REQ_CAT', 'CREATE TABLE IF NOT EXISTS `%scategory` ( `color` char(7) NOT NULL, PRIMARY KEY (`id`), UNIQUE KEY (`name`) -- v0.7 -) DEFAULT CHARACTER SET utf8 COLLATE utf8_unicode_ci;'); +) DEFAULT CHARACTER SET utf8 COLLATE utf8_unicode_ci +ENGINE = INNODB;'); define ('SQL_REQ_FEED', 'CREATE TABLE IF NOT EXISTS `%sfeed` ( `id` SMALLINT NOT NULL AUTO_INCREMENT, -- v0.7 @@ -41,14 +42,15 @@ define ('SQL_REQ_FEED', 'CREATE TABLE IF NOT EXISTS `%sfeed` ( INDEX (`name`), -- v0.7 INDEX (`priority`), -- v0.7 INDEX (`keep_history`) -- v0.7 -) DEFAULT CHARACTER SET utf8 COLLATE utf8_unicode_ci;'); +) DEFAULT CHARACTER SET utf8 COLLATE utf8_unicode_ci +ENGINE = INNODB;'); define ('SQL_REQ_ENTRY', 'CREATE TABLE IF NOT EXISTS `%sentry` ( `id` bigint NOT NULL, -- v0.7 `guid` varchar(760) CHARACTER SET latin1 NOT NULL, -- Maximum for UNIQUE is 767B `title` varchar(255) NOT NULL, `author` varchar(255) NOT NULL, - `content` text NOT NULL, + `content_bin` blob NOT NULL, -- v0.7 `link` varchar(1023) CHARACTER SET latin1 NOT NULL, `date` int(11) NOT NULL, `is_read` boolean NOT NULL DEFAULT 0, @@ -59,8 +61,9 @@ define ('SQL_REQ_ENTRY', 'CREATE TABLE IF NOT EXISTS `%sentry` ( FOREIGN KEY (`id_feed`) REFERENCES `%sfeed`(`id`) ON DELETE CASCADE ON UPDATE CASCADE, UNIQUE KEY (`id_feed`,`guid`), -- v0.7 INDEX (`is_favorite`), -- v0.7 - INDEX (`is_read`) -- v0.7 -) DEFAULT CHARACTER SET utf8 COLLATE utf8_unicode_ci;'); + INDEX (`is_read`), -- v0.7 +) DEFAULT CHARACTER SET utf8 COLLATE utf8_unicode_ci +ENGINE = INNODB;'); function writeLine ($f, $line) { -- 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') 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 From 1e077160fca3306a273ecae5a366fd756c32baee Mon Sep 17 00:00:00 2001 From: Alexandre Alapetite Date: Sat, 30 Nov 2013 22:47:48 +0100 Subject: Optimisation recherche et pagination MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Optimisation recherche SQL avec utilisation de HAVING plutôt que WHERE * Simplification et amélioration des performances en supprimant de RSSPaginator qui n'aidait plus vraiment et nécessitait plus de code et des copies de données. * Correction d'un bug dans le titre de la page introduit récemment, et simplification --- app/App_FrontController.php | 1 - app/controllers/indexController.php | 33 +++++++++++++--------------- app/layout/layout.phtml | 5 ++--- app/layout/nav_menu.phtml | 4 ++-- app/models/Entry.php | 11 +++++++--- app/models/RSSPaginator.php | 37 -------------------------------- app/views/helpers/pagination.phtml | 4 ++-- app/views/helpers/view/normal_view.phtml | 8 +++---- app/views/helpers/view/reader_view.phtml | 7 +++--- app/views/helpers/view/rss_view.phtml | 3 +-- 10 files changed, 36 insertions(+), 77 deletions(-) delete mode 100644 app/models/RSSPaginator.php (limited to 'app/models') diff --git a/app/App_FrontController.php b/app/App_FrontController.php index d701e2944..176677781 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/RSSPaginator.php'); include (APP_PATH . '/models/Log_Model.php'); } diff --git a/app/controllers/indexController.php b/app/controllers/indexController.php index cf0e5024a..b3ae40847 100755 --- a/app/controllers/indexController.php +++ b/app/controllers/indexController.php @@ -46,8 +46,6 @@ class indexController extends ActionController { 'params' => $params ); - $this->view->rss_title = View::title(); - if ($output === 'rss') { // no layout for RSS output $this->view->_useLayout (false); @@ -67,19 +65,6 @@ class indexController extends ActionController { $this->view->get_c = ''; $this->view->get_f = ''; - // mise à jour des titres - $this->view->nb_not_read = HelperCategory::CountUnreads($this->view->cat_aside, 1); - if ($this->view->nb_not_read > 0) { - View::appendTitle (' (' . $this->view->nb_not_read . ')'); - } - View::prependTitle (' - '); - - $this->view->rss_title = $this->view->currentName . ' - ' . $this->view->rss_title; - View::prependTitle ( - $this->view->currentName . - ($this->nb_not_read_cat > 0 ? ' (' . $this->nb_not_read_cat . ')' : '') - ); - $get = Request::param ('get', 'a'); $getType = $get[0]; $getId = substr ($get, 2); @@ -92,6 +77,18 @@ class indexController extends ActionController { return; } + $this->view->nb_not_read = HelperCategory::CountUnreads($this->view->cat_aside, 1); + + // mise à jour des titres + if ($this->view->nb_not_read > 0) { + View::appendTitle (' (' . $this->view->nb_not_read . ')'); + } + View::prependTitle ( + $this->view->currentName . + ($this->nb_not_read_cat > 0 ? ' (' . $this->nb_not_read_cat . ')' : '') . + ' - ' + ); + // 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', ''); @@ -138,13 +135,13 @@ class indexController extends ActionController { } if (count($entries) <= $nb) { - $next = ''; + $this->view->nextId = ''; } else { //We have more elements for pagination $lastEntry = array_pop($entries); - $next = $lastEntry->id(); + $this->view->nextId = $lastEntry->id(); } - $this->view->entryPaginator = new RSSPaginator ($entries, $next); + $this->view->entries = $entries; } catch (EntriesGetterException $e) { Minz_Log::record ($e->getMessage (), Minz_Log::NOTICE); Error::error ( diff --git a/app/layout/layout.phtml b/app/layout/layout.phtml index 9b502275c..6fc5c1cf0 100644 --- a/app/layout/layout.phtml +++ b/app/layout/layout.phtml @@ -10,10 +10,9 @@ renderHelper ('javascript_vars'); ?> //]]> entryPaginator) ? $this->entryPaginator->next() : ''; - if (!empty($next)) { + if (!empty($this->nextId)) { $params = Request::params (); - $params['next'] = $next; + $params['next'] = $this->nextId; ?> diff --git a/app/layout/nav_menu.phtml b/app/layout/nav_menu.phtml index 289fe6542..4b4945108 100644 --- a/app/layout/nav_menu.phtml +++ b/app/layout/nav_menu.phtml @@ -17,8 +17,6 @@ $string_mark = Translate::t ('mark_cat_read'); } $nextGet = $get; - $p = $this->entryPaginator->peek(); - $idMax = $p === null ? '0' : $p->id(); if (($this->conf->onread_jump_next () === 'yes') && (strlen ($get) > 2)) { $anotherUnreadId = ''; $foundCurrent = false; @@ -54,6 +52,8 @@ break; } } + $p = isset($this->entries[0]) ? $this->entries[0] : null; + $idMax = $p === null ? '0' : $p->id(); $markReadUrl = _url ('entry', 'read', 'is_read', 1, 'get', $get, 'nextGet', $nextGet, 'idMax', $idMax); Session::_param ('markReadUrl', $markReadUrl); ?> diff --git a/app/models/Entry.php b/app/models/Entry.php index 915fbccc8..ae8facf68 100755 --- a/app/models/Entry.php +++ b/app/models/Entry.php @@ -504,14 +504,18 @@ class EntryDAO extends Model_pdo { if ($firstId > 0) { $where .= 'AND e.id ' . ($order === 'DESC' ? '<=' : '>=') . $firstId . ' '; } - $terms = explode(' ', trim($filter)); + $terms = array_unique(explode(' ', trim($filter))); sort($terms); //Put #tags first + $having = ''; foreach ($terms as $word) { if (!empty($word)) { if ($word[0] === '#' && isset($word[1])) { - $where .= 'AND tags LIKE "%' . $word . '%" '; + $having .= 'AND tags LIKE ? '; + $values[] = '%' . $word .'%'; } elseif (!empty($word)) { - $where .= 'AND (e.title LIKE "%' . $word . '%" OR UNCOMPRESS(e.content_bin) LIKE "%' . $word . '%") '; + $having .= 'AND (e.title LIKE ? OR content LIKE ?) '; + $values[] = '%' . $word .'%'; + $values[] = '%' . $word .'%'; } } } @@ -519,6 +523,7 @@ class EntryDAO extends Model_pdo { $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 ' . $where + . (empty($having) ? '' : 'HAVING' . substr($having, 3)) . 'ORDER BY e.id ' . $order; if ($limit > 0) { diff --git a/app/models/RSSPaginator.php b/app/models/RSSPaginator.php deleted file mode 100644 index 39146f1ba..000000000 --- a/app/models/RSSPaginator.php +++ /dev/null @@ -1,37 +0,0 @@ -items = $items; - $this->next = $next; - } - - public function isEmpty () { - return empty ($this->items); - } - - public function items () { - return $this->items; - } - - public function next () { - return $this->next; - } - - public function peek () { - return isset($this->items[0]) ? $this->items[0] : null; - } - - public function render ($view, $getteur) { - $view = APP_PATH . '/views/helpers/'.$view; - - if (file_exists ($view)) { - include ($view); - } - } -} diff --git a/app/views/helpers/pagination.phtml b/app/views/helpers/pagination.phtml index 0b0d2f5ba..408cfca1b 100755 --- a/app/views/helpers/pagination.phtml +++ b/app/views/helpers/pagination.phtml @@ -8,8 +8,8 @@
    -- cgit v1.2.3 From 018273e2720c481c699ecc5cca1cdc90599921f7 Mon Sep 17 00:00:00 2001 From: Alexandre Alapetite Date: Tue, 3 Dec 2013 22:53:51 +0100 Subject: Corrige bug marquer tous les favoris comme lus Corrige https://github.com/marienfressinaud/FreshRSS/issues/270 --- app/controllers/entryController.php | 21 ++++++++++++++------- app/layout/nav_menu.phtml | 10 ++++++---- app/models/Entry.php | 8 +++++++- 3 files changed, 27 insertions(+), 12 deletions(-) (limited to 'app/models') diff --git a/app/controllers/entryController.php b/app/controllers/entryController.php index d92eb0ed3..d3159c4c3 100755 --- a/app/controllers/entryController.php +++ b/app/controllers/entryController.php @@ -47,14 +47,21 @@ class entryController extends ActionController { } else { $typeGet = $get[0]; $get = substr ($get, 2); - - if ($typeGet == 'c') { - $entryDAO->markReadCat ($get, $idMax); - $this->params = array ('get' => $nextGet); - } elseif ($typeGet == 'f') { - $entryDAO->markReadFeed ($get, $idMax); - $this->params = array ('get' => $nextGet); + switch ($typeGet) { + case 'c': + $entryDAO->markReadCat ($get, $idMax); + break; + case 'f': + $entryDAO->markReadFeed ($get, $idMax); + break; + case 's': + $entryDAO->markReadEntries ($idMax, true); + break; + case 'a': + $entryDAO->markReadEntries ($idMax); + break; } + $this->params = array ('get' => $nextGet); } $notif = array ( diff --git a/app/layout/nav_menu.phtml b/app/layout/nav_menu.phtml index c71497ced..5154b4aae 100644 --- a/app/layout/nav_menu.phtml +++ b/app/layout/nav_menu.phtml @@ -10,10 +10,12 @@ if ($this->get_f) { $get = 'f_' . $this->get_f; $string_mark = Translate::t ('mark_feed_read'); - } elseif ($this->get_c && - $this->get_c != 'a' && - $this->get_c != 's') { - $get = 'c_' . $this->get_c; + } elseif ($this->get_c && $this->get_c != 'a') { + if ($this->get_c === 's') { + $get = 's'; + } else { + $get = 'c_' . $this->get_c; + } $string_mark = Translate::t ('mark_cat_read'); } $nextGet = $get; diff --git a/app/models/Entry.php b/app/models/Entry.php index 899e98b00..6c37c3d6e 100755 --- a/app/models/Entry.php +++ b/app/models/Entry.php @@ -257,11 +257,14 @@ class EntryDAO extends Model_pdo { return false; } } - public function markReadEntries ($idMax = 0) { + public function markReadEntries ($idMax = 0, $onlyFavorites = false) { if ($idMax === 0) { $sql = 'UPDATE `' . $this->prefix . 'entry` e INNER JOIN `' . $this->prefix . 'feed` f ON e.id_feed = f.id ' . 'SET e.is_read = 1, f.cache_nbUnreads=0 ' . 'WHERE e.is_read = 0 AND f.priority > 0'; + if ($onlyFavorites) { + $sql .= ' AND e.is_favorite = 1'; + } $stm = $this->bd->prepare ($sql); if ($stm && $stm->execute ()) { return $stm->rowCount(); @@ -276,6 +279,9 @@ class EntryDAO extends Model_pdo { $sql = 'UPDATE `' . $this->prefix . 'entry` e INNER JOIN `' . $this->prefix . 'feed` f ON e.id_feed = f.id ' . 'SET e.is_read = 1 ' . 'WHERE e.is_read = 0 AND e.id <= ? AND f.priority > 0'; + if ($onlyFavorites) { + $sql .= ' AND e.is_favorite = 1'; + } $values = array ($idMax); $stm = $this->bd->prepare ($sql); if (!($stm && $stm->execute ($values))) { -- cgit v1.2.3 From e177b288f5125f9a34059ae8111d02c7f6d51c61 Mon Sep 17 00:00:00 2001 From: Alexandre Alapetite Date: Tue, 3 Dec 2013 23:15:20 +0100 Subject: Corrige bug marquage favoris pour f.priority = 0 https://github.com/marienfressinaud/FreshRSS/issues/270 --- app/models/Entry.php | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) (limited to 'app/models') diff --git a/app/models/Entry.php b/app/models/Entry.php index 6c37c3d6e..33d0c66bb 100755 --- a/app/models/Entry.php +++ b/app/models/Entry.php @@ -257,13 +257,15 @@ class EntryDAO extends Model_pdo { return false; } } - public function markReadEntries ($idMax = 0, $onlyFavorites = false) { + public function markReadEntries ($idMax = 0, $favorites = false) { if ($idMax === 0) { $sql = 'UPDATE `' . $this->prefix . 'entry` e INNER JOIN `' . $this->prefix . 'feed` f ON e.id_feed = f.id ' . 'SET e.is_read = 1, f.cache_nbUnreads=0 ' - . 'WHERE e.is_read = 0 AND f.priority > 0'; - if ($onlyFavorites) { - $sql .= ' AND e.is_favorite = 1'; + . 'WHERE e.is_read = 0 AND '; + if ($favorites) { + $sql .= 'e.is_favorite = 1'; + } else { + $sql .= 'f.priority > 0'; } $stm = $this->bd->prepare ($sql); if ($stm && $stm->execute ()) { @@ -278,9 +280,11 @@ class EntryDAO extends Model_pdo { $sql = 'UPDATE `' . $this->prefix . 'entry` e INNER JOIN `' . $this->prefix . 'feed` f ON e.id_feed = f.id ' . 'SET e.is_read = 1 ' - . 'WHERE e.is_read = 0 AND e.id <= ? AND f.priority > 0'; - if ($onlyFavorites) { - $sql .= ' AND e.is_favorite = 1'; + . 'WHERE e.is_read = 0 AND e.id <= ? AND '; + if ($favorites) { + $sql .= 'e.is_favorite = 1'; + } else { + $sql .= 'f.priority > 0'; } $values = array ($idMax); $stm = $this->bd->prepare ($sql); -- cgit v1.2.3 From e45357a91b9aa47d5b7ead14c174dc7c98ab9926 Mon Sep 17 00:00:00 2001 From: Alexandre Alapetite Date: Wed, 4 Dec 2013 20:48:53 +0100 Subject: Support contrôlé de iframe, audio, video MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Et filtrage de object, embed https://github.com/marienfressinaud/FreshRSS/issues/188 On ajoute un paramètre preload="none" à audio et video, ainsi qu'un paramètre sandbox="allow-scripts allow-same-origin" aux iframe. On interdit les paramètres autoplay et seamless de audio et video. Ré-écriture des URLS de l'attribut poster de video, ainsi que de l'attribut src de iframe. Suite de https://github.com/marienfressinaud/FreshRSS/issues/267 Au passage, filtrage du vieil élément PLAINTEXT. Modifications dans SimplePie. --- app/models/Feed.php | 16 +++++++---- lib/SimplePie/SimplePie/Sanitize.php | 53 +++++++++++++++++++++++++++++++----- 2 files changed, 56 insertions(+), 13 deletions(-) (limited to 'app/models') diff --git a/app/models/Feed.php b/app/models/Feed.php index 555759c9a..88833c706 100644 --- a/app/models/Feed.php +++ b/app/models/Feed.php @@ -204,15 +204,15 @@ class Feed extends Model { $feed->set_cache_location (CACHE_PATH); $feed->set_cache_duration(1500); $feed->strip_htmltags (array ( - 'base', 'blink', 'body', 'doctype', + 'base', 'blink', 'body', 'doctype', 'embed', 'font', 'form', 'frame', 'frameset', 'html', 'input', 'marquee', 'meta', 'noscript', - 'param', 'script', 'style' + 'object', 'param', 'plaintext', 'script', 'style', )); $feed->strip_attributes(array_merge($feed->strip_attributes, array( - 'onload', 'onunload', 'onclick', 'ondblclick', 'onmousedown', 'onmouseup', + 'autoplay', 'onload', 'onunload', 'onclick', 'ondblclick', 'onmousedown', 'onmouseup', 'onmouseover', 'onmousemove', 'onmouseout', 'onfocus', 'onblur', - 'onkeypress', 'onkeydown', 'onkeyup', 'onselect', 'onchange'))); + 'onkeypress', 'onkeydown', 'onkeyup', 'onselect', 'onchange', 'seamless'))); $feed->set_url_replacements(array( 'a' => 'href', 'area' => 'href', @@ -220,6 +220,7 @@ class Feed extends Model { 'blockquote' => 'cite', 'del' => 'cite', 'form' => 'action', + 'iframe' => 'src', 'img' => array( 'longdesc', 'src' @@ -229,7 +230,10 @@ class Feed extends Model { 'q' => 'cite', 'source' => 'src', 'track' => 'src', - 'video' => 'src', + 'video' => array( + 'poster', + 'src', + ), )); $feed->init (); @@ -581,7 +585,7 @@ class HelperFeed { $myFeed = new Feed (isset($dao['url']) ? $dao['url'] : '', false); $myFeed->_category ($catID === null ? $dao['category'] : $catID); $myFeed->_name ($dao['name']); - $myFeed->_website ($dao['website']); + $myFeed->_website ($dao['website'], false); $myFeed->_description (isset($dao['description']) ? $dao['description'] : ''); $myFeed->_lastUpdate (isset($dao['lastUpdate']) ? $dao['lastUpdate'] : 0); $myFeed->_priority ($dao['priority']); diff --git a/lib/SimplePie/SimplePie/Sanitize.php b/lib/SimplePie/SimplePie/Sanitize.php index 83a274ced..0974c150d 100644 --- a/lib/SimplePie/SimplePie/Sanitize.php +++ b/lib/SimplePie/SimplePie/Sanitize.php @@ -62,6 +62,7 @@ class SimplePie_Sanitize var $strip_htmltags = array('base', 'blink', 'body', 'doctype', 'embed', 'font', 'form', 'frame', 'frameset', 'html', 'iframe', 'input', 'marquee', 'meta', 'noscript', 'object', 'param', 'script', 'style'); var $encode_instead_of_strip = false; var $strip_attributes = array('bgsound', 'class', 'expr', 'id', 'style', 'onclick', 'onerror', 'onfinish', 'onmouseover', 'onmouseout', 'onfocus', 'onblur', 'lowsrc', 'dynsrc'); + var $add_attributes = array('audio' => array('preload' => 'none'), 'iframe' => array('sandbox' => 'allow-scripts allow-same-origin'), 'video' => array('preload' => 'none')); //FreshRSS var $strip_comments = false; var $output_encoding = 'UTF-8'; var $enable_cache = true; @@ -179,6 +180,25 @@ class SimplePie_Sanitize } } + public function add_attributes($attribs = array('audio' => array('preload' => 'none'), 'iframe' => array('sandbox' => 'allow-scripts allow-same-origin'), 'video' => array('preload' => 'none'))) + { + if ($attribs) + { + if (is_array($attribs)) + { + $this->add_attributes = $attribs; + } + else + { + $this->add_attributes = explode(',', $attribs); + } + } + else + { + $this->add_attributes = false; + } + } + public function strip_comments($strip = false) { $this->strip_comments = (bool) $strip; @@ -255,10 +275,11 @@ class SimplePie_Sanitize $document->loadHTML($data); restore_error_handler(); + $xpath = new DOMXPath($document); //FreshRSS + // Strip comments if ($this->strip_comments) { - $xpath = new DOMXPath($document); $comments = $xpath->query('//comment()'); foreach ($comments as $comment) @@ -274,7 +295,7 @@ class SimplePie_Sanitize { foreach ($this->strip_htmltags as $tag) { - $this->strip_tag($tag, $document, $type); + $this->strip_tag($tag, $document, $xpath, $type); } } @@ -282,7 +303,15 @@ class SimplePie_Sanitize { foreach ($this->strip_attributes as $attrib) { - $this->strip_attr($attrib, $document); + $this->strip_attr($attrib, $xpath); + } + } + + if ($this->add_attributes) + { + foreach ($this->add_attributes as $tag => $valuePairs) + { + $this->add_attr($tag, $valuePairs, $document); } } @@ -452,9 +481,8 @@ class SimplePie_Sanitize } } - protected function strip_tag($tag, $document, $type) + protected function strip_tag($tag, $document, $xpath, $type) { - $xpath = new DOMXPath($document); $elements = $xpath->query('body//' . $tag); if ($this->encode_instead_of_strip) { @@ -537,9 +565,8 @@ class SimplePie_Sanitize } } - protected function strip_attr($attrib, $document) + protected function strip_attr($attrib, $xpath) { - $xpath = new DOMXPath($document); $elements = $xpath->query('//*[@' . $attrib . ']'); foreach ($elements as $element) @@ -547,4 +574,16 @@ class SimplePie_Sanitize $element->removeAttribute($attrib); } } + + protected function add_attr($tag, $valuePairs, $document) + { + $elements = $document->getElementsByTagName($tag); + foreach ($elements as $element) + { + foreach ($valuePairs as $attrib => $value) + { + $element->setAttribute($attrib, $value); + } + } + } } -- cgit v1.2.3 From 25fa654529390dfc989898beb522d63cae4aed7d Mon Sep 17 00:00:00 2001 From: Alexandre Alapetite Date: Thu, 5 Dec 2013 19:18:28 +0100 Subject: Resource-priorities MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Prépare http://www.w3.org/TR/resource-priorities/ https://github.com/marienfressinaud/FreshRSS/issues/316 https://github.com/marienfressinaud/FreshRSS/issues/313 Continue https://github.com/marienfressinaud/FreshRSS/issues/188 https://github.com/marienfressinaud/FreshRSS/commit/e45357a91b9aa47d5b7ead14c174dc7c98ab9926 --- app/models/Feed.php | 6 ++++++ lib/SimplePie/SimplePie.php | 17 +++++++++++++++++ 2 files changed, 23 insertions(+) (limited to 'app/models') diff --git a/app/models/Feed.php b/app/models/Feed.php index 88833c706..1454f44d5 100644 --- a/app/models/Feed.php +++ b/app/models/Feed.php @@ -213,6 +213,12 @@ class Feed extends Model { 'autoplay', 'onload', 'onunload', 'onclick', 'ondblclick', 'onmousedown', 'onmouseup', 'onmouseover', 'onmousemove', 'onmouseout', 'onfocus', 'onblur', 'onkeypress', 'onkeydown', 'onkeyup', 'onselect', 'onchange', 'seamless'))); + $feed->add_attributes(array( + 'img' => array('lazyload' => ''), //http://www.w3.org/TR/resource-priorities/ + 'audio' => array('preload' => 'none'), + 'iframe' => array('postpone' => '', 'sandbox' => 'allow-scripts allow-same-origin'), + 'video' => array('postpone' => '', 'preload' => 'none'), + )); $feed->set_url_replacements(array( 'a' => 'href', 'area' => 'href', diff --git a/lib/SimplePie/SimplePie.php b/lib/SimplePie/SimplePie.php index 9e532023a..d20ab5430 100644 --- a/lib/SimplePie/SimplePie.php +++ b/lib/SimplePie/SimplePie.php @@ -601,6 +601,13 @@ class SimplePie */ public $strip_attributes = array('bgsound', 'class', 'expr', 'id', 'style', 'onclick', 'onerror', 'onfinish', 'onmouseover', 'onmouseout', 'onfocus', 'onblur', 'lowsrc', 'dynsrc'); + /** + * @var array Stores the default attributes to add to differet tags by add_attributes(). + * @see SimplePie::add_attributes() + * @access private + */ + public $add_attributes = array('audio' => array('preload' => 'none'), 'iframe' => array('sandbox' => 'allow-scripts allow-same-origin'), 'video' => array('preload' => 'none')); //FreshRSS + /** * @var array Stores the default tags to be stripped by strip_htmltags(). * @see SimplePie::strip_htmltags() @@ -1073,6 +1080,7 @@ class SimplePie $this->strip_comments(false); $this->strip_htmltags(false); $this->strip_attributes(false); + $this->add_attributes(false); $this->set_image_handler(false); } } @@ -1119,6 +1127,15 @@ class SimplePie $this->sanitize->strip_attributes($attribs); } + public function add_attributes($attribs = '') + { + if ($attribs === '') + { + $attribs = $this->add_attributes; + } + $this->sanitize->add_attributes($attribs); + } + /** * Set the output encoding * -- cgit v1.2.3 From 0e4274fc006203d23b632f4a7a7593427729d649 Mon Sep 17 00:00:00 2001 From: Alexandre Alapetite Date: Thu, 5 Dec 2013 22:12:08 +0100 Subject: Permet de supprimer les articles d'un flux MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Implémente https://github.com/marienfressinaud/FreshRSS/issues/311 --- app/controllers/feedController.php | 83 +++++++++++++++++++++++--------------- app/i18n/en.php | 4 +- app/i18n/fr.php | 4 +- app/models/Feed.php | 28 +++++++++++++ app/views/configure/feed.phtml | 24 ++++++----- 5 files changed, 99 insertions(+), 44 deletions(-) (limited to 'app/models') diff --git a/app/controllers/feedController.php b/app/controllers/feedController.php index c978857b2..02647e10f 100755 --- a/app/controllers/feedController.php +++ b/app/controllers/feedController.php @@ -157,6 +157,21 @@ class feedController extends ActionController { } } + public function truncateAction () { + if (Request::isPost ()) { + $id = Request::param ('id'); + $feedDAO = new FeedDAO (); + $n = $feedDAO->truncate($id); + $notif = array( + 'type' => $n === false ? 'bad' : 'good', + 'content' => Translate::t ('n_entries_deleted', $n) + ); + Session::_param ('notification', $notif); + invalidateHttpCache(); + Request::forward (array ('c' => 'configure', 'a' => 'feed', 'params' => array('id' => $id)), true); + } + } + public function actualizeAction () { @set_time_limit(300); @@ -356,44 +371,46 @@ class feedController extends ActionController { } public function deleteAction () { - $type = Request::param ('type', 'feed'); - $id = Request::param ('id'); + if (Request::isPost ()) { + $type = Request::param ('type', 'feed'); + $id = Request::param ('id'); - $feedDAO = new FeedDAO (); - if ($type == 'category') { - if ($feedDAO->deleteFeedByCategory ($id)) { - $notif = array ( - 'type' => 'good', - 'content' => Translate::t ('category_emptied') - ); - //TODO: Delete old favicons - } else { - $notif = array ( - 'type' => 'bad', - 'content' => Translate::t ('error_occured') - ); - } - } else { - if ($feedDAO->deleteFeed ($id)) { - $notif = array ( - 'type' => 'good', - 'content' => Translate::t ('feed_deleted') - ); - Feed::faviconDelete($id); + $feedDAO = new FeedDAO (); + if ($type == 'category') { + if ($feedDAO->deleteFeedByCategory ($id)) { + $notif = array ( + 'type' => 'good', + 'content' => Translate::t ('category_emptied') + ); + //TODO: Delete old favicons + } else { + $notif = array ( + 'type' => 'bad', + 'content' => Translate::t ('error_occured') + ); + } } else { - $notif = array ( - 'type' => 'bad', - 'content' => Translate::t ('error_occured') - ); + if ($feedDAO->deleteFeed ($id)) { + $notif = array ( + 'type' => 'good', + 'content' => Translate::t ('feed_deleted') + ); + Feed::faviconDelete($id); + } else { + $notif = array ( + 'type' => 'bad', + 'content' => Translate::t ('error_occured') + ); + } } - } - Session::_param ('notification', $notif); + Session::_param ('notification', $notif); - if ($type == 'category') { - Request::forward (array ('c' => 'configure', 'a' => 'categorize'), true); - } else { - Request::forward (array ('c' => 'configure', 'a' => 'feed'), true); + if ($type == 'category') { + Request::forward (array ('c' => 'configure', 'a' => 'categorize'), true); + } else { + Request::forward (array ('c' => 'configure', 'a' => 'feed'), true); + } } } diff --git a/app/i18n/en.php b/app/i18n/en.php index da61623a3..1c17e8149 100644 --- a/app/i18n/en.php +++ b/app/i18n/en.php @@ -85,6 +85,7 @@ return array ( 'n_feeds_actualized' => '%d feeds have been updated', 'feeds_actualized' => 'RSS feeds have been updated', 'no_feed_actualized' => 'No RSS feed has been updated', + 'n_entries_deleted' => '%d articles have been deleted', 'feeds_imported_with_errors' => 'Your feeds have been imported but some errors occurred', 'feeds_imported' => 'Your feeds have been imported and will now be updated', 'category_emptied' => 'Category has been emptied', @@ -135,8 +136,9 @@ return array ( 'feed_url' => 'Feed URL', 'articles' => 'articles', 'number_articles' => 'Number of articles', - 'keep_history' => 'Keep history?', + 'keep_history' => 'Keep old articles?', 'categorize' => 'Store in a category', + 'truncate' => 'Delete all articles', 'advanced' => 'Advanced', 'show_in_all_flux' => 'Show in main stream', 'yes' => 'Yes', diff --git a/app/i18n/fr.php b/app/i18n/fr.php index 979a364cd..cd39637cb 100644 --- a/app/i18n/fr.php +++ b/app/i18n/fr.php @@ -85,6 +85,7 @@ return array ( 'n_feeds_actualized' => '%d flux ont été mis à jour', 'feeds_actualized' => 'Les flux ont été mis à jour', 'no_feed_actualized' => 'Aucun flux n’a pu être mis à jour', + 'n_entries_deleted' => '%d articles ont été supprimés', 'feeds_imported_with_errors' => 'Vos flux ont été importés mais des erreurs sont survenues', 'feeds_imported' => 'Vos flux ont été importés et vont maintenant être actualisés', 'category_emptied' => 'La catégorie a été vidée', @@ -135,8 +136,9 @@ return array ( 'feed_url' => 'URL du flux', 'articles' => 'articles', 'number_articles' => 'Nombre d’articles', - 'keep_history' => 'Garder l’historique ?', + 'keep_history' => 'Garder les vieux articles ?', 'categorize' => 'Ranger dans une catégorie', + 'truncate' => 'Supprimer tous les articles', 'advanced' => 'Avancé', 'show_in_all_flux' => 'Afficher dans le flux principal', 'yes' => 'Oui', diff --git a/app/models/Feed.php b/app/models/Feed.php index 1454f44d5..043956f71 100644 --- a/app/models/Feed.php +++ b/app/models/Feed.php @@ -570,6 +570,34 @@ class FeedDAO extends Model_pdo { return false; } } + + public function truncate ($id) { + $sql = 'DELETE e.* FROM `' . $this->prefix . 'entry` e WHERE e.id_feed=?'; + $stm = $this->bd->prepare($sql); + $values = array($id); + $this->bd->beginTransaction (); + if (!($stm && $stm->execute ($values))) { + $info = $stm->errorInfo(); + Minz_Log::record ('SQL error : ' . $info[2], Minz_Log::ERROR); + $this->bd->rollBack (); + return false; + } + $affected = $stm->rowCount(); + + $sql = 'UPDATE `' . $this->prefix . 'feed` f ' + . 'SET f.cache_nbEntries=0, f.cache_nbUnreads=0 WHERE f.id=?'; + $values = array ($id); + $stm = $this->bd->prepare ($sql); + if (!($stm && $stm->execute ($values))) { + $info = $stm->errorInfo(); + Minz_Log::record ('SQL error : ' . $info[2], Minz_Log::ERROR); + $this->bd->rollBack (); + return false; + } + + $this->bd->commit (); + return $affected; + } } class HelperFeed { diff --git a/app/views/configure/feed.phtml b/app/views/configure/feed.phtml index 1fb0368de..de019863e 100644 --- a/app/views/configure/feed.phtml +++ b/app/views/configure/feed.phtml @@ -39,6 +39,18 @@ +
    + +
    + +
    +
    @@ -59,15 +71,9 @@
    - +
    - +
    @@ -107,7 +113,7 @@
    - +
    -- cgit v1.2.3 From 97a7d7b0b2c25d573a8dac72e6183abf640c8fe4 Mon Sep 17 00:00:00 2001 From: Alexandre Alapetite Date: Thu, 12 Dec 2013 19:30:19 +0100 Subject: Microtime : récupération de toutes les microsecondes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Microtime(true) dépend de la précision de PHP définie dans php.ini, et par défaut, nous perdons les deux dernières décimales des microsecondes. Du coup, sur une machine très rapide, cela aurait pu poser des problèmes d'identifiants dupliqués. Patch utilisant gettimeofday() à la place. Au passage, reste en string tout le long et plus besoin de faire la conversion CAST(? * 1000000 AS SIGNED INTEGER) côté base de données. https://github.com/marienfressinaud/FreshRSS/issues/202 --- app/controllers/feedController.php | 4 ++-- app/models/Entry.php | 2 +- lib/lib_rss.php | 12 +++++++++++- 3 files changed, 14 insertions(+), 4 deletions(-) (limited to 'app/models') diff --git a/app/controllers/feedController.php b/app/controllers/feedController.php index 02647e10f..a38614b3d 100755 --- a/app/controllers/feedController.php +++ b/app/controllers/feedController.php @@ -106,7 +106,7 @@ class feedController extends ActionController { $feed->keepHistory ()) { $values = $entry->toArray (); $values['id_feed'] = $feed->id (); - $values['id'] = min(time(), $entry->date (true)) . '.' . rand(0, 999999); + $values['id'] = min(time(), $entry->date (true)) . uSecString(); $values['is_read'] = $is_read; $entryDAO->addEntry ($values); } @@ -229,7 +229,7 @@ class feedController extends ActionController { $feed->keepHistory ())) { $values = $entry->toArray (); //Use declared date at first import, otherwise use discovery date - $values['id'] = empty($existingGuids) ? min(time(), $entry->date (true)) . '.' . rand(0, 999999) : microtime(true); + $values['id'] = empty($existingGuids) ? min(time(), $entry->date (true)) . uSecString() : uTimeString(); $values['is_read'] = $is_read; $entryDAO->addEntry ($values); } diff --git a/app/models/Entry.php b/app/models/Entry.php index 33d0c66bb..103a90706 100755 --- a/app/models/Entry.php +++ b/app/models/Entry.php @@ -196,7 +196,7 @@ class Entry extends Model { class EntryDAO extends Model_pdo { public function addEntry ($valuesTmp) { $sql = 'INSERT INTO `' . $this->prefix . 'entry`(id, guid, title, author, content_bin, link, date, is_read, is_favorite, id_feed, tags) ' - . 'VALUES(CAST(? * 1000000 AS SIGNED INTEGER), ?, ?, ?, COMPRESS(?), ?, ?, ?, ?, ?, ?)'; + . 'VALUES(?, ?, ?, ?, COMPRESS(?), ?, ?, ?, ?, ?, ?)'; $stm = $this->bd->prepare ($sql); $values = array ( diff --git a/lib/lib_rss.php b/lib/lib_rss.php index 8d4cecf44..4f5b90b61 100644 --- a/lib/lib_rss.php +++ b/lib/lib_rss.php @@ -255,6 +255,16 @@ function lazyimg($content) { ); } +function uTimeString() { + $t = @gettimeofday(); + return $t['sec'] . str_pad($t['usec'], 6, '0'); +} + +function uSecString() { + $t = @gettimeofday(); + return str_pad($t['usec'], 6, '0'); +} + function invalidateHttpCache() { - file_put_contents(DATA_PATH . '/touch.txt', microtime(true)); + file_put_contents(DATA_PATH . '/touch.txt', uTimeString()); } -- cgit v1.2.3 From 4f0b1efc2b6334a5be1e5f2b6a7b64b925c841b4 Mon Sep 17 00:00:00 2001 From: Alexandre Alapetite Date: Sat, 14 Dec 2013 13:57:25 +0100 Subject: Prefectch : précharge les icônes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Précharge les icônes qui ne sont pas forcément affichées sur la page en cours (par exemple l'icône favoris) pour éviter d'avoir un bref instant sans icône lors du changement d'état (par exemple lorsqu'on marque un article comme favoris) --- app/layout/layout.phtml | 4 ++++ app/models/RSSThemes.php | 5 +++-- 2 files changed, 7 insertions(+), 2 deletions(-) (limited to 'app/models') diff --git a/app/layout/layout.phtml b/app/layout/layout.phtml index 6fc5c1cf0..ac00e8fd0 100644 --- a/app/layout/layout.phtml +++ b/app/layout/layout.phtml @@ -20,6 +20,10 @@ rss_url)) { ?> + + + + diff --git a/app/models/RSSThemes.php b/app/models/RSSThemes.php index 7a6deaf3c..a3e67f8b1 100644 --- a/app/models/RSSThemes.php +++ b/app/models/RSSThemes.php @@ -47,7 +47,7 @@ class RSSThemes extends Model { ), 1) : array(); } - public static function icon($name) { + public static function icon($name, $urlOnly = false) { static $alts = array( 'add' => '✚', 'all' => '☰', @@ -82,6 +82,7 @@ class RSSThemes extends Model { $url = isset(self::$themeIcons[$url]) ? (self::$themeIconsUrl . $url) : (self::$defaultIconsUrl . $url); - return '' . $alts[$name] . ''; + return $urlOnly ? Url::display($url) : + '' . $alts[$name] . ''; } } -- cgit v1.2.3 From 4af233e1f736eb2256e5e1696418635165467855 Mon Sep 17 00:00:00 2001 From: Alexandre Alapetite Date: Sat, 14 Dec 2013 16:22:38 +0100 Subject: Nettoyage des flux plus intelligent MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Implémente https://github.com/marienfressinaud/FreshRSS/issues/323 Garde au moins n+10 articles, où n est le nombre d'articles toujours présent dans le flux RSS. --- app/controllers/feedController.php | 13 +++++-------- app/models/Entry.php | 18 ------------------ app/models/Feed.php | 21 +++++++++++++++++++++ 3 files changed, 26 insertions(+), 26 deletions(-) (limited to 'app/models') diff --git a/app/controllers/feedController.php b/app/controllers/feedController.php index a38614b3d..24b8627ff 100755 --- a/app/controllers/feedController.php +++ b/app/controllers/feedController.php @@ -197,14 +197,6 @@ class feedController extends ActionController { // on calcule la date des articles les plus anciens qu'on accepte $nb_month_old = $this->view->conf->oldEntries (); $date_min = time () - (60 * 60 * 24 * 30 * $nb_month_old); - if (rand(0, 30) === 1) { - $nb = $entryDAO->cleanOldEntries ($date_min); - Minz_Log::record ($nb . ' old entries cleaned.', Minz_Log::DEBUG); - if ($nb > 0) { - $nb = $feedDAO->updateCachedValues (); - Minz_Log::record ($nb . ' cached values updated.', Minz_Log::DEBUG); - } - } $i = 0; $flux_update = 0; @@ -235,6 +227,11 @@ class feedController extends ActionController { } } + if ((!$feed->keepHistory()) && (rand(0, 30) === 1)) { + $nb = $feedDAO->cleanOldEntries ($feed->id (), $date_min, count($entries) + 10); + Minz_Log::record ($nb . ' old entries cleaned in feed ' . $feed->id (), Minz_Log::DEBUG); + } + // on indique que le flux vient d'être mis à jour en BDD $feedDAO->updateLastUpdate ($feed->id ()); $feedDAO->commit (); diff --git a/app/models/Entry.php b/app/models/Entry.php index 103a90706..328a7da2e 100755 --- a/app/models/Entry.php +++ b/app/models/Entry.php @@ -423,24 +423,6 @@ class EntryDAO extends Model_pdo { } } - public function cleanOldEntries ($date_min) { - $sql = 'DELETE e.* FROM `' . $this->prefix . 'entry` e INNER JOIN `' . $this->prefix . 'feed` f ON e.id_feed = f.id ' - . 'WHERE e.id <= ? AND e.is_favorite = 0 AND f.keep_history = 0'; - $stm = $this->bd->prepare ($sql); - - $values = array ( - $date_min . '000000' - ); - - if ($stm && $stm->execute ($values)) { - return $stm->rowCount(); - } else { - $info = $stm->errorInfo(); - Minz_Log::record ('SQL error : ' . $info[2], Minz_Log::ERROR); - return false; - } - } - public function searchByGuid ($feed_id, $id) { // un guid est unique pour un flux donné $sql = 'SELECT id, guid, title, author, UNCOMPRESS(content_bin) AS content, link, date, is_read, is_favorite, id_feed, tags ' diff --git a/app/models/Feed.php b/app/models/Feed.php index 043956f71..4acf47744 100644 --- a/app/models/Feed.php +++ b/app/models/Feed.php @@ -598,6 +598,27 @@ class FeedDAO extends Model_pdo { $this->bd->commit (); return $affected; } + + public function cleanOldEntries ($id, $date_min, $keep = 15) { //Remember to call updateLastUpdate($id) just after + $sql = 'DELETE e.* FROM `' . $this->prefix . 'entry` e ' + . 'WHERE e.id_feed = :id_feed AND e.id <= :id_max AND e.is_favorite = 0 AND e.id NOT IN ' + . '(SELECT id FROM (SELECT e2.id FROM `' . $this->prefix . 'entry` e2 WHERE e2.id_feed = :id_feed ORDER BY id DESC LIMIT :keep) keep)'; //Double select because of: MySQL doesn't yet support 'LIMIT & IN/ALL/ANY/SOME subquery' + $stm = $this->bd->prepare ($sql); + + $id_max = intval($date_min) . '000000'; + + $stm->bindParam(':id_feed', $id, PDO::PARAM_INT); + $stm->bindParam(':id_max', $id_max, PDO::PARAM_INT); + $stm->bindParam(':keep', $keep, PDO::PARAM_INT); + + if ($stm && $stm->execute ()) { + return $stm->rowCount(); + } else { + $info = $stm->errorInfo(); + Minz_Log::record ('SQL error : ' . $info[2], Minz_Log::ERROR); + return false; + } + } } class HelperFeed { -- cgit v1.2.3 From 878e96202e8a22e4857b98e29b0a1fce68eccbc9 Mon Sep 17 00:00:00 2001 From: Alexandre Alapetite Date: Sun, 15 Dec 2013 03:30:24 +0100 Subject: Grosse refactorisation pour permettre le chargement automatique des classes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit C'est parti de changements pour https://github.com/marienfressinaud/FreshRSS/issues/255 et finalement j'ai continué la refactorisation... Ajout de préfixes FreshRSS_ et Minz_ sur le modèle de SimplePie_. Toutes les classes sont maintenant en chargement automatique (devrait améliorer les performances en évitant de charger plein de classes inutilisées, et faciliter la maintenance). Suppression de set_include_path(). Si souhaité, certaines classes de Minz pourraient être déplacées dans un sous-répertoire, par exemple les exceptions. Tests et relecture nécessaires. --- app/App_FrontController.php | 84 ---- app/Exceptions/BadUrlException.php | 6 + app/Exceptions/EntriesGetterException.php | 7 + app/Exceptions/FeedException.php | 6 + app/Exceptions/OpmlException.php | 6 + app/FreshRSS.php | 58 +++ app/Models/CategoryDAO.php | 252 +++++++++++ app/Models/Configuration.php | 326 ++++++++++++++ app/Models/ConfigurationDAO.php | 156 +++++++ app/Models/EntryDAO.php | 425 ++++++++++++++++++ app/Models/FeedDAO.php | 341 +++++++++++++++ app/Models/Log.php | 26 ++ app/Models/LogDAO.php | 20 + app/Models/Themes.php | 88 ++++ app/controllers/configureController.php | 234 +++++----- app/controllers/entryController.php | 44 +- app/controllers/errorController.php | 8 +- app/controllers/feedController.php | 142 +++--- app/controllers/indexController.php | 78 ++-- app/controllers/javascriptController.php | 4 +- app/layout/aside_configure.phtml | 14 +- app/layout/aside_feed.phtml | 28 +- app/layout/aside_flux.phtml | 30 +- app/layout/header.phtml | 38 +- app/layout/layout.phtml | 18 +- app/layout/nav_entries.phtml | 6 +- app/layout/nav_menu.phtml | 68 +-- app/models/Category.php | 260 +---------- app/models/Days.php | 2 +- app/models/Entry.php | 438 +------------------ app/models/Exception/EntriesGetterException.php | 7 - app/models/Exception/FeedException.php | 19 - app/models/Feed.php | 362 +--------------- app/models/Log_Model.php | 46 -- app/models/RSSConfiguration.php | 480 --------------------- app/models/RSSThemes.php | 88 ---- app/views/configure/categorize.phtml | 22 +- app/views/configure/display.phtml | 106 ++--- app/views/configure/feed.phtml | 54 +-- app/views/configure/importExport.phtml | 18 +- app/views/configure/sharing.phtml | 30 +- app/views/configure/shortcut.phtml | 30 +- app/views/entry/bookmark.phtml | 16 +- app/views/entry/read.phtml | 16 +- app/views/error/index.phtml | 4 +- app/views/helpers/javascript_vars.phtml | 20 +- app/views/helpers/logs_pagination.phtml | 16 +- app/views/helpers/pagination.phtml | 18 +- app/views/helpers/view/global_view.phtml | 2 +- app/views/helpers/view/normal_view.phtml | 53 ++- app/views/helpers/view/reader_view.phtml | 4 +- app/views/helpers/view/rss_view.phtml | 6 +- app/views/index/about.phtml | 24 +- app/views/index/index.phtml | 10 +- app/views/index/logs.phtml | 8 +- app/views/javascript/actualize.phtml | 4 +- lib/Minz/ActionException.php | 9 + lib/Minz/BadConfigurationException.php | 9 + lib/Minz/Cache.php | 116 +++++ .../ControllerNotActionControllerException.php | 9 + lib/Minz/ControllerNotExistException.php | 9 + lib/Minz/CurrentPagePaginationException.php | 8 + lib/Minz/Exception.php | 16 + lib/Minz/FileNotExistException.php | 8 + lib/Minz/Log.php | 94 ++++ lib/Minz/ModelArray.php | 122 ++++++ lib/Minz/ModelPdo.php | 111 +++++ lib/Minz/ModelTxt.php | 84 ++++ lib/Minz/PDOConnectionException.php | 9 + lib/Minz/PermissionDeniedException.php | 8 + lib/Minz/RouteNotFoundException.php | 16 + lib/SimplePie_autoloader.php | 86 ---- lib/lib_rss.php | 45 +- lib/minz/ActionController.php | 4 +- lib/minz/Configuration.php | 60 +-- lib/minz/Dispatcher.php | 54 +-- lib/minz/Error.php | 40 +- lib/minz/FrontController.php | 80 ++-- lib/minz/Helper.php | 2 +- lib/minz/Minz_Cache.php | 116 ----- lib/minz/Minz_Log.php | 94 ---- lib/minz/Model.php | 2 +- lib/minz/Paginator.php | 2 +- lib/minz/Request.php | 16 +- lib/minz/Response.php | 2 +- lib/minz/Router.php | 34 +- lib/minz/Session.php | 6 +- lib/minz/Translate.php | 6 +- lib/minz/Url.php | 18 +- lib/minz/View.php | 10 +- lib/minz/dao/Model_array.php | 122 ------ lib/minz/dao/Model_pdo.php | 111 ----- lib/minz/dao/Model_txt.php | 84 ---- lib/minz/exceptions/MinzException.php | 94 ---- public/index.php | 12 +- 95 files changed, 3134 insertions(+), 3270 deletions(-) delete mode 100644 app/App_FrontController.php create mode 100644 app/Exceptions/BadUrlException.php create mode 100644 app/Exceptions/EntriesGetterException.php create mode 100644 app/Exceptions/FeedException.php create mode 100644 app/Exceptions/OpmlException.php create mode 100644 app/FreshRSS.php create mode 100644 app/Models/CategoryDAO.php create mode 100644 app/Models/Configuration.php create mode 100644 app/Models/ConfigurationDAO.php create mode 100644 app/Models/EntryDAO.php create mode 100644 app/Models/FeedDAO.php create mode 100644 app/Models/Log.php create mode 100644 app/Models/LogDAO.php create mode 100644 app/Models/Themes.php delete mode 100644 app/models/Exception/EntriesGetterException.php delete mode 100644 app/models/Exception/FeedException.php delete mode 100644 app/models/Log_Model.php delete mode 100755 app/models/RSSConfiguration.php delete mode 100644 app/models/RSSThemes.php create mode 100644 lib/Minz/ActionException.php create mode 100644 lib/Minz/BadConfigurationException.php create mode 100644 lib/Minz/Cache.php create mode 100644 lib/Minz/ControllerNotActionControllerException.php create mode 100644 lib/Minz/ControllerNotExistException.php create mode 100644 lib/Minz/CurrentPagePaginationException.php create mode 100644 lib/Minz/Exception.php create mode 100644 lib/Minz/FileNotExistException.php create mode 100644 lib/Minz/Log.php create mode 100644 lib/Minz/ModelArray.php create mode 100644 lib/Minz/ModelPdo.php create mode 100644 lib/Minz/ModelTxt.php create mode 100644 lib/Minz/PDOConnectionException.php create mode 100644 lib/Minz/PermissionDeniedException.php create mode 100644 lib/Minz/RouteNotFoundException.php delete mode 100644 lib/SimplePie_autoloader.php delete mode 100644 lib/minz/Minz_Cache.php delete mode 100644 lib/minz/Minz_Log.php delete mode 100755 lib/minz/dao/Model_array.php delete mode 100755 lib/minz/dao/Model_pdo.php delete mode 100755 lib/minz/dao/Model_txt.php delete mode 100644 lib/minz/exceptions/MinzException.php (limited to 'app/models') diff --git a/app/App_FrontController.php b/app/App_FrontController.php deleted file mode 100644 index 0721dba45..000000000 --- a/app/App_FrontController.php +++ /dev/null @@ -1,84 +0,0 @@ - -*/ -require ('FrontController.php'); - -class App_FrontController extends FrontController { - public function init () { - $this->loadLibs (); - $this->loadModels (); - - Session::init (); - Translate::init (); - - $this->loadParamsView (); - $this->loadStylesAndScripts (); - $this->loadNotifications (); - } - - private function loadLibs () { - require (LIB_PATH . '/lib_rss.php'); - require (LIB_PATH . '/SimplePie_autoloader.php'); - } - - 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/RSSThemes.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/Log_Model.php'); - } - - private function loadParamsView () { - try { - $this->conf = Session::param ('conf', new RSSConfiguration ()); - } catch(MinzException $e) { - // Permission denied or conf file does not exist - // it's critical! - print $e->getMessage(); - exit(); - } - - View::_param ('conf', $this->conf); - Session::_param ('language', $this->conf->language ()); - - $output = Request::param ('output'); - if(!$output) { - $output = $this->conf->viewMode(); - Request::_param ('output', $output); - } - } - - private function loadStylesAndScripts () { - $theme = RSSThemes::get_infos($this->conf->theme()); - if ($theme) { - foreach($theme["files"] as $file) { - View::appendStyle (Url::display ('/themes/' . $theme['path'] . '/' . $file . '?' . @filemtime(PUBLIC_PATH . '/themes/' . $theme['path'] . '/' . $file))); - } - } - - if (login_is_conf ($this->conf)) { - View::appendScript ('https://login.persona.org/include.js'); - } - $includeLazyLoad = $this->conf->lazyload () === 'yes' && ($this->conf->displayPosts () === 'yes' || Request::param ('output') === 'reader'); - View::appendScript (Url::display ('/scripts/jquery.min.js?' . @filemtime(PUBLIC_PATH . '/scripts/jquery.min.js')), false, !$includeLazyLoad, !$includeLazyLoad); - if ($includeLazyLoad) { - View::appendScript (Url::display ('/scripts/jquery.lazyload.min.js?' . @filemtime(PUBLIC_PATH . '/scripts/jquery.lazyload.min.js'))); - } - View::appendScript (Url::display ('/scripts/main.js?' . @filemtime(PUBLIC_PATH . '/scripts/main.js'))); - } - - private function loadNotifications () { - $notif = Session::param ('notification'); - if ($notif) { - View::_param ('notification', $notif); - Session::_param ('notification'); - } - } -} diff --git a/app/Exceptions/BadUrlException.php b/app/Exceptions/BadUrlException.php new file mode 100644 index 000000000..7d1fe110e --- /dev/null +++ b/app/Exceptions/BadUrlException.php @@ -0,0 +1,6 @@ +loadParamsView (); + $this->loadStylesAndScripts (); + $this->loadNotifications (); + } + + private function loadParamsView () { + try { + $this->conf = Minz_Session::param ('conf', new FreshRSS_Configuration ()); + } catch (Minz_Exception $e) { + // Permission denied or conf file does not exist + // it's critical! + print $e->getMessage(); + exit(); + } + + Minz_View::_param ('conf', $this->conf); + Minz_Session::_param ('language', $this->conf->language ()); + + $output = Minz_Request::param ('output'); + if(!$output) { + $output = $this->conf->viewMode(); + Minz_Request::_param ('output', $output); + } + } + + private function loadStylesAndScripts () { + $theme = FreshRSS_Themes::get_infos($this->conf->theme()); + if ($theme) { + foreach($theme["files"] as $file) { + Minz_View::appendStyle (Minz_Url::display ('/themes/' . $theme['path'] . '/' . $file . '?' . @filemtime(PUBLIC_PATH . '/themes/' . $theme['path'] . '/' . $file))); + } + } + + if (login_is_conf ($this->conf)) { + Minz_View::appendScript ('https://login.persona.org/include.js'); + } + $includeLazyLoad = $this->conf->lazyload () === 'yes' && ($this->conf->displayPosts () === 'yes' || Minz_Request::param ('output') === 'reader'); + Minz_View::appendScript (Minz_Url::display ('/scripts/jquery.min.js?' . @filemtime(PUBLIC_PATH . '/scripts/jquery.min.js')), false, !$includeLazyLoad, !$includeLazyLoad); + if ($includeLazyLoad) { + Minz_View::appendScript (Minz_Url::display ('/scripts/jquery.lazyload.min.js?' . @filemtime(PUBLIC_PATH . '/scripts/jquery.lazyload.min.js'))); + } + Minz_View::appendScript (Minz_Url::display ('/scripts/main.js?' . @filemtime(PUBLIC_PATH . '/scripts/main.js'))); + } + + private function loadNotifications () { + $notif = Minz_Session::param ('notification'); + if ($notif) { + Minz_View::_param ('notification', $notif); + Minz_Session::_param ('notification'); + } + } +} diff --git a/app/Models/CategoryDAO.php b/app/Models/CategoryDAO.php new file mode 100644 index 000000000..793e593c3 --- /dev/null +++ b/app/Models/CategoryDAO.php @@ -0,0 +1,252 @@ +prefix . 'category` (name, color) VALUES(?, ?)'; + $stm = $this->bd->prepare ($sql); + + $values = array ( + substr($valuesTmp['name'], 0, 255), + substr($valuesTmp['color'], 0, 7), + ); + + if ($stm && $stm->execute ($values)) { + return $this->bd->lastInsertId(); + } else { + $info = $stm->errorInfo(); + Minz_Log::record ('SQL error : ' . $info[2], Minz_Log::ERROR); + return false; + } + } + + public function updateCategory ($id, $valuesTmp) { + $sql = 'UPDATE `' . $this->prefix . 'category` SET name=?, color=? WHERE id=?'; + $stm = $this->bd->prepare ($sql); + + $values = array ( + $valuesTmp['name'], + $valuesTmp['color'], + $id + ); + + if ($stm && $stm->execute ($values)) { + return $stm->rowCount(); + } else { + $info = $stm->errorInfo(); + Minz_Log::record ('SQL error : ' . $info[2], Minz_Log::ERROR); + return false; + } + } + + public function deleteCategory ($id) { + $sql = 'DELETE FROM `' . $this->prefix . 'category` WHERE id=?'; + $stm = $this->bd->prepare ($sql); + + $values = array ($id); + + if ($stm && $stm->execute ($values)) { + return $stm->rowCount(); + } else { + $info = $stm->errorInfo(); + Minz_Log::record ('SQL error : ' . $info[2], Minz_Log::ERROR); + return false; + } + } + + public function searchById ($id) { + $sql = 'SELECT * FROM `' . $this->prefix . 'category` WHERE id=?'; + $stm = $this->bd->prepare ($sql); + + $values = array ($id); + + $stm->execute ($values); + $res = $stm->fetchAll (PDO::FETCH_ASSOC); + $cat = HelperCategory::daoToCategory ($res); + + if (isset ($cat[0])) { + return $cat[0]; + } else { + return false; + } + } + public function searchByName ($name) { + $sql = 'SELECT * FROM `' . $this->prefix . 'category` WHERE name=?'; + $stm = $this->bd->prepare ($sql); + + $values = array ($name); + + $stm->execute ($values); + $res = $stm->fetchAll (PDO::FETCH_ASSOC); + $cat = HelperCategory::daoToCategory ($res); + + if (isset ($cat[0])) { + return $cat[0]; + } else { + return false; + } + } + + public function listCategories ($prePopulateFeeds = true, $details = false) { + if ($prePopulateFeeds) { + $sql = 'SELECT c.id AS c_id, c.name AS c_name, ' + . ($details ? 'c.color AS c_color, ' : '') + . ($details ? 'f.* ' : 'f.id, f.name, f.website, f.priority, f.error, f.cache_nbEntries, f.cache_nbUnreads ') + . 'FROM `' . $this->prefix . 'category` c ' + . 'LEFT OUTER JOIN `' . $this->prefix . 'feed` f ON f.category = c.id ' + . 'GROUP BY f.id ' + . 'ORDER BY c.name, f.name'; + $stm = $this->bd->prepare ($sql); + $stm->execute (); + return HelperCategory::daoToCategoryPrepopulated ($stm->fetchAll (PDO::FETCH_ASSOC)); + } else { + $sql = 'SELECT * FROM `' . $this->prefix . 'category` ORDER BY name'; + $stm = $this->bd->prepare ($sql); + $stm->execute (); + return HelperCategory::daoToCategory ($stm->fetchAll (PDO::FETCH_ASSOC)); + } + } + + public function getDefault () { + $sql = 'SELECT * FROM `' . $this->prefix . 'category` WHERE id=1'; + $stm = $this->bd->prepare ($sql); + + $stm->execute (); + $res = $stm->fetchAll (PDO::FETCH_ASSOC); + $cat = HelperCategory::daoToCategory ($res); + + if (isset ($cat[0])) { + return $cat[0]; + } else { + return false; + } + } + public function checkDefault () { + $def_cat = $this->searchById (1); + + if ($def_cat === false) { + $cat = new FreshRSS_Category (Minz_Translate::t ('default_category')); + $cat->_id (1); + + $values = array ( + 'id' => $cat->id (), + 'name' => $cat->name (), + 'color' => $cat->color () + ); + + $this->addCategory ($values); + } + } + + public function count () { + $sql = 'SELECT COUNT(*) AS count FROM `' . $this->prefix . 'category`'; + $stm = $this->bd->prepare ($sql); + $stm->execute (); + $res = $stm->fetchAll (PDO::FETCH_ASSOC); + + return $res[0]['count']; + } + + public function countFeed ($id) { + $sql = 'SELECT COUNT(*) AS count FROM `' . $this->prefix . 'feed` WHERE category=?'; + $stm = $this->bd->prepare ($sql); + $values = array ($id); + $stm->execute ($values); + $res = $stm->fetchAll (PDO::FETCH_ASSOC); + + return $res[0]['count']; + } + + public function countNotRead ($id) { + $sql = 'SELECT COUNT(*) AS count FROM `' . $this->prefix . 'entry` e INNER JOIN `' . $this->prefix . 'feed` f ON e.id_feed = f.id WHERE category=? AND e.is_read=0'; + $stm = $this->bd->prepare ($sql); + $values = array ($id); + $stm->execute ($values); + $res = $stm->fetchAll (PDO::FETCH_ASSOC); + + return $res[0]['count']; + } +} + +class HelperCategory { + public static function findFeed($categories, $feed_id) { + foreach ($categories as $category) { + foreach ($category->feeds () as $feed) { + if ($feed->id () === $feed_id) { + return $feed; + } + } + } + return null; + } + + public static function CountUnreads($categories, $minPriority = 0) { + $n = 0; + foreach ($categories as $category) { + foreach ($category->feeds () as $feed) { + if ($feed->priority () >= $minPriority) { + $n += $feed->nbNotRead(); + } + } + } + return $n; + } + + public static function daoToCategoryPrepopulated ($listDAO) { + $list = array (); + + if (!is_array ($listDAO)) { + $listDAO = array ($listDAO); + } + + $previousLine = null; + $feedsDao = array(); + foreach ($listDAO as $line) { + if ($previousLine['c_id'] != null && $line['c_id'] !== $previousLine['c_id']) { + // End of the current category, we add it to the $list + $cat = new FreshRSS_Category ( + $previousLine['c_name'], + isset($previousLine['c_color']) ? $previousLine['c_color'] : '', + HelperFeed::daoToFeed ($feedsDao, $previousLine['c_id']) + ); + $cat->_id ($previousLine['c_id']); + $list[$previousLine['c_id']] = $cat; + + $feedsDao = array(); //Prepare for next category + } + + $previousLine = $line; + $feedsDao[] = $line; + } + + // add the last category + if ($previousLine != null) { + $cat = new FreshRSS_Category ( + $previousLine['c_name'], + isset($previousLine['c_color']) ? $previousLine['c_color'] : '', + HelperFeed::daoToFeed ($feedsDao, $previousLine['c_id']) + ); + $cat->_id ($previousLine['c_id']); + $list[$previousLine['c_id']] = $cat; + } + + return $list; + } + + public static function daoToCategory ($listDAO) { + $list = array (); + + if (!is_array ($listDAO)) { + $listDAO = array ($listDAO); + } + + foreach ($listDAO as $key => $dao) { + $cat = new FreshRSS_Category ( + $dao['name'], + $dao['color'] + ); + $cat->_id ($dao['id']); + $list[$key] = $cat; + } + + return $list; + } +} diff --git a/app/Models/Configuration.php b/app/Models/Configuration.php new file mode 100644 index 000000000..7ef76b522 --- /dev/null +++ b/app/Models/Configuration.php @@ -0,0 +1,326 @@ + 'English', + 'fr' => 'Français', + ); + private $language; + private $posts_per_page; + private $view_mode; + private $default_view; + private $display_posts; + private $onread_jump_next; + private $lazyload; + private $sort_order; + private $old_entries; + private $shortcuts = array (); + private $mail_login = ''; + private $mark_when = array (); + private $sharing = array (); + private $theme; + private $anon_access; + private $token; + private $auto_load_more; + private $topline_read; + private $topline_favorite; + private $topline_date; + private $topline_link; + private $bottomline_read; + private $bottomline_favorite; + private $bottomline_sharing; + private $bottomline_tags; + private $bottomline_date; + private $bottomline_link; + + public function __construct () { + $confDAO = new FreshRSS_ConfigurationDAO (); + $this->_language ($confDAO->language); + $this->_postsPerPage ($confDAO->posts_per_page); + $this->_viewMode ($confDAO->view_mode); + $this->_defaultView ($confDAO->default_view); + $this->_displayPosts ($confDAO->display_posts); + $this->_onread_jump_next ($confDAO->onread_jump_next); + $this->_lazyload ($confDAO->lazyload); + $this->_sortOrder ($confDAO->sort_order); + $this->_oldEntries ($confDAO->old_entries); + $this->_shortcuts ($confDAO->shortcuts); + $this->_mailLogin ($confDAO->mail_login); + $this->_markWhen ($confDAO->mark_when); + $this->_sharing ($confDAO->sharing); + $this->_theme ($confDAO->theme); + FreshRSS_Themes::setThemeId ($confDAO->theme); + $this->_anonAccess ($confDAO->anon_access); + $this->_token ($confDAO->token); + $this->_autoLoadMore ($confDAO->auto_load_more); + $this->_topline_read ($confDAO->topline_read); + $this->_topline_favorite ($confDAO->topline_favorite); + $this->_topline_date ($confDAO->topline_date); + $this->_topline_link ($confDAO->topline_link); + $this->_bottomline_read ($confDAO->bottomline_read); + $this->_bottomline_favorite ($confDAO->bottomline_favorite); + $this->_bottomline_sharing ($confDAO->bottomline_sharing); + $this->_bottomline_tags ($confDAO->bottomline_tags); + $this->_bottomline_date ($confDAO->bottomline_date); + $this->_bottomline_link ($confDAO->bottomline_link); + } + + public function availableLanguages () { + return $this->available_languages; + } + public function language () { + return $this->language; + } + public function postsPerPage () { + return $this->posts_per_page; + } + public function viewMode () { + return $this->view_mode; + } + public function defaultView () { + return $this->default_view; + } + public function displayPosts () { + return $this->display_posts; + } + public function onread_jump_next () { + return $this->onread_jump_next; + } + public function lazyload () { + return $this->lazyload; + } + public function sortOrder () { + return $this->sort_order; + } + public function oldEntries () { + return $this->old_entries; + } + public function shortcuts () { + return $this->shortcuts; + } + public function mailLogin () { + return $this->mail_login; + } + public function markWhen () { + return $this->mark_when; + } + public function markWhenArticle () { + return $this->mark_when['article']; + } + public function markWhenSite () { + return $this->mark_when['site']; + } + public function markWhenScroll () { + return $this->mark_when['scroll']; + } + public function markUponReception () { + return $this->mark_when['reception']; + } + public function sharing ($key = false) { + if ($key === false) { + return $this->sharing; + } elseif (isset ($this->sharing[$key])) { + return $this->sharing[$key]; + } + return false; + } + public function theme () { + return $this->theme; + } + public function anonAccess () { + return $this->anon_access; + } + public function token () { + return $this->token; + } + public function autoLoadMore () { + return $this->auto_load_more; + } + public function toplineRead () { + return $this->topline_read; + } + public function toplineFavorite () { + return $this->topline_favorite; + } + public function toplineDate () { + return $this->topline_date; + } + public function toplineLink () { + return $this->topline_link; + } + public function bottomlineRead () { + return $this->bottomline_read; + } + public function bottomlineFavorite () { + return $this->bottomline_favorite; + } + public function bottomlineSharing () { + return $this->bottomline_sharing; + } + public function bottomlineTags () { + return $this->bottomline_tags; + } + public function bottomlineDate () { + return $this->bottomline_date; + } + public function bottomlineLink () { + return $this->bottomline_link; + } + + public function _language ($value) { + if (!isset ($this->available_languages[$value])) { + $value = 'en'; + } + $this->language = $value; + } + public function _postsPerPage ($value) { + $value = intval($value); + $this->posts_per_page = $value > 0 ? $value : 10; + } + public function _viewMode ($value) { + if ($value == 'global' || $value == 'reader') { + $this->view_mode = $value; + } else { + $this->view_mode = 'normal'; + } + } + public function _defaultView ($value) { + if ($value == 'not_read') { + $this->default_view = 'not_read'; + } else { + $this->default_view = 'all'; + } + } + public function _displayPosts ($value) { + if ($value == 'yes') { + $this->display_posts = 'yes'; + } else { + $this->display_posts = 'no'; + } + } + public function _onread_jump_next ($value) { + if ($value == 'no') { + $this->onread_jump_next = 'no'; + } else { + $this->onread_jump_next = 'yes'; + } + } + public function _lazyload ($value) { + if ($value == 'no') { + $this->lazyload = 'no'; + } else { + $this->lazyload = 'yes'; + } + } + public function _sortOrder ($value) { + $this->sort_order = $value === 'ASC' ? 'ASC' : 'DESC'; + } + public function _oldEntries ($value) { + if (ctype_digit ($value) && $value > 0) { + $this->old_entries = $value; + } else { + $this->old_entries = 3; + } + } + public function _shortcuts ($values) { + foreach ($values as $key => $value) { + $this->shortcuts[$key] = $value; + } + } + public function _mailLogin ($value) { + if (filter_var ($value, FILTER_VALIDATE_EMAIL)) { + $this->mail_login = $value; + } elseif ($value == false) { + $this->mail_login = false; + } + } + public function _markWhen ($values) { + if(!isset($values['article'])) { + $values['article'] = 'yes'; + } + if(!isset($values['site'])) { + $values['site'] = 'yes'; + } + if(!isset($values['scroll'])) { + $values['scroll'] = 'yes'; + } + if(!isset($values['reception'])) { + $values['reception'] = 'no'; + } + + $this->mark_when['article'] = $values['article']; + $this->mark_when['site'] = $values['site']; + $this->mark_when['scroll'] = $values['scroll']; + $this->mark_when['reception'] = $values['reception']; + } + public function _sharing ($values) { + $are_url = array ('shaarli', 'poche', 'diaspora'); + foreach ($values as $key => $value) { + if (in_array($key, $are_url)) { + $is_url = ( + filter_var ($value, FILTER_VALIDATE_URL) || + (version_compare(PHP_VERSION, '5.3.3', '<') && + (strpos($value, '-') > 0) && + ($value === filter_var($value, FILTER_SANITIZE_URL))) + ); //PHP bug #51192 + + if (!$is_url) { + $value = ''; + } + } elseif(!is_bool ($value)) { + $value = true; + } + + $this->sharing[$key] = $value; + } + } + public function _theme ($value) { + $this->theme = $value; + } + public function _anonAccess ($value) { + if ($value == 'yes') { + $this->anon_access = 'yes'; + } else { + $this->anon_access = 'no'; + } + } + public function _token ($value) { + $this->token = $value; + } + public function _autoLoadMore ($value) { + if ($value == 'yes') { + $this->auto_load_more = 'yes'; + } else { + $this->auto_load_more = 'no'; + } + } + public function _topline_read ($value) { + $this->topline_read = $value === 'yes'; + } + public function _topline_favorite ($value) { + $this->topline_favorite = $value === 'yes'; + } + public function _topline_date ($value) { + $this->topline_date = $value === 'yes'; + } + public function _topline_link ($value) { + $this->topline_link = $value === 'yes'; + } + public function _bottomline_read ($value) { + $this->bottomline_read = $value === 'yes'; + } + public function _bottomline_favorite ($value) { + $this->bottomline_favorite = $value === 'yes'; + } + public function _bottomline_sharing ($value) { + $this->bottomline_sharing = $value === 'yes'; + } + public function _bottomline_tags ($value) { + $this->bottomline_tags = $value === 'yes'; + } + public function _bottomline_date ($value) { + $this->bottomline_date = $value === 'yes'; + } + public function _bottomline_link ($value) { + $this->bottomline_link = $value === 'yes'; + } +} diff --git a/app/Models/ConfigurationDAO.php b/app/Models/ConfigurationDAO.php new file mode 100644 index 000000000..fec58d234 --- /dev/null +++ b/app/Models/ConfigurationDAO.php @@ -0,0 +1,156 @@ + 'r', + 'mark_favorite' => 'f', + 'go_website' => 'space', + 'next_entry' => 'j', + 'prev_entry' => 'k', + 'collapse_entry' => 'c', + 'load_more' => 'm' + ); + public $mail_login = ''; + public $mark_when = array ( + 'article' => 'yes', + 'site' => 'yes', + 'scroll' => 'no', + 'reception' => 'no' + ); + public $sharing = array ( + 'shaarli' => '', + 'poche' => '', + 'diaspora' => '', + 'twitter' => true, + 'g+' => true, + 'facebook' => true, + 'email' => true, + 'print' => true + ); + public $theme = 'default'; + public $anon_access = 'no'; + public $token = ''; + public $auto_load_more = 'no'; + public $topline_read = 'yes'; + public $topline_favorite = 'yes'; + public $topline_date = 'yes'; + public $topline_link = 'yes'; + public $bottomline_read = 'yes'; + public $bottomline_favorite = 'yes'; + public $bottomline_sharing = 'yes'; + public $bottomline_tags = 'yes'; + public $bottomline_date = 'yes'; + public $bottomline_link = 'yes'; + + public function __construct ($nameFile = '') { + if (empty($nameFile)) { + $nameFile = DATA_PATH . '/' . Minz_Configuration::currentUser () . '_user.php'; + } + parent::__construct ($nameFile); + + // TODO : simplifier ce code, une boucle for() devrait suffire ! + if (isset ($this->array['language'])) { + $this->language = $this->array['language']; + } + if (isset ($this->array['posts_per_page'])) { + $this->posts_per_page = $this->array['posts_per_page']; + } + if (isset ($this->array['view_mode'])) { + $this->view_mode = $this->array['view_mode']; + } + if (isset ($this->array['default_view'])) { + $this->default_view = $this->array['default_view']; + } + if (isset ($this->array['display_posts'])) { + $this->display_posts = $this->array['display_posts']; + } + if (isset ($this->array['onread_jump_next'])) { + $this->onread_jump_next = $this->array['onread_jump_next']; + } + if (isset ($this->array['lazyload'])) { + $this->lazyload = $this->array['lazyload']; + } + if (isset ($this->array['sort_order'])) { + $this->sort_order = $this->array['sort_order']; + } + if (isset ($this->array['old_entries'])) { + $this->old_entries = $this->array['old_entries']; + } + if (isset ($this->array['shortcuts'])) { + $this->shortcuts = array_merge ( + $this->shortcuts, $this->array['shortcuts'] + ); + } + if (isset ($this->array['mail_login'])) { + $this->mail_login = $this->array['mail_login']; + } + if (isset ($this->array['mark_when'])) { + $this->mark_when = $this->array['mark_when']; + } + if (isset ($this->array['sharing'])) { + $this->sharing = array_merge ( + $this->sharing, $this->array['sharing'] + ); + } + if (isset ($this->array['theme'])) { + $this->theme = $this->array['theme']; + } + if (isset ($this->array['anon_access'])) { + $this->anon_access = $this->array['anon_access']; + } + if (isset ($this->array['token'])) { + $this->token = $this->array['token']; + } + if (isset ($this->array['auto_load_more'])) { + $this->auto_load_more = $this->array['auto_load_more']; + } + + if (isset ($this->array['topline_read'])) { + $this->topline_read = $this->array['topline_read']; + } + if (isset ($this->array['topline_favorite'])) { + $this->topline_favorite = $this->array['topline_favorite']; + } + if (isset ($this->array['topline_date'])) { + $this->topline_date = $this->array['topline_date']; + } + if (isset ($this->array['topline_link'])) { + $this->topline_link = $this->array['topline_link']; + } + if (isset ($this->array['bottomline_read'])) { + $this->bottomline_read = $this->array['bottomline_read']; + } + if (isset ($this->array['bottomline_favorite'])) { + $this->bottomline_favorite = $this->array['bottomline_favorite']; + } + if (isset ($this->array['bottomline_sharing'])) { + $this->bottomline_sharing = $this->array['bottomline_sharing']; + } + if (isset ($this->array['bottomline_tags'])) { + $this->bottomline_tags = $this->array['bottomline_tags']; + } + if (isset ($this->array['bottomline_date'])) { + $this->bottomline_date = $this->array['bottomline_date']; + } + if (isset ($this->array['bottomline_link'])) { + $this->bottomline_link = $this->array['bottomline_link']; + } + } + + public function update ($values) { + foreach ($values as $key => $value) { + $this->array[$key] = $value; + } + + $this->writeFile($this->array); + invalidateHttpCache(); + } +} diff --git a/app/Models/EntryDAO.php b/app/Models/EntryDAO.php new file mode 100644 index 000000000..8c18150b6 --- /dev/null +++ b/app/Models/EntryDAO.php @@ -0,0 +1,425 @@ +prefix . 'entry`(id, guid, title, author, content_bin, link, date, is_read, is_favorite, id_feed, tags) ' + . 'VALUES(?, ?, ?, ?, COMPRESS(?), ?, ?, ?, ?, ?, ?)'; + $stm = $this->bd->prepare ($sql); + + $values = array ( + $valuesTmp['id'], + substr($valuesTmp['guid'], 0, 760), + substr($valuesTmp['title'], 0, 255), + substr($valuesTmp['author'], 0, 255), + $valuesTmp['content'], + substr($valuesTmp['link'], 0, 1023), + $valuesTmp['date'], + $valuesTmp['is_read'], + $valuesTmp['is_favorite'], + $valuesTmp['id_feed'], + substr($valuesTmp['tags'], 0, 1023), + ); + + if ($stm && $stm->execute ($values)) { + return $this->bd->lastInsertId(); + } else { + $info = $stm->errorInfo(); + if ((int)($info[0] / 1000) !== 23) { //Filter out "SQLSTATE Class code 23: Constraint Violation" because of expected duplicate entries + Minz_Log::record ('SQL error ' . $info[0] . ': ' . $info[1] . ' ' . $info[2] + . ' while adding entry in feed ' . $valuesTmp['id_feed'] . ' with title: ' . $valuesTmp['title'], Minz_Log::ERROR); + } /*else { + Minz_Log::record ('SQL error ' . $info[0] . ': ' . $info[1] . ' ' . $info[2] + . ' while adding entry in feed ' . $valuesTmp['id_feed'] . ' with title: ' . $valuesTmp['title'], Minz_Log::DEBUG); + }*/ + return false; + } + } + + public function markFavorite ($id, $is_favorite = true) { + $sql = 'UPDATE `' . $this->prefix . 'entry` e ' + . 'SET e.is_favorite = ? ' + . 'WHERE e.id=?'; + $values = array ($is_favorite ? 1 : 0, $id); + $stm = $this->bd->prepare ($sql); + if ($stm && $stm->execute ($values)) { + return $stm->rowCount(); + } else { + $info = $stm->errorInfo(); + Minz_Log::record ('SQL error : ' . $info[2], Minz_Log::ERROR); + return false; + } + } + public function markRead ($id, $is_read = true) { + $sql = 'UPDATE `' . $this->prefix . 'entry` e INNER JOIN `' . $this->prefix . 'feed` f ON e.id_feed = f.id ' + . 'SET e.is_read = ?,' + . 'f.cache_nbUnreads=f.cache_nbUnreads' . ($is_read ? '-' : '+') . '1 ' + . 'WHERE e.id=?'; + $values = array ($is_read ? 1 : 0, $id); + $stm = $this->bd->prepare ($sql); + if ($stm && $stm->execute ($values)) { + return $stm->rowCount(); + } else { + $info = $stm->errorInfo(); + Minz_Log::record ('SQL error : ' . $info[2], Minz_Log::ERROR); + return false; + } + } + public function markReadEntries ($idMax = 0, $favorites = false) { + if ($idMax === 0) { + $sql = 'UPDATE `' . $this->prefix . 'entry` e INNER JOIN `' . $this->prefix . 'feed` f ON e.id_feed = f.id ' + . 'SET e.is_read = 1, f.cache_nbUnreads=0 ' + . 'WHERE e.is_read = 0 AND '; + if ($favorites) { + $sql .= 'e.is_favorite = 1'; + } else { + $sql .= 'f.priority > 0'; + } + $stm = $this->bd->prepare ($sql); + if ($stm && $stm->execute ()) { + return $stm->rowCount(); + } else { + $info = $stm->errorInfo(); + Minz_Log::record ('SQL error : ' . $info[2], Minz_Log::ERROR); + return false; + } + } else { + $this->bd->beginTransaction (); + + $sql = 'UPDATE `' . $this->prefix . 'entry` e INNER JOIN `' . $this->prefix . 'feed` f ON e.id_feed = f.id ' + . 'SET e.is_read = 1 ' + . 'WHERE e.is_read = 0 AND e.id <= ? AND '; + if ($favorites) { + $sql .= 'e.is_favorite = 1'; + } else { + $sql .= 'f.priority > 0'; + } + $values = array ($idMax); + $stm = $this->bd->prepare ($sql); + if (!($stm && $stm->execute ($values))) { + $info = $stm->errorInfo(); + Minz_Log::record ('SQL error : ' . $info[2], Minz_Log::ERROR); + $this->bd->rollBack (); + return false; + } + $affected = $stm->rowCount(); + + if ($affected > 0) { + $sql = 'UPDATE `' . $this->prefix . 'feed` f ' + . 'LEFT OUTER JOIN (' + . 'SELECT e.id_feed, ' + . 'COUNT(*) AS nbUnreads ' + . 'FROM `' . $this->prefix . 'entry` e ' + . 'WHERE e.is_read = 0 ' + . 'GROUP BY e.id_feed' + . ') x ON x.id_feed=f.id ' + . 'SET f.cache_nbUnreads=COALESCE(x.nbUnreads, 0)'; + $stm = $this->bd->prepare ($sql); + if (!($stm && $stm->execute ())) { + $info = $stm->errorInfo(); + Minz_Log::record ('SQL error : ' . $info[2], Minz_Log::ERROR); + $this->bd->rollBack (); + return false; + } + } + + $this->bd->commit (); + return $affected; + } + } + public function markReadCat ($id, $idMax = 0) { + if ($idMax === 0) { + $sql = 'UPDATE `' . $this->prefix . 'entry` e INNER JOIN `' . $this->prefix . 'feed` f ON e.id_feed = f.id ' + . 'SET e.is_read = 1, f.cache_nbUnreads=0 ' + . 'WHERE f.category = ? AND e.is_read = 0'; + $values = array ($id); + $stm = $this->bd->prepare ($sql); + if ($stm && $stm->execute ($values)) { + return $stm->rowCount(); + } else { + $info = $stm->errorInfo(); + Minz_Log::record ('SQL error : ' . $info[2], Minz_Log::ERROR); + return false; + } + } else { + $this->bd->beginTransaction (); + + $sql = 'UPDATE `' . $this->prefix . 'entry` e INNER JOIN `' . $this->prefix . 'feed` f ON e.id_feed = f.id ' + . 'SET e.is_read = 1 ' + . 'WHERE f.category = ? AND e.is_read = 0 AND e.id <= ?'; + $values = array ($id, $idMax); + $stm = $this->bd->prepare ($sql); + if (!($stm && $stm->execute ($values))) { + $info = $stm->errorInfo(); + Minz_Log::record ('SQL error : ' . $info[2], Minz_Log::ERROR); + $this->bd->rollBack (); + return false; + } + $affected = $stm->rowCount(); + + if ($affected > 0) { + $sql = 'UPDATE `' . $this->prefix . 'feed` f ' + . 'LEFT OUTER JOIN (' + . 'SELECT e.id_feed, ' + . 'COUNT(*) AS nbUnreads ' + . 'FROM `' . $this->prefix . 'entry` e ' + . 'WHERE e.is_read = 0 ' + . 'GROUP BY e.id_feed' + . ') x ON x.id_feed=f.id ' + . 'SET f.cache_nbUnreads=COALESCE(x.nbUnreads, 0) ' + . 'WHERE f.category = ?'; + $values = array ($id); + $stm = $this->bd->prepare ($sql); + if (!($stm && $stm->execute ($values))) { + $info = $stm->errorInfo(); + Minz_Log::record ('SQL error : ' . $info[2], Minz_Log::ERROR); + $this->bd->rollBack (); + return false; + } + } + + $this->bd->commit (); + return $affected; + } + } + public function markReadFeed ($id, $idMax = 0) { + if ($idMax === 0) { + $sql = 'UPDATE `' . $this->prefix . 'entry` e INNER JOIN `' . $this->prefix . 'feed` f ON e.id_feed = f.id ' + . 'SET e.is_read = 1, f.cache_nbUnreads=0 ' + . 'WHERE f.id=? AND e.is_read = 0'; + $values = array ($id); + $stm = $this->bd->prepare ($sql); + if ($stm && $stm->execute ($values)) { + return $stm->rowCount(); + } else { + $info = $stm->errorInfo(); + Minz_Log::record ('SQL error : ' . $info[2], Minz_Log::ERROR); + return false; + } + } else { + $this->bd->beginTransaction (); + + $sql = 'UPDATE `' . $this->prefix . 'entry` e INNER JOIN `' . $this->prefix . 'feed` f ON e.id_feed = f.id ' + . 'SET e.is_read = 1 ' + . 'WHERE f.id=? AND e.is_read = 0 AND e.id <= ?'; + $values = array ($id, $idMax); + $stm = $this->bd->prepare ($sql); + if (!($stm && $stm->execute ($values))) { + $info = $stm->errorInfo(); + Minz_Log::record ('SQL error : ' . $info[2], Minz_Log::ERROR); + $this->bd->rollBack (); + return false; + } + $affected = $stm->rowCount(); + + if ($affected > 0) { + $sql = 'UPDATE `' . $this->prefix . 'feed` f ' + . 'SET f.cache_nbUnreads=f.cache_nbUnreads-' . $affected + . ' WHERE f.id=?'; + $values = array ($id); + $stm = $this->bd->prepare ($sql); + if (!($stm && $stm->execute ($values))) { + $info = $stm->errorInfo(); + Minz_Log::record ('SQL error : ' . $info[2], Minz_Log::ERROR); + $this->bd->rollBack (); + return false; + } + } + + $this->bd->commit (); + return $affected; + } + } + + public function searchByGuid ($feed_id, $id) { + // un guid est unique pour un flux donné + $sql = 'SELECT id, guid, title, author, UNCOMPRESS(content_bin) AS content, link, date, is_read, is_favorite, id_feed, tags ' + . 'FROM `' . $this->prefix . 'entry` WHERE id_feed=? AND guid=?'; + $stm = $this->bd->prepare ($sql); + + $values = array ( + $feed_id, + $id + ); + + $stm->execute ($values); + $res = $stm->fetchAll (PDO::FETCH_ASSOC); + $entries = HelperEntry::daoToEntry ($res); + return isset ($entries[0]) ? $entries[0] : false; + } + + public function searchById ($id) { + $sql = 'SELECT id, guid, title, author, UNCOMPRESS(content_bin) AS content, link, date, is_read, is_favorite, id_feed, tags ' + . 'FROM `' . $this->prefix . 'entry` WHERE id=?'; + $stm = $this->bd->prepare ($sql); + + $values = array ($id); + + $stm->execute ($values); + $res = $stm->fetchAll (PDO::FETCH_ASSOC); + $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 FreshRSS_EntriesGetter_Exception ('Bad type in Entry->listByType: [' . $type . ']!'); + } + 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 FreshRSS_EntriesGetter_Exception ('Bad state in Entry->listByType: [' . $state . ']!'); + } + switch ($order) { + case 'DESC': + case 'ASC': + break; + default: + throw new FreshRSS_EntriesGetter_Exception ('Bad order in Entry->listByType: [' . $order . ']!'); + } + if ($firstId > 0) { + $where .= 'AND e.id ' . ($order === 'DESC' ? '<=' : '>=') . $firstId . ' '; + } + $terms = array_unique(explode(' ', trim($filter))); + sort($terms); //Put #tags first + $having = ''; + foreach ($terms as $word) { + if (!empty($word)) { + if ($word[0] === '#' && isset($word[1])) { + $having .= 'AND tags LIKE ? '; + $values[] = '%' . $word .'%'; + } elseif (!empty($word)) { + $having .= 'AND (e.title LIKE ? OR content LIKE ?) '; + $values[] = '%' . $word .'%'; + $values[] = '%' . $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 ' . $where + . (empty($having) ? '' : 'HAVING' . substr($having, 3)) + . 'ORDER BY e.id ' . $order; + + if ($limit > 0) { + $sql .= ' LIMIT ' . $limit; //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 listLastGuidsByFeed($id, $n) { + $sql = 'SELECT guid FROM `' . $this->prefix . 'entry` WHERE id_feed=? ORDER BY id DESC LIMIT ' . intval($n); + $stm = $this->bd->prepare ($sql); + $values = array ($id); + $stm->execute ($values); + return $stm->fetchAll (PDO::FETCH_COLUMN, 0); + } + + public function countUnreadRead () { + $sql = 'SELECT COUNT(e.id) AS count FROM `' . $this->prefix . 'entry` e INNER JOIN `' . $this->prefix . 'feed` f ON e.id_feed = f.id WHERE priority > 0' + . ' UNION SELECT COUNT(e.id) AS count FROM `' . $this->prefix . 'entry` e INNER JOIN `' . $this->prefix . 'feed` f ON e.id_feed = f.id WHERE priority > 0 AND is_read = 0'; + $stm = $this->bd->prepare ($sql); + $stm->execute (); + $res = $stm->fetchAll (PDO::FETCH_COLUMN, 0); + $all = empty($res[0]) ? 0 : $res[0]; + $unread = empty($res[1]) ? 0 : $res[1]; + return array('all' => $all, 'unread' => $unread, 'read' => $all - $unread); + } + public function count ($minPriority = null) { + $sql = 'SELECT COUNT(e.id) AS count FROM `' . $this->prefix . 'entry` e INNER JOIN `' . $this->prefix . 'feed` f ON e.id_feed = f.id'; + if ($minPriority !== null) { + $sql = ' WHERE priority > ' . intval($minPriority); + } + $stm = $this->bd->prepare ($sql); + $stm->execute (); + $res = $stm->fetchAll (PDO::FETCH_COLUMN, 0); + return $res[0]; + } + public function countNotRead ($minPriority = null) { + $sql = 'SELECT COUNT(e.id) AS count FROM `' . $this->prefix . 'entry` e INNER JOIN `' . $this->prefix . 'feed` f ON e.id_feed = f.id WHERE is_read = 0'; + if ($minPriority !== null) { + $sql = ' AND priority > ' . intval($minPriority); + } + $stm = $this->bd->prepare ($sql); + $stm->execute (); + $res = $stm->fetchAll (PDO::FETCH_COLUMN, 0); + return $res[0]; + } + + public function countUnreadReadFavorites () { + $sql = 'SELECT COUNT(id) FROM `' . $this->prefix . 'entry` WHERE is_favorite=1' + . ' UNION SELECT COUNT(id) FROM `' . $this->prefix . 'entry` WHERE is_favorite=1 AND is_read = 0'; + $stm = $this->bd->prepare ($sql); + $stm->execute (); + $res = $stm->fetchAll (PDO::FETCH_COLUMN, 0); + $all = empty($res[0]) ? 0 : $res[0]; + $unread = empty($res[1]) ? 0 : $res[1]; + return array('all' => $all, 'unread' => $unread, 'read' => $all - $unread); + } + + public function optimizeTable() { + $sql = 'OPTIMIZE TABLE `' . $this->prefix . 'entry`'; + $stm = $this->bd->prepare ($sql); + $stm->execute (); + } +} + +class HelperEntry { + public static function daoToEntry ($listDAO) { + $list = array (); + + if (!is_array ($listDAO)) { + $listDAO = array ($listDAO); + } + + foreach ($listDAO as $key => $dao) { + $entry = new FreshRSS_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 $list; + } +} diff --git a/app/Models/FeedDAO.php b/app/Models/FeedDAO.php new file mode 100644 index 000000000..8f59b1c76 --- /dev/null +++ b/app/Models/FeedDAO.php @@ -0,0 +1,341 @@ +prefix . 'feed` (url, category, name, website, description, lastUpdate, priority, httpAuth, error, keep_history) VALUES(?, ?, ?, ?, ?, ?, 10, ?, 0, 0)'; + $stm = $this->bd->prepare ($sql); + + $values = array ( + substr($valuesTmp['url'], 0, 511), + $valuesTmp['category'], + substr($valuesTmp['name'], 0, 255), + substr($valuesTmp['website'], 0, 255), + substr($valuesTmp['description'], 0, 1023), + $valuesTmp['lastUpdate'], + base64_encode ($valuesTmp['httpAuth']), + ); + + if ($stm && $stm->execute ($values)) { + return $this->bd->lastInsertId(); + } else { + $info = $stm->errorInfo(); + Minz_Log::record ('SQL error : ' . $info[2], Minz_Log::ERROR); + return false; + } + } + + public function updateFeed ($id, $valuesTmp) { + $set = ''; + foreach ($valuesTmp as $key => $v) { + $set .= $key . '=?, '; + + if ($key == 'httpAuth') { + $valuesTmp[$key] = base64_encode ($v); + } + } + $set = substr ($set, 0, -2); + + $sql = 'UPDATE `' . $this->prefix . 'feed` SET ' . $set . ' WHERE id=?'; + $stm = $this->bd->prepare ($sql); + + foreach ($valuesTmp as $v) { + $values[] = $v; + } + $values[] = $id; + + if ($stm && $stm->execute ($values)) { + return $stm->rowCount(); + } else { + $info = $stm->errorInfo(); + Minz_Log::record ('SQL error : ' . $info[2], Minz_Log::ERROR); + return false; + } + } + + public function updateLastUpdate ($id, $inError = 0) { + $sql = 'UPDATE `' . $this->prefix . 'feed` f ' //2 sub-requests with FOREIGN KEY(e.id_feed), INDEX(e.is_read) faster than 1 request with GROUP BY or CASE + . 'SET f.cache_nbEntries=(SELECT COUNT(e1.id) FROM `' . $this->prefix . 'entry` e1 WHERE e1.id_feed=f.id),' + . 'f.cache_nbUnreads=(SELECT COUNT(e2.id) FROM `' . $this->prefix . 'entry` e2 WHERE e2.id_feed=f.id AND e2.is_read=0),' + . 'lastUpdate=?, error=? ' + . 'WHERE f.id=?'; + + $stm = $this->bd->prepare ($sql); + + $values = array ( + time (), + $inError, + $id, + ); + + if ($stm && $stm->execute ($values)) { + return $stm->rowCount(); + } else { + $info = $stm->errorInfo(); + Minz_Log::record ('SQL error : ' . $info[2], Minz_Log::ERROR); + return false; + } + } + + public function changeCategory ($idOldCat, $idNewCat) { + $catDAO = new FreshRSS_CategoryDAO (); + $newCat = $catDAO->searchById ($idNewCat); + if (!$newCat) { + $newCat = $catDAO->getDefault (); + } + + $sql = 'UPDATE `' . $this->prefix . 'feed` SET category=? WHERE category=?'; + $stm = $this->bd->prepare ($sql); + + $values = array ( + $newCat->id (), + $idOldCat + ); + + if ($stm && $stm->execute ($values)) { + return $stm->rowCount(); + } else { + $info = $stm->errorInfo(); + Minz_Log::record ('SQL error : ' . $info[2], Minz_Log::ERROR); + return false; + } + } + + public function deleteFeed ($id) { + /*//For MYISAM (MySQL 5.5-) without FOREIGN KEY + $sql = 'DELETE FROM `' . $this->prefix . 'entry` WHERE id_feed=?'; + $stm = $this->bd->prepare ($sql); + $values = array ($id); + if (!($stm && $stm->execute ($values))) { + $info = $stm->errorInfo(); + Minz_Log::record ('SQL error : ' . $info[2], Minz_Log::ERROR); + return false; + }*/ + + $sql = 'DELETE FROM `' . $this->prefix . 'feed` WHERE id=?'; + $stm = $this->bd->prepare ($sql); + + $values = array ($id); + + if ($stm && $stm->execute ($values)) { + return $stm->rowCount(); + } else { + $info = $stm->errorInfo(); + Minz_Log::record ('SQL error : ' . $info[2], Minz_Log::ERROR); + return false; + } + } + public function deleteFeedByCategory ($id) { + /*//For MYISAM (MySQL 5.5-) without FOREIGN KEY + $sql = 'DELETE FROM `' . $this->prefix . 'entry` e ' + . 'INNER JOIN `' . $this->prefix . 'feed` f ON e.id_feed = f.id ' + . 'WHERE f.category=?'; + $stm = $this->bd->prepare ($sql); + $values = array ($id); + if (!($stm && $stm->execute ($values))) { + $info = $stm->errorInfo(); + Minz_Log::record ('SQL error : ' . $info[2], Minz_Log::ERROR); + return false; + }*/ + + $sql = 'DELETE FROM `' . $this->prefix . 'feed` WHERE category=?'; + $stm = $this->bd->prepare ($sql); + + $values = array ($id); + + if ($stm && $stm->execute ($values)) { + return $stm->rowCount(); + } else { + $info = $stm->errorInfo(); + Minz_Log::record ('SQL error : ' . $info[2], Minz_Log::ERROR); + return false; + } + } + + public function searchById ($id) { + $sql = 'SELECT * FROM `' . $this->prefix . 'feed` WHERE id=?'; + $stm = $this->bd->prepare ($sql); + + $values = array ($id); + + $stm->execute ($values); + $res = $stm->fetchAll (PDO::FETCH_ASSOC); + $feed = HelperFeed::daoToFeed ($res); + + if (isset ($feed[$id])) { + return $feed[$id]; + } else { + return false; + } + } + public function searchByUrl ($url) { + $sql = 'SELECT * FROM `' . $this->prefix . 'feed` WHERE url=?'; + $stm = $this->bd->prepare ($sql); + + $values = array ($url); + + $stm->execute ($values); + $res = $stm->fetchAll (PDO::FETCH_ASSOC); + $feed = current (HelperFeed::daoToFeed ($res)); + + if (isset ($feed)) { + return $feed; + } else { + return false; + } + } + + public function listFeeds () { + $sql = 'SELECT * FROM `' . $this->prefix . 'feed` ORDER BY name'; + $stm = $this->bd->prepare ($sql); + $stm->execute (); + + return HelperFeed::daoToFeed ($stm->fetchAll (PDO::FETCH_ASSOC)); + } + + public function listFeedsOrderUpdate () { + $sql = 'SELECT * FROM `' . $this->prefix . 'feed` ORDER BY lastUpdate'; + $stm = $this->bd->prepare ($sql); + $stm->execute (); + + return HelperFeed::daoToFeed ($stm->fetchAll (PDO::FETCH_ASSOC)); + } + + public function listByCategory ($cat) { + $sql = 'SELECT * FROM `' . $this->prefix . 'feed` WHERE category=? ORDER BY name'; + $stm = $this->bd->prepare ($sql); + + $values = array ($cat); + + $stm->execute ($values); + + return HelperFeed::daoToFeed ($stm->fetchAll (PDO::FETCH_ASSOC)); + } + + public function countEntries ($id) { + $sql = 'SELECT COUNT(*) AS count FROM `' . $this->prefix . 'entry` WHERE id_feed=?'; + $stm = $this->bd->prepare ($sql); + $values = array ($id); + $stm->execute ($values); + $res = $stm->fetchAll (PDO::FETCH_ASSOC); + + return $res[0]['count']; + } + public function countNotRead ($id) { + $sql = 'SELECT COUNT(*) AS count FROM `' . $this->prefix . 'entry` WHERE id_feed=? AND is_read=0'; + $stm = $this->bd->prepare ($sql); + $values = array ($id); + $stm->execute ($values); + $res = $stm->fetchAll (PDO::FETCH_ASSOC); + + return $res[0]['count']; + } + public function updateCachedValues () { //For one single feed, call updateLastUpdate($id) + $sql = 'UPDATE `' . $this->prefix . 'feed` f ' + . 'INNER JOIN (' + . 'SELECT e.id_feed, ' + . 'COUNT(CASE WHEN e.is_read = 0 THEN 1 END) AS nbUnreads, ' + . 'COUNT(e.id) AS nbEntries ' + . 'FROM `' . $this->prefix . 'entry` e ' + . 'GROUP BY e.id_feed' + . ') x ON x.id_feed=f.id ' + . 'SET f.cache_nbEntries=x.nbEntries, f.cache_nbUnreads=x.nbUnreads'; + $stm = $this->bd->prepare ($sql); + + $values = array ($feed_id); + + if ($stm && $stm->execute ($values)) { + return $stm->rowCount(); + } else { + $info = $stm->errorInfo(); + Minz_Log::record ('SQL error : ' . $info[2], Minz_Log::ERROR); + return false; + } + } + + public function truncate ($id) { + $sql = 'DELETE e.* FROM `' . $this->prefix . 'entry` e WHERE e.id_feed=?'; + $stm = $this->bd->prepare($sql); + $values = array($id); + $this->bd->beginTransaction (); + if (!($stm && $stm->execute ($values))) { + $info = $stm->errorInfo(); + Minz_Log::record ('SQL error : ' . $info[2], Minz_Log::ERROR); + $this->bd->rollBack (); + return false; + } + $affected = $stm->rowCount(); + + $sql = 'UPDATE `' . $this->prefix . 'feed` f ' + . 'SET f.cache_nbEntries=0, f.cache_nbUnreads=0 WHERE f.id=?'; + $values = array ($id); + $stm = $this->bd->prepare ($sql); + if (!($stm && $stm->execute ($values))) { + $info = $stm->errorInfo(); + Minz_Log::record ('SQL error : ' . $info[2], Minz_Log::ERROR); + $this->bd->rollBack (); + return false; + } + + $this->bd->commit (); + return $affected; + } + + public function cleanOldEntries ($id, $date_min, $keep = 15) { //Remember to call updateLastUpdate($id) just after + $sql = 'DELETE e.* FROM `' . $this->prefix . 'entry` e ' + . 'WHERE e.id_feed = :id_feed AND e.id <= :id_max AND e.is_favorite = 0 AND e.id NOT IN ' + . '(SELECT id FROM (SELECT e2.id FROM `' . $this->prefix . 'entry` e2 WHERE e2.id_feed = :id_feed ORDER BY id DESC LIMIT :keep) keep)'; //Double select because of: MySQL doesn't yet support 'LIMIT & IN/ALL/ANY/SOME subquery' + $stm = $this->bd->prepare ($sql); + + $id_max = intval($date_min) . '000000'; + + $stm->bindParam(':id_feed', $id, PDO::PARAM_INT); + $stm->bindParam(':id_max', $id_max, PDO::PARAM_INT); + $stm->bindParam(':keep', $keep, PDO::PARAM_INT); + + if ($stm && $stm->execute ()) { + return $stm->rowCount(); + } else { + $info = $stm->errorInfo(); + Minz_Log::record ('SQL error : ' . $info[2], Minz_Log::ERROR); + return false; + } + } +} + +class HelperFeed { + public static function daoToFeed ($listDAO, $catID = null) { + $list = array (); + + if (!is_array ($listDAO)) { + $listDAO = array ($listDAO); + } + + foreach ($listDAO as $key => $dao) { + if (!isset ($dao['name'])) { + continue; + } + if (isset ($dao['id'])) { + $key = $dao['id']; + } + + $myFeed = new FreshRSS_Feed (isset($dao['url']) ? $dao['url'] : '', false); + $myFeed->_category ($catID === null ? $dao['category'] : $catID); + $myFeed->_name ($dao['name']); + $myFeed->_website ($dao['website'], false); + $myFeed->_description (isset($dao['description']) ? $dao['description'] : ''); + $myFeed->_lastUpdate (isset($dao['lastUpdate']) ? $dao['lastUpdate'] : 0); + $myFeed->_priority ($dao['priority']); + $myFeed->_pathEntries (isset($dao['pathEntries']) ? $dao['pathEntries'] : ''); + $myFeed->_httpAuth (isset($dao['httpAuth']) ? base64_decode ($dao['httpAuth']) : ''); + $myFeed->_error ($dao['error']); + $myFeed->_keepHistory (isset($dao['keep_history']) ? $dao['keep_history'] : ''); + $myFeed->_nbNotRead ($dao['cache_nbUnreads']); + $myFeed->_nbEntries ($dao['cache_nbEntries']); + if (isset ($dao['id'])) { + $myFeed->_id ($dao['id']); + } + $list[$key] = $myFeed; + } + + return $list; + } +} diff --git a/app/Models/Log.php b/app/Models/Log.php new file mode 100644 index 000000000..d2794458b --- /dev/null +++ b/app/Models/Log.php @@ -0,0 +1,26 @@ +date; + } + public function level () { + return $this->level; + } + public function info () { + return $this->information; + } + public function _date ($date) { + $this->date = $date; + } + public function _level ($level) { + $this->level = $level; + } + public function _info ($information) { + $this->information = $information; + } +} diff --git a/app/Models/LogDAO.php b/app/Models/LogDAO.php new file mode 100644 index 000000000..bf043fd6d --- /dev/null +++ b/app/Models/LogDAO.php @@ -0,0 +1,20 @@ +readLine ()) !== false) { + if (preg_match ('/^\[([^\[]+)\] \[([^\[]+)\] --- (.*)$/', $line, $matches)) { + $myLog = new FreshRSS_Log (); + $myLog->_date ($matches[1]); + $myLog->_level ($matches[2]); + $myLog->_info ($matches[3]); + $logs[] = $myLog; + } + } + return $logs; + } +} diff --git a/app/Models/Themes.php b/app/Models/Themes.php new file mode 100644 index 000000000..a52812339 --- /dev/null +++ b/app/Models/Themes.php @@ -0,0 +1,88 @@ + '✚', + 'all' => '☰', + 'bookmark' => '★', + 'category' => '☷', + 'category-white' => '☷', + 'close' => '❌', + 'configure' => '⚙', + 'down' => '▽', + 'favorite' => '★', + 'help' => 'ⓘ', + 'link' => '↗', + 'login' => '🔒', + 'logout' => '🔓', + 'next' => '⏩', + 'non-starred' => '☆', + 'prev' => '⏪', + 'read' => '☑', + 'unread' => '☐', + 'refresh' => '🔃', //↻ + 'search' => '🔍', + 'share' => '♺', + 'starred' => '★', + 'tag' => '⚐', + 'up' => '△', + ); + if (!isset($alts[$name])) { + return ''; + } + + $url = $name . '.svg'; + $url = isset(self::$themeIcons[$url]) ? (self::$themeIconsUrl . $url) : + (self::$defaultIconsUrl . $url); + + return $urlOnly ? Minz_Url::display($url) : + '' . $alts[$name] . ''; + } +} diff --git a/app/controllers/configureController.php b/app/controllers/configureController.php index deec54a2b..0e7fbbdde 100755 --- a/app/controllers/configureController.php +++ b/app/controllers/configureController.php @@ -1,33 +1,33 @@ view->conf) && !is_logged ()) { - Error::error ( + Minz_Error::error ( 403, - array ('error' => array (Translate::t ('access_denied'))) + array ('error' => array (Minz_Translate::t ('access_denied'))) ); } - $catDAO = new CategoryDAO (); + $catDAO = new FreshRSS_CategoryDAO (); $catDAO->checkDefault (); } public function categorizeAction () { - $feedDAO = new FeedDAO (); - $catDAO = new CategoryDAO (); + $feedDAO = new FreshRSS_FeedDAO (); + $catDAO = new FreshRSS_CategoryDAO (); $catDAO->checkDefault (); $defaultCategory = $catDAO->getDefault (); $defaultId = $defaultCategory->id (); - if (Request::isPost ()) { - $cats = Request::param ('categories', array ()); - $ids = Request::param ('ids', array ()); - $newCat = trim (Request::param ('new_category', '')); + if (Minz_Request::isPost ()) { + $cats = Minz_Request::param ('categories', array ()); + $ids = Minz_Request::param ('ids', array ()); + $newCat = trim (Minz_Request::param ('new_category', '')); foreach ($cats as $key => $name) { if (strlen ($name) > 0) { - $cat = new Category ($name); + $cat = new FreshRSS_Category ($name); $values = array ( 'name' => $cat->name (), 'color' => $cat->color () @@ -40,7 +40,7 @@ class configureController extends ActionController { } if ($newCat != '') { - $cat = new Category ($newCat); + $cat = new FreshRSS_Category ($newCat); $values = array ( 'id' => $cat->id (), 'name' => $cat->name (), @@ -55,11 +55,11 @@ class configureController extends ActionController { // notif $notif = array ( 'type' => 'good', - 'content' => Translate::t ('categories_updated') + 'content' => Minz_Translate::t ('categories_updated') ); - Session::_param ('notification', $notif); + Minz_Session::_param ('notification', $notif); - Request::forward (array ('c' => 'configure', 'a' => 'categorize'), true); + Minz_Request::forward (array ('c' => 'configure', 'a' => 'categorize'), true); } $this->view->categories = $catDAO->listCategories (false); @@ -67,17 +67,17 @@ class configureController extends ActionController { $this->view->feeds = $feedDAO->listFeeds (); $this->view->flux = false; - View::prependTitle (Translate::t ('categories_management') . ' - '); + Minz_View::prependTitle (Minz_Translate::t ('categories_management') . ' - '); } public function feedAction () { - $catDAO = new CategoryDAO (); + $catDAO = new FreshRSS_CategoryDAO (); $this->view->categories = $catDAO->listCategories (false); - $feedDAO = new FeedDAO (); + $feedDAO = new FreshRSS_FeedDAO (); $this->view->feeds = $feedDAO->listFeeds (); - $id = Request::param ('id'); + $id = Minz_Request::param ('id'); if ($id == false && !empty ($this->view->feeds)) { $id = current ($this->view->feeds)->id (); } @@ -87,22 +87,22 @@ class configureController extends ActionController { $this->view->flux = $this->view->feeds[$id]; if (!$this->view->flux) { - Error::error ( + Minz_Error::error ( 404, - array ('error' => array (Translate::t ('page_not_found'))) + array ('error' => array (Minz_Translate::t ('page_not_found'))) ); } else { - if (Request::isPost () && $this->view->flux) { - $name = Request::param ('name', ''); - $description = Request::param('description', ''); - $website = Request::param('website', ''); - $url = Request::param('url', ''); - $hist = Request::param ('keep_history', 'no'); - $cat = Request::param ('category', 0); - $path = Request::param ('path_entries', ''); - $priority = Request::param ('priority', 0); - $user = Request::param ('http_user', ''); - $pass = Request::param ('http_pass', ''); + if (Minz_Request::isPost () && $this->view->flux) { + $name = Minz_Request::param ('name', ''); + $description = Minz_Request::param('description', ''); + $website = Minz_Request::param('website', ''); + $url = Minz_Request::param('url', ''); + $hist = Minz_Request::param ('keep_history', 'no'); + $cat = Minz_Request::param ('category', 0); + $path = Minz_Request::param ('path_entries', ''); + $priority = Minz_Request::param ('priority', 0); + $user = Minz_Request::param ('http_user', ''); + $pass = Minz_Request::param ('http_pass', ''); $keep_history = false; if ($hist == 'yes') { @@ -131,58 +131,58 @@ class configureController extends ActionController { $notif = array ( 'type' => 'good', - 'content' => Translate::t ('feed_updated') + 'content' => Minz_Translate::t ('feed_updated') ); } else { $notif = array ( 'type' => 'bad', - 'content' => Translate::t ('error_occurred_update') + 'content' => Minz_Translate::t ('error_occurred_update') ); } - Session::_param ('notification', $notif); - Request::forward (array ('c' => 'configure', 'a' => 'feed', 'params' => array ('id' => $id)), true); + Minz_Session::_param ('notification', $notif); + Minz_Request::forward (array ('c' => 'configure', 'a' => 'feed', 'params' => array ('id' => $id)), true); } - View::prependTitle (Translate::t ('rss_feed_management') . ' - ' . $this->view->flux->name () . ' - '); + Minz_View::prependTitle (Minz_Translate::t ('rss_feed_management') . ' - ' . $this->view->flux->name () . ' - '); } } else { - View::prependTitle (Translate::t ('rss_feed_management') . ' - '); + Minz_View::prependTitle (Minz_Translate::t ('rss_feed_management') . ' - '); } } public function displayAction () { - if (Request::isPost ()) { + if (Minz_Request::isPost ()) { $current_token = $this->view->conf->token (); - $language = Request::param ('language', 'en'); - $nb = Request::param ('posts_per_page', 10); - $mode = Request::param ('view_mode', 'normal'); - $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', 'DESC'); - $old = Request::param ('old_entries', 3); - $mail = Request::param ('mail_login', false); - $anon = Request::param ('anon_access', 'no'); - $token = Request::param ('token', $current_token); - $openArticle = Request::param ('mark_open_article', 'no'); - $openSite = Request::param ('mark_open_site', 'no'); - $scroll = Request::param ('mark_scroll', 'no'); - $reception = Request::param ('mark_upon_reception', 'no'); - $theme = Request::param ('theme', 'default'); - $topline_read = Request::param ('topline_read', 'no'); - $topline_favorite = Request::param ('topline_favorite', 'no'); - $topline_date = Request::param ('topline_date', 'no'); - $topline_link = Request::param ('topline_link', 'no'); - $bottomline_read = Request::param ('bottomline_read', 'no'); - $bottomline_favorite = Request::param ('bottomline_favorite', 'no'); - $bottomline_sharing = Request::param ('bottomline_sharing', 'no'); - $bottomline_tags = Request::param ('bottomline_tags', 'no'); - $bottomline_date = Request::param ('bottomline_date', 'no'); - $bottomline_link = Request::param ('bottomline_link', 'no'); + $language = Minz_Request::param ('language', 'en'); + $nb = Minz_Request::param ('posts_per_page', 10); + $mode = Minz_Request::param ('view_mode', 'normal'); + $view = Minz_Request::param ('default_view', 'a'); + $auto_load_more = Minz_Request::param ('auto_load_more', 'no'); + $display = Minz_Request::param ('display_posts', 'no'); + $onread_jump_next = Minz_Request::param ('onread_jump_next', 'no'); + $lazyload = Minz_Request::param ('lazyload', 'no'); + $sort = Minz_Request::param ('sort_order', 'DESC'); + $old = Minz_Request::param ('old_entries', 3); + $mail = Minz_Request::param ('mail_login', false); + $anon = Minz_Request::param ('anon_access', 'no'); + $token = Minz_Request::param ('token', $current_token); + $openArticle = Minz_Request::param ('mark_open_article', 'no'); + $openSite = Minz_Request::param ('mark_open_site', 'no'); + $scroll = Minz_Request::param ('mark_scroll', 'no'); + $reception = Minz_Request::param ('mark_upon_reception', 'no'); + $theme = Minz_Request::param ('theme', 'default'); + $topline_read = Minz_Request::param ('topline_read', 'no'); + $topline_favorite = Minz_Request::param ('topline_favorite', 'no'); + $topline_date = Minz_Request::param ('topline_date', 'no'); + $topline_link = Minz_Request::param ('topline_link', 'no'); + $bottomline_read = Minz_Request::param ('bottomline_read', 'no'); + $bottomline_favorite = Minz_Request::param ('bottomline_favorite', 'no'); + $bottomline_sharing = Minz_Request::param ('bottomline_sharing', 'no'); + $bottomline_tags = Minz_Request::param ('bottomline_tags', 'no'); + $bottomline_date = Minz_Request::param ('bottomline_date', 'no'); + $bottomline_link = Minz_Request::param ('bottomline_link', 'no'); $this->view->conf->_language ($language); $this->view->conf->_postsPerPage (intval ($nb)); @@ -243,81 +243,81 @@ class configureController extends ActionController { 'bottomline_link' => $this->view->conf->bottomlineLink () ? 'yes' : 'no', ); - $confDAO = new RSSConfigurationDAO (); + $confDAO = new FreshRSS_ConfigurationDAO (); $confDAO->update ($values); - Session::_param ('conf', $this->view->conf); - Session::_param ('mail', $this->view->conf->mailLogin ()); + Minz_Session::_param ('conf', $this->view->conf); + Minz_Session::_param ('mail', $this->view->conf->mailLogin ()); - Session::_param ('language', $this->view->conf->language ()); + Minz_Session::_param ('language', $this->view->conf->language ()); Translate::reset (); // notif $notif = array ( 'type' => 'good', - 'content' => Translate::t ('configuration_updated') + 'content' => Minz_Translate::t ('configuration_updated') ); - Session::_param ('notification', $notif); + Minz_Session::_param ('notification', $notif); - Request::forward (array ('c' => 'configure', 'a' => 'display'), true); + Minz_Request::forward (array ('c' => 'configure', 'a' => 'display'), true); } - $this->view->themes = RSSThemes::get(); + $this->view->themes = FreshRSS_Themes::get(); - View::prependTitle (Translate::t ('general_and_reading_management') . ' - '); + Minz_View::prependTitle (Minz_Translate::t ('general_and_reading_management') . ' - '); - $entryDAO = new EntryDAO (); + $entryDAO = new FreshRSS_EntryDAO (); $this->view->nb_total = $entryDAO->count (); $this->view->size_total = $entryDAO->size (); } public function sharingAction () { - if (Request::isPost ()) { + if (Minz_Request::isPost ()) { $this->view->conf->_sharing (array ( - 'shaarli' => Request::param ('shaarli', ''), - 'poche' => Request::param ('poche', ''), - 'diaspora' => Request::param ('diaspora', ''), - 'twitter' => Request::param ('twitter', 'no') === 'yes', - 'g+' => Request::param ('g+', 'no') === 'yes', - 'facebook' => Request::param ('facebook', 'no') === 'yes', - 'email' => Request::param ('email', 'no') === 'yes', - 'print' => Request::param ('print', 'no') === 'yes' + 'shaarli' => Minz_Request::param ('shaarli', ''), + 'poche' => Minz_Request::param ('poche', ''), + 'diaspora' => Minz_Request::param ('diaspora', ''), + 'twitter' => Minz_Request::param ('twitter', 'no') === 'yes', + 'g+' => Minz_Request::param ('g+', 'no') === 'yes', + 'facebook' => Minz_Request::param ('facebook', 'no') === 'yes', + 'email' => Minz_Request::param ('email', 'no') === 'yes', + 'print' => Minz_Request::param ('print', 'no') === 'yes' )); - $confDAO = new RSSConfigurationDAO (); + $confDAO = new FreshRSS_ConfigurationDAO (); $confDAO->update ($this->view->conf->sharing ()); - Session::_param ('conf', $this->view->conf); + Minz_Session::_param ('conf', $this->view->conf); // notif $notif = array ( 'type' => 'good', - 'content' => Translate::t ('configuration_updated') + 'content' => Minz_Translate::t ('configuration_updated') ); - Session::_param ('notification', $notif); + Minz_Session::_param ('notification', $notif); - Request::forward (array ('c' => 'configure', 'a' => 'sharing'), true); + Minz_Request::forward (array ('c' => 'configure', 'a' => 'sharing'), true); } - View::prependTitle (Translate::t ('sharing_management') . ' - '); + Minz_View::prependTitle (Minz_Translate::t ('sharing_management') . ' - '); - $entryDAO = new EntryDAO (); + $entryDAO = new FreshRSS_EntryDAO (); $this->view->nb_total = $entryDAO->count (); } public function importExportAction () { - $catDAO = new CategoryDAO (); + $catDAO = new FreshRSS_CategoryDAO (); $this->view->categories = $catDAO->listCategories (); - $this->view->req = Request::param ('q'); + $this->view->req = Minz_Request::param ('q'); if ($this->view->req == 'export') { - View::_title ('freshrss_feeds.opml'); + Minz_View::_title ('freshrss_feeds.opml'); $this->view->_useLayout (false); header('Content-Type: application/xml; charset=utf-8'); header('Content-disposition: attachment; filename=freshrss_feeds.opml'); - $feedDAO = new FeedDAO (); - $catDAO = new CategoryDAO (); + $feedDAO = new FreshRSS_FeedDAO (); + $catDAO = new FreshRSS_CategoryDAO (); $list = array (); foreach ($catDAO->listCategories () as $key => $cat) { @@ -326,7 +326,7 @@ class configureController extends ActionController { } $this->view->categories = $list; - } elseif ($this->view->req == 'import' && Request::isPost ()) { + } elseif ($this->view->req == 'import' && Minz_Request::isPost ()) { if ($_FILES['file']['error'] == 0) { // on parse le fichier OPML pour récupérer les catégories et les flux associés try { @@ -336,20 +336,20 @@ class configureController extends ActionController { // On redirige vers le controller feed qui va se charger d'insérer les flux en BDD // les flux sont mis au préalable dans des variables de Request - Request::_param ('q', 'null'); - Request::_param ('categories', $categories); - Request::_param ('feeds', $feeds); - Request::forward (array ('c' => 'feed', 'a' => 'massiveImport')); - } catch (OpmlException $e) { + Minz_Request::_param ('q', 'null'); + Minz_Request::_param ('categories', $categories); + Minz_Request::_param ('feeds', $feeds); + Minz_Request::forward (array ('c' => 'feed', 'a' => 'massiveImport')); + } catch (FreshRSS_Opml_Exception $e) { Minz_Log::record ($e->getMessage (), Minz_Log::WARNING); $notif = array ( 'type' => 'bad', - 'content' => Translate::t ('bad_opml_file') + 'content' => Minz_Translate::t ('bad_opml_file') ); - Session::_param ('notification', $notif); + Minz_Session::_param ('notification', $notif); - Request::forward (array ( + Minz_Request::forward (array ( 'c' => 'configure', 'a' => 'importExport' ), true); @@ -357,13 +357,13 @@ class configureController extends ActionController { } } - $feedDAO = new FeedDAO (); + $feedDAO = new FreshRSS_FeedDAO (); $this->view->feeds = $feedDAO->listFeeds (); // au niveau de la vue, permet de ne pas voir un flux sélectionné dans la liste $this->view->flux = false; - View::prependTitle (Translate::t ('import_export_opml') . ' - '); + Minz_View::prependTitle (Translate::t ('import_export_opml') . ' - '); } public function shortcutAction () { @@ -379,8 +379,8 @@ class configureController extends ActionController { 'prev_entry', 'next_page', 'prev_page', 'collapse_entry', 'load_more'); - if (Request::isPost ()) { - $shortcuts = Request::param ('shortcuts'); + if (Minz_Request::isPost ()) { + $shortcuts = Minz_Request::param ('shortcuts'); $shortcuts_ok = array (); foreach ($shortcuts as $key => $value) { @@ -396,20 +396,20 @@ class configureController extends ActionController { 'shortcuts' => $this->view->conf->shortcuts () ); - $confDAO = new RSSConfigurationDAO (); + $confDAO = new FreshRSS_ConfigurationDAO (); $confDAO->update ($values); - Session::_param ('conf', $this->view->conf); + Minz_Session::_param ('conf', $this->view->conf); // notif $notif = array ( 'type' => 'good', - 'content' => Translate::t ('shortcuts_updated') + 'content' => Minz_Translate::t ('shortcuts_updated') ); - Session::_param ('notification', $notif); + Minz_Session::_param ('notification', $notif); - Request::forward (array ('c' => 'configure', 'a' => 'shortcut'), true); + Minz_Request::forward (array ('c' => 'configure', 'a' => 'shortcut'), true); } - View::prependTitle (Translate::t ('shortcuts_management') . ' - '); + Minz_View::prependTitle (Minz_Translate::t ('shortcuts_management') . ' - '); } } diff --git a/app/controllers/entryController.php b/app/controllers/entryController.php index c01139ba4..a332ca8a9 100755 --- a/app/controllers/entryController.php +++ b/app/controllers/entryController.php @@ -1,46 +1,46 @@ view->conf) && !is_logged ()) { - Error::error ( + Minz_Error::error ( 403, - array ('error' => array (Translate::t ('access_denied'))) + array ('error' => array (Minz_Translate::t ('access_denied'))) ); } $this->params = array (); $this->redirect = false; - $ajax = Request::param ('ajax'); + $ajax = Minz_Request::param ('ajax'); if ($ajax) { $this->view->_useLayout (false); } } public function lastAction () { - $ajax = Request::param ('ajax'); + $ajax = Minz_Request::param ('ajax'); if (!$ajax && $this->redirect) { - Request::forward (array ( + Minz_Request::forward (array ( 'c' => 'index', 'a' => 'index', 'params' => $this->params ), true); } else { - Request::_param ('ajax'); + Minz_Request::_param ('ajax'); } } public function readAction () { $this->redirect = true; - $id = Request::param ('id'); - $is_read = Request::param ('is_read'); - $get = Request::param ('get'); - $nextGet = Request::param ('nextGet', $get); - $idMax = Request::param ('idMax', 0); + $id = Minz_Request::param ('id'); + $is_read = Minz_Request::param ('is_read'); + $get = Minz_Request::param ('get'); + $nextGet = Minz_Request::param ('nextGet', $get); + $idMax = Minz_Request::param ('idMax', 0); $is_read = !!$is_read; - $entryDAO = new EntryDAO (); + $entryDAO = new FreshRSS_EntryDAO (); if ($id == false) { if (!$get) { $entryDAO->markReadEntries ($idMax); @@ -68,9 +68,9 @@ class entryController extends ActionController { $notif = array ( 'type' => 'good', - 'content' => Translate::t ('feeds_marked_read') + 'content' => Minz_Translate::t ('feeds_marked_read') ); - Session::_param ('notification', $notif); + Minz_Session::_param ('notification', $notif); } else { $entryDAO->markRead ($id, $is_read); } @@ -79,10 +79,10 @@ class entryController extends ActionController { public function bookmarkAction () { $this->redirect = true; - $id = Request::param ('id'); + $id = Minz_Request::param ('id'); if ($id) { - $entryDAO = new EntryDAO (); - $entryDAO->markFavorite ($id, Request::param ('is_favorite')); + $entryDAO = new FreshRSS_EntryDAO (); + $entryDAO->markFavorite ($id, Minz_Request::param ('is_favorite')); } } @@ -93,18 +93,18 @@ class entryController extends ActionController { // La table des entrées a tendance à grossir énormément // Cette action permet d'optimiser cette table permettant de grapiller un peu de place // Cette fonctionnalité n'est à appeler qu'occasionnellement - $entryDAO = new EntryDAO(); + $entryDAO = new FreshRSS_EntryDAO(); $entryDAO->optimizeTable(); invalidateHttpCache(); $notif = array ( 'type' => 'good', - 'content' => Translate::t ('optimization_complete') + 'content' => Minz_Translate::t ('optimization_complete') ); - Session::_param ('notification', $notif); + Minz_Session::_param ('notification', $notif); - Request::forward(array( + Minz_Request::forward(array( 'c' => 'configure', 'a' => 'display' ), true); diff --git a/app/controllers/errorController.php b/app/controllers/errorController.php index 092609280..d1c2f8fec 100644 --- a/app/controllers/errorController.php +++ b/app/controllers/errorController.php @@ -1,8 +1,8 @@ view->code = 'Error 403 - Forbidden'; break; @@ -19,8 +19,8 @@ class ErrorController extends ActionController { $this->view->code = 'Error 404 - Not found'; } - $this->view->logs = Request::param ('logs'); + $this->view->logs = Minz_Request::param ('logs'); - View::prependTitle ($this->view->code . ' - '); + Minz_View::prependTitle ($this->view->code . ' - '); } } diff --git a/app/controllers/feedController.php b/app/controllers/feedController.php index 24b8627ff..e4014c326 100755 --- a/app/controllers/feedController.php +++ b/app/controllers/feedController.php @@ -1,22 +1,22 @@ view->conf->token(); - $token_param = Request::param ('token', ''); + $token_param = Minz_Request::param ('token', ''); $token_is_ok = ($token != '' && $token == $token_param); - $action = Request::actionName (); + $action = Minz_Request::actionName (); if (login_is_conf ($this->view->conf) && !is_logged () && !($token_is_ok && $action == 'actualize')) { - Error::error ( + Minz_Error::error ( 403, - array ('error' => array (Translate::t ('access_denied'))) + array ('error' => array (Minz_Translate::t ('access_denied'))) ); } - $this->catDAO = new CategoryDAO (); + $this->catDAO = new FreshRSS_CategoryDAO (); $this->catDAO->checkDefault (); } @@ -32,21 +32,21 @@ class feedController extends ActionController { public function addAction () { @set_time_limit(300); - if (Request::isPost ()) { - $url = Request::param ('url_rss'); - $cat = Request::param ('category', false); + if (Minz_Request::isPost ()) { + $url = Minz_Request::param ('url_rss'); + $cat = Minz_Request::param ('category', false); if ($cat === false) { $def_cat = $this->catDAO->getDefault (); $cat = $def_cat->id (); } - $user = Request::param ('username'); - $pass = Request::param ('password'); + $user = Minz_Request::param ('username'); + $pass = Minz_Request::param ('password'); $params = array (); $transactionStarted = false; try { - $feed = new Feed ($url); + $feed = new FreshRSS_Feed ($url); $feed->_category ($cat); $httpAuth = ''; @@ -57,7 +57,7 @@ class feedController extends ActionController { $feed->load (); - $feedDAO = new FeedDAO (); + $feedDAO = new FreshRSS_FeedDAO (); $values = array ( 'url' => $feed->url (), 'category' => $feed->category (), @@ -72,25 +72,25 @@ class feedController extends ActionController { // on est déjà abonné à ce flux $notif = array ( 'type' => 'bad', - 'content' => Translate::t ('already_subscribed', $feed->name ()) + 'content' => Minz_Translate::t ('already_subscribed', $feed->name ()) ); - Session::_param ('notification', $notif); + Minz_Session::_param ('notification', $notif); } else { $id = $feedDAO->addFeed ($values); if (!$id) { // problème au niveau de la base de données $notif = array ( 'type' => 'bad', - 'content' => Translate::t ('feed_not_added', $feed->name ()) + 'content' => Minz_Translate::t ('feed_not_added', $feed->name ()) ); - Session::_param ('notification', $notif); + Minz_Session::_param ('notification', $notif); } else { $feed->_id ($id); $feed->faviconPrepare(); $is_read = $this->view->conf->markUponReception() === 'yes' ? 1 : 0; - $entryDAO = new EntryDAO (); + $entryDAO = new FreshRSS_EntryDAO (); $entries = $feed->entries (); usort($entries, 'self::entryDateComparer'); @@ -118,68 +118,68 @@ class feedController extends ActionController { // ok, ajout terminé $notif = array ( 'type' => 'good', - 'content' => Translate::t ('feed_added', $feed->name ()) + 'content' => Minz_Translate::t ('feed_added', $feed->name ()) ); - Session::_param ('notification', $notif); + Minz_Session::_param ('notification', $notif); // permet de rediriger vers la page de conf du flux $params['id'] = $feed->id (); } } - } catch (BadUrlException $e) { + } catch (FreshRSS_BadUrl_Exception $e) { Minz_Log::record ($e->getMessage (), Minz_Log::WARNING); $notif = array ( 'type' => 'bad', - 'content' => Translate::t ('invalid_url', $url) + 'content' => Minz_Translate::t ('invalid_url', $url) ); - Session::_param ('notification', $notif); - } catch (FeedException $e) { + Minz_Session::_param ('notification', $notif); + } catch (FreshRSS_Feed_Exception $e) { Minz_Log::record ($e->getMessage (), Minz_Log::WARNING); $notif = array ( 'type' => 'bad', - 'content' => Translate::t ('internal_problem_feed') + 'content' => Minz_Translate::t ('internal_problem_feed') ); - Session::_param ('notification', $notif); - } catch (FileNotExistException $e) { + Minz_Session::_param ('notification', $notif); + } catch (Minz_FileNotExistException $e) { // Répertoire de cache n'existe pas Minz_Log::record ($e->getMessage (), Minz_Log::ERROR); $notif = array ( 'type' => 'bad', - 'content' => Translate::t ('internal_problem_feed') + 'content' => Minz_Translate::t ('internal_problem_feed') ); - Session::_param ('notification', $notif); + Minz_Session::_param ('notification', $notif); } if ($transactionStarted) { $feedDAO->rollBack (); } - Request::forward (array ('c' => 'configure', 'a' => 'feed', 'params' => $params), true); + Minz_Request::forward (array ('c' => 'configure', 'a' => 'feed', 'params' => $params), true); } } public function truncateAction () { - if (Request::isPost ()) { - $id = Request::param ('id'); - $feedDAO = new FeedDAO (); + if (Minz_Request::isPost ()) { + $id = Minz_Request::param ('id'); + $feedDAO = new FreshRSS_FeedDAO (); $n = $feedDAO->truncate($id); $notif = array( 'type' => $n === false ? 'bad' : 'good', - 'content' => Translate::t ('n_entries_deleted', $n) + 'content' => Minz_Translate::t ('n_entries_deleted', $n) ); - Session::_param ('notification', $notif); + Minz_Session::_param ('notification', $notif); invalidateHttpCache(); - Request::forward (array ('c' => 'configure', 'a' => 'feed', 'params' => array('id' => $id)), true); + Minz_Request::forward (array ('c' => 'configure', 'a' => 'feed', 'params' => array('id' => $id)), true); } } public function actualizeAction () { @set_time_limit(300); - $feedDAO = new FeedDAO (); - $entryDAO = new EntryDAO (); + $feedDAO = new FreshRSS_FeedDAO (); + $entryDAO = new FreshRSS_EntryDAO (); - $id = Request::param ('id'); - $force = Request::param ('force', false); + $id = Minz_Request::param ('id'); + $force = Minz_Request::param ('force', false); // on créé la liste des flux à mettre à actualiser // si on veut mettre un flux à jour spécifiquement, on le met @@ -236,7 +236,7 @@ class feedController extends ActionController { $feedDAO->updateLastUpdate ($feed->id ()); $feedDAO->commit (); $flux_update++; - } catch (FeedException $e) { + } catch (FreshRSS_Feed_Exception $e) { Minz_Log::record ($e->getMessage (), Minz_Log::NOTICE); $feedDAO->updateLastUpdate ($feed->id (), 1); } @@ -254,19 +254,19 @@ class feedController extends ActionController { // on a mis un seul flux à jour $notif = array ( 'type' => 'good', - 'content' => Translate::t ('feed_actualized', $feed->name ()) + 'content' => Minz_Translate::t ('feed_actualized', $feed->name ()) ); } elseif ($flux_update > 1) { // plusieurs flux on été mis à jour $notif = array ( 'type' => 'good', - 'content' => Translate::t ('n_feeds_actualized', $flux_update) + 'content' => Minz_Translate::t ('n_feeds_actualized', $flux_update) ); } else { // aucun flux n'a été mis à jour, oups $notif = array ( 'type' => 'bad', - 'content' => Translate::t ('no_feed_actualized') + 'content' => Minz_Translate::t ('no_feed_actualized') ); } @@ -277,9 +277,9 @@ class feedController extends ActionController { $url['params'] = array ('get' => 'f_' . $feed->id ()); } - if (Request::param ('ajax', 0) === 0) { - Session::_param ('notification', $notif); - Request::forward ($url, true); + if (Minz_Request::param ('ajax', 0) === 0) { + Minz_Session::_param ('notification', $notif); + Minz_Request::forward ($url, true); } else { // Une requête Ajax met un seul flux à jour. // Comme en principe plusieurs requêtes ont lieu, @@ -288,9 +288,9 @@ class feedController extends ActionController { // ressenti utilisateur $notif = array ( 'type' => 'good', - 'content' => Translate::t ('feeds_actualized') + 'content' => Minz_Translate::t ('feeds_actualized') ); - Session::_param ('notification', $notif); + Minz_Session::_param ('notification', $notif); // et on désactive le layout car ne sert à rien $this->view->_useLayout (false); } @@ -299,11 +299,11 @@ class feedController extends ActionController { public function massiveImportAction () { @set_time_limit(300); - $entryDAO = new EntryDAO (); - $feedDAO = new FeedDAO (); + $entryDAO = new FreshRSS_EntryDAO (); + $feedDAO = new FreshRSS_FeedDAO (); - $categories = Request::param ('categories', array (), true); - $feeds = Request::param ('feeds', array (), true); + $categories = Minz_Request::param ('categories', array (), true); + $feeds = Minz_Request::param ('feeds', array (), true); // on ajoute les catégories en masse dans une fonction à part $this->addCategories ($categories); @@ -341,78 +341,78 @@ class feedController extends ActionController { $error = true; } } - } catch (FeedException $e) { + } catch (FreshRSS_Feed_Exception $e) { $error = true; Minz_Log::record ($e->getMessage (), Minz_Log::WARNING); } } if ($error) { - $res = Translate::t ('feeds_imported_with_errors'); + $res = Minz_Translate::t ('feeds_imported_with_errors'); } else { - $res = Translate::t ('feeds_imported'); + $res = Minz_Translate::t ('feeds_imported'); } $notif = array ( 'type' => 'good', 'content' => $res ); - Session::_param ('notification', $notif); - Session::_param ('actualize_feeds', true); + Minz_Session::_param ('notification', $notif); + Minz_Session::_param ('actualize_feeds', true); // et on redirige vers la page d'accueil - Request::forward (array ( + Minz_Request::forward (array ( 'c' => 'index', 'a' => 'index' ), true); } public function deleteAction () { - if (Request::isPost ()) { - $type = Request::param ('type', 'feed'); - $id = Request::param ('id'); + if (Minz_Request::isPost ()) { + $type = Minz_Request::param ('type', 'feed'); + $id = Minz_Request::param ('id'); - $feedDAO = new FeedDAO (); + $feedDAO = new FreshRSS_FeedDAO (); if ($type == 'category') { if ($feedDAO->deleteFeedByCategory ($id)) { $notif = array ( 'type' => 'good', - 'content' => Translate::t ('category_emptied') + 'content' => Minz_Translate::t ('category_emptied') ); //TODO: Delete old favicons } else { $notif = array ( 'type' => 'bad', - 'content' => Translate::t ('error_occured') + 'content' => Minz_Translate::t ('error_occured') ); } } else { if ($feedDAO->deleteFeed ($id)) { $notif = array ( 'type' => 'good', - 'content' => Translate::t ('feed_deleted') + 'content' => Minz_Translate::t ('feed_deleted') ); Feed::faviconDelete($id); } else { $notif = array ( 'type' => 'bad', - 'content' => Translate::t ('error_occured') + 'content' => Minz_Translate::t ('error_occured') ); } } - Session::_param ('notification', $notif); + Minz_Session::_param ('notification', $notif); if ($type == 'category') { - Request::forward (array ('c' => 'configure', 'a' => 'categorize'), true); + Minz_Request::forward (array ('c' => 'configure', 'a' => 'categorize'), true); } else { - Request::forward (array ('c' => 'configure', 'a' => 'feed'), true); + Minz_Request::forward (array ('c' => 'configure', 'a' => 'feed'), true); } } } private function addCategories ($categories) { - $catDAO = new CategoryDAO (); + $catDAO = new FreshRSS_CategoryDAO (); foreach ($categories as $cat) { if (!$catDAO->searchByName ($cat->name ())) { diff --git a/app/controllers/indexController.php b/app/controllers/indexController.php index 9c1e18f0b..16a053ba3 100755 --- a/app/controllers/indexController.php +++ b/app/controllers/indexController.php @@ -1,6 +1,6 @@ entryDAO = new EntryDAO (); - $this->feedDAO = new FeedDAO (); - $this->catDAO = new CategoryDAO (); + $this->entryDAO = new FreshRSS_EntryDAO (); + $this->feedDAO = new FreshRSS_FeedDAO (); + $this->catDAO = new FreshRSS_CategoryDAO (); } public function indexAction () { - $output = Request::param ('output'); + $output = Minz_Request::param ('output'); $token = $this->view->conf->token(); - $token_param = Request::param ('token', ''); + $token_param = Minz_Request::param ('token', ''); $token_is_ok = ($token != '' && $token === $token_param); // check if user is log in @@ -30,7 +30,7 @@ class indexController extends ActionController { } // construction of RSS url of this feed - $params = Request::params (); + $params = Minz_Request::params (); $params['output'] = 'rss'; if (isset ($params['search'])) { $params['search'] = urlencode ($params['search']); @@ -51,10 +51,10 @@ class indexController extends ActionController { $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'))); + Minz_View::appendScript (Minz_Url::display ('/scripts/shortcut.js?' . @filemtime(PUBLIC_PATH . '/scripts/shortcut.js'))); if ($output === 'global') { - View::appendScript (Url::display ('/scripts/global_view.js?' . @filemtime(PUBLIC_PATH . '/scripts/global_view.js'))); + Minz_View::appendScript (Minz_Url::display ('/scripts/global_view.js?' . @filemtime(PUBLIC_PATH . '/scripts/global_view.js'))); } } @@ -65,14 +65,14 @@ class indexController extends ActionController { $this->view->get_c = ''; $this->view->get_f = ''; - $get = Request::param ('get', 'a'); + $get = Minz_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 ( + Minz_Error::error ( 404, - array ('error' => array (Translate::t ('page_not_found'))) + array ('error' => array (Minz_Translate::t ('page_not_found'))) ); return; } @@ -80,25 +80,25 @@ class indexController extends ActionController { $this->view->nb_not_read = HelperCategory::CountUnreads($this->view->cat_aside, 1); // mise à jour des titres - $this->view->rss_title = $this->view->currentName . ' | ' . View::title(); + $this->view->rss_title = $this->view->currentName . ' | ' . Minz_View::title(); if ($this->view->nb_not_read > 0) { - View::appendTitle (' (' . $this->view->nb_not_read . ')'); + Minz_View::appendTitle (' (' . $this->view->nb_not_read . ')'); } - View::prependTitle ( + Minz_View::prependTitle ( $this->view->currentName . ($this->nb_not_read_cat > 0 ? ' (' . $this->nb_not_read_cat . ')' : '') . ' - ' ); // 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->state = $state = Minz_Request::param ('state', $this->view->conf->defaultView ()); + $filter = Minz_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', ''); + $this->view->order = $order = Minz_Request::param ('order', $this->view->conf->sortOrder ()); + $nb = Minz_Request::param ('nb', $this->view->conf->postsPerPage ()); + $first = Minz_Request::param ('next', ''); if ($state === 'not_read') { //Any unread article in this category at all? switch ($getType) { @@ -143,11 +143,11 @@ class indexController extends ActionController { } $this->view->entries = $entries; - } catch (EntriesGetterException $e) { + } catch (FreshRSS_EntriesGetter_Exception $e) { Minz_Log::record ($e->getMessage (), Minz_Log::NOTICE); - Error::error ( + Minz_Error::error ( 404, - array ('error' => array (Translate::t ('page_not_found'))) + array ('error' => array (Minz_Translate::t ('page_not_found'))) ); } } @@ -160,11 +160,11 @@ class indexController extends ActionController { private function checkAndProcessType ($getType, $getId) { switch ($getType) { case 'a': - $this->view->currentName = Translate::t ('your_rss_feeds'); + $this->view->currentName = Minz_Translate::t ('your_rss_feeds'); $this->view->get_c = $getType; return true; case 's': - $this->view->currentName = Translate::t ('your_favorites'); + $this->view->currentName = Minz_Translate::t ('your_favorites'); $this->view->get_c = $getType; return true; case 'c': @@ -200,35 +200,35 @@ class indexController extends ActionController { } public function aboutAction () { - View::prependTitle (Translate::t ('about') . ' - '); + Minz_View::prependTitle (Minz_Translate::t ('about') . ' - '); } public function logsAction () { if (login_is_conf ($this->view->conf) && !is_logged ()) { - Error::error ( + Minz_Error::error ( 403, - array ('error' => array (Translate::t ('access_denied'))) + array ('error' => array (Minz_Translate::t ('access_denied'))) ); } - View::prependTitle (Translate::t ('logs') . ' - '); + Minz_View::prependTitle (Minz_Translate::t ('logs') . ' - '); - if (Request::isPost ()) { + if (Minz_Request::isPost ()) { file_put_contents(LOG_PATH . '/application.log', ''); } $logs = array(); try { - $logDAO = new LogDAO (); + $logDAO = new FreshRSS_LogDAO (); $logs = $logDAO->lister (); $logs = array_reverse ($logs); - } catch(FileNotExistException $e) { + } catch (Minz_FileNotExistException $e) { } //gestion pagination - $page = Request::param ('page', 1); - $this->view->logsPaginator = new Paginator ($logs); + $page = Minz_Request::param ('page', 1); + $this->view->logsPaginator = new Minz_Paginator ($logs); $this->view->logsPaginator->_nbItemsPerPage (50); $this->view->logsPaginator->_currentPage ($page); } @@ -237,9 +237,9 @@ class indexController extends ActionController { $this->view->_useLayout (false); $url = 'https://verifier.login.persona.org/verify'; - $assert = Request::param ('assertion'); + $assert = Minz_Request::param ('assertion'); $params = 'assertion=' . $assert . '&audience=' . - urlencode (Url::display (null, 'php', true)); + urlencode (Minz_Url::display (null, 'php', true)); $ch = curl_init (); $options = array ( CURLOPT_URL => $url, @@ -253,12 +253,12 @@ class indexController extends ActionController { $res = json_decode ($result, true); if ($res['status'] === 'okay' && $res['email'] === $this->view->conf->mailLogin ()) { - Session::_param ('mail', $res['email']); + Minz_Session::_param ('mail', $res['email']); invalidateHttpCache(); } else { $res = array (); $res['status'] = 'failure'; - $res['reason'] = Translate::t ('invalid_login'); + $res['reason'] = Minz_Translate::t ('invalid_login'); } header('Content-Type: application/json; charset=UTF-8'); @@ -267,7 +267,7 @@ class indexController extends ActionController { public function logoutAction () { $this->view->_useLayout (false); - Session::_param ('mail'); + Minz_Session::_param ('mail'); invalidateHttpCache(); } } diff --git a/app/controllers/javascriptController.php b/app/controllers/javascriptController.php index 291474130..e7e25f656 100755 --- a/app/controllers/javascriptController.php +++ b/app/controllers/javascriptController.php @@ -1,13 +1,13 @@ view->_useLayout (false); header('Content-type: text/javascript'); } public function actualizeAction () { - $feedDAO = new FeedDAO (); + $feedDAO = new FreshRSS_FeedDAO (); $this->view->feeds = $feedDAO->listFeeds (); } } diff --git a/app/layout/aside_configure.phtml b/app/layout/aside_configure.phtml index 7dbe445b2..aa46af95d 100644 --- a/app/layout/aside_configure.phtml +++ b/app/layout/aside_configure.phtml @@ -1,13 +1,13 @@ diff --git a/app/layout/aside_feed.phtml b/app/layout/aside_feed.phtml index 2ce0b3ba4..7fbccce1e 100644 --- a/app/layout/aside_feed.phtml +++ b/app/layout/aside_feed.phtml @@ -1,17 +1,17 @@ diff --git a/app/layout/aside_flux.phtml b/app/layout/aside_flux.phtml index ce5ded230..9a6b16d58 100644 --- a/app/layout/aside_flux.phtml +++ b/app/layout/aside_flux.phtml @@ -1,23 +1,23 @@
    - +
      conf) || is_logged ()) { ?>
    • - - + +
    • conf)) { ?> -
    • +
    • @@ -25,8 +25,8 @@
    • @@ -38,7 +38,7 @@ get_c == $cat->id ()) { $c_active = true; } ?>
        @@ -49,7 +49,7 @@
      • ✇ @@ -67,13 +67,13 @@ diff --git a/app/layout/header.phtml b/app/layout/header.phtml index 12af6057a..6cb1380a3 100644 --- a/app/layout/header.phtml +++ b/app/layout/header.phtml @@ -1,9 +1,9 @@ conf)) { ?> @@ -12,8 +12,8 @@ @@ -24,25 +24,25 @@ $this->conf->anonAccess() == 'yes') { ?>
        - - + + - + - + - + - +
        @@ -53,19 +53,19 @@ @@ -74,7 +74,7 @@ if (login_is_conf ($this->conf) && !is_logged ()) { ?>
        - +
    diff --git a/app/layout/layout.phtml b/app/layout/layout.phtml index ac00e8fd0..b7c34f04e 100644 --- a/app/layout/layout.phtml +++ b/app/layout/layout.phtml @@ -11,19 +11,19 @@ //]]> nextId)) { - $params = Request::params (); + $params = Minz_Request::params (); $params['next'] = $this->nextId; ?> - + - + rss_url)) { ?> - + - - - - + + + + @@ -39,7 +39,7 @@ ?>
    notification['content']; ?> - +
    diff --git a/app/layout/nav_entries.phtml b/app/layout/nav_entries.phtml index 0811fe8fa..3141e92a0 100644 --- a/app/layout/nav_entries.phtml +++ b/app/layout/nav_entries.phtml @@ -1,5 +1,5 @@ \ No newline at end of file diff --git a/app/layout/nav_menu.phtml b/app/layout/nav_menu.phtml index f3e985dc0..92a987aed 100644 --- a/app/layout/nav_menu.phtml +++ b/app/layout/nav_menu.phtml @@ -1,22 +1,22 @@