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/Entry.php') 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/Entry.php') 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 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/Entry.php') 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/Entry.php') 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/Entry.php') 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 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/Entry.php') 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 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/Entry.php') 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 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/Entry.php') 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 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/Entry.php') 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 @@
    • - - + +
    • -- 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/Entry.php') 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 @@
      • - next != '') { ?> - next; ?> + nextId)) { ?> + nextId; ?> diff --git a/app/views/helpers/view/normal_view.phtml b/app/views/helpers/view/normal_view.phtml index 0a03ea15a..1a7efa58f 100644 --- a/app/views/helpers/view/normal_view.phtml +++ b/app/views/helpers/view/normal_view.phtml @@ -3,8 +3,7 @@ $this->partial ('aside_flux'); $this->partial ('nav_menu'); -if (isset ($this->entryPaginator) && !$this->entryPaginator->isEmpty ()) { - $items = $this->entryPaginator->items (); +if (!empty($this->entries)) { ?>
        @@ -23,8 +22,7 @@ if (isset ($this->entryPaginator) && !$this->entryPaginator->isEmpty ()) { $email = $this->conf->sharing ('email'); $print = $this->conf->sharing ('print'); ?> - - + entries as $item) { ?> isDay (Days::TODAY)) { ?>
        @@ -199,7 +197,7 @@ if (isset ($this->entryPaginator) && !$this->entryPaginator->isEmpty ()) {
        - entryPaginator->render ('pagination.phtml', 'next'); ?> + renderHelper('pagination'); ?>
        partial ('nav_entries'); ?> diff --git a/app/views/helpers/view/reader_view.phtml b/app/views/helpers/view/reader_view.phtml index 9b8ec6cde..30226af42 100644 --- a/app/views/helpers/view/reader_view.phtml +++ b/app/views/helpers/view/reader_view.phtml @@ -1,12 +1,11 @@ partial ('nav_menu'); -if (isset ($this->entryPaginator) && !$this->entryPaginator->isEmpty ()) { - $items = $this->entryPaginator->items (); +if (!empty($this->entries)) { ?>
        - + entries as $item) { ?>
        @@ -38,7 +37,7 @@ if (isset ($this->entryPaginator) && !$this->entryPaginator->isEmpty ()) {
        - entryPaginator->render ('pagination.phtml', 'next'); ?> + renderHelper('pagination'); ?>
        diff --git a/app/views/helpers/view/rss_view.phtml b/app/views/helpers/view/rss_view.phtml index e34f3b8b5..460146dc0 100755 --- a/app/views/helpers/view/rss_view.phtml +++ b/app/views/helpers/view/rss_view.phtml @@ -8,8 +8,7 @@ GMT entryPaginator->items (); -foreach ($items as $item) { +foreach ($this->entries as $item) { ?> <?php echo $item->title (); ?> -- cgit v1.2.3 From baa8d21341d3f35a06815fd3f4ec536ef6ac2f3e Mon Sep 17 00:00:00 2001 From: Alexandre Alapetite Date: Sun, 1 Dec 2013 21:38:20 +0100 Subject: PHP ctype_digit MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Utilisation d'une fonction plus appropriée pour tester si une chaîne représente un nombre entier Corrige un bug de date --- app/models/Entry.php | 2 +- app/models/Feed.php | 6 +++--- app/models/RSSConfiguration.php | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) (limited to 'app/models/Entry.php') diff --git a/app/models/Entry.php b/app/models/Entry.php index ae8facf68..196823f67 100755 --- a/app/models/Entry.php +++ b/app/models/Entry.php @@ -106,7 +106,7 @@ class Entry extends Model { $this->link = $value; } public function _date ($value) { - if (is_int ($value)) { + if (ctype_digit ($value)) { $this->date = intval ($value); } else { $this->date = time (); diff --git a/app/models/Feed.php b/app/models/Feed.php index 954d1d45c..f183b2aa7 100644 --- a/app/models/Feed.php +++ b/app/models/Feed.php @@ -150,7 +150,7 @@ class Feed extends Model { $this->lastUpdate = $value; } public function _priority ($value) { - $this->priority = is_numeric ($value) ? intval ($value) : 10; + $this->priority = ctype_digit ($value) ? intval ($value) : 10; } public function _pathEntries ($value) { $this->pathEntries = $value; @@ -175,10 +175,10 @@ class Feed extends Model { $this->keep_history = $value; } public function _nbNotRead ($value) { - $this->nbNotRead = is_numeric ($value) ? intval ($value) : -1; + $this->nbNotRead = ctype_digit ($value) ? intval ($value) : -1; } public function _nbEntries ($value) { - $this->nbEntries = is_numeric ($value) ? intval ($value) : -1; + $this->nbEntries = ctype_digit ($value) ? intval ($value) : -1; } public function load () { diff --git a/app/models/RSSConfiguration.php b/app/models/RSSConfiguration.php index 007c1c0f5..5458ba2f3 100755 --- a/app/models/RSSConfiguration.php +++ b/app/models/RSSConfiguration.php @@ -171,7 +171,7 @@ class RSSConfiguration extends Model { $this->language = $value; } public function _postsPerPage ($value) { - if (is_int (intval ($value)) && $value > 0) { + if (ctype_digit ($value) && $value > 0) { $this->posts_per_page = $value; } else { $this->posts_per_page = 10; @@ -216,7 +216,7 @@ class RSSConfiguration extends Model { $this->sort_order = $value === 'ASC' ? 'ASC' : 'DESC'; } public function _oldEntries ($value) { - if (is_int (intval ($value)) && $value > 0) { + if (ctype_digit ($value) && $value > 0) { $this->old_entries = $value; } else { $this->old_entries = 3; -- cgit v1.2.3 From 56b269cef6bc54fa8d8fc69ff0f0e8b2ffb36afb Mon Sep 17 00:00:00 2001 From: Alexandre Alapetite Date: Mon, 2 Dec 2013 20:12:55 +0100 Subject: PHP : suppression autres alertes Voir https://github.com/marienfressinaud/FreshRSS/issues/310 --- app/layout/nav_menu.phtml | 2 +- app/models/Entry.php | 2 +- app/models/Feed.php | 2 +- lib/http-conditional.php | 4 ++-- public/install.php | 1 + 5 files changed, 6 insertions(+), 5 deletions(-) (limited to 'app/models/Entry.php') diff --git a/app/layout/nav_menu.phtml b/app/layout/nav_menu.phtml index 4b4945108..c71497ced 100644 --- a/app/layout/nav_menu.phtml +++ b/app/layout/nav_menu.phtml @@ -70,7 +70,7 @@
      • diff --git a/app/models/Entry.php b/app/models/Entry.php index 196823f67..899e98b00 100755 --- a/app/models/Entry.php +++ b/app/models/Entry.php @@ -137,7 +137,7 @@ class Entry extends Model { public function isDay ($day) { $date = $this->dateAdded(true); - $today = strtotime('today'); + $today = @strtotime('today'); $yesterday = $today - 86400; if ($day === Days::TODAY && diff --git a/app/models/Feed.php b/app/models/Feed.php index c1d0379a9..555759c9a 100644 --- a/app/models/Feed.php +++ b/app/models/Feed.php @@ -265,7 +265,7 @@ class Feed extends Model { $title = html_only_entity_decode (strip_tags ($item->get_title ())); $author = $item->get_author (); $link = $item->get_permalink (); - $date = strtotime ($item->get_date ()); + $date = @strtotime ($item->get_date ()); // gestion des tags (catégorie == tag) $tags_tmp = $item->get_categories (); diff --git a/lib/http-conditional.php b/lib/http-conditional.php index 6684fd6ac..59fbef41f 100644 --- a/lib/http-conditional.php +++ b/lib/http-conditional.php @@ -35,7 +35,7 @@ ... //Rest of the script, just as you would do normally. ?> - Version 1.7 beta, 2013-11-03, http://alexandre.alapetite.fr/doc-alex/php-http-304/ + Version 1.7 beta, 2013-12-02, http://alexandre.alapetite.fr/doc-alex/php-http-304/ ------------------------------------------------------------------ Written by Alexandre Alapetite, http://alexandre.alapetite.fr/cv/ @@ -124,7 +124,7 @@ function httpConditional($UnixTimeStamp,$cacheSeconds=0,$cachePrivacy=0,$feedMod if ($feedMode) {//Special RSS/ATOM global $clientCacheDate; - $clientCacheDate=strtotime($dateCacheClient); + $clientCacheDate=@strtotime($dateCacheClient); $cachePrivacy=0; } diff --git a/public/install.php b/public/install.php index 577714764..6765d8cd1 100644 --- a/public/install.php +++ b/public/install.php @@ -228,6 +228,7 @@ function saveStep3 () { $_SESSION['bd_error'] = true; } } + invalidateHttpCache(); } function deleteInstall () { $res = unlink (PUBLIC_PATH . '/install.php'); -- 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/Entry.php') 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/Entry.php') 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 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/Entry.php') 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 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/Entry.php') 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/Entry.php') 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 @@
      diff --git a/app/views/helpers/pagination.phtml b/app/views/helpers/pagination.phtml index 408cfca1b..d4983a32e 100755 --- a/app/views/helpers/pagination.phtml +++ b/app/views/helpers/pagination.phtml @@ -1,25 +1,25 @@
      • nextId)) { ?> nextId; ?> - + -
        +

        - +
        -
        +
      • diff --git a/app/views/helpers/view/global_view.phtml b/app/views/helpers/view/global_view.phtml index ac17d608a..bc6e24e37 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 1a7efa58f..094017957 100644 --- a/app/views/helpers/view/normal_view.phtml +++ b/app/views/helpers/view/normal_view.phtml @@ -24,23 +24,23 @@ if (!empty($this->entries)) { ?> entries as $item) { ?> - isDay (Days::TODAY)) { ?> + isDay (FreshRSS_Days::TODAY)) { ?>
        - + - currentName; ?>
        - isDay (Days::YESTERDAY)) { ?> + isDay (FreshRSS_Days::YESTERDAY)) { ?>
        - + - currentName; ?>
        - isDay (Days::BEFORE_YESTERDAY)) { ?> + isDay (FreshRSS_Days::BEFORE_YESTERDAY)) { ?>
        - + currentName; ?>
        @@ -51,13 +51,13 @@ if (!empty($this->entries)) { if ($this->conf->toplineRead ()) { ?>
      • isRead () ? 'read' : 'unread'); ?>isRead () ? 'read' : 'unread'); ?>
      • conf->toplineFavorite ()) { ?>
      • isFavorite () ? 'starred' : 'non-starred'); ?>isFavorite () ? 'starred' : 'non-starred'); ?>
      • entries)) {
      • ✇ name(); ?>
      • title (); ?>
      • conf->toplineDate ()) { ?>
      • date (); ?> 
      • - conf->toplineLink ()) { ?> + conf->toplineLink ()) { ?>
      @@ -75,7 +75,7 @@ if (!empty($this->entries)) {

      title (); ?>

      author (); - echo $author != '' ? '
      ' . Translate::t ('by_author', $author) . '
      ' : ''; + echo $author != '' ? '
      ' . Minz_Translate::t ('by_author', $author) . '
      ' : ''; if($this->conf->lazyload() == 'yes') { echo lazyimg($item->content ()); } else { @@ -83,19 +83,18 @@ if (!empty($this->entries)) { } ?>
      -
        conf) || is_logged ()) { if ($this->conf->bottomlineRead ()) { ?>
      • isRead () ? 'read' : 'unread'); ?>isRead () ? 'read' : 'unread'); ?>
      • conf->bottomlineFavorite ()) { ?>
      • isFavorite () ? 'starred' : 'non-starred'); ?>isFavorite () ? 'starred' : 'non-starred'); ?>
      • @@ -111,8 +110,8 @@ if (!empty($this->entries)) { @@ -204,6 +203,6 @@ if (!empty($this->entries)) {
        - +
        \ No newline at end of file diff --git a/app/views/helpers/view/reader_view.phtml b/app/views/helpers/view/reader_view.phtml index 30226af42..29b2be04c 100644 --- a/app/views/helpers/view/reader_view.phtml +++ b/app/views/helpers/view/reader_view.phtml @@ -21,7 +21,7 @@ if (!empty($this->entries)) {
        author (); ?> - + date (); ?>
        @@ -42,6 +42,6 @@ if (!empty($this->entries)) {
        - +
        \ No newline at end of file diff --git a/app/views/helpers/view/rss_view.phtml b/app/views/helpers/view/rss_view.phtml index 460146dc0..620bf1388 100755 --- a/app/views/helpers/view/rss_view.phtml +++ b/app/views/helpers/view/rss_view.phtml @@ -2,11 +2,11 @@ <?php echo $this->rss_title; ?> - - rss_title); ?> + + rss_title); ?> GMT - + entries as $item) { ?> diff --git a/app/views/index/about.phtml b/app/views/index/about.phtml index fa799154b..b5c00a1ed 100644 --- a/app/views/index/about.phtml +++ b/app/views/index/about.phtml @@ -1,24 +1,24 @@
        - + -

        +

        -
        +
        -
        -
        Marien Fressinaud -
        +
        +
        Marien Fressinaud -
        -
        -
        +
        +
        -
        -
        +
        +
        -

        +

        -

        -

        +

        +

        diff --git a/app/views/index/index.phtml b/app/views/index/index.phtml index bd18d2d77..cf98060c4 100644 --- a/app/views/index/index.phtml +++ b/app/views/index/index.phtml @@ -1,8 +1,8 @@ conf->token(); -$token_param = Request::param ('token', ''); +$token_param = Minz_Request::param ('token', ''); $token_is_ok = ($token != '' && $token == $token_param); if(!login_is_conf ($this->conf) || @@ -21,9 +21,9 @@ if(!login_is_conf ($this->conf) || } else { ?>
        -

        -

        -

        +

        +

        +

        - + -

        +

        - +

        logsPaginator->items (); ?> @@ -20,6 +20,6 @@ logsPaginator->render ('logs_pagination.phtml','page'); ?>
      -

      +

      diff --git a/app/views/javascript/actualize.phtml b/app/views/javascript/actualize.phtml index f39540a9a..69689133c 100644 --- a/app/views/javascript/actualize.phtml +++ b/app/views/javascript/actualize.phtml @@ -1,12 +1,12 @@ var feeds = new Array (); feeds as $feed) { ?> -feeds.push (" 'feed', 'a' => 'actualize', 'params' => array ('id' => $feed->id (), 'ajax' => '1')), 'php'); ?>"); +feeds.push (" 'feed', 'a' => 'actualize', 'params' => array ('id' => $feed->id (), 'ajax' => '1')), 'php'); ?>"); function initProgressBar (init) { if (init) { $("body").after ("\
      \ - 0 / " + feeds.length + "
      \ + 0 / " + feeds.length + "
      \ \
      "); } else { diff --git a/lib/Minz/ActionException.php b/lib/Minz/ActionException.php new file mode 100644 index 000000000..c566a076f --- /dev/null +++ b/lib/Minz/ActionException.php @@ -0,0 +1,9 @@ + +*/ + +/** + * La classe Cache permet de gérer facilement les pages en cache + */ +class Minz_Cache { + /** + * $expire timestamp auquel expire le cache de $url + */ + private $expire = 0; + + /** + * $file est le nom du fichier de cache + */ + private $file = ''; + + /** + * $enabled permet de déterminer si le cache est activé + */ + private static $enabled = true; + + /** + * Constructeur + */ + public function __construct () { + $this->_fileName (); + $this->_expire (); + } + + /** + * Setteurs + */ + public function _fileName () { + $file = md5 (Minz_Request::getURI ()); + + $this->file = CACHE_PATH . '/'.$file; + } + + public function _expire () { + if ($this->exist ()) { + $this->expire = filemtime ($this->file) + + Minz_Configuration::delayCache (); + } + } + + /** + * Permet de savoir si le cache est activé + * @return true si activé, false sinon + */ + public static function isEnabled () { + return Minz_Configuration::cacheEnabled () && self::$enabled; + } + + /** + * Active / désactive le cache + */ + public static function switchOn () { + self::$enabled = true; + } + public static function switchOff () { + self::$enabled = false; + } + + /** + * Détermine si le cache de $url a expiré ou non + * @return true si il a expiré, false sinon + */ + public function expired () { + return time () > $this->expire; + } + + /** + * Affiche le contenu du cache + * @print le code html du cache + */ + public function render () { + if ($this->exist ()) { + include ($this->file); + } + } + + /** + * Enregistre $html en cache + * @param $html le html à mettre en cache + */ + public function cache ($html) { + file_put_contents ($this->file, $html); + } + + /** + * Permet de savoir si le cache existe + * @return true si il existe, false sinon + */ + public function exist () { + return file_exists ($this->file); + } + + /** + * Nettoie le cache en supprimant tous les fichiers + */ + public static function clean () { + $files = opendir (CACHE_PATH); + + while ($fic = readdir ($files)) { + if ($fic != '.' && $fic != '..') { + unlink (CACHE_PATH.'/'.$fic); + } + } + + closedir ($files); + } +} diff --git a/lib/Minz/ControllerNotActionControllerException.php b/lib/Minz/ControllerNotActionControllerException.php new file mode 100644 index 000000000..535a1377e --- /dev/null +++ b/lib/Minz/ControllerNotActionControllerException.php @@ -0,0 +1,9 @@ + +*/ + +/** + * La classe Log permet de logger des erreurs + */ +class Minz_Log { + /** + * Les différents niveau de log + * ERROR erreurs bloquantes de l'application + * WARNING erreurs pouvant géner le bon fonctionnement, mais non bloquantes + * NOTICE erreurs mineures ou messages d'informations + * DEBUG Informations affichées pour le déboggage + */ + const ERROR = 2; + const WARNING = 4; + const NOTICE = 8; + const DEBUG = 16; + + /** + * Enregistre un message dans un fichier de log spécifique + * Message non loggué si + * - environment = SILENT + * - level = WARNING et environment = PRODUCTION + * - level = NOTICE et environment = PRODUCTION + * @param $information message d'erreur / information à enregistrer + * @param $level niveau d'erreur + * @param $file_name fichier de log, par défaut LOG_PATH/application.log + */ + public static function record ($information, $level, $file_name = null) { + $env = Minz_Configuration::environment (); + + if (! ($env === Minz_Configuration::SILENT + || ($env === Minz_Configuration::PRODUCTION + && ($level >= Minz_Log::NOTICE)))) { + if (is_null ($file_name)) { + $file_name = LOG_PATH . '/application.log'; + } + + switch ($level) { + case Minz_Log::ERROR : + $level_label = 'error'; + break; + case Minz_Log::WARNING : + $level_label = 'warning'; + break; + case Minz_Log::NOTICE : + $level_label = 'notice'; + break; + case Minz_Log::DEBUG : + $level_label = 'debug'; + break; + default : + $level_label = 'unknown'; + } + + if ($env == Minz_Configuration::PRODUCTION) { + $file = @fopen ($file_name, 'a'); + } else { + $file = fopen ($file_name, 'a'); + } + + if ($file !== false) { + $log = '[' . date('r') . ']'; + $log .= ' [' . $level_label . ']'; + $log .= ' --- ' . $information . "\n"; + fwrite ($file, $log); + fclose ($file); + } else { + throw new Minz_PermissionDeniedException ( + $file_name, + Minz_Exception::ERROR + ); + } + } + } + + /** + * Automatise le log des variables globales $_GET et $_POST + * Fait appel à la fonction record(...) + * Ne fonctionne qu'en environnement "development" + * @param $file_name fichier de log, par défaut LOG_PATH/application.log + */ + public static function recordRequest($file_name = null) { + $msg_get = str_replace("\n", '', '$_GET content : ' . print_r($_GET, true)); + $msg_post = str_replace("\n", '', '$_POST content : ' . print_r($_POST, true)); + + self::record($msg_get, Minz_Log::DEBUG, $file_name); + self::record($msg_post, Minz_Log::DEBUG, $file_name); + } +} diff --git a/lib/Minz/ModelArray.php b/lib/Minz/ModelArray.php new file mode 100644 index 000000000..4ba022143 --- /dev/null +++ b/lib/Minz/ModelArray.php @@ -0,0 +1,122 @@ + +*/ + +/** + * La classe Model_array représente le modèle interragissant avec les fichiers de type texte gérant des tableaux php + */ +class Minz_ModelArray extends Minz_ModelTxt { + /** + * $array Le tableau php contenu dans le fichier $nameFile + */ + protected $array = array (); + + /** + * Ouvre le fichier indiqué, charge le tableau dans $array et le $nameFile + * @param $nameFile le nom du fichier à ouvrir contenant un tableau + * Remarque : $array sera obligatoirement un tableau + */ + public function __construct ($nameFile) { + parent::__construct ($nameFile); + + if (!$this->getLock ('read')) { + throw new Minz_PermissionDeniedException ($this->filename); + } else { + $this->array = include ($this->filename); + $this->releaseLock (); + + if (!is_array ($this->array)) { + $this->array = array (); + } + + $this->array = $this->decodeArray ($this->array); + } + } + + /** + * Écrit un tableau dans le fichier $nameFile + * @param $array le tableau php à enregistrer + **/ + public function writeFile ($array) { + if (!$this->getLock ('write')) { + throw new Minz_PermissionDeniedException ($this->namefile); + } else { + $this->erase (); + + $this->writeLine ('writeLine ('return ', false); + $this->writeArray ($array); + $this->writeLine (';'); + + $this->releaseLock (); + } + } + + private function writeArray ($array, $profondeur = 0) { + $tab = ''; + for ($i = 0; $i < $profondeur; $i++) { + $tab .= "\t"; + } + $this->writeLine ('array ('); + + foreach ($array as $key => $value) { + if (is_int ($key)) { + $this->writeLine ($tab . "\t" . $key . ' => ', false); + } else { + $this->writeLine ($tab . "\t" . '\'' . $key . '\'' . ' => ', false); + } + + if (is_array ($value)) { + $this->writeArray ($value, $profondeur + 1); + $this->writeLine (','); + } else { + if (is_numeric ($value)) { + $this->writeLine ($value . ','); + } else { + $this->writeLine ('\'' . addslashes ($value) . '\','); + } + } + } + + $this->writeLine ($tab . ')', false); + } + + private function decodeArray ($array) { + $new_array = array (); + + foreach ($array as $key => $value) { + if (is_array ($value)) { + $new_array[$key] = $this->decodeArray ($value); + } else { + $new_array[$key] = stripslashes ($value); + } + } + + return $new_array; + } + + private function getLock ($type) { + if ($type == 'write') { + $lock = LOCK_EX; + } else { + $lock = LOCK_SH; + } + + $count = 1; + while (!flock ($this->file, $lock) && $count <= 50) { + $count++; + } + + if ($count >= 50) { + return false; + } else { + return true; + } + } + + private function releaseLock () { + flock ($this->file, LOCK_UN); + } +} diff --git a/lib/Minz/ModelPdo.php b/lib/Minz/ModelPdo.php new file mode 100644 index 000000000..9655539b2 --- /dev/null +++ b/lib/Minz/ModelPdo.php @@ -0,0 +1,111 @@ + +*/ + +/** + * La classe Model_sql représente le modèle interragissant avec les bases de données + * Seul la connexion MySQL est prise en charge pour le moment + */ +class Minz_ModelPdo { + + /** + * Partage la connexion à la base de données entre toutes les instances. + */ + public static $useSharedBd = true; + private static $sharedBd = null; + private static $sharedPrefix; + + /** + * $bd variable représentant la base de données + */ + protected $bd; + + protected $prefix; + + /** + * Créé la connexion à la base de données à l'aide des variables + * HOST, BASE, USER et PASS définies dans le fichier de configuration + */ + public function __construct () { + if (self::$useSharedBd && self::$sharedBd != null) { + $this->bd = self::$sharedBd; + $this->prefix = self::$sharedPrefix; + return; + } + + $db = Minz_Configuration::dataBase (); + $driver_options = null; + + try { + $type = $db['type']; + if($type == 'mysql') { + $string = $type + . ':host=' . $db['host'] + . ';dbname=' . $db['base'] + . ';charset=utf8'; + $driver_options = array( + PDO::MYSQL_ATTR_INIT_COMMAND => 'SET NAMES utf8' + ); + } elseif($type == 'sqlite') { + $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 ( + $string, + $db['user'], + $db['password'], + $driver_options + ); + self::$sharedBd = $this->bd; + + $userPrefix = Minz_Configuration::currentUser (); + $this->prefix = $db['prefix'] . (empty($userPrefix) ? '' : ($userPrefix . '_')); + self::$sharedPrefix = $this->prefix; + } catch (Exception $e) { + throw new Minz_PDOConnectionException ( + $string, + $db['user'], Minz_Exception::ERROR + ); + } + } + + public function beginTransaction() { + $this->bd->beginTransaction(); + } + public function commit() { + $this->bd->commit(); + } + public function rollBack() { + $this->bd->rollBack(); + } + + public function size() { + $db = Minz_Configuration::dataBase (); + $sql = 'SELECT SUM(data_length + index_length) FROM information_schema.TABLES WHERE table_schema = ?'; + $stm = $this->bd->prepare ($sql); + $values = array ($db['base']); + $stm->execute ($values); + $res = $stm->fetchAll(PDO::FETCH_COLUMN, 0); + return $res[0]; + } +} + +class FreshPDO extends PDO { + private static function check($statement) { + if (preg_match('/^(?:UPDATE|INSERT|DELETE)/i', $statement)) { + invalidateHttpCache(); + } + } + + public function prepare ($statement, $driver_options = array()) { + FreshPDO::check($statement); + return parent::prepare($statement, $driver_options); + } + + public function exec ($statement) { + FreshPDO::check($statement); + return parent::exec($statement); + } +} diff --git a/lib/Minz/ModelTxt.php b/lib/Minz/ModelTxt.php new file mode 100644 index 000000000..8c5973f4d --- /dev/null +++ b/lib/Minz/ModelTxt.php @@ -0,0 +1,84 @@ + +*/ + +/** + * La classe Model_txt représente le modèle interragissant avec les fichiers de type texte + */ +class Minz_ModelTxt { + /** + * $file représente le fichier à ouvrir + */ + protected $file; + + /** + * $filename est le nom du fichier + */ + protected $filename; + + /** + * Ouvre un fichier dans $file + * @param $nameFile nom du fichier à ouvrir + * @param $mode mode d'ouverture du fichier ('a+' par défaut) + * @exception FileNotExistException si le fichier n'existe pas + * > ou ne peux pas être ouvert + */ + public function __construct ($nameFile, $mode = 'a+') { + $this->filename = $nameFile; + if (!file_exists($this->filename)) { + throw new Minz_FileNotExistException ( + $this->filename, + Minz_Exception::WARNING + ); + } + + $this->file = @fopen ($this->filename, $mode); + + if (!$this->file) { + throw new Minz_PermissionDeniedException ( + $this->filename, + Minz_Exception::WARNING + ); + } + } + + /** + * Lit une ligne de $file + * @return une ligne du fichier + */ + public function readLine () { + return fgets ($this->file); + } + + /** + * Écrit une ligne dans $file + * @param $line la ligne à écrire + */ + public function writeLine ($line, $newLine = true) { + $char = ''; + if ($newLine) { + $char = "\n"; + } + + fwrite ($this->file, $line . $char); + } + + /** + * Efface le fichier $file + * @return true en cas de succès, false sinon + */ + public function erase () { + return ftruncate ($this->file, 0); + } + + /** + * Ferme $file + */ + public function __destruct () { + if (isset ($this->file)) { + fclose ($this->file); + } + } +} diff --git a/lib/Minz/PDOConnectionException.php b/lib/Minz/PDOConnectionException.php new file mode 100644 index 000000000..faf2e0fe9 --- /dev/null +++ b/lib/Minz/PDOConnectionException.php @@ -0,0 +1,9 @@ +route = $route; + + $message = 'Route `' . $route . '` not found'; + + parent::__construct ($message, $code); + } + + public function route () { + return $this->route; + } +} diff --git a/lib/SimplePie_autoloader.php b/lib/SimplePie_autoloader.php deleted file mode 100644 index 3f67635b0..000000000 --- a/lib/SimplePie_autoloader.php +++ /dev/null @@ -1,86 +0,0 @@ -path = dirname(__FILE__) . DIRECTORY_SEPARATOR . 'SimplePie'; - } - - /** - * Autoloader - * - * @param string $class The name of the class to attempt to load. - */ - public function autoload($class) - { - // Only load the class if it starts with "SimplePie" - if (strpos($class, 'SimplePie') !== 0) - { - return; - } - - $filename = $this->path . DIRECTORY_SEPARATOR . str_replace('_', DIRECTORY_SEPARATOR, $class) . '.php'; - include $filename; - } -} diff --git a/lib/lib_rss.php b/lib/lib_rss.php index 4f5b90b61..2fdfd4bd8 100644 --- a/lib/lib_rss.php +++ b/lib/lib_rss.php @@ -15,6 +15,31 @@ if (!function_exists('json_encode')) { } } +// +function classAutoloader($class) { + if (strpos($class, 'FreshRSS') === 0) { + $components = explode('_', $class); + switch (count($components)) { + case 1: + include(APP_PATH . '/' . $components[0] . '.php'); + return; + case 2: + include(APP_PATH . '/Models/' . $components[1] . '.php'); + return; + case 3: //Controllers, Exceptions + include(APP_PATH . '/' . $components[2] . 's/' . $components[1] . $components[2] . '.php'); + return; + } + } elseif (strpos($class, 'Minz') === 0) { + include(LIB_PATH . '/' . str_replace('_', '/', $class) . '.php'); + } elseif (strpos($class, 'SimplePie') === 0) { + include(LIB_PATH . '/SimplePie/' . str_replace('_', '/', $class) . '.php'); + } +} + +spl_autoload_register('classAutoloader'); +// + function checkUrl($url) { if (empty ($url)) { return ''; @@ -33,7 +58,7 @@ function checkUrl($url) { // vérifie qu'on est connecté function is_logged () { - return Session::param ('mail') != false; + return Minz_Session::param ('mail') != false; } // vérifie que le système d'authentification est configuré @@ -63,11 +88,11 @@ function formatBytes($bytes, $precision = 2, $system = 'IEC') { } function timestamptodate ($t, $hour = true) { - $month = Translate::t (date('M', $t)); + $month = Minz_Translate::t (date('M', $t)); if ($hour) { - $date = Translate::t ('format_date_hour', $month); + $date = Minz_Translate::t ('format_date_hour', $month); } else { - $date = Translate::t ('format_date', $month); + $date = Minz_Translate::t ('format_date', $month); } return @date ($date, $t); @@ -123,10 +148,10 @@ function opml_import ($xml) { $opml = simplexml_import_dom($dom); if (!$opml) { - throw new OpmlException (); + throw new FreshRSS_Opml_Exception (); } - $catDAO = new CategoryDAO(); + $catDAO = new FreshRSS_CategoryDAO(); $catDAO->checkDefault(); $defCat = $catDAO->getDefault(); @@ -152,10 +177,10 @@ function opml_import ($xml) { // Y ne sera pas ajouté et le flux non plus vu que l'id // de sa catégorie n'exisera pas $title = htmlspecialchars($title, ENT_QUOTES, 'UTF-8'); - $catDAO = new CategoryDAO (); + $catDAO = new FreshRSS_CategoryDAO (); $cat = $catDAO->searchByName ($title); if ($cat === false) { - $cat = new Category ($title); + $cat = new FreshRSS_Category ($title); $values = array ( 'name' => $cat->name (), 'color' => $cat->color () @@ -204,7 +229,7 @@ function getFeed ($outline, $cat_id) { $title = (string) $outline['title']; } $title = htmlspecialchars($title, ENT_QUOTES, 'UTF-8'); - $feed = new Feed ($url); + $feed = new FreshRSS_Feed ($url); $feed->_category ($cat_id); $feed->_name ($title); if (isset($outline['htmlUrl'])) { @@ -250,7 +275,7 @@ function get_content_by_parsing ($url, $path) { function lazyimg($content) { return preg_replace( '/]+?)src=[\'"]([^"\']+)[\'"]([^>]*)>/i', - '', + '', $content ); } diff --git a/lib/minz/ActionController.php b/lib/minz/ActionController.php index ab9389dbd..409d9611f 100755 --- a/lib/minz/ActionController.php +++ b/lib/minz/ActionController.php @@ -7,7 +7,7 @@ /** * La classe ActionController représente le contrôleur de l'application */ -class ActionController { +class Minz_ActionController { protected $router; protected $view; @@ -18,7 +18,7 @@ class ActionController { */ public function __construct ($router) { $this->router = $router; - $this->view = new View (); + $this->view = new Minz_View (); $this->view->attributeParams (); } diff --git a/lib/minz/Configuration.php b/lib/minz/Configuration.php index 7d6e3743e..9fc913964 100755 --- a/lib/minz/Configuration.php +++ b/lib/minz/Configuration.php @@ -7,7 +7,7 @@ /** * La classe Configuration permet de gérer la configuration de l'application */ -class Configuration { +class Minz_Configuration { const CONF_PATH_NAME = '/application.ini'; /** @@ -43,7 +43,7 @@ class Configuration { * - base le nom de la base de données */ private static $sel_application = ''; - private static $environment = Configuration::PRODUCTION; + private static $environment = Minz_Configuration::PRODUCTION; private static $base_url = ''; private static $use_url_rewriting = false; private static $title = ''; @@ -99,30 +99,30 @@ class Configuration { /** * Initialise les variables de configuration - * @exception FileNotExistException si le CONF_PATH_NAME n'existe pas - * @exception BadConfigurationException si CONF_PATH_NAME mal formaté + * @exception Minz_FileNotExistException si le CONF_PATH_NAME n'existe pas + * @exception Minz_BadConfigurationException si CONF_PATH_NAME mal formaté */ public static function init () { try { self::parseFile (); self::setReporting (); - } catch (FileNotExistException $e) { + } catch (Minz_FileNotExistException $e) { throw $e; - } catch (BadConfigurationException $e) { + } catch (Minz_BadConfigurationException $e) { throw $e; } } /** * Parse un fichier de configuration de type ".ini" - * @exception FileNotExistException si le CONF_PATH_NAME n'existe pas - * @exception BadConfigurationException si CONF_PATH_NAME mal formaté + * @exception Minz_FileNotExistException si le CONF_PATH_NAME n'existe pas + * @exception Minz_BadConfigurationException si CONF_PATH_NAME mal formaté */ private static function parseFile () { if (!file_exists (DATA_PATH . self::CONF_PATH_NAME)) { - throw new FileNotExistException ( + throw new Minz_FileNotExistException ( DATA_PATH . self::CONF_PATH_NAME, - MinzException::ERROR + Minz_Exception::ERROR ); } @@ -132,17 +132,17 @@ class Configuration { ); if (!$ini_array) { - throw new PermissionDeniedException ( + throw new Minz_PermissionDeniedException ( DATA_PATH . self::CONF_PATH_NAME, - MinzException::ERROR + Minz_Exception::ERROR ); } // [general] est obligatoire if (!isset ($ini_array['general'])) { - throw new BadConfigurationException ( + throw new Minz_BadConfigurationException ( '[general]', - MinzException::ERROR + Minz_Exception::ERROR ); } $general = $ini_array['general']; @@ -150,9 +150,9 @@ class Configuration { // sel_application est obligatoire if (!isset ($general['sel_application'])) { - throw new BadConfigurationException ( + throw new Minz_BadConfigurationException ( 'sel_application', - MinzException::ERROR + Minz_Exception::ERROR ); } self::$sel_application = $general['sel_application']; @@ -160,18 +160,18 @@ class Configuration { if (isset ($general['environment'])) { switch ($general['environment']) { case 'silent': - self::$environment = Configuration::SILENT; + self::$environment = Minz_Configuration::SILENT; break; case 'development': - self::$environment = Configuration::DEVELOPMENT; + self::$environment = Minz_Configuration::DEVELOPMENT; break; case 'production': - self::$environment = Configuration::PRODUCTION; + self::$environment = Minz_Configuration::PRODUCTION; break; default: - throw new BadConfigurationException ( + throw new Minz_BadConfigurationException ( 'environment', - MinzException::ERROR + Minz_Exception::ERROR ); } @@ -194,7 +194,7 @@ class Configuration { if (CACHE_PATH === false && self::$cache_enabled) { throw new FileNotExistException ( 'CACHE_PATH', - MinzException::ERROR + Minz_Exception::ERROR ); } } @@ -213,27 +213,27 @@ class Configuration { } if ($db) { if (!isset ($db['host'])) { - throw new BadConfigurationException ( + throw new Minz_BadConfigurationException ( 'host', - MinzException::ERROR + Minz_Exception::ERROR ); } if (!isset ($db['user'])) { - throw new BadConfigurationException ( + throw new Minz_BadConfigurationException ( 'user', - MinzException::ERROR + Minz_Exception::ERROR ); } if (!isset ($db['password'])) { - throw new BadConfigurationException ( + throw new Minz_BadConfigurationException ( 'password', - MinzException::ERROR + Minz_Exception::ERROR ); } if (!isset ($db['base'])) { - throw new BadConfigurationException ( + throw new Minz_BadConfigurationException ( 'base', - MinzException::ERROR + Minz_Exception::ERROR ); } diff --git a/lib/minz/Dispatcher.php b/lib/minz/Dispatcher.php index 0cfdd8e75..2898b5f00 100644 --- a/lib/minz/Dispatcher.php +++ b/lib/minz/Dispatcher.php @@ -9,8 +9,8 @@ * déterminée dans la Request * C'est un singleton */ -class Dispatcher { - const CONTROLLERS_PATH_NAME = '/controllers'; +class Minz_Dispatcher { + const CONTROLLERS_PATH_NAME = '/Controllers'; /* singleton */ private static $instance = null; @@ -23,7 +23,7 @@ class Dispatcher { */ public static function getInstance ($router) { if (is_null (self::$instance)) { - self::$instance = new Dispatcher ($router); + self::$instance = new Minz_Dispatcher ($router); } return self::$instance; } @@ -38,7 +38,7 @@ class Dispatcher { /** * Lance le controller indiqué dans Request * Remplit le body de Response à partir de la Vue - * @exception MinzException + * @exception Minz_Exception */ public function run () { $cache = new Minz_Cache(); @@ -53,29 +53,25 @@ class Dispatcher { $cache->render (); $text = ob_get_clean(); } else { - while (Request::$reseted) { - Request::$reseted = false; + while (Minz_Request::$reseted) { + Minz_Request::$reseted = false; try { - $this->createController ( - Request::controllerName () - . 'Controller' - ); - + $this->createController ('FreshRSS_' . Minz_Request::controllerName () . '_Controller'); $this->controller->init (); $this->controller->firstAction (); $this->launchAction ( - Request::actionName () + Minz_Request::actionName () . 'Action' ); $this->controller->lastAction (); - if (!Request::$reseted) { + if (!Minz_Request::$reseted) { ob_start (); $this->controller->view ()->build (); $text = ob_get_clean(); } - } catch (MinzException $e) { + } catch (Minz_Exception $e) { throw $e; } } @@ -85,14 +81,12 @@ class Dispatcher { } } - Response::setBody ($text); + Minz_Response::setBody ($text); } /** * Instancie le Controller * @param $controller_name le nom du controller à instancier - * @exception FileNotExistException le fichier correspondant au - * > controller n'existe pas * @exception ControllerNotExistException le controller n'existe pas * @exception ControllerNotActionControllerException controller n'est * > pas une instance de ActionController @@ -101,26 +95,18 @@ class Dispatcher { $filename = APP_PATH . self::CONTROLLERS_PATH_NAME . '/' . $controller_name . '.php'; - if (!file_exists ($filename)) { - throw new FileNotExistException ( - $filename, - MinzException::ERROR - ); - } - require_once ($filename); - if (!class_exists ($controller_name)) { - throw new ControllerNotExistException ( + throw new Minz_ControllerNotExistException ( $controller_name, - MinzException::ERROR + Minz_Exception::ERROR ); } $this->controller = new $controller_name ($this->router); - if (! ($this->controller instanceof ActionController)) { - throw new ControllerNotActionControllerException ( + if (! ($this->controller instanceof Minz_ActionController)) { + throw new Minz_ControllerNotActionControllerException ( $controller_name, - MinzException::ERROR + Minz_Exception::ERROR ); } } @@ -129,18 +115,18 @@ class Dispatcher { * Lance l'action sur le controller du dispatcher * @param $action_name le nom de l'action * @exception ActionException si on ne peut pas exécuter l'action sur - * > le controller + * le controller */ private function launchAction ($action_name) { - if (!Request::$reseted) { + if (!Minz_Request::$reseted) { if (!is_callable (array ( $this->controller, $action_name ))) { - throw new ActionException ( + throw new Minz_ActionException ( get_class ($this->controller), $action_name, - MinzException::ERROR + Minz_Exception::ERROR ); } call_user_func (array ( diff --git a/lib/minz/Error.php b/lib/minz/Error.php index 0e8c2f60b..1ad0d313c 100755 --- a/lib/minz/Error.php +++ b/lib/minz/Error.php @@ -1,5 +1,5 @@ */ @@ -7,7 +7,7 @@ /** * La classe Error permet de lancer des erreurs HTTP */ -class Error { +class Minz_Error { public function __construct () { } /** @@ -21,28 +21,28 @@ class Error { */ public static function error ($code = 404, $logs = array (), $redirect = false) { $logs = self::processLogs ($logs); - $error_filename = APP_PATH . '/controllers/errorController.php'; - + $error_filename = APP_PATH . '/Controllers/ErrorController.php'; + if (file_exists ($error_filename)) { $params = array ( 'code' => $code, 'logs' => $logs ); - - Response::setHeader ($code); + + Minz_Response::setHeader ($code); if ($redirect) { - Request::forward (array ( + Minz_Request::forward (array ( 'c' => 'error' ), true); } else { - Request::forward (array ( + Minz_Request::forward (array ( 'c' => 'error', 'params' => $params ), false); } } else { $text = '

      An error occured

      '."\n"; - + if (!empty ($logs)) { $text .= '
        '."\n"; foreach ($logs as $log) { @@ -50,14 +50,14 @@ class Error { } $text .= '
      '."\n"; } - - Response::setHeader ($code); - Response::setBody ($text); - Response::send (); + + Minz_Response::setHeader ($code); + Minz_Response::setBody ($text); + Minz_Response::send (); exit (); } } - + /** * Permet de retourner les logs de façon à n'avoir que * ceux que l'on veut réellement @@ -66,12 +66,12 @@ class Error { * > en fonction de l'environment */ private static function processLogs ($logs) { - $env = Configuration::environment (); + $env = Minz_Configuration::environment (); $logs_ok = array (); $error = array (); $warning = array (); $notice = array (); - + if (isset ($logs['error'])) { $error = $logs['error']; } @@ -81,14 +81,14 @@ class Error { if (isset ($logs['notice'])) { $notice = $logs['notice']; } - - if ($env == Configuration::PRODUCTION) { + + if ($env == Minz_Configuration::PRODUCTION) { $logs_ok = $error; } - if ($env == Configuration::DEVELOPMENT) { + if ($env == Minz_Configuration::DEVELOPMENT) { $logs_ok = array_merge ($error, $warning, $notice); } - + return $logs_ok; } } diff --git a/lib/minz/FrontController.php b/lib/minz/FrontController.php index d48d43d04..eb9835fe5 100755 --- a/lib/minz/FrontController.php +++ b/lib/minz/FrontController.php @@ -2,109 +2,79 @@ # ***** BEGIN LICENSE BLOCK ***** # MINZ - a free PHP Framework like Zend Framework # Copyright (C) 2011 Marien Fressinaud -# +# # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU Affero General Public License as # published by the Free Software Foundation, either version 3 of the # License, or (at your option) any later version. -# +# # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU Affero General Public License for more details. -# +# # You should have received a copy of the GNU Affero General Public License # along with this program. If not, see . # # ***** END LICENSE BLOCK ***** /** - * La classe FrontController est le noyau du framework, elle lance l'application + * La classe FrontController est le Dispatcher du framework, elle lance l'application * Elle est appelée en général dans le fichier index.php à la racine du serveur */ -class FrontController { +class Minz_FrontController { protected $dispatcher; protected $router; - + /** * Constructeur * Initialise le router et le dispatcher */ public function __construct () { - $this->loadLib (); - if (LOG_PATH === false) { $this->killApp ('Path doesn\'t exist : LOG_PATH'); } - + try { - Configuration::init (); + Minz_Configuration::init (); - Request::init (); + Minz_Request::init (); - $this->router = new Router (); + $this->router = new Minz_Router (); $this->router->init (); - } catch (RouteNotFoundException $e) { + } catch (Minz_RouteNotFoundException $e) { Minz_Log::record ($e->getMessage (), Minz_Log::ERROR); - Error::error ( + Minz_Error::error ( 404, array ('error' => array ($e->getMessage ())) ); - } catch (MinzException $e) { + } catch (Minz_Exception $e) { Minz_Log::record ($e->getMessage (), Minz_Log::ERROR); $this->killApp ($e->getMessage ()); } - - $this->dispatcher = Dispatcher::getInstance ($this->router); - } - - /** - * Inclue les fichiers de la librairie - */ - private function loadLib () { - require ('ActionController.php'); - require ('Minz_Cache.php'); - require ('Configuration.php'); - require ('Dispatcher.php'); - require ('Error.php'); - require ('Helper.php'); - require ('Minz_Log.php'); - require ('Model.php'); - require ('Paginator.php'); - require ('Request.php'); - require ('Response.php'); - require ('Router.php'); - require ('Session.php'); - require ('Translate.php'); - require ('Url.php'); - require ('View.php'); - - require ('dao/Model_pdo.php'); - require ('dao/Model_txt.php'); - require ('dao/Model_array.php'); - - require ('exceptions/MinzException.php'); + + $this->dispatcher = Minz_Dispatcher::getInstance ($this->router); } - + /** * Démarre l'application (lance le dispatcher et renvoie la réponse */ public function run () { try { $this->dispatcher->run (); - Response::send (); - } catch (MinzException $e) { + Minz_Response::send (); + } catch (Minz_Exception $e) { try { Minz_Log::record ($e->getMessage (), Minz_Log::ERROR); - } catch (PermissionDeniedException $e) { + } catch (Minz_PermissionDeniedException $e) { $this->killApp ($e->getMessage ()); } - if ($e instanceof FileNotExistException || - $e instanceof ControllerNotExistException || - $e instanceof ControllerNotActionControllerException || - $e instanceof ActionException) { - Error::error ( + if ($e instanceof Minz_FileNotExistException || + $e instanceof Minz_ControllerNotExistException || + $e instanceof Minz_ControllerNotActionControllerException || + $e instanceof Minz_ActionException) { + Minz_Error::error ( 404, array ('error' => array ($e->getMessage ())), true @@ -114,7 +84,7 @@ class FrontController { } } } - + /** * Permet d'arrêter le programme en urgence */ diff --git a/lib/minz/Helper.php b/lib/minz/Helper.php index 4f64ba218..b058211d3 100755 --- a/lib/minz/Helper.php +++ b/lib/minz/Helper.php @@ -7,7 +7,7 @@ /** * La classe Helper représente une aide pour des tâches récurrentes */ -class Helper { +class Minz_Helper { /** * Annule les effets des magic_quotes pour une variable donnée * @param $var variable à traiter (tableau ou simple variable) diff --git a/lib/minz/Minz_Cache.php b/lib/minz/Minz_Cache.php deleted file mode 100644 index 6848e3350..000000000 --- a/lib/minz/Minz_Cache.php +++ /dev/null @@ -1,116 +0,0 @@ - -*/ - -/** - * La classe Cache permet de gérer facilement les pages en cache - */ -class Minz_Cache { - /** - * $expire timestamp auquel expire le cache de $url - */ - private $expire = 0; - - /** - * $file est le nom du fichier de cache - */ - private $file = ''; - - /** - * $enabled permet de déterminer si le cache est activé - */ - private static $enabled = true; - - /** - * Constructeur - */ - public function __construct () { - $this->_fileName (); - $this->_expire (); - } - - /** - * Setteurs - */ - public function _fileName () { - $file = md5 (Request::getURI ()); - - $this->file = CACHE_PATH . '/'.$file; - } - - public function _expire () { - if ($this->exist ()) { - $this->expire = filemtime ($this->file) - + Configuration::delayCache (); - } - } - - /** - * Permet de savoir si le cache est activé - * @return true si activé, false sinon - */ - public static function isEnabled () { - return Configuration::cacheEnabled () && self::$enabled; - } - - /** - * Active / désactive le cache - */ - public static function switchOn () { - self::$enabled = true; - } - public static function switchOff () { - self::$enabled = false; - } - - /** - * Détermine si le cache de $url a expiré ou non - * @return true si il a expiré, false sinon - */ - public function expired () { - return time () > $this->expire; - } - - /** - * Affiche le contenu du cache - * @print le code html du cache - */ - public function render () { - if ($this->exist ()) { - include ($this->file); - } - } - - /** - * Enregistre $html en cache - * @param $html le html à mettre en cache - */ - public function cache ($html) { - file_put_contents ($this->file, $html); - } - - /** - * Permet de savoir si le cache existe - * @return true si il existe, false sinon - */ - public function exist () { - return file_exists ($this->file); - } - - /** - * Nettoie le cache en supprimant tous les fichiers - */ - public static function clean () { - $files = opendir (CACHE_PATH); - - while ($fic = readdir ($files)) { - if ($fic != '.' && $fic != '..') { - unlink (CACHE_PATH.'/'.$fic); - } - } - - closedir ($files); - } -} diff --git a/lib/minz/Minz_Log.php b/lib/minz/Minz_Log.php deleted file mode 100644 index 12005aa88..000000000 --- a/lib/minz/Minz_Log.php +++ /dev/null @@ -1,94 +0,0 @@ - -*/ - -/** - * La classe Log permet de logger des erreurs - */ -class Minz_Log { - /** - * Les différents niveau de log - * ERROR erreurs bloquantes de l'application - * WARNING erreurs pouvant géner le bon fonctionnement, mais non bloquantes - * NOTICE erreurs mineures ou messages d'informations - * DEBUG Informations affichées pour le déboggage - */ - const ERROR = 2; - const WARNING = 4; - const NOTICE = 8; - const DEBUG = 16; - - /** - * Enregistre un message dans un fichier de log spécifique - * Message non loggué si - * - environment = SILENT - * - level = WARNING et environment = PRODUCTION - * - level = NOTICE et environment = PRODUCTION - * @param $information message d'erreur / information à enregistrer - * @param $level niveau d'erreur - * @param $file_name fichier de log, par défaut LOG_PATH/application.log - */ - public static function record ($information, $level, $file_name = null) { - $env = Configuration::environment (); - - if (! ($env === Configuration::SILENT - || ($env === Configuration::PRODUCTION - && ($level >= Minz_Log::NOTICE)))) { - if (is_null ($file_name)) { - $file_name = LOG_PATH . '/application.log'; - } - - switch ($level) { - case Minz_Log::ERROR : - $level_label = 'error'; - break; - case Minz_Log::WARNING : - $level_label = 'warning'; - break; - case Minz_Log::NOTICE : - $level_label = 'notice'; - break; - case Minz_Log::DEBUG : - $level_label = 'debug'; - break; - default : - $level_label = 'unknown'; - } - - if ($env == Configuration::PRODUCTION) { - $file = @fopen ($file_name, 'a'); - } else { - $file = fopen ($file_name, 'a'); - } - - if ($file !== false) { - $log = '[' . date('r') . ']'; - $log .= ' [' . $level_label . ']'; - $log .= ' --- ' . $information . "\n"; - fwrite ($file, $log); - fclose ($file); - } else { - throw new PermissionDeniedException ( - $file_name, - MinzException::ERROR - ); - } - } - } - - /** - * Automatise le log des variables globales $_GET et $_POST - * Fait appel à la fonction record(...) - * Ne fonctionne qu'en environnement "development" - * @param $file_name fichier de log, par défaut LOG_PATH/application.log - */ - public static function recordRequest($file_name = null) { - $msg_get = str_replace("\n", '', '$_GET content : ' . print_r($_GET, true)); - $msg_post = str_replace("\n", '', '$_POST content : ' . print_r($_POST, true)); - - self::record($msg_get, Minz_Log::DEBUG, $file_name); - self::record($msg_post, Minz_Log::DEBUG, $file_name); - } -} diff --git a/lib/minz/Model.php b/lib/minz/Model.php index 37fc19ed1..adbaba942 100755 --- a/lib/minz/Model.php +++ b/lib/minz/Model.php @@ -7,6 +7,6 @@ /** * La classe Model représente un modèle de l'application (représentation MVC) */ -class Model { +class Minz_Model { } diff --git a/lib/minz/Paginator.php b/lib/minz/Paginator.php index 1a8376e75..5858e76a5 100755 --- a/lib/minz/Paginator.php +++ b/lib/minz/Paginator.php @@ -7,7 +7,7 @@ /** * La classe Paginator permet de gérer la pagination de l'application facilement */ -class Paginator { +class Minz_Paginator { /** * $items tableau des éléments à afficher/gérer */ diff --git a/lib/minz/Request.php b/lib/minz/Request.php index 3e508d8f1..c8ffa4a42 100644 --- a/lib/minz/Request.php +++ b/lib/minz/Request.php @@ -7,7 +7,7 @@ /** * Request représente la requête http */ -class Request { +class Minz_Request { private static $controller_name = ''; private static $action_name = ''; private static $params = array (); @@ -96,7 +96,7 @@ class Request { * @return la base de l'url */ public static function getBaseUrl () { - return Configuration::baseUrl (); + return Minz_Configuration::baseUrl (); } /** @@ -124,10 +124,10 @@ class Request { * > sinon, le dispatcher recharge en interne */ public static function forward ($url = array (), $redirect = false) { - $url = Url::checkUrl ($url); + $url = Minz_Url::checkUrl ($url); if ($redirect) { - header ('Location: ' . Url::display ($url, 'php')); + header ('Location: ' . Minz_Url::display ($url, 'php')); exit (); } else { self::$reseted = true; @@ -185,9 +185,9 @@ class Request { */ private static function magicQuotesOff () { if (get_magic_quotes_gpc ()) { - $_GET = Helper::stripslashes_r ($_GET); - $_POST = Helper::stripslashes_r ($_POST); - $_COOKIE = Helper::stripslashes_r ($_COOKIE); + $_GET = Minz_Helper::stripslashes_r ($_GET); + $_POST = Minz_Helper::stripslashes_r ($_POST); + $_COOKIE = Minz_Helper::stripslashes_r ($_COOKIE); } } @@ -195,5 +195,3 @@ class Request { return !empty ($_POST) || !empty ($_FILES); } } - - diff --git a/lib/minz/Response.php b/lib/minz/Response.php index fcf53c5b1..f8ea3d946 100644 --- a/lib/minz/Response.php +++ b/lib/minz/Response.php @@ -7,7 +7,7 @@ /** * Response représente la requête http renvoyée à l'utilisateur */ -class Response { +class Minz_Response { private static $header = 'HTTP/1.0 200 OK'; private static $body = ''; diff --git a/lib/minz/Router.php b/lib/minz/Router.php index c5d6f5baa..1ccd72597 100755 --- a/lib/minz/Router.php +++ b/lib/minz/Router.php @@ -8,7 +8,7 @@ * La classe Router gère le routage de l'application * Les routes sont définies dans APP_PATH.'/configuration/routes.php' */ -class Router { +class Minz_Router { const ROUTES_PATH_NAME = '/configuration/routes.php'; private $routes = array (); @@ -19,7 +19,7 @@ class Router { * et que l'on utilise l'url rewriting */ public function __construct () { - if (Configuration::useUrlRewriting ()) { + if (Minz_Configuration::useUrlRewriting ()) { if (file_exists (APP_PATH . self::ROUTES_PATH_NAME)) { $routes = include ( APP_PATH . self::ROUTES_PATH_NAME @@ -34,9 +34,9 @@ class Router { $routes ); } else { - throw new FileNotExistException ( + throw new Minz_FileNotExistException ( self::ROUTES_PATH_NAME, - MinzException::ERROR + Minz_Exception::ERROR ); } } @@ -51,10 +51,10 @@ class Router { public function init () { $url = array (); - if (Configuration::useUrlRewriting ()) { + if (Minz_Configuration::useUrlRewriting ()) { try { $url = $this->buildWithRewriting (); - } catch (RouteNotFoundException $e) { + } catch (Minz_RouteNotFoundException $e) { throw $e; } } else { @@ -63,10 +63,10 @@ class Router { $url['params'] = array_merge ( $url['params'], - Request::fetchPOST () + Minz_Request::fetchPOST () ); - Request::forward ($url); + Minz_Request::forward ($url); } /** @@ -77,15 +77,15 @@ class Router { public function buildWithoutRewriting () { $url = array (); - $url['c'] = Request::fetchGET ( + $url['c'] = Minz_Request::fetchGET ( 'c', - Request::defaultControllerName () + Minz_Request::defaultControllerName () ); - $url['a'] = Request::fetchGET ( + $url['a'] = Minz_Request::fetchGET ( 'a', - Request::defaultActionName () + Minz_Request::defaultActionName () ); - $url['params'] = Request::fetchGET (); + $url['params'] = Minz_Request::fetchGET (); // post-traitement unset ($url['params']['c']); @@ -103,7 +103,7 @@ class Router { */ public function buildWithRewriting () { $url = array (); - $uri = Request::getURI (); + $uri = Minz_Request::getURI (); $find = false; foreach ($this->routes as $route) { @@ -121,14 +121,14 @@ class Router { } if (!$find && $uri != '/') { - throw new RouteNotFoundException ( + throw new Minz_RouteNotFoundException ( $uri, - MinzException::ERROR + Minz_Exception::ERROR ); } // post-traitement - $url = Url::checkUrl ($url); + $url = Minz_Url::checkUrl ($url); return $url; } diff --git a/lib/minz/Session.php b/lib/minz/Session.php index f9c9c6754..878caa556 100755 --- a/lib/minz/Session.php +++ b/lib/minz/Session.php @@ -4,7 +4,7 @@ * La classe Session gère la session utilisateur * C'est un singleton */ -class Session { +class Minz_Session { /** * $session stocke les variables de session */ @@ -15,7 +15,7 @@ class Session { */ public static function init () { // démarre la session - session_name (md5 (Configuration::selApplication ())); + session_name (md5 (Minz_Configuration::selApplication ())); session_start (); if (isset ($_SESSION)) { @@ -55,7 +55,7 @@ class Session { if($p == 'language') { // reset pour remettre à jour le fichier de langue à utiliser - Translate::reset (); + Minz_Translate::reset (); } } } diff --git a/lib/minz/Translate.php b/lib/minz/Translate.php index e8cbe4852..e14f783f7 100644 --- a/lib/minz/Translate.php +++ b/lib/minz/Translate.php @@ -8,7 +8,7 @@ * La classe Translate se charge de la traduction * Utilise les fichiers du répertoire /app/i18n/ */ -class Translate { +class Minz_Translate { /** * $language est la langue à afficher */ @@ -25,8 +25,8 @@ class Translate { * l'enregistre dans $translates */ public static function init () { - $l = Configuration::language (); - self::$language = Session::param ('language', $l); + $l = Minz_Configuration::language (); + self::$language = Minz_Session::param ('language', $l); $l_path = APP_PATH . '/i18n/' . self::$language . '.php'; diff --git a/lib/minz/Url.php b/lib/minz/Url.php index ce051ebd9..30f7f6231 100755 --- a/lib/minz/Url.php +++ b/lib/minz/Url.php @@ -3,7 +3,7 @@ /** * La classe Url permet de gérer les URL à travers MINZ */ -class Url { +class Minz_Url { /** * Affiche une Url formatée selon que l'on utilise l'url_rewriting ou non * si oui, on cherche dans la table de routage la correspondance pour formater @@ -29,16 +29,16 @@ class Url { } else { $protocol = 'http:'; } - $url_string = $protocol . '//' . Request::getDomainName () . Request::getBaseUrl (); + $url_string = $protocol . '//' . Minz_Request::getDomainName () . Minz_Request::getBaseUrl (); } else { $url_string = '.'; } if (is_array ($url)) { - $router = new Router (); + $router = new Minz_Router (); - if (Configuration::useUrlRewriting ()) { + if (Minz_Configuration::useUrlRewriting ()) { $url_string .= $router->printUriRewrited ($url); } else { $url_string .= self::printUri ($url, $encodage); @@ -67,13 +67,13 @@ class Url { } if (isset ($url['c']) - && $url['c'] != Request::defaultControllerName ()) { + && $url['c'] != Minz_Request::defaultControllerName ()) { $uri .= $separator . 'c=' . $url['c']; $separator = $and; } if (isset ($url['a']) - && $url['a'] != Request::defaultActionName ()) { + && $url['a'] != Minz_Request::defaultActionName ()) { $uri .= $separator . 'a=' . $url['a']; $separator = $and; } @@ -98,10 +98,10 @@ class Url { if (is_array ($url)) { if (!isset ($url['c'])) { - $url_checked['c'] = Request::defaultControllerName (); + $url_checked['c'] = Minz_Request::defaultControllerName (); } if (!isset ($url['a'])) { - $url_checked['a'] = Request::defaultActionName (); + $url_checked['a'] = Minz_Request::defaultActionName (); } if (!isset ($url['params'])) { $url_checked['params'] = array (); @@ -125,5 +125,5 @@ function _url ($controller, $action) { $params[$args[$i]] = $args[$i + 1]; } - return Url::display (array ('c' => $controller, 'a' => $action, 'params' => $params)); + return Minz_Url::display (array ('c' => $controller, 'a' => $action, 'params' => $params)); } diff --git a/lib/minz/View.php b/lib/minz/View.php index 12202542f..c8d0aefed 100755 --- a/lib/minz/View.php +++ b/lib/minz/View.php @@ -7,7 +7,7 @@ /** * La classe View représente la vue de l'application */ -class View { +class Minz_View { const VIEWS_PATH_NAME = '/views'; const LAYOUT_PATH_NAME = '/layout'; const LAYOUT_FILENAME = '/layout.phtml'; @@ -28,8 +28,8 @@ class View { public function __construct () { $this->view_filename = APP_PATH . self::VIEWS_PATH_NAME . '/' - . Request::controllerName () . '/' - . Request::actionName () . '.phtml'; + . Minz_Request::controllerName () . '/' + . Minz_Request::actionName () . '.phtml'; if (file_exists (APP_PATH . self::LAYOUT_PATH_NAME @@ -37,7 +37,7 @@ class View { $this->use_layout = true; } - self::$title = Configuration::title (); + self::$title = Minz_Configuration::title (); } /** @@ -232,7 +232,7 @@ class View { self::$params[$key] = $value; } public function attributeParams () { - foreach (View::$params as $key => $value) { + foreach (Minz_View::$params as $key => $value) { $this->$key = $value; } } diff --git a/lib/minz/dao/Model_array.php b/lib/minz/dao/Model_array.php deleted file mode 100755 index 0b9ccf071..000000000 --- a/lib/minz/dao/Model_array.php +++ /dev/null @@ -1,122 +0,0 @@ - -*/ - -/** - * La classe Model_array représente le modèle interragissant avec les fichiers de type texte gérant des tableaux php - */ -class Model_array extends Model_txt { - /** - * $array Le tableau php contenu dans le fichier $nameFile - */ - protected $array = array (); - - /** - * Ouvre le fichier indiqué, charge le tableau dans $array et le $nameFile - * @param $nameFile le nom du fichier à ouvrir contenant un tableau - * Remarque : $array sera obligatoirement un tableau - */ - public function __construct ($nameFile) { - parent::__construct ($nameFile); - - if (!$this->getLock ('read')) { - throw new PermissionDeniedException ($this->filename); - } else { - $this->array = include ($this->filename); - $this->releaseLock (); - - if (!is_array ($this->array)) { - $this->array = array (); - } - - $this->array = $this->decodeArray ($this->array); - } - } - - /** - * Écrit un tableau dans le fichier $nameFile - * @param $array le tableau php à enregistrer - **/ - public function writeFile ($array) { - if (!$this->getLock ('write')) { - throw new PermissionDeniedException ($this->namefile); - } else { - $this->erase (); - - $this->writeLine ('writeLine ('return ', false); - $this->writeArray ($array); - $this->writeLine (';'); - - $this->releaseLock (); - } - } - - private function writeArray ($array, $profondeur = 0) { - $tab = ''; - for ($i = 0; $i < $profondeur; $i++) { - $tab .= "\t"; - } - $this->writeLine ('array ('); - - foreach ($array as $key => $value) { - if (is_int ($key)) { - $this->writeLine ($tab . "\t" . $key . ' => ', false); - } else { - $this->writeLine ($tab . "\t" . '\'' . $key . '\'' . ' => ', false); - } - - if (is_array ($value)) { - $this->writeArray ($value, $profondeur + 1); - $this->writeLine (','); - } else { - if (is_numeric ($value)) { - $this->writeLine ($value . ','); - } else { - $this->writeLine ('\'' . addslashes ($value) . '\','); - } - } - } - - $this->writeLine ($tab . ')', false); - } - - private function decodeArray ($array) { - $new_array = array (); - - foreach ($array as $key => $value) { - if (is_array ($value)) { - $new_array[$key] = $this->decodeArray ($value); - } else { - $new_array[$key] = stripslashes ($value); - } - } - - return $new_array; - } - - private function getLock ($type) { - if ($type == 'write') { - $lock = LOCK_EX; - } else { - $lock = LOCK_SH; - } - - $count = 1; - while (!flock ($this->file, $lock) && $count <= 50) { - $count++; - } - - if ($count >= 50) { - return false; - } else { - return true; - } - } - - private function releaseLock () { - flock ($this->file, LOCK_UN); - } -} diff --git a/lib/minz/dao/Model_pdo.php b/lib/minz/dao/Model_pdo.php deleted file mode 100755 index a93291fc8..000000000 --- a/lib/minz/dao/Model_pdo.php +++ /dev/null @@ -1,111 +0,0 @@ - -*/ - -/** - * La classe Model_sql représente le modèle interragissant avec les bases de données - * Seul la connexion MySQL est prise en charge pour le moment - */ -class Model_pdo { - - /** - * Partage la connexion à la base de données entre toutes les instances. - */ - public static $useSharedBd = true; - private static $sharedBd = null; - private static $sharedPrefix; - - /** - * $bd variable représentant la base de données - */ - protected $bd; - - protected $prefix; - - /** - * Créé la connexion à la base de données à l'aide des variables - * HOST, BASE, USER et PASS définies dans le fichier de configuration - */ - public function __construct () { - if (self::$useSharedBd && self::$sharedBd != null) { - $this->bd = self::$sharedBd; - $this->prefix = self::$sharedPrefix; - return; - } - - $db = Configuration::dataBase (); - $driver_options = null; - - try { - $type = $db['type']; - if($type == 'mysql') { - $string = $type - . ':host=' . $db['host'] - . ';dbname=' . $db['base'] - . ';charset=utf8'; - $driver_options = array( - PDO::MYSQL_ATTR_INIT_COMMAND => 'SET NAMES utf8' - ); - } elseif($type == 'sqlite') { - $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 ( - $string, - $db['user'], - $db['password'], - $driver_options - ); - self::$sharedBd = $this->bd; - - $userPrefix = Configuration::currentUser (); - $this->prefix = $db['prefix'] . (empty($userPrefix) ? '' : ($userPrefix . '_')); - self::$sharedPrefix = $this->prefix; - } catch (Exception $e) { - throw new PDOConnectionException ( - $string, - $db['user'], MinzException::ERROR - ); - } - } - - public function beginTransaction() { - $this->bd->beginTransaction(); - } - public function commit() { - $this->bd->commit(); - } - public function rollBack() { - $this->bd->rollBack(); - } - - public function size() { - $db = Configuration::dataBase (); - $sql = 'SELECT SUM(data_length + index_length) FROM information_schema.TABLES WHERE table_schema = ?'; - $stm = $this->bd->prepare ($sql); - $values = array ($db['base']); - $stm->execute ($values); - $res = $stm->fetchAll(PDO::FETCH_COLUMN, 0); - return $res[0]; - } -} - -class FreshPDO extends PDO { - private static function check($statement) { - if (preg_match('/^(?:UPDATE|INSERT|DELETE)/i', $statement)) { - invalidateHttpCache(); - } - } - - public function prepare ($statement, $driver_options = array()) { - FreshPDO::check($statement); - return parent::prepare($statement, $driver_options); - } - - public function exec ($statement) { - FreshPDO::check($statement); - return parent::exec($statement); - } -} diff --git a/lib/minz/dao/Model_txt.php b/lib/minz/dao/Model_txt.php deleted file mode 100755 index aed653068..000000000 --- a/lib/minz/dao/Model_txt.php +++ /dev/null @@ -1,84 +0,0 @@ - -*/ - -/** - * La classe Model_txt représente le modèle interragissant avec les fichiers de type texte - */ -class Model_txt { - /** - * $file représente le fichier à ouvrir - */ - protected $file; - - /** - * $filename est le nom du fichier - */ - protected $filename; - - /** - * Ouvre un fichier dans $file - * @param $nameFile nom du fichier à ouvrir - * @param $mode mode d'ouverture du fichier ('a+' par défaut) - * @exception FileNotExistException si le fichier n'existe pas - * > ou ne peux pas être ouvert - */ - public function __construct ($nameFile, $mode = 'a+') { - $this->filename = $nameFile; - if (!file_exists($this->filename)) { - throw new FileNotExistException ( - $this->filename, - MinzException::WARNING - ); - } - - $this->file = @fopen ($this->filename, $mode); - - if (!$this->file) { - throw new PermissionDeniedException ( - $this->filename, - MinzException::WARNING - ); - } - } - - /** - * Lit une ligne de $file - * @return une ligne du fichier - */ - public function readLine () { - return fgets ($this->file); - } - - /** - * Écrit une ligne dans $file - * @param $line la ligne à écrire - */ - public function writeLine ($line, $newLine = true) { - $char = ''; - if ($newLine) { - $char = "\n"; - } - - fwrite ($this->file, $line . $char); - } - - /** - * Efface le fichier $file - * @return true en cas de succès, false sinon - */ - public function erase () { - return ftruncate ($this->file, 0); - } - - /** - * Ferme $file - */ - public function __destruct () { - if (isset ($this->file)) { - fclose ($this->file); - } - } -} diff --git a/lib/minz/exceptions/MinzException.php b/lib/minz/exceptions/MinzException.php deleted file mode 100644 index 4568c4da8..000000000 --- a/lib/minz/exceptions/MinzException.php +++ /dev/null @@ -1,94 +0,0 @@ -route = $route; - - $message = 'Route `' . $route . '` not found'; - - parent::__construct ($message, $code); - } - - public function route () { - return $this->route; - } -} -class PDOConnectionException extends MinzException { - public function __construct ($string_connection, $user, $code = self::ERROR) { - $message = 'Access to database is denied for `' . $user . '`' - . ' (`' . $string_connection . '`)'; - - parent::__construct ($message, $code); - } -} -class CurrentPagePaginationException extends MinzException { - public function __construct ($page) { - $message = 'Page number `' . $page . '` doesn\'t exist'; - - parent::__construct ($message, self::ERROR); - } -} diff --git a/public/index.php b/public/index.php index 3a2bcd3ae..829e418f9 100755 --- a/public/index.php +++ b/public/index.php @@ -37,18 +37,10 @@ if (file_exists ('install.php')) { } } - set_include_path (get_include_path () - . PATH_SEPARATOR - . LIB_PATH - . PATH_SEPARATOR - . LIB_PATH . '/minz' - . PATH_SEPARATOR - . APP_PATH); - - require (APP_PATH . '/App_FrontController.php'); + require(LIB_PATH . '/lib_rss.php'); //Includes class autoloader try { - $front_controller = new App_FrontController (); + $front_controller = new FreshRSS(); $front_controller->init (); $front_controller->run (); } catch (Exception $e) { -- cgit v1.2.3 From ae3225dd71b1aa911a13477e9efb46e1721a2d6a Mon Sep 17 00:00:00 2001 From: Alexandre Alapetite Date: Sun, 15 Dec 2013 11:21:55 +0100 Subject: Delete Entry.php --- app/models/Entry.php | 193 --------------------------------------------------- 1 file changed, 193 deletions(-) delete mode 100755 app/models/Entry.php (limited to 'app/models/Entry.php') diff --git a/app/models/Entry.php b/app/models/Entry.php deleted file mode 100755 index ba0fb48f4..000000000 --- a/app/models/Entry.php +++ /dev/null @@ -1,193 +0,0 @@ -_guid ($guid); - $this->_title ($title); - $this->_author ($author); - $this->_content ($content); - $this->_link ($link); - $this->_date ($pubdate); - $this->_isRead ($is_read); - $this->_isFavorite ($is_favorite); - $this->_feed ($feed); - $this->_tags (preg_split('/[\s#]/', $tags)); - } - - public function id () { - return $this->id; - } - public function guid () { - return $this->guid; - } - public function title () { - return $this->title; - } - public function author () { - if (is_null ($this->author)) { - return ''; - } else { - return $this->author; - } - } - public function content () { - return $this->content; - } - public function link () { - return $this->link; - } - public function date ($raw = false) { - if ($raw) { - return $this->date; - } else { - 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; - } - public function isFavorite () { - return $this->is_favorite; - } - public function feed ($object = false) { - if ($object) { - $feedDAO = new FreshRSS_FeedDAO (); - return $feedDAO->searchById ($this->feed); - } else { - return $this->feed; - } - } - public function tags ($inString = false) { - if ($inString) { - return empty ($this->tags) ? '' : '#' . implode(' #', $this->tags); - } else { - return $this->tags; - } - } - - public function _id ($value) { - $this->id = $value; - } - public function _guid ($value) { - $this->guid = $value; - } - public function _title ($value) { - $this->title = $value; - } - public function _author ($value) { - $this->author = $value; - } - public function _content ($value) { - $this->content = $value; - } - public function _link ($value) { - $this->link = $value; - } - public function _date ($value) { - if (ctype_digit ($value)) { - $this->date = intval ($value); - } else { - $this->date = time (); - } - } - public function _isRead ($value) { - $this->is_read = $value; - } - public function _isFavorite ($value) { - $this->is_favorite = $value; - } - public function _feed ($value) { - $this->feed = $value; - } - public function _tags ($value) { - if (!is_array ($value)) { - $value = array ($value); - } - - foreach ($value as $key => $t) { - if (!$t) { - unset ($value[$key]); - } - } - - $this->tags = $value; - } - - public function isDay ($day) { - $date = $this->dateAdded(true); - $today = @strtotime('today'); - $yesterday = $today - 86400; - - if ($day === FreshRSS_Days::TODAY && - $date >= $today && $date < $today + 86400) { - return true; - } elseif ($day === FreshRSS_Days::YESTERDAY && - $date >= $yesterday && $date < $yesterday + 86400) { - return true; - } elseif ($day === FreshRSS_Days::BEFORE_YESTERDAY && $date < $yesterday) { - return true; - } else { - return false; - } - } - - public function loadCompleteContent($pathEntries) { - // Gestion du contenu - // On cherche à récupérer les articles en entier... même si le flux ne le propose pas - if ($pathEntries) { - $entryDAO = new FreshRSS_EntryDAO(); - $entry = $entryDAO->searchByGuid($this->feed, $this->guid); - - if($entry) { - // l'article existe déjà en BDD, en se contente de recharger ce contenu - $this->content = $entry->content(); - } else { - try { - // l'article n'est pas en BDD, on va le chercher sur le site - $this->content = get_content_by_parsing( - $this->link(), $pathEntries - ); - } catch (Exception $e) { - // rien à faire, on garde l'ancien contenu (requête a échoué) - } - } - } - } - - public function toArray () { - return array ( - 'id' => $this->id (), - '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' => $this->tags (true), - ); - } -} -- cgit v1.2.3