From d9e14621b5a0de1c189486bbc8c18a7b007d6965 Mon Sep 17 00:00:00 2001 From: romibi Date: Fri, 8 Jul 2016 19:12:43 +0200 Subject: Make Sidebar Sticky --- app/FreshRSS.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'app') diff --git a/app/FreshRSS.php b/app/FreshRSS.php index 4933892bc..b1c01478f 100644 --- a/app/FreshRSS.php +++ b/app/FreshRSS.php @@ -95,7 +95,8 @@ class FreshRSS extends Minz_FrontController { } } - Minz_View::appendScript(Minz_Url::display('/scripts/jquery.min.js?' . @filemtime(PUBLIC_PATH . '/scripts/jquery.min.js'))); + Minz_View::appendScript(Minz_Url::display('/scripts/jquery.min.js?' . @filemtime(PUBLIC_PATH . '/scripts/jquery.min.js')),false,false,false); + Minz_View::appendScript(Minz_Url::display('/scripts/jquery.sticky-kit.min.js?' . @filemtime(PUBLIC_PATH . '/scripts/jquery.sticky-kit.min.js'))); Minz_View::appendScript(Minz_Url::display('/scripts/shortcut.js?' . @filemtime(PUBLIC_PATH . '/scripts/shortcut.js'))); Minz_View::appendScript(Minz_Url::display('/scripts/main.js?' . @filemtime(PUBLIC_PATH . '/scripts/main.js'))); -- cgit v1.2.3 From a180485f9146f22d48470f3ba541317dbc2ee076 Mon Sep 17 00:00:00 2001 From: Alexandre Alapetite Date: Sat, 13 Aug 2016 23:39:52 +0200 Subject: sticky-kit fix, and compatible async defer And set correct parent option https://github.com/FreshRSS/FreshRSS/pull/1172 --- CHANGELOG.md | 1 + app/FreshRSS.php | 3 +-- p/scripts/main.js | 37 +++++++++++++++++++++++++++++-------- 3 files changed, 31 insertions(+), 10 deletions(-) (limited to 'app') diff --git a/CHANGELOG.md b/CHANGELOG.md index 0c8655bca..50498da99 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -20,6 +20,7 @@ * Fixed Apache Etag issue that prevented caching [#1199](https://github.com/FreshRSS/FreshRSS/pull/1199) * Fixed OPML import of categories [#1202](https://github.com/FreshRSS/FreshRSS/issues/1202) * UI + * Use sticky category column [#1172](https://github.com/FreshRSS/FreshRSS/pull/1172) * Updated to jQuery 3.1.0 and several JavaScript fixes (e.g. drag & drop) [#1197](https://github.com/FreshRSS/FreshRSS/pull/1197) * API * Add API link in FreshRSS profile settings to ease set-up [#1186](https://github.com/FreshRSS/FreshRSS/pull/1186) diff --git a/app/FreshRSS.php b/app/FreshRSS.php index 6b36c87f4..f9c371d27 100644 --- a/app/FreshRSS.php +++ b/app/FreshRSS.php @@ -95,8 +95,7 @@ class FreshRSS extends Minz_FrontController { } } - Minz_View::appendScript(Minz_Url::display('/scripts/jquery.min.js?' . @filemtime(PUBLIC_PATH . '/scripts/jquery.min.js')),false,false,false); - Minz_View::appendScript(Minz_Url::display('/scripts/jquery.sticky-kit.min.js?' . @filemtime(PUBLIC_PATH . '/scripts/jquery.sticky-kit.min.js'))); + Minz_View::appendScript(Minz_Url::display('/scripts/jquery.min.js?' . @filemtime(PUBLIC_PATH . '/scripts/jquery.min.js'))); Minz_View::appendScript(Minz_Url::display('/scripts/shortcut.js?' . @filemtime(PUBLIC_PATH . '/scripts/shortcut.js'))); Minz_View::appendScript(Minz_Url::display('/scripts/main.js?' . @filemtime(PUBLIC_PATH . '/scripts/main.js'))); } diff --git a/p/scripts/main.js b/p/scripts/main.js index 9bf0c6dd3..b0ea40965 100644 --- a/p/scripts/main.js +++ b/p/scripts/main.js @@ -493,6 +493,27 @@ function init_posts() { } } +function inject_script(name) { + var script = document.createElement('script'); + script.async = 'async'; + script.defer = 'defer'; + script.src = '../scripts/' + name; + document.head.appendChild(script); +} + +function init_sticky_column() { + if (!window.$ || !window.$.fn.stick_in_parent) { + if (window.console) { + console.log('FreshRSS waiting for Sticky-kit…'); + } + window.setTimeout(init_sticky_column, 200); + return; + } + if ($('.toggle_aside').css('display') === 'none') { + $('#aside_feed .tree').stick_in_parent({parent:'#aside_feed'}); + } +} + function init_column_categories() { if (context.current_view !== 'normal') { return; @@ -508,7 +529,7 @@ function init_column_categories() { this.alt = '▽'; } }); - $(this).parent().next(".tree-folder-items").slideToggle( 400 , function() { $(document.body).trigger("sticky_kit:recalc"); } ); + $(this).parent().next(".tree-folder-items").slideToggle(300 , function() { $(document.body).trigger("sticky_kit:recalc"); }); return false; }); $('#aside_feed').on('click', '.tree-folder-items .item .dropdown-toggle', function () { @@ -519,9 +540,8 @@ function init_column_categories() { $(this).attr('href', '#dropdown-' + feed_id).prev('.dropdown-target').attr('id', 'dropdown-' + feed_id).parent().append(template); } }); - if( $('.toggle_aside').css('display')=='none') { - $('#aside_feed .tree').stick_in_parent(); - } + + init_sticky_column(); } function init_shortcuts() { @@ -529,7 +549,7 @@ function init_shortcuts() { if (window.console) { console.log('FreshRSS waiting for sortcut.js…'); } - window.setTimeout(init_shortcuts, 50); + window.setTimeout(init_shortcuts, 200); return; } // Touches de manipulation @@ -1313,7 +1333,7 @@ function init_normal() { if (window.console) { console.log('FreshRSS waiting for content…'); } - window.setTimeout(init_normal, 50); + window.setTimeout(init_normal, 100); return; } init_column_categories(); @@ -1328,11 +1348,12 @@ function init_beforeDOM() { if (window.console) { console.log('FreshRSS waiting for jQuery…'); } - window.setTimeout(init_beforeDOM, 50); + window.setTimeout(init_beforeDOM, 100); return; } init_confirm_action(); if (['normal', 'reader', 'global'].indexOf(context.current_view) >= 0) { + inject_script('jquery.sticky-kit.min.js'); init_normal(); } } @@ -1342,7 +1363,7 @@ function init_afterDOM() { if (window.console) { console.log('FreshRSS waiting again for jQuery…'); } - window.setTimeout(init_afterDOM, 50); + window.setTimeout(init_afterDOM, 100); return; } init_notifications(); -- cgit v1.2.3 From dd7d5855e3aedfca2ca216049afd3a1aaa23733b Mon Sep 17 00:00:00 2001 From: Alexandre Alapetite Date: Sun, 14 Aug 2016 19:55:27 +0200 Subject: Remove code for PHP 5.3.2- --- README.fr.md | 2 +- README.md | 2 +- app/Models/ConfigurationSetter.php | 7 +----- lib/lib_rss.php | 45 +++++--------------------------------- 4 files changed, 9 insertions(+), 47 deletions(-) (limited to 'app') diff --git a/README.fr.md b/README.fr.md index 577c7b73e..507a6010d 100644 --- a/README.fr.md +++ b/README.fr.md @@ -32,7 +32,7 @@ Nous sommes une communauté amicale. * Serveur modeste, par exemple sous Linux ou Windows * Fonctionne même sur un Raspberry Pi 1 avec des temps de réponse < 1s (testé sur 150 flux, 22k articles) * Serveur Web Apache2 (recommandé), ou nginx, lighttpd (non testé sur les autres) -* PHP 5.3.3+ (PHP 5.3.7+ recommandé, et PHP 5.5+ pour les performances, et PHP 7+ pour d’encore meilleures performances) +* PHP 5.3.3+ (PHP 5.4+ recommandé, et PHP 5.5+ pour les performances, et PHP 7+ pour d’encore meilleures performances) * Requis : [PDO_MySQL](http://php.net/pdo-mysql) ou [PDO_SQLite](http://php.net/pdo-sqlite), [cURL](http://php.net/curl), [GMP](http://php.net/gmp) (pour accès API sur plateformes < 64 bits), [IDN](http://php.net/intl.idn) (pour les noms de domaines internationalisés) * Recommandés : [iconv](http://php.net/iconv), [JSON](http://php.net/json), [mbstring](http://php.net/mbstring), [Zip](http://php.net/zip), [zlib](http://php.net/zlib) * Inclus par défaut : [DOM](http://php.net/dom), [XML](http://php.net/xml)… diff --git a/README.md b/README.md index 9a8355f9c..cc1e258ff 100644 --- a/README.md +++ b/README.md @@ -32,7 +32,7 @@ We are a friendly community. * Light server running Linux or Windows * It even works on Raspberry Pi 1 with response time under a second (tested with 150 feeds, 22k articles) * A web server: Apache2 (recommended), nginx, lighttpd (not tested on others) -* PHP 5.3.3+ (PHP 5.3.7+ recommended, and PHP 5.5+ for performance, and PHP 7 for even higher performance) +* PHP 5.3.3+ (PHP 5.4+ recommended, and PHP 5.5+ for performance, and PHP 7 for even higher performance) * Required extensions: [PDO_MySQL](http://php.net/pdo-mysql) or [PDO_SQLite](http://php.net/pdo-sqlite), [cURL](http://php.net/curl), [GMP](http://php.net/gmp) (for API access on platforms < 64 bits), [IDN](http://php.net/intl.idn) (for Internationalized Domain Names) * Recommended extensions: [iconv](http://php.net/iconv), [JSON](http://php.net/json), [mbstring](http://php.net/mbstring), [Zip](http://php.net/zip), [zlib](http://php.net/zlib) * Enabled by default: [DOM](http://php.net/dom), [XML](http://php.net/xml)… diff --git a/app/Models/ConfigurationSetter.php b/app/Models/ConfigurationSetter.php index e472b1e7f..79bd0170b 100644 --- a/app/Models/ConfigurationSetter.php +++ b/app/Models/ConfigurationSetter.php @@ -129,12 +129,7 @@ class FreshRSS_ConfigurationSetter { // Verify URL and add default value when needed if (isset($value['url'])) { - $is_url = ( - filter_var($value['url'], FILTER_VALIDATE_URL) || - (version_compare(PHP_VERSION, '5.3.3', '<') && - (strpos($value, '-') > 0) && - ($value === filter_var($value, FILTER_SANITIZE_URL))) - ); //PHP bug #51192 + $is_url = filter_var($value['url'], FILTER_VALIDATE_URL); if (!$is_url) { continue; } diff --git a/lib/lib_rss.php b/lib/lib_rss.php index b5ba78889..cf56ae9b2 100644 --- a/lib/lib_rss.php +++ b/lib/lib_rss.php @@ -15,35 +15,6 @@ if (!function_exists('json_encode')) { } } -if (!function_exists('array_replace_recursive')) { //PHP 5.2 - function arr_recurse($array, $array1) { - foreach ($array1 as $key => $value) { - if (!isset($array[$key]) || (isset($array[$key]) && !is_array($array[$key]))) { - $array[$key] = array(); //create new key in $array, if it is empty or not an array - } - if (is_array($value)) { - $value = arr_recurse($array[$key], $value); // overwrite the value in the base array - } - $array[$key] = $value; - } - return $array; - } - function array_replace_recursive($array, $array1) { //http://php.net/manual/function.array-replace-recursive.php#92574 - // handle the arguments, merge one by one - $args = func_get_args(); - $array = $args[0]; - if (!is_array($array)) { - return $array; - } - for ($i = 1; $i < count($args); $i++) { - if (is_array($args[$i])) { - $array = arr_recurse($array, $args[$i]); - } - } - return $array; - } -} - /** * Build a directory path by concatenating a list of directory names. * @@ -103,9 +74,7 @@ function checkUrl($url) { $url = 'http://' . $url; } $url = idn_to_puny($url); //PHP bug #53474 IDN - if (filter_var($url, FILTER_VALIDATE_URL) || - (version_compare(PHP_VERSION, '5.3.3', '<') && (strpos($url, '-') > 0) && //PHP bug #51192 - ($url === filter_var($url, FILTER_SANITIZE_URL)))) { + if (filter_var($url, FILTER_VALIDATE_URL)) { return $url; } else { return false; @@ -379,12 +348,10 @@ function httpAuthUser() { } function cryptAvailable() { - if (version_compare(PHP_VERSION, '5.3.3', '>=')) { - try { - $hash = '$2y$04$usesomesillystringfore7hnbRJHxXVLeakoG8K30oukPsA.ztMG'; - return $hash === @crypt('password', $hash); - } catch (Exception $e) { - } + try { + $hash = '$2y$04$usesomesillystringfore7hnbRJHxXVLeakoG8K30oukPsA.ztMG'; + return $hash === @crypt('password', $hash); + } catch (Exception $e) { } return false; } @@ -416,7 +383,7 @@ function check_install_php() { $pdo_mysql = extension_loaded('pdo_mysql'); $pdo_sqlite = extension_loaded('pdo_sqlite'); return array( - 'php' => version_compare(PHP_VERSION, '5.2.1') >= 0, + 'php' => version_compare(PHP_VERSION, '5.3.3') >= 0, 'minz' => file_exists(LIB_PATH . '/Minz'), 'curl' => extension_loaded('curl'), 'pdo' => $pdo_mysql || $pdo_sqlite, -- cgit v1.2.3 From a0230ad70b0e1d5cef7423f101adeba1e1fe34b3 Mon Sep 17 00:00:00 2001 From: Alexandre Alapetite Date: Mon, 15 Aug 2016 21:57:37 +0200 Subject: Minor HTML fixes Fix aria bug. Move some content before the flush. XHTML syntax. --- app/layout/layout.phtml | 15 ++++++++------- app/layout/nav_menu.phtml | 2 +- 2 files changed, 9 insertions(+), 8 deletions(-) (limited to 'app') diff --git a/app/layout/layout.phtml b/app/layout/layout.phtml index 189d93fbe..4d9ad5458 100644 --- a/app/layout/layout.phtml +++ b/app/layout/layout.phtml @@ -11,16 +11,19 @@ - - - - - + + + + + +allow_referrer) { ?> + callbackBeforeContent)) { call_user_func($this->callbackBeforeContent, $this); @@ -41,8 +44,6 @@ $url_rss['a'] = 'rss'; ?> -allow_referrer) { ?> - allow_robots) { ?> diff --git a/app/layout/nav_menu.phtml b/app/layout/nav_menu.phtml index 17655acbf..488c6fdef 100644 --- a/app/layout/nav_menu.phtml +++ b/app/layout/nav_menu.phtml @@ -22,7 +22,7 @@ ?> -- cgit v1.2.3 From 32c734ef622f4ed83d212d3eb1d15d83d406bd86 Mon Sep 17 00:00:00 2001 From: Alexandre Alapetite Date: Thu, 18 Aug 2016 00:00:08 +0200 Subject: SQL mark search as read https://github.com/FreshRSS/FreshRSS/issues/608 --- app/Controllers/entryController.php | 19 ++++- app/Models/EntryDAO.php | 150 ++++++++++++++++++++---------------- app/layout/nav_menu.phtml | 2 + app/views/helpers/pagination.phtml | 2 + 4 files changed, 102 insertions(+), 71 deletions(-) (limited to 'app') diff --git a/app/Controllers/entryController.php b/app/Controllers/entryController.php index bff1073ef..c40588105 100755 --- a/app/Controllers/entryController.php +++ b/app/Controllers/entryController.php @@ -40,6 +40,17 @@ class FreshRSS_entry_Controller extends Minz_ActionController { $get = Minz_Request::param('get'); $next_get = Minz_Request::param('nextGet', $get); $id_max = Minz_Request::param('idMax', 0); + FreshRSS_Context::$search = new FreshRSS_Search(Minz_Request::param('search', '')); + + FreshRSS_Context::$state = Minz_Request::param('state', 0); + if (FreshRSS_Context::isStateEnabled(FreshRSS_Entry::STATE_FAVORITE)) { + FreshRSS_Context::$state = FreshRSS_Entry::STATE_FAVORITE; + } elseif (FreshRSS_Context::isStateEnabled(FreshRSS_Entry::STATE_NOT_FAVORITE)) { + FreshRSS_Context::$state = FreshRSS_Entry::STATE_NOT_FAVORITE; + } else { + FreshRSS_Context::$state = 0; + } + $params = array(); $entryDAO = FreshRSS_Factory::createEntryDao(); @@ -58,16 +69,16 @@ class FreshRSS_entry_Controller extends Minz_ActionController { $get = substr($get, 2); switch($type_get) { case 'c': - $entryDAO->markReadCat($get, $id_max); + $entryDAO->markReadCat($get, $id_max, FreshRSS_Context::$search, FreshRSS_Context::$state); break; case 'f': - $entryDAO->markReadFeed($get, $id_max); + $entryDAO->markReadFeed($get, $id_max, FreshRSS_Context::$search, FreshRSS_Context::$state); break; case 's': - $entryDAO->markReadEntries($id_max, true); + $entryDAO->markReadEntries($id_max, true, 0, FreshRSS_Context::$search); break; case 'a': - $entryDAO->markReadEntries($id_max); + $entryDAO->markReadEntries($id_max, false, 0, FreshRSS_Context::$search, FreshRSS_Context::$state); break; } diff --git a/app/Models/EntryDAO.php b/app/Models/EntryDAO.php index c9e6f9742..3bb8a720c 100644 --- a/app/Models/EntryDAO.php +++ b/app/Models/EntryDAO.php @@ -344,7 +344,7 @@ class FreshRSS_EntryDAO extends Minz_ModelPdo implements FreshRSS_Searchable { * @param integer $priorityMin * @return integer affected rows */ - public function markReadEntries($idMax = 0, $onlyFavorites = false, $priorityMin = 0) { + public function markReadEntries($idMax = 0, $onlyFavorites = false, $priorityMin = 0, $filter = null, $state = 0) { if ($idMax == 0) { $idMax = time() . '000000'; Minz_Log::debug('Calling markReadEntries(0) is deprecated!'); @@ -359,8 +359,11 @@ class FreshRSS_EntryDAO extends Minz_ModelPdo implements FreshRSS_Searchable { $sql .= ' AND f.priority > ' . intval($priorityMin); } $values = array($idMax); - $stm = $this->bd->prepare($sql); - if (!($stm && $stm->execute($values))) { + + list($searchValues, $search) = $this->sqlListEntriesWhere($filter, $state); + + $stm = $this->bd->prepare($sql . $search); + if (!($stm && $stm->execute(array_merge($values, $searchValues)))) { $info = $stm == null ? array(2 => 'syntax error') : $stm->errorInfo(); Minz_Log::error('SQL error markReadEntries: ' . $info[2]); return false; @@ -383,7 +386,7 @@ class FreshRSS_EntryDAO extends Minz_ModelPdo implements FreshRSS_Searchable { * @param integer $idMax fail safe article ID * @return integer affected rows */ - public function markReadCat($id, $idMax = 0) { + public function markReadCat($id, $idMax = 0, $filter = null, $state = 0) { if ($idMax == 0) { $idMax = time() . '000000'; Minz_Log::debug('Calling markReadCat(0) is deprecated!'); @@ -393,8 +396,11 @@ class FreshRSS_EntryDAO extends Minz_ModelPdo implements FreshRSS_Searchable { . '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))) { + + list($searchValues, $search) = $this->sqlListEntriesWhere($filter, $state); + + $stm = $this->bd->prepare($sql . $search); + if (!($stm && $stm->execute(array_merge($values, $searchValues)))) { $info = $stm == null ? array(2 => 'syntax error') : $stm->errorInfo(); Minz_Log::error('SQL error markReadCat: ' . $info[2]); return false; @@ -417,19 +423,22 @@ class FreshRSS_EntryDAO extends Minz_ModelPdo implements FreshRSS_Searchable { * @param integer $idMax fail safe article ID * @return integer affected rows */ - public function markReadFeed($id_feed, $idMax = 0) { + public function markReadFeed($id_feed, $idMax = 0, $filter = null, $state = 0) { if ($idMax == 0) { $idMax = time() . '000000'; Minz_Log::debug('Calling markReadFeed(0) is deprecated!'); } $this->bd->beginTransaction(); - $sql = 'UPDATE `' . $this->prefix . 'entry` ' - . 'SET is_read=1 ' - . 'WHERE id_feed=? AND is_read=0 AND id <= ?'; + $sql = 'UPDATE `' . $this->prefix . 'entry` e ' + . 'SET e.is_read=1 ' + . 'WHERE e.id_feed=? AND e.is_read=0 AND e.id <= ?'; $values = array($id_feed, $idMax); - $stm = $this->bd->prepare($sql); - if (!($stm && $stm->execute($values))) { + + list($searchValues, $search) = $this->sqlListEntriesWhere($filter, $state); + + $stm = $this->bd->prepare($sql . $search); + if (!($stm && $stm->execute(array_merge($values, $searchValues)))) { $info = $stm == null ? array(2 => 'syntax error') : $stm->errorInfo(); Minz_Log::error('SQL error markReadFeed: ' . $info[2]); $this->bd->rollBack(); @@ -493,52 +502,24 @@ class FreshRSS_EntryDAO extends Minz_ModelPdo implements FreshRSS_Searchable { return 'CONCAT(' . $s1 . ',' . $s2 . ')'; //MySQL } - private function sqlListWhere($type = 'a', $id = '', $state = FreshRSS_Entry::STATE_ALL, $order = 'DESC', $limit = 1, $firstId = '', $filter = '', $date_min = 0) { - if (!$state) { - $state = FreshRSS_Entry::STATE_ALL; - } - $where = ''; - $joinFeed = false; + private function sqlListEntriesWhere($filter = null, $state = FreshRSS_Entry::STATE_ALL, $order = 'DESC', $firstId = '', $date_min = 0) { + $search = ' '; $values = array(); - switch ($type) { - case 'a': - $where .= 'f.priority > 0 '; - $joinFeed = true; - break; - case 's': //Deprecated: use $state instead - $where .= 'e1.is_favorite=1 '; - break; - case 'c': - $where .= 'f.category=? '; - $values[] = intval($id); - $joinFeed = true; - break; - case 'f': - $where .= 'e1.id_feed=? '; - $values[] = intval($id); - break; - case 'A': - $where .= '1 '; - break; - default: - throw new FreshRSS_EntriesGetter_Exception('Bad type in Entry->listByType: [' . $type . ']!'); - } - if ($state & FreshRSS_Entry::STATE_NOT_READ) { if (!($state & FreshRSS_Entry::STATE_READ)) { - $where .= 'AND e1.is_read=0 '; + $search .= 'AND e.is_read=0 '; } } elseif ($state & FreshRSS_Entry::STATE_READ) { - $where .= 'AND e1.is_read=1 '; + $search .= 'AND e.is_read=1 '; } if ($state & FreshRSS_Entry::STATE_FAVORITE) { if (!($state & FreshRSS_Entry::STATE_NOT_FAVORITE)) { - $where .= 'AND e1.is_favorite=1 '; + $search .= 'AND e.is_favorite=1 '; } } elseif ($state & FreshRSS_Entry::STATE_NOT_FAVORITE) { - $where .= 'AND e1.is_favorite=0 '; + $search .= 'AND e.is_favorite=0 '; } switch ($order) { @@ -552,76 +533,111 @@ class FreshRSS_EntryDAO extends Minz_ModelPdo implements FreshRSS_Searchable { $firstId = $order === 'DESC' ? '9000000000'. '000000' : '0'; //MySQL optimization. TODO: check if this is needed again, after the filtering for old articles has been removed in 0.9-dev }*/ if ($firstId !== '') { - $where .= 'AND e1.id ' . ($order === 'DESC' ? '<=' : '>=') . $firstId . ' '; + $search .= 'AND e.id ' . ($order === 'DESC' ? '<=' : '>=') . $firstId . ' '; } if ($date_min > 0) { - $where .= 'AND e1.id >= ' . $date_min . '000000 '; + $search .= 'AND e.id >= ' . $date_min . '000000 '; } - $search = ''; if ($filter) { if ($filter->getIntitle()) { - $search .= 'AND e1.title LIKE ? '; + $search .= 'AND e.title LIKE ? '; $values[] = "%{$filter->getIntitle()}%"; } if ($filter->getInurl()) { - $search .= 'AND CONCAT(e1.link, e1.guid) LIKE ? '; + $search .= 'AND CONCAT(e.link, e.guid) LIKE ? '; $values[] = "%{$filter->getInurl()}%"; } if ($filter->getAuthor()) { - $search .= 'AND e1.author LIKE ? '; + $search .= 'AND e.author LIKE ? '; $values[] = "%{$filter->getAuthor()}%"; } if ($filter->getMinDate()) { - $search .= 'AND e1.id >= ? '; + $search .= 'AND e.id >= ? '; $values[] = "{$filter->getMinDate()}000000"; } if ($filter->getMaxDate()) { - $search .= 'AND e1.id <= ? '; + $search .= 'AND e.id <= ? '; $values[] = "{$filter->getMaxDate()}000000"; } if ($filter->getMinPubdate()) { - $search .= 'AND e1.date >= ? '; + $search .= 'AND e.date >= ? '; $values[] = $filter->getMinPubdate(); } if ($filter->getMaxPubdate()) { - $search .= 'AND e1.date <= ? '; + $search .= 'AND e.date <= ? '; $values[] = $filter->getMaxPubdate(); } if ($filter->getTags()) { $tags = $filter->getTags(); foreach ($tags as $tag) { - $search .= 'AND e1.tags LIKE ? '; + $search .= 'AND e.tags LIKE ? '; $values[] = "%{$tag}%"; } } if ($filter->getSearch()) { $search_values = $filter->getSearch(); foreach ($search_values as $search_value) { - $search .= 'AND ' . $this->sqlconcat('e1.title', $this->isCompressed() ? 'UNCOMPRESS(content_bin)' : 'content') . ' LIKE ? '; + $search .= 'AND ' . $this->sqlconcat('e.title', $this->isCompressed() ? 'UNCOMPRESS(content_bin)' : 'content') . ' LIKE ? '; $values[] = "%{$search_value}%"; } } } - return array($values, - 'SELECT e1.id FROM `' . $this->prefix . 'entry` e1 ' - . ($joinFeed ? 'INNER JOIN `' . $this->prefix . 'feed` f ON e1.id_feed=f.id ' : '') + return array($values, $search); + } + + private function sqlListWhere($type = 'a', $id = '', $state = FreshRSS_Entry::STATE_ALL, $order = 'DESC', $limit = 1, $firstId = '', $filter = '', $date_min = 0) { + if (!$state) { + $state = FreshRSS_Entry::STATE_ALL; + } + $where = ''; + $joinFeed = false; + $values = array(); + switch ($type) { + case 'a': + $where .= 'f.priority > 0 '; + $joinFeed = true; + break; + case 's': //Deprecated: use $state instead + $where .= 'e.is_favorite=1 '; + break; + case 'c': + $where .= 'f.category=? '; + $values[] = intval($id); + $joinFeed = true; + break; + case 'f': + $where .= 'e.id_feed=? '; + $values[] = intval($id); + break; + case 'A': + $where .= '1 '; + break; + default: + throw new FreshRSS_EntriesGetter_Exception('Bad type in Entry->listByType: [' . $type . ']!'); + } + + list($searchValues, $search) = $this->sqlListEntriesWhere($filter, $state, $order, $firstId, $date_min); + + return array(array_merge($values, $searchValues), + 'SELECT e.id FROM `' . $this->prefix . 'entry` e ' + . ($joinFeed ? 'INNER JOIN `' . $this->prefix . 'feed` f ON e.id_feed=f.id ' : '') . 'WHERE ' . $where . $search - . 'ORDER BY e1.id ' . $order + . 'ORDER BY e.id ' . $order . ($limit > 0 ? ' LIMIT ' . $limit : '')); //TODO: See http://explainextended.com/2009/10/23/mysql-order-by-limit-performance-late-row-lookups/ } public function listWhere($type = 'a', $id = '', $state = FreshRSS_Entry::STATE_ALL, $order = 'DESC', $limit = 1, $firstId = '', $filter = '', $date_min = 0) { list($values, $sql) = $this->sqlListWhere($type, $id, $state, $order, $limit, $firstId, $filter, $date_min); - $sql = 'SELECT e.id, e.guid, e.title, e.author, ' + $sql = 'SELECT e0.id, e0.guid, e0.title, e0.author, ' . ($this->isCompressed() ? 'UNCOMPRESS(content_bin) AS content' : 'content') - . ', e.link, e.date, e.is_read, e.is_favorite, e.id_feed, e.tags ' - . 'FROM `' . $this->prefix . 'entry` e ' + . ', e0.link, e0.date, e0.is_read, e0.is_favorite, e0.id_feed, e0.tags ' + . 'FROM `' . $this->prefix . 'entry` e0 ' . 'INNER JOIN (' . $sql - . ') e2 ON e2.id=e.id ' - . 'ORDER BY e.id ' . $order; + . ') e2 ON e2.id=e0.id ' + . 'ORDER BY e0.id ' . $order; $stm = $this->bd->prepare($sql); $stm->execute($values); diff --git a/app/layout/nav_menu.phtml b/app/layout/nav_menu.phtml index 488c6fdef..23255f04f 100644 --- a/app/layout/nav_menu.phtml +++ b/app/layout/nav_menu.phtml @@ -75,6 +75,8 @@ 'get' => $get, 'nextGet' => FreshRSS_Context::$next_get, 'idMax' => FreshRSS_Context::$id_max, + 'search' => FreshRSS_Context::$search, + 'state' => FreshRSS_Context::$state, ) ); ?> diff --git a/app/views/helpers/pagination.phtml b/app/views/helpers/pagination.phtml index 23c45114d..20957fc67 100755 --- a/app/views/helpers/pagination.phtml +++ b/app/views/helpers/pagination.phtml @@ -10,6 +10,8 @@ 'get' => FreshRSS_Context::currentGet(), 'nextGet' => FreshRSS_Context::$next_get, 'idMax' => FreshRSS_Context::$id_max, + 'search' => FreshRSS_Context::$search, + 'state' => FreshRSS_Context::$state, ) ); ?> -- cgit v1.2.3 From 6afa36e7e101236b4ac08f8c267f4e2bd78f4ea6 Mon Sep 17 00:00:00 2001 From: Alexandre Alapetite Date: Fri, 19 Aug 2016 11:05:24 +0200 Subject: SQLite fix for mark search as read https://github.com/FreshRSS/FreshRSS/issues/1220 https://github.com/FreshRSS/FreshRSS/pull/1218 https://github.com/FreshRSS/FreshRSS/issues/608 --- app/Models/EntryDAO.php | 2 +- app/Models/EntryDAOSQLite.php | 20 +++++++++++++------- 2 files changed, 14 insertions(+), 8 deletions(-) (limited to 'app') diff --git a/app/Models/EntryDAO.php b/app/Models/EntryDAO.php index 3bb8a720c..769d2ae6c 100644 --- a/app/Models/EntryDAO.php +++ b/app/Models/EntryDAO.php @@ -502,7 +502,7 @@ class FreshRSS_EntryDAO extends Minz_ModelPdo implements FreshRSS_Searchable { return 'CONCAT(' . $s1 . ',' . $s2 . ')'; //MySQL } - private function sqlListEntriesWhere($filter = null, $state = FreshRSS_Entry::STATE_ALL, $order = 'DESC', $firstId = '', $date_min = 0) { + protected function sqlListEntriesWhere($filter = null, $state = FreshRSS_Entry::STATE_ALL, $order = 'DESC', $firstId = '', $date_min = 0) { $search = ' '; $values = array(); if ($state & FreshRSS_Entry::STATE_NOT_READ) { diff --git a/app/Models/EntryDAOSQLite.php b/app/Models/EntryDAOSQLite.php index 19b97fd3a..de02616d6 100644 --- a/app/Models/EntryDAOSQLite.php +++ b/app/Models/EntryDAOSQLite.php @@ -119,7 +119,7 @@ class FreshRSS_EntryDAOSQLite extends FreshRSS_EntryDAO { * @param integer $priorityMin * @return integer affected rows */ - public function markReadEntries($idMax = 0, $onlyFavorites = false, $priorityMin = 0) { + public function markReadEntries($idMax = 0, $onlyFavorites = false, $priorityMin = 0, $filter = null, $state = 0) { if ($idMax == 0) { $idMax = time() . '000000'; Minz_Log::debug('Calling markReadEntries(0) is deprecated!'); @@ -132,8 +132,11 @@ class FreshRSS_EntryDAOSQLite extends FreshRSS_EntryDAO { $sql .= ' AND id_feed IN (SELECT f.id FROM `' . $this->prefix . 'feed` f WHERE f.priority > ' . intval($priorityMin) . ')'; } $values = array($idMax); - $stm = $this->bd->prepare($sql); - if (!($stm && $stm->execute($values))) { + + list($searchValues, $search) = $this->sqlListEntriesWhere($filter, $state); + + $stm = $this->bd->prepare($sql . $search); + if (!($stm && $stm->execute(array_merge($values, $searchValues)))) { $info = $stm == null ? array(2 => 'syntax error') : $stm->errorInfo(); Minz_Log::error('SQL error markReadEntries: ' . $info[2]); return false; @@ -156,7 +159,7 @@ class FreshRSS_EntryDAOSQLite extends FreshRSS_EntryDAO { * @param integer $idMax fail safe article ID * @return integer affected rows */ - public function markReadCat($id, $idMax = 0) { + public function markReadCat($id, $idMax = 0, $filter = null, $state = 0) { if ($idMax == 0) { $idMax = time() . '000000'; Minz_Log::debug('Calling markReadCat(0) is deprecated!'); @@ -166,9 +169,12 @@ class FreshRSS_EntryDAOSQLite extends FreshRSS_EntryDAO { . 'SET is_read=1 ' . 'WHERE is_read=0 AND id <= ? AND ' . 'id_feed IN (SELECT f.id FROM `' . $this->prefix . 'feed` f WHERE f.category=?)'; - $values = array($idMax, $id); - $stm = $this->bd->prepare($sql); - if (!($stm && $stm->execute($values))) { + $values = array($id, $idMax); + + list($searchValues, $search) = $this->sqlListEntriesWhere($filter, $state); + + $stm = $this->bd->prepare($sql . $search); + if (!($stm && $stm->execute(array_merge($values, $searchValues)))) { $info = $stm == null ? array(2 => 'syntax error') : $stm->errorInfo(); Minz_Log::error('SQL error markReadCat: ' . $info[2]); return false; -- cgit v1.2.3 From edd4516178c49f966248d832e63776f5f2f90236 Mon Sep 17 00:00:00 2001 From: Alexandre Alapetite Date: Fri, 19 Aug 2016 14:33:08 +0200 Subject: More SQLite fix for mark search as read --- app/Models/EntryDAO.php | 40 ++++++++++++++++++++-------------------- app/Models/EntryDAOSQLite.php | 6 +++--- 2 files changed, 23 insertions(+), 23 deletions(-) (limited to 'app') diff --git a/app/Models/EntryDAO.php b/app/Models/EntryDAO.php index 769d2ae6c..8f64098e5 100644 --- a/app/Models/EntryDAO.php +++ b/app/Models/EntryDAO.php @@ -360,7 +360,7 @@ class FreshRSS_EntryDAO extends Minz_ModelPdo implements FreshRSS_Searchable { } $values = array($idMax); - list($searchValues, $search) = $this->sqlListEntriesWhere($filter, $state); + list($searchValues, $search) = $this->sqlListEntriesWhere('e.', $filter, $state); $stm = $this->bd->prepare($sql . $search); if (!($stm && $stm->execute(array_merge($values, $searchValues)))) { @@ -397,7 +397,7 @@ class FreshRSS_EntryDAO extends Minz_ModelPdo implements FreshRSS_Searchable { . 'WHERE f.category=? AND e.is_read=0 AND e.id <= ?'; $values = array($id, $idMax); - list($searchValues, $search) = $this->sqlListEntriesWhere($filter, $state); + list($searchValues, $search) = $this->sqlListEntriesWhere('e.', $filter, $state); $stm = $this->bd->prepare($sql . $search); if (!($stm && $stm->execute(array_merge($values, $searchValues)))) { @@ -435,7 +435,7 @@ class FreshRSS_EntryDAO extends Minz_ModelPdo implements FreshRSS_Searchable { . 'WHERE e.id_feed=? AND e.is_read=0 AND e.id <= ?'; $values = array($id_feed, $idMax); - list($searchValues, $search) = $this->sqlListEntriesWhere($filter, $state); + list($searchValues, $search) = $this->sqlListEntriesWhere('e.', $filter, $state); $stm = $this->bd->prepare($sql . $search); if (!($stm && $stm->execute(array_merge($values, $searchValues)))) { @@ -502,24 +502,24 @@ class FreshRSS_EntryDAO extends Minz_ModelPdo implements FreshRSS_Searchable { return 'CONCAT(' . $s1 . ',' . $s2 . ')'; //MySQL } - protected function sqlListEntriesWhere($filter = null, $state = FreshRSS_Entry::STATE_ALL, $order = 'DESC', $firstId = '', $date_min = 0) { + protected function sqlListEntriesWhere($alias = '', $filter = null, $state = FreshRSS_Entry::STATE_ALL, $order = 'DESC', $firstId = '', $date_min = 0) { $search = ' '; $values = array(); if ($state & FreshRSS_Entry::STATE_NOT_READ) { if (!($state & FreshRSS_Entry::STATE_READ)) { - $search .= 'AND e.is_read=0 '; + $search .= 'AND ' . $alias . 'is_read=0 '; } } elseif ($state & FreshRSS_Entry::STATE_READ) { - $search .= 'AND e.is_read=1 '; + $search .= 'AND ' . $alias . 'is_read=1 '; } if ($state & FreshRSS_Entry::STATE_FAVORITE) { if (!($state & FreshRSS_Entry::STATE_NOT_FAVORITE)) { - $search .= 'AND e.is_favorite=1 '; + $search .= 'AND ' . $alias . 'is_favorite=1 '; } } elseif ($state & FreshRSS_Entry::STATE_NOT_FAVORITE) { - $search .= 'AND e.is_favorite=0 '; + $search .= 'AND ' . $alias . 'is_favorite=0 '; } switch ($order) { @@ -533,51 +533,51 @@ class FreshRSS_EntryDAO extends Minz_ModelPdo implements FreshRSS_Searchable { $firstId = $order === 'DESC' ? '9000000000'. '000000' : '0'; //MySQL optimization. TODO: check if this is needed again, after the filtering for old articles has been removed in 0.9-dev }*/ if ($firstId !== '') { - $search .= 'AND e.id ' . ($order === 'DESC' ? '<=' : '>=') . $firstId . ' '; + $search .= 'AND ' . $alias . 'id ' . ($order === 'DESC' ? '<=' : '>=') . $firstId . ' '; } if ($date_min > 0) { - $search .= 'AND e.id >= ' . $date_min . '000000 '; + $search .= 'AND ' . $alias . 'id >= ' . $date_min . '000000 '; } if ($filter) { if ($filter->getIntitle()) { - $search .= 'AND e.title LIKE ? '; + $search .= 'AND ' . $alias . 'title LIKE ? '; $values[] = "%{$filter->getIntitle()}%"; } if ($filter->getInurl()) { - $search .= 'AND CONCAT(e.link, e.guid) LIKE ? '; + $search .= 'AND CONCAT(' . $alias . 'link, ' . $alias . 'guid) LIKE ? '; $values[] = "%{$filter->getInurl()}%"; } if ($filter->getAuthor()) { - $search .= 'AND e.author LIKE ? '; + $search .= 'AND ' . $alias . 'author LIKE ? '; $values[] = "%{$filter->getAuthor()}%"; } if ($filter->getMinDate()) { - $search .= 'AND e.id >= ? '; + $search .= 'AND ' . $alias . 'id >= ? '; $values[] = "{$filter->getMinDate()}000000"; } if ($filter->getMaxDate()) { - $search .= 'AND e.id <= ? '; + $search .= 'AND ' . $alias . 'id <= ? '; $values[] = "{$filter->getMaxDate()}000000"; } if ($filter->getMinPubdate()) { - $search .= 'AND e.date >= ? '; + $search .= 'AND ' . $alias . 'date >= ? '; $values[] = $filter->getMinPubdate(); } if ($filter->getMaxPubdate()) { - $search .= 'AND e.date <= ? '; + $search .= 'AND ' . $alias . 'date <= ? '; $values[] = $filter->getMaxPubdate(); } if ($filter->getTags()) { $tags = $filter->getTags(); foreach ($tags as $tag) { - $search .= 'AND e.tags LIKE ? '; + $search .= 'AND ' . $alias . 'tags LIKE ? '; $values[] = "%{$tag}%"; } } if ($filter->getSearch()) { $search_values = $filter->getSearch(); foreach ($search_values as $search_value) { - $search .= 'AND ' . $this->sqlconcat('e.title', $this->isCompressed() ? 'UNCOMPRESS(content_bin)' : 'content') . ' LIKE ? '; + $search .= 'AND ' . $this->sqlconcat($alias . 'title', $this->isCompressed() ? 'UNCOMPRESS(' . $alias . 'content_bin)' : '' . $alias . 'content') . ' LIKE ? '; $values[] = "%{$search_value}%"; } } @@ -616,7 +616,7 @@ class FreshRSS_EntryDAO extends Minz_ModelPdo implements FreshRSS_Searchable { throw new FreshRSS_EntriesGetter_Exception('Bad type in Entry->listByType: [' . $type . ']!'); } - list($searchValues, $search) = $this->sqlListEntriesWhere($filter, $state, $order, $firstId, $date_min); + list($searchValues, $search) = $this->sqlListEntriesWhere('e.', $filter, $state, $order, $firstId, $date_min); return array(array_merge($values, $searchValues), 'SELECT e.id FROM `' . $this->prefix . 'entry` e ' diff --git a/app/Models/EntryDAOSQLite.php b/app/Models/EntryDAOSQLite.php index de02616d6..dad34a93d 100644 --- a/app/Models/EntryDAOSQLite.php +++ b/app/Models/EntryDAOSQLite.php @@ -133,7 +133,7 @@ class FreshRSS_EntryDAOSQLite extends FreshRSS_EntryDAO { } $values = array($idMax); - list($searchValues, $search) = $this->sqlListEntriesWhere($filter, $state); + list($searchValues, $search) = $this->sqlListEntriesWhere('', $filter, $state); $stm = $this->bd->prepare($sql . $search); if (!($stm && $stm->execute(array_merge($values, $searchValues)))) { @@ -169,9 +169,9 @@ class FreshRSS_EntryDAOSQLite extends FreshRSS_EntryDAO { . 'SET is_read=1 ' . 'WHERE is_read=0 AND id <= ? AND ' . 'id_feed IN (SELECT f.id FROM `' . $this->prefix . 'feed` f WHERE f.category=?)'; - $values = array($id, $idMax); + $values = array($idMax, $id); - list($searchValues, $search) = $this->sqlListEntriesWhere($filter, $state); + list($searchValues, $search) = $this->sqlListEntriesWhere('', $filter, $state); $stm = $this->bd->prepare($sql . $search); if (!($stm && $stm->execute(array_merge($values, $searchValues)))) { -- cgit v1.2.3