From 520676893fa9fc14dfe4e611a70b1ab305d5c222 Mon Sep 17 00:00:00 2001 From: Tibor Repček Date: Tue, 20 Aug 2019 21:20:57 +0200 Subject: [i18n] Slovak (slovenčina) - added new language (#2497) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/i18n/sk/sub.php | 100 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 100 insertions(+) create mode 100644 app/i18n/sk/sub.php (limited to 'app/i18n/sk/sub.php') diff --git a/app/i18n/sk/sub.php b/app/i18n/sk/sub.php new file mode 100644 index 000000000..4dcd09f57 --- /dev/null +++ b/app/i18n/sk/sub.php @@ -0,0 +1,100 @@ + array( + 'documentation' => 'Skopírujte tento odkaz a použite ho v inom programe.', + 'title' => 'API', + ), + 'bookmarklet' => array( + 'documentation' => 'Presunte toto tlačidlo do vašich záložiek, alebo kliknite pravým a zvoľte "Uložiť odkaz do záložiek". Potom kliknite na tlačidlo "Odoberať" na ktorejkoľvek stránke, ktorú chcete odoberať.', + 'label' => 'Odoberať', + 'title' => 'Záložka', + ), + 'category' => array( + '_' => 'Kategória', + 'add' => 'Pridať kategóriu', + 'empty' => 'Prázdna kategória', + 'information' => 'Informácia', + 'new' => 'Nová kategória', + 'title' => 'Názov', + ), + 'feed' => array( + 'add' => 'Pridať RSS kanál', + 'advanced' => 'Pokročilé', + 'archiving' => 'Archivovanie', + 'auth' => array( + 'configuration' => 'Prihlásenie', + 'help' => 'Povoliť prístup do kanálov chránených cez HTTP.', + 'http' => 'Prihlásenie cez HTTP', + 'password' => 'Heslo pre HTTP', + 'username' => 'Používateľské meno pre HTTP', + ), + 'clear_cache' => 'Vždy vymazať vyrovnávaciu pamäť', + 'css_help' => 'Stiahnuť skrátenú verziu RSS kanála (pozor, vyžaduje viac času!)', + 'css_path' => 'Pôvodný CSS súbor článku z webovej stránky', + 'description' => 'Popis', + 'empty' => 'Tento kanál je prázdny. Overte, prosím, či je ešte spravovaný autorom.', + 'error' => 'Vyskytol sa problém s týmto kanálom. Overte, prosím, či kanál stále existuje, potom ho obnovte.', + 'filteractions' => array( + '_' => 'Filtrovať akcie', + 'help' => 'Napíšte jeden výraz hľadania na riadok.', + ), + 'information' => 'Informácia', + 'keep_history' => 'Minimálny počet článkov na uchovanie', + 'moved_category_deleted' => 'Keď vymažete kategóriu, jej kanály sa automaticky zaradia pod %s.', + 'mute' => 'stíšiť', + 'no_selected' => 'Nevybrali ste kanál.', + 'number_entries' => 'Počet článkov: %d', + 'priority' => array( + '_' => 'Viditeľnosť', + 'archived' => 'Nezobrazovať (archivované)', + 'main_stream' => 'Zobraziť v prehľade kanálov', + 'normal' => 'Zobraziť vo svojej kategórii', + ), + 'websub' => 'Okamžité oznámenia cez WebSub', + 'show' => array( + 'all' => 'Zobraziť všetky kanály', + 'error' => 'Zobraziť iba kanály s chybou', + ), + 'showing' => array( + 'error' => 'Zobraziť iba kanály s chybou', + ), + 'ssl_verify' => 'Overiť bezpečnosť SSL', + 'stats' => 'Štatistiky', + 'think_to_add' => 'Mali by ste pridať kanály.', + 'timeout' => 'Doba platnosti dá v sekundách', + 'title' => 'Nadpis', + 'title_add' => 'Pridať kanál RSS', + 'ttl' => 'Automaticky neaktualizovať častejšie ako', + 'url' => 'Odkaz kanála', + 'validator' => 'Skontrolovať platnosť kanála', + 'website' => 'Odkaz webovej stránky', + ), + 'firefox' => array( + 'documentation' => 'Pridajte RSS kanály do Firefoxu pomocou tohto návodu.', + 'title' => 'RSS čítačka vo Firefoxe', + ), + 'import_export' => array( + 'export' => 'Exportovať', + 'export_opml' => 'Exportovať zoznam kanálov (OPML)', + 'export_starred' => 'Exportovať vaše obľúbené', + 'export_labelled' => 'Exportovať vaše označené články', + 'feed_list' => 'Zoznam článkov %s', + 'file_to_import' => 'Súbor na import
(OPML, JSON alebo ZIP)', + 'file_to_import_no_zip' => 'Súbor na import
(OPML alebo JSON)', + 'import' => 'Importovať', + 'starred_list' => 'Zoznam obľúbených článkov', + 'title' => 'Import / export', + ), + 'menu' => array( + 'bookmark' => 'Odoberať (záložka FreshRSS)', + 'import_export' => 'Import / export', + 'subscription_management' => 'Správa odoberaných kanálov', + 'subscription_tools' => 'Nástroje na odoberanie kanálov', + ), + 'title' => array( + '_' => 'Správa odoberaných kanálov', + 'feed_management' => 'Správa RSS kanálov', + 'subscription_tools' => 'Nástroje na odoberanie kanálov', + ), +); -- cgit v1.2.3 From cc0db9af4f980829faa4bf0960617807b32fb4fa Mon Sep 17 00:00:00 2001 From: Alexis Degrugillier Date: Wed, 23 Oct 2019 00:52:15 +0200 Subject: Feature/new archiving (#2335) * Change archiving config page layout I've changed some wording and moved actions into a maintenance section. * Update purge action Now we have more control on the purge action. The configuration allows us to choose what to keep and what to discard in a more precise way. At the moment, the configuration applies for all feeds. * Add purge configuration on feed level Now the extend purge configuration is available on feed level. It is stored as attributes and will be used in the purge action. * Update purge action Now the purge action uses the feed configuration if it exists and defaults on user configuration if not. * Add empty option in period list * Fix configuration warnings * Add archiving configuration on categories See #2369 * Add user info back * Add explanations in UI * Fixes for SQLite + error + misc. * Fix invalid feed reference * Short array syntax Only for new code, so far * Fix prefix error * Query performance, default values Work in progress * Fix default values and confirm before leaving Form cancel and confirm changes before leaving were broken. And start taking advantage of the short echo syntax `` as we have moved to PHP 5.4+ * More work * Tuning SQL * Fix MariaDB + performance issue * SQL performance * Fix SQLite bug * Fix some attributes JSON encoding bugs Especially for SQLite export/import * More uniform, fix bugs More uniform between global, category, feed settings * Drop special cases for old articles during refresh Instead will use lastSeen date with the new archiving logic. This was generating problems anyway https://github.com/FreshRSS/FreshRSS/issues/2154 * Draft drop index keep_history Not needed anymore * MySQL typo Now properly tested with MySQL, PostgreSQL, SQLite * More work for legacy values Important to avoid overriding user's preference and risking deleting data erroneously * Fix PHP 7.3 / 7.4 warnings @aledeg "Trying to use values of type null, bool, int, float or resource as an array (such as $null["key"]) will now generate a notice. " https://php.net/migration74.incompatible * Reintroduce min articles and take care of legacy parameters * A few changes forgotten * Draft of migration + DROP of feed.keep_history * Fix several errors And give up using const for SQL to allow multiple database types (and we cannot redefine a const) * Add keep_min to categories + factorise archiving logic * Legacy fix * Fix bug yield from * Minor: Use JSON_UNESCAPED_SLASHE for attributes And make more uniform * Fix sign and missing variable * Fine tune the logic --- app/Controllers/configureController.php | 43 +++++++++- app/Controllers/entryController.php | 20 +---- app/Controllers/feedController.php | 24 +----- app/Controllers/subscriptionController.php | 58 +++++++++++++- app/Models/Category.php | 24 ++++++ app/Models/CategoryDAO.php | 122 ++++++++++++++++++++++++++--- app/Models/CategoryDAOSQLite.php | 17 ++++ app/Models/ConfigurationSetter.php | 10 --- app/Models/Context.php | 19 +++++ app/Models/DatabaseDAO.php | 12 +-- app/Models/DatabaseDAOSQLite.php | 2 +- app/Models/EntryDAO.php | 65 ++++++++++----- app/Models/Factory.php | 8 +- app/Models/Feed.php | 38 ++++++--- app/Models/FeedDAO.php | 20 ++--- app/Models/FeedDAOSQLite.php | 2 +- app/Models/Tag.php | 2 +- app/Models/TagDAO.php | 14 +++- app/Models/UserDAO.php | 11 ++- app/SQL/install.sql.mysql.php | 21 +++-- app/SQL/install.sql.pgsql.php | 19 +++-- app/SQL/install.sql.sqlite.php | 17 ++-- app/i18n/cz/conf.php | 12 ++- app/i18n/cz/gen.php | 7 ++ app/i18n/cz/sub.php | 3 +- app/i18n/de/conf.php | 12 ++- app/i18n/de/gen.php | 7 ++ app/i18n/de/sub.php | 3 +- app/i18n/en/conf.php | 12 ++- app/i18n/en/gen.php | 7 ++ app/i18n/en/sub.php | 3 +- app/i18n/es/conf.php | 12 ++- app/i18n/es/gen.php | 7 ++ app/i18n/es/sub.php | 3 +- app/i18n/fr/conf.php | 12 ++- app/i18n/fr/gen.php | 7 ++ app/i18n/fr/sub.php | 3 +- app/i18n/he/conf.php | 12 ++- app/i18n/he/gen.php | 7 ++ app/i18n/he/sub.php | 3 +- app/i18n/it/conf.php | 12 ++- app/i18n/it/gen.php | 7 ++ app/i18n/it/sub.php | 3 +- app/i18n/kr/conf.php | 12 ++- app/i18n/kr/gen.php | 7 ++ app/i18n/kr/sub.php | 3 +- app/i18n/nl/conf.php | 16 +++- app/i18n/nl/gen.php | 7 ++ app/i18n/nl/sub.php | 3 +- app/i18n/oc/conf.php | 11 ++- app/i18n/oc/gen.php | 7 ++ app/i18n/oc/sub.php | 3 +- app/i18n/pt-br/conf.php | 12 ++- app/i18n/pt-br/gen.php | 7 ++ app/i18n/pt-br/sub.php | 3 +- app/i18n/ru/conf.php | 14 +++- app/i18n/ru/gen.php | 7 ++ app/i18n/ru/sub.php | 3 +- app/i18n/sk/conf.php | 2 +- app/i18n/sk/sub.php | 2 +- app/i18n/tr/conf.php | 12 ++- app/i18n/tr/gen.php | 7 ++ app/i18n/tr/sub.php | 3 +- app/i18n/zh-cn/conf.php | 12 ++- app/i18n/zh-cn/gen.php | 7 ++ app/i18n/zh-cn/sub.php | 3 +- app/install.php | 20 +---- app/views/configure/archiving.phtml | 110 ++++++++++++++++++++------ app/views/helpers/category/update.phtml | 116 +++++++++++++++++++++++++++ app/views/helpers/feed/update.phtml | 113 ++++++++++++++++++++++++-- cli/_update-or-create-user.php | 4 +- config-user.default.php | 10 ++- lib/Minz/Request.php | 6 ++ lib/lib_rss.php | 6 +- p/scripts/category.js | 23 ++++++ p/scripts/extra.js | 38 ++++++--- p/themes/base-theme/template.css | 3 + phpcs.xml | 5 -- 78 files changed, 1062 insertions(+), 277 deletions(-) create mode 100644 app/Models/CategoryDAOSQLite.php (limited to 'app/i18n/sk/sub.php') diff --git a/app/Controllers/configureController.php b/app/Controllers/configureController.php index 85ca9da39..b38d3289a 100755 --- a/app/Controllers/configureController.php +++ b/app/Controllers/configureController.php @@ -196,9 +196,31 @@ class FreshRSS_configure_Controller extends Minz_ActionController { */ public function archivingAction() { if (Minz_Request::isPost()) { - FreshRSS_Context::$user_conf->old_entries = Minz_Request::param('old_entries', 3); - FreshRSS_Context::$user_conf->keep_history_default = Minz_Request::param('keep_history_default', 0); + if (!Minz_Request::paramBoolean('enable_keep_max')) { + $keepMax = false; + } elseif (!$keepMax = Minz_Request::param('keep_max')) { + $keepMax = FreshRSS_Feed::ARCHIVING_RETENTION_COUNT_LIMIT; + } + if ($enableRetentionPeriod = Minz_Request::paramBoolean('enable_keep_period')) { + $keepPeriod = FreshRSS_Feed::ARCHIVING_RETENTION_PERIOD; + if (is_numeric(Minz_Request::param('keep_period_count')) && preg_match('/^PT?1[YMWDH]$/', Minz_Request::param('keep_period_unit'))) { + $keepPeriod = str_replace('1', Minz_Request::param('keep_period_count'), Minz_Request::param('keep_period_unit')); + } + } else { + $keepPeriod = false; + } + FreshRSS_Context::$user_conf->ttl_default = Minz_Request::param('ttl_default', FreshRSS_Feed::TTL_DEFAULT); + FreshRSS_Context::$user_conf->archiving = [ + 'keep_period' => $keepPeriod, + 'keep_max' => $keepMax, + 'keep_min' => Minz_Request::param('keep_min_default', 0), + 'keep_favourites' => Minz_Request::paramBoolean('keep_favourites'), + 'keep_labels' => Minz_Request::paramBoolean('keep_labels'), + 'keep_unreads' => Minz_Request::paramBoolean('keep_unreads'), + ]; + FreshRSS_Context::$user_conf->keep_history_default = null; //Legacy < FreshRSS 1.15 + FreshRSS_Context::$user_conf->old_entries = null; //Legacy < FreshRSS 1.15 FreshRSS_Context::$user_conf->save(); invalidateHttpCache(); @@ -206,7 +228,20 @@ class FreshRSS_configure_Controller extends Minz_ActionController { array('c' => 'configure', 'a' => 'archiving')); } - Minz_View::prependTitle(_t('conf.archiving.title') . ' · '); + $volatile = [ + 'enable_keep_period' => false, + 'keep_period_count' => '3', + 'keep_period_unit' => 'P1M', + ]; + $keepPeriod = FreshRSS_Context::$user_conf->archiving['keep_period']; + if (preg_match('/^PT?(?P\d+)[YMWDH]$/', $keepPeriod, $matches)) { + $volatile = [ + 'enable_keep_period' => true, + 'keep_period_count' => $matches['count'], + 'keep_period_unit' => str_replace($matches['count'], 1, $keepPeriod), + ]; + } + FreshRSS_Context::$user_conf->volatile = $volatile; $entryDAO = FreshRSS_Factory::createEntryDao(); $this->view->nb_total = $entryDAO->count(); @@ -217,6 +252,8 @@ class FreshRSS_configure_Controller extends Minz_ActionController { if (FreshRSS_Auth::hasAccess('admin')) { $this->view->size_total = $databaseDAO->size(true); } + + Minz_View::prependTitle(_t('conf.archiving.title') . ' · '); } /** diff --git a/app/Controllers/entryController.php b/app/Controllers/entryController.php index 0215128f4..7881cb3ec 100755 --- a/app/Controllers/entryController.php +++ b/app/Controllers/entryController.php @@ -181,32 +181,20 @@ class FreshRSS_entry_Controller extends Minz_ActionController { public function purgeAction() { @set_time_limit(300); - $nb_month_old = max(FreshRSS_Context::$user_conf->old_entries, 1); - $date_min = time() - (3600 * 24 * 30 * $nb_month_old); - - $entryDAO = FreshRSS_Factory::createEntryDao(); $feedDAO = FreshRSS_Factory::createFeedDao(); $feeds = $feedDAO->listFeeds(); $nb_total = 0; invalidateHttpCache(); - foreach ($feeds as $feed) { - $feed_history = $feed->keepHistory(); - if (FreshRSS_Feed::KEEP_HISTORY_DEFAULT === $feed_history) { - $feed_history = FreshRSS_Context::$user_conf->keep_history_default; - } + $feedDAO->beginTransaction(); - if ($feed_history >= 0) { - $nb = $entryDAO->cleanOldEntries($feed->id(), $date_min, $feed_history); - if ($nb > 0) { - $nb_total += $nb; - Minz_Log::debug($nb . ' old entries cleaned in feed [' . $feed->url(false) . ']'); - } - } + foreach ($feeds as $feed) { + $nb_total += $feed->cleanOldEntries(); } $feedDAO->updateCachedValues(); + $feedDAO->commit(); $databaseDAO = FreshRSS_Factory::createDatabaseDAO(); $databaseDAO->minorDbMaintenance(); diff --git a/app/Controllers/feedController.php b/app/Controllers/feedController.php index ea07d96e4..aabeb80ff 100755 --- a/app/Controllers/feedController.php +++ b/app/Controllers/feedController.php @@ -267,10 +267,6 @@ class FreshRSS_feed_Controller extends Minz_ActionController { $maxFeeds = 10; } - // Calculate date of oldest entries we accept in DB. - $nb_month_old = max(FreshRSS_Context::$user_conf->old_entries, 1); - $date_min = time() - (3600 * 24 * 30 * $nb_month_old); - // WebSub (PubSubHubbub) support $pubsubhubbubEnabledGeneral = FreshRSS_Context::$system_conf->pubsubhubbub_enabled; $pshbMinAge = time() - (3600 * 24); //TODO: Make a configuration. @@ -323,12 +319,6 @@ class FreshRSS_feed_Controller extends Minz_ActionController { continue; } - $feed_history = $feed->keepHistory(); - if ($isNewFeed) { - $feed_history = FreshRSS_Feed::KEEP_HISTORY_INFINITE; - } elseif (FreshRSS_Feed::KEEP_HISTORY_DEFAULT === $feed_history) { - $feed_history = FreshRSS_Context::$user_conf->keep_history_default; - } $needFeedCacheRefresh = false; // We want chronological order and SimplePie uses reverse order. @@ -376,15 +366,9 @@ class FreshRSS_feed_Controller extends Minz_ActionController { } $entryDAO->updateEntry($entry->toArray()); } - } elseif ($feed_history == 0 && $entry_date < $date_min) { - // This entry should not be added considering configuration and date. - $oldGuids[] = $entry->guid(); } else { $id = uTimeString(); $entry->_id($id); - if ($entry_date < $date_min) { - $entry->_isRead(true); //Old article that was not in database. Probably an error, so mark as read - } $entry->applyFilterActions(); @@ -413,17 +397,13 @@ class FreshRSS_feed_Controller extends Minz_ActionController { $entryDAO->updateLastSeen($feed->id(), $oldGuids, $mtime); } - if ($feed_history >= 0 && mt_rand(0, 30) === 1) { - // TODO: move this function in web cron when available (see entry::purge) - // Remove old entries once in 30. + if (mt_rand(0, 30) === 1) { // Remove old entries once in 30. if (!$entryDAO->inTransaction()) { $entryDAO->beginTransaction(); } - - $nb = $entryDAO->cleanOldEntries($feed->id(), $date_min, max($feed_history, count($entries) + 10)); + $nb = $feed->cleanOldEntries(); if ($nb > 0) { $needFeedCacheRefresh = true; - Minz_Log::debug($nb . ' old entries cleaned in feed [' . $feed->url(false) . ']'); } } diff --git a/app/Controllers/subscriptionController.php b/app/Controllers/subscriptionController.php index f6d5e9457..f9497f0be 100644 --- a/app/Controllers/subscriptionController.php +++ b/app/Controllers/subscriptionController.php @@ -121,6 +121,32 @@ class FreshRSS_subscription_Controller extends Minz_ActionController { $feed->_attributes('timeout', null); } + if (Minz_Request::paramBoolean('use_default_purge_options')) { + $feed->_attributes('archiving', null); + } else { + if (!Minz_Request::paramBoolean('enable_keep_max')) { + $keepMax = false; + } elseif (!$keepMax = Minz_Request::param('keep_max')) { + $keepMax = FreshRSS_Feed::ARCHIVING_RETENTION_COUNT_LIMIT; + } + if ($enableRetentionPeriod = Minz_Request::paramBoolean('enable_keep_period')) { + $keepPeriod = FreshRSS_Feed::ARCHIVING_RETENTION_PERIOD; + if (is_numeric(Minz_Request::param('keep_period_count')) && preg_match('/^PT?1[YMWDH]$/', Minz_Request::param('keep_period_unit'))) { + $keepPeriod = str_replace(1, Minz_Request::param('keep_period_count'), Minz_Request::param('keep_period_unit')); + } + } else { + $keepPeriod = false; + } + $feed->_attributes('archiving', [ + 'keep_period' => $keepPeriod, + 'keep_max' => $keepMax, + 'keep_min' => intval(Minz_Request::param('keep_min', 0)), + 'keep_favourites' => Minz_Request::paramBoolean('keep_favourites'), + 'keep_labels' => Minz_Request::paramBoolean('keep_labels'), + 'keep_unreads' => Minz_Request::paramBoolean('keep_unreads'), + ]); + } + $feed->_filtersAction('read', preg_split('/[\n\r]+/', Minz_Request::param('filteractions_read', ''))); $values = array( @@ -132,7 +158,6 @@ class FreshRSS_subscription_Controller extends Minz_ActionController { 'pathEntries' => Minz_Request::param('path_entries', ''), 'priority' => intval(Minz_Request::param('priority', FreshRSS_Feed::PRIORITY_MAIN_STREAM)), 'httpAuth' => $httpAuth, - 'keep_history' => intval(Minz_Request::param('keep_history', FreshRSS_Feed::KEEP_HISTORY_DEFAULT)), 'ttl' => $ttl * ($mute ? -1 : 1), 'attributes' => $feed->attributes(), ); @@ -165,9 +190,36 @@ class FreshRSS_subscription_Controller extends Minz_ActionController { $this->view->category = $category; if (Minz_Request::isPost()) { - $values = array( + if (Minz_Request::paramBoolean('use_default_purge_options')) { + $category->_attributes('archiving', null); + } else { + if (!Minz_Request::paramBoolean('enable_keep_max')) { + $keepMax = false; + } elseif (!$keepMax = Minz_Request::param('keep_max')) { + $keepMax = FreshRSS_Feed::ARCHIVING_RETENTION_COUNT_LIMIT; + } + if ($enableRetentionPeriod = Minz_Request::paramBoolean('enable_keep_period')) { + $keepPeriod = FreshRSS_Feed::ARCHIVING_RETENTION_PERIOD; + if (is_numeric(Minz_Request::param('keep_period_count')) && preg_match('/^PT?1[YMWDH]$/', Minz_Request::param('keep_period_unit'))) { + $keepPeriod = str_replace(1, Minz_Request::param('keep_period_count'), Minz_Request::param('keep_period_unit')); + } + } else { + $keepPeriod = false; + } + $category->_attributes('archiving', [ + 'keep_period' => $keepPeriod, + 'keep_max' => $keepMax, + 'keep_min' => intval(Minz_Request::param('keep_min', 0)), + 'keep_favourites' => Minz_Request::paramBoolean('keep_favourites'), + 'keep_labels' => Minz_Request::paramBoolean('keep_labels'), + 'keep_unreads' => Minz_Request::paramBoolean('keep_unreads'), + ]); + } + + $values = [ 'name' => Minz_Request::param('name', ''), - ); + 'attributes' => $category->attributes(), + ]; invalidateHttpCache(); diff --git a/app/Models/Category.php b/app/Models/Category.php index 29c0e586b..a0ee1ddaa 100644 --- a/app/Models/Category.php +++ b/app/Models/Category.php @@ -8,6 +8,7 @@ class FreshRSS_Category extends Minz_Model { private $feeds = null; private $hasFeedsWithError = false; private $isDefault = false; + private $attributes = []; public function __construct($name = '', $feeds = null) { $this->_name($name); @@ -68,6 +69,14 @@ class FreshRSS_Category extends Minz_Model { return $this->hasFeedsWithError; } + public function attributes($key = '') { + if ($key == '') { + return $this->attributes; + } else { + return isset($this->attributes[$key]) ? $this->attributes[$key] : null; + } + } + public function _id($id) { $this->id = $id; if ($id == FreshRSS_CategoryDAO::DEFAULTCATEGORYID) { @@ -87,4 +96,19 @@ class FreshRSS_Category extends Minz_Model { $this->feeds = $values; } + + public function _attributes($key, $value) { + if ($key == '') { + if (is_string($value)) { + $value = json_decode($value, true); + } + if (is_array($value)) { + $this->attributes = $value; + } + } elseif ($value === null) { + unset($this->attributes[$key]); + } else { + $this->attributes[$key] = $value; + } + } } diff --git a/app/Models/CategoryDAO.php b/app/Models/CategoryDAO.php index dd49b542d..1b8717e83 100644 --- a/app/Models/CategoryDAO.php +++ b/app/Models/CategoryDAO.php @@ -4,15 +4,81 @@ class FreshRSS_CategoryDAO extends Minz_ModelPdo implements FreshRSS_Searchable const DEFAULTCATEGORYID = 1; + protected function addColumn($name) { + Minz_Log::warning(__method__ . ': ' . $name); + try { + if ('attributes' === $name) { //v1.15.0 + $ok = $this->pdo->exec('ALTER TABLE `_category` ADD COLUMN attributes TEXT') !== false; + + $stm = $this->pdo->query('SELECT * FROM `_feed`'); + $feeds = $stm->fetchAll(PDO::FETCH_ASSOC); + + $stm = $this->pdo->prepare('UPDATE `_feed` SET attributes = :attributes WHERE id = :id'); + foreach ($feeds as $feed) { + if (empty($feed['keep_history']) || empty($feed['id'])) { + continue; + } + $keepHistory = $feed['keep_history']; + $attributes = empty($feed['attributes']) ? [] : json_decode($feed['attributes'], true); + if (is_string($attributes)) { //Legacy risk of double-encoding + $attributes = json_decode($attributes, true); + } + if (!is_array($attributes)) { + $attributes = []; + } + if ($keepHistory > 0) { + $attributes['archiving']['keep_min'] = intval($keepHistory); + } elseif ($keepHistory == -1) { //Infinite + $attributes['archiving']['keep_period'] = false; + $attributes['archiving']['keep_max'] = false; + $attributes['archiving']['keep_min'] = false; + } else { + continue; + } + $stm->bindValue(':id', $feed['id'], PDO::PARAM_INT); + $stm->bindValue(':attributes', json_encode($attributes, JSON_UNESCAPED_SLASHES)); + $stm->execute(); + } + + if ($this->pdo->dbType() !== 'sqlite') { //SQLite does not support DROP COLUMN + $this->pdo->exec('ALTER TABLE `_feed` DROP COLUMN keep_history'); + } else { + $this->pdo->exec('DROP INDEX IF EXISTS feed_keep_history_index'); //SQLite at least drop index + } + return $ok; + } + } catch (Exception $e) { + Minz_Log::error(__method__ . ': ' . $e->getMessage()); + } + return false; + } + + protected function autoUpdateDb($errorInfo) { + if (isset($errorInfo[0])) { + if ($errorInfo[0] === FreshRSS_DatabaseDAO::ER_BAD_FIELD_ERROR || $errorInfo[0] === FreshRSS_DatabaseDAOPGSQL::UNDEFINED_COLUMN) { + foreach (['attributes'] as $column) { + if (stripos($errorInfo[2], $column) !== false) { + return $this->addColumn($column); + } + } + } + } + return false; + } + public function addCategory($valuesTmp) { - $sql = 'INSERT INTO `_category`(name) ' - . 'SELECT * FROM (SELECT TRIM(?)) c2 ' //TRIM() to provide a type hint as text for PostgreSQL + $sql = 'INSERT INTO `_category`(name, attributes) ' + . 'SELECT * FROM (SELECT TRIM(?), ?) c2 ' //TRIM() to provide a type hint as text for PostgreSQL . 'WHERE NOT EXISTS (SELECT 1 FROM `_tag` WHERE name = TRIM(?))'; //No tag of the same name $stm = $this->pdo->prepare($sql); $valuesTmp['name'] = mb_strcut(trim($valuesTmp['name']), 0, FreshRSS_DatabaseDAO::LENGTH_INDEX_UNICODE, 'UTF-8'); + if (!isset($valuesTmp['attributes'])) { + $valuesTmp['attributes'] = []; + } $values = array( $valuesTmp['name'], + is_string($valuesTmp['attributes']) ? $valuesTmp['attributes'] : json_encode($valuesTmp['attributes'], JSON_UNESCAPED_SLASHES), $valuesTmp['name'], ); @@ -20,7 +86,10 @@ class FreshRSS_CategoryDAO extends Minz_ModelPdo implements FreshRSS_Searchable return $this->pdo->lastInsertId('`_category_id_seq`'); } else { $info = $stm == null ? $this->pdo->errorInfo() : $stm->errorInfo(); - Minz_Log::error('SQL error addCategory: ' . $info[2]); + if ($this->autoUpdateDb($info)) { + return $this->addCategory($valuesTmp); + } + Minz_Log::error('SQL error addCategory: ' . json_encode($info)); return false; } } @@ -39,13 +108,17 @@ class FreshRSS_CategoryDAO extends Minz_ModelPdo implements FreshRSS_Searchable } public function updateCategory($id, $valuesTmp) { - $sql = 'UPDATE `_category` SET name=? WHERE id=? ' + $sql = 'UPDATE `_category` SET name=?, attributes=? WHERE id=? ' . 'AND NOT EXISTS (SELECT 1 FROM `_tag` WHERE name = ?)'; //No tag of the same name $stm = $this->pdo->prepare($sql); $valuesTmp['name'] = mb_strcut(trim($valuesTmp['name']), 0, FreshRSS_DatabaseDAO::LENGTH_INDEX_UNICODE, 'UTF-8'); + if (!isset($valuesTmp['attributes'])) { + $valuesTmp['attributes'] = []; + } $values = array( $valuesTmp['name'], + is_string($valuesTmp['attributes']) ? $valuesTmp['attributes'] : json_encode($valuesTmp['attributes'], JSON_UNESCAPED_SLASHES), $id, $valuesTmp['name'], ); @@ -54,7 +127,10 @@ class FreshRSS_CategoryDAO extends Minz_ModelPdo implements FreshRSS_Searchable return $stm->rowCount(); } else { $info = $stm == null ? $this->pdo->errorInfo() : $stm->errorInfo(); - Minz_Log::error('SQL error updateCategory: ' . $info[2]); + if ($this->autoUpdateDb($info)) { + return $this->updateCategory($valuesTmp); + } + Minz_Log::error('SQL error updateCategory: ' . json_encode($info)); return false; } } @@ -70,16 +146,27 @@ class FreshRSS_CategoryDAO extends Minz_ModelPdo implements FreshRSS_Searchable return $stm->rowCount(); } else { $info = $stm == null ? $this->pdo->errorInfo() : $stm->errorInfo(); - Minz_Log::error('SQL error deleteCategory: ' . $info[2]); + Minz_Log::error('SQL error deleteCategory: ' . json_encode($info)); return false; } } public function selectAll() { - $sql = 'SELECT id, name FROM `_category`'; + $sql = 'SELECT id, name, attributes FROM `_category`'; $stm = $this->pdo->query($sql); - while ($row = $stm->fetch(PDO::FETCH_ASSOC)) { - yield $row; + if ($stm != false) { + while ($row = $stm->fetch(PDO::FETCH_ASSOC)) { + yield $row; + } + } else { + $info = $this->pdo->errorInfo(); + if ($this->autoUpdateDb($info)) { + foreach ($this->selectAll() as $category) { // `yield from` requires PHP 7+ + yield $category; + } + } + Minz_Log::error(__method__ . ' error: ' . json_encode($info)); + return false; } } @@ -116,7 +203,7 @@ class FreshRSS_CategoryDAO extends Minz_ModelPdo implements FreshRSS_Searchable public function listCategories($prePopulateFeeds = true, $details = false) { if ($prePopulateFeeds) { - $sql = 'SELECT c.id AS c_id, c.name AS c_name, ' + $sql = 'SELECT c.id AS c_id, c.name AS c_name, c.attributes AS c_attributes, ' . ($details ? 'f.* ' : 'f.id, f.name, f.url, f.website, f.priority, f.error, f.`cache_nbEntries`, f.`cache_nbUnreads`, f.ttl ') . 'FROM `_category` c ' . 'LEFT OUTER JOIN `_feed` f ON f.category=c.id ' @@ -124,9 +211,17 @@ class FreshRSS_CategoryDAO extends Minz_ModelPdo implements FreshRSS_Searchable . 'GROUP BY f.id, c_id ' . 'ORDER BY c.name, f.name'; $stm = $this->pdo->prepare($sql); - $stm->bindValue(':priority_normal', FreshRSS_Feed::PRIORITY_NORMAL, PDO::PARAM_INT); - $stm->execute(); - return self::daoToCategoryPrepopulated($stm->fetchAll(PDO::FETCH_ASSOC)); + $values = [ ':priority_normal' => FreshRSS_Feed::PRIORITY_NORMAL ]; + if ($stm && $stm->execute($values)) { + return self::daoToCategoryPrepopulated($stm->fetchAll(PDO::FETCH_ASSOC)); + } else { + $info = $stm == null ? $this->pdo->errorInfo() : $stm->errorInfo(); + if ($this->autoUpdateDb($info)) { + return $this->listCategories($prePopulateFeeds, $details); + } + Minz_Log::error('SQL error listCategories: ' . json_encode($info)); + return false; + } } else { $sql = 'SELECT * FROM `_category` ORDER BY name'; $stm = $this->pdo->query($sql); @@ -282,6 +377,7 @@ class FreshRSS_CategoryDAO extends Minz_ModelPdo implements FreshRSS_Searchable $dao['name'] ); $cat->_id($dao['id']); + $cat->_attributes('', isset($dao['attributes']) ? $dao['attributes'] : ''); $cat->_isDefault(static::DEFAULTCATEGORYID === intval($dao['id'])); $list[$key] = $cat; } diff --git a/app/Models/CategoryDAOSQLite.php b/app/Models/CategoryDAOSQLite.php new file mode 100644 index 000000000..e32545c90 --- /dev/null +++ b/app/Models/CategoryDAOSQLite.php @@ -0,0 +1,17 @@ +pdo->query("PRAGMA table_info('category')")) { + $columns = $tableInfo->fetchAll(PDO::FETCH_COLUMN, 1); + foreach (['attributes'] as $column) { + if (!in_array($column, $columns)) { + return $this->addColumn($column); + } + } + } + return false; + } + +} diff --git a/app/Models/ConfigurationSetter.php b/app/Models/ConfigurationSetter.php index 963d37e2b..b1d271f41 100644 --- a/app/Models/ConfigurationSetter.php +++ b/app/Models/ConfigurationSetter.php @@ -79,11 +79,6 @@ class FreshRSS_ConfigurationSetter { $data['html5_notif_timeout'] = $value >= 0 ? $value : 0; } - private function _keep_history_default(&$data, $value) { - $value = intval($value); - $data['keep_history_default'] = $value >= FreshRSS_Feed::KEEP_HISTORY_INFINITE ? $value : 0; - } - // It works for system config too! private function _language(&$data, $value) { $value = strtolower($value); @@ -94,11 +89,6 @@ class FreshRSS_ConfigurationSetter { $data['language'] = $value; } - private function _old_entries(&$data, $value) { - $value = intval($value); - $data['old_entries'] = $value > 0 ? $value : 3; - } - private function _passwordHash(&$data, $value) { $data['passwordHash'] = ctype_graph($value) && (strlen($value) >= 60) ? $value : ''; } diff --git a/app/Models/Context.php b/app/Models/Context.php index 95dc47c8c..878b72c69 100644 --- a/app/Models/Context.php +++ b/app/Models/Context.php @@ -51,6 +51,25 @@ class FreshRSS_Context { // Init configuration. self::$system_conf = Minz_Configuration::get('system'); self::$user_conf = Minz_Configuration::get('user'); + + //Legacy + $oldEntries = (int)FreshRSS_Context::$user_conf->param('old_entries', 0); + if ($oldEntries > 0) { //Freshrss < 1.15 + $archiving['keep_period'] = 'P' . $oldEntries . 'M'; + } + + $keepMin = (int)FreshRSS_Context::$user_conf->param('keep_history_default', -5); + if ($keepMin != 0 && $keepMin > -5) { //Freshrss < 1.15 + $archiving = FreshRSS_Context::$user_conf->archiving; + if ($keepMin > 0) { + $archiving['keep_min'] = $keepMin; + } elseif ($keepMin == -1) { //Infinite + $archiving['keep_period'] = false; + $archiving['keep_max'] = false; + $archiving['keep_min'] = false; + } + FreshRSS_Context::$user_conf->archiving = $archiving; + } } /** diff --git a/app/Models/DatabaseDAO.php b/app/Models/DatabaseDAO.php index f6cd2f756..a36b469b1 100644 --- a/app/Models/DatabaseDAO.php +++ b/app/Models/DatabaseDAO.php @@ -15,11 +15,11 @@ class FreshRSS_DatabaseDAO extends Minz_ModelPdo { const LENGTH_INDEX_UNICODE = 191; public function create() { - require_once(APP_PATH . '/SQL/install.sql.' . $this->pdo->dbType() . '.php'); + require(APP_PATH . '/SQL/install.sql.' . $this->pdo->dbType() . '.php'); $db = FreshRSS_Context::$system_conf->db; try { - $sql = sprintf(SQL_CREATE_DB, empty($db['base']) ? '' : $db['base']); + $sql = sprintf($SQL_CREATE_DB, empty($db['base']) ? '' : $db['base']); return $this->pdo->exec($sql) !== false; } catch (PDOException $e) { $_SESSION['bd_error'] = $e->getMessage(); @@ -86,7 +86,7 @@ class FreshRSS_DatabaseDAO extends Minz_ModelPdo { public function feedIsCorrect() { return $this->checkTable('feed', array( 'id', 'url', 'category', 'name', 'website', 'description', 'lastUpdate', - 'priority', 'pathEntries', 'httpAuth', 'error', 'keep_history', 'ttl', 'attributes', + 'priority', 'pathEntries', 'httpAuth', 'error', 'ttl', 'attributes', 'cache_nbEntries', 'cache_nbUnreads', )); } @@ -164,11 +164,11 @@ class FreshRSS_DatabaseDAO extends Minz_ModelPdo { public function ensureCaseInsensitiveGuids() { $ok = true; if ($this->pdo->dbType() === 'mysql') { - include_once(APP_PATH . '/SQL/install.sql.mysql.php'); + include(APP_PATH . '/SQL/install.sql.mysql.php'); $ok = false; try { - $ok = $this->pdo->exec(SQL_UPDATE_GUID_LATIN1_BIN) !== false; //FreshRSS 1.12 + $ok = $this->pdo->exec($SQL_UPDATE_GUID_LATIN1_BIN) !== false; //FreshRSS 1.12 } catch (Exception $e) { $ok = false; Minz_Log::error(__METHOD__ . ' error: ' . $e->getMessage()); @@ -243,7 +243,7 @@ class FreshRSS_DatabaseDAO extends Minz_ModelPdo { Minz_ModelPdo::clean(); $userDAOSQLite = new FreshRSS_UserDAO('', $sqlite); - $categoryDAOSQLite = new FreshRSS_CategoryDAO('', $sqlite); + $categoryDAOSQLite = new FreshRSS_CategoryDAOSQLite('', $sqlite); $feedDAOSQLite = new FreshRSS_FeedDAOSQLite('', $sqlite); $entryDAOSQLite = new FreshRSS_EntryDAOSQLite('', $sqlite); $tagDAOSQLite = new FreshRSS_TagDAOSQLite('', $sqlite); diff --git a/app/Models/DatabaseDAOSQLite.php b/app/Models/DatabaseDAOSQLite.php index b1473ab09..413e7ee09 100644 --- a/app/Models/DatabaseDAOSQLite.php +++ b/app/Models/DatabaseDAOSQLite.php @@ -66,6 +66,6 @@ class FreshRSS_DatabaseDAOSQLite extends FreshRSS_DatabaseDAO { } public function optimize() { - return $this->exec('VACUUM') !== false; + return $this->pdo->exec('VACUUM') !== false; } } diff --git a/app/Models/EntryDAO.php b/app/Models/EntryDAO.php index 5ff3a5b70..6a8a25b3e 100644 --- a/app/Models/EntryDAO.php +++ b/app/Models/EntryDAO.php @@ -26,9 +26,9 @@ class FreshRSS_EntryDAO extends Minz_ModelPdo implements FreshRSS_Searchable { $this->pdo->commit(); } try { - require_once(APP_PATH . '/SQL/install.sql.' . $this->pdo->dbType() . '.php'); + require(APP_PATH . '/SQL/install.sql.' . $this->pdo->dbType() . '.php'); Minz_Log::warning('SQL CREATE TABLE entrytmp...'); - $ok = $this->pdo->exec(SQL_CREATE_TABLE_ENTRYTMP . SQL_CREATE_INDEX_ENTRY_1) !== false; + $ok = $this->pdo->exec($SQL_CREATE_TABLE_ENTRYTMP . $SQL_CREATE_INDEX_ENTRY_1) !== false; } catch (Exception $ex) { Minz_Log::error(__method__ . ' error: ' . $ex->getMessage()); } @@ -544,32 +544,57 @@ SQL; return $affected; } - public function cleanOldEntries($id_feed, $date_min, $keep = 15) { //Remember to call updateCachedValue($id_feed) or updateCachedValues() just after - $sql = 'DELETE FROM `_entry` ' - . 'WHERE id_feed=:id_feed1 AND id<=:id_max ' - . 'AND is_favorite=0 ' //Do not remove favourites - . 'AND `lastSeen` < (SELECT maxLastSeen FROM (SELECT (MAX(e3.`lastSeen`)-99) AS maxLastSeen FROM `_entry` e3 WHERE e3.id_feed=:id_feed2) recent) ' //Do not remove the most newly seen articles, plus a few seconds of tolerance - . 'AND id NOT IN (SELECT id_entry FROM `_entrytag`) ' //Do not purge tagged entries - . 'AND id NOT IN (SELECT id FROM (SELECT e2.id FROM `_entry` e2 WHERE e2.id_feed=:id_feed3 ORDER BY id DESC LIMIT :keep) keep)'; //Double select: MySQL doesn't support 'LIMIT & IN/ALL/ANY/SOME subquery' - $stm = $this->pdo->prepare($sql); + public function cleanOldEntries($id_feed, $options = []) { //Remember to call updateCachedValue($id_feed) or updateCachedValues() just after + $sql = 'DELETE FROM `_entry` WHERE id_feed = :id_feed1'; //No alias for MySQL / MariaDB + $params = []; + $params[':id_feed1'] = $id_feed; - if ($stm) { - $id_max = intval($date_min) . '000000'; - $stm->bindParam(':id_max', $id_max, PDO::PARAM_STR); - $stm->bindParam(':id_feed1', $id_feed, PDO::PARAM_INT); - $stm->bindParam(':id_feed2', $id_feed, PDO::PARAM_INT); - $stm->bindParam(':id_feed3', $id_feed, PDO::PARAM_INT); - $stm->bindParam(':keep', $keep, PDO::PARAM_INT); + //==Exclusions== + if (!empty($options['keep_favourites'])) { + $sql .= ' AND is_favorite = 0'; + } + if (!empty($options['keep_unreads'])) { + $sql .= ' AND is_read = 1'; + } + if (!empty($options['keep_labels'])) { + $sql .= ' AND NOT EXISTS (SELECT 1 FROM `_entrytag` WHERE id_entry = id)'; + } + if (!empty($options['keep_min']) && $options['keep_min'] > 0) { + $sql .= ' AND `lastSeen` < (SELECT e2.`lastSeen` FROM `_entry` e2 WHERE e2.id_feed = :id_feed2' + . ' ORDER BY e2.`lastSeen` DESC LIMIT 1 OFFSET :keep_min)'; + $params[':id_feed2'] = $id_feed; + $params[':keep_min'] = (int)$options['keep_min']; } + //Keep at least the articles seen at the last refresh + $sql .= ' AND `lastSeen` < (SELECT MAX(e3.`lastSeen`) FROM `_entry` e3 WHERE e3.id_feed = :id_feed3)'; + $params[':id_feed3'] = $id_feed; + + //==Inclusions== + $sql .= ' AND (1=0'; + if (!empty($options['keep_period'])) { + $sql .= ' OR `lastSeen` < :max_last_seen'; + $now = new DateTime('now'); + $now->sub(new DateInterval($options['keep_period'])); + $params[':max_last_seen'] = $now->format('U'); + } + if (!empty($options['keep_max']) && $options['keep_max'] > 0) { + $sql .= ' OR `lastSeen` <= (SELECT e4.`lastSeen` FROM `_entry` e4 WHERE e4.id_feed = :id_feed4' + . ' ORDER BY e4.`lastSeen` DESC LIMIT 1 OFFSET :keep_max)'; + $params[':id_feed4'] = $id_feed; + $params[':keep_max'] = (int)$options['keep_max']; + } + $sql .= ')'; + + $stm = $this->pdo->prepare($sql); - if ($stm && $stm->execute()) { + if ($stm && $stm->execute($params)) { return $stm->rowCount(); } else { $info = $stm == null ? $this->pdo->errorInfo() : $stm->errorInfo(); if ($this->autoUpdateDb($info)) { - return $this->cleanOldEntries($id_feed, $date_min, $keep); + return $this->cleanOldEntries($id_feed, $options); } - Minz_Log::error('SQL error cleanOldEntries: ' . $info[2]); + Minz_Log::error(__method__ . ' error:' . json_encode($info)); return false; } } diff --git a/app/Models/Factory.php b/app/Models/Factory.php index 6f2ca2217..69885c205 100644 --- a/app/Models/Factory.php +++ b/app/Models/Factory.php @@ -7,7 +7,13 @@ class FreshRSS_Factory { } public static function createCategoryDao($username = null) { - return new FreshRSS_CategoryDAO($username); + $conf = Minz_Configuration::get('system'); + switch ($conf->db['type']) { + case 'sqlite': + return new FreshRSS_CategoryDAOSQLite($username); + default: + return new FreshRSS_CategoryDAO($username); + } } public static function createFeedDao($username = null) { diff --git a/app/Models/Feed.php b/app/Models/Feed.php index 8aee9d62f..0a45a1f4c 100644 --- a/app/Models/Feed.php +++ b/app/Models/Feed.php @@ -7,8 +7,8 @@ class FreshRSS_Feed extends Minz_Model { const TTL_DEFAULT = 0; - const KEEP_HISTORY_DEFAULT = -2; - const KEEP_HISTORY_INFINITE = -1; + const ARCHIVING_RETENTION_COUNT_LIMIT = 10000; + const ARCHIVING_RETENTION_PERIOD = 'P3M'; private $id = 0; private $url; @@ -24,9 +24,8 @@ class FreshRSS_Feed extends Minz_Model { private $pathEntries = ''; private $httpAuth = ''; private $error = false; - private $keep_history = self::KEEP_HISTORY_DEFAULT; private $ttl = self::TTL_DEFAULT; - private $attributes = array(); + private $attributes = []; private $mute = false; private $hash = null; private $lockPath = ''; @@ -110,9 +109,6 @@ class FreshRSS_Feed extends Minz_Model { public function inError() { return $this->error; } - public function keepHistory() { - return $this->keep_history; - } public function ttl() { return $this->ttl; } @@ -230,12 +226,6 @@ class FreshRSS_Feed extends Minz_Model { public function _error($value) { $this->error = (bool)$value; } - public function _keepHistory($value) { - $value = intval($value); - $value = min($value, 1000000); - $value = max($value, self::KEEP_HISTORY_DEFAULT); - $this->keep_history = $value; - } public function _ttl($value) { $value = intval($value); $value = min($value, 100000000); @@ -469,6 +459,28 @@ class FreshRSS_Feed extends Minz_Model { $this->entries = $entries; } + public function cleanOldEntries() { //Remember to call updateCachedValue($id_feed) or updateCachedValues() just after + $archiving = $this->attributes('archiving'); + if ($archiving == null) { + $catDAO = FreshRSS_Factory::createCategoryDao(); + $category = $catDAO->searchById($this->category()); + $archiving = $category == null ? null : $category->attributes('archiving'); + if ($archiving == null) { + $archiving = FreshRSS_Context::$user_conf->archiving; + } + } + if (is_array($archiving)) { + $entryDAO = FreshRSS_Factory::createEntryDao(); + $nb = $entryDAO->cleanOldEntries($this->id(), $archiving); + if ($nb > 0) { + $needFeedCacheRefresh = true; + Minz_Log::debug($nb . ' entries cleaned in feed [' . $this->url(false) . '] with: ' . json_encode($archiving)); + } + return $nb; + } + return false; + } + protected function cacheFilename() { return CACHE_PATH . '/' . md5($this->url) . '.spc'; } diff --git a/app/Models/FeedDAO.php b/app/Models/FeedDAO.php index d4a91c145..fa0001df7 100644 --- a/app/Models/FeedDAO.php +++ b/app/Models/FeedDAO.php @@ -17,7 +17,7 @@ class FreshRSS_FeedDAO extends Minz_ModelPdo implements FreshRSS_Searchable { protected function autoUpdateDb($errorInfo) { if (isset($errorInfo[0])) { if ($errorInfo[0] === FreshRSS_DatabaseDAO::ER_BAD_FIELD_ERROR || $errorInfo[0] === FreshRSS_DatabaseDAOPGSQL::UNDEFINED_COLUMN) { - foreach (array('attributes') as $column) { + foreach (['attributes'] as $column) { if (stripos($errorInfo[2], $column) !== false) { return $this->addColumn($column); } @@ -41,12 +41,11 @@ class FreshRSS_FeedDAO extends Minz_ModelPdo implements FreshRSS_Searchable { `pathEntries`, `httpAuth`, error, - keep_history, ttl, attributes ) VALUES - (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)'; + (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)'; $stm = $this->pdo->prepare($sql); $valuesTmp['url'] = safe_ascii($valuesTmp['url']); @@ -54,6 +53,9 @@ class FreshRSS_FeedDAO extends Minz_ModelPdo implements FreshRSS_Searchable { if (!isset($valuesTmp['pathEntries'])) { $valuesTmp['pathEntries'] = ''; } + if (!isset($valuesTmp['attributes'])) { + $valuesTmp['attributes'] = []; + } $values = array( substr($valuesTmp['url'], 0, 511), @@ -66,9 +68,8 @@ class FreshRSS_FeedDAO extends Minz_ModelPdo implements FreshRSS_Searchable { mb_strcut($valuesTmp['pathEntries'], 0, 511, 'UTF-8'), base64_encode($valuesTmp['httpAuth']), isset($valuesTmp['error']) ? intval($valuesTmp['error']) : 0, - isset($valuesTmp['keep_history']) ? intval($valuesTmp['keep_history']) : FreshRSS_Feed::KEEP_HISTORY_DEFAULT, isset($valuesTmp['ttl']) ? intval($valuesTmp['ttl']) : FreshRSS_Feed::TTL_DEFAULT, - isset($valuesTmp['attributes']) ? json_encode($valuesTmp['attributes']) : '', + is_string($valuesTmp['attributes']) ? $valuesTmp['attributes'] : json_encode($valuesTmp['attributes'], JSON_UNESCAPED_SLASHES), ); if ($stm && $stm->execute($values)) { @@ -135,7 +136,7 @@ class FreshRSS_FeedDAO extends Minz_ModelPdo implements FreshRSS_Searchable { if ($key === 'httpAuth') { $valuesTmp[$key] = base64_encode($v); } elseif ($key === 'attributes') { - $valuesTmp[$key] = json_encode($v); + $valuesTmp[$key] = is_string($valuesTmp[$key]) ? $valuesTmp[$key] : json_encode($valuesTmp[$key], JSON_UNESCAPED_SLASHES); } } $set = substr($set, 0, -2); @@ -246,7 +247,7 @@ class FreshRSS_FeedDAO extends Minz_ModelPdo implements FreshRSS_Searchable { public function selectAll() { $sql = 'SELECT id, url, category, name, website, description, `lastUpdate`, priority, ' - . '`pathEntries`, `httpAuth`, error, keep_history, ttl, attributes ' + . '`pathEntries`, `httpAuth`, error, ttl, attributes ' . 'FROM `_feed`'; $stm = $this->pdo->query($sql); while ($row = $stm->fetch(PDO::FETCH_ASSOC)) { @@ -319,7 +320,7 @@ class FreshRSS_FeedDAO extends Minz_ModelPdo implements FreshRSS_Searchable { */ public function listFeedsOrderUpdate($defaultCacheDuration = 3600, $limit = 0) { $this->updateTTL(); - $sql = 'SELECT id, url, name, website, `lastUpdate`, `pathEntries`, `httpAuth`, keep_history, ttl, attributes ' + $sql = 'SELECT id, url, name, website, `lastUpdate`, `pathEntries`, `httpAuth`, ttl, attributes ' . 'FROM `_feed` ' . ($defaultCacheDuration < 0 ? '' : 'WHERE ttl >= ' . FreshRSS_Feed::TTL_DEFAULT . ' AND `lastUpdate` < (' . (time() + 60) @@ -407,7 +408,7 @@ class FreshRSS_FeedDAO extends Minz_ModelPdo implements FreshRSS_Searchable { . 'SET `cache_nbEntries`=0, `cache_nbUnreads`=0 WHERE id=:id'; $stm = $this->pdo->prepare($sql); $stm->bindParam(':id', $id, PDO::PARAM_INT); - if (!($stm && $stm->execute($values))) { + if (!($stm && $stm->execute())) { $info = $stm == null ? $this->pdo->errorInfo() : $stm->errorInfo(); Minz_Log::error('SQL error truncate: ' . $info[2]); $this->pdo->rollBack(); @@ -448,7 +449,6 @@ class FreshRSS_FeedDAO extends Minz_ModelPdo implements FreshRSS_Searchable { $myFeed->_pathEntries(isset($dao['pathEntries']) ? $dao['pathEntries'] : ''); $myFeed->_httpAuth(isset($dao['httpAuth']) ? base64_decode($dao['httpAuth']) : ''); $myFeed->_error(isset($dao['error']) ? $dao['error'] : 0); - $myFeed->_keepHistory(isset($dao['keep_history']) ? $dao['keep_history'] : FreshRSS_Feed::KEEP_HISTORY_DEFAULT); $myFeed->_ttl(isset($dao['ttl']) ? $dao['ttl'] : FreshRSS_Feed::TTL_DEFAULT); $myFeed->_attributes('', isset($dao['attributes']) ? $dao['attributes'] : ''); $myFeed->_nbNotRead(isset($dao['cache_nbUnreads']) ? $dao['cache_nbUnreads'] : 0); diff --git a/app/Models/FeedDAOSQLite.php b/app/Models/FeedDAOSQLite.php index c56447df6..0f685867a 100644 --- a/app/Models/FeedDAOSQLite.php +++ b/app/Models/FeedDAOSQLite.php @@ -5,7 +5,7 @@ class FreshRSS_FeedDAOSQLite extends FreshRSS_FeedDAO { protected function autoUpdateDb($errorInfo) { if ($tableInfo = $this->pdo->query("PRAGMA table_info('feed')")) { $columns = $tableInfo->fetchAll(PDO::FETCH_COLUMN, 1); - foreach (array('attributes') as $column) { + foreach (['attributes'] as $column) { if (!in_array($column, $columns)) { return $this->addColumn($column); } diff --git a/app/Models/Tag.php b/app/Models/Tag.php index 3eb989cc1..0d50e356c 100644 --- a/app/Models/Tag.php +++ b/app/Models/Tag.php @@ -3,7 +3,7 @@ class FreshRSS_Tag extends Minz_Model { private $id = 0; private $name; - private $attributes = array(); + private $attributes = []; private $nbEntries = -1; private $nbUnread = -1; diff --git a/app/Models/TagDAO.php b/app/Models/TagDAO.php index 9c0f591c9..5882eee76 100644 --- a/app/Models/TagDAO.php +++ b/app/Models/TagDAO.php @@ -13,14 +13,14 @@ class FreshRSS_TagDAO extends Minz_ModelPdo implements FreshRSS_Searchable { $this->pdo->commit(); } try { - require_once(APP_PATH . '/SQL/install.sql.' . $this->pdo->dbType() . '.php'); + require(APP_PATH . '/SQL/install.sql.' . $this->pdo->dbType() . '.php'); Minz_Log::warning('SQL ALTER GUID case sensitivity...'); $databaseDAO = FreshRSS_Factory::createDatabaseDAO(); $databaseDAO->ensureCaseInsensitiveGuids(); Minz_Log::warning('SQL CREATE TABLE tag...'); - $ok = $this->pdo->exec(SQL_CREATE_TABLE_TAGS) !== false; + $ok = $this->pdo->exec($SQL_CREATE_TABLE_TAGS) !== false; } catch (Exception $e) { Minz_Log::error('FreshRSS_EntryDAO::createTagTable error: ' . $e->getMessage()); } @@ -48,9 +48,12 @@ class FreshRSS_TagDAO extends Minz_ModelPdo implements FreshRSS_Searchable { $stm = $this->pdo->prepare($sql); $valuesTmp['name'] = mb_strcut(trim($valuesTmp['name']), 0, 63, 'UTF-8'); + if (!isset($valuesTmp['attributes'])) { + $valuesTmp['attributes'] = []; + } $values = array( $valuesTmp['name'], - isset($valuesTmp['attributes']) ? json_encode($valuesTmp['attributes']) : '', + is_string($valuesTmp['attributes']) ? $valuesTmp['attributes'] : json_encode($valuesTmp['attributes'], JSON_UNESCAPED_SLASHES), $valuesTmp['name'], ); @@ -81,9 +84,12 @@ class FreshRSS_TagDAO extends Minz_ModelPdo implements FreshRSS_Searchable { $stm = $this->pdo->prepare($sql); $valuesTmp['name'] = mb_strcut(trim($valuesTmp['name']), 0, 63, 'UTF-8'); + if (!isset($valuesTmp['attributes'])) { + $valuesTmp['attributes'] = []; + } $values = array( $valuesTmp['name'], - isset($valuesTmp['attributes']) ? json_encode($valuesTmp['attributes']) : '', + is_string($valuesTmp['attributes']) ? $valuesTmp['attributes'] : json_encode($valuesTmp['attributes'], JSON_UNESCAPED_SLASHES), $id, $valuesTmp['name'], ); diff --git a/app/Models/UserDAO.php b/app/Models/UserDAO.php index 8e7e977d0..4e824cf01 100644 --- a/app/Models/UserDAO.php +++ b/app/Models/UserDAO.php @@ -2,14 +2,14 @@ class FreshRSS_UserDAO extends Minz_ModelPdo { public function createUser($insertDefaultFeeds = false) { - require_once(APP_PATH . '/SQL/install.sql.' . $this->pdo->dbType() . '.php'); + require(APP_PATH . '/SQL/install.sql.' . $this->pdo->dbType() . '.php'); try { - $sql = SQL_CREATE_TABLES . SQL_CREATE_TABLE_ENTRYTMP . SQL_CREATE_TABLE_TAGS; + $sql = $SQL_CREATE_TABLES . $SQL_CREATE_TABLE_ENTRYTMP . $SQL_CREATE_TABLE_TAGS; $ok = $this->pdo->exec($sql) !== false; //Note: Only exec() can take multiple statements safely. if ($ok && $insertDefaultFeeds) { $default_feeds = FreshRSS_Context::$system_conf->default_feeds; - $stm = $this->pdo->prepare(SQL_INSERT_FEED); + $stm = $this->pdo->prepare($SQL_INSERT_FEED); foreach ($default_feeds as $feed) { $parameters = [ ':url' => $feed['url'], @@ -38,9 +38,8 @@ class FreshRSS_UserDAO extends Minz_ModelPdo { fwrite(STDERR, 'Deleting SQL data for user “' . $this->current_user . "”…\n"); } - require_once(APP_PATH . '/SQL/install.sql.' . $this->pdo->dbType() . '.php'); - - $ok = $this->pdo->exec(SQL_DROP_TABLES) !== false; + require(APP_PATH . '/SQL/install.sql.' . $this->pdo->dbType() . '.php'); + $ok = $this->pdo->exec($SQL_DROP_TABLES) !== false; if ($ok) { return true; diff --git a/app/SQL/install.sql.mysql.php b/app/SQL/install.sql.mysql.php index 87b5d1989..1eabfae8b 100644 --- a/app/SQL/install.sql.mysql.php +++ b/app/SQL/install.sql.mysql.php @@ -1,12 +1,13 @@ array( '_' => 'Archivace', - 'advanced' => 'Pokročilé', 'delete_after' => 'Smazat články starší než', + 'exception' => 'Purge exception', //TODO - Translation 'help' => 'Více možností je dostupných v nastavení jednotlivých kanálů', - 'keep_history_by_feed' => 'Zachovat tento minimální počet článků v každém kanálu', + 'keep_favourites' => 'Never delete favourites', //TODO - Translation + 'keep_min_by_feed' => 'Zachovat tento minimální počet článků v každém kanálu', + 'keep_labels' => 'Never delete labels', //TODO - Translation + 'keep_unreads' => 'Never delete unreads', //TODO - Translation + 'maintenance' => 'Maintenance', //TODO - Translation 'optimize' => 'Optimalizovat databázi', 'optimize_help' => 'Občasná údržba zmenší velikost databáze', + 'policy' => 'Purge policy', //TODO - Translation + 'policy_warning' => 'If no purge policy is selected, every article will be kept.', //TODO - Translation 'purge_now' => 'Vyčistit nyní', + 'keep_max' => 'Maximum number of articles to keep', //TODO - Translation + 'keep_period' => 'Maximum age of articles to keep', //TODO - Translation 'title' => 'Archivace', 'ttl' => 'Neaktualizovat častěji než', ), diff --git a/app/i18n/cz/gen.php b/app/i18n/cz/gen.php index c6dabd555..de1456187 100644 --- a/app/i18n/cz/gen.php +++ b/app/i18n/cz/gen.php @@ -162,6 +162,13 @@ return array( 'nothing_to_load' => 'Žádné nové články', 'previous' => 'Předchozí', ), + 'period' => array( + 'days' => 'days', //TODO - Translation + 'hours' => 'hours', //TODO - Translation + 'months' => 'months', //TODO - Translation + 'weeks' => 'weeks', //TODO - Translation + 'years' => 'years', //TODO - Translation + ), 'share' => array( 'blogotext' => 'Blogotext', 'diaspora' => 'Diaspora*', diff --git a/app/i18n/cz/sub.php b/app/i18n/cz/sub.php index b2bdf416b..eaaff9acd 100644 --- a/app/i18n/cz/sub.php +++ b/app/i18n/cz/sub.php @@ -13,6 +13,7 @@ return array( 'category' => array( '_' => 'Kategorie', 'add' => 'Přidat kategorii', + 'archiving' => 'Archivace', 'empty' => 'Vyprázdit kategorii', 'information' => 'Informace', 'new' => 'Nová kategorie', @@ -40,7 +41,7 @@ return array( 'help' => 'Write one search filter per line.', //TODO - Translation ), 'information' => 'Informace', - 'keep_history' => 'Zachovat tento minimální počet článků', + 'keep_min' => 'Zachovat tento minimální počet článků', 'moved_category_deleted' => 'Po smazání kategorie budou v ní obsažené kanály automaticky přesunuty do %s.', 'mute' => 'mute', //TODO - Translation 'no_selected' => 'Nejsou označeny žádné kanály.', diff --git a/app/i18n/de/conf.php b/app/i18n/de/conf.php index 99225da9c..89bbfc10e 100644 --- a/app/i18n/de/conf.php +++ b/app/i18n/de/conf.php @@ -3,13 +3,21 @@ return array( 'archiving' => array( '_' => 'Archivierung', - 'advanced' => 'Erweitert', 'delete_after' => 'Entferne Artikel nach', + 'exception' => 'Purge exception', //TODO - Translation 'help' => 'Weitere Optionen sind in den Einstellungen der individuellen Feeds verfügbar.', - 'keep_history_by_feed' => 'Minimale Anzahl an Artikeln, die pro Feed behalten werden', + 'keep_favourites' => 'Never delete favourites', //TODO - Translation + 'keep_min_by_feed' => 'Minimale Anzahl an Artikeln, die pro Feed behalten werden', + 'keep_labels' => 'Never delete labels', //TODO - Translation + 'keep_unreads' => 'Never delete unreads', //TODO - Translation + 'maintenance' => 'Maintenance', //TODO - Translation 'optimize' => 'Datenbank optimieren', 'optimize_help' => 'Sollte gelegentlich durchgeführt werden, um die Größe der Datenbank zu reduzieren.', + 'policy' => 'Purge policy', //TODO - Translation + 'policy_warning' => 'If no purge policy is selected, every article will be kept.', //TODO - Translation 'purge_now' => 'Jetzt bereinigen', + 'keep_max' => 'Maximum number of articles to keep', //TODO - Translation + 'keep_period' => 'Maximum age of articles to keep', //TODO - Translation 'title' => 'Archivierung', 'ttl' => 'Aktualisiere automatisch nicht öfter als', ), diff --git a/app/i18n/de/gen.php b/app/i18n/de/gen.php index 6cc791d5e..e2dd2a251 100644 --- a/app/i18n/de/gen.php +++ b/app/i18n/de/gen.php @@ -162,6 +162,13 @@ return array( 'nothing_to_load' => 'Es gibt keine weiteren Artikel', 'previous' => 'Vorherige', ), + 'period' => array( + 'days' => 'days', //TODO - Translation + 'hours' => 'hours', //TODO - Translation + 'months' => 'months', //TODO - Translation + 'weeks' => 'weeks', //TODO - Translation + 'years' => 'years', //TODO - Translation + ), 'share' => array( 'blogotext' => 'Blogotext', 'diaspora' => 'Diaspora*', diff --git a/app/i18n/de/sub.php b/app/i18n/de/sub.php index abc01b954..1227b5559 100644 --- a/app/i18n/de/sub.php +++ b/app/i18n/de/sub.php @@ -13,6 +13,7 @@ return array( 'category' => array( '_' => 'Kategorie', 'add' => 'Eine Kategorie hinzufügen', + 'archiving' => 'Archivierung', 'empty' => 'Leere Kategorie', 'information' => 'Information', 'new' => 'Neue Kategorie', @@ -40,7 +41,7 @@ return array( 'help' => 'Write one search filter per line.', //TODO - Translation ), 'information' => 'Information', - 'keep_history' => 'Minimale Anzahl an Artikeln, die behalten wird', + 'keep_min' => 'Minimale Anzahl an Artikeln, die behalten wird', 'moved_category_deleted' => 'Wenn Sie eine Kategorie entfernen, werden deren Feeds automatisch in die Kategorie %s eingefügt.', 'mute' => 'Stumm schalten', 'no_selected' => 'Kein Feed ausgewählt.', diff --git a/app/i18n/en/conf.php b/app/i18n/en/conf.php index 1078c736c..2d4e06550 100644 --- a/app/i18n/en/conf.php +++ b/app/i18n/en/conf.php @@ -3,13 +3,21 @@ return array( 'archiving' => array( '_' => 'Archiving', - 'advanced' => 'Advanced', 'delete_after' => 'Remove articles after', + 'exception' => 'Purge exception', 'help' => 'More options are available in the individual feed settings', - 'keep_history_by_feed' => 'Minimum number of articles to keep by feed', + 'keep_favourites' => 'Never delete favourites', + 'keep_min_by_feed' => 'Minimum number of articles to keep by feed', + 'keep_labels' => 'Never delete labels', + 'keep_unreads' => 'Never delete unreads', + 'maintenance' => 'Maintenance', 'optimize' => 'Optimise database', 'optimize_help' => 'Do occasionally to reduce the size of the database', + 'policy' => 'Purge policy', + 'policy_warning' => 'If no purge policy is selected, every article will be kept.', 'purge_now' => 'Purge now', + 'keep_max' => 'Maximum number of articles to keep', + 'keep_period' => 'Maximum age of articles to keep', 'title' => 'Archiving', 'ttl' => 'Do not automatically refresh more often than', ), diff --git a/app/i18n/en/gen.php b/app/i18n/en/gen.php index a6ddcbb60..fc1bd587a 100644 --- a/app/i18n/en/gen.php +++ b/app/i18n/en/gen.php @@ -163,6 +163,13 @@ return array( 'nothing_to_load' => 'There are no more articles', 'previous' => 'Previous', ), + 'period' => array( + 'days' => 'days', + 'hours' => 'hours', + 'months' => 'months', + 'weeks' => 'weeks', + 'years' => 'years', + ), 'share' => array( 'blogotext' => 'Blogotext', 'diaspora' => 'Diaspora*', diff --git a/app/i18n/en/sub.php b/app/i18n/en/sub.php index fde01f9df..04ca793ec 100644 --- a/app/i18n/en/sub.php +++ b/app/i18n/en/sub.php @@ -13,6 +13,7 @@ return array( 'category' => array( '_' => 'Category', 'add' => 'Add a category', + 'archiving' => 'Archiving', 'empty' => 'Empty category', 'information' => 'Information', 'new' => 'New category', @@ -40,7 +41,7 @@ return array( 'help' => 'Write one search filter per line.', ), 'information' => 'Information', - 'keep_history' => 'Minimum number of articles to keep', + 'keep_min' => 'Minimum number of articles to keep', 'moved_category_deleted' => 'When you delete a category, its feeds are automatically classified under %s.', 'mute' => 'mute', 'no_selected' => 'No feed selected.', diff --git a/app/i18n/es/conf.php b/app/i18n/es/conf.php index 6aaad8d13..7a93a87de 100755 --- a/app/i18n/es/conf.php +++ b/app/i18n/es/conf.php @@ -3,13 +3,21 @@ return array( 'archiving' => array( '_' => 'Archivo', - 'advanced' => 'Avanzado', 'delete_after' => 'Eliminar artículos tras', + 'exception' => 'Purge exception', //TODO - Translation 'help' => 'Hay más opciones disponibles en los ajustes de la fuente', - 'keep_history_by_feed' => 'Número mínimo de artículos a conservar por fuente', + 'keep_favourites' => 'Never delete favourites', //TODO - Translation + 'keep_min_by_feed' => 'Número mínimo de artículos a conservar por fuente', + 'keep_labels' => 'Never delete labels', //TODO - Translation + 'keep_unreads' => 'Never delete unreads', //TODO - Translation + 'maintenance' => 'Maintenance', //TODO - Translation 'optimize' => 'Optimizar la base de datos', 'optimize_help' => 'Ejecuta la optimización de vez en cuando para reducir el tamaño de la base de datos', + 'policy' => 'Purge policy', //TODO - Translation + 'policy_warning' => 'If no purge policy is selected, every article will be kept.', //TODO - Translation 'purge_now' => 'Limpiar ahora', + 'keep_max' => 'Maximum number of articles to keep', //TODO - Translation + 'keep_period' => 'Maximum age of articles to keep', //TODO - Translation 'title' => 'Archivo', 'ttl' => 'No actualizar automáticamente más de', ), diff --git a/app/i18n/es/gen.php b/app/i18n/es/gen.php index 4affecc51..538ddc8fe 100755 --- a/app/i18n/es/gen.php +++ b/app/i18n/es/gen.php @@ -162,6 +162,13 @@ return array( 'nothing_to_load' => 'No hay más artículos', 'previous' => 'Anterior', ), + 'period' => array( + 'days' => 'days', //TODO - Translation + 'hours' => 'hours', //TODO - Translation + 'months' => 'months', //TODO - Translation + 'weeks' => 'weeks', //TODO - Translation + 'years' => 'years', //TODO - Translation + ), 'share' => array( 'blogotext' => 'Blogotext', 'diaspora' => 'Diaspora*', diff --git a/app/i18n/es/sub.php b/app/i18n/es/sub.php index 7d33c59fa..96be76c6c 100755 --- a/app/i18n/es/sub.php +++ b/app/i18n/es/sub.php @@ -13,6 +13,7 @@ return array( 'category' => array( '_' => 'Categoría', 'add' => 'Añadir a la categoría', + 'archiving' => 'Archivo', 'empty' => 'Vaciar categoría', 'information' => 'Información', 'new' => 'Nueva categoría', @@ -40,7 +41,7 @@ return array( 'help' => 'Write one search filter per line.', //TODO - Translation ), 'information' => 'Información', - 'keep_history' => 'Número mínimo de artículos a conservar', + 'keep_min' => 'Número mínimo de artículos a conservar', 'moved_category_deleted' => 'Al borrar una categoría todas sus fuentes pasan automáticamente a la categoría %s.', 'mute' => 'mute', //TODO - Translation 'no_selected' => 'No hay funentes seleccionadas.', diff --git a/app/i18n/fr/conf.php b/app/i18n/fr/conf.php index dcd623b5a..020c94085 100644 --- a/app/i18n/fr/conf.php +++ b/app/i18n/fr/conf.php @@ -3,13 +3,21 @@ return array( 'archiving' => array( '_' => 'Archivage', - 'advanced' => 'Avancé', 'delete_after' => 'Supprimer les articles après', + 'exception' => 'Exception de nettoyage', 'help' => 'D’autres options sont disponibles dans la configuration individuelle des flux.', - 'keep_history_by_feed' => 'Nombre minimum d’articles à conserver par flux', + 'keep_favourites' => 'Ne jamais supprimer les articles favoris', + 'keep_min_by_feed' => 'Nombre minimum d’articles à conserver par flux', + 'keep_labels' => 'Ne jamais supprimer les articles étiquetés', + 'keep_unreads' => 'Ne jamais supprimer les articles non lus', + 'maintenance' => 'Maintenance', 'optimize' => 'Optimiser la base de données', 'optimize_help' => 'À faire de temps en temps pour réduire la taille de la BDD', + 'policy' => 'Politique de nettoyage', + 'policy_warning' => 'Si aucune politique de nettoyage n’est sélectionnée, tous les articles seront conservés.', 'purge_now' => 'Purger maintenant', + 'keep_max' => 'Nombre maximum d’articles à conserver', + 'keep_period' => 'Âge maximum des articles à conserver', 'title' => 'Archivage', 'ttl' => 'Ne pas automatiquement rafraîchir plus souvent que', ), diff --git a/app/i18n/fr/gen.php b/app/i18n/fr/gen.php index 01b66d316..a6875dd05 100644 --- a/app/i18n/fr/gen.php +++ b/app/i18n/fr/gen.php @@ -162,6 +162,13 @@ return array( 'nothing_to_load' => 'Fin des articles', 'previous' => 'Précédent', ), + 'period' => array( + 'days' => 'jours', + 'hours' => 'heures', + 'months' => 'mois', + 'weeks' => 'semaines', + 'years' => 'années', + ), 'share' => array( 'blogotext' => 'Blogotext', 'diaspora' => 'Diaspora*', diff --git a/app/i18n/fr/sub.php b/app/i18n/fr/sub.php index df44150c2..d09a19e5a 100644 --- a/app/i18n/fr/sub.php +++ b/app/i18n/fr/sub.php @@ -13,6 +13,7 @@ return array( 'category' => array( '_' => 'Catégorie', 'add' => 'Ajouter une catégorie', + 'archiving' => 'Archivage', 'empty' => 'Catégorie vide', 'information' => 'Informations', 'new' => 'Nouvelle catégorie', @@ -40,7 +41,7 @@ return array( 'help' => 'Écrivez une recherche par ligne.', ), 'information' => 'Informations', - 'keep_history' => 'Nombre minimum d’articles à conserver', + 'keep_min' => 'Nombre minimum d’articles à conserver', 'moved_category_deleted' => 'Lors de la suppression d’une catégorie, ses flux seront automatiquement classés dans %s.', 'mute' => 'muet', 'no_selected' => 'Aucun flux sélectionné.', diff --git a/app/i18n/he/conf.php b/app/i18n/he/conf.php index 7e764b944..b987f21f4 100644 --- a/app/i18n/he/conf.php +++ b/app/i18n/he/conf.php @@ -3,13 +3,21 @@ return array( 'archiving' => array( '_' => 'ארכוב', - 'advanced' => 'מתקדם', 'delete_after' => 'מחיקת מאמרים לאחר', + 'exception' => 'Purge exception', //TODO - Translation 'help' => 'אפשרויות נוספות זמינות בזרמים ספציפיים', - 'keep_history_by_feed' => 'Minimum number of articles to keep by feed', //TODO - Translation + 'keep_favourites' => 'Never delete favourites', //TODO - Translation + 'keep_min_by_feed' => 'Minimum number of articles to keep by feed', + 'keep_labels' => 'Never delete labels', //TODO - Translation + 'keep_unreads' => 'Never delete unreads', //TODO - Translation + 'maintenance' => 'Maintenance', //TODO - Translation 'optimize' => 'מיטוב בסיס הנתונים', 'optimize_help' => 'ביצוע לעיתים קרובות על מנת למטב את בסיס הנתונים', + 'policy' => 'Purge policy', //TODO - Translation + 'policy_warning' => 'If no purge policy is selected, every article will be kept.', //TODO - Translation 'purge_now' => 'ניקוי עכשיו', + 'keep_max' => 'Maximum number of articles to keep', //TODO - Translation + 'keep_period' => 'Maximum age of articles to keep', //TODO - Translation 'title' => 'ארכוב', 'ttl' => 'אין לרענן אוטומטית יותר מ', ), diff --git a/app/i18n/he/gen.php b/app/i18n/he/gen.php index 158f11e5b..34e6d77de 100644 --- a/app/i18n/he/gen.php +++ b/app/i18n/he/gen.php @@ -162,6 +162,13 @@ return array( 'nothing_to_load' => 'אין מאמרים נוספים', 'previous' => 'הקודם', ), + 'period' => array( + 'days' => 'days', //TODO - Translation + 'hours' => 'hours', //TODO - Translation + 'months' => 'months', //TODO - Translation + 'weeks' => 'weeks', //TODO - Translation + 'years' => 'years', //TODO - Translation + ), 'share' => array( 'blogotext' => 'Blogotext', 'diaspora' => 'Diaspora*', diff --git a/app/i18n/he/sub.php b/app/i18n/he/sub.php index 8a629defb..15965d9e2 100644 --- a/app/i18n/he/sub.php +++ b/app/i18n/he/sub.php @@ -13,6 +13,7 @@ return array( 'category' => array( '_' => 'קטגוריה', 'add' => 'הוספת קטגוריה', + 'archiving' => 'ארכוב', 'empty' => 'Empty category', //TODO - Translation 'information' => 'מידע', 'new' => 'קטגוריה חדשה', @@ -40,7 +41,7 @@ return array( 'help' => 'Write one search filter per line.', //TODO - Translation ), 'information' => 'מידע', - 'keep_history' => 'מסםר מינימלי של מאמרים לשמור', + 'keep_min' => 'מסםר מינימלי של מאמרים לשמור', 'moved_category_deleted' => 'כאשר הקטגוריה נמחקת ההזנות שבתוכה אוטומטית מקוטלגות תחת %s.', 'mute' => 'mute', //TODO - Translation 'no_selected' => 'אף הזנה לא נבחרה.', diff --git a/app/i18n/it/conf.php b/app/i18n/it/conf.php index f06302c72..4bdaad33d 100644 --- a/app/i18n/it/conf.php +++ b/app/i18n/it/conf.php @@ -3,13 +3,21 @@ return array( 'archiving' => array( '_' => 'Archiviazione', - 'advanced' => 'Avanzate', 'delete_after' => 'Rimuovi articoli dopo', + 'exception' => 'Purge exception', //TODO - Translation 'help' => 'Altre opzioni sono disponibili nelle impostazioni dei singoli feed', - 'keep_history_by_feed' => 'Numero minimo di articoli da mantenere per feed', + 'keep_favourites' => 'Never delete favourites', //TODO - Translation + 'keep_min_by_feed' => 'Numero minimo di articoli da mantenere per feed', + 'keep_labels' => 'Never delete labels', //TODO - Translation + 'keep_unreads' => 'Never delete unreads', //TODO - Translation + 'maintenance' => 'Maintenance', //TODO - Translation 'optimize' => 'Ottimizza database', 'optimize_help' => 'Da fare occasionalmente per ridurre le dimensioni del database', + 'policy' => 'Purge policy', //TODO - Translation + 'policy_warning' => 'If no purge policy is selected, every article will be kept.', //TODO - Translation 'purge_now' => 'Cancella ora', + 'keep_max' => 'Maximum number of articles to keep', //TODO - Translation + 'keep_period' => 'Maximum age of articles to keep', //TODO - Translation 'title' => 'Archiviazione', 'ttl' => 'Non effettuare aggiornamenti per più di', ), diff --git a/app/i18n/it/gen.php b/app/i18n/it/gen.php index 604cc6941..50d4b4e6c 100644 --- a/app/i18n/it/gen.php +++ b/app/i18n/it/gen.php @@ -162,6 +162,13 @@ return array( 'nothing_to_load' => 'Non ci sono altri articoli', 'previous' => 'Precedente', ), + 'period' => array( + 'days' => 'days', //TODO - Translation + 'hours' => 'hours', //TODO - Translation + 'months' => 'months', //TODO - Translation + 'weeks' => 'weeks', //TODO - Translation + 'years' => 'years', //TODO - Translation + ), 'share' => array( 'blogotext' => 'Blogotext', 'diaspora' => 'Diaspora*', diff --git a/app/i18n/it/sub.php b/app/i18n/it/sub.php index 50738d9e3..22cd36986 100644 --- a/app/i18n/it/sub.php +++ b/app/i18n/it/sub.php @@ -13,6 +13,7 @@ return array( 'category' => array( '_' => 'Categoria', 'add' => 'Aggiungi una categoria', + 'archiving' => 'Archiviazione', 'empty' => 'Categoria vuota', 'information' => 'Informazioni', 'new' => 'Nuova categoria', @@ -40,7 +41,7 @@ return array( 'help' => 'Write one search filter per line.', //TODO - Translation ), 'information' => 'Informazioni', - 'keep_history' => 'Numero minimo di articoli da mantenere', + 'keep_min' => 'Numero minimo di articoli da mantenere', 'moved_category_deleted' => 'Cancellando una categoria i feed al suo interno verranno classificati automaticamente come %s.', 'mute' => 'mute', //TODO - Translation 'no_selected' => 'Nessun feed selezionato.', diff --git a/app/i18n/kr/conf.php b/app/i18n/kr/conf.php index 397d57418..1e77d0098 100644 --- a/app/i18n/kr/conf.php +++ b/app/i18n/kr/conf.php @@ -3,13 +3,21 @@ return array( 'archiving' => array( '_' => '보관', - 'advanced' => '고급 설정', 'delete_after' => '다음 기간보다 오래된 글 삭제', + 'exception' => 'Purge exception', //TODO - Translation 'help' => '더 자세한 옵션은 개별 피드 설정에 있습니다', - 'keep_history_by_feed' => '피드별 최소 유지 글 개수', + 'keep_favourites' => 'Never delete favourites', //TODO - Translation + 'keep_min_by_feed' => '피드별 최소 유지 글 개수', + 'keep_labels' => 'Never delete labels', //TODO - Translation + 'keep_unreads' => 'Never delete unreads', //TODO - Translation + 'maintenance' => 'Maintenance', //TODO - Translation 'optimize' => '데이터베이스 최적화', 'optimize_help' => '데이터베이스 크기를 줄이기 위해 가끔씩 수행해주세요', + 'policy' => 'Purge policy', //TODO - Translation + 'policy_warning' => 'If no purge policy is selected, every article will be kept.', //TODO - Translation 'purge_now' => '지금 삭제', + 'keep_max' => 'Maximum number of articles to keep', //TODO - Translation + 'keep_period' => 'Maximum age of articles to keep', //TODO - Translation 'title' => '보관', 'ttl' => '다음 시간이 지나기 전에 새로고침 금지', ), diff --git a/app/i18n/kr/gen.php b/app/i18n/kr/gen.php index 55fea3d66..fdc95d431 100644 --- a/app/i18n/kr/gen.php +++ b/app/i18n/kr/gen.php @@ -162,6 +162,13 @@ return array( 'nothing_to_load' => '더 이상 글이 없습니다', 'previous' => '이전', ), + 'period' => array( + 'days' => 'days', //TODO - Translation + 'hours' => 'hours', //TODO - Translation + 'months' => 'months', //TODO - Translation + 'weeks' => 'weeks', //TODO - Translation + 'years' => 'years', //TODO - Translation + ), 'share' => array( 'blogotext' => 'Blogotext', 'diaspora' => 'Diaspora*', diff --git a/app/i18n/kr/sub.php b/app/i18n/kr/sub.php index f8eccfa27..2586395f2 100644 --- a/app/i18n/kr/sub.php +++ b/app/i18n/kr/sub.php @@ -13,6 +13,7 @@ return array( 'category' => array( '_' => '카테고리', 'add' => '카테고리 추가', + 'archiving' => '보관', 'empty' => '빈 카테고리', 'information' => '정보', 'new' => '새 카테고리', @@ -40,7 +41,7 @@ return array( 'help' => 'Write one search filter per line.', //TODO - Translation ), 'information' => '정보', - 'keep_history' => '최소 유지 글 개수', + 'keep_min' => '최소 유지 글 개수', 'moved_category_deleted' => '카테고리를 삭제하면, 해당 카테고리 아래에 있던 피드들은 자동적으로 %s 아래로 분류됩니다.', 'mute' => '무기한 새로고침 금지', 'no_selected' => '선택된 피드가 없습니다.', diff --git a/app/i18n/nl/conf.php b/app/i18n/nl/conf.php index ec219d051..22302ccc0 100644 --- a/app/i18n/nl/conf.php +++ b/app/i18n/nl/conf.php @@ -1,15 +1,23 @@ array( '_' => 'Archivering', - 'advanced' => 'Geavanceerd', 'delete_after' => 'Verwijder artikelen na', + 'exception' => 'Purge exception', //TODO - Translation 'help' => 'Meer opties zijn beschikbaar in de persoonlijke stroom instellingen', - 'keep_history_by_feed' => 'Minimum aantal te behouden artikelen in de feed', - 'optimize' => 'Optimaliseer database', + 'keep_favourites' => 'Never delete favourites', //TODO - Translation + 'keep_min_by_feed' => 'Minimum aantal te behouden artikelen in de feed', + 'keep_labels' => 'Never delete labels', //TODO - Translation + 'keep_unreads' => 'Never delete unreads', //TODO - Translation + 'maintenance' => 'Maintenance', //TODO - Translation + 'optimize' => 'Optimaliseer database', //TODO - Translation 'optimize_help' => 'Doe dit zo af en toe om de omvang van de database te verkleinen', + 'policy' => 'Purge policy', //TODO - Translation + 'policy_warning' => 'If no purge policy is selected, every article will be kept.', //TODO - Translation 'purge_now' => 'Schoon nu op', + 'keep_max' => 'Maximum number of articles to keep', //TODO - Translation + 'keep_period' => 'Maximum age of articles to keep', //TODO - Translation 'title' => 'Archivering', 'ttl' => 'Vernieuw niet automatisch meer dan', ), diff --git a/app/i18n/nl/gen.php b/app/i18n/nl/gen.php index 0dcb3010a..4854e806e 100644 --- a/app/i18n/nl/gen.php +++ b/app/i18n/nl/gen.php @@ -162,6 +162,13 @@ return array( 'nothing_to_load' => 'Er zijn geen artikelen meer', 'previous' => 'Vorige', ), + 'period' => array( + 'days' => 'days', //TODO - Translation + 'hours' => 'hours', //TODO - Translation + 'months' => 'months', //TODO - Translation + 'weeks' => 'weeks', //TODO - Translation + 'years' => 'years', //TODO - Translation + ), 'share' => array( 'email' => 'Email', 'Known' => 'Known-gebaseerde sites', diff --git a/app/i18n/nl/sub.php b/app/i18n/nl/sub.php index 8ceb5aa28..6b498132f 100644 --- a/app/i18n/nl/sub.php +++ b/app/i18n/nl/sub.php @@ -13,6 +13,7 @@ return array( 'category' => array( '_' => 'Categorie', 'add' => 'Voeg categorie toe', + 'archiving' => 'Archiveren', 'empty' => 'Lege categorie', 'information' => 'Informatie', 'new' => 'Nieuwe categorie', @@ -40,7 +41,7 @@ return array( 'help' => 'Voer één zoekfilter per lijn in.', ), 'information' => 'Informatie', - 'keep_history' => 'Minimum aantal artikelen om te houden', + 'keep_min' => 'Minimum aantal artikelen om te houden', 'moved_category_deleted' => 'Als u een categorie verwijderd, worden de feeds automatisch geclassificeerd onder %s.', 'mute' => 'demp', 'no_selected' => 'Geen feed geselecteerd.', diff --git a/app/i18n/oc/conf.php b/app/i18n/oc/conf.php index 76c41911e..e8de3b089 100644 --- a/app/i18n/oc/conf.php +++ b/app/i18n/oc/conf.php @@ -5,11 +5,20 @@ return array( '_' => 'Archius', 'advanced' => 'Avançat', 'delete_after' => 'Levar los articles aprèp', + 'exception' => 'Purge exception', //TODO - Translation 'help' => 'Mai d’opcions son disponiblas dins la configuracion individuala dels fluxes', - 'keep_history_by_feed' => 'Nombre minimum d’articles de servar per flux', + 'keep_favourites' => 'Never delete favourites', //TODO - Translation + 'keep_min_by_feed' => 'Nombre minimum d’articles de servar per flux', + 'keep_labels' => 'Never delete labels', //TODO - Translation + 'keep_unreads' => 'Never delete unreads', //TODO - Translation + 'maintenance' => 'Maintenance', //TODO - Translation 'optimize' => 'Optimizar la basa de donada', 'optimize_help' => 'De far de temps en temps per redusir la talha de la basa de donadas', + 'policy' => 'Purge policy', //TODO - Translation + 'policy_warning' => 'If no purge policy is selected, every article will be kept.', //TODO - Translation 'purge_now' => 'Purgar ara', + 'keep_max' => 'Maximum number of articles to keep', //TODO - Translation + 'keep_period' => 'Maximum age of articles to keep', //TODO - Translation 'title' => 'Archius', 'ttl' => 'Actualizar pas automaticament mai sovent que', ), diff --git a/app/i18n/oc/gen.php b/app/i18n/oc/gen.php index 7ab56368f..928377997 100644 --- a/app/i18n/oc/gen.php +++ b/app/i18n/oc/gen.php @@ -162,6 +162,13 @@ return array( 'nothing_to_load' => 'I a pas mai d’articles', 'previous' => 'Precedent', ), + 'period' => array( + 'days' => 'days', //TODO - Translation + 'hours' => 'hours', //TODO - Translation + 'months' => 'months', //TODO - Translation + 'weeks' => 'weeks', //TODO - Translation + 'years' => 'years', //TODO - Translation + ), 'share' => array( 'blogotext' => 'Blogotext', 'diaspora' => 'Diaspora*', diff --git a/app/i18n/oc/sub.php b/app/i18n/oc/sub.php index eae9dff29..0f465d7ca 100644 --- a/app/i18n/oc/sub.php +++ b/app/i18n/oc/sub.php @@ -12,6 +12,7 @@ return array( 'category' => array( '_' => 'Categoria', 'add' => 'Ajustar una categoria', + 'archiving' => 'Archivar', 'empty' => 'Categoria voida', 'information' => 'Informacions', 'new' => 'Nòva categoria', @@ -39,7 +40,7 @@ return array( 'help' => 'Escrivètz una recèrca per linha.', ), 'information' => 'Informacions', - 'keep_history' => 'Nombre minimum d’articles de servar', + 'keep_min' => 'Nombre minimum d’articles de servar', 'moved_category_deleted' => 'Quand escafatz una categoria, sos fluxes son automaticament classats dins %s.', 'mute' => 'mut', 'no_selected' => 'Cap de flux pas seleccionat.', diff --git a/app/i18n/pt-br/conf.php b/app/i18n/pt-br/conf.php index eb067e58a..5e43cc373 100644 --- a/app/i18n/pt-br/conf.php +++ b/app/i18n/pt-br/conf.php @@ -3,13 +3,21 @@ return array( 'archiving' => array( '_' => 'Arquivar', - 'advanced' => 'Avançado', 'delete_after' => 'Remover artigos depois', + 'exception' => 'Purge exception', //TODO - Translation 'help' => 'Mais opções estão disponíveis nas configurações individuais do feed', - 'keep_history_by_feed' => 'Número mínimo de artigos para deixar no feed', + 'keep_favourites' => 'Never delete favourites', //TODO - Translation + 'keep_min_by_feed' => 'Número mínimo de artigos para deixar no feed', + 'keep_labels' => 'Never delete labels', //TODO - Translation + 'keep_unreads' => 'Never delete unreads', //TODO - Translation + 'maintenance' => 'Maintenance', //TODO - Translation 'optimize' => 'Otimizar banco de dados', 'optimize_help' => 'Faça ocasionalmente para reduzir o tamanho do banco de dados', + 'policy' => 'Purge policy', //TODO - Translation + 'policy_warning' => 'If no purge policy is selected, every article will be kept.', //TODO - Translation 'purge_now' => 'Purge agora', + 'keep_max' => 'Maximum number of articles to keep', //TODO - Translation + 'keep_period' => 'Maximum age of articles to keep', //TODO - Translation 'title' => 'Arquivar', 'ttl' => 'Não atualize automaticamente mais frequente que', ), diff --git a/app/i18n/pt-br/gen.php b/app/i18n/pt-br/gen.php index b327937d5..0e7f367ee 100644 --- a/app/i18n/pt-br/gen.php +++ b/app/i18n/pt-br/gen.php @@ -162,6 +162,13 @@ return array( 'nothing_to_load' => 'Não há mais artigos', 'previous' => 'Anterior', ), + 'period' => array( + 'days' => 'days', //TODO - Translation + 'hours' => 'hours', //TODO - Translation + 'months' => 'months', //TODO - Translation + 'weeks' => 'weeks', //TODO - Translation + 'years' => 'years', //TODO - Translation + ), 'share' => array( 'blogotext' => 'Blogotext', 'diaspora' => 'Diaspora*', diff --git a/app/i18n/pt-br/sub.php b/app/i18n/pt-br/sub.php index d4bea33c4..c4c28bd6c 100644 --- a/app/i18n/pt-br/sub.php +++ b/app/i18n/pt-br/sub.php @@ -13,6 +13,7 @@ return array( 'category' => array( '_' => 'Categoria', 'add' => 'Adicionar uma categoria', + 'archiving' => 'Arquivar', 'empty' => 'Categoria vazia', 'information' => 'Informações', 'new' => 'Nova categoria', @@ -40,7 +41,7 @@ return array( 'help' => 'Write one search filter per line.', //TODO - Translation ), 'information' => 'Informações', - 'keep_history' => 'Número mínimo de artigos para manter', + 'keep_min' => 'Número mínimo de artigos para manter', 'moved_category_deleted' => 'Quando você deleta uma categoria, seus feeds são automaticamente classificados como %s.', 'mute' => 'mute', //TODO - Translation 'no_selected' => 'Nenhum feed selecionado.', diff --git a/app/i18n/ru/conf.php b/app/i18n/ru/conf.php index af6f3b5f6..7a80587f8 100644 --- a/app/i18n/ru/conf.php +++ b/app/i18n/ru/conf.php @@ -3,13 +3,21 @@ return array( 'archiving' => array( '_' => 'Архивация', - 'advanced' => 'Продвинутые настройки', 'delete_after' => 'Удалять статьи после', + 'exception' => 'Purge exception', //TODO - Translation 'help' => 'Каждую подписку можно настроить более гибко', - 'keep_history_by_feed' => 'Minimum number of articles to keep by feed', //TODO - Translation + 'keep_favourites' => 'Never delete favourites', //TODO - Translation + 'keep_min_by_feed' => 'Minimum number of articles to keep by feed', //TODO - Translation + 'keep_labels' => 'Never delete labels', //TODO - Translation + 'keep_unreads' => 'Never delete unreads', //TODO - Translation + 'maintenance' => 'Maintenance', //TODO - Translation 'optimize' => 'Оптимизировать базу данных', - 'optimize_help' => 'To do occasionally to reduce the size of the database', //TODO - Translation + 'optimize_help' => 'To do occasionally to reduce the size of the database', //TODO - Translation + 'policy' => 'Purge policy', //TODO - Translation + 'policy_warning' => 'If no purge policy is selected, every article will be kept.', //TODO - Translation 'purge_now' => 'Очистить сейчас', + 'keep_max' => 'Maximum number of articles to keep', //TODO - Translation + 'keep_period' => 'Maximum age of articles to keep', //TODO - Translation 'title' => 'Архивация', 'ttl' => 'Не обновлять чаще чем', ), diff --git a/app/i18n/ru/gen.php b/app/i18n/ru/gen.php index cc1d7e00e..5200a7005 100644 --- a/app/i18n/ru/gen.php +++ b/app/i18n/ru/gen.php @@ -162,6 +162,13 @@ return array( 'nothing_to_load' => 'There are no more articles', //TODO - Translation 'previous' => 'Previous', //TODO - Translation ), + 'period' => array( + 'days' => 'days', //TODO - Translation + 'hours' => 'hours', //TODO - Translation + 'months' => 'months', //TODO - Translation + 'weeks' => 'weeks', //TODO - Translation + 'years' => 'years', //TODO - Translation + ), 'share' => array( 'blogotext' => 'Blogotext', 'diaspora' => 'Diaspora*', diff --git a/app/i18n/ru/sub.php b/app/i18n/ru/sub.php index a2c4e4690..f4bda385d 100644 --- a/app/i18n/ru/sub.php +++ b/app/i18n/ru/sub.php @@ -13,6 +13,7 @@ return array( 'category' => array( '_' => 'Category', //TODO - Translation 'add' => 'Add a category', //TODO - Translation + 'archiving' => 'Archivage', //TODO - Translation 'empty' => 'Empty category', //TODO - Translation 'information' => 'Information', //TODO - Translation 'new' => 'New category', //TODO - Translation @@ -40,7 +41,7 @@ return array( 'help' => 'Write one search filter per line.', //TODO - Translation ), 'information' => 'Information', //TODO - Translation - 'keep_history' => 'Minimum number of articles to keep', //TODO - Translation + 'keep_min' => 'Minimum number of articles to keep', //TODO - Translation 'moved_category_deleted' => 'When you delete a category, its feeds are automatically classified under %s.', //TODO - Translation 'mute' => 'mute', //TODO - Translation 'no_selected' => 'No feed selected.', //TODO - Translation diff --git a/app/i18n/sk/conf.php b/app/i18n/sk/conf.php index f704fd4be..2e2289b79 100644 --- a/app/i18n/sk/conf.php +++ b/app/i18n/sk/conf.php @@ -6,7 +6,7 @@ return array( 'advanced' => 'Pokročilé', 'delete_after' => 'Vymazať články po', 'help' => 'Viac možností nájdete v nastaveniach kanála', - 'keep_history_by_feed' => 'Minimálny počet článkov kanála na zachovanie', + 'keep_min_by_feed' => 'Minimálny počet článkov kanála na zachovanie', 'optimize' => 'Optimalizovať databázu', 'optimize_help' => 'Občas vykonajte na zmenšenie veľkosti databázy', 'purge_now' => 'Vyčistiť teraz', diff --git a/app/i18n/sk/sub.php b/app/i18n/sk/sub.php index 4dcd09f57..2167e1817 100644 --- a/app/i18n/sk/sub.php +++ b/app/i18n/sk/sub.php @@ -40,7 +40,7 @@ return array( 'help' => 'Napíšte jeden výraz hľadania na riadok.', ), 'information' => 'Informácia', - 'keep_history' => 'Minimálny počet článkov na uchovanie', + 'keep_min' => 'Minimálny počet článkov na uchovanie', 'moved_category_deleted' => 'Keď vymažete kategóriu, jej kanály sa automaticky zaradia pod %s.', 'mute' => 'stíšiť', 'no_selected' => 'Nevybrali ste kanál.', diff --git a/app/i18n/tr/conf.php b/app/i18n/tr/conf.php index 2bf1e8a6a..c8ea78efa 100644 --- a/app/i18n/tr/conf.php +++ b/app/i18n/tr/conf.php @@ -3,13 +3,21 @@ return array( 'archiving' => array( '_' => 'Arşiv', - 'advanced' => 'Gelişmiş', 'delete_after' => 'Makelelerin tutulacağı süre', + 'exception' => 'Purge exception', //TODO - Translation 'help' => 'Akış ayarlarında daha çok ayar bulabilirsiniz', - 'keep_history_by_feed' => 'Akışta en az tutulacak makale sayısı', + 'keep_favourites' => 'Never delete favourites', //TODO - Translation + 'keep_min_by_feed' => 'Akışta en az tutulacak makale sayısı', + 'keep_labels' => 'Never delete labels', //TODO - Translation + 'keep_unreads' => 'Never delete unreads', //TODO - Translation + 'maintenance' => 'Maintenance', //TODO - Translation 'optimize' => 'Veritabanı optimize et', 'optimize_help' => 'Bu işlem bazen veritabanı boyutunu düşürmeye yardımcı olur', + 'policy' => 'Purge policy', //TODO - Translation + 'policy_warning' => 'If no purge policy is selected, every article will be kept.', //TODO - Translation 'purge_now' => 'Şimdi temizle', + 'keep_max' => 'Maximum number of articles to keep', //TODO - Translation + 'keep_period' => 'Maximum age of articles to keep', //TODO - Translation 'title' => 'Arşiv', 'ttl' => 'Şu süreden sık otomatik yenileme yapma', ), diff --git a/app/i18n/tr/gen.php b/app/i18n/tr/gen.php index 5e361affb..ccc5b9ee6 100644 --- a/app/i18n/tr/gen.php +++ b/app/i18n/tr/gen.php @@ -162,6 +162,13 @@ return array( 'nothing_to_load' => 'Başka makale yok', 'previous' => 'Önceki', ), + 'period' => array( + 'days' => 'days', //TODO - Translation + 'hours' => 'hours', //TODO - Translation + 'months' => 'months', //TODO - Translation + 'weeks' => 'weeks', //TODO - Translation + 'years' => 'years', //TODO - Translation + ), 'share' => array( 'blogotext' => 'Blogotext', 'diaspora' => 'Diaspora*', diff --git a/app/i18n/tr/sub.php b/app/i18n/tr/sub.php index 858d15758..f6f40d3f7 100644 --- a/app/i18n/tr/sub.php +++ b/app/i18n/tr/sub.php @@ -13,6 +13,7 @@ return array( 'category' => array( '_' => 'Kategori', 'add' => 'Kategori ekle', + 'archiving' => 'Arşiv', 'empty' => 'Boş kategori', 'information' => 'Bilgi', 'new' => 'Yeni kategori', @@ -40,7 +41,7 @@ return array( 'help' => 'Write one search filter per line.', //TODO - Translation ), 'information' => 'Bilgi', - 'keep_history' => 'En az tutulacak makale sayısı', + 'keep_min' => 'En az tutulacak makale sayısı', 'moved_category_deleted' => 'Bir kategoriyi silerseniz, içerisindeki akışlar %s içerisine yerleşir.', 'mute' => 'mute', //TODO - Translation 'no_selected' => 'Hiçbir akış seçilmedi.', diff --git a/app/i18n/zh-cn/conf.php b/app/i18n/zh-cn/conf.php index 2960cd6b1..a7404bc58 100644 --- a/app/i18n/zh-cn/conf.php +++ b/app/i18n/zh-cn/conf.php @@ -3,13 +3,21 @@ return array( 'archiving' => array( '_' => '存档', - 'advanced' => '高级', 'delete_after' => '文章保留', + 'exception' => 'Purge exception', //TODO - Translation 'help' => '详细选项位于单独的 RSS 源设置', - 'keep_history_by_feed' => '至少保存的文章数', + 'keep_favourites' => 'Never delete favourites', //TODO - Translation + 'keep_min_by_feed' => '至少保存的文章数', + 'keep_labels' => 'Never delete labels', //TODO - Translation + 'keep_unreads' => 'Never delete unreads', //TODO - Translation + 'maintenance' => 'Maintenance', //TODO - Translation 'optimize' => '优化数据库', 'optimize_help' => '偶尔执行优化可以减少数据库大小', + 'policy' => 'Purge policy', //TODO - Translation + 'policy_warning' => 'If no purge policy is selected, every article will be kept.', //TODO - Translation 'purge_now' => '立即清除', + 'keep_max' => 'Maximum number of articles to keep', //TODO - Translation + 'keep_period' => 'Maximum age of articles to keep', //TODO - Translation 'title' => '存档', 'ttl' => '最小自动更新时间', ), diff --git a/app/i18n/zh-cn/gen.php b/app/i18n/zh-cn/gen.php index 7ae156573..31817260e 100644 --- a/app/i18n/zh-cn/gen.php +++ b/app/i18n/zh-cn/gen.php @@ -162,6 +162,13 @@ return array( 'nothing_to_load' => '没有更多文章了', 'previous' => '上一页', ), + 'period' => array( + 'days' => 'days', //TODO - Translation + 'hours' => 'hours', //TODO - Translation + 'months' => 'months', //TODO - Translation + 'weeks' => 'weeks', //TODO - Translation + 'years' => 'years', //TODO - Translation + ), 'share' => array( 'blogotext' => 'Blogotext', 'diaspora' => 'Diaspora*', diff --git a/app/i18n/zh-cn/sub.php b/app/i18n/zh-cn/sub.php index bf517756b..f6f3a0f7a 100644 --- a/app/i18n/zh-cn/sub.php +++ b/app/i18n/zh-cn/sub.php @@ -13,6 +13,7 @@ return array( 'category' => array( '_' => '分类', 'add' => '添加分类', + 'archiving' => '存档', 'empty' => '空分类', 'information' => '信息', 'new' => '新分类', @@ -40,7 +41,7 @@ return array( 'help' => 'Write one search filter per line.', //TODO - Translation ), 'information' => '信息', - 'keep_history' => '至少保存的文章数', + 'keep_min' => '至少保存的文章数', 'moved_category_deleted' => '删除分类时,其中的 RSS 源会自动归类到 %s', 'mute' => '暂停', 'no_selected' => '未选择 RSS 源。', diff --git a/app/install.php b/app/install.php index 366fb0cfc..f8bc6dd4e 100644 --- a/app/install.php +++ b/app/install.php @@ -86,7 +86,6 @@ function saveStep1() { // Then, we set $_SESSION vars $_SESSION['title'] = $system_conf->title; $_SESSION['auth_type'] = $system_conf->auth_type; - $_SESSION['old_entries'] = $user_conf->old_entries; $_SESSION['default_user'] = $current_user; $_SESSION['passwordHash'] = $user_conf->passwordHash; @@ -184,14 +183,12 @@ function saveStep3() { if (!empty($_POST)) { $system_default_config = Minz_Configuration::get('default_system'); $_SESSION['title'] = $system_default_config->title; - $_SESSION['old_entries'] = param('old_entries', $user_default_config->old_entries); $_SESSION['auth_type'] = param('auth_type', 'form'); if (FreshRSS_user_Controller::checkUsername(param('default_user', ''))) { $_SESSION['default_user'] = param('default_user', ''); } - if (empty($_SESSION['old_entries']) || - empty($_SESSION['auth_type']) || + if (empty($_SESSION['auth_type']) || empty($_SESSION['default_user'])) { return false; } @@ -208,10 +205,6 @@ function saveStep3() { FreshRSS_Context::$system_conf->default_user = $_SESSION['default_user']; FreshRSS_Context::$system_conf->save(); - if ((!ctype_digit($_SESSION['old_entries'])) ||($_SESSION['old_entries'] < 1)) { - $_SESSION['old_entries'] = $user_default_config->old_entries; - } - // Create default user files but first, we delete previous data to // avoid access right problems. recursive_unlink(USERS_PATH . '/' . $_SESSION['default_user']); @@ -225,7 +218,6 @@ function saveStep3() { '', [ 'language' => $_SESSION['language'], - 'old_entries' => $_SESSION['old_entries'], ] ); } catch (Exception $e) { @@ -317,8 +309,7 @@ function checkStep2() { } function checkStep3() { - $conf = !empty($_SESSION['old_entries']) && - !empty($_SESSION['default_user']); + $conf = !empty($_SESSION['default_user']); $form = isset($_SESSION['auth_type']); @@ -593,13 +584,6 @@ function printStep3() {
-
- -
- -
-
-
diff --git a/app/views/configure/archiving.phtml b/app/views/configure/archiving.phtml index 09be55fd9..0387a2b96 100644 --- a/app/views/configure/archiving.phtml +++ b/app/views/configure/archiving.phtml @@ -8,23 +8,6 @@

-
- -
- -   -
-
-
- -
- () -
-
@@ -47,6 +30,76 @@
+

+ +

+ +
+ +
+ +
+
+ +
+
+ +
+
+ +
+ +
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+
@@ -55,9 +108,9 @@
-
+ + -
@@ -66,21 +119,30 @@
-
-
- size_total); ?> +
+ -
+
+ +
-
+ + +
+ +
+ size_total); ?> +
+
+
diff --git a/app/views/helpers/category/update.phtml b/app/views/helpers/category/update.phtml index b64bd786a..31482f163 100644 --- a/app/views/helpers/category/update.phtml +++ b/app/views/helpers/category/update.phtml @@ -33,5 +33,121 @@
+ + + category->attributes('archiving'); + if (empty($archiving)) { + $archiving = [ 'default' => true ]; + } else { + $archiving['default'] = false; + } + $volatile = [ + 'enable_keep_period' => false, + 'keep_period_count' => '3', + 'keep_period_unit' => 'P1M', + ]; + if (!empty($archiving['keep_period'])) { + if (preg_match('/^PT?(?P\d+)[YMWDH]$/', $archiving['keep_period'], $matches)) { + $volatile['enable_keep_period'] = true; + $volatile['keep_period_count'] = $matches['count']; + $volatile['keep_period_unit'] = str_replace($matches['count'], '1', $archiving['keep_period']); + } + } + //Defaults + if (!isset($archiving['keep_max'])) { + $archiving['keep_max'] = false; + } + if (!isset($archiving['keep_favourites'])) { + $archiving['keep_favourites'] = true; + } + if (!isset($archiving['keep_labels'])) { + $archiving['keep_labels'] = true; + } + if (!isset($archiving['keep_unreads'])) { + $archiving['keep_unreads'] = false; + } + if (!isset($archiving['keep_min'])) { + $archiving['keep_min'] = 50; + } + ?> + +

