summaryrefslogtreecommitdiff
path: root/app
diff options
context:
space:
mode:
authorGravatar plopoyop <clement@iMac-de-Clement.local> 2014-09-24 20:06:34 +0200
committerGravatar plopoyop <clement@iMac-de-Clement.local> 2014-09-24 20:06:34 +0200
commitc446625c7f6eda76b03fdac228b2f7b4ded74130 (patch)
tree42ab49b32804eeca003dfe69d6456ecf732b8fb1 /app
parentffbfbb92cc89c5ae07e0a28ee3477fcd0c44505d (diff)
parenta12d90d85d86c168a6e8a13345f05897f17958a4 (diff)
Merge remote-tracking branch 'upstream/dev' into dev
Diffstat (limited to 'app')
-rwxr-xr-xapp/Controllers/configureController.php319
-rwxr-xr-xapp/Controllers/feedController.php22
-rwxr-xr-xapp/Controllers/indexController.php6
-rw-r--r--app/Controllers/statsController.php42
-rw-r--r--app/Models/Configuration.php12
-rw-r--r--app/Models/Entry.php3
-rw-r--r--app/Models/EntryDAO.php5
-rw-r--r--app/Models/StatsDAO.php9
-rw-r--r--app/Models/StatsDAOSQLite.php1
-rw-r--r--app/Models/Themes.php1
-rw-r--r--app/i18n/de.php128
-rw-r--r--app/i18n/en.php24
-rw-r--r--app/i18n/fr.php32
-rw-r--r--app/layout/aside_flux.phtml10
-rw-r--r--app/layout/nav_menu.phtml17
-rw-r--r--app/views/configure/categorize.phtml5
-rw-r--r--app/views/configure/feed.phtml30
-rw-r--r--app/views/configure/queries.phtml15
-rw-r--r--app/views/configure/reading.phtml6
-rw-r--r--app/views/helpers/javascript_vars.phtml2
-rwxr-xr-xapp/views/helpers/pagination.phtml4
-rw-r--r--app/views/helpers/view/global_view.phtml8
-rw-r--r--app/views/helpers/view/normal_view.phtml6
-rw-r--r--app/views/helpers/view/reader_view.phtml6
-rw-r--r--app/views/stats/idle.phtml18
-rw-r--r--app/views/stats/index.phtml2
-rw-r--r--app/views/stats/repartition.phtml4
27 files changed, 505 insertions, 232 deletions
diff --git a/app/Controllers/configureController.php b/app/Controllers/configureController.php
index b1cd45014..231865bd7 100755
--- a/app/Controllers/configureController.php
+++ b/app/Controllers/configureController.php
@@ -1,11 +1,22 @@
<?php
+/**
+ * Controller to handle every configuration options.
+ */
class FreshRSS_configure_Controller extends Minz_ActionController {
+ /**
+ * This action is called before every other action in that class. It is
+ * the common boiler plate for every action. It is triggered by the
+ * underlying framework.
+ *
+ * @todo see if the category default configuration is needed here or if
+ * we can move it to the categorize action
+ */
public function firstAction() {
if (!$this->view->loginOk) {
Minz_Error::error(
403,
- array('error' => array(Minz_Translate::t('access_denied')))
+ array('error' => array(_t('access_denied')))
);
}
@@ -13,6 +24,18 @@ class FreshRSS_configure_Controller extends Minz_ActionController {
$catDAO->checkDefault();
}
+ /**
+ * This action handles the category configuration page
+ *
+ * It displays the category configuration page.
+ * If this action is reached through a POST request, it loops through
+ * every category to check for modification then add a new category if
+ * needed then sends a notification to the user.
+ * If a category name is emptied, the category is deleted and all
+ * related feeds are moved to the default category. Related user queries
+ * are deleted too.
+ * If a category name is changed, it is updated.
+ */
public function categorizeAction() {
$feedDAO = FreshRSS_Factory::createFeedDao();
$catDAO = new FreshRSS_CategoryDAO();
@@ -34,6 +57,10 @@ class FreshRSS_configure_Controller extends Minz_ActionController {
} elseif ($ids[$key] != $defaultId) {
$feedDAO->changeCategory($ids[$key], $defaultId);
$catDAO->deleteCategory($ids[$key]);
+
+ // Remove related queries.
+ $this->view->conf->remove_query_by_get('c_' . $ids[$key]);
+ $this->view->conf->save();
}
}
@@ -50,22 +77,37 @@ class FreshRSS_configure_Controller extends Minz_ActionController {
}
invalidateHttpCache();
- $notif = array(
- 'type' => 'good',
- 'content' => Minz_Translate::t('categories_updated')
- );
- Minz_Session::_param('notification', $notif);
-
- Minz_Request::forward(array('c' => 'configure', 'a' => 'categorize'), true);
+ Minz_Request::good(_t('categories_updated'),
+ array('c' => 'configure', 'a' => 'categorize'));
}
$this->view->categories = $catDAO->listCategories(false);
$this->view->defaultCategory = $catDAO->getDefault();
$this->view->feeds = $feedDAO->listFeeds();
- Minz_View::prependTitle(Minz_Translate::t('categories_management') . ' · ');
+ Minz_View::prependTitle(_t('categories_management') . ' · ');
}
+ /**
+ * This action handles the feed configuration page.
+ *
+ * It displays the feed configuration page.
+ * If this action is reached through a POST request, it stores all new
+ * configuraiton values then sends a notification to the user.
+ *
+ * The options available on the page are:
+ * - name
+ * - description
+ * - website URL
+ * - feed URL
+ * - category id (default: default category id)
+ * - CSS path to article on website
+ * - display in main stream (default: 0)
+ * - HTTP authentication
+ * - number of article to retain (default: -2)
+ * - refresh frequency (default: -2)
+ * Default values are empty strings unless specified.
+ */
public function feedAction() {
$catDAO = new FreshRSS_CategoryDAO();
$this->view->categories = $catDAO->listCategories(false);
@@ -85,7 +127,7 @@ class FreshRSS_configure_Controller extends Minz_ActionController {
if (!$this->view->flux) {
Minz_Error::error(
404,
- array('error' => array(Minz_Translate::t('page_not_found')))
+ array('error' => array(_t('page_not_found')))
);
} else {
if (Minz_Request::isPost() && $this->view->flux) {
@@ -117,12 +159,12 @@ class FreshRSS_configure_Controller extends Minz_ActionController {
$this->view->flux->faviconPrepare();
$notif = array(
'type' => 'good',
- 'content' => Minz_Translate::t('feed_updated')
+ 'content' => _t('feed_updated')
);
} else {
$notif = array(
'type' => 'bad',
- 'content' => Minz_Translate::t('error_occurred_update')
+ 'content' => _t('error_occurred_update')
);
}
invalidateHttpCache();
@@ -131,21 +173,41 @@ class FreshRSS_configure_Controller extends Minz_ActionController {
Minz_Request::forward(array('c' => 'configure', 'a' => 'feed', 'params' => array('id' => $id)), true);
}
- Minz_View::prependTitle(Minz_Translate::t('rss_feed_management') . ' — ' . $this->view->flux->name() . ' · ');
+ Minz_View::prependTitle(_t('rss_feed_management') . ' — ' . $this->view->flux->name() . ' · ');
}
} else {
- Minz_View::prependTitle(Minz_Translate::t('rss_feed_management') . ' · ');
+ Minz_View::prependTitle(_t('rss_feed_management') . ' · ');
}
}
+ /**
+ * This action handles the display configuration page.
+ *
+ * It displays the display configuration page.
+ * If this action is reached through a POST request, it stores all new
+ * configuration values then sends a notification to the user.
+ *
+ * The options available on the page are:
+ * - language (default: en)
+ * - theme (default: Origin)
+ * - content width (default: thin)
+ * - display of read action in header
+ * - display of favorite action in header
+ * - display of date in header
+ * - display of open action in header
+ * - display of read action in footer
+ * - display of favorite action in footer
+ * - display of sharing action in footer
+ * - display of tags in footer
+ * - display of date in footer
+ * - display of open action in footer
+ * - html5 notification timeout (default: 0)
+ * Default values are false unless specified.
+ */
public function displayAction() {
if (Minz_Request::isPost()) {
$this->view->conf->_language(Minz_Request::param('language', 'en'));
- $themeId = Minz_Request::param('theme', '');
- if ($themeId == '') {
- $themeId = FreshRSS_Themes::defaultTheme;
- }
- $this->view->conf->_theme($themeId);
+ $this->view->conf->_theme(Minz_Request::param('theme', FreshRSS_Themes::$defaultTheme));
$this->view->conf->_content_width(Minz_Request::param('content_width', 'thin'));
$this->view->conf->_topline_read(Minz_Request::param('topline_read', false));
$this->view->conf->_topline_favorite(Minz_Request::param('topline_favorite', false));
@@ -164,20 +226,42 @@ class FreshRSS_configure_Controller extends Minz_ActionController {
Minz_Translate::reset();
invalidateHttpCache();
- $notif = array(
- 'type' => 'good',
- 'content' => Minz_Translate::t('configuration_updated')
- );
- Minz_Session::_param('notification', $notif);
-
- Minz_Request::forward(array('c' => 'configure', 'a' => 'display'), true);
+ Minz_Request::good(_t('configuration_updated'),
+ array('c' => 'configure', 'a' => 'display'));
}
$this->view->themes = FreshRSS_Themes::get();
- Minz_View::prependTitle(Minz_Translate::t('display_configuration') . ' · ');
+ Minz_View::prependTitle(_t('display_configuration') . ' · ');
}
+ /**
+ * This action handles the reading configuration page.
+ *
+ * It displays the reading configuration page.
+ * If this action is reached through a POST request, it stores all new
+ * configuration values then sends a notification to the user.
+ *
+ * The options available on the page are:
+ * - number of posts per page (default: 10)
+ * - view mode (default: normal)
+ * - default article view (default: all)
+ * - load automatically articles
+ * - display expanded articles
+ * - display expanded categories
+ * - hide categories and feeds without unread articles
+ * - jump on next category or feed when marked as read
+ * - image lazy loading
+ * - stick open articles to the top
+ * - display a confirmation when reading all articles
+ * - article order (default: DESC)
+ * - mark articles as read when:
+ * - displayed
+ * - opened on site
+ * - scrolled
+ * - received
+ * Default values are false unless specified.
+ */
public function readingAction() {
if (Minz_Request::isPost()) {
$this->view->conf->_posts_per_page(Minz_Request::param('posts_per_page', 10));
@@ -204,18 +288,20 @@ class FreshRSS_configure_Controller extends Minz_ActionController {
Minz_Translate::reset();
invalidateHttpCache();
- $notif = array(
- 'type' => 'good',
- 'content' => Minz_Translate::t('configuration_updated')
- );
- Minz_Session::_param('notification', $notif);
-
- Minz_Request::forward(array('c' => 'configure', 'a' => 'reading'), true);
+ Minz_Request::good(_t('configuration_updated'),
+ array('c' => 'configure', 'a' => 'reading'));
}
- Minz_View::prependTitle(Minz_Translate::t('reading_configuration') . ' · ');
+ Minz_View::prependTitle(_t('reading_configuration') . ' · ');
}
+ /**
+ * This action handles the sharing configuration page.
+ *
+ * It displays the sharing configuration page.
+ * If this action is reached through a POST request, it stores all
+ * configuration values then sends a notification to the user.
+ */
public function sharingAction() {
if (Minz_Request::isPost()) {
$params = Minz_Request::params();
@@ -223,25 +309,31 @@ class FreshRSS_configure_Controller extends Minz_ActionController {
$this->view->conf->save();
invalidateHttpCache();
- $notif = array(
- 'type' => 'good',
- 'content' => Minz_Translate::t('configuration_updated')
- );
- Minz_Session::_param('notification', $notif);
-
- Minz_Request::forward(array('c' => 'configure', 'a' => 'sharing'), true);
+ Minz_Request::good(_t('configuration_updated'),
+ array('c' => 'configure', 'a' => 'sharing'));
}
- Minz_View::prependTitle(Minz_Translate::t('sharing') . ' · ');
+ Minz_View::prependTitle(_t('sharing') . ' · ');
}
+ /**
+ * This action handles the shortcut configuration page.
+ *
+ * It displays the shortcut configuration page.
+ * If this action is reached through a POST request, it stores all new
+ * configuration values then sends a notification to the user.
+ *
+ * The authorized values for shortcuts are letters (a to z), numbers (0
+ * to 9), function keys (f1 to f12), backspace, delete, down, end, enter,
+ * escape, home, insert, left, page down, page up, return, right, space,
+ * tab and up.
+ */
public function shortcutAction() {
$list_keys = array('a', 'b', 'backspace', 'c', 'd', 'delete', 'down', 'e', 'end', 'enter',
'escape', 'f', 'g', 'h', 'home', 'i', 'insert', 'j', 'k', 'l', 'left',
'm', 'n', 'o', 'p', 'page_down', 'page_up', 'q', 'r', 'return', 'right',
's', 'space', 't', 'tab', 'u', 'up', 'v', 'w', 'x', 'y',
- 'z', '0', '1', '2', '3', '4', '5', '6', '7', '8',
- '9', 'f1', 'f2', 'f3', 'f4', 'f5', 'f6', 'f7', 'f8', 'f9',
+ 'z', 'f1', 'f2', 'f3', 'f4', 'f5', 'f6', 'f7', 'f8', 'f9',
'f10', 'f11', 'f12');
$this->view->list_keys = $list_keys;
@@ -259,44 +351,50 @@ class FreshRSS_configure_Controller extends Minz_ActionController {
$this->view->conf->save();
invalidateHttpCache();
- $notif = array(
- 'type' => 'good',
- 'content' => Minz_Translate::t('shortcuts_updated')
- );
- Minz_Session::_param('notification', $notif);
-
- Minz_Request::forward(array('c' => 'configure', 'a' => 'shortcut'), true);
+ Minz_Request::good(_t('shortcuts_updated'),
+ array('c' => 'configure', 'a' => 'shortcut'));
}
- Minz_View::prependTitle(Minz_Translate::t('shortcuts') . ' · ');
+ Minz_View::prependTitle(_t('shortcuts') . ' · ');
}
+ /**
+ * This action display the user configuration page
+ *
+ * @todo move that action in the user controller
+ */
public function usersAction() {
- Minz_View::prependTitle(Minz_Translate::t('users') . ' · ');
+ Minz_View::prependTitle(_t('users') . ' · ');
}
+ /**
+ * This action handles the archive configuration page.
+ *
+ * It displays the archive configuration page.
+ * If this action is reached through a POST request, it stores all new
+ * configuration values then sends a notification to the user.
+ *
+ * The options available on that page are:
+ * - duration to retain old article (default: 3)
+ * - number of article to retain per feed (default: 0)
+ * - refresh frequency (default: -2)
+ *
+ * @todo explain why the default value is -2 but this value does not
+ * exist in the drop-down list
+ */
public function archivingAction() {
if (Minz_Request::isPost()) {
- $old = Minz_Request::param('old_entries', 3);
- $keepHistoryDefault = Minz_Request::param('keep_history_default', 0);
- $ttlDefault = Minz_Request::param('ttl_default', -2);
-
- $this->view->conf->_old_entries($old);
- $this->view->conf->_keep_history_default($keepHistoryDefault);
- $this->view->conf->_ttl_default($ttlDefault);
+ $this->view->conf->_old_entries(Minz_Request::param('old_entries', 3));
+ $this->view->conf->_keep_history_default(Minz_Request::param('keep_history_default', 0));
+ $this->view->conf->_ttl_default(Minz_Request::param('ttl_default', -2));
$this->view->conf->save();
invalidateHttpCache();
- $notif = array(
- 'type' => 'good',
- 'content' => Minz_Translate::t('configuration_updated')
- );
- Minz_Session::_param('notification', $notif);
-
- Minz_Request::forward(array('c' => 'configure', 'a' => 'archiving'), true);
+ Minz_Request::good(_t('configuration_updated'),
+ array('c' => 'configure', 'a' => 'archiving'));
}
- Minz_View::prependTitle(Minz_Translate::t('archiving_configuration') . ' · ');
+ Minz_View::prependTitle(_t('archiving_configuration') . ' · ');
$entryDAO = FreshRSS_Factory::createEntryDao();
$this->view->nb_total = $entryDAO->count();
@@ -306,28 +404,35 @@ class FreshRSS_configure_Controller extends Minz_ActionController {
$this->view->size_total = $entryDAO->size(true);
}
}
-
+
+ /**
+ * This action handles the user queries configuration page.
+ *
+ * If this action is reached through a POST request, it stores all new
+ * configuration values then sends a notification to the user then
+ * redirect to the same page.
+ * If this action is not reached through a POST request, it displays the
+ * configuration page and verifies that every user query is runable by
+ * checking if categories and feeds are still in use.
+ */
public function queriesAction() {
if (Minz_Request::isPost()) {
$queries = Minz_Request::param('queries', array());
foreach ($queries as $key => $query) {
if (!$query['name']) {
- $query['name'] = Minz_Translate::t('query_number', $key + 1);
+ $query['name'] = _t('query_number', $key + 1);
}
}
$this->view->conf->_queries($queries);
$this->view->conf->save();
- $notif = array(
- 'type' => 'good',
- 'content' => Minz_Translate::t('configuration_updated')
- );
- Minz_Session::_param('notification', $notif);
-
- Minz_Request::forward(array('c' => 'configure', 'a' => 'queries'), true);
+ Minz_Request::good(_t('configuration_updated'),
+ array('c' => 'configure', 'a' => 'queries'));
} else {
$this->view->query_get = array();
+ $cat_dao = new FreshRSS_CategoryDAO();
+ $feed_dao = FreshRSS_Factory::createFeedDao();
foreach ($this->view->conf->queries as $key => $query) {
if (!isset($query['get'])) {
continue;
@@ -335,51 +440,83 @@ class FreshRSS_configure_Controller extends Minz_ActionController {
switch ($query['get'][0]) {
case 'c':
- $dao = new FreshRSS_CategoryDAO();
- $category = $dao->searchById(substr($query['get'], 2));
+ $category = $cat_dao->searchById(substr($query['get'], 2));
+
+ $deprecated = true;
+ $cat_name = '';
+ if ($category) {
+ $cat_name = $category->name();
+ $deprecated = false;
+ }
+
$this->view->query_get[$key] = array(
'type' => 'category',
- 'name' => $category->name(),
+ 'name' => $cat_name,
+ 'deprecated' => $deprecated,
);
break;
case 'f':
- $dao = FreshRSS_Factory::createFeedDao();
- $feed = $dao->searchById(substr($query['get'], 2));
+ $feed = $feed_dao->searchById(substr($query['get'], 2));
+
+ $deprecated = true;
+ $feed_name = '';
+ if ($feed) {
+ $feed_name = $feed->name();
+ $deprecated = false;
+ }
+
$this->view->query_get[$key] = array(
'type' => 'feed',
- 'name' => $feed->name(),
+ 'name' => $feed_name,
+ 'deprecated' => $deprecated,
);
break;
case 's':
$this->view->query_get[$key] = array(
'type' => 'favorite',
'name' => 'favorite',
+ 'deprecated' => false,
);
break;
case 'a':
$this->view->query_get[$key] = array(
'type' => 'all',
'name' => 'all',
+ 'deprecated' => false,
);
break;
}
}
}
- Minz_View::prependTitle(Minz_Translate::t('queries') . ' · ');
+ Minz_View::prependTitle(_t('queries') . ' · ');
}
-
+
+ /**
+ * This action handles the creation of a user query.
+ *
+ * It gets the GET parameters and stores them in the configuration query
+ * storage. Before it is saved, the unwanted parameters are unset to keep
+ * lean data.
+ */
public function addQueryAction() {
+ $whitelist = array('get', 'order', 'name', 'search', 'state');
$queries = $this->view->conf->queries;
$query = Minz_Request::params();
- $query['name'] = Minz_Translate::t('query_number', count($queries) + 1);
- unset($query['output']);
- unset($query['token']);
+ $query['name'] = _t('query_number', count($queries) + 1);
+ foreach ($query as $key => $value) {
+ if (!in_array($key, $whitelist)) {
+ unset($query[$key]);
+ }
+ }
+ if (!empty($query['state']) && $query['state'] & FreshRSS_Entry::STATE_STRICT) {
+ $query['state'] -= FreshRSS_Entry::STATE_STRICT;
+ }
$queries[] = $query;
$this->view->conf->_queries($queries);
$this->view->conf->save();
- // Minz_Request::forward(array('params' => $query), true);
- Minz_Request::forward(array('c' => 'configure', 'a' => 'queries'), true);
+ Minz_Request::good(_t('query_created', $query['name']),
+ array('c' => 'configure', 'a' => 'queries'));
}
}
diff --git a/app/Controllers/feedController.php b/app/Controllers/feedController.php
index 3326b2059..c7cc25fbb 100755
--- a/app/Controllers/feedController.php
+++ b/app/Controllers/feedController.php
@@ -383,7 +383,16 @@ class FreshRSS_feed_Controller extends Minz_ActionController {
$feedDAO = FreshRSS_Factory::createFeedDao();
if ($type == 'category') {
+ // List feeds to remove then related user queries.
+ $feeds = $feedDAO->listByCategory($id);
+
if ($feedDAO->deleteFeedByCategory ($id)) {
+ // Remove related queries
+ foreach ($feeds as $feed) {
+ $this->view->conf->remove_query_by_get('f_' . $feed->id());
+ }
+ $this->view->conf->save();
+
$notif = array (
'type' => 'good',
'content' => Minz_Translate::t ('category_emptied')
@@ -397,6 +406,10 @@ class FreshRSS_feed_Controller extends Minz_ActionController {
}
} else {
if ($feedDAO->deleteFeed ($id)) {
+ // Remove related queries
+ $this->view->conf->remove_query_by_get('f_' . $id);
+ $this->view->conf->save();
+
$notif = array (
'type' => 'good',
'content' => Minz_Translate::t ('feed_deleted')
@@ -412,10 +425,13 @@ class FreshRSS_feed_Controller extends Minz_ActionController {
Minz_Session::_param ('notification', $notif);
- if ($type == 'category') {
- Minz_Request::forward (array ('c' => 'configure', 'a' => 'categorize'), true);
+ $redirect_url = Minz_Request::param('r', false, true);
+ if ($redirect_url) {
+ Minz_Request::forward($redirect_url);
+ } elseif ($type == 'category') {
+ Minz_Request::forward(array ('c' => 'configure', 'a' => 'categorize'), true);
} else {
- Minz_Request::forward (array ('c' => 'configure', 'a' => 'feed'), true);
+ Minz_Request::forward(array ('c' => 'configure', 'a' => 'feed'), true);
}
}
}
diff --git a/app/Controllers/indexController.php b/app/Controllers/indexController.php
index b69c09127..e8e26b142 100755
--- a/app/Controllers/indexController.php
+++ b/app/Controllers/indexController.php
@@ -84,7 +84,7 @@ class FreshRSS_index_Controller extends Minz_ActionController {
$first = Minz_Request::param ('next', '');
$ajax_request = Minz_Request::param('ajax', false);
- if ($ajax_request == 1 && $this->view->conf->display_posts) {
+ if ($output === 'reader') {
$nb = max(1, round($nb / 2));
}
@@ -337,6 +337,10 @@ class FreshRSS_index_Controller extends Minz_ActionController {
}
public function formLoginAction () {
+ if ($this->view->loginOk) {
+ Minz_Request::forward(array('c' => 'index', 'a' => 'index'), true);
+ }
+
if (Minz_Request::isPost()) {
$ok = false;
$nonce = Minz_Session::param('nonce');
diff --git a/app/Controllers/statsController.php b/app/Controllers/statsController.php
index 000b41dd2..256543f37 100644
--- a/app/Controllers/statsController.php
+++ b/app/Controllers/statsController.php
@@ -1,7 +1,21 @@
<?php
+/**
+ * Controller to handle application statistics.
+ */
class FreshRSS_stats_Controller extends Minz_ActionController {
+ /**
+ * This action handles the statistic main page.
+ *
+ * It displays the statistic main page.
+ * The values computed to display the page are:
+ * - repartition of read/unread/favorite/not favorite
+ * - number of article per day
+ * - number of feed by category
+ * - number of article by category
+ * - list of most prolific feed
+ */
public function indexAction() {
$statsDAO = FreshRSS_Factory::createStatsDAO();
Minz_View::appendScript(Minz_Url::display('/scripts/flotr2.min.js?' . @filemtime(PUBLIC_PATH . '/scripts/flotr2.min.js')));
@@ -12,6 +26,17 @@ class FreshRSS_stats_Controller extends Minz_ActionController {
$this->view->topFeed = $statsDAO->calculateTopFeed();
}
+ /**
+ * This action handles the idle feed statistic page.
+ *
+ * It displays the list of idle feed for different period. The supported
+ * periods are:
+ * - last year
+ * - last 6 months
+ * - last 3 months
+ * - last month
+ * - last week
+ */
public function idleAction() {
$statsDAO = FreshRSS_Factory::createStatsDAO();
$feeds = $statsDAO->calculateFeedLastDate();
@@ -56,6 +81,18 @@ class FreshRSS_stats_Controller extends Minz_ActionController {
$this->view->idleFeeds = $idleFeeds;
}
+ /**
+ * This action handles the article repartition statistic page.
+ *
+ * It displays the number of article and the average of article for the
+ * following periods:
+ * - hour of the day
+ * - day of the week
+ * - month
+ *
+ * @todo verify that the metrics used here make some sense. Especially
+ * for the average.
+ */
public function repartitionAction() {
$statsDAO = FreshRSS_Factory::createStatsDAO();
$categoryDAO = new FreshRSS_CategoryDAO();
@@ -74,6 +111,11 @@ class FreshRSS_stats_Controller extends Minz_ActionController {
$this->view->averageMonth = $statsDAO->calculateEntryAveragePerFeedPerMonth($id);
}
+ /**
+ * This action is called before every other action in that class. It is
+ * the common boiler plate for every action. It is triggered by the
+ * underlying framework.
+ */
public function firstAction() {
if (!$this->view->loginOk) {
Minz_Error::error(
diff --git a/app/Models/Configuration.php b/app/Models/Configuration.php
index f94d82402..91d2ab846 100644
--- a/app/Models/Configuration.php
+++ b/app/Models/Configuration.php
@@ -124,6 +124,16 @@ class FreshRSS_Configuration {
return $this->available_languages;
}
+ public function remove_query_by_get($get) {
+ $final_queries = array();
+ foreach ($this->queries as $key => $query) {
+ if (empty($query['get']) || $query['get'] !== $get) {
+ $final_queries[$key] = $query;
+ }
+ }
+ $this->_queries($final_queries);
+ }
+
public function _language($value) {
if (!isset($this->available_languages[$value])) {
$value = 'en';
@@ -147,7 +157,7 @@ class FreshRSS_Configuration {
// left blank on purpose
case FreshRSS_Entry::STATE_NOT_READ:
// left blank on purpose
- case FreshRSS_Entry::STATE_NOT_READ_STRICT:
+ case FreshRSS_Entry::STATE_STRICT + FreshRSS_Entry::STATE_NOT_READ:
$this->data['default_view'] = $value;
break;
default:
diff --git a/app/Models/Entry.php b/app/Models/Entry.php
index 5f1c8abc4..9d7dd5dc4 100644
--- a/app/Models/Entry.php
+++ b/app/Models/Entry.php
@@ -6,8 +6,7 @@ class FreshRSS_Entry extends Minz_Model {
const STATE_NOT_READ = 2;
const STATE_FAVORITE = 4;
const STATE_NOT_FAVORITE = 8;
- const STATE_READ_STRICT = 16;
- const STATE_NOT_READ_STRICT = 32;
+ const STATE_STRICT = 16;
private $id = 0;
private $guid;
diff --git a/app/Models/EntryDAO.php b/app/Models/EntryDAO.php
index dee49212d..c1f87ee34 100644
--- a/app/Models/EntryDAO.php
+++ b/app/Models/EntryDAO.php
@@ -333,14 +333,13 @@ class FreshRSS_EntryDAO extends Minz_ModelPdo {
if ($state & FreshRSS_Entry::STATE_NOT_READ) {
if (!($state & FreshRSS_Entry::STATE_READ)) {
$where .= 'AND e1.is_read=0 ';
+ } elseif ($state & FreshRSS_Entry::STATE_STRICT) {
+ $where .= 'AND e1.is_read=0 ';
}
}
elseif ($state & FreshRSS_Entry::STATE_READ) {
$where .= 'AND e1.is_read=1 ';
}
- elseif ($state & FreshRSS_Entry::STATE_NOT_READ_STRICT) {
- $where .= 'AND e1.is_read=0 ';
- }
if ($state & FreshRSS_Entry::STATE_FAVORITE) {
if (!($state & FreshRSS_Entry::STATE_NOT_FAVORITE)) {
$where .= 'AND e1.is_favorite=1 ';
diff --git a/app/Models/StatsDAO.php b/app/Models/StatsDAO.php
index bd4271ba8..40505ab3e 100644
--- a/app/Models/StatsDAO.php
+++ b/app/Models/StatsDAO.php
@@ -209,8 +209,14 @@ SQL;
$date_max = new \DateTime();
$date_max->setTimestamp($res['date_max']);
$interval = $date_max->diff($date_min, true);
+ $interval_in_days = $interval->format('%a');
+ if ($interval_in_days <= 0) {
+ // Surely only one article.
+ // We will return count / (period/period) == count.
+ $interval_in_days = $period;
+ }
- return round($res['count'] / ($interval->format('%a') / ($period)), 2);
+ return round($res['count'] / ($interval_in_days / $period), 2);
}
/**
@@ -309,6 +315,7 @@ SQL;
SELECT MAX(f.id) as id
, MAX(f.name) AS name
, MAX(date) AS last_date
+, COUNT(*) AS nb_articles
FROM {$this->prefix}feed AS f,
{$this->prefix}entry AS e
WHERE f.id = e.id_feed
diff --git a/app/Models/StatsDAOSQLite.php b/app/Models/StatsDAOSQLite.php
index 6cb54ddf6..3b1256de1 100644
--- a/app/Models/StatsDAOSQLite.php
+++ b/app/Models/StatsDAOSQLite.php
@@ -53,6 +53,7 @@ SQL;
$stm->execute();
$res = $stm->fetchAll(PDO::FETCH_NAMED);
+ $repartition = array();
foreach ($res as $value) {
$repartition[(int) $value['period']] = (int) $value['count'];
}
diff --git a/app/Models/Themes.php b/app/Models/Themes.php
index 538eb6554..68fc17a2b 100644
--- a/app/Models/Themes.php
+++ b/app/Models/Themes.php
@@ -96,6 +96,7 @@ class FreshRSS_Themes extends Minz_Model {
'search' => '🔍',
'share' => '♺',
'starred' => '★',
+ 'stats' => '%',
'tag' => '⚐',
'up' => '△',
'view-normal' => '☰',
diff --git a/app/i18n/de.php b/app/i18n/de.php
index 3dc1536de..77fb805fb 100644
--- a/app/i18n/de.php
+++ b/app/i18n/de.php
@@ -15,16 +15,16 @@ return array (
'feed' => 'Feed',
'feeds' => 'Feeds',
'shortcuts' => 'Shortcuts',
- 'about' => '&Uuml;ber',
+ 'about' => 'Über',
'stats' => 'Statistiken',
'your_rss_feeds' => 'Ihre RSS Feeds',
- 'add_rss_feed' => 'RSS-Feed hinzuf&uuml;gen',
+ 'add_rss_feed' => 'RSS-Feed hinzufügen',
'no_rss_feed' => 'Kein RSS Feed',
'import_export_opml' => 'Import / Export (OPML)',
'subscription_management' => 'Abonnementsverwaltung',
- 'main_stream' => 'Haupt-Nachrichtenflu&szlig;',
+ 'main_stream' => 'Haupt-Nachrichtenfluß',
'all_feeds' => 'Alle Feeds',
'favorite_feeds' => 'Favoriten (%d)',
'not_read' => '%d ungelesen',
@@ -42,22 +42,22 @@ return array (
'mark_cat_read' => 'Kategorie als gelesen markieren',
'before_one_day' => 'Vor einem Tag',
'before_one_week' => 'Vor einer Woche',
- 'display' => 'Anzeige',
+ 'display' => 'Anzeige',
'normal_view' => 'Normale Anzeige',
'reader_view' => 'Leseanzeige-Modus',
'global_view' => 'Globale Anzeige',
- 'rss_view' => 'RSS-Feed',
+ 'rss_view' => 'RSS-Feed',
'show_all_articles' => 'zeige alle Artikel',
'show_not_reads' => 'zeige nicht gelesene',
- 'show_read' => 'zeige nur gelesene',
+ 'show_read' => 'zeige nur gelesene',
'show_favorite' => 'Favoriten anzeigen',
- 'older_first' => '&Auml;lteste zuerst',
+ 'older_first' => 'Älteste zuerst',
'newer_first' => 'Neuere zuerst',
// Pagination
'first' => 'Erste',
'previous' => 'Vorherige',
- 'next' => 'N&auml;chste',
+ 'next' => 'Nächste',
'last' => 'Letzte',
// CONTROLLERS
@@ -67,7 +67,7 @@ return array (
'access_denied' => 'Sie haben nicht die Berechtigung, diese Seite aufzurufen',
'page_not_found' => 'Sie suchen nach einer Seite, die es nicht gibt',
'error_occurred' => 'Es gab einen Fehler',
- 'error_occurred_update' => 'Es wurde nichts ge&auml;ndert',
+ 'error_occurred_update' => 'Es wurde nichts geändert',
'default_category' => 'Unkategorisiert',
'categories_updated' => 'Kategorien wurden aktualisiert',
@@ -75,67 +75,67 @@ return array (
'feed_updated' => 'Der Feed wurde aktualisiert',
'rss_feed_management' => 'Verwaltung der RSS Feeds',
'configuration_updated' => 'Die Konfiguration wurde aktualisiert',
- 'sharing_management' => 'Verwaltung der Optionen f&uuml;r das Teilen',
- 'bad_opml_file' => 'Ihre OPML-Datei ist ung&uuml;ltig',
+ 'sharing_management' => 'Verwaltung der Optionen für das Teilen',
+ 'bad_opml_file' => 'Ihre OPML-Datei ist ungültig',
'shortcuts_updated' => 'Shortcuts wurden aktualisiert',
'shortcuts_management' => 'Verwaltung der Shortcuts',
'shortcuts_navigation' => 'Navigation',
- 'shortcuts_navigation_help' => 'Mit der "Shift" Taste gelten die Navigations-Shortcuts f&uuml;r Feeds.<br/>Mit der "Alt" Taste gelten die Navigations-Shortcuts f&uuml;r Kategorien.',
+ 'shortcuts_navigation_help' => 'Mit der "Shift" Taste gelten die Navigations-Shortcuts für Feeds.<br/>Mit der "Alt" Taste gelten die Navigations-Shortcuts für Kategorien.',
'shortcuts_article_action' => 'Artikelaktionen',
'shortcuts_other_action' => 'Andere Aktionen',
'feeds_marked_read' => 'Die Feeds wurden als gelesen markiert',
- 'updated' => 'Die &Auml;nderungen wurden aktualisiert',
+ 'updated' => 'Die Änderungen wurden aktualisiert',
'already_subscribed' => 'Sie haben bereits <em>%s</em> abonniert',
- 'feed_added' => 'Der RSS Feed <em>%s</em> wurde hinzugef&uuml;gt',
- 'feed_not_added' => '<em>%s</em> konnte nicht hinzugef&uuml;gt werden',
- 'internal_problem_feed' => 'Der RSS Feed konnte nicht hinzugef&uuml;gt werden. &uuml;berpr&uuml;fen Sie die Protokolldateien von FressRSS f&uuml;r weitere Informationen.',
- 'invalid_url' => 'URL <em>%s</em> ist ung&uuml;ltig',
+ 'feed_added' => 'Der RSS Feed <em>%s</em> wurde hinzugefügt',
+ 'feed_not_added' => '<em>%s</em> konnte nicht hinzugefügt werden',
+ 'internal_problem_feed' => 'Der RSS Feed konnte nicht hinzugefügt werden. überprüfen Sie die Protokolldateien von FressRSS für weitere Informationen.',
+ 'invalid_url' => 'URL <em>%s</em> ist ungültig',
'feed_actualized' => '<em>%s</em> wurde aktualisiert',
'n_feeds_actualized' => '%d Feeds wurden aktualisiert',
'feeds_actualized' => 'RSS Feeds wurden aktualisiert',
'no_feed_actualized' => 'Es wurden keine RSS Feeds aktualisiert',
- 'n_entries_deleted' => '%d Artikel wurden gel&ouml;scht',
+ 'n_entries_deleted' => '%d Artikel wurden gelöscht',
'feeds_imported_with_errors' => 'Ihre Feeds wurden importiert, es gab aber einige Fehler',
'feeds_imported' => 'Ihre Feeds wurden importiert und werden jetzt aktualisiert',
'category_emptied' => 'Die Kategorie wurde geleert',
- 'feed_deleted' => 'Der Feed wurde gel&ouml;scht',
- 'feed_validator' => '&Üuml;berpr&uuml;fen Sie die G&uuml;ltigkeit des Feeds',
+ 'feed_deleted' => 'Der Feed wurde gelöscht',
+ 'feed_validator' => 'Überprüfen Sie die Gültigkeit des Feeds',
'optimization_complete' => 'Die Optimierung ist beendet',
'your_rss_feeds' => 'Ihre RSS Feeds',
'your_favorites' => 'Ihre Favoriten',
- 'public' => '&Ouml;ffentlich',
- 'invalid_login' => 'Das Login ist ung&uuml;ltig',
+ 'public' => 'Öffentlich',
+ 'invalid_login' => 'Das Login ist ungültig',
// VIEWS
'save' => 'Speichern',
- 'delete' => 'L&ouml;schen',
+ 'delete' => 'Löschen',
'cancel' => 'Abbrechen',
- 'back_to_rss_feeds' => '← Zur&uuml;ck zu den RSS Feeds gehen',
- 'feeds_moved_category_deleted' => 'Wenn Sie eine Kategorie l&ouml;schen, werden deren Feeds automatisch in die Kategorie <em>%s</em> eingef&uuml;gt.',
+ 'back_to_rss_feeds' => '← Zurück zu den RSS Feeds gehen',
+ 'feeds_moved_category_deleted' => 'Wenn Sie eine Kategorie löschen, werden deren Feeds automatisch in die Kategorie <em>%s</em> eingefügt.',
'category_number' => 'Kategorie n°%d',
'ask_empty' => 'Leeren?',
'number_feeds' => '%d Feeds',
- 'can_not_be_deleted' => 'Kann nicht gel&ouml;scht werden',
- 'add_category' => 'F&uuml;ge eine Kategorie hinzu',
+ 'can_not_be_deleted' => 'Kann nicht gelöscht werden',
+ 'add_category' => 'Füge eine Kategorie hinzu',
'new_category' => 'Neue Kategorie',
- 'javascript_for_shortcuts' => 'JavaScript muss erm&ouml;glicht werden, wenn Shortcuts verwendet werden sollen',
- 'javascript_should_be_activated'=> 'JavaScript muss erm&ouml;glicht werden',
+ 'javascript_for_shortcuts' => 'JavaScript muss ermöglicht werden, wenn Shortcuts verwendet werden sollen',
+ 'javascript_should_be_activated'=> 'JavaScript muss ermöglicht werden',
'shift_for_all_read' => '+ <code>shift</code> um alle Artikel als gelesen zu markieren',
'see_on_website' => 'Auf der Originalwebseite anschauen',
- 'next_article' => 'Zum n&auml;chsten Artikel springen',
+ 'next_article' => 'Zum nächsten Artikel springen',
'last_article' => 'Zum letzten Artikel springen',
'previous_article' => 'Zum vorherigen Artikel springen',
'first_article' => 'Zum ersten Artikel springen',
- 'next_page' => 'Zur n&auml;chsten Seite springen',
+ 'next_page' => 'Zur nächsten Seite springen',
'previous_page' => 'Zur vorherigen Seite springen',
'collapse_article' => 'Zusammenfalten',
'auto_share' => 'Teilen',
- 'auto_share_help' => 'Wenn es nur eine Option zum Teilen gibt, wird die verwendet. Ansonsten werden die Optionen &uuml;ber die Nummer ausgew&auml;hlt.',
+ 'auto_share_help' => 'Wenn es nur eine Option zum Teilen gibt, wird die verwendet. Ansonsten werden die Optionen über die Nummer ausgewählt.',
'file_to_import' => 'Datei zum importieren',
'import' => 'Import',
@@ -150,75 +150,75 @@ return array (
'website_url' => 'Webseiten-Adresse URL',
'feed_url' => 'Feed URL',
'articles' => 'Artikel',
- 'number_articles' => 'Anzahl der Artikel',
+ 'number_articles' => '%d Artikel',
'by_feed' => 'per Feed',
'by_default' => 'Als Vorgabe',
'keep_history' => 'Kleinste Anzahl der Artikel, die behalten werden',
'categorize' => 'In einer Kategorie speichern',
- 'truncate' => 'Alle Artikel l&ouml;schen',
+ 'truncate' => 'Alle Artikel löschen',
'advanced' => 'Erweitert',
'show_in_all_flux' => 'Im Hauptstrom anzeigen',
'yes' => 'Ja',
'no' => 'Nein',
'css_path_on_website' => 'Pfad zur CSS-Datei des Artikels auf der Original Webseite',
- 'retrieve_truncated_feeds' => 'Gek&uuml;rzte RSS Feeds abrufen (Achtung, ben&ouml;tigt mehr Zeit!)',
+ 'retrieve_truncated_feeds' => 'Gekürzte RSS Feeds abrufen (Achtung, benötigt mehr Zeit!)',
'http_authentication' => 'HTTP Authentifizierung',
'http_username' => 'HTTP Nutzername',
'http_password' => 'HTTP Passwort',
'blank_to_disable' => 'Zum Ausschalten frei lassen',
'not_yet_implemented' => 'Noch nicht implementiert',
- 'access_protected_feeds' => 'Die Verbindung erlaubt Zugriff zu HTTP-gesch&uuml;tzten RSS Feeds',
- 'no_selected_feed' => 'Kein Feed ausgew&auml;hlt.',
- 'think_to_add' => '<a href="./?c=configure&amp;a=feed">Sie k&ouml;nnen Feeds hinzuf&uuml;gen</a>.',
+ 'access_protected_feeds' => 'Die Verbindung erlaubt Zugriff zu HTTP-geschützten RSS Feeds',
+ 'no_selected_feed' => 'Kein Feed ausgewählt.',
+ 'think_to_add' => 'Sie können Feeds hinzufügen.',
'current_user' => 'Aktuelle Nutzung',
'default_user' => 'Nutzername des Standardnutzers <small>(maximal 16 Zeichen - alphanumerisch)</small>',
- 'password_form' => 'Passwort<br /><small>(f&uuml;r die Anmeldemethode per Webformular)</small>',
- 'persona_connection_email' => 'Login E-Mail Adresse<br /><small>(f&uuml;r <a href="https://persona.org/" rel="external">Mozilla Persona</a>)</small>',
+ 'password_form' => 'Passwort<br /><small>(für die Anmeldemethode per Webformular)</small>',
+ 'persona_connection_email' => 'Login E-Mail Adresse<br /><small>(für <a href="https://persona.org/" rel="external">Mozilla Persona</a>)</small>',
'allow_anonymous' => 'Anonymes lesen der Artikel des Standardnutzers (%s) wird erlaubt',
'allow_anonymous_refresh' => 'Aktualisieren der Artikel wird anonymen Nutzern erlaubt',
'auth_token' => 'Authentifizierungs-Token',
- 'explain_token' => 'Erlaube den Zugriff auf die RSS-Ausgabe des Standardnutzers ohne Authentifizierung.<br /><kbd>%s?output=rss&token=%s</kbd>',
+ 'explain_token' => 'Erlaube den Zugriff auf die RSS-Ausgabe des Standardnutzers ohne Authentifizierung.<br /><kbd>%s?output=rss&amp;token=%s</kbd>',
'login_configuration' => 'Login',
'is_admin' => 'ist Administrator',
'auth_type' => 'Authentifizierungsmethode',
- 'auth_none' => 'Keine (gef&auml;hrlich)',
- 'auth_form' => 'Webformular (traditionell, JavaScript wird ben&ouml;tigt)',
- 'http_auth' => 'HTTP (mit HTTPS f&uuml;r erfahrene Nutzer)',
- 'auth_persona' => 'Mozilla Persona (modern, JavaScript wird ben&ouml;tigt)',
+ 'auth_none' => 'Keine (gefährlich)',
+ 'auth_form' => 'Webformular (traditionell, JavaScript wird benötigt)',
+ 'http_auth' => 'HTTP (mit HTTPS für erfahrene Nutzer)',
+ 'auth_persona' => 'Mozilla Persona (modern, JavaScript wird benötigt)',
'users_list' => 'Liste der Nutzer',
'create_user' => 'Neuen Nutzer erstellen',
'username' => 'Nutzername',
'password' => 'Passwort',
'create' => 'Erstellen',
'user_created' => 'Nutzer %s wurde erstellt',
- 'user_deleted' => 'Nutzer %s wurde gel&ouml;scht',
+ 'user_deleted' => 'Nutzer %s wurde gelöscht',
'language' => 'Sprache',
'month' => 'Monate',
'archiving_configuration' => 'Archivieren',
'delete_articles_every' => 'Entfernen von Artikeln nach',
'purge_now' => 'Jetzt bereinigen',
- 'purge_completed' => 'Die Bereinigung ist abgeschlossen (%d Artikel wurden gel&ouml;scht)',
- 'archiving_configuration_help' => 'Es gibt weitere Optionen bei den Einstellungen der individuellen Nachrichtenstr&ouml;me',
+ 'purge_completed' => 'Die Bereinigung ist abgeschlossen (%d Artikel wurden gelöscht)',
+ 'archiving_configuration_help' => 'Es gibt weitere Optionen bei den Einstellungen der individuellen Nachrichtenströme',
'reading_configuration' => 'Lesen',
'articles_per_page' => 'Anzahl der Artikel pro Seite',
'default_view' => 'Standard-Ansicht',
'sort_order' => 'Sortierreihenfolge',
- 'auto_load_more' => 'Die n&auml;chsten Artikel am Seitenende laden',
+ 'auto_load_more' => 'Die nächsten Artikel am Seitenende laden',
'display_articles_unfolded' => 'Die Artikel als Standard zusammen gefaltet anzeigen',
'after_onread' => 'Nach “als gelesen markieren”',
- 'jump_next' => 'springe zum n&auml;chsten ungelesenen Geschwisterelement (Feed oder Kategorie)',
+ 'jump_next' => 'springe zum nächsten ungelesenen Geschwisterelement (Feed oder Kategorie)',
'reading_icons' => 'Lese Symbol',
'top_line' => 'Kopfzeile',
'bottom_line' => 'Fusszeile',
'html5_notif_timeout' => 'HTML5 notification timeout',
'seconds_(0_means_no_timeout)' => 'seconds (0 means no timeout)',
- 'img_with_lazyload' => 'Verwende die "tr&auml;ge laden" Methode zum laden von Bildern',
+ 'img_with_lazyload' => 'Verwende die "träge laden" Methode zum laden von Bildern',
'auto_read_when' => 'Artikel als gelesen markieren…',
- 'article_selected' => 'wenn der Artikel ausgew&auml;hlt ist',
- 'article_open_on_website' => 'wenn der Artikel auf der Originalwebseite ge&ouml;ffnet ist',
- 'scroll' => 'w&auml;hrend des Seiten-Scrollens',
+ 'article_selected' => 'wenn der Artikel ausgewählt ist',
+ 'article_open_on_website' => 'wenn der Artikel auf der Originalwebseite geöffnet ist',
+ 'scroll' => 'während des Seiten-Scrollens',
'upon_reception' => 'beim Empfang des Artikels',
'your_shaarli' => 'Ihr Shaarli',
'your_wallabag' => 'Ihr wallabag',
@@ -227,7 +227,7 @@ return array (
'share' => 'teile',
'by_email' => 'Per E-Mail',
'optimize_bdd' => 'Datenbank optimieren',
- 'optimize_todo_sometimes' => 'Sollte gelegentlich gemacht werden, um die Gr&ouml;ße der Datenbank zu reduzieren',
+ 'optimize_todo_sometimes' => 'Sollte gelegentlich gemacht werden, um die Größe der Datenbank zu reduzieren',
'theme' => 'Thema',
'more_information' => 'Weitere Informationen',
'activate_sharing' => 'Teilen aktivieren',
@@ -243,7 +243,7 @@ return array (
'article' => 'Artikel',
'title' => 'Titel',
'author' => 'Autor',
- 'publication_date' => 'Datum der Ver&ouml;ffentlichung',
+ 'publication_date' => 'Datum der Veröffentlichung',
'by' => 'von',
'load_more' => 'Weitere Artikel laden',
@@ -262,7 +262,7 @@ return array (
'related_tags' => 'Verwandte tags',
'no_feed_to_display' => 'Es gibt keinen Artikel zum anzeigen.',
- 'about_freshrss' => '&Uuml;ber FreshRSS',
+ 'about_freshrss' => 'Über FreshRSS',
'project_website' => 'Projekt Webseite',
'lead_developer' => 'Hauptentwickler',
'website' => 'Webseite',
@@ -280,14 +280,14 @@ return array (
'clear_logs' => 'Protokolldateien leeren',
'forbidden_access' => 'Der Zugriff ist verboten!',
- 'login_required' => 'Das Login ist n&ouml;tig:',
+ 'login_required' => 'Das Login ist nötig:',
- 'confirm_action' => 'Sind Sie sicher, dass Sie diese Aktion durchf&uuml;hren wollen? Die Aktion kann nicht abgebrochen werden!',
+ 'confirm_action' => 'Sind Sie sicher, dass Sie diese Aktion durchführen wollen? Die Aktion kann nicht abgebrochen werden!',
// DATE
'january' => 'januar',
'february' => 'februar',
- 'march' => 'm&auml;rz',
+ 'march' => 'märz',
'april' => 'april',
'may' => 'mai',
'june' => 'juni',
@@ -319,10 +319,10 @@ return array (
'status_unread' => 'Ungelesen',
'status_total' => 'Gesamt',
- 'stats_entry_repartition' => 'Verteilung der Eintr&auml;ge',
- 'stats_entry_per_day' => 'Eintr&auml;ge pro Tag (w&auml;hrend der letzten 30 Tage)',
+ 'stats_entry_repartition' => 'Verteilung der Einträge',
+ 'stats_entry_per_day' => 'Einträge pro Tag (während der letzten 30 Tage)',
'stats_feed_per_category' => 'Feeds pro Kategorie',
- 'stats_entry_per_category' => 'Eintr&auml;ge pro Kategorie',
+ 'stats_entry_per_category' => 'Einträge pro Kategorie',
'stats_top_feed' => 'Top 10 Feeds',
- 'stats_entry_count' => 'Z&auml;hler f&uuml;r Eintr&auml;ge',
+ 'stats_entry_count' => 'Zähler für Einträge',
);
diff --git a/app/i18n/en.php b/app/i18n/en.php
index 8598e61cb..1ceb7b1fa 100644
--- a/app/i18n/en.php
+++ b/app/i18n/en.php
@@ -5,7 +5,7 @@ return array (
'login' => 'Login',
'keep_logged_in' => 'Keep me logged in <small>(1 month)</small>',
'login_with_persona' => 'Login with Persona',
- 'login_persona_problem' => 'Problem of connection with Persona?',
+ 'login_persona_problem' => 'Connection problem with Persona?',
'logout' => 'Logout',
'search' => 'Search words or #tags',
'search_short' => 'Search',
@@ -43,9 +43,11 @@ return array (
'query_state_15' => 'Display all articles',
'query_number' => 'Query n°%d',
'add_query' => 'Add a query',
+ 'query_created' => 'Query "%s" has been created.',
'no_query' => 'You haven’t created any user query yet.',
'query_filter' => 'Filter applied:',
'no_query_filter' => 'No filter',
+ 'query_deprecated' => 'This query is no longer valid. The referenced category or feed has been deleted.',
'about' => 'About',
'stats' => 'Statistics',
'stats_idle' => 'Idle feeds',
@@ -113,7 +115,7 @@ return array (
'access_denied' => 'You don’t have permission to access this page',
'page_not_found' => 'You are looking for a page which doesn’t exist',
'error_occurred' => 'An error occurred',
- 'error_occurred_update' => 'Nothing was changed',
+ 'error_occurred_update' => 'Nothing was changed',
'default_category' => 'Uncategorized',
'categories_updated' => 'Categories have been updated',
@@ -213,7 +215,7 @@ return array (
'website_url' => 'Website URL',
'feed_url' => 'Feed URL',
'articles' => 'articles',
- 'number_articles' => 'Number of articles',
+ 'number_articles' => '%d articles',
'by_feed' => 'by feed',
'by_default' => 'By default',
'keep_history' => 'Minimum number of articles to keep',
@@ -235,7 +237,7 @@ return array (
'not_yet_implemented' => 'Not yet implemented',
'access_protected_feeds' => 'Connection allows to access HTTP protected RSS feeds',
'no_selected_feed' => 'No feed selected.',
- 'think_to_add' => '<a href="./?c=configure&amp;a=feed">You may add some feeds</a>.',
+ 'think_to_add' => 'You may add some feeds.',
'current_user' => 'Current user',
'default_user' => 'Username of the default user <small>(maximum 16 alphanumeric characters)</small>',
@@ -247,7 +249,7 @@ return array (
'unsafe_autologin' => 'Allow unsafe automatic login using the format: ',
'api_enabled' => 'Allow <abbr>API</abbr> access <small>(required for mobile apps)</small>',
'auth_token' => 'Authentication token',
- 'explain_token' => 'Allows to access RSS output of the default user without authentication.<br /><kbd>%s?output=rss&token=%s</kbd>',
+ 'explain_token' => 'Allows to access RSS output of the default user without authentication.<br /><kbd>%s?output=rss&amp;token=%s</kbd>',
'login_configuration' => 'Login',
'is_admin' => 'is administrator',
'auth_type' => 'Authentication method',
@@ -267,21 +269,21 @@ return array (
'language' => 'Language',
'month' => 'months',
'archiving_configuration' => 'Archiving',
- 'delete_articles_every' => 'Remove articles after',
+ 'delete_articles_every' => 'Remove articles after',
'purge_now' => 'Purge now',
'purge_completed' => 'Purge completed (%d articles deleted)',
'archiving_configuration_help' => 'More options are available in the individual stream settings',
'reading_configuration' => 'Reading',
'display_configuration' => 'Display',
'articles_per_page' => 'Number of articles per page',
- 'number_divided_when_unfolded' => 'Divided by 2 during loading of unfolded articles.',
+ 'number_divided_when_reader' => 'Divided by 2 in the reading view.',
'default_view' => 'Default view',
'articles_to_display' => 'Articles to display',
'sort_order' => 'Sort order',
'auto_load_more' => 'Load next articles at the page bottom',
'display_articles_unfolded' => 'Show articles unfolded by default',
'display_categories_unfolded' => 'Show categories folded by default',
- 'hide_read_feeds' => 'Hide categories &amp; feeds with no unread article (only in “unread articles” display mode)',
+ 'hide_read_feeds' => 'Hide categories &amp; feeds with no unread article (does not work with “Show all articles” configuration)',
'after_onread' => 'After “mark all as read”,',
'jump_next' => 'jump to next unread sibling (feed or category)',
'article_icons' => 'Article icons',
@@ -366,6 +368,7 @@ return array (
'login_required' => 'Login required:',
'confirm_action' => 'Are you sure you want to perform this action? It cannot be cancelled!',
+ 'confirm_action_feed_cat' => 'Are you sure you want to perform this action? You may lost related favorites and user queries. It cannot be cancelled!',
'notif_title_new_articles' => 'FreshRSS: new articles!',
'notif_body_new_articles' => 'There are \d new articles to read on FreshRSS.',
@@ -429,6 +432,7 @@ return array (
'stats_entry_per_category' => 'Entries per category',
'stats_top_feed' => 'Top ten feeds',
'stats_entry_count' => 'Entry count',
+ 'stats_no_idle' => 'There is no idle feed!',
'update' => 'Update',
'update_system' => 'Update system',
@@ -442,8 +446,8 @@ return array (
'update_finished' => 'Update completed!',
'auth_reset' => 'Authentication reset',
- 'auth_will_reset' => 'Authentication system will be reseted: form will be used instead of Persona.',
- 'auth_not_persona' => 'Only Persona system can be reseted.',
+ 'auth_will_reset' => 'Authentication system will be reset: a form will be used instead of Persona.',
+ 'auth_not_persona' => 'Only Persona system can be reset.',
'auth_no_password_set' => 'Administrator password hasn’t been set. This feature isn’t available.',
'auth_form_set' => 'Form is now your default authentication system.',
'auth_form_not_set' => 'A problem occured during authentication system configuration. Please retry later.',
diff --git a/app/i18n/fr.php b/app/i18n/fr.php
index 4af819cac..b0fbf15ae 100644
--- a/app/i18n/fr.php
+++ b/app/i18n/fr.php
@@ -43,9 +43,11 @@ return array (
'query_state_15' => 'Afficher tous les articles',
'query_number' => 'Filtre n°%d',
'add_query' => 'Créer un filtre',
+ 'query_created' => 'Le filtre "%s" a bien été créé.',
'no_query' => 'Vous n’avez pas encore créé de filtre.',
'query_filter' => 'Filtres appliqués :',
'no_query_filter' => 'Aucun filtre appliqué',
+ 'query_deprecated' => 'Ce filtre n’est plus valide. La catégorie ou le flux concerné a été supprimé.',
'about' => 'À propos',
'stats' => 'Statistiques',
'stats_idle' => 'Flux inactifs',
@@ -55,11 +57,11 @@ return array (
'stats_entry_per_day_of_week' => 'Par jour de la semaine',
'stats_entry_per_month' => 'Par mois',
- 'last_week' => 'La dernière semaine',
- 'last_month' => 'Le dernier mois',
- 'last_3_month' => 'Les derniers trois mois',
- 'last_6_month' => 'Les derniers six mois',
- 'last_year' => 'La dernière année',
+ 'last_week' => 'Depuis la semaine dernière',
+ 'last_month' => 'Depuis le mois dernier',
+ 'last_3_month' => 'Depuis les trois derniers mois',
+ 'last_6_month' => 'Depuis les six derniers mois',
+ 'last_year' => 'Depuis l’année dernière',
'your_rss_feeds' => 'Vos flux RSS',
'add_rss_feed' => 'Ajouter un flux RSS',
@@ -213,7 +215,7 @@ return array (
'website_url' => 'URL du site',
'feed_url' => 'URL du flux',
'articles' => 'articles',
- 'number_articles' => 'Nombre d’articles',
+ 'number_articles' => '%d articles',
'by_feed' => 'par flux',
'by_default' => 'Par défaut',
'keep_history' => 'Nombre minimum d’articles à conserver',
@@ -235,7 +237,7 @@ return array (
'not_yet_implemented' => 'Pas encore implémenté',
'access_protected_feeds' => 'La connexion permet d’accéder aux flux protégés par une authentification HTTP.',
'no_selected_feed' => 'Aucun flux sélectionné.',
- 'think_to_add' => '<a href="./?c=configure&amp;a=feed">Vous pouvez ajouter des flux</a>.',
+ 'think_to_add' => 'Vous pouvez ajouter des flux.',
'current_user' => 'Utilisateur actuel',
'password_form' => 'Mot de passe<br /><small>(pour connexion par formulaire)</small>',
@@ -247,7 +249,7 @@ return array (
'unsafe_autologin' => 'Autoriser les connexions automatiques non-sûres au format : ',
'api_enabled' => 'Autoriser l’accès par <abbr>API</abbr> <small>(nécessaire pour les applis mobiles)</small>',
'auth_token' => 'Jeton d’identification',
- 'explain_token' => 'Permet d’accéder à la sortie RSS de l’utilisateur par défaut sans besoin de s’authentifier.<br /><kbd>%s?output=rss&token=%s</kbd>',
+ 'explain_token' => 'Permet d’accéder à la sortie RSS de l’utilisateur par défaut sans besoin de s’authentifier.<br /><kbd>%s?output=rss&amp;token=%s</kbd>',
'login_configuration' => 'Identification',
'is_admin' => 'est administrateur',
'auth_type' => 'Méthode d’authentification',
@@ -274,20 +276,20 @@ return array (
'reading_configuration' => 'Lecture',
'display_configuration' => 'Affichage',
'articles_per_page' => 'Nombre d’articles par page',
- 'number_divided_when_unfolded' => 'Divisé par 2 lors du chargement d’articles dépliés.',
+ 'number_divided_when_reader' => 'Divisé par 2 dans la vue de lecture.',
'default_view' => 'Vue par défaut',
'articles_to_display' => 'Articles à afficher',
'sort_order' => 'Ordre de tri',
'auto_load_more' => 'Charger les articles suivants en bas de page',
'display_articles_unfolded' => 'Afficher les articles dépliés par défaut',
'display_categories_unfolded' => 'Afficher les catégories pliées par défaut',
- 'hide_read_feeds' => 'Cacher les catégories &amp; flux sans article non-lu (uniquement en affichage “articles non lus”)',
+ 'hide_read_feeds' => 'Cacher les catégories &amp; flux sans article non-lu (ne fonctionne pas avec la configuration “Afficher tous les articles”)',
'after_onread' => 'Après “marquer tout comme lu”,',
'jump_next' => 'sauter au prochain voisin non lu (flux ou catégorie)',
'article_icons' => 'Icônes d’article',
'top_line' => 'Ligne du haut',
'bottom_line' => 'Ligne du bas',
- 'html5_notif_timeout' => 'Temps d\'affichage de la notification HTML5',
+ 'html5_notif_timeout' => 'Temps d’affichage de la notification HTML5',
'seconds_(0_means_no_timeout)' => 'secondes (0 signifie aucun timeout ) ',
'img_with_lazyload' => 'Utiliser le mode “chargement différé” pour les images',
'sticky_post' => 'Aligner l’article en haut quand il est ouvert',
@@ -366,6 +368,7 @@ return array (
'login_required' => 'Accès protégé par mot de passe :',
'confirm_action' => 'Êtes-vous sûr(e) de vouloir continuer ? Cette action ne peut être annulée !',
+ 'confirm_action_feed_cat' => 'Êtes-vous sûr(e) de vouloir continuer ? Vous pourriez perdre les favoris et les filtres associés. Cette action ne peut être annulée !',
'notif_title_new_articles' => 'FreshRSS : nouveaux articles !',
'notif_body_new_articles' => 'Il y a \d nouveaux articles à lire sur FreshRSS.',
@@ -429,6 +432,7 @@ return array (
'stats_entry_per_category' => 'Articles par catégorie',
'stats_top_feed' => 'Les dix plus gros flux',
'stats_entry_count' => 'Nombre d’articles',
+ 'stats_no_idle' => 'Il n’y a aucun flux inactif !',
'update' => 'Mise à jour',
'update_system' => 'Système de mise à jour',
@@ -441,9 +445,9 @@ return array (
'update_problem' => 'La mise à jour a rencontré un problème : %s',
'update_finished' => 'La mise à jour est terminée !',
- 'auth_reset' => 'Reset de l’authentification',
- 'auth_will_reset' => 'Le système d’authentification va être remis à zéro : le formulaire sera utilisé à la place de Persona.',
- 'auth_not_persona' => 'Seul le système d’authentification Persona peut être remis à zéro.',
+ 'auth_reset' => 'Réinitialisation de l’authentification',
+ 'auth_will_reset' => 'Le système d’authentification va être réinitialisé : un formulaire sera utilisé à la place de Persona.',
+ 'auth_not_persona' => 'Seul le système d’authentification Persona peut être réinitialisé.',
'auth_no_password_set' => 'Aucun mot de passe administrateur n’a été précisé. Cette fonctionnalité n’est pas disponible.',
'auth_form_set' => 'Le formulaire est désormais votre système d’authentification.',
'auth_form_not_set' => 'Un problème est survenu lors de la configuration de votre système d’authentification. Veuillez réessayer plus tard.',
diff --git a/app/layout/aside_flux.phtml b/app/layout/aside_flux.phtml
index 9688a3273..76f53e8dc 100644
--- a/app/layout/aside_flux.phtml
+++ b/app/layout/aside_flux.phtml
@@ -3,6 +3,8 @@
<ul class="categories">
<?php if ($this->loginOk) { ?>
+ <form id="mark-read-aside" method="post" style="display: none"></form>
+
<li>
<div class="stick configure-feeds">
<a class="btn btn-important" href="<?php echo _url ('configure', 'feed'); ?>"><?php echo Minz_Translate::t ('subscription_management'); ?></a>
@@ -87,7 +89,13 @@
<li class="separator"></li>
<li class="item"><a href="<?php echo _url ('configure', 'feed', 'id', '!!!!!!'); ?>"><?php echo Minz_Translate::t ('administration'); ?></a></li>
<li class="item"><a href="<?php echo _url ('feed', 'actualize', 'id', '!!!!!!'); ?>"><?php echo Minz_Translate::t ('actualize'); ?></a></li>
- <li class="item"><a href="<?php echo _url ('entry', 'read', 'get', 'f_!!!!!!'); ?>"><?php echo Minz_Translate::t ('mark_read'); ?></a></li>
+ <li class="item">
+ <?php $confirm = $this->conf->reading_confirm ? 'confirm' : ''; ?>
+ <button class="read_all as-link <?php echo $confirm; ?>"
+ form="mark-read-aside"
+ formaction="<?php echo _url('entry', 'read', 'get', 'f_!!!!!!'); ?>"
+ type="submit"><?php echo _t('mark_read'); ?></button>
+ </li>
<?php } ?>
</ul>
</script>
diff --git a/app/layout/nav_menu.phtml b/app/layout/nav_menu.phtml
index 2a09b0c12..a9e6614e7 100644
--- a/app/layout/nav_menu.phtml
+++ b/app/layout/nav_menu.phtml
@@ -49,7 +49,7 @@
</a>
<?php
- if ($this->state & FreshRSS_Entry::STATE_FAVORITE) {
+ if ($this->state & FreshRSS_Entry::STATE_FAVORITE || $this->get_c == 's') {
$url_state['params']['state'] = $this->state & ~FreshRSS_Entry::STATE_FAVORITE;
$checked = 'true';
$class = 'active';
@@ -93,7 +93,10 @@
<ul class="dropdown-menu">
<li class="dropdown-close"><a href="#close">❌</a></li>
- <li class="dropdown-header"><?php echo _t('queries'); ?> <a class="no-mobile" href="<?php echo _url('configure', 'queries'); ?>"><?php echo _i('configure'); ?></a></li>
+ <li class="dropdown-header">
+ <?php echo _t('queries'); ?>
+ <a class="no-mobile" href="<?php echo _url('configure', 'queries'); ?>"><?php echo _i('configure'); ?></a>
+ </li>
<?php foreach ($this->conf->queries as $query) { ?>
<li class="item query">
@@ -184,12 +187,12 @@
Minz_Session::_param('markReadUrl', $markReadUrl);
?>
- <form id="mark-read" method="post" style="display: none"></form>
+ <form id="mark-read-menu" method="post" style="display: none"></form>
<div class="stick" id="nav_menu_read_all">
<?php $confirm = $this->conf->reading_confirm ? 'confirm' : ''; ?>
<button class="read_all btn <?php echo $confirm; ?>"
- form="mark-read"
+ form="mark-read-menu"
formaction="<?php echo $markReadUrl; ?>"
type="submit"><?php echo _t('mark_read'); ?></button>
@@ -202,7 +205,7 @@
<li class="item">
<button class="as-link <?php echo $confirm; ?>"
- form="mark-read"
+ form="mark-read-menu"
formaction="<?php echo $markReadUrl; ?>"
type="submit"><?php echo $string_mark; ?></button>
</li>
@@ -215,13 +218,13 @@
?>
<li class="item">
<button class="as-link <?php echo $confirm; ?>"
- form="mark-read"
+ form="mark-read-menu"
formaction="<?php echo Minz_Url::display($mark_before_today); ?>"
type="submit"><?php echo _t('before_one_day'); ?></button>
</li>
<li class="item">
<button class="as-link <?php echo $confirm; ?>"
- form="mark-read"
+ form="mark-read-menu"
formaction="<?php echo Minz_Url::display($mark_before_one_week); ?>"
type="submit"><?php echo _t('before_one_week'); ?></button>
</li>
diff --git a/app/views/configure/categorize.phtml b/app/views/configure/categorize.phtml
index 2f0e554ca..23d1c9fa1 100644
--- a/app/views/configure/categorize.phtml
+++ b/app/views/configure/categorize.phtml
@@ -21,7 +21,10 @@
<a class="btn" href="<?php echo _url('index', 'index', 'get', 'c_' . $cat->id ()); ?>">
<?php echo _i('link'); ?>
</a>
- <button type="submit" class="btn btn-attention confirm" formaction="<?php echo _url ('feed', 'delete', 'id', $cat->id (), 'type', 'category'); ?>"><?php echo Minz_Translate::t ('ask_empty'); ?></button>
+ <button formaction="<?php echo _url('feed', 'delete', 'id', $cat->id (), 'type', 'category'); ?>"
+ class="btn btn-attention confirm"
+ data-str-confirm="<?php echo _t('confirm_action_feed_cat'); ?>"
+ type="submit"><?php echo _t('ask_empty'); ?></button>
<?php } ?>
</div>
(<?php echo Minz_Translate::t ('number_feeds', $cat->nbFeed ()); ?>)
diff --git a/app/views/configure/feed.phtml b/app/views/configure/feed.phtml
index a8dd9a8cb..e96a28739 100644
--- a/app/views/configure/feed.phtml
+++ b/app/views/configure/feed.phtml
@@ -70,27 +70,33 @@
</label>
</div>
</div>
+ <div class="form-group">
+ <div class="group-controls">
+ <a href="<?php echo _url('stats', 'repartition', 'id', $this->flux->id()); ?>">
+ <?php echo _i('stats'); ?> <?php echo _t('stats'); ?>
+ </a>
+ </div>
+ </div>
<div class="form-group form-actions">
<div class="group-controls">
- <button class="btn btn-important"><?php echo Minz_Translate::t ('save'); ?></button>
- <button class="btn btn-attention confirm" formmethod="post" formaction="<?php echo Minz_Url::display (array ('c' => 'feed', 'a' => 'delete', 'params' => array ('id' => $this->flux->id ()))); ?>"><?php echo Minz_Translate::t ('delete'); ?></button>
+ <button class="btn btn-important"><?php echo _t('save'); ?></button>
+ <button class="btn btn-attention confirm"
+ data-str-confirm="<?php echo _t('confirm_action_feed_cat'); ?>"
+ formaction="<?php echo _url('feed', 'delete', 'id', $this->flux->id ()); ?>"
+ formmethod="post"><?php echo _t('delete'); ?></button>
</div>
</div>
<legend><?php echo Minz_Translate::t ('archiving_configuration'); ?></legend>
<div class="form-group">
- <label class="group-name"></label>
<div class="group-controls">
- <a class="btn" href="<?php echo _url ('feed', 'actualize', 'id', $this->flux->id ()); ?>">
- <?php echo FreshRSS_Themes::icon('refresh'); ?> <?php echo Minz_Translate::t('actualize'); ?>
- </a>
- </div>
- </div>
- <div class="form-group">
- <label class="group-name"><?php echo Minz_Translate::t ('number_articles'); ?></label>
- <div class="group-controls">
- <span class="control"><?php echo $nbEntries; ?></span>
+ <div class="stick">
+ <input type="text" value="<?php echo _t('number_articles', $nbEntries); ?>" disabled="disabled" />
+ <a class="btn" href="<?php echo _url('feed', 'actualize', 'id', $this->flux->id ()); ?>">
+ <?php echo _i('refresh'); ?> <?php echo _t('actualize'); ?>
+ </a>
+ </div>
</div>
</div>
<div class="form-group">
diff --git a/app/views/configure/queries.phtml b/app/views/configure/queries.phtml
index 2895f584c..e778ce078 100644
--- a/app/views/configure/queries.phtml
+++ b/app/views/configure/queries.phtml
@@ -42,30 +42,37 @@
+ (isset($query['get']) ? 1 : 0);
// If the only filter is "all" articles, we consider there is no filter
$exist = ($exist === 1 && isset($query['get']) && $query['get'] === 'a') ? 0 : $exist;
+
+ $deprecated = (isset($this->query_get[$key]) &&
+ $this->query_get[$key]['deprecated']);
?>
<?php if ($exist === 0) { ?>
<div class="alert alert-warn">
<div class="alert-head"><?php echo _t('no_query_filter'); ?></div>
</div>
+ <?php } elseif ($deprecated) { ?>
+ <div class="alert alert-error">
+ <div class="alert-head"><?php echo _t('query_deprecated'); ?></div>
+ </div>
<?php } else { ?>
<div class="alert alert-success">
<div class="alert-head"><?php echo _t('query_filter'); ?></div>
<ul>
- <?php if (isset($query['search'])) { $exist = true; ?>
+ <?php if (isset($query['search'])) { ?>
<li class="item"><?php echo _t('query_search', $query['search']); ?></li>
<?php } ?>
- <?php if (isset($query['state'])) { $exist = true; ?>
+ <?php if (isset($query['state'])) { ?>
<li class="item"><?php echo _t('query_state_' . $query['state']); ?></li>
<?php } ?>
- <?php if (isset($query['order'])) { $exist = true; ?>
+ <?php if (isset($query['order'])) { ?>
<li class="item"><?php echo _t('query_order_' . strtolower($query['order'])); ?></li>
<?php } ?>
- <?php if (isset($query['get'])) { $exist = true; ?>
+ <?php if (isset($query['get'])) { ?>
<li class="item"><?php echo _t('query_get_' . $this->query_get[$key]['type'], $this->query_get[$key]['name']); ?></li>
<?php } ?>
</ul>
diff --git a/app/views/configure/reading.phtml b/app/views/configure/reading.phtml
index 3dd457a2b..8b2da2a28 100644
--- a/app/views/configure/reading.phtml
+++ b/app/views/configure/reading.phtml
@@ -10,9 +10,7 @@
<label class="group-name" for="posts_per_page"><?php echo Minz_Translate::t ('articles_per_page'); ?></label>
<div class="group-controls">
<input type="number" id="posts_per_page" name="posts_per_page" value="<?php echo $this->conf->posts_per_page; ?>" min="5" max="50" />
- <?php if ($this->conf->display_posts) { ?>
- <?php echo _i('help'); ?> <?php echo _t('number_divided_when_unfolded'); ?>
- <?php } ?>
+ <?php echo _i('help'); ?> <?php echo _t('number_divided_when_reader'); ?>
</div>
</div>
@@ -43,7 +41,7 @@
<select name="default_view" id="default_view">
<option value="<?php echo FreshRSS_Entry::STATE_NOT_READ; ?>"<?php echo $this->conf->default_view === FreshRSS_Entry::STATE_NOT_READ ? ' selected="selected"' : ''; ?>><?php echo _t('show_adaptive'); ?></option>
<option value="<?php echo FreshRSS_Entry::STATE_ALL; ?>"<?php echo $this->conf->default_view === FreshRSS_Entry::STATE_ALL ? ' selected="selected"' : ''; ?>><?php echo _t('show_all_articles'); ?></option>
- <option value="<?php echo FreshRSS_Entry::STATE_NOT_READ_STRICT; ?>"<?php echo $this->conf->default_view === FreshRSS_Entry::STATE_NOT_READ_STRICT ? ' selected="selected"' : ''; ?>><?php echo _t('show_not_reads'); ?></option>
+ <option value="<?php echo FreshRSS_Entry::STATE_STRICT + FreshRSS_Entry::STATE_NOT_READ; ?>"<?php echo $this->conf->default_view === FreshRSS_Entry::STATE_STRICT + FreshRSS_Entry::STATE_NOT_READ ? ' selected="selected"' : ''; ?>><?php echo _t('show_not_reads'); ?></option>
</select>
</div>
</div>
diff --git a/app/views/helpers/javascript_vars.phtml b/app/views/helpers/javascript_vars.phtml
index bf0ffdb76..1139eb446 100644
--- a/app/views/helpers/javascript_vars.phtml
+++ b/app/views/helpers/javascript_vars.phtml
@@ -51,7 +51,7 @@ echo 'authType="', $authType, '",',
'url_login="', _url ('index', 'login'), '",',
'url_logout="', _url ('index', 'logout'), '",';
-echo 'str_confirmation="', Minz_Translate::t('confirm_action'), '"', ",\n";
+echo 'str_confirmation_default="', Minz_Translate::t('confirm_action'), '"', ",\n";
echo 'str_notif_title_articles="', Minz_Translate::t('notif_title_new_articles'), '"', ",\n";
echo 'str_notif_body_articles="', Minz_Translate::t('notif_body_new_articles'), '"', ",\n";
echo 'html5_notif_timeout=', $this->conf->html5_notif_timeout,",\n";
diff --git a/app/views/helpers/pagination.phtml b/app/views/helpers/pagination.phtml
index 1b15cc632..cea338364 100755
--- a/app/views/helpers/pagination.phtml
+++ b/app/views/helpers/pagination.phtml
@@ -6,6 +6,8 @@
Minz_Session::_param('markReadUrl', false);
?>
+<form id="mark-read-pagination" method="post" style="display: none"></form>
+
<ul class="pagination">
<li class="item pager-next">
<?php if (!empty($this->nextId)) { ?>
@@ -19,7 +21,7 @@
<?php } elseif ($markReadUrl) { ?>
<button id="bigMarkAsRead"
class="as-link <?php echo $this->conf->reading_confirm ? 'confirm' : ''; ?>"
- form="mark-read"
+ form="mark-read-pagination"
formaction="<?php echo $markReadUrl; ?>"
type="submit">
<?php echo _t('nothing_to_load'); ?><br />
diff --git a/app/views/helpers/view/global_view.phtml b/app/views/helpers/view/global_view.phtml
index db937eeae..72bcf4c73 100644
--- a/app/views/helpers/view/global_view.phtml
+++ b/app/views/helpers/view/global_view.phtml
@@ -1,5 +1,6 @@
<?php $this->partial ('nav_menu'); ?>
+<?php if (!empty($this->entries)) { ?>
<div id="stream" class="global categories">
<?php
$arUrl = array('c' => 'index', 'a' => 'index', 'params' => array());
@@ -43,3 +44,10 @@
<div id="panel"<?php echo $this->conf->display_posts ? '' : ' class="hide_posts"'; ?>>
<a class="close" href="#"><?php echo FreshRSS_Themes::icon('close'); ?></a>
</div>
+
+<?php } else { ?>
+<div id="stream" class="prompt alert alert-warn global">
+ <h2><?php echo _t('no_feed_to_display'); ?></h2>
+ <a href="<?php echo _url('configure', 'feed'); ?>"><?php echo _t('think_to_add'); ?></a><br /><br />
+</div>
+<?php } ?>
diff --git a/app/views/helpers/view/normal_view.phtml b/app/views/helpers/view/normal_view.phtml
index 87bf2e22a..1dbf14f4c 100644
--- a/app/views/helpers/view/normal_view.phtml
+++ b/app/views/helpers/view/normal_view.phtml
@@ -183,8 +183,8 @@ if (!empty($this->entries)) {
<?php $this->partial ('nav_entries'); ?>
<?php } else { ?>
-<div id="stream" class="alert alert-warn normal">
- <span class="alert-head"><?php echo Minz_Translate::t ('no_feed_to_display'); ?></span>
- <?php echo Minz_Translate::t ('think_to_add'); ?>
+<div id="stream" class="prompt alert alert-warn normal">
+ <h2><?php echo _t('no_feed_to_display'); ?></h2>
+ <a href="<?php echo _url('configure', 'feed'); ?>"><?php echo _t('think_to_add'); ?></a><br /><br />
</div>
<?php } ?>
diff --git a/app/views/helpers/view/reader_view.phtml b/app/views/helpers/view/reader_view.phtml
index 665f72849..c80dca519 100644
--- a/app/views/helpers/view/reader_view.phtml
+++ b/app/views/helpers/view/reader_view.phtml
@@ -37,8 +37,8 @@ if (!empty($this->entries)) {
</div>
<?php } else { ?>
-<div id="stream" class="alert alert-warn reader">
- <span class="alert-head"><?php echo Minz_Translate::t ('no_feed_to_display'); ?></span>
- <?php echo Minz_Translate::t ('think_to_add'); ?>
+<div id="stream" class="prompt alert alert-warn reader">
+ <h2><?php echo _t('no_feed_to_display'); ?></h2>
+ <a href="<?php echo _url('configure', 'feed'); ?>"><?php echo _t('think_to_add'); ?></a><br /><br />
</div>
<?php } ?>
diff --git a/app/views/stats/idle.phtml b/app/views/stats/idle.phtml
index 608e2d33c..6f3d4a117 100644
--- a/app/views/stats/idle.phtml
+++ b/app/views/stats/idle.phtml
@@ -6,8 +6,14 @@
<h1><?php echo _t('stats_idle'); ?></h1>
<?php
+ $current_url = urlencode(Minz_Url::display(
+ array('c' => 'stats', 'a' => 'idle'),
+ 'php', true
+ ));
+ $nothing = true;
foreach ($this->idleFeeds as $period => $feeds) {
if (!empty($feeds)) {
+ $nothing = false;
?>
<div class="stat">
<h2><?php echo _t($period); ?></h2>
@@ -20,15 +26,23 @@
<div class="stick">
<a class="btn" href="<?php echo _url('index', 'index', 'get', 'f_' . $feed['id']); ?>"><?php echo _i('link'); ?> <?php echo _t('filter'); ?></a>
<a class="btn" href="<?php echo _url('configure', 'feed', 'id', $feed['id']); ?>"><?php echo _i('configure'); ?> <?php echo _t('administration'); ?></a>
- <button class="btn btn-attention confirm" form="form-delete" formaction="<?php echo _url('feed', 'delete', 'id', $feed['id']); ?>"><?php echo _t('delete'); ?></button>
+ <button class="btn btn-attention confirm" form="form-delete" formaction="<?php echo _url('feed', 'delete', 'id', $feed['id'], 'r', $current_url); ?>"><?php echo _t('delete'); ?></button>
</div>
</li>
- <li class="item"><span title="<?php echo timestamptodate($feed['last_date'], false); ?>"><?php echo $feed['name']; ?></span></li>
+ <li class="item">
+ <span title="<?php echo timestamptodate($feed['last_date'], false); ?>"><?php echo $feed['name']; ?> (<?php echo _t('number_articles', $feed['nb_articles']); ?>)</span>
+ </li>
</ul>
<?php } ?>
</div>
<?php
}
}
+
+ if ($nothing) {
?>
+ <p class="alert alert-warn">
+ <span class="alert-head"><?php echo _t('stats_no_idle'); ?></span>
+ </p>
+ <?php } ?>
</div>
diff --git a/app/views/stats/index.phtml b/app/views/stats/index.phtml
index 46cdc2a8b..412e77e16 100644
--- a/app/views/stats/index.phtml
+++ b/app/views/stats/index.phtml
@@ -53,7 +53,7 @@
<tbody>
<?php foreach ($this->topFeed as $feed): ?>
<tr>
- <td><?php echo $feed['name']; ?></td>
+ <td><a href="<?php echo _url('stats', 'repartition', 'id', $feed['id']); ?>"><?php echo $feed['name']; ?></a></td>
<td><?php echo $feed['category']; ?></td>
<td class="numeric"><?php echo formatNumber($feed['count']); ?></td>
</tr>
diff --git a/app/views/stats/repartition.phtml b/app/views/stats/repartition.phtml
index ead275696..b425c1458 100644
--- a/app/views/stats/repartition.phtml
+++ b/app/views/stats/repartition.phtml
@@ -24,8 +24,8 @@
</select>
<?php if ($this->feed) {?>
- <a href="<?php echo _url('configure', 'feed', 'id', $this->feed->id()); ?>">
- <?php echo _t('administration'); ?>
+ <a class="btn" href="<?php echo _url('configure', 'feed', 'id', $this->feed->id()); ?>">
+ <?php echo _i('configure'); ?> <?php echo _t('administration'); ?>
</a>
<?php }?>