aboutsummaryrefslogtreecommitdiff
path: root/app
diff options
context:
space:
mode:
Diffstat (limited to 'app')
-rwxr-xr-xapp/Controllers/configureController.php320
-rwxr-xr-xapp/Controllers/entryController.php4
-rwxr-xr-xapp/Controllers/feedController.php22
-rw-r--r--app/Controllers/importExportController.php28
-rwxr-xr-xapp/Controllers/indexController.php80
-rw-r--r--app/Controllers/statsController.php45
-rw-r--r--app/Controllers/updateController.php129
-rw-r--r--app/FreshRSS.php17
-rw-r--r--app/Models/Configuration.php39
-rw-r--r--app/Models/Entry.php1
-rw-r--r--app/Models/EntryDAO.php2
-rw-r--r--app/Models/FeedDAO.php2
-rw-r--r--app/Models/StatsDAO.php69
-rw-r--r--app/Models/StatsDAOSQLite.php1
-rw-r--r--app/Models/Themes.php1
-rw-r--r--app/i18n/en.php53
-rw-r--r--app/i18n/fr.php55
-rw-r--r--app/i18n/install.en.php2
-rw-r--r--app/i18n/install.fr.php2
-rw-r--r--app/install.php951
-rw-r--r--app/layout/aside_configure.phtml38
-rw-r--r--app/layout/aside_flux.phtml74
-rw-r--r--app/layout/header.phtml6
-rw-r--r--app/layout/layout.phtml1
-rw-r--r--app/layout/nav_menu.phtml175
-rw-r--r--app/views/configure/categorize.phtml8
-rw-r--r--app/views/configure/display.phtml7
-rw-r--r--app/views/configure/feed.phtml30
-rw-r--r--app/views/configure/queries.phtml15
-rw-r--r--app/views/configure/reading.phtml20
-rw-r--r--app/views/configure/shortcut.phtml15
-rw-r--r--app/views/helpers/javascript_vars.phtml11
-rwxr-xr-xapp/views/helpers/pagination.phtml41
-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/index/formLogin.phtml13
-rw-r--r--app/views/index/resetAuth.phtml33
-rw-r--r--app/views/stats/idle.phtml33
-rw-r--r--app/views/stats/index.phtml48
-rw-r--r--app/views/stats/repartition.phtml66
-rw-r--r--app/views/update/apply.phtml9
-rw-r--r--app/views/update/index.phtml36
43 files changed, 1576 insertions, 946 deletions
diff --git a/app/Controllers/configureController.php b/app/Controllers/configureController.php
index bb96bfae3..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));
@@ -157,26 +219,49 @@ class FreshRSS_configure_Controller extends Minz_ActionController {
$this->view->conf->_bottomline_tags(Minz_Request::param('bottomline_tags', false));
$this->view->conf->_bottomline_date(Minz_Request::param('bottomline_date', false));
$this->view->conf->_bottomline_link(Minz_Request::param('bottomline_link', false));
+ $this->view->conf->_html5_notif_timeout(Minz_Request::param('html5_notif_timeout', 0));
$this->view->conf->save();
Minz_Session::_param('language', $this->view->conf->language);
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));
@@ -203,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();
@@ -222,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;
@@ -258,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();
@@ -305,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;
@@ -334,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/entryController.php b/app/Controllers/entryController.php
index ac43587ea..ab66d9198 100755
--- a/app/Controllers/entryController.php
+++ b/app/Controllers/entryController.php
@@ -45,6 +45,10 @@ class FreshRSS_entry_Controller extends Minz_ActionController {
$entryDAO = FreshRSS_Factory::createEntryDao();
if ($id == false) {
+ if (!Minz_Request::isPost()) {
+ return;
+ }
+
if (!$get) {
$entryDAO->markReadEntries ($idMax);
} else {
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/importExportController.php b/app/Controllers/importExportController.php
index 5adf3878a..f329766b8 100644
--- a/app/Controllers/importExportController.php
+++ b/app/Controllers/importExportController.php
@@ -109,7 +109,6 @@ class FreshRSS_importExport_Controller extends Minz_ActionController {
// A *very* basic guess file type function. Only based on filename
// That's could be improved but should be enough, at least for a first
// implementation.
- // TODO: improve this function?
if (substr_compare($filename, '.zip', -4) === 0) {
return 'zip';
@@ -119,8 +118,7 @@ class FreshRSS_importExport_Controller extends Minz_ActionController {
} elseif (substr_compare($filename, '.json', -5) === 0 &&
strpos($filename, 'starred') !== false) {
return 'json_starred';
- } elseif (substr_compare($filename, '.json', -5) === 0 &&
- strpos($filename, 'feed_') === 0) {
+ } elseif (substr_compare($filename, '.json', -5) === 0) {
return 'json_feed';
} else {
return 'unknown';
@@ -239,13 +237,27 @@ class FreshRSS_importExport_Controller extends Minz_ActionController {
);
$error = false;
+ $article_to_feed = array();
+
+ // First, we check feeds of articles are in DB (and add them if needed).
foreach ($article_object['items'] as $item) {
$feed = $this->addFeedArticles($item['origin'], $google_compliant);
if (is_null($feed)) {
$error = true;
+ } else {
+ $article_to_feed[$item['id']] = $feed->id();
+ }
+ }
+
+ // Then, articles are imported.
+ $prepared_statement = $this->entryDAO->addEntryPrepare();
+ $this->entryDAO->beginTransaction();
+ foreach ($article_object['items'] as $item) {
+ if (!isset($article_to_feed[$item['id']])) {
continue;
}
+ $feed_id = $article_to_feed[$item['id']];
$author = isset($item['author']) ? $item['author'] : '';
$key_content = ($google_compliant && !isset($item['content'])) ?
'summary' : 'content';
@@ -257,21 +269,21 @@ class FreshRSS_importExport_Controller extends Minz_ActionController {
}
$entry = new FreshRSS_Entry(
- $feed->id(), $item['id'], $item['title'], $author,
+ $feed_id, $item['id'], $item['title'], $author,
$item[$key_content]['content'], $item['alternate'][0]['href'],
$item['published'], $is_read, $starred
);
+ $entry->_id(min(time(), $entry->date(true)) . uSecString());
$entry->_tags($tags);
- //FIME: Use entryDAO->addEntryPrepare(). Do not call entryDAO->listLastGuidsByFeed() for each entry. Consider using a transaction.
- $id = $this->entryDAO->addEntryObject(
- $entry, $this->view->conf, $feed->keepHistory()
- );
+ $values = $entry->toArray();
+ $id = $this->entryDAO->addEntry($values, $prepared_statement);
if (!$error && ($id === false)) {
$error = true;
}
}
+ $this->entryDAO->commit();
return $error;
}
diff --git a/app/Controllers/indexController.php b/app/Controllers/indexController.php
index b0b051119..e8e26b142 100755
--- a/app/Controllers/indexController.php
+++ b/app/Controllers/indexController.php
@@ -83,6 +83,11 @@ class FreshRSS_index_Controller extends Minz_ActionController {
$nb = Minz_Request::param ('nb', $this->view->conf->posts_per_page);
$first = Minz_Request::param ('next', '');
+ $ajax_request = Minz_Request::param('ajax', false);
+ if ($output === 'reader') {
+ $nb = max(1, round($nb / 2));
+ }
+
if ($this->view->state === FreshRSS_Entry::STATE_NOT_READ) { //Any unread article in this category at all?
switch ($getType) {
case 'a':
@@ -332,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');
@@ -415,4 +424,75 @@ class FreshRSS_index_Controller extends Minz_ActionController {
self::deleteLongTermCookie();
Minz_Request::forward(array('c' => 'index', 'a' => 'index'), true);
}
+
+ public function resetAuthAction() {
+ Minz_View::prependTitle(_t('auth_reset') . ' · ');
+ Minz_View::appendScript(Minz_Url::display(
+ '/scripts/bcrypt.min.js?' . @filemtime(PUBLIC_PATH . '/scripts/bcrypt.min.js')
+ ));
+
+ $this->view->no_form = false;
+ // Enable changement of auth only if Persona!
+ if (Minz_Configuration::authType() != 'persona') {
+ $this->view->message = array(
+ 'status' => 'bad',
+ 'title' => _t('damn'),
+ 'body' => _t('auth_not_persona')
+ );
+ $this->view->no_form = true;
+ return;
+ }
+
+ $conf = new FreshRSS_Configuration(Minz_Configuration::defaultUser());
+ // Admin user must have set its master password.
+ if (!$conf->passwordHash) {
+ $this->view->message = array(
+ 'status' => 'bad',
+ 'title' => _t('damn'),
+ 'body' => _t('auth_no_password_set')
+ );
+ $this->view->no_form = true;
+ return;
+ }
+
+ invalidateHttpCache();
+
+ if (Minz_Request::isPost()) {
+ $nonce = Minz_Session::param('nonce');
+ $username = Minz_Request::param('username', '');
+ $c = Minz_Request::param('challenge', '');
+ if (!(ctype_alnum($username) && ctype_graph($c) && ctype_alnum($nonce))) {
+ Minz_Log::debug('Invalid credential parameters:' .
+ ' user=' . $username .
+ ' challenge=' . $c .
+ ' nonce=' . $nonce);
+ Minz_Request::bad(_t('invalid_login'),
+ array('c' => 'index', 'a' => 'resetAuth'));
+ }
+
+ if (!function_exists('password_verify')) {
+ include_once(LIB_PATH . '/password_compat.php');
+ }
+
+ $s = $conf->passwordHash;
+ $ok = password_verify($nonce . $s, $c);
+ if ($ok) {
+ Minz_Configuration::_authType('form');
+ $ok = Minz_Configuration::writeFile();
+
+ if ($ok) {
+ Minz_Request::good(_t('auth_form_set'));
+ } else {
+ Minz_Request::bad(_t('auth_form_not_set'),
+ array('c' => 'index', 'a' => 'resetAuth'));
+ }
+ } else {
+ Minz_Log::debug('Password mismatch for user ' . $username .
+ ', nonce=' . $nonce . ', c=' . $c);
+
+ Minz_Request::bad(_t('invalid_login'),
+ array('c' => 'index', 'a' => 'resetAuth'));
+ }
+ }
+ }
}
diff --git a/app/Controllers/statsController.php b/app/Controllers/statsController.php
index 98f46f0d2..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();
@@ -67,10 +104,18 @@ class FreshRSS_stats_Controller extends Minz_ActionController {
$this->view->days = $statsDAO->getDays();
$this->view->months = $statsDAO->getMonths();
$this->view->repartitionHour = $statsDAO->calculateEntryRepartitionPerFeedPerHour($id);
+ $this->view->averageHour = $statsDAO->calculateEntryAveragePerFeedPerHour($id);
$this->view->repartitionDayOfWeek = $statsDAO->calculateEntryRepartitionPerFeedPerDayOfWeek($id);
+ $this->view->averageDayOfWeek = $statsDAO->calculateEntryAveragePerFeedPerDayOfWeek($id);
$this->view->repartitionMonth = $statsDAO->calculateEntryRepartitionPerFeedPerMonth($id);
+ $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/Controllers/updateController.php b/app/Controllers/updateController.php
new file mode 100644
index 000000000..da5bddc65
--- /dev/null
+++ b/app/Controllers/updateController.php
@@ -0,0 +1,129 @@
+<?php
+
+class FreshRSS_update_Controller extends Minz_ActionController {
+ public function firstAction() {
+ $current_user = Minz_Session::param('currentUser', '');
+ if (!$this->view->loginOk && Minz_Configuration::isAdmin($current_user)) {
+ Minz_Error::error(
+ 403,
+ array('error' => array(_t('access_denied')))
+ );
+ }
+
+ invalidateHttpCache();
+
+ Minz_View::prependTitle(_t('update_system') . ' · ');
+ $this->view->update_to_apply = false;
+ $this->view->last_update_time = 'unknown';
+ $this->view->check_last_hour = false;
+ $timestamp = (int)@file_get_contents(DATA_PATH . '/last_update.txt');
+ if (is_numeric($timestamp) && $timestamp > 0) {
+ $this->view->last_update_time = timestamptodate($timestamp);
+ $this->view->check_last_hour = (time() - 3600) <= $timestamp;
+ }
+ }
+
+ public function indexAction() {
+ if (file_exists(UPDATE_FILENAME) && !is_writable(FRESHRSS_PATH)) {
+ $this->view->message = array(
+ 'status' => 'bad',
+ 'title' => _t('damn'),
+ 'body' => _t('file_is_nok', FRESHRSS_PATH)
+ );
+ } elseif (file_exists(UPDATE_FILENAME)) {
+ // There is an update file to apply!
+ $this->view->update_to_apply = true;
+ $this->view->message = array(
+ 'status' => 'good',
+ 'title' => _t('ok'),
+ 'body' => _t('update_can_apply')
+ );
+ }
+ }
+
+ public function checkAction() {
+ $this->view->change_view('update', 'index');
+
+ if (file_exists(UPDATE_FILENAME) || $this->view->check_last_hour) {
+ // There is already an update file to apply: we don't need to check
+ // the webserver!
+ // Or if already check during the last hour, do nothing.
+ Minz_Request::forward(array('c' => 'update'));
+
+ return;
+ }
+
+ $c = curl_init(FRESHRSS_UPDATE_WEBSITE);
+ curl_setopt($c, CURLOPT_RETURNTRANSFER, true);
+ curl_setopt($c, CURLOPT_SSL_VERIFYPEER, true);
+ curl_setopt($c, CURLOPT_SSL_VERIFYHOST, 2);
+ $result = curl_exec($c);
+ $c_status = curl_getinfo($c, CURLINFO_HTTP_CODE);
+ $c_error = curl_error($c);
+ curl_close($c);
+
+ if ($c_status !== 200) {
+ Minz_Log::error(
+ 'Error during update (HTTP code ' . $c_status . '): ' . $c_error
+ );
+
+ $this->view->message = array(
+ 'status' => 'bad',
+ 'title' => _t('damn'),
+ 'body' => _t('update_server_not_found', FRESHRSS_UPDATE_WEBSITE)
+ );
+ return;
+ }
+
+ $res_array = explode("\n", $result, 2);
+ $status = $res_array[0];
+ if (strpos($status, 'UPDATE') !== 0) {
+ $this->view->message = array(
+ 'status' => 'bad',
+ 'title' => _t('damn'),
+ 'body' => _t('no_update')
+ );
+
+ @file_put_contents(DATA_PATH . '/last_update.txt', time());
+
+ return;
+ }
+
+ $script = $res_array[1];
+ if (file_put_contents(UPDATE_FILENAME, $script) !== false) {
+ Minz_Request::forward(array('c' => 'update'));
+ } else {
+ $this->view->message = array(
+ 'status' => 'bad',
+ 'title' => _t('damn'),
+ 'body' => _t('update_problem', 'Cannot save the update script')
+ );
+ }
+ }
+
+ public function applyAction() {
+ if (!file_exists(UPDATE_FILENAME) || !is_writable(FRESHRSS_PATH)) {
+ Minz_Request::forward(array('c' => 'update'), true);
+ }
+
+ require(UPDATE_FILENAME);
+
+ if (Minz_Request::isPost()) {
+ save_info_update();
+ }
+
+ if (!need_info_update()) {
+ $res = apply_update();
+
+ if ($res === true) {
+ @unlink(UPDATE_FILENAME);
+ @file_put_contents(DATA_PATH . '/last_update.txt', time());
+
+ Minz_Request::good(_t('update_finished'));
+ } else {
+ Minz_Request::bad(_t('update_problem', $res),
+ array('c' => 'update', 'a' => 'index'));
+ }
+ }
+ }
+}
diff --git a/app/FreshRSS.php b/app/FreshRSS.php
index 30f711e20..cdf8962cb 100644
--- a/app/FreshRSS.php
+++ b/app/FreshRSS.php
@@ -6,8 +6,7 @@ class FreshRSS extends Minz_FrontController {
}
$loginOk = $this->accessControl(Minz_Session::param('currentUser', ''));
$this->loadParamsView();
- if (Minz_Request::isPost() && (empty($_SERVER['HTTP_REFERER']) ||
- Minz_Request::getDomainName() !== parse_url($_SERVER['HTTP_REFERER'], PHP_URL_HOST))) {
+ if (Minz_Request::isPost() && !is_referer_from_same_domain()) {
$loginOk = false; //Basic protection against XSRF attacks
Minz_Error::error(
403,
@@ -140,11 +139,21 @@ class FreshRSS extends Minz_FrontController {
}
}
- private function loadStylesAndScripts ($loginOk) {
+ private function loadStylesAndScripts($loginOk) {
$theme = FreshRSS_Themes::load($this->conf->theme);
if ($theme) {
foreach($theme['files'] as $file) {
- Minz_View::appendStyle (Minz_Url::display ('/themes/' . $theme['id'] . '/' . $file . '?' . @filemtime(PUBLIC_PATH . '/themes/' . $theme['id'] . '/' . $file)));
+ if ($file[0] === '_') {
+ $theme_id = 'base-theme';
+ $filename = substr($file, 1);
+ } else {
+ $theme_id = $theme['id'];
+ $filename = $file;
+ }
+ $filetime = @filemtime(PUBLIC_PATH . '/themes/' . $theme_id . '/' . $filename);
+ Minz_View::appendStyle(Minz_Url::display(
+ '/themes/' . $theme_id . '/' . $filename . '?' . $filetime
+ ));
}
}
diff --git a/app/Models/Configuration.php b/app/Models/Configuration.php
index 4c804a9fb..95f819779 100644
--- a/app/Models/Configuration.php
+++ b/app/Models/Configuration.php
@@ -45,6 +45,8 @@ class FreshRSS_Configuration {
'load_more' => 'm',
'auto_share' => 's',
'focus_search' => 'a',
+ 'user_filter' => 'u',
+ 'help' => 'f1',
),
'topline_read' => true,
'topline_favorite' => true,
@@ -58,6 +60,7 @@ class FreshRSS_Configuration {
'bottomline_link' => true,
'sharing' => array(),
'queries' => array(),
+ 'html5_notif_timeout' => 0,
);
private $available_languages = array(
@@ -120,6 +123,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';
@@ -138,7 +151,18 @@ class FreshRSS_Configuration {
}
}
public function _default_view ($value) {
- $this->data['default_view'] = $value === FreshRSS_Entry::STATE_ALL ? FreshRSS_Entry::STATE_ALL : FreshRSS_Entry::STATE_NOT_READ;
+ switch ($value) {
+ case FreshRSS_Entry::STATE_ALL:
+ // left blank on purpose
+ case FreshRSS_Entry::STATE_NOT_READ:
+ // left blank on purpose
+ case FreshRSS_Entry::STATE_STRICT + FreshRSS_Entry::STATE_NOT_READ:
+ $this->data['default_view'] = $value;
+ break;
+ default:
+ $this->data['default_view'] = FreshRSS_Entry::STATE_ALL;
+ break;
+ }
}
public function _display_posts ($value) {
$this->data['display_posts'] = ((bool)$value) && $value !== 'no';
@@ -209,6 +233,7 @@ class FreshRSS_Configuration {
}
public function _sharing ($values) {
$this->data['sharing'] = array();
+ $unique = array();
foreach ($values as $value) {
if (!is_array($value)) {
continue;
@@ -234,7 +259,11 @@ class FreshRSS_Configuration {
$value['name'] = $value['type'];
}
- $this->data['sharing'][] = $value;
+ $json_value = json_encode($value);
+ if (!in_array($json_value, $unique)) {
+ $unique[] = $json_value;
+ $this->data['sharing'][] = $value;
+ }
}
}
public function _queries ($values) {
@@ -261,6 +290,12 @@ class FreshRSS_Configuration {
$this->data['content_width'] = 'thin';
}
}
+
+ public function _html5_notif_timeout ($value) {
+ $value = intval($value);
+ $this->data['html5_notif_timeout'] = $value >= 0 ? $value : 0;
+ }
+
public function _token($value) {
$this->data['token'] = $value;
}
diff --git a/app/Models/Entry.php b/app/Models/Entry.php
index 0bf1f2616..9d7dd5dc4 100644
--- a/app/Models/Entry.php
+++ b/app/Models/Entry.php
@@ -6,6 +6,7 @@ class FreshRSS_Entry extends Minz_Model {
const STATE_NOT_READ = 2;
const STATE_FAVORITE = 4;
const STATE_NOT_FAVORITE = 8;
+ const STATE_STRICT = 16;
private $id = 0;
private $guid;
diff --git a/app/Models/EntryDAO.php b/app/Models/EntryDAO.php
index 75a8aeba4..c1f87ee34 100644
--- a/app/Models/EntryDAO.php
+++ b/app/Models/EntryDAO.php
@@ -333,6 +333,8 @@ 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) {
diff --git a/app/Models/FeedDAO.php b/app/Models/FeedDAO.php
index 756b1f008..b89ae2045 100644
--- a/app/Models/FeedDAO.php
+++ b/app/Models/FeedDAO.php
@@ -331,7 +331,7 @@ class FreshRSS_FeedDAO extends Minz_ModelPdo {
$id_max = intval($date_min) . '000000';
$stm->bindParam(':id_feed', $id, PDO::PARAM_INT);
- $stm->bindParam(':id_max', $id_max, PDO::PARAM_INT);
+ $stm->bindParam(':id_max', $id_max, PDO::PARAM_STR);
$stm->bindParam(':keep', $keep, PDO::PARAM_INT);
if ($stm && $stm->execute()) {
diff --git a/app/Models/StatsDAO.php b/app/Models/StatsDAO.php
index 89be76a26..40505ab3e 100644
--- a/app/Models/StatsDAO.php
+++ b/app/Models/StatsDAO.php
@@ -152,6 +152,74 @@ SQL;
}
/**
+ * Calculates the average number of article per hour per feed
+ *
+ * @param integer $feed id
+ * @return integer
+ */
+ public function calculateEntryAveragePerFeedPerHour($feed = null) {
+ return $this->calculateEntryAveragePerFeedPerPeriod(1/24, $feed);
+ }
+
+ /**
+ * Calculates the average number of article per day of week per feed
+ *
+ * @param integer $feed id
+ * @return integer
+ */
+ public function calculateEntryAveragePerFeedPerDayOfWeek($feed = null) {
+ return $this->calculateEntryAveragePerFeedPerPeriod(7, $feed);
+ }
+
+ /**
+ * Calculates the average number of article per month per feed
+ *
+ * @param integer $feed id
+ * @return integer
+ */
+ public function calculateEntryAveragePerFeedPerMonth($feed = null) {
+ return $this->calculateEntryAveragePerFeedPerPeriod(30, $feed);
+ }
+
+ /**
+ * Calculates the average number of article per feed
+ *
+ * @param float $period number used to divide the number of day in the period
+ * @param integer $feed id
+ * @return integer
+ */
+ protected function calculateEntryAveragePerFeedPerPeriod($period, $feed = null) {
+ if ($feed) {
+ $restrict = "WHERE e.id_feed = {$feed}";
+ } else {
+ $restrict = '';
+ }
+ $sql = <<<SQL
+SELECT COUNT(1) AS count
+, MIN(date) AS date_min
+, MAX(date) AS date_max
+FROM {$this->prefix}entry AS e
+{$restrict}
+SQL;
+ $stm = $this->bd->prepare($sql);
+ $stm->execute();
+ $res = $stm->fetch(PDO::FETCH_NAMED);
+ $date_min = new \DateTime();
+ $date_min->setTimestamp($res['date_min']);
+ $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_in_days / $period), 2);
+ }
+
+ /**
* Initialize an array for statistics depending on a range
*
* @param integer $min
@@ -247,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/en.php b/app/i18n/en.php
index be0cdc642..beba02c4d 100644
--- a/app/i18n/en.php
+++ b/app/i18n/en.php
@@ -5,6 +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' => 'Connection problem with Persona?',
'logout' => 'Logout',
'search' => 'Search words or #tags',
'search_short' => 'Search',
@@ -42,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',
@@ -92,6 +95,7 @@ return array (
'rss_view' => 'RSS feed',
'show_all_articles' => 'Show all articles',
'show_not_reads' => 'Show only unread',
+ 'show_adaptive' => 'Adjust showing',
'show_read' => 'Show only read',
'show_favorite' => 'Show only favorites',
'show_not_favorite' => 'Show all but favorites',
@@ -111,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',
@@ -152,10 +156,13 @@ return array (
'public' => 'Public',
'invalid_login' => 'Login is invalid',
+ 'file_is_nok' => 'Check permissions on <em>%s</em> directory. HTTP server must have rights to write into.',
+
// VIEWS
'save' => 'Save',
'delete' => 'Delete',
'cancel' => 'Cancel',
+ 'submit' => 'Submit',
'back_to_rss_feeds' => '← Go back to your RSS feeds',
'feeds_moved_category_deleted' => 'When you delete a category, their feeds are automatically classified under <em>%s</em>.',
@@ -180,6 +187,9 @@ return array (
'auto_share' => 'Share',
'auto_share_help' => 'If there is only one sharing mode, it is used. Else modes are accessible by their number.',
'focus_search' => 'Access search box',
+ 'user_filter' => 'Access user filters',
+ 'user_filter_help' => 'If there is only one user filter, it is used. Else filters are accessible by their number.',
+ 'help' => 'Display documentation',
'file_to_import' => 'File to import<br />(OPML, Json or Zip)',
'file_to_import_no_zip' => 'File to import<br />(OPML or Json)',
@@ -197,13 +207,15 @@ return array (
'informations' => 'Information',
'damn' => 'Damn!',
+ 'ok' => 'Ok!',
+ 'attention' => 'Be careful!',
'feed_in_error' => 'This feed has encountered a problem. Please verify that it is always reachable then actualize it.',
'feed_empty' => 'This feed is empty. Please verify that it is still maintained.',
'feed_description' => 'Description',
'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',
@@ -225,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>',
@@ -237,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',
@@ -248,6 +260,7 @@ return array (
'users_list' => 'List of users',
'create_user' => 'Create new user',
'username' => 'Username',
+ 'username_admin' => 'Administrator username',
'password' => 'Password',
'create' => 'Create',
'user_created' => 'User %s has been created',
@@ -256,31 +269,35 @@ 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_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',
'top_line' => 'Top line',
'bottom_line' => 'Bottom line',
+ 'html5_notif_timeout' => 'HTML5 notification timeout',
+ 'seconds_(0_means_no_timeout)' => 'seconds (0 means no timeout)',
'img_with_lazyload' => 'Use "lazy load" mode to load pictures',
'sticky_post' => 'Stick the article to the top when opened',
'reading_confirm' => 'Display a confirmation dialog on “mark all as read” actions',
'auto_read_when' => 'Mark article as read…',
'article_viewed' => 'when article is viewed',
'article_open_on_website' => 'when article is opened on its original website',
- 'scroll' => 'during page scrolls',
+ 'scroll' => 'while scrolling',
'upon_reception' => 'upon reception of the article',
'your_shaarli' => 'Your Shaarli',
'your_wallabag' => 'Your wallabag',
@@ -340,7 +357,7 @@ return array (
'agpl3' => '<a href="https://www.gnu.org/licenses/agpl-3.0.html">AGPL 3</a>',
'freshrss_description' => 'FreshRSS is a RSS feeds aggregator to self-host like <a href="http://tontof.net/kriss/feed/">Kriss Feed</a> or <a href="http://projet.idleman.fr/leed/">Leed</a>. It is light and easy to take in hand while being powerful and configurable tool.',
'credits' => 'Credits',
- 'credits_content' => 'Some design elements come from <a href="http://twitter.github.io/bootstrap/">Bootstrap</a> although FreshRSS doesn’t use this framework. <a href="https://git.gnome.org/browse/gnome-icon-theme-symbolic">Icons</a> come from <a href="https://www.gnome.org/">GNOME project</a>. <em>Open Sans</em> font police used has been created by <a href="https://www.google.com/webfonts/specimen/Open+Sans">Steve Matteson</a>. Favicons are collected with <a href="https://getfavicon.appspot.com/">getFavicon API</a>. FreshRSS is based on <a href="https://github.com/marienfressinaud/MINZ">Minz</a>, a PHP framework.',
+ 'credits_content' => 'Some design elements come from <a href="http://twitter.github.io/bootstrap/">Bootstrap</a> although FreshRSS doesn’t use this framework. <a href="https://git.gnome.org/browse/gnome-icon-theme-symbolic">Icons</a> come from <a href="https://www.gnome.org/">GNOME project</a>. <em>Open Sans</em> font police has been created by <a href="https://www.google.com/webfonts/specimen/Open+Sans">Steve Matteson</a>. Favicons are collected with <a href="https://getfavicon.appspot.com/">getFavicon API</a>. FreshRSS is based on <a href="https://github.com/marienfressinaud/MINZ">Minz</a>, a PHP framework.',
'version' => 'Version',
'logs' => 'Logs',
@@ -351,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.',
@@ -414,4 +432,23 @@ 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',
+ 'update_check' => 'Check for new updates',
+ 'update_last' => 'Last verification: %s',
+ 'update_can_apply' => 'An update is available.',
+ 'update_apply' => 'Apply',
+ 'update_server_not_found' => 'Update server cannot be found. [%s]',
+ 'no_update' => 'No update to apply',
+ 'update_problem' => 'The update process has encountered an error: %s',
+ 'update_finished' => 'Update completed!',
+
+ 'auth_reset' => 'Authentication reset',
+ '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 08f12234e..b0fbf15ae 100644
--- a/app/i18n/fr.php
+++ b/app/i18n/fr.php
@@ -5,6 +5,7 @@ return array (
'login' => 'Connexion',
'keep_logged_in' => 'Rester connecté <small>(1 mois)</small>',
'login_with_persona' => 'Connexion avec Persona',
+ 'login_persona_problem' => 'Problème de connexion à Persona ?',
'logout' => 'Déconnexion',
'search' => 'Rechercher des mots ou des #tags',
'search_short' => 'Rechercher',
@@ -42,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',
@@ -54,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',
@@ -92,6 +95,7 @@ return array (
'rss_view' => 'Flux RSS',
'show_all_articles' => 'Afficher tous les articles',
'show_not_reads' => 'Afficher les non lus',
+ 'show_adaptive' => 'Adapter l’affichage',
'show_read' => 'Afficher les lus',
'show_favorite' => 'Afficher les favoris',
'show_not_favorite' => 'Afficher tout sauf les favoris',
@@ -152,10 +156,13 @@ return array (
'public' => 'Public',
'invalid_login' => 'L’identifiant est invalide !',
+ 'file_is_nok' => 'Veuillez vérifier les droits sur le répertoire <em>%s</em>. Le serveur HTTP doit être capable d’écrire dedans.',
+
// VIEWS
'save' => 'Enregistrer',
'delete' => 'Supprimer',
'cancel' => 'Annuler',
+ 'submit' => 'Valider',
'back_to_rss_feeds' => '← Retour à vos flux RSS',
'feeds_moved_category_deleted' => 'Lors de la suppression d’une catégorie, ses flux seront automatiquement classés dans <em>%s</em>.',
@@ -180,6 +187,9 @@ return array (
'auto_share' => 'Partager',
'auto_share_help' => 'S’il n’y a qu’un mode de partage, celui ci est utilisé automatiquement. Sinon ils sont accessibles par leur numéro.',
'focus_search' => 'Accéder à la recherche',
+ 'user_filter' => 'Accéder aux filtres utilisateur',
+ 'user_filter_help' => 'S’il n’y a qu’un filtre utilisateur, celui ci est utilisé automatiquement. Sinon ils sont accessibles par leur numéro.',
+ 'help' => 'Afficher la documentation',
'file_to_import' => 'Fichier à importer<br />(OPML, Json ou Zip)',
'file_to_import_no_zip' => 'Fichier à importer<br />(OPML ou Json)',
@@ -197,13 +207,15 @@ return array (
'informations' => 'Informations',
'damn' => 'Arf !',
+ 'ok' => 'Ok !',
+ 'attention' => 'Attention !',
'feed_in_error' => 'Ce flux a rencontré un problème. Veuillez vérifier qu’il est toujours accessible puis actualisez-le.',
'feed_empty' => 'Ce flux est vide. Veuillez vérifier qu’il est toujours maintenu.',
'feed_description' => 'Description',
'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',
@@ -225,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>',
@@ -237,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',
@@ -248,6 +260,7 @@ return array (
'users_list' => 'Liste des utilisateurs',
'create_user' => 'Créer un nouvel utilisateur',
'username' => 'Nom d’utilisateur',
+ 'username_admin' => 'Nom d’utilisateur administrateur',
'password' => 'Mot de passe',
'create' => 'Créer',
'user_created' => 'L’utilisateur %s a été créé.',
@@ -263,17 +276,21 @@ return array (
'reading_configuration' => 'Lecture',
'display_configuration' => 'Affichage',
'articles_per_page' => 'Nombre d’articles par page',
+ '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',
+ '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',
'reading_confirm' => 'Afficher une confirmation lors des actions “marquer tout comme lu”',
@@ -351,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.',
@@ -414,4 +432,23 @@ 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',
+ 'update_check' => 'Vérifier les mises à jour',
+ 'update_last' => 'Dernière vérification : %s',
+ 'update_can_apply' => 'Une mise à jour est disponible.',
+ 'update_apply' => 'Appliquer la mise à jour',
+ 'update_server_not_found' => 'Le serveur de mise à jour n’a pas été trouvé. [%s]',
+ 'no_update' => 'Aucune mise à jour à appliquer',
+ 'update_problem' => 'La mise à jour a rencontré un problème : %s',
+ 'update_finished' => 'La mise à jour est terminée !',
+
+ '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/i18n/install.en.php b/app/i18n/install.en.php
index 50208fcef..c422de90f 100644
--- a/app/i18n/install.en.php
+++ b/app/i18n/install.en.php
@@ -42,6 +42,8 @@ return array (
'data_is_ok' => 'Permissions on data directory are good',
'persona_is_ok' => 'Permissions on Mozilla Persona directory are good',
'file_is_nok' => 'Check permissions on <em>%s</em> directory. HTTP server must have rights to write into',
+ 'http_referer_is_ok' => 'Your HTTP REFERER is known and corresponds to your server.',
+ 'http_referer_is_nok' => 'Please check that you are not altering your HTTP REFERER.',
'fix_errors_before' => 'Fix errors before skip to the next step.',
'general_conf_is_ok' => 'General configuration has been saved.',
diff --git a/app/i18n/install.fr.php b/app/i18n/install.fr.php
index 9c039f904..785c02459 100644
--- a/app/i18n/install.fr.php
+++ b/app/i18n/install.fr.php
@@ -42,6 +42,8 @@ return array (
'data_is_ok' => 'Les droits sur le répertoire de data sont bons',
'persona_is_ok' => 'Les droits sur le répertoire de Mozilla Persona sont bons',
'file_is_nok' => 'Veuillez vérifier les droits sur le répertoire <em>%s</em>. Le serveur HTTP doit être capable d’écrire dedans',
+ 'http_referer_is_ok' => 'Le HTTP REFERER est connu et semble correspondre à votre serveur.',
+ 'http_referer_is_nok' => 'Veuillez vérifier que vous ne modifiez pas votre HTTP REFERER.',
'fix_errors_before' => 'Veuillez corriger les erreurs avant de passer à l’étape suivante.',
'general_conf_is_ok' => 'La configuration générale a été enregistrée.',
diff --git a/app/install.php b/app/install.php
index eaa1100c1..4449cd063 100644
--- a/app/install.php
+++ b/app/install.php
@@ -9,10 +9,10 @@ session_name('FreshRSS');
session_set_cookie_params(0, dirname(empty($_SERVER['REQUEST_URI']) ? '/' : dirname($_SERVER['REQUEST_URI'])), null, false, true);
session_start();
-if (isset ($_GET['step'])) {
- define ('STEP', (int)$_GET['step']);
+if (isset($_GET['step'])) {
+ define('STEP',(int)$_GET['step']);
} else {
- define ('STEP', 1);
+ define('STEP', 0);
}
define('SQL_CREATE_DB', 'CREATE DATABASE IF NOT EXISTS %1$s DEFAULT CHARACTER SET utf8 COLLATE utf8_unicode_ci;');
@@ -23,88 +23,28 @@ if (STEP === 3 && isset($_POST['type'])) {
if (isset($_SESSION['bd_type'])) {
switch ($_SESSION['bd_type']) {
- case 'mysql':
- include(APP_PATH . '/SQL/install.sql.mysql.php');
- break;
- case 'sqlite':
- include(APP_PATH . '/SQL/install.sql.sqlite.php');
- break;
+ case 'mysql':
+ include(APP_PATH . '/SQL/install.sql.mysql.php');
+ break;
+ case 'sqlite':
+ include(APP_PATH . '/SQL/install.sql.sqlite.php');
+ break;
}
}
-//<updates>
-define('SQL_BACKUP006', 'RENAME TABLE `%1$scategory` TO `%1$scategory006`, `%1$sfeed` TO `%1$sfeed006`, `%1$sentry` TO `%1$sentry006`;');
-
-define('SQL_SHOW_COLUMNS_UPDATEv006', 'SHOW columns FROM `%1$sentry006` LIKE "id2";');
-
-define('SQL_UPDATEv006', '
-ALTER TABLE `%1$scategory006` ADD id2 SMALLINT;
-
-SET @i = 0;
-UPDATE `%1$scategory006` SET id2=(@i:=@i+1) ORDER BY id;
-
-ALTER TABLE `%1$sfeed006` ADD id2 SMALLINT, ADD category2 SMALLINT;
-
-SET @i = 0;
-UPDATE `%1$sfeed006` SET id2=(@i:=@i+1) ORDER BY name;
-
-UPDATE `%1$sfeed006` f
-INNER JOIN `%1$scategory006` c ON f.category = c.id
-SET f.category2 = c.id2;
-
-INSERT IGNORE INTO `%2$scategory` (name)
-SELECT name
-FROM `%1$scategory006`
-ORDER BY id2;
-
-INSERT IGNORE INTO `%2$sfeed` (url, category, name, website, description, priority, pathEntries, httpAuth, keep_history)
-SELECT url, category2, name, website, description, priority, pathEntries, httpAuth, IF(keep_history = 1, -1, -2)
-FROM `%1$sfeed006`
-ORDER BY id2;
-
-ALTER TABLE `%1$sentry006` ADD id2 bigint;
-
-UPDATE `%1$sentry006` SET id2 = ((date * 1000000) + (rand() * 100000000));
-
-INSERT IGNORE INTO `%2$sentry` (id, guid, title, author, link, date, is_read, is_favorite, id_feed, tags)
-SELECT e0.id2, e0.guid, e0.title, e0.author, e0.link, e0.date, e0.is_read, e0.is_favorite, f0.id2, e0.tags
-FROM `%1$sentry006` e0
-INNER JOIN `%1$sfeed006` f0 ON e0.id_feed = f0.id;
-');
-
-define('SQL_CONVERT_SELECTv006', '
-SELECT e0.id2, e0.content
-FROM `%1$sentry006` e0
-INNER JOIN `%2$sentry` e1 ON e0.id2 = e1.id
-WHERE e1.content_bin IS NULL');
-
-define('SQL_CONVERT_UPDATEv006', 'UPDATE `%1$sentry` SET '
- . (isset($_SESSION['bd_type']) && $_SESSION['bd_type'] === 'mysql' ? 'content_bin=COMPRESS(?)' : 'content=?')
- . ' WHERE id=?;');
-
-define('SQL_DROP_BACKUPv006', 'DROP TABLE IF EXISTS `%1$sentry006`, `%1$sfeed006`, `%1$scategory006`;');
-
-define('SQL_UPDATE_CACHED_VALUES', '
-UPDATE `%1$sfeed` f
-INNER JOIN (
- SELECT e.id_feed,
- COUNT(CASE WHEN e.is_read = 0 THEN 1 END) AS nbUnreads,
- COUNT(e.id) AS nbEntries
- FROM `%1$sentry` e
- GROUP BY e.id_feed
-) x ON x.id_feed=f.id
-SET f.cache_nbEntries=x.nbEntries, f.cache_nbUnreads=x.nbUnreads
-');
-
-define('SQL_UPDATE_HISTORYv007b', 'UPDATE `%1$sfeed` SET keep_history = CASE WHEN keep_history = 0 THEN -2 WHEN keep_history = 1 THEN -1 ELSE keep_history END;');
+function param($key, $default = false) {
+ if (isset($_POST[$key])) {
+ return $_POST[$key];
+ } else {
+ return $default;
+ }
+}
-define('SQL_GET_FEEDS', 'SELECT id, url, website FROM `%1$sfeed`;');
-//</updates>
// gestion internationalisation
-$translates = array ();
+$translates = array();
$actual = 'en';
-function initTranslate () {
+function initTranslate() {
global $translates;
global $actual;
@@ -121,83 +61,95 @@ function initTranslate () {
}
}
-function getBetterLanguage ($fallback) {
- $available = availableLanguages ();
+function getBetterLanguage($fallback) {
+ $available = availableLanguages();
$accept = $_SERVER['HTTP_ACCEPT_LANGUAGE'];
- $language = strtolower (substr ($accept, 0, 2));
+ $language = strtolower(substr($accept, 0, 2));
- if (isset ($available[$language])) {
+ if (isset($available[$language])) {
return $language;
} else {
return $fallback;
}
}
-function availableLanguages () {
- return array (
+
+function availableLanguages() {
+ return array(
'en' => 'English',
'fr' => 'Français'
);
}
-function _t ($key) {
+
+function _t($key) {
global $translates;
$translate = $key;
- if (isset ($translates[$key])) {
+ if (isset($translates[$key])) {
$translate = $translates[$key];
}
- $args = func_get_args ();
+ $args = func_get_args();
unset($args[0]);
- return vsprintf ($translate, $args);
+ return vsprintf($translate, $args);
}
+
/*** SAUVEGARDES ***/
-function saveLanguage () {
- if (!empty ($_POST)) {
- if (!isset ($_POST['language'])) {
+function saveLanguage() {
+ if (!empty($_POST)) {
+ if (!isset($_POST['language'])) {
return false;
}
$_SESSION['language'] = $_POST['language'];
- header ('Location: index.php?step=1');
+ header('Location: index.php?step=1');
}
}
-function saveStep2 () {
- if (!empty ($_POST)) {
- if (empty ($_POST['title']) ||
- empty ($_POST['old_entries']) ||
- empty ($_POST['auth_type']) ||
- empty ($_POST['default_user'])) {
- return false;
- }
- $_SESSION['salt'] = sha1(uniqid(mt_rand(), true).implode('', stat(__FILE__)));
- $_SESSION['title'] = substr(trim($_POST['title']), 0, 25);
- $_SESSION['old_entries'] = $_POST['old_entries'];
- if ((!ctype_digit($_SESSION['old_entries'])) || ($_SESSION['old_entries'] < 1)) {
- $_SESSION['old_entries'] = 3;
- }
- $_SESSION['mail_login'] = filter_var($_POST['mail_login'], FILTER_VALIDATE_EMAIL);
- $_SESSION['default_user'] = substr(preg_replace('/[^a-zA-Z0-9]/', '', $_POST['default_user']), 0, 16);
- $_SESSION['auth_type'] = $_POST['auth_type'];
- if (!empty($_POST['passwordPlain'])) {
+function saveStep2() {
+ if (!empty($_POST)) {
+ $_SESSION['title'] = substr(trim(param('title', _t('freshrss'))), 0, 25);
+ $_SESSION['old_entries'] = param('old_entries', 3);
+ $_SESSION['auth_type'] = param('auth_type', 'form');
+ $_SESSION['default_user'] = substr(preg_replace('/[^a-zA-Z0-9]/', '', param('default_user', '')), 0, 16);
+ $_SESSION['mail_login'] = filter_var(param('mail_login', ''), FILTER_VALIDATE_EMAIL);
+
+ $password_plain = param('passwordPlain', false);
+ if ($password_plain !== false) {
if (!function_exists('password_hash')) {
include_once(LIB_PATH . '/password_compat.php');
}
- $passwordHash = password_hash($_POST['passwordPlain'], PASSWORD_BCRYPT, array('cost' => BCRYPT_COST));
+ $passwordHash = password_hash($password_plain, PASSWORD_BCRYPT, array('cost' => BCRYPT_COST));
$passwordHash = preg_replace('/^\$2[xy]\$/', '\$2a\$', $passwordHash); //Compatibility with bcrypt.js
$_SESSION['passwordHash'] = $passwordHash;
}
+ if (empty($_SESSION['title']) ||
+ empty($_SESSION['old_entries']) ||
+ empty($_SESSION['auth_type']) ||
+ empty($_SESSION['default_user'])) {
+ return false;
+ }
+
+ if (($_SESSION['auth_type'] === 'form' && empty($_SESSION['passwordHash'])) ||
+ ($_SESSION['auth_type'] === 'persona' && empty($_SESSION['mail_login']))) {
+ return false;
+ }
+
+ $_SESSION['salt'] = sha1(uniqid(mt_rand(), true).implode('', stat(__FILE__)));
+ if ((!ctype_digit($_SESSION['old_entries'])) ||($_SESSION['old_entries'] < 1)) {
+ $_SESSION['old_entries'] = 3;
+ }
+
$token = '';
if ($_SESSION['mail_login']) {
$token = sha1($_SESSION['salt'] . $_SESSION['mail_login']);
}
- $config_array = array (
+ $config_array = array(
'language' => $_SESSION['language'],
- 'theme' => $_SESSION['theme'],
+ 'theme' => 'Origine',
'old_entries' => $_SESSION['old_entries'],
'mail_login' => $_SESSION['mail_login'],
'passwordHash' => $_SESSION['passwordHash'],
@@ -214,12 +166,12 @@ function saveStep2 () {
file_put_contents($personaFile, $_SESSION['default_user']);
}
- header ('Location: index.php?step=3');
+ header('Location: index.php?step=3');
}
}
-function saveStep3 () {
- if (!empty ($_POST)) {
+function saveStep3() {
+ if (!empty($_POST)) {
if ($_SESSION['bd_type'] === 'sqlite') {
$_SESSION['bd_base'] = $_SESSION['default_user'];
$_SESSION['bd_host'] = '';
@@ -228,10 +180,10 @@ function saveStep3 () {
$_SESSION['bd_prefix'] = '';
$_SESSION['bd_prefix_user'] = ''; //No prefix for SQLite
} else {
- if (empty ($_POST['type']) ||
- empty ($_POST['host']) ||
- empty ($_POST['user']) ||
- empty ($_POST['base'])) {
+ if (empty($_POST['type']) ||
+ empty($_POST['host']) ||
+ empty($_POST['user']) ||
+ empty($_POST['base'])) {
$_SESSION['bd_error'] = 'Missing parameters!';
}
$_SESSION['bd_base'] = substr($_POST['base'], 0, 64);
@@ -239,7 +191,7 @@ function saveStep3 () {
$_SESSION['bd_user'] = $_POST['user'];
$_SESSION['bd_password'] = $_POST['pass'];
$_SESSION['bd_prefix'] = substr($_POST['prefix'], 0, 16);
- $_SESSION['bd_prefix_user'] = $_SESSION['bd_prefix'] . (empty($_SESSION['default_user']) ? '' : ($_SESSION['default_user'] . '_'));
+ $_SESSION['bd_prefix_user'] = $_SESSION['bd_prefix'] .(empty($_SESSION['default_user']) ? '' :($_SESSION['default_user'] . '_'));
}
$ini_array = array(
@@ -268,15 +220,11 @@ function saveStep3 () {
@unlink(DATA_PATH . '/config.php'); //To avoid access-rights problems
file_put_contents(DATA_PATH . '/config.php', "<?php\n return " . var_export($ini_array, true) . ';');
- if (file_exists(DATA_PATH . '/config.php') && file_exists(DATA_PATH . '/application.ini')) {
- @unlink(DATA_PATH . '/application.ini'); //v0.6
- }
-
- $res = checkBD ();
+ $res = checkBD();
if ($res) {
$_SESSION['bd_error'] = '';
- header ('Location: index.php?step=4');
+ header('Location: index.php?step=4');
} elseif (empty($_SESSION['bd_error'])) {
$_SESSION['bd_error'] = 'Unknown error!';
}
@@ -284,309 +232,84 @@ function saveStep3 () {
invalidateHttpCache();
}
-function updateDatabase($perform = false) {
- $needs = array('bd_type', 'bd_host', 'bd_base', 'bd_user', 'bd_password', 'bd_prefix', 'bd_prefix_user');
- foreach ($needs as $need) {
- if (!isset($_SESSION[$need])) {
- return false;
- }
- }
-
- try {
- $str = '';
- switch ($_SESSION['bd_type']) {
- case 'mysql':
- $str = 'mysql:host=' . $_SESSION['bd_host'] . ';dbname=' . $_SESSION['bd_base'];
- $driver_options = array(
- PDO::MYSQL_ATTR_INIT_COMMAND => 'SET NAMES utf8',
- );
- break;
- case 'sqlite':
- return false; //No update for SQLite needed so far
- default:
- return false;
- }
-
- $c = new PDO($str, $_SESSION['bd_user'], $_SESSION['bd_password'], $driver_options);
-
- $stm = $c->prepare(SQL_SHOW_TABLES);
- $stm->execute();
- $res = $stm->fetchAll(PDO::FETCH_COLUMN, 0);
- if (!in_array($_SESSION['bd_prefix'] . 'entry006', $res)) {
- return false;
- }
-
- $sql = sprintf(SQL_SHOW_COLUMNS_UPDATEv006, $_SESSION['bd_prefix']);
- $stm = $c->prepare($sql);
- $stm->execute();
- $res = $stm->fetchAll(PDO::FETCH_COLUMN, 0);
- if (!in_array('id2', $res)) {
- if (!$perform) {
- return true;
- }
- $sql = sprintf(SQL_UPDATEv006, $_SESSION['bd_prefix'], $_SESSION['bd_prefix_user']);
- $stm = $c->prepare($sql, array(PDO::ATTR_EMULATE_PREPARES => true));
- $stm->execute();
- }
-
- $sql = sprintf(SQL_CONVERT_SELECTv006, $_SESSION['bd_prefix'], $_SESSION['bd_prefix_user']);
- if (!$perform) {
- $sql .= ' LIMIT 1';
- }
- $stm = $c->prepare($sql);
- $stm->execute();
- if (!$perform) {
- $res = $stm->fetchAll(PDO::FETCH_COLUMN, 0);
- return count($res) > 0;
- } else {
- @set_time_limit(300);
- }
-
- $c2 = new PDO($str, $_SESSION['bd_user'], $_SESSION['bd_password'], $driver_options);
- $sql = sprintf(SQL_CONVERT_UPDATEv006, $_SESSION['bd_prefix_user']);
- $stm2 = $c2->prepare($sql);
- while ($row = $stm->fetch(PDO::FETCH_ASSOC)) {
- $id = $row['id2'];
- $content = unserialize(gzinflate(base64_decode($row['content'])));
- $stm2->execute(array($content, $id));
- }
-
- return true;
- } catch (PDOException $e) {
- return false;
- }
- return false;
-}
-
function newPdo() {
switch ($_SESSION['bd_type']) {
- case 'mysql':
- $str = 'mysql:host=' . $_SESSION['bd_host'] . ';dbname=' . $_SESSION['bd_base'];
- $driver_options = array(
- PDO::MYSQL_ATTR_INIT_COMMAND => 'SET NAMES utf8',
- );
- break;
- case 'sqlite':
- $str = 'sqlite:' . DATA_PATH . '/' . $_SESSION['default_user'] . '.sqlite';
- $driver_options = array(
- PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
- );
- break;
- default:
- return false;
+ case 'mysql':
+ $str = 'mysql:host=' . $_SESSION['bd_host'] . ';dbname=' . $_SESSION['bd_base'];
+ $driver_options = array(
+ PDO::MYSQL_ATTR_INIT_COMMAND => 'SET NAMES utf8',
+ );
+ break;
+ case 'sqlite':
+ $str = 'sqlite:' . DATA_PATH . '/' . $_SESSION['default_user'] . '.sqlite';
+ $driver_options = array(
+ PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
+ );
+ break;
+ default:
+ return false;
}
return new PDO($str, $_SESSION['bd_user'], $_SESSION['bd_password'], $driver_options);
}
-function postUpdate() {
- $c = newPdo();
-
- if ($_SESSION['bd_type'] !== 'sqlite') { //No update for SQLite needed yet
- $sql = sprintf(SQL_UPDATE_HISTORYv007b, $_SESSION['bd_prefix_user']);
- $stm = $c->prepare($sql);
- $stm->execute();
+function deleteInstall() {
+ $res = unlink(DATA_PATH . '/do-install.txt');
- $sql = sprintf(SQL_UPDATE_CACHED_VALUES, $_SESSION['bd_prefix_user']);
- $stm = $c->prepare($sql);
- $stm->execute();
- }
-
- //<favicons>
- $sql = sprintf(SQL_GET_FEEDS, $_SESSION['bd_prefix_user']);
- $stm = $c->prepare($sql);
- $stm->execute();
- $res = $stm->fetchAll(PDO::FETCH_ASSOC);
- foreach ($res as $feed) {
- if (empty($feed['url'])) {
- continue;
- }
- $hash = hash('crc32b', $_SESSION['salt'] . $feed['url']);
- @file_put_contents(DATA_PATH . '/favicons/' . $hash . '.txt',
- empty($feed['website']) ? $feed['url'] : $feed['website']);
- }
- //</favicons>
-}
-
-function deleteInstall () {
- $res = unlink (DATA_PATH . '/do-install.txt');
- if ($res) {
- header ('Location: index.php');
- }
-
- $needs = array('bd_type', 'bd_host', 'bd_base', 'bd_user', 'bd_password', 'bd_prefix');
- foreach ($needs as $need) {
- if (!isset($_SESSION[$need])) {
- return false;
- }
- }
-
- try {
- $c = newPdo();
- $sql = sprintf(SQL_DROP_BACKUPv006, $_SESSION['bd_prefix']);
- $stm = $c->prepare($sql);
- $stm->execute();
-
- return true;
- } catch (PDOException $e) {
+ if (!$res) {
return false;
}
- return false;
-}
-function moveOldFiles() {
- $mvs = array(
- '/app/configuration/application.ini' => '/data/application.ini', //v0.6
- '/public/data/Configuration.array.php' => '/data/Configuration.array.php', //v0.6
- );
- $ok = true;
- foreach ($mvs as $fFrom => $fTo) {
- if (file_exists(FRESHRSS_PATH . $fFrom)) {
- if (copy(FRESHRSS_PATH . $fFrom, FRESHRSS_PATH . $fTo)) {
- @unlink(FRESHRSS_PATH . $fFrom);
- } else {
- $ok = false;
- }
- }
- }
- return $ok;
+ header('Location: index.php');
}
-function delTree($dir) { //http://php.net/rmdir#110489
- if (!is_dir($dir)) {
- return true;
- }
- $files = array_diff(scandir($dir), array('.', '..'));
- foreach ($files as $file) {
- $f = $dir . '/' . $file;
- if (is_dir($f)) {
- @chmod($f, 0777);
- delTree($f);
- }
- else unlink($f);
- }
- return rmdir($dir);
-}
/*** VÉRIFICATIONS ***/
-function checkStep () {
- $s0 = checkStep0 ();
- $s1 = checkStep1 ();
- $s2 = checkStep2 ();
- $s3 = checkStep3 ();
+function checkStep() {
+ $s0 = checkStep0();
+ $s1 = checkStep1();
+ $s2 = checkStep2();
+ $s3 = checkStep3();
if (STEP > 0 && $s0['all'] != 'ok') {
- header ('Location: index.php?step=0');
+ header('Location: index.php?step=0');
} elseif (STEP > 1 && $s1['all'] != 'ok') {
- header ('Location: index.php?step=1');
+ header('Location: index.php?step=1');
} elseif (STEP > 2 && $s2['all'] != 'ok') {
- header ('Location: index.php?step=2');
+ header('Location: index.php?step=2');
} elseif (STEP > 3 && $s3['all'] != 'ok') {
- header ('Location: index.php?step=3');
+ header('Location: index.php?step=3');
}
$_SESSION['actualize_feeds'] = true;
}
-function checkStep0 () {
- moveOldFiles();
-
- if (file_exists(DATA_PATH . '/config.php')) {
- $ini_array = include(DATA_PATH . '/config.php');
- } elseif (file_exists(DATA_PATH . '/application.ini')) { //v0.6
- $ini_array = parse_ini_file(DATA_PATH . '/application.ini', true);
- $ini_array['general']['title'] = empty($ini_array['general']['title']) ? '' : stripslashes($ini_array['general']['title']);
- } else {
- $ini_array = null;
- }
- if ($ini_array) {
- $ini_general = isset($ini_array['general']) ? $ini_array['general'] : null;
- if ($ini_general) {
- $keys = array('environment', 'salt', 'title', 'default_user', 'allow_anonymous', 'allow_anonymous_refresh', 'auth_type', 'api_enabled', 'unsafe_autologin_enabled');
- foreach ($keys as $key) {
- if ((empty($_SESSION[$key])) && isset($ini_general[$key])) {
- $_SESSION[$key] = $ini_general[$key];
- }
- }
- }
- $ini_db = isset($ini_array['db']) ? $ini_array['db'] : null;
- if ($ini_db) {
- $keys = array('type', 'host', 'user', 'password', 'base', 'prefix');
- foreach ($keys as $key) {
- if ((!isset($_SESSION['bd_' . $key])) && isset($ini_db[$key])) {
- $_SESSION['bd_' . $key] = $ini_db[$key];
- }
- }
- }
- }
+function checkStep0() {
+ $languages = availableLanguages();
+ $language = isset($_SESSION['language']) &&
+ isset($languages[$_SESSION['language']]);
- if (isset($_SESSION['default_user']) && file_exists(DATA_PATH . '/' . $_SESSION['default_user'] . '_user.php')) {
- $userConfig = include(DATA_PATH . '/' . $_SESSION['default_user'] . '_user.php');
- } elseif (file_exists(DATA_PATH . '/Configuration.array.php')) {
- $userConfig = include(DATA_PATH . '/Configuration.array.php'); //v0.6
- if (empty($_SESSION['auth_type'])) {
- $_SESSION['auth_type'] = empty($userConfig['mail_login']) ? 'none' : 'persona';
- }
- if (!isset($_SESSION['allow_anonymous'])) {
- $_SESSION['allow_anonymous'] = empty($userConfig['anon_access']) ? false : ($userConfig['anon_access'] === 'yes');
- }
- } else {
- $userConfig = array();
- }
- if (empty($_SESSION['auth_type'])) { //v0.7b
- $_SESSION['auth_type'] = '';
- }
-
- $keys = array('language', 'theme', 'old_entries', 'mail_login', 'passwordHash');
- foreach ($keys as $key) {
- if ((!isset($_SESSION[$key])) && isset($userConfig[$key])) {
- $_SESSION[$key] = $userConfig[$key];
- }
- }
-
- $languages = availableLanguages ();
- $language = isset ($_SESSION['language']) &&
- isset ($languages[$_SESSION['language']]);
-
- if (empty($_SESSION['passwordHash'])) { //v0.7b
- $_SESSION['passwordHash'] = '';
- }
- if (empty($_SESSION['theme'])) {
- $_SESSION['theme'] = 'Origine';
- } else {
- switch (strtolower($_SESSION['theme'])) {
- case 'default': //v0.7b
- $_SESSION['theme'] = 'Origine';
- break;
- case 'flat-design': //v0.7b
- $_SESSION['theme'] = 'Flat';
- break;
- case 'default_dark': //v0.7b
- $_SESSION['theme'] = 'Dark';
- break;
- }
- }
-
- return array (
+ return array(
'language' => $language ? 'ok' : 'ko',
'all' => $language ? 'ok' : 'ko'
);
}
-function checkStep1 () {
- $php = version_compare (PHP_VERSION, '5.2.1') >= 0;
- $minz = file_exists (LIB_PATH . '/Minz');
- $curl = extension_loaded ('curl');
- $pdo_mysql = extension_loaded ('pdo_mysql');
- $pdo_sqlite = extension_loaded ('pdo_sqlite');
+function checkStep1() {
+ $php = version_compare(PHP_VERSION, '5.2.1') >= 0;
+ $minz = file_exists(LIB_PATH . '/Minz');
+ $curl = extension_loaded('curl');
+ $pdo_mysql = extension_loaded('pdo_mysql');
+ $pdo_sqlite = extension_loaded('pdo_sqlite');
$pdo = $pdo_mysql || $pdo_sqlite;
- $pcre = extension_loaded ('pcre');
- $ctype = extension_loaded ('ctype');
+ $pcre = extension_loaded('pcre');
+ $ctype = extension_loaded('ctype');
$dom = class_exists('DOMDocument');
- $data = DATA_PATH && is_writable (DATA_PATH);
- $cache = CACHE_PATH && is_writable (CACHE_PATH);
- $log = LOG_PATH && is_writable (LOG_PATH);
- $favicons = is_writable (DATA_PATH . '/favicons');
- $persona = is_writable (DATA_PATH . '/persona');
-
- return array (
+ $data = DATA_PATH && is_writable(DATA_PATH);
+ $cache = CACHE_PATH && is_writable(CACHE_PATH);
+ $log = LOG_PATH && is_writable(LOG_PATH);
+ $favicons = is_writable(DATA_PATH . '/favicons');
+ $persona = is_writable(DATA_PATH . '/persona');
+ $http_referer = is_referer_from_same_domain();
+
+ return array(
'php' => $php ? 'ok' : 'ko',
'minz' => $minz ? 'ok' : 'ko',
'curl' => $curl ? 'ok' : 'ko',
@@ -601,44 +324,57 @@ function checkStep1 () {
'log' => $log ? 'ok' : 'ko',
'favicons' => $favicons ? 'ok' : 'ko',
'persona' => $persona ? 'ok' : 'ko',
- 'all' => $php && $minz && $curl && $pdo && $pcre && $ctype && $dom && $data && $cache && $log && $favicons && $persona ? 'ok' : 'ko'
+ 'http_referer' => $http_referer ? 'ok' : 'ko',
+ 'all' => $php && $minz && $curl && $pdo && $pcre && $ctype && $dom &&
+ $data && $cache && $log && $favicons && $persona && $http_referer ?
+ 'ok' : 'ko'
);
}
-function checkStep2 () {
- $conf = !empty($_SESSION['salt']) &&
- !empty($_SESSION['title']) &&
+function checkStep2() {
+ $conf = !empty($_SESSION['title']) &&
!empty($_SESSION['old_entries']) &&
isset($_SESSION['mail_login']) &&
!empty($_SESSION['default_user']);
+
+ $form = (
+ isset($_SESSION['auth_type']) &&
+ ($_SESSION['auth_type'] != 'form' || !empty($_SESSION['passwordHash']))
+ );
+
+ $persona = (
+ isset($_SESSION['auth_type']) &&
+ ($_SESSION['auth_type'] != 'persona' || !empty($_SESSION['mail_login']))
+ );
+
$defaultUser = empty($_POST['default_user']) ? null : $_POST['default_user'];
if ($defaultUser === null) {
$defaultUser = empty($_SESSION['default_user']) ? '' : $_SESSION['default_user'];
}
$data = is_writable(DATA_PATH . '/' . $defaultUser . '_user.php');
- if ($data) {
- @unlink(DATA_PATH . '/Configuration.array.php'); //v0.6
- }
- return array (
+ return array(
'conf' => $conf ? 'ok' : 'ko',
+ 'form' => $form ? 'ok' : 'ko',
+ 'persona' => $persona ? 'ok' : 'ko',
'data' => $data ? 'ok' : 'ko',
- 'all' => $conf && $data ? 'ok' : 'ko'
+ 'all' => $conf && $form && $persona && $data ? 'ok' : 'ko'
);
}
-function checkStep3 () {
+
+function checkStep3() {
$conf = is_writable(DATA_PATH . '/config.php');
- $bd = isset ($_SESSION['bd_type']) &&
- isset ($_SESSION['bd_host']) &&
- isset ($_SESSION['bd_user']) &&
- isset ($_SESSION['bd_password']) &&
- isset ($_SESSION['bd_base']) &&
- isset ($_SESSION['bd_prefix']) &&
- isset ($_SESSION['bd_error']);
+ $bd = isset($_SESSION['bd_type']) &&
+ isset($_SESSION['bd_host']) &&
+ isset($_SESSION['bd_user']) &&
+ isset($_SESSION['bd_password']) &&
+ isset($_SESSION['bd_base']) &&
+ isset($_SESSION['bd_prefix']) &&
+ isset($_SESSION['bd_error']);
$conn = empty($_SESSION['bd_error']);
- return array (
+ return array(
'bd' => $bd ? 'ok' : 'ko',
'conn' => $conn ? 'ok' : 'ko',
'conf' => $conf ? 'ok' : 'ko',
@@ -646,51 +382,41 @@ function checkStep3 () {
);
}
-function checkBD () {
+function checkBD() {
$ok = false;
try {
$str = '';
$driver_options = null;
switch ($_SESSION['bd_type']) {
- case 'mysql':
- $driver_options = array(
- PDO::MYSQL_ATTR_INIT_COMMAND => 'SET NAMES utf8'
- );
-
- try { // on ouvre une connexion juste pour créer la base si elle n'existe pas
- $str = 'mysql:host=' . $_SESSION['bd_host'] . ';';
- $c = new PDO ($str, $_SESSION['bd_user'], $_SESSION['bd_password'], $driver_options);
- $sql = sprintf (SQL_CREATE_DB, $_SESSION['bd_base']);
- $res = $c->query ($sql);
- } catch (PDOException $e) {
- }
-
- // on écrase la précédente connexion en sélectionnant la nouvelle BDD
- $str = 'mysql:host=' . $_SESSION['bd_host'] . ';dbname=' . $_SESSION['bd_base'];
- break;
- case 'sqlite':
- $str = 'sqlite:' . DATA_PATH . '/' . $_SESSION['default_user'] . '.sqlite';
- $driver_options = array(
- PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
- );
- break;
- default:
- return false;
- }
-
- $c = new PDO ($str, $_SESSION['bd_user'], $_SESSION['bd_password'], $driver_options);
+ case 'mysql':
+ $driver_options = array(
+ PDO::MYSQL_ATTR_INIT_COMMAND => 'SET NAMES utf8'
+ );
- if ($_SESSION['bd_type'] !== 'sqlite') { //No SQL backup for SQLite
- $stm = $c->prepare(SQL_SHOW_TABLES);
- $stm->execute();
- $res = $stm->fetchAll(PDO::FETCH_COLUMN, 0);
- if (in_array($_SESSION['bd_prefix'] . 'entry', $res) && !in_array($_SESSION['bd_prefix'] . 'entry006', $res)) {
- $sql = sprintf(SQL_BACKUP006, $_SESSION['bd_prefix']); //v0.6
- $res = $c->query($sql); //Backup tables
+ try { // on ouvre une connexion juste pour créer la base si elle n'existe pas
+ $str = 'mysql:host=' . $_SESSION['bd_host'] . ';';
+ $c = new PDO($str, $_SESSION['bd_user'], $_SESSION['bd_password'], $driver_options);
+ $sql = sprintf(SQL_CREATE_DB, $_SESSION['bd_base']);
+ $res = $c->query($sql);
+ } catch (PDOException $e) {
}
+
+ // on écrase la précédente connexion en sélectionnant la nouvelle BDD
+ $str = 'mysql:host=' . $_SESSION['bd_host'] . ';dbname=' . $_SESSION['bd_base'];
+ break;
+ case 'sqlite':
+ $str = 'sqlite:' . DATA_PATH . '/' . $_SESSION['default_user'] . '.sqlite';
+ $driver_options = array(
+ PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
+ );
+ break;
+ default:
+ return false;
}
+ $c = new PDO($str, $_SESSION['bd_user'], $_SESSION['bd_password'], $driver_options);
+
if (defined('SQL_CREATE_TABLES')) {
$sql = sprintf(SQL_CREATE_TABLES, $_SESSION['bd_prefix_user'], _t('default_category'));
$stm = $c->prepare($sql);
@@ -719,20 +445,20 @@ function checkBD () {
}
/*** AFFICHAGE ***/
-function printStep0 () {
+function printStep0() {
global $actual;
?>
- <?php $s0 = checkStep0 (); if ($s0['all'] == 'ok') { ?>
- <p class="alert alert-success"><span class="alert-head"><?php echo _t ('ok'); ?></span> <?php echo _t ('language_defined'); ?></p>
+ <?php $s0 = checkStep0(); if ($s0['all'] == 'ok') { ?>
+ <p class="alert alert-success"><span class="alert-head"><?php echo _t('ok'); ?></span> <?php echo _t('language_defined'); ?></p>
<?php } ?>
<form action="index.php?step=0" method="post">
- <legend><?php echo _t ('choose_language'); ?></legend>
+ <legend><?php echo _t('choose_language'); ?></legend>
<div class="form-group">
- <label class="group-name" for="language"><?php echo _t ('language'); ?></label>
+ <label class="group-name" for="language"><?php echo _t('language'); ?></label>
<div class="group-controls">
<select name="language" id="language">
- <?php $languages = availableLanguages (); ?>
+ <?php $languages = availableLanguages(); ?>
<?php foreach ($languages as $short => $lib) { ?>
<option value="<?php echo $short; ?>"<?php echo $actual == $short ? ' selected="selected"' : ''; ?>><?php echo $lib; ?></option>
<?php } ?>
@@ -742,10 +468,10 @@ function printStep0 () {
<div class="form-group form-actions">
<div class="group-controls">
- <button type="submit" class="btn btn-important"><?php echo _t ('save'); ?></button>
- <button type="reset" class="btn"><?php echo _t ('cancel'); ?></button>
+ <button type="submit" class="btn btn-important"><?php echo _t('save'); ?></button>
+ <button type="reset" class="btn"><?php echo _t('cancel'); ?></button>
<?php if ($s0['all'] == 'ok') { ?>
- <a class="btn btn-important next-step" href="?step=1"><?php echo _t ('next_step'); ?></a>
+ <a class="btn btn-important next-step" href="?step=1"><?php echo _t('next_step'); ?></a>
<?php } ?>
</div>
</div>
@@ -753,133 +479,144 @@ function printStep0 () {
<?php
}
-function printStep1 () {
- $res = checkStep1 ();
+function printStep1() {
+ $res = checkStep1();
?>
- <noscript><p class="alert alert-warn"><span class="alert-head"><?php echo _t ('attention'); ?></span> <?php echo _t ('javascript_is_better'); ?></p></noscript>
+ <noscript><p class="alert alert-warn"><span class="alert-head"><?php echo _t('attention'); ?></span> <?php echo _t('javascript_is_better'); ?></p></noscript>
<?php if ($res['php'] == 'ok') { ?>
- <p class="alert alert-success"><span class="alert-head"><?php echo _t ('ok'); ?></span> <?php echo _t ('php_is_ok', PHP_VERSION); ?></p>
+ <p class="alert alert-success"><span class="alert-head"><?php echo _t('ok'); ?></span> <?php echo _t('php_is_ok', PHP_VERSION); ?></p>
<?php } else { ?>
- <p class="alert alert-error"><span class="alert-head"><?php echo _t ('damn'); ?></span> <?php echo _t ('php_is_nok', PHP_VERSION, '5.2.1'); ?></p>
+ <p class="alert alert-error"><span class="alert-head"><?php echo _t('damn'); ?></span> <?php echo _t('php_is_nok', PHP_VERSION, '5.2.1'); ?></p>
<?php } ?>
<?php if ($res['minz'] == 'ok') { ?>
- <p class="alert alert-success"><span class="alert-head"><?php echo _t ('ok'); ?></span> <?php echo _t ('minz_is_ok'); ?></p>
+ <p class="alert alert-success"><span class="alert-head"><?php echo _t('ok'); ?></span> <?php echo _t('minz_is_ok'); ?></p>
<?php } else { ?>
- <p class="alert alert-error"><span class="alert-head"><?php echo _t ('damn'); ?></span> <?php echo _t ('minz_is_nok', LIB_PATH . '/Minz'); ?></p>
+ <p class="alert alert-error"><span class="alert-head"><?php echo _t('damn'); ?></span> <?php echo _t('minz_is_nok', LIB_PATH . '/Minz'); ?></p>
<?php } ?>
<?php if ($res['pdo'] == 'ok') { ?>
- <p class="alert alert-success"><span class="alert-head"><?php echo _t ('ok'); ?></span> <?php echo _t ('pdo_is_ok'); ?></p>
+ <p class="alert alert-success"><span class="alert-head"><?php echo _t('ok'); ?></span> <?php echo _t('pdo_is_ok'); ?></p>
<?php } else { ?>
- <p class="alert alert-error"><span class="alert-head"><?php echo _t ('damn'); ?></span> <?php echo _t ('pdo_is_nok'); ?></p>
+ <p class="alert alert-error"><span class="alert-head"><?php echo _t('damn'); ?></span> <?php echo _t('pdo_is_nok'); ?></p>
<?php } ?>
<?php if ($res['curl'] == 'ok') { ?>
<?php $version = curl_version(); ?>
- <p class="alert alert-success"><span class="alert-head"><?php echo _t ('ok'); ?></span> <?php echo _t ('curl_is_ok', $version['version']); ?></p>
+ <p class="alert alert-success"><span class="alert-head"><?php echo _t('ok'); ?></span> <?php echo _t('curl_is_ok', $version['version']); ?></p>
<?php } else { ?>
- <p class="alert alert-error"><span class="alert-head"><?php echo _t ('damn'); ?></span> <?php echo _t ('curl_is_nok'); ?></p>
+ <p class="alert alert-error"><span class="alert-head"><?php echo _t('damn'); ?></span> <?php echo _t('curl_is_nok'); ?></p>
<?php } ?>
<?php if ($res['pcre'] == 'ok') { ?>
- <p class="alert alert-success"><span class="alert-head"><?php echo _t ('ok'); ?></span> <?php echo _t ('pcre_is_ok'); ?></p>
+ <p class="alert alert-success"><span class="alert-head"><?php echo _t('ok'); ?></span> <?php echo _t('pcre_is_ok'); ?></p>
<?php } else { ?>
- <p class="alert alert-error"><span class="alert-head"><?php echo _t ('damn'); ?></span> <?php echo _t ('pcre_is_nok'); ?></p>
+ <p class="alert alert-error"><span class="alert-head"><?php echo _t('damn'); ?></span> <?php echo _t('pcre_is_nok'); ?></p>
<?php } ?>
<?php if ($res['ctype'] == 'ok') { ?>
- <p class="alert alert-success"><span class="alert-head"><?php echo _t ('ok'); ?></span> <?php echo _t ('ctype_is_ok'); ?></p>
+ <p class="alert alert-success"><span class="alert-head"><?php echo _t('ok'); ?></span> <?php echo _t('ctype_is_ok'); ?></p>
<?php } else { ?>
- <p class="alert alert-error"><span class="alert-head"><?php echo _t ('damn'); ?></span> <?php echo _t ('ctype_is_nok'); ?></p>
+ <p class="alert alert-error"><span class="alert-head"><?php echo _t('damn'); ?></span> <?php echo _t('ctype_is_nok'); ?></p>
<?php } ?>
<?php if ($res['dom'] == 'ok') { ?>
- <p class="alert alert-success"><span class="alert-head"><?php echo _t ('ok'); ?></span> <?php echo _t ('dom_is_ok'); ?></p>
+ <p class="alert alert-success"><span class="alert-head"><?php echo _t('ok'); ?></span> <?php echo _t('dom_is_ok'); ?></p>
<?php } else { ?>
- <p class="alert alert-error"><span class="alert-head"><?php echo _t ('damn'); ?></span> <?php echo _t ('dom_is_nok'); ?></p>
+ <p class="alert alert-error"><span class="alert-head"><?php echo _t('damn'); ?></span> <?php echo _t('dom_is_nok'); ?></p>
<?php } ?>
<?php if ($res['data'] == 'ok') { ?>
- <p class="alert alert-success"><span class="alert-head"><?php echo _t ('ok'); ?></span> <?php echo _t ('data_is_ok'); ?></p>
+ <p class="alert alert-success"><span class="alert-head"><?php echo _t('ok'); ?></span> <?php echo _t('data_is_ok'); ?></p>
<?php } else { ?>
- <p class="alert alert-error"><span class="alert-head"><?php echo _t ('damn'); ?></span> <?php echo _t ('file_is_nok', DATA_PATH); ?></p>
+ <p class="alert alert-error"><span class="alert-head"><?php echo _t('damn'); ?></span> <?php echo _t('file_is_nok', DATA_PATH); ?></p>
<?php } ?>
<?php if ($res['cache'] == 'ok') { ?>
- <p class="alert alert-success"><span class="alert-head"><?php echo _t ('ok'); ?></span> <?php echo _t ('cache_is_ok'); ?></p>
+ <p class="alert alert-success"><span class="alert-head"><?php echo _t('ok'); ?></span> <?php echo _t('cache_is_ok'); ?></p>
<?php } else { ?>
- <p class="alert alert-error"><span class="alert-head"><?php echo _t ('damn'); ?></span> <?php echo _t ('file_is_nok', CACHE_PATH); ?></p>
+ <p class="alert alert-error"><span class="alert-head"><?php echo _t('damn'); ?></span> <?php echo _t('file_is_nok', CACHE_PATH); ?></p>
<?php } ?>
<?php if ($res['log'] == 'ok') { ?>
- <p class="alert alert-success"><span class="alert-head"><?php echo _t ('ok'); ?></span> <?php echo _t ('log_is_ok'); ?></p>
+ <p class="alert alert-success"><span class="alert-head"><?php echo _t('ok'); ?></span> <?php echo _t('log_is_ok'); ?></p>
<?php } else { ?>
- <p class="alert alert-error"><span class="alert-head"><?php echo _t ('damn'); ?></span> <?php echo _t ('file_is_nok', LOG_PATH); ?></p>
+ <p class="alert alert-error"><span class="alert-head"><?php echo _t('damn'); ?></span> <?php echo _t('file_is_nok', LOG_PATH); ?></p>
<?php } ?>
<?php if ($res['favicons'] == 'ok') { ?>
- <p class="alert alert-success"><span class="alert-head"><?php echo _t ('ok'); ?></span> <?php echo _t ('favicons_is_ok'); ?></p>
+ <p class="alert alert-success"><span class="alert-head"><?php echo _t('ok'); ?></span> <?php echo _t('favicons_is_ok'); ?></p>
<?php } else { ?>
- <p class="alert alert-error"><span class="alert-head"><?php echo _t ('damn'); ?></span> <?php echo _t ('file_is_nok', DATA_PATH . '/favicons'); ?></p>
+ <p class="alert alert-error"><span class="alert-head"><?php echo _t('damn'); ?></span> <?php echo _t('file_is_nok', DATA_PATH . '/favicons'); ?></p>
<?php } ?>
<?php if ($res['persona'] == 'ok') { ?>
- <p class="alert alert-success"><span class="alert-head"><?php echo _t ('ok'); ?></span> <?php echo _t ('persona_is_ok'); ?></p>
+ <p class="alert alert-success"><span class="alert-head"><?php echo _t('ok'); ?></span> <?php echo _t('persona_is_ok'); ?></p>
<?php } else { ?>
- <p class="alert alert-error"><span class="alert-head"><?php echo _t ('damn'); ?></span> <?php echo _t ('file_is_nok', DATA_PATH . '/persona'); ?></p>
+ <p class="alert alert-error"><span class="alert-head"><?php echo _t('damn'); ?></span> <?php echo _t('file_is_nok', DATA_PATH . '/persona'); ?></p>
+ <?php } ?>
+
+ <?php if ($res['http_referer'] == 'ok') { ?>
+ <p class="alert alert-success"><span class="alert-head"><?php echo _t('ok'); ?></span> <?php echo _t('http_referer_is_ok'); ?></p>
+ <?php } else { ?>
+ <p class="alert alert-error"><span class="alert-head"><?php echo _t('damn'); ?></span> <?php echo _t('http_referer_is_nok'); ?></p>
<?php } ?>
<?php if ($res['all'] == 'ok') { ?>
- <a class="btn btn-important next-step" href="?step=2"><?php echo _t ('next_step'); ?></a>
+ <a class="btn btn-important next-step" href="?step=2"><?php echo _t('next_step'); ?></a>
<?php } else { ?>
- <p class="alert alert-error"><?php echo _t ('fix_errors_before'); ?></p>
+ <p class="alert alert-error"><?php echo _t('fix_errors_before'); ?></p>
<?php } ?>
<?php
}
-function printStep2 () {
+function printStep2() {
?>
- <?php $s2 = checkStep2 (); if ($s2['all'] == 'ok') { ?>
- <p class="alert alert-success"><span class="alert-head"><?php echo _t ('ok'); ?></span> <?php echo _t ('general_conf_is_ok'); ?></p>
+ <?php $s2 = checkStep2(); if ($s2['all'] == 'ok') { ?>
+ <p class="alert alert-success"><span class="alert-head"><?php echo _t('ok'); ?></span> <?php echo _t('general_conf_is_ok'); ?></p>
+ <?php } elseif (!empty($_POST)) { ?>
+ <p class="alert alert-error"><?php echo _t('fix_errors_before'); ?></p>
<?php } ?>
<form action="index.php?step=2" method="post">
- <legend><?php echo _t ('general_configuration'); ?></legend>
+ <legend><?php echo _t('general_configuration'); ?></legend>
<div class="form-group">
- <label class="group-name" for="title"><?php echo _t ('title'); ?></label>
+ <label class="group-name" for="title"><?php echo _t('title'); ?></label>
<div class="group-controls">
- <input type="text" id="title" name="title" value="<?php echo isset ($_SESSION['title']) ? $_SESSION['title'] : _t ('freshrss'); ?>" />
+ <input type="text" id="title" name="title" value="<?php echo isset($_SESSION['title']) ? $_SESSION['title'] : _t('freshrss'); ?>" />
</div>
</div>
<div class="form-group">
- <label class="group-name" for="old_entries"><?php echo _t ('delete_articles_every'); ?></label>
+ <label class="group-name" for="old_entries"><?php echo _t('delete_articles_every'); ?></label>
<div class="group-controls">
- <input type="number" id="old_entries" name="old_entries" required="required" min="1" max="1200" value="<?php echo isset ($_SESSION['old_entries']) ? $_SESSION['old_entries'] : '3'; ?>" /> <?php echo _t ('month'); ?>
+ <input type="number" id="old_entries" name="old_entries" required="required" min="1" max="1200" value="<?php echo isset($_SESSION['old_entries']) ? $_SESSION['old_entries'] : '3'; ?>" /> <?php echo _t('month'); ?>
</div>
</div>
<div class="form-group">
- <label class="group-name" for="default_user"><?php echo _t ('default_user'); ?></label>
+ <label class="group-name" for="default_user"><?php echo _t('default_user'); ?></label>
<div class="group-controls">
- <input type="text" id="default_user" name="default_user" required="required" size="16" maxlength="16" pattern="[0-9a-zA-Z]{1,16}" value="<?php echo isset ($_SESSION['default_user']) ? $_SESSION['default_user'] : ''; ?>" placeholder="<?php echo httpAuthUser() == '' ? 'user1' : httpAuthUser(); ?>" />
+ <input type="text" id="default_user" name="default_user" required="required" size="16" maxlength="16" pattern="[0-9a-zA-Z]{1,16}" value="<?php echo isset($_SESSION['default_user']) ? $_SESSION['default_user'] : ''; ?>" placeholder="<?php echo httpAuthUser() == '' ? 'user1' : httpAuthUser(); ?>" />
</div>
</div>
<div class="form-group">
<label class="group-name" for="auth_type"><?php echo _t('auth_type'); ?></label>
<div class="group-controls">
- <select id="auth_type" name="auth_type" required="required">
- <?php if (!in_array($_SESSION['auth_type'], array('form', 'persona', 'http_auth', 'none'))) { ?>
- <option selected="selected"></option>
- <?php } ?>
- <option value="form"<?php echo $_SESSION['auth_type'] === 'form' ? ' selected="selected"' : '', cryptAvailable() ? '' : ' disabled="disabled"'; ?>><?php echo _t('auth_form'); ?></option>
- <option value="persona"<?php echo $_SESSION['auth_type'] === 'persona' ? ' selected="selected"' : ''; ?>><?php echo _t('auth_persona'); ?></option>
- <option value="http_auth"<?php echo $_SESSION['auth_type'] === 'http_auth' ? ' selected="selected"' : '', httpAuthUser() == '' ? ' disabled="disabled"' : ''; ?>><?php echo _t('http_auth'); ?> (REMOTE_USER = '<?php echo httpAuthUser(); ?>')</option>
- <option value="none"<?php echo $_SESSION['auth_type'] === 'none' ? ' selected="selected"' : ''; ?>><?php echo _t('auth_none'); ?></option>
+ <select id="auth_type" name="auth_type" required="required" onchange="auth_type_change(true)">
+ <?php
+ function no_auth($auth_type) {
+ return !in_array($auth_type, array('form', 'persona', 'http_auth', 'none'));
+ }
+ $auth_type = isset($_SESSION['auth_type']) ? $_SESSION['auth_type'] : '';
+ ?>
+ <option value="form"<?php echo $auth_type === 'form' || no_auth($auth_type) ? ' selected="selected"' : '', cryptAvailable() ? '' : ' disabled="disabled"'; ?>><?php echo _t('auth_form'); ?></option>
+ <option value="persona"<?php echo $auth_type === 'persona' ? ' selected="selected"' : ''; ?>><?php echo _t('auth_persona'); ?></option>
+ <option value="http_auth"<?php echo $auth_type === 'http_auth' ? ' selected="selected"' : '', httpAuthUser() == '' ? ' disabled="disabled"' : ''; ?>><?php echo _t('http_auth'); ?>(REMOTE_USER = '<?php echo httpAuthUser(); ?>')</option>
+ <option value="none"<?php echo $auth_type === 'none' ? ' selected="selected"' : ''; ?>><?php echo _t('auth_none'); ?></option>
</select>
</div>
</div>
@@ -887,25 +624,73 @@ function printStep2 () {
<div class="form-group">
<label class="group-name" for="passwordPlain"><?php echo _t('password_form'); ?></label>
<div class="group-controls">
- <input type="password" id="passwordPlain" name="passwordPlain" pattern=".{7,}" autocomplete="off" />
+ <div class="stick">
+ <input type="password" id="passwordPlain" name="passwordPlain" pattern=".{7,}" autocomplete="off" <?php echo $auth_type === 'form' ? ' required="required"' : ''; ?> />
+ <a class="btn toggle-password" data-toggle="passwordPlain"><?php echo FreshRSS_Themes::icon('key'); ?></a>
+ </div>
<noscript><b><?php echo _t('javascript_should_be_activated'); ?></b></noscript>
</div>
</div>
<div class="form-group">
- <label class="group-name" for="mail_login"><?php echo _t ('persona_connection_email'); ?></label>
+ <label class="group-name" for="mail_login"><?php echo _t('persona_connection_email'); ?></label>
<div class="group-controls">
- <input type="email" id="mail_login" name="mail_login" value="<?php echo isset ($_SESSION['mail_login']) ? $_SESSION['mail_login'] : ''; ?>" placeholder="alice@example.net" />
- <noscript><b><?php echo _t ('javascript_should_be_activated'); ?></b></noscript>
+ <input type="email" id="mail_login" name="mail_login" value="<?php echo isset($_SESSION['mail_login']) ? $_SESSION['mail_login'] : ''; ?>" placeholder="alice@example.net" <?php echo $auth_type === 'persona' ? ' required="required"' : ''; ?> />
+ <noscript><b><?php echo _t('javascript_should_be_activated'); ?></b></noscript>
</div>
</div>
+ <script>
+ function toggle_password() {
+ var button = this;
+ var passwordField = document.getElementById(button.getAttribute('data-toggle'));
+
+ passwordField.setAttribute('type', 'text');
+ button.className += ' active';
+
+ setTimeout(function() {
+ passwordField.setAttribute('type', 'password');
+ button.className = button.className.replace(/(?:^|\s)active(?!\S)/g , '');
+ }, 2000);
+
+ return false;
+ }
+ toggles = document.getElementsByClassName('toggle-password');
+ for (var i = 0 ; i < toggles.length ; i++) {
+ toggles[i].addEventListener('click', toggle_password);
+ }
+
+ function auth_type_change(focus) {
+ var auth_value = document.getElementById('auth_type').value,
+ password_input = document.getElementById('passwordPlain'),
+ mail_input = document.getElementById('mail_login');
+
+ if (auth_value === 'form') {
+ password_input.required = true;
+ mail_input.required = false;
+ if (focus) {
+ password_input.focus();
+ }
+ } else if (auth_value === 'persona') {
+ password_input.required = false;
+ mail_input.required = true;
+ if (focus) {
+ mail_input.focus();
+ }
+ } else {
+ password_input.required = false;
+ mail_input.required = false;
+ }
+ }
+ auth_type_change(false);
+ </script>
+
<div class="form-group form-actions">
<div class="group-controls">
- <button type="submit" class="btn btn-important"><?php echo _t ('save'); ?></button>
- <button type="reset" class="btn"><?php echo _t ('cancel'); ?></button>
+ <button type="submit" class="btn btn-important"><?php echo _t('save'); ?></button>
+ <button type="reset" class="btn"><?php echo _t('cancel'); ?></button>
<?php if ($s2['all'] == 'ok') { ?>
- <a class="btn btn-important next-step" href="?step=3"><?php echo _t ('next_step'); ?></a>
+ <a class="btn btn-important next-step" href="?step=3"><?php echo _t('next_step'); ?></a>
<?php } ?>
</div>
</div>
@@ -913,29 +698,29 @@ function printStep2 () {
<?php
}
-function printStep3 () {
+function printStep3() {
?>
- <?php $s3 = checkStep3 (); if ($s3['all'] == 'ok') { ?>
- <p class="alert alert-success"><span class="alert-head"><?php echo _t ('ok'); ?></span> <?php echo _t ('bdd_conf_is_ok'); ?></p>
+ <?php $s3 = checkStep3(); if ($s3['all'] == 'ok') { ?>
+ <p class="alert alert-success"><span class="alert-head"><?php echo _t('ok'); ?></span> <?php echo _t('bdd_conf_is_ok'); ?></p>
<?php } elseif ($s3['conn'] == 'ko') { ?>
- <p class="alert alert-error"><span class="alert-head"><?php echo _t ('damn'); ?></span> <?php echo _t ('bdd_conf_is_ko'), (empty($_SESSION['bd_error']) ? '' : ' : ' . $_SESSION['bd_error']); ?></p>
+ <p class="alert alert-error"><span class="alert-head"><?php echo _t('damn'); ?></span> <?php echo _t('bdd_conf_is_ko'),(empty($_SESSION['bd_error']) ? '' : ' : ' . $_SESSION['bd_error']); ?></p>
<?php } ?>
<form action="index.php?step=3" method="post">
- <legend><?php echo _t ('bdd_configuration'); ?></legend>
+ <legend><?php echo _t('bdd_configuration'); ?></legend>
<div class="form-group">
- <label class="group-name" for="type"><?php echo _t ('bdd_type'); ?></label>
+ <label class="group-name" for="type"><?php echo _t('bdd_type'); ?></label>
<div class="group-controls">
<select name="type" id="type" onchange="mySqlShowHide()">
<?php if (extension_loaded('pdo_mysql')) {?>
<option value="mysql"
- <?php echo (isset($_SESSION['bd_type']) && $_SESSION['bd_type'] === 'mysql') ? 'selected="selected"' : ''; ?>>
+ <?php echo(isset($_SESSION['bd_type']) && $_SESSION['bd_type'] === 'mysql') ? 'selected="selected"' : ''; ?>>
MySQL
</option>
<?php }?>
<?php if (extension_loaded('pdo_sqlite')) {?>
<option value="sqlite"
- <?php echo (isset($_SESSION['bd_type']) && $_SESSION['bd_type'] === 'sqlite') ? 'selected="selected"' : ''; ?>>
+ <?php echo(isset($_SESSION['bd_type']) && $_SESSION['bd_type'] === 'sqlite') ? 'selected="selected"' : ''; ?>>
SQLite
</option>
<?php }?>
@@ -945,37 +730,37 @@ function printStep3 () {
<div id="mysql">
<div class="form-group">
- <label class="group-name" for="host"><?php echo _t ('host'); ?></label>
+ <label class="group-name" for="host"><?php echo _t('host'); ?></label>
<div class="group-controls">
- <input type="text" id="host" name="host" pattern="[0-9A-Za-z_.-]{1,64}" value="<?php echo isset ($_SESSION['bd_host']) ? $_SESSION['bd_host'] : 'localhost'; ?>" />
+ <input type="text" id="host" name="host" pattern="[0-9A-Za-z_.-]{1,64}" value="<?php echo isset($_SESSION['bd_host']) ? $_SESSION['bd_host'] : 'localhost'; ?>" />
</div>
</div>
<div class="form-group">
- <label class="group-name" for="user"><?php echo _t ('username'); ?></label>
+ <label class="group-name" for="user"><?php echo _t('username'); ?></label>
<div class="group-controls">
- <input type="text" id="user" name="user" maxlength="16" pattern="[0-9A-Za-z_.-]{1,16}" value="<?php echo isset ($_SESSION['bd_user']) ? $_SESSION['bd_user'] : ''; ?>" />
+ <input type="text" id="user" name="user" maxlength="16" pattern="[0-9A-Za-z_.-]{1,16}" value="<?php echo isset($_SESSION['bd_user']) ? $_SESSION['bd_user'] : ''; ?>" />
</div>
</div>
<div class="form-group">
- <label class="group-name" for="pass"><?php echo _t ('password'); ?></label>
+ <label class="group-name" for="pass"><?php echo _t('password'); ?></label>
<div class="group-controls">
- <input type="password" id="pass" name="pass" value="<?php echo isset ($_SESSION['bd_password']) ? $_SESSION['bd_password'] : ''; ?>" />
+ <input type="password" id="pass" name="pass" value="<?php echo isset($_SESSION['bd_password']) ? $_SESSION['bd_password'] : ''; ?>" />
</div>
</div>
<div class="form-group">
- <label class="group-name" for="base"><?php echo _t ('bdd'); ?></label>
+ <label class="group-name" for="base"><?php echo _t('bdd'); ?></label>
<div class="group-controls">
- <input type="text" id="base" name="base" maxlength="64" pattern="[0-9A-Za-z_]{1,64}" value="<?php echo isset ($_SESSION['bd_base']) ? $_SESSION['bd_base'] : ''; ?>" placeholder="freshrss" />
+ <input type="text" id="base" name="base" maxlength="64" pattern="[0-9A-Za-z_]{1,64}" value="<?php echo isset($_SESSION['bd_base']) ? $_SESSION['bd_base'] : ''; ?>" placeholder="freshrss" />
</div>
</div>
<div class="form-group">
- <label class="group-name" for="prefix"><?php echo _t ('prefix'); ?></label>
+ <label class="group-name" for="prefix"><?php echo _t('prefix'); ?></label>
<div class="group-controls">
- <input type="text" id="prefix" name="prefix" maxlength="16" pattern="[0-9A-Za-z_]{1,16}" value="<?php echo isset ($_SESSION['bd_prefix']) ? $_SESSION['bd_prefix'] : 'freshrss_'; ?>" />
+ <input type="text" id="prefix" name="prefix" maxlength="16" pattern="[0-9A-Za-z_]{1,16}" value="<?php echo isset($_SESSION['bd_prefix']) ? $_SESSION['bd_prefix'] : 'freshrss_'; ?>" />
</div>
</div>
</div>
@@ -988,10 +773,10 @@ function printStep3 () {
<div class="form-group form-actions">
<div class="group-controls">
- <button type="submit" class="btn btn-important"><?php echo _t ('save'); ?></button>
- <button type="reset" class="btn"><?php echo _t ('cancel'); ?></button>
+ <button type="submit" class="btn btn-important"><?php echo _t('save'); ?></button>
+ <button type="reset" class="btn"><?php echo _t('cancel'); ?></button>
<?php if ($s3['all'] == 'ok') { ?>
- <a class="btn btn-important next-step" href="?step=4"><?php echo _t ('next_step'); ?></a>
+ <a class="btn btn-important next-step" href="?step=4"><?php echo _t('next_step'); ?></a>
<?php } ?>
</div>
</div>
@@ -999,74 +784,40 @@ function printStep3 () {
<?php
}
-function printStep4 () {
+function printStep4() {
?>
- <form action="index.php?step=4" method="post">
- <legend><?php echo _t ('version_update'); ?></legend>
-
- <?php if (updateDatabase(false)) { ?>
- <p class="alert alert-warn"><?php echo _t ('update_long'); ?></p>
-
- <div class="form-group form-actions">
- <div class="group-controls">
- <input type="hidden" name="updateDatabase" value="1" />
- <button type="submit" class="btn btn-important"><?php echo _t ('update_start'); ?></button>
- </div>
- </div>
-
- <?php } else { ?>
- <p class="alert alert-warn"><?php echo _t ('update_end'); ?></p>
-
- <div class="form-group form-actions">
- <div class="group-controls">
- <a class="btn btn-important next-step" href="?step=5"><?php echo _t ('next_step'); ?></a>
- </div>
- </div>
- <?php } ?>
- </form>
-<?php
-}
-
-function printStep5 () {
-?>
- <p class="alert alert-success"><span class="alert-head"><?php echo _t ('congratulations'); ?></span> <?php echo _t ('installation_is_ok'); ?></p>
- <a class="btn btn-important next-step" href="?step=6"><?php echo _t ('finish_installation'); ?></a>
+ <p class="alert alert-success"><span class="alert-head"><?php echo _t('congratulations'); ?></span> <?php echo _t('installation_is_ok'); ?></p>
+ <a class="btn btn-important next-step" href="?step=5"><?php echo _t('finish_installation'); ?></a>
<?php
}
-function printStep6 () {
+function printStep5() {
?>
- <p class="alert alert-error"><span class="alert-head"><?php echo _t ('oops'); ?></span> <?php echo _t ('install_not_deleted', DATA_PATH . '/do-install.txt'); ?></p>
+ <p class="alert alert-error"><span class="alert-head"><?php echo _t('oops'); ?></span> <?php echo _t('install_not_deleted', DATA_PATH . '/do-install.txt'); ?></p>
<?php
}
-checkStep ();
+checkStep();
-initTranslate ();
+initTranslate();
switch (STEP) {
case 0:
default:
- saveLanguage ();
+ saveLanguage();
break;
case 1:
break;
case 2:
- saveStep2 ();
+ saveStep2();
break;
case 3:
- saveStep3 ();
+ saveStep3();
break;
case 4:
- if (!empty($_POST['updateDatabase'])) {
- updateDatabase(true);
- }
break;
case 5:
- postUpdate();
- break;
-case 6:
- deleteInstall ();
+ deleteInstall();
break;
}
?>
@@ -1075,28 +826,27 @@ case 6:
<head>
<meta charset="utf-8">
<meta name="viewport" content="initial-scale=1.0">
- <title><?php echo _t ('freshrss_installation'); ?></title>
- <link rel="stylesheet" type="text/css" media="all" href="../themes/Origine/template.css" />
+ <title><?php echo _t('freshrss_installation'); ?></title>
+ <link rel="stylesheet" type="text/css" media="all" href="../themes/base-theme/template.css" />
<link rel="stylesheet" type="text/css" media="all" href="../themes/Origine/origine.css" />
</head>
<body>
<div class="header">
<div class="item title">
- <h1><a href="index.php"><?php echo _t ('freshrss'); ?></a></h1>
- <h2><?php echo _t ('installation_step', STEP); ?></h2>
+ <h1><a href="index.php"><?php echo _t('freshrss'); ?></a></h1>
+ <h2><?php echo _t('installation_step', STEP); ?></h2>
</div>
</div>
<div id="global">
<ul class="nav nav-list aside">
- <li class="nav-header"><?php echo _t ('steps'); ?></li>
- <li class="item<?php echo STEP == 0 ? ' active' : ''; ?>"><a href="?step=0"><?php echo _t ('language'); ?></a></li>
- <li class="item<?php echo STEP == 1 ? ' active' : ''; ?>"><a href="?step=1"><?php echo _t ('checks'); ?></a></li>
- <li class="item<?php echo STEP == 2 ? ' active' : ''; ?>"><a href="?step=2"><?php echo _t ('general_configuration'); ?></a></li>
- <li class="item<?php echo STEP == 3 ? ' active' : ''; ?>"><a href="?step=3"><?php echo _t ('bdd_configuration'); ?></a></li>
- <li class="item<?php echo STEP == 4 ? ' active' : ''; ?>"><a href="?step=4"><?php echo _t ('version_update'); ?></a></li>
- <li class="item<?php echo STEP == 5 ? ' active' : ''; ?>"><a href="?step=5"><?php echo _t ('this_is_the_end'); ?></a></li>
+ <li class="nav-header"><?php echo _t('steps'); ?></li>
+ <li class="item<?php echo STEP == 0 ? ' active' : ''; ?>"><a href="?step=0"><?php echo _t('language'); ?></a></li>
+ <li class="item<?php echo STEP == 1 ? ' active' : ''; ?>"><a href="?step=1"><?php echo _t('checks'); ?></a></li>
+ <li class="item<?php echo STEP == 2 ? ' active' : ''; ?>"><a href="?step=2"><?php echo _t('general_configuration'); ?></a></li>
+ <li class="item<?php echo STEP == 3 ? ' active' : ''; ?>"><a href="?step=3"><?php echo _t('bdd_configuration'); ?></a></li>
+ <li class="item<?php echo STEP == 4 ? ' active' : ''; ?>"><a href="?step=5"><?php echo _t('this_is_the_end'); ?></a></li>
</ul>
<div class="post">
@@ -1104,25 +854,22 @@ case 6:
switch (STEP) {
case 0:
default:
- printStep0 ();
+ printStep0();
break;
case 1:
- printStep1 ();
+ printStep1();
break;
case 2:
- printStep2 ();
+ printStep2();
break;
case 3:
- printStep3 ();
+ printStep3();
break;
case 4:
- printStep4 ();
+ printStep4();
break;
case 5:
- printStep5 ();
- break;
- case 6:
- printStep6 ();
+ printStep5();
break;
}
?>
diff --git a/app/layout/aside_configure.phtml b/app/layout/aside_configure.phtml
index e66f2f64c..d5c9bf4c9 100644
--- a/app/layout/aside_configure.phtml
+++ b/app/layout/aside_configure.phtml
@@ -1,25 +1,33 @@
<ul class="nav nav-list aside">
- <li class="nav-header"><?php echo Minz_Translate::t ('configuration'); ?></li>
- <li class="item<?php echo Minz_Request::actionName () == 'display' ? ' active' : ''; ?>">
- <a href="<?php echo _url ('configure', 'display'); ?>"><?php echo Minz_Translate::t ('display_configuration'); ?></a>
+ <li class="nav-header"><?php echo _t('configuration'); ?></li>
+ <li class="item<?php echo Minz_Request::actionName() === 'display' ? ' active' : ''; ?>">
+ <a href="<?php echo _url('configure', 'display'); ?>"><?php echo _t('display_configuration'); ?></a>
</li>
- <li class="item<?php echo Minz_Request::actionName () == 'reading' ? ' active' : ''; ?>">
- <a href="<?php echo _url ('configure', 'reading'); ?>"><?php echo Minz_Translate::t ('reading_configuration'); ?></a>
+ <li class="item<?php echo Minz_Request::actionName() === 'reading' ? ' active' : ''; ?>">
+ <a href="<?php echo _url('configure', 'reading'); ?>"><?php echo _t('reading_configuration'); ?></a>
</li>
- <li class="item<?php echo Minz_Request::actionName () == 'archiving' ? ' active' : ''; ?>">
- <a href="<?php echo _url ('configure', 'archiving'); ?>"><?php echo Minz_Translate::t ('archiving_configuration'); ?></a>
+ <li class="item<?php echo Minz_Request::actionName() === 'archiving' ? ' active' : ''; ?>">
+ <a href="<?php echo _url('configure', 'archiving'); ?>"><?php echo _t('archiving_configuration'); ?></a>
</li>
- <li class="item<?php echo Minz_Request::actionName () == 'sharing' ? ' active' : ''; ?>">
- <a href="<?php echo _url ('configure', 'sharing'); ?>"><?php echo Minz_Translate::t ('sharing'); ?></a>
+ <li class="item<?php echo Minz_Request::actionName() === 'sharing' ? ' active' : ''; ?>">
+ <a href="<?php echo _url('configure', 'sharing'); ?>"><?php echo _t('sharing'); ?></a>
</li>
- <li class="item<?php echo Minz_Request::actionName () == 'shortcut' ? ' active' : ''; ?>">
- <a href="<?php echo _url ('configure', 'shortcut'); ?>"><?php echo Minz_Translate::t ('shortcuts'); ?></a>
+ <li class="item<?php echo Minz_Request::actionName() === 'shortcut' ? ' active' : ''; ?>">
+ <a href="<?php echo _url('configure', 'shortcut'); ?>"><?php echo _t('shortcuts'); ?></a>
</li>
- <li class="item<?php echo Minz_Request::actionName () == 'queries' ? ' active' : ''; ?>">
- <a href="<?php echo _url ('configure', 'queries'); ?>"><?php echo Minz_Translate::t ('queries'); ?></a>
+ <li class="item<?php echo Minz_Request::actionName() === 'queries' ? ' active' : ''; ?>">
+ <a href="<?php echo _url('configure', 'queries'); ?>"><?php echo _t('queries'); ?></a>
</li>
<li class="separator"></li>
- <li class="item<?php echo Minz_Request::actionName () == 'users' ? ' active' : ''; ?>">
- <a href="<?php echo _url ('configure', 'users'); ?>"><?php echo Minz_Translate::t ('users'); ?></a>
+ <li class="item<?php echo Minz_Request::actionName() === 'users' ? ' active' : ''; ?>">
+ <a href="<?php echo _url('configure', 'users'); ?>"><?php echo _t('users'); ?></a>
</li>
+ <?php
+ $current_user = Minz_Session::param('currentUser', '');
+ if (Minz_Configuration::isAdmin($current_user)) {
+ ?>
+ <li class="item<?php echo Minz_Request::controllerName() === 'update' ? ' active' : ''; ?>">
+ <a href="<?php echo _url('update', 'index'); ?>"><?php echo _t('update'); ?></a>
+ </li>
+ <?php } ?>
</ul>
diff --git a/app/layout/aside_flux.phtml b/app/layout/aside_flux.phtml
index 432d6fdb7..aac3c0896 100644
--- a/app/layout/aside_flux.phtml
+++ b/app/layout/aside_flux.phtml
@@ -1,16 +1,18 @@
<div class="aside aside_flux<?php if ($this->conf->hide_read_feeds && ($this->state & FreshRSS_Entry::STATE_NOT_READ) && !($this->state & FreshRSS_Entry::STATE_READ)) echo ' state_unread'; ?>" id="aside_flux">
- <a class="toggle_aside" href="#close"><?php echo FreshRSS_Themes::icon('close'); ?></a>
+ <a class="toggle_aside" href="#close"><?php echo _i('close'); ?></a>
<ul class="categories">
<?php if ($this->loginOk) { ?>
+ <form id="mark-read-aside" method="post" style="display: none"></form>
+
<li>
- <div class="stick">
- <a class="btn btn-important" href="<?php echo _url ('configure', 'feed'); ?>"><?php echo Minz_Translate::t ('subscription_management'); ?></a>
- <a class="btn btn-important" href="<?php echo _url ('configure', 'categorize'); ?>" title="<?php echo Minz_Translate::t ('categories_management'); ?>"><?php echo FreshRSS_Themes::icon('category-white'); ?></a>
+ <div class="stick configure-feeds">
+ <a class="btn btn-important" href="<?php echo _url('configure', 'feed'); ?>"><?php echo _t('subscription_management'); ?></a>
+ <a class="btn btn-important" href="<?php echo _url('configure', 'categorize'); ?>" title="<?php echo _t('categories_management'); ?>"><?php echo _i('category-white'); ?></a>
</div>
</li>
<?php } elseif (Minz_Configuration::needsLogin()) { ?>
- <li><a href="<?php echo _url ('index', 'about'); ?>"><?php echo Minz_Translate::t ('about_freshrss'); ?></a></li>
+ <li><a href="<?php echo _url('index', 'about'); ?>"><?php echo _t('about_freshrss'); ?></a></li>
<?php } ?>
<?php
@@ -22,8 +24,8 @@
<li>
<div class="category all<?php echo $this->get_c == 'a' ? ' active' : ''; ?>">
<a data-unread="<?php echo formatNumber($this->nb_not_read); ?>" class="btn<?php echo $this->get_c == 'a' ? ' active' : ''; ?>" href="<?php echo Minz_Url::display($arUrl); ?>">
- <?php echo FreshRSS_Themes::icon('all'); ?>
- <?php echo Minz_Translate::t ('main_stream'); ?>
+ <?php echo _i('all'); ?>
+ <?php echo _t('main_stream'); ?>
</a>
</div>
</li>
@@ -31,44 +33,42 @@
<li>
<div class="category favorites<?php echo $this->get_c == 's' ? ' active' : ''; ?>">
<a data-unread="<?php echo formatNumber($this->nb_favorites['unread']); ?>" class="btn<?php echo $this->get_c == 's' ? ' active' : ''; ?>" href="<?php $arUrl['params']['get'] = 's'; echo Minz_Url::display($arUrl); ?>">
- <?php echo FreshRSS_Themes::icon('bookmark'); ?>
- <?php echo Minz_Translate::t('favorite_feeds', formatNumber($this->nb_favorites['all'])); ?>
+ <?php echo _i('bookmark'); ?>
+ <?php echo _t('favorite_feeds', formatNumber($this->nb_favorites['all'])); ?>
</a>
</div>
</li>
<?php
foreach ($this->cat_aside as $cat) {
- $feeds = $cat->feeds ();
- if (!empty ($feeds)) {
+ $feeds = $cat->feeds();
+ if (!empty($feeds)) {
$c_active = false;
- if ($this->conf->display_categories) {
- if ($this->get_c == $cat->id () && $this->get_f) {
- $c_active = true;
- }
- } else {
- if ($this->get_c == $cat->id ()) {
- $c_active = true;
+ $c_show = false;
+ if ($this->get_c == $cat->id()) {
+ $c_active = true;
+ if (!$this->conf->display_categories || $this->get_f) {
+ $c_show = true;
}
}
?><li data-unread="<?php echo $cat->nbNotRead(); ?>"<?php if ($c_active) echo ' class="active"'; ?>><?php
?><div class="category stick<?php echo $c_active ? ' active' : ''; ?>"><?php
- ?><a data-unread="<?php echo formatNumber($cat->nbNotRead()); ?>" class="btn<?php echo $c_active ? ' active' : ''; ?>" href="<?php $arUrl['params']['get'] = 'c_' . $cat->id(); echo Minz_Url::display($arUrl); ?>"><?php echo $cat->name (); ?></a><?php
- ?><a class="btn dropdown-toggle" href="#"><?php echo FreshRSS_Themes::icon($c_active ? 'up' : 'down'); ?></a><?php
+ ?><a data-unread="<?php echo formatNumber($cat->nbNotRead()); ?>" class="btn<?php echo $c_active ? ' active' : ''; ?>" href="<?php $arUrl['params']['get'] = 'c_' . $cat->id(); echo Minz_Url::display($arUrl); ?>"><?php echo $cat->name(); ?></a><?php
+ ?><a class="btn dropdown-toggle" href="#"><?php echo _i($c_show ? 'up' : 'down'); ?></a><?php
?></div><?php
- ?><ul class="feeds<?php echo $c_active ? ' active' : ''; ?>"><?php
+ ?><ul class="feeds<?php echo $c_show ? ' active' : ''; ?>"><?php
foreach ($feeds as $feed) {
- $feed_id = $feed->id ();
- $nbEntries = $feed->nbEntries ();
+ $feed_id = $feed->id();
+ $nbEntries = $feed->nbEntries();
$f_active = ($this->get_f == $feed_id);
- ?><li id="f_<?php echo $feed_id; ?>" class="item<?php echo $f_active ? ' active' : ''; ?><?php echo $feed->inError () ? ' error' : ''; ?><?php echo $nbEntries == 0 ? ' empty' : ''; ?>" data-unread="<?php echo $feed->nbNotRead(); ?>"><?php
+ ?><li id="f_<?php echo $feed_id; ?>" class="item<?php echo $f_active ? ' active' : ''; ?><?php echo $feed->inError() ? ' error' : ''; ?><?php echo $nbEntries == 0 ? ' empty' : ''; ?>" data-unread="<?php echo $feed->nbNotRead(); ?>"><?php
?><div class="dropdown"><?php
?><div class="dropdown-target"></div><?php
- ?><a class="dropdown-toggle" data-fweb="<?php echo $feed->website (); ?>"><?php echo FreshRSS_Themes::icon('configure'); ?></a><?php
+ ?><a class="dropdown-toggle" data-fweb="<?php echo $feed->website(); ?>"><?php echo _i('configure'); ?></a><?php
/* feed_config_template */
?></div><?php
- ?> <img class="favicon" src="<?php echo $feed->favicon (); ?>" alt="✇" /> <?php
- ?><a class="feed" data-unread="<?php echo formatNumber($feed->nbNotRead()); ?>" data-priority="<?php echo $feed->priority (); ?>" href="<?php $arUrl['params']['get'] = 'f_' . $feed_id; echo Minz_Url::display($arUrl); ?>"><?php echo $feed->name(); ?></a><?php
+ ?> <img class="favicon" src="<?php echo $feed->favicon(); ?>" alt="✇" /> <?php
+ ?><a class="feed" data-unread="<?php echo formatNumber($feed->nbNotRead()); ?>" data-priority="<?php echo $feed->priority(); ?>" href="<?php $arUrl['params']['get'] = 'f_' . $feed_id; echo Minz_Url::display($arUrl); ?>"><?php echo $feed->name(); ?></a><?php
?></li><?php
}
?></ul><?php
@@ -82,14 +82,22 @@
<script id="feed_config_template" type="text/html">
<ul class="dropdown-menu">
<li class="dropdown-close"><a href="#close">❌</a></li>
- <li class="item"><a href="<?php echo _url ('index', 'index', 'get', 'f_!!!!!!'); ?>"><?php echo Minz_Translate::t ('filter'); ?></a></li>
- <li class="item"><a href="<?php echo _url ('stats', 'repartition', 'id', '!!!!!!'); ?>"><?php echo Minz_Translate::t ('stats'); ?></a></li>
- <li class="item"><a target="_blank" href="http://example.net/"><?php echo Minz_Translate::t ('see_website'); ?></a></li>
+ <li class="item"><a href="<?php echo _url('index', 'index', 'get', 'f_!!!!!!'); ?>"><?php echo _t('filter'); ?></a></li>
+ <?php if ($this->loginOk) { ?>
+ <li class="item"><a href="<?php echo _url('stats', 'repartition', 'id', '!!!!!!'); ?>"><?php echo _t('stats'); ?></a></li>
+ <?php } ?>
+ <li class="item"><a target="_blank" href="http://example.net/"><?php echo _t('see_website'); ?></a></li>
<?php if ($this->loginOk) { ?>
<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"><a href="<?php echo _url('configure', 'feed', 'id', '!!!!!!'); ?>"><?php echo _t('administration'); ?></a></li>
+ <li class="item"><a href="<?php echo _url('feed', 'actualize', 'id', '!!!!!!'); ?>"><?php echo _t('actualize'); ?></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/header.phtml b/app/layout/header.phtml
index 2e42bfdea..028e63d8a 100644
--- a/app/layout/header.phtml
+++ b/app/layout/header.phtml
@@ -75,6 +75,12 @@ if (Minz_Configuration::canLogIn()) {
<li class="item"><a href="<?php echo _url('configure', 'queries'); ?>"><?php echo _t('queries'); ?></a></li>
<li class="separator"></li>
<li class="item"><a href="<?php echo _url('configure', 'users'); ?>"><?php echo _t('users'); ?></a></li>
+ <?php
+ $current_user = Minz_Session::param('currentUser', '');
+ if (Minz_Configuration::isAdmin($current_user)) {
+ ?>
+ <li class="item"><a href="<?php echo _url('update', 'index'); ?>"><?php echo _t('update'); ?></a></li>
+ <?php } ?>
<li class="separator"></li>
<li class="item"><a href="<?php echo _url('stats', 'index'); ?>"><?php echo _t('stats'); ?></a></li>
<li class="item"><a href="<?php echo _url('index', 'logs'); ?>"><?php echo _t('logs'); ?></a></li>
diff --git a/app/layout/layout.phtml b/app/layout/layout.phtml
index 96a88d245..f95f45b5e 100644
--- a/app/layout/layout.phtml
+++ b/app/layout/layout.phtml
@@ -13,6 +13,7 @@
if (!empty($this->nextId)) {
$params = Minz_Request::params();
$params['next'] = $this->nextId;
+ $params['ajax'] = 1;
?>
<link id="prefetch" rel="next prefetch" href="<?php echo Minz_Url::display(array('c' => Minz_Request::controllerName(), 'a' => Minz_Request::actionName(), 'params' => $params)); ?>" />
<?php } ?>
diff --git a/app/layout/nav_menu.phtml b/app/layout/nav_menu.phtml
index 25833c16d..a9e6614e7 100644
--- a/app/layout/nav_menu.phtml
+++ b/app/layout/nav_menu.phtml
@@ -3,11 +3,11 @@
?>
<div class="nav_menu">
<?php if ($actual_view === 'normal') { ?>
- <a class="btn toggle_aside" href="#aside_flux"><?php echo FreshRSS_Themes::icon('category'); ?></a>
+ <a class="btn toggle_aside" href="#aside_flux"><?php echo _i('category'); ?></a>
<?php } ?>
<?php if ($this->loginOk) { ?>
- <div class="stick">
+ <div id="nav_menu_actions" class="stick">
<?php
$url_state = $this->url;
@@ -24,9 +24,9 @@
<a id="toggle-read"
class="btn <?php echo $class; ?>"
aria-checked="<?php echo $checked; ?>"
- href="<?php echo Minz_Url::display ($url_state); ?>"
- title="<?php echo Minz_Translate::t ('show_read'); ?>">
- <?php echo FreshRSS_Themes::icon('read'); ?>
+ href="<?php echo Minz_Url::display($url_state); ?>"
+ title="<?php echo _t('show_read'); ?>">
+ <?php echo _i('read'); ?>
</a>
<?php
@@ -43,13 +43,13 @@
<a id="toggle-unread"
class="btn <?php echo $class; ?>"
aria-checked="<?php echo $checked; ?>"
- href="<?php echo Minz_Url::display ($url_state); ?>"
- title="<?php echo Minz_Translate::t ('show_not_reads'); ?>">
- <?php echo FreshRSS_Themes::icon('unread'); ?>
+ href="<?php echo Minz_Url::display($url_state); ?>"
+ title="<?php echo _t('show_not_reads'); ?>">
+ <?php echo _i('unread'); ?>
</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';
@@ -62,9 +62,9 @@
<a id="toggle-favorite"
class="btn <?php echo $class; ?>"
aria-checked="<?php echo $checked; ?>"
- href="<?php echo Minz_Url::display ($url_state); ?>"
- title="<?php echo Minz_Translate::t ('show_favorite'); ?>">
- <?php echo FreshRSS_Themes::icon('starred'); ?>
+ href="<?php echo Minz_Url::display($url_state); ?>"
+ title="<?php echo _t('show_favorite'); ?>">
+ <?php echo _i('starred'); ?>
</a>
<?php
@@ -81,22 +81,25 @@
<a id="toggle-not-favorite"
class="btn <?php echo $class; ?>"
aria-checked="<?php echo $checked; ?>"
- href="<?php echo Minz_Url::display ($url_state); ?>"
- title="<?php echo Minz_Translate::t ('show_not_favorite'); ?>">
- <?php echo FreshRSS_Themes::icon('non-starred'); ?>
+ href="<?php echo Minz_Url::display($url_state); ?>"
+ title="<?php echo _t('show_not_favorite'); ?>">
+ <?php echo _i('non-starred'); ?>
</a>
<div class="dropdown">
<div id="dropdown-query" class="dropdown-target"></div>
- <a class="dropdown-toggle btn" href="#dropdown-query"><?php echo FreshRSS_Themes::icon('down'); ?></a>
+ <a class="dropdown-toggle btn" href="#dropdown-query"><?php echo _i('down'); ?></a>
<ul class="dropdown-menu">
<li class="dropdown-close"><a href="#close">❌</a></li>
- <li class="dropdown-header"><?php echo Minz_Translate::t('queries'); ?> <a class="no-mobile" href="<?php echo _url('configure', 'queries'); ?>"><?php echo FreshRSS_Themes::icon('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">
+ <li class="item query">
<a href="<?php echo $query['url']; ?>"><?php echo $query['name']; ?></a>
</li>
<?php } ?>
@@ -110,58 +113,58 @@
$url_query['c'] = 'configure';
$url_query['a'] = 'addQuery';
?>
- <li class="item no-mobile"><a href="<?php echo Minz_Url::display($url_query); ?>"><?php echo FreshRSS_Themes::icon('bookmark-add'); ?> <?php echo Minz_Translate::t('add_query'); ?></a></li>
+ <li class="item no-mobile"><a href="<?php echo Minz_Url::display($url_query); ?>"><?php echo _i('bookmark-add'); ?> <?php echo _t('add_query'); ?></a></li>
</ul>
</div>
</div>
<?php
$get = false;
- $string_mark = Minz_Translate::t ('mark_all_read');
+ $string_mark = _t('mark_all_read');
if ($this->get_f) {
$get = 'f_' . $this->get_f;
- $string_mark = Minz_Translate::t ('mark_feed_read');
+ $string_mark = _t('mark_feed_read');
} elseif ($this->get_c && $this->get_c != 'a') {
if ($this->get_c === 's') {
$get = 's';
} else {
$get = 'c_' . $this->get_c;
}
- $string_mark = Minz_Translate::t ('mark_cat_read');
+ $string_mark = _t('mark_cat_read');
}
$nextGet = $get;
- if ($this->conf->onread_jump_next && (strlen ($get) > 2)) {
+ if ($this->conf->onread_jump_next && strlen($get) > 2) {
$anotherUnreadId = '';
$foundCurrent = false;
switch ($get[0]) {
- case 'c':
- foreach ($this->cat_aside as $cat) {
- if ($cat->id () == $this->get_c) {
- $foundCurrent = true;
- continue;
- }
- if ($cat->nbNotRead () <= 0) continue;
- $anotherUnreadId = $cat->id ();
- if ($foundCurrent) break;
+ case 'c':
+ foreach ($this->cat_aside as $cat) {
+ if ($cat->id() == $this->get_c) {
+ $foundCurrent = true;
+ continue;
}
- $nextGet = empty ($anotherUnreadId) ? 'a' : 'c_' . $anotherUnreadId;
- break;
- case 'f':
- foreach ($this->cat_aside as $cat) {
- if ($cat->id () == $this->get_c) {
- foreach ($cat->feeds () as $feed) {
- if ($feed->id () == $this->get_f) {
- $foundCurrent = true;
- continue;
- }
- if ($feed->nbNotRead () <= 0) continue;
- $anotherUnreadId = $feed->id ();
- if ($foundCurrent) break;
+ if ($cat->nbNotRead() <= 0) continue;
+ $anotherUnreadId = $cat->id();
+ if ($foundCurrent) break;
+ }
+ $nextGet = empty($anotherUnreadId) ? 'a' : 'c_' . $anotherUnreadId;
+ break;
+ case 'f':
+ foreach ($this->cat_aside as $cat) {
+ if ($cat->id() == $this->get_c) {
+ foreach ($cat->feeds() as $feed) {
+ if ($feed->id() == $this->get_f) {
+ $foundCurrent = true;
+ continue;
}
- break;
+ if ($feed->nbNotRead() <= 0) continue;
+ $anotherUnreadId = $feed->id();
+ if ($foundCurrent) break;
}
+ break;
}
- $nextGet = empty ($anotherUnreadId) ? 'c_' . $this->get_c : 'f_' . $anotherUnreadId;
- break;
+ }
+ $nextGet = empty($anotherUnreadId) ? 'c_' . $this->get_c : 'f_' . $anotherUnreadId;
+ break;
}
}
@@ -177,30 +180,54 @@
$arUrl = array('c' => 'entry', 'a' => 'read', 'params' => array('get' => $get, 'nextGet' => $nextGet, 'idMax' => $idMax));
$output = Minz_Request::param('output', '');
- if (($output != '') && ($this->conf->view_mode !== $output)) {
+ if ($output != '' && $this->conf->view_mode !== $output) {
$arUrl['params']['output'] = $output;
}
$markReadUrl = Minz_Url::display($arUrl);
- Minz_Session::_param ('markReadUrl', $markReadUrl);
+ Minz_Session::_param('markReadUrl', $markReadUrl);
?>
+ <form id="mark-read-menu" method="post" style="display: none"></form>
+
<div class="stick" id="nav_menu_read_all">
- <a class="read_all btn<?php if ($this->conf->reading_confirm) {echo ' confirm';} ?>" href="<?php echo $markReadUrl; ?>"><?php echo Minz_Translate::t ('mark_read'); ?></a>
+ <?php $confirm = $this->conf->reading_confirm ? 'confirm' : ''; ?>
+ <button class="read_all btn <?php echo $confirm; ?>"
+ form="mark-read-menu"
+ formaction="<?php echo $markReadUrl; ?>"
+ type="submit"><?php echo _t('mark_read'); ?></button>
+
<div class="dropdown">
<div id="dropdown-read" class="dropdown-target"></div>
- <a class="dropdown-toggle btn" href="#dropdown-read"><?php echo FreshRSS_Themes::icon('down'); ?></a>
+ <a class="dropdown-toggle btn" href="#dropdown-read"><?php echo _i('down'); ?></a>
<ul class="dropdown-menu">
<li class="dropdown-close"><a href="#close">❌</a></li>
- <li class="item"><a href="<?php echo $markReadUrl; ?>"><?php echo $string_mark; ?></a></li>
+ <li class="item">
+ <button class="as-link <?php echo $confirm; ?>"
+ form="mark-read-menu"
+ formaction="<?php echo $markReadUrl; ?>"
+ type="submit"><?php echo $string_mark; ?></button>
+ </li>
<li class="separator"></li>
<?php
- $today = $this->today;
- $one_week = $today - 604800;
+ $mark_before_today = $arUrl;
+ $mark_before_today['params']['idMax'] = $this->today . '000000';
+ $mark_before_one_week = $arUrl;
+ $mark_before_one_week['params']['idMax'] = ($this->today - 604800) . '000000';
?>
- <li class="item"><a href="<?php echo _url ('entry', 'read', 'is_read', 1, 'get', $get, 'idMax', $today . '000000'); ?>"><?php echo Minz_Translate::t ('before_one_day'); ?></a></li>
- <li class="item"><a href="<?php echo _url ('entry', 'read', 'is_read', 1, 'get', $get, 'idMax', $one_week . '000000'); ?>"><?php echo Minz_Translate::t ('before_one_week'); ?></a></li>
+ <li class="item">
+ <button class="as-link <?php echo $confirm; ?>"
+ 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-menu"
+ formaction="<?php echo Minz_Url::display($mark_before_one_week); ?>"
+ type="submit"><?php echo _t('before_one_week'); ?></button>
+ </li>
</ul>
</div>
</div>
@@ -209,18 +236,18 @@
<?php $url_output = $this->url; ?>
<div class="stick" id="nav_menu_views">
<?php $url_output['params']['output'] = 'normal'; ?>
- <a class="view_normal btn <?php echo $actual_view == 'normal'? 'active' : ''; ?>" title="<?php echo Minz_Translate::t('normal_view'); ?>" href="<?php echo Minz_Url::display($url_output); ?>">
- <?php echo FreshRSS_Themes::icon("view-normal"); ?>
+ <a class="view_normal btn <?php echo $actual_view == 'normal'? 'active' : ''; ?>" title="<?php echo _t('normal_view'); ?>" href="<?php echo Minz_Url::display($url_output); ?>">
+ <?php echo _i("view-normal"); ?>
</a>
<?php $url_output['params']['output'] = 'global'; ?>
- <a class="view_global btn <?php echo $actual_view == 'global'? 'active' : ''; ?>" title="<?php echo Minz_Translate::t('global_view'); ?>" href="<?php echo Minz_Url::display($url_output); ?>">
- <?php echo FreshRSS_Themes::icon("view-global"); ?>
+ <a class="view_global btn <?php echo $actual_view == 'global'? 'active' : ''; ?>" title="<?php echo _t('global_view'); ?>" href="<?php echo Minz_Url::display($url_output); ?>">
+ <?php echo _i("view-global"); ?>
</a>
<?php $url_output['params']['output'] = 'reader'; ?>
- <a class="view_reader btn <?php echo $actual_view == 'reader'? 'active' : ''; ?>" title="<?php echo Minz_Translate::t('reader_view'); ?>" href="<?php echo Minz_Url::display($url_output); ?>">
- <?php echo FreshRSS_Themes::icon("view-reader"); ?>
+ <a class="view_reader btn <?php echo $actual_view == 'reader'? 'active' : ''; ?>" title="<?php echo _t('reader_view'); ?>" href="<?php echo Minz_Url::display($url_output); ?>">
+ <?php echo _i("view-reader"); ?>
</a>
<?php
@@ -229,27 +256,27 @@
$url_output['params']['token'] = $this->conf->token;
}
?>
- <a class="view_rss btn" target="_blank" title="<?php echo Minz_Translate::t ('rss_view'); ?>" href="<?php echo Minz_Url::display($url_output); ?>">
- <?php echo FreshRSS_Themes::icon('rss'); ?>
+ <a class="view_rss btn" target="_blank" title="<?php echo _t('rss_view'); ?>" href="<?php echo Minz_Url::display($url_output); ?>">
+ <?php echo _i('rss'); ?>
</a>
</div>
<div class="item search">
- <form action="<?php echo _url ('index', 'index'); ?>" method="get">
- <?php $search = Minz_Request::param ('search', ''); ?>
- <input type="search" name="search" class="extend" value="<?php echo $search; ?>" placeholder="<?php echo Minz_Translate::t ('search_short'); ?>" />
+ <form action="<?php echo _url('index', 'index'); ?>" method="get">
+ <?php $search = Minz_Request::param('search', ''); ?>
+ <input type="search" name="search" class="extend" value="<?php echo $search; ?>" placeholder="<?php echo _t('search_short'); ?>" />
- <?php $get = Minz_Request::param ('get', ''); ?>
+ <?php $get = Minz_Request::param('get', ''); ?>
<?php if($get != '') { ?>
<input type="hidden" name="get" value="<?php echo $get; ?>" />
<?php } ?>
- <?php $order = Minz_Request::param ('order', ''); ?>
+ <?php $order = Minz_Request::param('order', ''); ?>
<?php if($order != '') { ?>
<input type="hidden" name="order" value="<?php echo $order; ?>" />
<?php } ?>
- <?php $state = Minz_Request::param ('state', ''); ?>
+ <?php $state = Minz_Request::param('state', ''); ?>
<?php if($state != '') { ?>
<input type="hidden" name="state" value="<?php echo $state; ?>" />
<?php } ?>
@@ -269,11 +296,11 @@
$url_order = $this->url;
$url_order['params']['order'] = $order;
?>
- <a class="btn" href="<?php echo Minz_Url::display ($url_order); ?>" title="<?php echo Minz_Translate::t ($title); ?>">
- <?php echo FreshRSS_Themes::icon($icon); ?>
+ <a id="toggle-order" class="btn" href="<?php echo Minz_Url::display($url_order); ?>" title="<?php echo _t($title); ?>">
+ <?php echo _i($icon); ?>
</a>
<?php if ($this->loginOk || Minz_Configuration::allowAnonymousRefresh()) { ?>
- <a id="actualize" class="btn" href="<?php echo _url ('feed', 'actualize'); ?>"><?php echo FreshRSS_Themes::icon('refresh'); ?></a>
+ <a id="actualize" class="btn" href="<?php echo _url('feed', 'actualize'); ?>"><?php echo _i('refresh'); ?></a>
<?php } ?>
</div>
diff --git a/app/views/configure/categorize.phtml b/app/views/configure/categorize.phtml
index 9bae99b39..23d1c9fa1 100644
--- a/app/views/configure/categorize.phtml
+++ b/app/views/configure/categorize.phtml
@@ -18,7 +18,13 @@
<input type="text" id="cat_<?php echo $cat->id (); ?>" name="categories[]" value="<?php echo $cat->name (); ?>" />
<?php if ($cat->nbFeed () > 0) { ?>
- <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>
+ <a class="btn" href="<?php echo _url('index', 'index', 'get', 'c_' . $cat->id ()); ?>">
+ <?php echo _i('link'); ?>
+ </a>
+ <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/display.phtml b/app/views/configure/display.phtml
index 955fc6747..8eb3a156b 100644
--- a/app/views/configure/display.phtml
+++ b/app/views/configure/display.phtml
@@ -91,6 +91,13 @@
</tbody>
</table><br />
</div>
+
+ <div class="form-group">
+ <label class="group-name" for="posts_per_page"><?php echo Minz_Translate::t ('html5_notif_timeout'); ?></label>
+ <div class="group-controls">
+ <input type="number" id="html5_notif_timeout" name="html5_notif_timeout" value="<?php echo $this->conf->html5_notif_timeout; ?>" /> <?php echo Minz_Translate::t ('seconds_(0_means_no_timeout)'); ?>
+ </div>
+ </div>
<div class="form-group form-actions">
<div class="group-controls">
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 5a26501a4..8b2da2a28 100644
--- a/app/views/configure/reading.phtml
+++ b/app/views/configure/reading.phtml
@@ -10,6 +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 echo _i('help'); ?> <?php echo _t('number_divided_when_reader'); ?>
</div>
</div>
@@ -31,14 +32,17 @@
<option value="reader"<?php echo $this->conf->view_mode === 'reader' ? ' selected="selected"' : ''; ?>><?php echo Minz_Translate::t ('reader_view'); ?></option>
<option value="global"<?php echo $this->conf->view_mode === 'global' ? ' selected="selected"' : ''; ?>><?php echo Minz_Translate::t ('global_view'); ?></option>
</select>
- <label class="radio" for="radio_all">
- <input type="radio" name="default_view" id="radio_all" value="<?php echo FreshRSS_Entry::STATE_ALL; ?>"<?php echo $this->conf->default_view === FreshRSS_Entry::STATE_ALL ? ' checked="checked"' : ''; ?> />
- <?php echo Minz_Translate::t ('show_all_articles'); ?>
- </label>
- <label class="radio" for="radio_not_read">
- <input type="radio" name="default_view" id="radio_not_read" value="<?php echo FreshRSS_Entry::STATE_NOT_READ; ?>"<?php echo $this->conf->default_view === FreshRSS_Entry::STATE_NOT_READ ? ' checked="checked"' : ''; ?> />
- <?php echo Minz_Translate::t ('show_not_reads'); ?>
- </label>
+ </div>
+ </div>
+
+ <div class="form-group">
+ <label class="group-name" for="view_mode"><?php echo _t('articles_to_display'); ?></label>
+ <div class="group-controls">
+ <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_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/configure/shortcut.phtml b/app/views/configure/shortcut.phtml
index bfb13f003..a4029b676 100644
--- a/app/views/configure/shortcut.phtml
+++ b/app/views/configure/shortcut.phtml
@@ -103,6 +103,21 @@
</div>
</div>
+ <div class="form-group">
+ <label class="group-name" for="user_filter_shortcut"><?php echo Minz_Translate::t ('user_filter'); ?></label>
+ <div class="group-controls">
+ <input type="text" id="user_filter_shortcut" name="shortcuts[user_filter]" list="keys" value="<?php echo $s['user_filter']; ?>" />
+ <?php echo Minz_Translate::t ('user_filter_help'); ?>
+ </div>
+ </div>
+
+ <div class="form-group">
+ <label class="group-name" for="help_shortcut"><?php echo Minz_Translate::t ('help'); ?></label>
+ <div class="group-controls">
+ <input type="text" id="help_shortcut" name="shortcuts[help]" list="keys" value="<?php echo $s['help']; ?>" />
+ </div>
+ </div>
+
<div class="form-group form-actions">
<div class="group-controls">
<button type="submit" class="btn btn-important"><?php echo Minz_Translate::t ('save'); ?></button>
diff --git a/app/views/helpers/javascript_vars.phtml b/app/views/helpers/javascript_vars.phtml
index 7144c519a..1139eb446 100644
--- a/app/views/helpers/javascript_vars.phtml
+++ b/app/views/helpers/javascript_vars.phtml
@@ -4,7 +4,8 @@ echo '"use strict";', "\n";
$mark = $this->conf->mark_when;
echo 'var ',
- 'hide_posts=', ($this->conf->display_posts || Minz_Request::param('output') === 'reader') ? 'false' : 'true',
+ 'help_url="', FRESHRSS_WIKI, '"',
+ ',hide_posts=', ($this->conf->display_posts || Minz_Request::param('output') === 'reader') ? 'false' : 'true',
',display_order="', Minz_Request::param('order', $this->conf->sort_order), '"',
',auto_mark_article=', $mark['article'] ? 'true' : 'false',
',auto_mark_site=', $mark['site'] ? 'true' : 'false',
@@ -25,7 +26,9 @@ echo ',shortcuts={',
'collapse_entry:"', $s['collapse_entry'], '",',
'load_more:"', $s['load_more'], '",',
'auto_share:"', $s['auto_share'], '",',
- 'focus_search:"', $s['focus_search'], '"',
+ 'focus_search:"', $s['focus_search'], '",',
+ 'user_filter:"', $s['user_filter'], '",',
+ 'help:"', $s['help'], '"',
"},\n";
if (Minz_Request::param ('output') === 'global') {
@@ -48,9 +51,11 @@ 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";
+
$autoActualise = Minz_Session::param('actualize_feeds', false);
echo 'auto_actualize_feeds=', $autoActualise ? 'true' : 'false', ";\n";
diff --git a/app/views/helpers/pagination.phtml b/app/views/helpers/pagination.phtml
index f237e1f3e..cea338364 100755
--- a/app/views/helpers/pagination.phtml
+++ b/app/views/helpers/pagination.phtml
@@ -1,26 +1,37 @@
<?php
- $c = Minz_Request::controllerName ();
- $a = Minz_Request::actionName ();
- $params = Minz_Request::params ();
- $markReadUrl = Minz_Session::param ('markReadUrl');
- Minz_Session::_param ('markReadUrl', false);
+ $c = Minz_Request::controllerName();
+ $a = Minz_Request::actionName();
+ $params = Minz_Request::params();
+ $markReadUrl = Minz_Session::param('markReadUrl');
+ 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)) { ?>
- <?php $params['next'] = $this->nextId; ?>
- <a id="load_more" href="<?php echo Minz_Url::display (array ('c' => $c, 'a' => $a, 'params' => $params)); ?>"><?php echo Minz_Translate::t ('load_more'); ?></a>
+ <?php
+ $params['next'] = $this->nextId;
+ $params['ajax'] = 1;
+ ?>
+ <a id="load_more" href="<?php echo Minz_Url::display(array('c' => $c, 'a' => $a, 'params' => $params)); ?>">
+ <?php echo _t('load_more'); ?>
+ </a>
<?php } elseif ($markReadUrl) { ?>
- <a id="bigMarkAsRead" href="<?php echo $markReadUrl; ?>"<?php if ($this->conf->reading_confirm) { echo ' class="confirm"';} ?>>
- <?php echo Minz_Translate::t ('nothing_to_load'); ?><br />
- <span class="bigTick">✓</span><br />
- <?php echo Minz_Translate::t ('mark_all_read'); ?>
- </a>
+ <button id="bigMarkAsRead"
+ class="as-link <?php echo $this->conf->reading_confirm ? 'confirm' : ''; ?>"
+ form="mark-read-pagination"
+ formaction="<?php echo $markReadUrl; ?>"
+ type="submit">
+ <?php echo _t('nothing_to_load'); ?><br />
+ <span class="bigTick">✓</span><br />
+ <?php echo _t('mark_all_read'); ?>
+ </button>
<?php } else { ?>
- <a id="bigMarkAsRead" href=".">
- <?php echo Minz_Translate::t ('nothing_to_load'); ?><br />
- </a>
+ <a id="bigMarkAsRead" href=".">
+ <?php echo _t('nothing_to_load'); ?><br />
+ </a>
<?php } ?>
</li>
</ul>
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/index/formLogin.phtml b/app/views/index/formLogin.phtml
index b79c1b614..b05cdced4 100644
--- a/app/views/index/formLogin.phtml
+++ b/app/views/index/formLogin.phtml
@@ -3,7 +3,7 @@
switch (Minz_Configuration::authType()) {
case 'form':
- ?><form id="loginForm" method="post" action="<?php echo _url('index', 'formLogin'); ?>">
+ ?><form id="crypto-form" method="post" action="<?php echo _url('index', 'formLogin'); ?>">
<div>
<label for="username"><?php echo _t('username'); ?></label>
<input type="text" id="username" name="username" size="16" required="required" maxlength="16" pattern="[0-9a-zA-Z]{1,16}" autofocus="autofocus" />
@@ -29,8 +29,15 @@
case 'persona':
?><p>
- <?php echo _i('login'); ?>
- <a class="signin" href="#"><?php echo _t('login_with_persona'); ?></a>
+ <a class="signin btn btn-important" href="#">
+ <?php echo _i('login'); ?>
+ <?php echo _t('login_with_persona'); ?>
+ </a><br /><br />
+
+ <?php echo _i('help'); ?>
+ <small>
+ <a href="<?php echo _url('index', 'resetAuth'); ?>"><?php echo _t('login_persona_problem'); ?></a>
+ </small>
</p><?php
break;
} ?>
diff --git a/app/views/index/resetAuth.phtml b/app/views/index/resetAuth.phtml
new file mode 100644
index 000000000..6d4282c14
--- /dev/null
+++ b/app/views/index/resetAuth.phtml
@@ -0,0 +1,33 @@
+<div class="prompt">
+ <h1><?php echo _t('auth_reset'); ?></h1>
+
+ <?php if (!empty($this->message)) { ?>
+ <p class="alert <?php echo $this->message['status'] === 'bad' ? 'alert-error' : 'alert-warn'; ?>">
+ <span class="alert-head"><?php echo $this->message['title']; ?></span><br />
+ <?php echo $this->message['body']; ?>
+ </p>
+ <?php } ?>
+
+ <?php if (!$this->no_form) { ?>
+ <form id="crypto-form" method="post" action="<?php echo _url('index', 'resetAuth'); ?>">
+ <p class="alert alert-warn">
+ <span class="alert-head"><?php echo _t('attention'); ?></span><br />
+ <?php echo _t('auth_will_reset'); ?>
+ </p>
+
+ <div>
+ <label for="username"><?php echo _t('username_admin'); ?></label>
+ <input type="text" id="username" name="username" size="16" required="required" maxlength="16" pattern="[0-9a-zA-Z]{1,16}" autofocus="autofocus" />
+ </div>
+ <div>
+ <label for="passwordPlain"><?php echo _t('password'); ?></label>
+ <input type="password" id="passwordPlain" required="required" />
+ <input type="hidden" id="challenge" name="challenge" /><br />
+ <noscript><strong><?php echo _t('javascript_should_be_activated'); ?></strong></noscript>
+ </div>
+ <div>
+ <button id="loginButton" type="submit" class="btn btn-important"><?php echo _t('submit'); ?></button>
+ </div>
+ </form>
+ <?php } ?>
+</div>
diff --git a/app/views/stats/idle.phtml b/app/views/stats/idle.phtml
index 2ba5237f7..6f3d4a117 100644
--- a/app/views/stats/idle.phtml
+++ b/app/views/stats/idle.phtml
@@ -1,25 +1,48 @@
<?php $this->partial('aside_stats'); ?>
-<div class="post content">
+<div class="post">
<a href="<?php echo _url('index', 'index'); ?>"><?php echo _t('back_to_rss_feeds'); ?></a>
<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>
- <ul>
- <?php foreach ($feeds as $feed) { ?>
- <li><a href="<?php echo _url('configure', 'feed', 'id', $feed['id']); ?>" title="<?php echo date('Y-m-d', $feed['last_date']); ?>"><?php echo $feed['name']; ?></a></li>
- <?php } ?>
+ <form id="form-delete" method="post" style="display: none"></form>
+
+ <?php foreach ($feeds as $feed) { ?>
+ <ul class="horizontal-list">
+ <li class="item">
+ <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'], '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']; ?> (<?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 a48181fe4..412e77e16 100644
--- a/app/views/stats/index.phtml
+++ b/app/views/stats/index.phtml
@@ -1,11 +1,11 @@
<?php $this->partial('aside_stats'); ?>
-<div class="post content">
+<div class="post">
<a href="<?php echo _url ('index', 'index'); ?>"><?php echo _t ('back_to_rss_feeds'); ?></a>
-
+
<h1><?php echo _t ('stats_main'); ?></h1>
- <div class="stat">
+ <div class="stat half">
<h2><?php echo _t ('stats_entry_repartition'); ?></h2>
<table>
<thead>
@@ -38,26 +38,9 @@
</tr>
</tbody>
</table>
- </div>
-
- <div class="stat">
- <h2><?php echo _t ('stats_entry_per_day'); ?></h2>
- <div id="statsEntryPerDay" style="height: 300px"></div>
- </div>
-
- <div class="stat">
- <h2><?php echo _t ('stats_feed_per_category'); ?></h2>
- <div id="statsFeedPerCategory" style="height: 300px"></div>
- <div id="statsFeedPerCategoryLegend"></div>
- </div>
-
- <div class="stat">
- <h2><?php echo _t ('stats_entry_per_category'); ?></h2>
- <div id="statsEntryPerCategory" style="height: 300px"></div>
- <div id="statsEntryPerCategoryLegend"></div>
- </div>
-
- <div class="stat">
+ </div><!--
+
+ --><div class="stat half">
<h2><?php echo _t ('stats_top_feed'); ?></h2>
<table>
<thead>
@@ -70,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>
@@ -78,6 +61,23 @@
</tbody>
</table>
</div>
+
+ <div class="stat">
+ <h2><?php echo _t ('stats_entry_per_day'); ?></h2>
+ <div id="statsEntryPerDay" style="height: 300px"></div>
+ </div>
+
+ <div class="stat half">
+ <h2><?php echo _t ('stats_feed_per_category'); ?></h2>
+ <div id="statsFeedPerCategory" style="height: 300px"></div>
+ <div id="statsFeedPerCategoryLegend"></div>
+ </div><!--
+
+ --><div class="stat half">
+ <h2><?php echo _t ('stats_entry_per_category'); ?></h2>
+ <div id="statsEntryPerCategory" style="height: 300px"></div>
+ <div id="statsEntryPerCategoryLegend"></div>
+ </div>
</div>
<script>
diff --git a/app/views/stats/repartition.phtml b/app/views/stats/repartition.phtml
index 9d2eb28e4..b425c1458 100644
--- a/app/views/stats/repartition.phtml
+++ b/app/views/stats/repartition.phtml
@@ -1,6 +1,6 @@
<?php $this->partial('aside_stats'); ?>
-<div class="post content">
+<div class="post ">
<a href="<?php echo _url('index', 'index'); ?>"><?php echo _t('back_to_rss_feeds'); ?></a>
<h1><?php echo _t('stats_repartition'); ?></h1>
@@ -10,12 +10,12 @@
<?php foreach ($this->categories as $category) {
$feeds = $category->feeds();
if (!empty($feeds)) {
- echo '<optgroup label=', $category->name(), '>';
+ echo '<optgroup label="', $category->name(), '">';
foreach ($feeds as $feed) {
if ($this->feed && $feed->id() == $this->feed->id()){
- echo '<option value ="', $feed->id(), '" selected data-url="', _url('stats', 'repartition', 'id', $feed->id()), '">', $feed->name(), '</option>';
+ echo '<option value="', $feed->id(), '" selected="selected" data-url="', _url('stats', 'repartition', 'id', $feed->id()), '">', $feed->name(), '</option>';
} else {
- echo '<option value ="', $feed->id(), '" data-url="', _url('stats', 'repartition', 'id', $feed->id()), '">', $feed->name(), '</option>';
+ echo '<option value="', $feed->id(), '" data-url="', _url('stats', 'repartition', 'id', $feed->id()), '">', $feed->name(), '</option>';
}
}
echo '</optgroup>';
@@ -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 }?>
@@ -34,12 +34,12 @@
<div id="statsEntryPerHour" style="height: 300px"></div>
</div>
- <div class="stat">
+ <div class="stat half">
<h2><?php echo _t('stats_entry_per_day_of_week'); ?></h2>
<div id="statsEntryPerDayOfWeek" style="height: 300px"></div>
- </div>
+ </div><!--
- <div class="stat">
+ --><div class="stat half">
<h2><?php echo _t('stats_entry_per_month'); ?></h2>
<div id="statsEntryPerMonth" style="height: 300px"></div>
</div>
@@ -56,11 +56,22 @@ function initStats() {
return;
}
// Entry per hour
+ var avg_h = [];
+ for (var i = -1; i <= 24; i++) {
+ avg_h.push([i, <?php echo $this->averageHour?>]);
+ }
Flotr.draw(document.getElementById('statsEntryPerHour'),
- [<?php echo $this->repartitionHour ?>],
+ [{
+ data: <?php echo $this->repartitionHour ?>,
+ bars: {horizontal: false, show: true}
+ }, {
+ data: avg_h,
+ lines: {show: true},
+ label: <?php echo $this->averageHour?>,
+ yaxis: 2
+ }],
{
grid: {verticalLines: false},
- bars: {horizontal: false, show: true},
xaxis: {noTicks: 23,
tickFormatter: function(x) {
var x = parseInt(x);
@@ -70,14 +81,26 @@ function initStats() {
max: 23.9,
tickDecimals: 0},
yaxis: {min: 0},
+ y2axis: {showLabels: false},
mouse: {relative: true, track: true, trackDecimals: 0, trackFormatter: function(obj) {return numberFormat(obj.y);}}
});
// Entry per day of week
+ var avg_dow = [];
+ for (var i = -1; i <= 7; i++) {
+ avg_dow.push([i, <?php echo $this->averageDayOfWeek?>]);
+ }
Flotr.draw(document.getElementById('statsEntryPerDayOfWeek'),
- [<?php echo $this->repartitionDayOfWeek ?>],
+ [{
+ data: <?php echo $this->repartitionDayOfWeek ?>,
+ bars: {horizontal: false, show: true}
+ }, {
+ data: avg_dow,
+ lines: {show: true},
+ label: <?php echo $this->averageDayOfWeek?>,
+ yaxis: 2
+ }],
{
grid: {verticalLines: false},
- bars: {horizontal: false, show: true},
xaxis: {noTicks: 6,
tickFormatter: function(x) {
var x = parseInt(x),
@@ -88,14 +111,26 @@ function initStats() {
max: 6.9,
tickDecimals: 0},
yaxis: {min: 0},
+ y2axis: {showLabels: false},
mouse: {relative: true, track: true, trackDecimals: 0, trackFormatter: function(obj) {return numberFormat(obj.y);}}
});
// Entry per month
+ var avg_m = [];
+ for (var i = 0; i <= 13; i++) {
+ avg_m.push([i, <?php echo $this->averageMonth?>]);
+ }
Flotr.draw(document.getElementById('statsEntryPerMonth'),
- [<?php echo $this->repartitionMonth ?>],
+ [{
+ data: <?php echo $this->repartitionMonth ?>,
+ bars: {horizontal: false, show: true}
+ }, {
+ data: avg_m,
+ lines: {show: true},
+ label: <?php echo $this->averageMonth?>,
+ yaxis: 2
+ }],
{
grid: {verticalLines: false},
- bars: {horizontal: false, show: true},
xaxis: {noTicks: 12,
tickFormatter: function(x) {
var x = parseInt(x),
@@ -106,6 +141,7 @@ function initStats() {
max: 12.9,
tickDecimals: 0},
yaxis: {min: 0},
+ y2axis: {showLabels: false},
mouse: {relative: true, track: true, trackDecimals: 0, trackFormatter: function(obj) {return numberFormat(obj.y);}}
});
diff --git a/app/views/update/apply.phtml b/app/views/update/apply.phtml
new file mode 100644
index 000000000..30566c7ab
--- /dev/null
+++ b/app/views/update/apply.phtml
@@ -0,0 +1,9 @@
+<?php $this->partial('aside_configure'); ?>
+
+<div class="post">
+ <a href="<?php echo _url('index', 'index'); ?>"><?php echo _t('back_to_rss_feeds'); ?></a>
+
+ <h1><?php echo _t('update_system'); ?></h1>
+
+ <?php ask_info_update(); ?>
+</div>
diff --git a/app/views/update/index.phtml b/app/views/update/index.phtml
new file mode 100644
index 000000000..401f6acd6
--- /dev/null
+++ b/app/views/update/index.phtml
@@ -0,0 +1,36 @@
+<?php $this->partial('aside_configure'); ?>
+
+<div class="post">
+ <a href="<?php echo _url('index', 'index'); ?>"><?php echo _t('back_to_rss_feeds'); ?></a>
+
+ <h1><?php echo _t('update_system'); ?></h1>
+
+ <p>
+ <?php echo _i('help'); ?> <?php echo _t('update_last', $this->last_update_time); ?>
+ </p>
+
+ <?php if (!empty($this->message)) { ?>
+ <p class="alert <?php echo $this->message['status'] === 'bad' ? 'alert-error' : 'alert-warn'; ?>">
+ <span class="alert-head"><?php echo $this->message['title']; ?></span>
+ <?php echo $this->message['body']; ?>
+ </p>
+ <?php } elseif ($this->check_last_hour) { ?>
+ <p class="alert alert-warn">
+ <span class="alert-head"><?php echo _t('damn'); ?></span>
+ <?php echo _t('no_update'); ?>
+ </p>
+ <?php } ?>
+
+ <?php
+ if (!$this->check_last_hour &&
+ (empty($this->message) || $this->message['status'] !== 'good')) {
+ ?>
+ <p>
+ <a href="<?php echo _url('update', 'check'); ?>" class="btn"><?php echo _t('update_check'); ?></a>
+ </p>
+ <?php } ?>
+
+ <?php if ($this->update_to_apply) { ?>
+ <a class="btn btn-important" href="<?php echo _url('update', 'apply'); ?>"><?php echo _t('update_apply'); ?></a>
+ <?php } ?>
+</div>