+ +

+ +
+ +
+ +
+
+ + + + + + +
+
+ + +
+
diff --git a/app/views/helpers/feed/update.phtml b/app/views/helpers/feed/update.phtml index 620806d7b..84461ed03 100644 --- a/app/views/helpers/feed/update.phtml +++ b/app/views/helpers/feed/update.phtml @@ -78,6 +78,7 @@
+
+ feed->attributes('archiving'); + if (empty($archiving)) { + $archiving = [ 'default' => true ]; + } else { + $archiving['default'] = false; + } + $volatile = [ + 'enable_keep_period' => false, + 'keep_period_count' => '3', + 'keep_period_unit' => 'P1M', + ]; + if (!empty($archiving['keep_period'])) { + if (preg_match('/^PT?(?P\d+)[YMWDH]$/', $archiving['keep_period'], $matches)) { + $volatile['enable_keep_period'] = true; + $volatile['keep_period_count'] = $matches['count']; + $volatile['keep_period_unit'] = str_replace($matches['count'], '1', $archiving['keep_period']); + } + } + //Defaults + if (!isset($archiving['keep_max'])) { + $archiving['keep_max'] = false; + } + if (!isset($archiving['keep_min'])) { + $archiving['keep_min'] = 50; + } + if (!isset($archiving['keep_favourites'])) { + $archiving['keep_favourites'] = true; + } + if (!isset($archiving['keep_labels'])) { + $archiving['keep_labels'] = true; + } + if (!isset($archiving['keep_unreads'])) { + $archiving['keep_unreads'] = false; + } + ?> + +

