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/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 +++++++++ 8 files changed, 1634 insertions(+) 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 (limited to 'app/Models') 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] . ''; + } +} -- cgit v1.2.3