+ +

+
- +
- +
+ + + + + + +
@@ -143,6 +243,7 @@
+
diff --git a/cli/_update-or-create-user.php b/cli/_update-or-create-user.php index eda597f19..43b86a4a9 100644 --- a/cli/_update-or-create-user.php +++ b/cli/_update-or-create-user.php @@ -45,8 +45,8 @@ $values = array( 'language' => strParam('language'), 'mail_login' => strParam('email'), 'token' => strParam('token'), - 'old_entries' => intParam('purge_after_months'), - 'keep_history_default' => intParam('feed_min_articles_default'), + 'old_entries' => intParam('purge_after_months'), //TODO: Update with new mechanism + 'keep_history_default' => intParam('feed_min_articles_default'), //TODO: Update with new mechanism 'ttl_default' => intParam('feed_ttl_default'), 'since_hours_posts_per_rss' => intParam('since_hours_posts_per_rss'), 'min_posts_per_rss' => intParam('min_posts_per_rss'), diff --git a/config-user.default.php b/config-user.default.php index 950bef045..5b49d689a 100644 --- a/config-user.default.php +++ b/config-user.default.php @@ -5,8 +5,14 @@ # override. return array ( 'language' => 'en', - 'old_entries' => 3, - 'keep_history_default' => 50, + 'archiving' => [ + 'keep_period' => 'P3M', + 'keep_max' => 200, + 'keep_min' => 50, + 'keep_favourites' => true, + 'keep_labels' => true, + 'keep_unreads' => false, + ], 'ttl_default' => 3600, 'mail_login' => '', 'email_validation_token' => '', diff --git a/lib/Minz/Request.php b/lib/Minz/Request.php index 01feece52..9235f873a 100644 --- a/lib/Minz/Request.php +++ b/lib/Minz/Request.php @@ -52,6 +52,12 @@ class Minz_Request { } return null; } + public static function paramBoolean($key) { + if (null === $value = self::paramTernary($key)) { + return false; + } + return $value; + } public static function defaultControllerName() { return self::$default_controller_name; } diff --git a/lib/lib_rss.php b/lib/lib_rss.php index 854126b54..2a230e6f8 100644 --- a/lib/lib_rss.php +++ b/lib/lib_rss.php @@ -300,7 +300,11 @@ function invalidateHttpCache($username = '') { Minz_Session::_param('touch', uTimeString()); $username = Minz_Session::param('currentUser', '_'); } - return touch(join_path(DATA_PATH, 'users', $username, 'log.txt')); + $ok = @touch(DATA_PATH . '/users/' . $username . '/log.txt'); + if (!$ok) { + //TODO: Display notification error on front-end + } + return $ok; } function listUsers() { diff --git a/p/scripts/category.js b/p/scripts/category.js index c01b1fdd7..c5d36e900 100644 --- a/p/scripts/category.js +++ b/p/scripts/category.js @@ -137,11 +137,34 @@ function init_draggable() { }; } +function archiving() { + const slider = document.getElementById('slider'); + slider.addEventListener('change', function (e) { + if (e.target.id === 'use_default_purge_options') { + slider.querySelectorAll('.archiving').forEach(function (element) { + element.hidden = e.target.checked; + }); + } + }); + slider.addEventListener('click', function (e) { + if (e.target.closest('button[type=reset]')) { + const archiving = document.getElementById('use_default_purge_options'); + if (archiving) { + slider.querySelectorAll('.archiving').forEach(function (element) { + element.hidden = archiving.getAttribute('data-leave-validation') == 1; + }); + } + } + }); +} + if (document.readyState && document.readyState !== 'loading') { init_draggable(); + archiving(); } else if (document.addEventListener) { document.addEventListener('DOMContentLoaded', function () { init_draggable(); + archiving(); }, false); } // @license-end diff --git a/p/scripts/extra.js b/p/scripts/extra.js index bba2e8e2b..1fd8a19de 100644 --- a/p/scripts/extra.js +++ b/p/scripts/extra.js @@ -184,12 +184,32 @@ function init_slider_observers() { }; closer.onclick = function (ev) { - closer.classList.remove('active'); - slider.classList.remove('active'); - return false; + if (data_leave_validation() || confirm(context.i18n.confirmation_default)) { + slider.querySelectorAll('form').forEach(function (f) { f.reset(); }); + closer.classList.remove('active'); + slider.classList.remove('active'); + return true; + } else { + return false; + } }; } +function data_leave_validation() { + const ds = document.querySelectorAll('[data-leave-validation]'); + for (let i = ds.length - 1; i >= 0; i--) { + const input = ds[i]; + if (input.type === 'checkbox' || input.type === 'radio') { + if (input.checked != input.getAttribute('data-leave-validation')) { + return false; + } + } else if (input.value != input.getAttribute('data-leave-validation')) { + return false; + } + } + return true; +} + function init_configuration_alert() { window.onsubmit = function (e) { window.hasSubmit = true; @@ -198,16 +218,8 @@ function init_configuration_alert() { if (window.hasSubmit) { return; } - const ds = document.querySelectorAll('[data-leave-validation]'); - for (let i = ds.length - 1; i >= 0; i--) { - const input = ds[i]; - if (input.type === 'checkbox' || input.type === 'radio') { - if (input.checked != input.getAttribute('data-leave-validation')) { - return false; - } - } else if (input.value != input.getAttribute('data-leave-validation')) { - return false; - } + if (!data_leave_validation()) { + return false; } }; } diff --git a/p/themes/base-theme/template.css b/p/themes/base-theme/template.css index 889d33c4e..2d76c9b4d 100644 --- a/p/themes/base-theme/template.css +++ b/p/themes/base-theme/template.css @@ -101,6 +101,9 @@ label { input { width: 180px; } +input[type=number] { + width: 6em; +} textarea, input[type="file"], diff --git a/phpcs.xml b/phpcs.xml index c69f53ea4..fba5624a8 100644 --- a/phpcs.xml +++ b/phpcs.xml @@ -3,8 +3,6 @@ Created with the PHP Coding Standard Generator. https://edorian.github.com/php-coding-standard-generator/ - ./static - ./vendor ./lib/SimplePie/ ./lib/PHPMailer/ ./lib/http-conditional.php @@ -28,9 +26,6 @@ ./app/install.php ./tests/app/ - - ./app/SQL/install.sql.mysql.php - ./app/SQL/install.sql.pgsql.php -- cgit v1.2.3 From f6e10579f2e78dc6403141351e41e2db9a2b6e97 Mon Sep 17 00:00:00 2001 From: Alexis Degrugillier Date: Sat, 26 Oct 2019 13:16:15 +0200 Subject: Add category order (#2592) * Add category order Each category has a new 'priority' attribute. It is used to sort categories in views. Categories with the same priority are sorted alphabetically. Categories with no priority are displayed after those with one. For example, if we have the following categories: - A (priority: 2) - B (no priority) - C (priority: 1) - D (priority: 2) - E (no priority) - F (priority: 1) They will be displayed in the following order: - C - F - A - D - B - E See #190 * Shorten help text It took too much room and will not be so necessary once we have drag & drop --- app/Controllers/indexController.php | 2 +- app/Controllers/subscriptionController.php | 5 ++++- app/Models/Category.php | 4 ++-- app/Models/CategoryDAO.php | 25 +++++++++++++++++++++++++ app/i18n/cz/sub.php | 2 ++ app/i18n/de/sub.php | 2 ++ app/i18n/en/sub.php | 2 ++ app/i18n/es/sub.php | 2 ++ app/i18n/fr/sub.php | 2 ++ app/i18n/he/sub.php | 2 ++ app/i18n/it/sub.php | 2 ++ app/i18n/kr/sub.php | 2 ++ app/i18n/nl/sub.php | 2 ++ app/i18n/oc/sub.php | 2 ++ app/i18n/pt-br/sub.php | 2 ++ app/i18n/ru/sub.php | 2 ++ app/i18n/sk/sub.php | 2 ++ app/i18n/tr/sub.php | 2 ++ app/i18n/zh-cn/sub.php | 2 ++ app/layout/aside_feed.phtml | 3 ++- app/views/helpers/category/update.phtml | 7 +++++++ 21 files changed, 71 insertions(+), 5 deletions(-) (limited to 'app/i18n/sk/sub.php') diff --git a/app/Controllers/indexController.php b/app/Controllers/indexController.php index 2d791ce1d..967029fd1 100755 --- a/app/Controllers/indexController.php +++ b/app/Controllers/indexController.php @@ -173,7 +173,7 @@ class FreshRSS_index_Controller extends Minz_ActionController { private function updateContext() { if (empty(FreshRSS_Context::$categories)) { $catDAO = FreshRSS_Factory::createCategoryDao(); - FreshRSS_Context::$categories = $catDAO->listCategories(); + FreshRSS_Context::$categories = $catDAO->listSortedCategories(); } // Update number of read / unread variables. diff --git a/app/Controllers/subscriptionController.php b/app/Controllers/subscriptionController.php index f9497f0be..b4520c8e6 100644 --- a/app/Controllers/subscriptionController.php +++ b/app/Controllers/subscriptionController.php @@ -19,7 +19,7 @@ class FreshRSS_subscription_Controller extends Minz_ActionController { $catDAO->checkDefault(); $feedDAO->updateTTL(); - $this->view->categories = $catDAO->listCategories(false); + $this->view->categories = $catDAO->listSortedCategories(false); $this->view->default_category = $catDAO->getDefault(); } @@ -216,6 +216,9 @@ class FreshRSS_subscription_Controller extends Minz_ActionController { ]); } + $position = Minz_Request::param('position'); + $category->_attributes('position', '' === $position ? null : (int) $position); + $values = [ 'name' => Minz_Request::param('name', ''), 'attributes' => $category->attributes(), diff --git a/app/Models/Category.php b/app/Models/Category.php index a0ee1ddaa..a195c88b3 100644 --- a/app/Models/Category.php +++ b/app/Models/Category.php @@ -98,14 +98,14 @@ class FreshRSS_Category extends Minz_Model { } public function _attributes($key, $value) { - if ($key == '') { + if ('' == $key) { if (is_string($value)) { $value = json_decode($value, true); } if (is_array($value)) { $this->attributes = $value; } - } elseif ($value === null) { + } elseif (null === $value) { unset($this->attributes[$key]); } else { $this->attributes[$key] = $value; diff --git a/app/Models/CategoryDAO.php b/app/Models/CategoryDAO.php index 210830640..a0eda89e7 100644 --- a/app/Models/CategoryDAO.php +++ b/app/Models/CategoryDAO.php @@ -201,6 +201,29 @@ class FreshRSS_CategoryDAO extends Minz_ModelPdo implements FreshRSS_Searchable } } + public function listSortedCategories($prePopulateFeeds = true, $details = false) { + $categories = $this->listCategories($prePopulateFeeds, $details); + + if (!is_array($categories)) { + return $categories; + } + + usort($categories, function ($a, $b) { + $aPosition = $a->attributes('position'); + $bPosition = $b->attributes('position'); + if ($aPosition === $bPosition) { + return ($a->name() < $b->name()) ? -1 : 1; + } elseif (null === $aPosition) { + return 1; + } elseif (null === $bPosition) { + return -1; + } + return ($aPosition < $bPosition) ? -1 : 1; + }); + + return $categories; + } + public function listCategories($prePopulateFeeds = true, $details = false) { if ($prePopulateFeeds) { $sql = 'SELECT c.id AS c_id, c.name AS c_name, c.attributes AS c_attributes, ' @@ -343,6 +366,7 @@ class FreshRSS_CategoryDAO extends Minz_ModelPdo implements FreshRSS_Searchable $feedDao->daoToFeed($feedsDao, $previousLine['c_id']) ); $cat->_id($previousLine['c_id']); + $cat->_attributes('', $previousLine['c_attributes']); $list[$previousLine['c_id']] = $cat; $feedsDao = array(); //Prepare for next category @@ -359,6 +383,7 @@ class FreshRSS_CategoryDAO extends Minz_ModelPdo implements FreshRSS_Searchable $feedDao->daoToFeed($feedsDao, $previousLine['c_id']) ); $cat->_id($previousLine['c_id']); + $cat->_attributes('', $previousLine['c_attributes']); $list[$previousLine['c_id']] = $cat; } diff --git a/app/i18n/cz/sub.php b/app/i18n/cz/sub.php index eaaff9acd..fefc05699 100644 --- a/app/i18n/cz/sub.php +++ b/app/i18n/cz/sub.php @@ -17,6 +17,8 @@ return array( 'empty' => 'Vyprázdit kategorii', 'information' => 'Informace', 'new' => 'Nová kategorie', + 'position' => 'Display position', //TODO - Translation + 'position_help' => 'To control category sort order', //TODO - Translation 'title' => 'Název', ), 'feed' => array( diff --git a/app/i18n/de/sub.php b/app/i18n/de/sub.php index 1227b5559..6feb1d6e1 100644 --- a/app/i18n/de/sub.php +++ b/app/i18n/de/sub.php @@ -17,6 +17,8 @@ return array( 'empty' => 'Leere Kategorie', 'information' => 'Information', 'new' => 'Neue Kategorie', + 'position' => 'Display position', //TODO - Translation + 'position_help' => 'To control category sort order', //TODO - Translation 'title' => 'Titel', ), 'feed' => array( diff --git a/app/i18n/en/sub.php b/app/i18n/en/sub.php index 04ca793ec..765cbf964 100644 --- a/app/i18n/en/sub.php +++ b/app/i18n/en/sub.php @@ -17,6 +17,8 @@ return array( 'empty' => 'Empty category', 'information' => 'Information', 'new' => 'New category', + 'position' => 'Display position', + 'position_help' => 'To control category sort order', 'title' => 'Title', ), 'feed' => array( diff --git a/app/i18n/es/sub.php b/app/i18n/es/sub.php index 96be76c6c..f2986ee5d 100755 --- a/app/i18n/es/sub.php +++ b/app/i18n/es/sub.php @@ -17,6 +17,8 @@ return array( 'empty' => 'Vaciar categoría', 'information' => 'Información', 'new' => 'Nueva categoría', + 'position' => 'Display position', //TODO - Translation + 'position_help' => 'To control category sort order', //TODO - Translation 'title' => 'Título', ), 'feed' => array( diff --git a/app/i18n/fr/sub.php b/app/i18n/fr/sub.php index d09a19e5a..ff0d72a11 100644 --- a/app/i18n/fr/sub.php +++ b/app/i18n/fr/sub.php @@ -17,6 +17,8 @@ return array( 'empty' => 'Catégorie vide', 'information' => 'Informations', 'new' => 'Nouvelle catégorie', + 'position' => 'Position d’affichage', + 'position_help' => 'Pour contrôler l’ordre de tri des catégories', 'title' => 'Titre', ), 'feed' => array( diff --git a/app/i18n/he/sub.php b/app/i18n/he/sub.php index 15965d9e2..2b806f6ff 100644 --- a/app/i18n/he/sub.php +++ b/app/i18n/he/sub.php @@ -17,6 +17,8 @@ return array( 'empty' => 'Empty category', //TODO - Translation 'information' => 'מידע', 'new' => 'קטגוריה חדשה', + 'position' => 'Display position', //TODO - Translation + 'position_help' => 'To control category sort order', //TODO - Translation 'title' => 'כותרת', ), 'feed' => array( diff --git a/app/i18n/it/sub.php b/app/i18n/it/sub.php index 22cd36986..400a0d259 100644 --- a/app/i18n/it/sub.php +++ b/app/i18n/it/sub.php @@ -17,6 +17,8 @@ return array( 'empty' => 'Categoria vuota', 'information' => 'Informazioni', 'new' => 'Nuova categoria', + 'position' => 'Display position', //TODO - Translation + 'position_help' => 'To control category sort order', //TODO - Translation 'title' => 'Titolo', ), 'feed' => array( diff --git a/app/i18n/kr/sub.php b/app/i18n/kr/sub.php index 2586395f2..eba732e22 100644 --- a/app/i18n/kr/sub.php +++ b/app/i18n/kr/sub.php @@ -17,6 +17,8 @@ return array( 'empty' => '빈 카테고리', 'information' => '정보', 'new' => '새 카테고리', + 'position' => 'Display position', //TODO - Translation + 'position_help' => 'To control category sort order', //TODO - Translation 'title' => '제목', ), 'feed' => array( diff --git a/app/i18n/nl/sub.php b/app/i18n/nl/sub.php index 6b498132f..e4a0c7fdf 100644 --- a/app/i18n/nl/sub.php +++ b/app/i18n/nl/sub.php @@ -17,6 +17,8 @@ return array( 'empty' => 'Lege categorie', 'information' => 'Informatie', 'new' => 'Nieuwe categorie', + 'position' => 'Display position', //TODO - Translation + 'position_help' => 'To control category sort order', //TODO - Translation 'title' => 'Titel', ), 'feed' => array( diff --git a/app/i18n/oc/sub.php b/app/i18n/oc/sub.php index 0f465d7ca..ad3a10935 100644 --- a/app/i18n/oc/sub.php +++ b/app/i18n/oc/sub.php @@ -16,6 +16,8 @@ return array( 'empty' => 'Categoria voida', 'information' => 'Informacions', 'new' => 'Nòva categoria', + 'position' => 'Display position', //TODO - Translation + 'position_help' => 'To control category sort order', //TODO - Translation 'title' => 'Títol', ), 'feed' => array( diff --git a/app/i18n/pt-br/sub.php b/app/i18n/pt-br/sub.php index c4c28bd6c..08ffc9a40 100644 --- a/app/i18n/pt-br/sub.php +++ b/app/i18n/pt-br/sub.php @@ -17,6 +17,8 @@ return array( 'empty' => 'Categoria vazia', 'information' => 'Informações', 'new' => 'Nova categoria', + 'position' => 'Display position', //TODO - Translation + 'position_help' => 'To control category sort order', //TODO - Translation 'title' => 'Título', ), 'feed' => array( diff --git a/app/i18n/ru/sub.php b/app/i18n/ru/sub.php index f4bda385d..47c7846e8 100644 --- a/app/i18n/ru/sub.php +++ b/app/i18n/ru/sub.php @@ -17,6 +17,8 @@ return array( 'empty' => 'Empty category', //TODO - Translation 'information' => 'Information', //TODO - Translation 'new' => 'New category', //TODO - Translation + 'position' => 'Display position', //TODO - Translation + 'position_help' => 'To control category sort order', //TODO - Translation 'title' => 'Title', //TODO - Translation ), 'feed' => array( diff --git a/app/i18n/sk/sub.php b/app/i18n/sk/sub.php index 2167e1817..971cfb683 100644 --- a/app/i18n/sk/sub.php +++ b/app/i18n/sk/sub.php @@ -16,6 +16,8 @@ return array( 'empty' => 'Prázdna kategória', 'information' => 'Informácia', 'new' => 'Nová kategória', + 'position' => 'Display position', //TODO - Translation + 'position_help' => 'To control category sort order', //TODO - Translation 'title' => 'Názov', ), 'feed' => array( diff --git a/app/i18n/tr/sub.php b/app/i18n/tr/sub.php index f6f40d3f7..45b84fe89 100644 --- a/app/i18n/tr/sub.php +++ b/app/i18n/tr/sub.php @@ -17,6 +17,8 @@ return array( 'empty' => 'Boş kategori', 'information' => 'Bilgi', 'new' => 'Yeni kategori', + 'position' => 'Display position', //TODO - Translation + 'position_help' => 'To control category sort order', //TODO - Translation 'title' => 'Başlık', ), 'feed' => array( diff --git a/app/i18n/zh-cn/sub.php b/app/i18n/zh-cn/sub.php index f6f3a0f7a..bd00bacc6 100644 --- a/app/i18n/zh-cn/sub.php +++ b/app/i18n/zh-cn/sub.php @@ -17,6 +17,8 @@ return array( 'empty' => '空分类', 'information' => '信息', 'new' => '新分类', + 'position' => 'Display position', //TODO - Translation + 'position_help' => 'To control category sort order', //TODO - Translation 'title' => '标题', ), 'feed' => array( diff --git a/app/layout/aside_feed.phtml b/app/layout/aside_feed.phtml index 4d5682001..e0c90282f 100644 --- a/app/layout/aside_feed.phtml +++ b/app/layout/aside_feed.phtml @@ -63,11 +63,12 @@ categories as $cat) { $feeds = $cat->feeds(); + $position = $cat->attributes('position'); if (!empty($feeds)) { $c_active = FreshRSS_Context::isCurrentGet('c_' . $cat->id()); $c_show = $c_active || FreshRSS_Context::$user_conf->display_categories; ?> -
  • +
  • data-unread="nbNotRead() ?>">
    name() ?> diff --git a/app/views/helpers/category/update.phtml b/app/views/helpers/category/update.phtml index 6a4c041ba..9e55e613d 100644 --- a/app/views/helpers/category/update.phtml +++ b/app/views/helpers/category/update.phtml @@ -17,6 +17,13 @@ ?> />
  • +
    + +
    + + +
    +
    -- cgit v1.2.3 From 571fb31af819ad2c53ee9cabccc0eeb62b915ae9 Mon Sep 17 00:00:00 2001 From: Alexis Degrugillier Date: Sun, 27 Oct 2019 17:34:55 +0100 Subject: Add a warning message for Firefox user (#2606) From version 63 and onwards, Firefox has removed the ability to add subscription services. This is a warning for deprecation on the subscription tools page. See #2100 --- app/i18n/cz/sub.php | 1 + app/i18n/de/sub.php | 1 + app/i18n/en/sub.php | 1 + app/i18n/es/sub.php | 1 + app/i18n/fr/sub.php | 1 + app/i18n/he/sub.php | 1 + app/i18n/it/sub.php | 1 + app/i18n/kr/sub.php | 1 + app/i18n/nl/sub.php | 1 + app/i18n/oc/sub.php | 1 + app/i18n/pt-br/sub.php | 5 +++++ app/i18n/ru/sub.php | 1 + app/i18n/sk/sub.php | 1 + app/i18n/tr/sub.php | 1 + app/i18n/zh-cn/sub.php | 1 + app/views/subscription/bookmarklet.phtml | 3 +++ 16 files changed, 22 insertions(+) (limited to 'app/i18n/sk/sub.php') diff --git a/app/i18n/cz/sub.php b/app/i18n/cz/sub.php index fefc05699..f2c259d15 100644 --- a/app/i18n/cz/sub.php +++ b/app/i18n/cz/sub.php @@ -75,6 +75,7 @@ return array( ), 'firefox' => array( 'documentation' => 'Follow the steps described here to add FreshRSS to Firefox feed reader list.',// TODO + 'obsolete_63' => 'From version 63 and onwards, Firefox has removed the ability to add your own subscription services that are not standalone programs.', //TODO - Translation 'title' => 'Firefox feed reader', //TODO - Translation ), 'import_export' => array( diff --git a/app/i18n/de/sub.php b/app/i18n/de/sub.php index 6feb1d6e1..754ac0866 100644 --- a/app/i18n/de/sub.php +++ b/app/i18n/de/sub.php @@ -75,6 +75,7 @@ return array( ), 'firefox' => array( 'documentation' => 'Folge den hier beschriebenen Schritten um FreshRSS zu Deiner Firefox RSS-Reader Liste hinzuzufügen.', + 'obsolete_63' => 'From version 63 and onwards, Firefox has removed the ability to add your own subscription services that are not standalone programs.', //TODO - Translation 'title' => 'Firefox RSS-Reader', ), 'import_export' => array( diff --git a/app/i18n/en/sub.php b/app/i18n/en/sub.php index 765cbf964..252177940 100644 --- a/app/i18n/en/sub.php +++ b/app/i18n/en/sub.php @@ -75,6 +75,7 @@ return array( ), 'firefox' => array( 'documentation' => 'Follow the steps described here to add FreshRSS to Firefox feed reader list.', + 'obsolete_63' => 'From version 63 and onwards, Firefox has removed the ability to add your own subscription services that are not standalone programs.', 'title' => 'Firefox feed reader', ), 'import_export' => array( diff --git a/app/i18n/es/sub.php b/app/i18n/es/sub.php index f2986ee5d..f1640b76b 100755 --- a/app/i18n/es/sub.php +++ b/app/i18n/es/sub.php @@ -75,6 +75,7 @@ return array( ), 'firefox' => array( 'documentation' => 'Follow the steps described here to add FreshRSS to Firefox feed reader list.', //TODO - Translation + 'obsolete_63' => 'From version 63 and onwards, Firefox has removed the ability to add your own subscription services that are not standalone programs.', //TODO - Translation 'title' => 'Firefox feed reader', //TODO - Translation ), 'import_export' => array( diff --git a/app/i18n/fr/sub.php b/app/i18n/fr/sub.php index ff0d72a11..e12444315 100644 --- a/app/i18n/fr/sub.php +++ b/app/i18n/fr/sub.php @@ -75,6 +75,7 @@ return array( ), 'firefox' => array( 'documentation' => 'Suivre les étapes décrites ici pour ajouter FreshRSS à la liste des lecteurs de flux dans Firefox.', + 'obsolete_63' => 'À partir de la version 63, Firefox ne supporte plus l’ajout de services d’abonnements.', 'title' => 'Lecteur de flux dans Firefox', ), 'import_export' => array( diff --git a/app/i18n/he/sub.php b/app/i18n/he/sub.php index 2b806f6ff..3fd0f267a 100644 --- a/app/i18n/he/sub.php +++ b/app/i18n/he/sub.php @@ -75,6 +75,7 @@ return array( ), 'firefox' => array( 'documentation' => 'Follow the steps described here to add FreshRSS to Firefox feed reader list.', //TODO - Translation + 'obsolete_63' => 'From version 63 and onwards, Firefox has removed the ability to add your own subscription services that are not standalone programs.', //TODO - Translation 'title' => 'Firefox feed reader', //TODO - Translation ), 'import_export' => array( diff --git a/app/i18n/it/sub.php b/app/i18n/it/sub.php index 400a0d259..78db7b0a6 100644 --- a/app/i18n/it/sub.php +++ b/app/i18n/it/sub.php @@ -75,6 +75,7 @@ return array( ), 'firefox' => array( 'documentation' => 'Follow the steps described here to add FreshRSS to Firefox feed reader list.', //TODO - Translation + 'obsolete_63' => 'From version 63 and onwards, Firefox has removed the ability to add your own subscription services that are not standalone programs.', //TODO - Translation 'title' => 'Firefox feed reader', //TODO - Translation ), 'import_export' => array( diff --git a/app/i18n/kr/sub.php b/app/i18n/kr/sub.php index eba732e22..ac45e4e73 100644 --- a/app/i18n/kr/sub.php +++ b/app/i18n/kr/sub.php @@ -75,6 +75,7 @@ return array( ), 'firefox' => array( 'documentation' => 'FreshRSS를 Firefox 피드 리더에 추가하기 위해서는 여기의 설명을 따르세요.', + 'obsolete_63' => 'From version 63 and onwards, Firefox has removed the ability to add your own subscription services that are not standalone programs.', //TODO - Translation 'title' => 'Firefox 피드 리더', ), 'import_export' => array( diff --git a/app/i18n/nl/sub.php b/app/i18n/nl/sub.php index e4a0c7fdf..690d8fad8 100644 --- a/app/i18n/nl/sub.php +++ b/app/i18n/nl/sub.php @@ -75,6 +75,7 @@ return array( ), 'firefox' => array( 'documentation' => 'Volg de stappen die hier beschreven worden om FreshRSS aan de Firefox-nieuwslezerlijst toe te voegen.', + 'obsolete_63' => 'From version 63 and onwards, Firefox has removed the ability to add your own subscription services that are not standalone programs.', //TODO - Translation 'title' => 'Firefox-nieuwslezer', ), 'import_export' => array( diff --git a/app/i18n/oc/sub.php b/app/i18n/oc/sub.php index f9081dbe5..32aff192d 100644 --- a/app/i18n/oc/sub.php +++ b/app/i18n/oc/sub.php @@ -74,6 +74,7 @@ return array( ), 'firefox' => array( 'documentation' => 'Seguissètz las etapas descrichas aquí per ajustar FreshRSS a la lista dels lectors de flux de Firefox.', + 'obsolete_63' => 'From version 63 and onwards, Firefox has removed the ability to add your own subscription services that are not standalone programs.', //TODO - Translation 'title' => 'Lector de flux de Firefox', ), 'import_export' => array( diff --git a/app/i18n/pt-br/sub.php b/app/i18n/pt-br/sub.php index 08ffc9a40..04e0c85ab 100644 --- a/app/i18n/pt-br/sub.php +++ b/app/i18n/pt-br/sub.php @@ -73,6 +73,11 @@ return array( 'validator' => 'Verifique a validade do feed', 'website' => 'URL do site', ), + 'firefox' => array( + 'documentation' => 'Follow the steps described here to add FreshRSS to Firefox feed reader list.',// TODO + 'obsolete_63' => 'From version 63 and onwards, Firefox has removed the ability to add your own subscription services that are not standalone programs.', //TODO - Translation + 'title' => 'Firefox feed reader', //TODO - Translation + ), 'import_export' => array( 'export' => 'Exportar', 'export_opml' => 'Exporta a lista dos feeds (OPML)', diff --git a/app/i18n/ru/sub.php b/app/i18n/ru/sub.php index 47c7846e8..e8cdeb89d 100644 --- a/app/i18n/ru/sub.php +++ b/app/i18n/ru/sub.php @@ -75,6 +75,7 @@ return array( ), 'firefox' => array( 'documentation' => 'Follow the steps described here to add FreshRSS to Firefox feed reader list.', //TODO - Translation + 'obsolete_63' => 'From version 63 and onwards, Firefox has removed the ability to add your own subscription services that are not standalone programs.', //TODO - Translation 'title' => 'Firefox feed reader', //TODO - Translation ), 'import_export' => array( diff --git a/app/i18n/sk/sub.php b/app/i18n/sk/sub.php index 971cfb683..3149c370b 100644 --- a/app/i18n/sk/sub.php +++ b/app/i18n/sk/sub.php @@ -74,6 +74,7 @@ return array( ), 'firefox' => array( 'documentation' => 'Pridajte RSS kanály do Firefoxu pomocou tohto návodu.', + 'obsolete_63' => 'From version 63 and onwards, Firefox has removed the ability to add your own subscription services that are not standalone programs.', //TODO - Translation 'title' => 'RSS čítačka vo Firefoxe', ), 'import_export' => array( diff --git a/app/i18n/tr/sub.php b/app/i18n/tr/sub.php index 45b84fe89..ed2a7ce76 100644 --- a/app/i18n/tr/sub.php +++ b/app/i18n/tr/sub.php @@ -75,6 +75,7 @@ return array( ), 'firefox' => array( 'documentation' => 'Follow the steps described here to add FreshRSS to Firefox feed reader list.', //TODO - Translation + 'obsolete_63' => 'From version 63 and onwards, Firefox has removed the ability to add your own subscription services that are not standalone programs.', //TODO - Translation 'title' => 'Firefox feed reader', //TODO - Translation ), 'import_export' => array( diff --git a/app/i18n/zh-cn/sub.php b/app/i18n/zh-cn/sub.php index bd00bacc6..944d6986f 100644 --- a/app/i18n/zh-cn/sub.php +++ b/app/i18n/zh-cn/sub.php @@ -75,6 +75,7 @@ return array( ), 'firefox' => array( 'documentation' => '按照 这里 描述的步骤可将 FreshRSS 添加到 Firefox 阅读器列表', + 'obsolete_63' => 'From version 63 and onwards, Firefox has removed the ability to add your own subscription services that are not standalone programs.', //TODO - Translation 'title' => 'Firefox RSS 阅读器', ), 'import_export' => array( diff --git a/app/views/subscription/bookmarklet.phtml b/app/views/subscription/bookmarklet.phtml index 385ce8cea..e6f311f58 100644 --- a/app/views/subscription/bookmarklet.phtml +++ b/app/views/subscription/bookmarklet.phtml @@ -8,6 +8,9 @@ +

    + default_category->name()) ?> +

    browser.contentHandlers.types.number.uri →  'feed', 'a' => 'add'), 'html', true) ?>&url_rss=%s
    -- cgit v1.2.3