|
|
@@ -1,6 +1,14 @@
|
|
|
<?php
|
|
|
|
|
|
+/**
|
|
|
+ * Controller to handle every feed actions.
|
|
|
+ */
|
|
|
class FreshRSS_feed_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.
|
|
|
+ */
|
|
|
public function firstAction() {
|
|
|
if (!$this->view->loginOk) {
|
|
|
// Token is useful in the case that anonymous refresh is forbidden
|
|
|
@@ -10,9 +18,8 @@ class FreshRSS_feed_Controller extends Minz_ActionController {
|
|
|
$token_param = Minz_Request::param('token', '');
|
|
|
$token_is_ok = ($token != '' && $token == $token_param);
|
|
|
$action = Minz_Request::actionName();
|
|
|
- if (!(($token_is_ok || Minz_Configuration::allowAnonymousRefresh()) &&
|
|
|
- $action === 'actualize')
|
|
|
- ) {
|
|
|
+ if ($action !== 'actualize' ||
|
|
|
+ !(Minz_Configuration::allowAnonymousRefresh() || $token_is_ok)) {
|
|
|
Minz_Error::error(
|
|
|
403,
|
|
|
array('error' => array(_t('access_denied')))
|
|
|
@@ -21,10 +28,32 @@ class FreshRSS_feed_Controller extends Minz_ActionController {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+ /**
|
|
|
+ * This action subscribes to a feed.
|
|
|
+ *
|
|
|
+ * It can be reached by both GET and POST requests.
|
|
|
+ *
|
|
|
+ * GET request displays a form to add and configure a feed.
|
|
|
+ * Request parameter is:
|
|
|
+ * - url_rss (default: false)
|
|
|
+ *
|
|
|
+ * POST request adds a feed in database.
|
|
|
+ * Parameters are:
|
|
|
+ * - url_rss (default: false)
|
|
|
+ * - category (default: false)
|
|
|
+ * - new_category (required if category == 'nc')
|
|
|
+ * - http_user (default: false)
|
|
|
+ * - http_pass (default: false)
|
|
|
+ * It tries to get website information from RSS feed.
|
|
|
+ * If no category is given, feed is added to the default one.
|
|
|
+ *
|
|
|
+ * If url_rss is false, nothing happened.
|
|
|
+ */
|
|
|
public function addAction() {
|
|
|
- $url = Minz_Request::param('url_rss', false);
|
|
|
+ $url = Minz_Request::param('url_rss');
|
|
|
|
|
|
if ($url === false) {
|
|
|
+ // No url, do nothing
|
|
|
Minz_Request::forward(array(
|
|
|
'c' => 'subscription',
|
|
|
'a' => 'index'
|
|
|
@@ -33,14 +62,19 @@ class FreshRSS_feed_Controller extends Minz_ActionController {
|
|
|
|
|
|
$feedDAO = FreshRSS_Factory::createFeedDao();
|
|
|
$this->catDAO = new FreshRSS_CategoryDAO();
|
|
|
- $this->catDAO->checkDefault();
|
|
|
+ $url_redirect = array(
|
|
|
+ 'c' => 'subscription',
|
|
|
+ 'a' => 'index',
|
|
|
+ 'params' => array(),
|
|
|
+ );
|
|
|
|
|
|
if (Minz_Request::isPost()) {
|
|
|
@set_time_limit(300);
|
|
|
|
|
|
-
|
|
|
- $cat = Minz_Request::param('category', false);
|
|
|
+ $cat = Minz_Request::param('category');
|
|
|
if ($cat === 'nc') {
|
|
|
+ // User want to create a new category, new_category parameter
|
|
|
+ // must exist
|
|
|
$new_cat = Minz_Request::param('new_category');
|
|
|
if (empty($new_cat['name'])) {
|
|
|
$cat = false;
|
|
|
@@ -48,139 +82,114 @@ class FreshRSS_feed_Controller extends Minz_ActionController {
|
|
|
$cat = $this->catDAO->addCategory($new_cat);
|
|
|
}
|
|
|
}
|
|
|
+
|
|
|
if ($cat === false) {
|
|
|
+ // If category was not given or if creating new category failed,
|
|
|
+ // get the default category
|
|
|
+ $this->catDAO->checkDefault();
|
|
|
$def_cat = $this->catDAO->getDefault();
|
|
|
$cat = $def_cat->id();
|
|
|
}
|
|
|
|
|
|
+ // HTTP information are useful if feed is protected behind a
|
|
|
+ // HTTP authentication
|
|
|
$user = Minz_Request::param('http_user');
|
|
|
$pass = Minz_Request::param('http_pass');
|
|
|
- $params = array();
|
|
|
+ $http_auth = '';
|
|
|
+ if ($user != '' || $pass != '') {
|
|
|
+ $http_auth = $user . ':' . $pass;
|
|
|
+ }
|
|
|
|
|
|
- $transactionStarted = false;
|
|
|
+ $transaction_started = false;
|
|
|
try {
|
|
|
$feed = new FreshRSS_Feed($url);
|
|
|
- $feed->_category($cat);
|
|
|
-
|
|
|
- $httpAuth = '';
|
|
|
- if ($user != '' || $pass != '') {
|
|
|
- $httpAuth = $user . ':' . $pass;
|
|
|
- }
|
|
|
- $feed->_httpAuth($httpAuth);
|
|
|
-
|
|
|
- $feed->load(true);
|
|
|
-
|
|
|
- $values = array(
|
|
|
- 'url' => $feed->url(),
|
|
|
- 'category' => $feed->category(),
|
|
|
- 'name' => $feed->name(),
|
|
|
- 'website' => $feed->website(),
|
|
|
- 'description' => $feed->description(),
|
|
|
- 'lastUpdate' => time(),
|
|
|
- 'httpAuth' => $feed->httpAuth(),
|
|
|
- );
|
|
|
-
|
|
|
- if ($feedDAO->searchByUrl($values['url'])) {
|
|
|
- // on est déjà abonné à ce flux
|
|
|
- $notif = array(
|
|
|
- 'type' => 'bad',
|
|
|
- 'content' => _t('already_subscribed', $feed->name())
|
|
|
- );
|
|
|
- Minz_Session::_param('notification', $notif);
|
|
|
- } else {
|
|
|
- $id = $feedDAO->addFeed($values);
|
|
|
- if (!$id) {
|
|
|
- // problème au niveau de la base de données
|
|
|
- $notif = array(
|
|
|
- 'type' => 'bad',
|
|
|
- 'content' => _t('feed_not_added', $feed->name())
|
|
|
- );
|
|
|
- Minz_Session::_param('notification', $notif);
|
|
|
- } else {
|
|
|
- $feed->_id($id);
|
|
|
- $feed->faviconPrepare();
|
|
|
-
|
|
|
- $is_read = $this->view->conf->mark_when['reception'] ? 1 : 0;
|
|
|
-
|
|
|
- $entryDAO = FreshRSS_Factory::createEntryDao();
|
|
|
- $entries = array_reverse($feed->entries()); //We want chronological order and SimplePie uses reverse order
|
|
|
-
|
|
|
- // on calcule la date des articles les plus anciens qu'on accepte
|
|
|
- $nb_month_old = $this->view->conf->old_entries;
|
|
|
- $date_min = time() - (3600 * 24 * 30 * $nb_month_old);
|
|
|
-
|
|
|
- //MySQL: http://docs.oracle.com/cd/E17952_01/refman-5.5-en/optimizing-innodb-transaction-management.html
|
|
|
- //SQLite: http://stackoverflow.com/questions/1711631/how-do-i-improve-the-performance-of-sqlite
|
|
|
- $preparedStatement = $entryDAO->addEntryPrepare();
|
|
|
- $transactionStarted = true;
|
|
|
- $feedDAO->beginTransaction();
|
|
|
- // on ajoute les articles en masse sans vérification
|
|
|
- foreach ($entries as $entry) {
|
|
|
- $values = $entry->toArray();
|
|
|
- $values['id_feed'] = $feed->id();
|
|
|
- $values['id'] = min(time(), $entry->date(true)) . uSecString();
|
|
|
- $values['is_read'] = $is_read;
|
|
|
- $entryDAO->addEntry($values, $preparedStatement);
|
|
|
- }
|
|
|
- $feedDAO->updateLastUpdate($feed->id());
|
|
|
- if ($transactionStarted) {
|
|
|
- $feedDAO->commit();
|
|
|
- }
|
|
|
- $transactionStarted = false;
|
|
|
-
|
|
|
- // ok, ajout terminé
|
|
|
- $notif = array(
|
|
|
- 'type' => 'good',
|
|
|
- 'content' => _t('feed_added', $feed->name())
|
|
|
- );
|
|
|
- Minz_Session::_param('notification', $notif);
|
|
|
-
|
|
|
- // permet de rediriger vers la page de conf du flux
|
|
|
- $params['id'] = $feed->id();
|
|
|
- }
|
|
|
- }
|
|
|
} catch (FreshRSS_BadUrl_Exception $e) {
|
|
|
+ // Given url was not a valid url!
|
|
|
Minz_Log::warning($e->getMessage());
|
|
|
- $notif = array(
|
|
|
- 'type' => 'bad',
|
|
|
- 'content' => _t('invalid_url', $url)
|
|
|
- );
|
|
|
- Minz_Session::_param('notification', $notif);
|
|
|
+ Minz_Request::bad(_t('invalid_url', $url), $url_redirect);
|
|
|
+ }
|
|
|
+
|
|
|
+ try {
|
|
|
+ $feed->load(true);
|
|
|
} catch (FreshRSS_Feed_Exception $e) {
|
|
|
+ // Something went bad (timeout, server not found, etc.)
|
|
|
Minz_Log::warning($e->getMessage());
|
|
|
- $notif = array(
|
|
|
- 'type' => 'bad',
|
|
|
- 'content' => _t('internal_problem_feed',
|
|
|
- Minz_Url::display(array('a' => 'logs')))
|
|
|
+ Minz_Request::bad(
|
|
|
+ _t('internal_problem_feed', _url('index', 'logs')),
|
|
|
+ $url_redirect
|
|
|
);
|
|
|
- Minz_Session::_param('notification', $notif);
|
|
|
} catch (Minz_FileNotExistException $e) {
|
|
|
- // Répertoire de cache n'existe pas
|
|
|
+ // Cache directory doesn't exist!
|
|
|
Minz_Log::error($e->getMessage());
|
|
|
- $notif = array(
|
|
|
- 'type' => 'bad',
|
|
|
- 'content' => _t('internal_problem_feed',
|
|
|
- Minz_Url::display(array('a' => 'logs')))
|
|
|
+ Minz_Request::bad(
|
|
|
+ _t('internal_problem_feed', _url('index', 'logs')),
|
|
|
+ $url_redirect
|
|
|
);
|
|
|
- Minz_Session::_param('notification', $notif);
|
|
|
}
|
|
|
- if ($transactionStarted) {
|
|
|
- $feedDAO->rollBack();
|
|
|
+
|
|
|
+ if ($feedDAO->searchByUrl($feed->url())) {
|
|
|
+ Minz_Request::bad(_t('already_subscribed', $feed->name()), $url_redirect);
|
|
|
}
|
|
|
|
|
|
- Minz_Request::forward(array(
|
|
|
- 'c' => 'subscription',
|
|
|
- 'a' => 'index',
|
|
|
- 'params' => $params
|
|
|
- ), true);
|
|
|
- } else {
|
|
|
+ $feed->_category($cat);
|
|
|
+ $feed->_httpAuth($http_auth);
|
|
|
+
|
|
|
+ $values = array(
|
|
|
+ 'url' => $feed->url(),
|
|
|
+ 'category' => $feed->category(),
|
|
|
+ 'name' => $feed->name(),
|
|
|
+ 'website' => $feed->website(),
|
|
|
+ 'description' => $feed->description(),
|
|
|
+ 'lastUpdate' => time(),
|
|
|
+ 'httpAuth' => $feed->httpAuth(),
|
|
|
+ );
|
|
|
+
|
|
|
+ $id = $feedDAO->addFeed($values);
|
|
|
+ if (!$id) {
|
|
|
+ // There was an error in database... we cannot say what here.
|
|
|
+ Minz_Request::bad(_t('feed_not_added', $feed->name()), $url_redirect);
|
|
|
+ }
|
|
|
+
|
|
|
+ // Ok, feed has been added in database. Now we have to refresh entries.
|
|
|
+ $feed->_id($id);
|
|
|
+ $feed->faviconPrepare();
|
|
|
+
|
|
|
+ $is_read = $this->view->conf->mark_when['reception'] ? 1 : 0;
|
|
|
+
|
|
|
+ $entryDAO = FreshRSS_Factory::createEntryDao();
|
|
|
+ // We want chronological order and SimplePie uses reverse order.
|
|
|
+ $entries = array_reverse($feed->entries());
|
|
|
+
|
|
|
+ // Calculate date of oldest entries we accept in DB.
|
|
|
+ $nb_month_old = $this->view->conf->old_entries;
|
|
|
+ $date_min = time() - (3600 * 24 * 30 * $nb_month_old);
|
|
|
+
|
|
|
+ // Use a shared statement and a transaction to improve a LOT the
|
|
|
+ // performances.
|
|
|
+ $prepared_statement = $entryDAO->addEntryPrepare();
|
|
|
+ $feedDAO->beginTransaction();
|
|
|
+ foreach ($entries as $entry) {
|
|
|
+ // Entries are added without any verification.
|
|
|
+ $values = $entry->toArray();
|
|
|
+ $values['id_feed'] = $feed->id();
|
|
|
+ $values['id'] = min(time(), $entry->date(true)) . uSecString();
|
|
|
+ $values['is_read'] = $is_read;
|
|
|
+ $entryDAO->addEntry($values, $prepared_statement);
|
|
|
+ }
|
|
|
+ $feedDAO->updateLastUpdate($feed->id());
|
|
|
+ $feedDAO->commit();
|
|
|
|
|
|
- // GET request so we must ask confirmation to user
|
|
|
+ // Entries are in DB, we redirect to feed configuration page.
|
|
|
+ $url_redirect['params']['id'] = $feed->id();
|
|
|
+ Minz_Request::good(_t('feed_added', $feed->name()), $url_redirect);
|
|
|
+ } else {
|
|
|
+ // GET request: we must ask confirmation to user before adding feed.
|
|
|
Minz_View::prependTitle(_t('add_rss_feed') . ' · ');
|
|
|
+
|
|
|
$this->view->categories = $this->catDAO->listCategories(false);
|
|
|
$this->view->feed = new FreshRSS_Feed($url);
|
|
|
try {
|
|
|
- // We try to get some more information about the feed
|
|
|
+ // We try to get more information about the feed.
|
|
|
$this->view->feed->load(true);
|
|
|
$this->view->load_ok = true;
|
|
|
} catch (Exception $e) {
|
|
|
@@ -189,43 +198,53 @@ class FreshRSS_feed_Controller extends Minz_ActionController {
|
|
|
|
|
|
$feed = $feedDAO->searchByUrl($this->view->feed->url());
|
|
|
if ($feed) {
|
|
|
- // Already subscribe so we redirect to the feed configuration page
|
|
|
- $notif = array(
|
|
|
- 'type' => 'bad',
|
|
|
- 'content' => _t('already_subscribed', $feed->name())
|
|
|
- );
|
|
|
- Minz_Session::_param('notification', $notif);
|
|
|
-
|
|
|
- Minz_Request::forward(array(
|
|
|
- 'c' => 'subscription',
|
|
|
- 'a' => 'index',
|
|
|
- 'params' => array(
|
|
|
- 'id' => $feed->id()
|
|
|
- )
|
|
|
- ), true);
|
|
|
+ // Already subscribe so we redirect to the feed configuration page.
|
|
|
+ $url_redirect['params']['id'] = $feed->id();
|
|
|
+ Minz_Request::good(_t('already_subscribed', $feed->name()), $url_redirect);
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+ /**
|
|
|
+ * This action remove entries from a given feed.
|
|
|
+ *
|
|
|
+ * It should be reached by a POST action.
|
|
|
+ *
|
|
|
+ * Parameter is:
|
|
|
+ * - id (default: false)
|
|
|
+ */
|
|
|
public function truncateAction() {
|
|
|
- if (Minz_Request::isPost()) {
|
|
|
- $id = Minz_Request::param('id');
|
|
|
- $feedDAO = FreshRSS_Factory::createFeedDao();
|
|
|
- $n = $feedDAO->truncate($id);
|
|
|
- $notif = array(
|
|
|
- 'type' => $n === false ? 'bad' : 'good',
|
|
|
- 'content' => _t('n_entries_deleted', $n)
|
|
|
- );
|
|
|
- Minz_Session::_param('notification', $notif);
|
|
|
- invalidateHttpCache();
|
|
|
- Minz_Request::forward(array(
|
|
|
- 'c' => 'subscription',
|
|
|
- 'a' => 'index',
|
|
|
- 'params' => array('id' => $id)
|
|
|
- ), true);
|
|
|
+ $id = Minz_Request::param('id');
|
|
|
+ $url_redirect = array(
|
|
|
+ 'c' => 'subscription',
|
|
|
+ 'a' => 'index',
|
|
|
+ 'params' => array('id' => $id)
|
|
|
+ );
|
|
|
+
|
|
|
+ if (!Minz_Request::isPost()) {
|
|
|
+ Minz_Request::forward($url_redirect, true);
|
|
|
+ }
|
|
|
+
|
|
|
+ $feedDAO = FreshRSS_Factory::createFeedDao();
|
|
|
+ $n = $feedDAO->truncate($id);
|
|
|
+
|
|
|
+ invalidateHttpCache();
|
|
|
+ if ($n === false) {
|
|
|
+ Minz_Request::bad(_t('error_occurred'), $url_redirect);
|
|
|
+ } else {
|
|
|
+ Minz_Request::good(_t('n_entries_deleted', $n), $url_redirect);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+ /**
|
|
|
+ * This action actualizes entries from one or several feeds.
|
|
|
+ *
|
|
|
+ * Parameters are:
|
|
|
+ * - id (default: false)
|
|
|
+ * - force (default: false)
|
|
|
+ * If id is not specified, all the feeds are actualized. But if force is
|
|
|
+ * false, process stops at 10 feeds to avoid time execution problem.
|
|
|
+ */
|
|
|
public function actualizeAction() {
|
|
|
@set_time_limit(300);
|
|
|
|
|
|
@@ -234,213 +253,229 @@ class FreshRSS_feed_Controller extends Minz_ActionController {
|
|
|
|
|
|
Minz_Session::_param('actualize_feeds', false);
|
|
|
$id = Minz_Request::param('id');
|
|
|
- $force = Minz_Request::param('force', false);
|
|
|
+ $force = Minz_Request::param('force');
|
|
|
|
|
|
- // on créé la liste des flux à mettre à actualiser
|
|
|
- // si on veut mettre un flux à jour spécifiquement, on le met
|
|
|
- // dans la liste, mais seul (permet d'automatiser le traitement)
|
|
|
+ // Create a list of feeds to actualize.
|
|
|
+ // If id is set and valid, corresponding feed is added to the list but
|
|
|
+ // alone in order to automatize further process.
|
|
|
$feeds = array();
|
|
|
if ($id) {
|
|
|
$feed = $feedDAO->searchById($id);
|
|
|
if ($feed) {
|
|
|
- $feeds = array($feed);
|
|
|
+ $feeds[] = $feed;
|
|
|
}
|
|
|
} else {
|
|
|
$feeds = $feedDAO->listFeedsOrderUpdate($this->view->conf->ttl_default);
|
|
|
}
|
|
|
|
|
|
- // on calcule la date des articles les plus anciens qu'on accepte
|
|
|
+ // Calculate date of oldest entries we accept in DB.
|
|
|
$nb_month_old = max($this->view->conf->old_entries, 1);
|
|
|
$date_min = time() - (3600 * 24 * 30 * $nb_month_old);
|
|
|
|
|
|
- $i = 0;
|
|
|
- $flux_update = 0;
|
|
|
+ $updated_feeds = 0;
|
|
|
$is_read = $this->view->conf->mark_when['reception'] ? 1 : 0;
|
|
|
foreach ($feeds as $feed) {
|
|
|
if (!$feed->lock()) {
|
|
|
Minz_Log::notice('Feed already being actualized: ' . $feed->url());
|
|
|
continue;
|
|
|
}
|
|
|
- try {
|
|
|
- $url = $feed->url();
|
|
|
- $feedHistory = $feed->keepHistory();
|
|
|
|
|
|
+ try {
|
|
|
+ // Load entries
|
|
|
$feed->load(false);
|
|
|
- $entries = array_reverse($feed->entries()); //We want chronological order and SimplePie uses reverse order
|
|
|
- $hasTransaction = false;
|
|
|
-
|
|
|
- if (count($entries) > 0) {
|
|
|
- //For this feed, check last n entry GUIDs already in database
|
|
|
- $existingGuids = array_fill_keys(
|
|
|
- $entryDAO->listLastGuidsByFeed($feed->id(),
|
|
|
- count($entries) + 10), 1);
|
|
|
- $useDeclaredDate = empty($existingGuids);
|
|
|
-
|
|
|
- if ($feedHistory == -2) { //default
|
|
|
- $feedHistory = $this->view->conf->keep_history_default;
|
|
|
- }
|
|
|
+ } catch (FreshRSS_Feed_Exception $e) {
|
|
|
+ Minz_Log::notice($e->getMessage());
|
|
|
+ $feedDAO->updateLastUpdate($feed->id(), 1);
|
|
|
+ continue;
|
|
|
+ }
|
|
|
|
|
|
- $preparedStatement = $entryDAO->addEntryPrepare();
|
|
|
- $hasTransaction = true;
|
|
|
- $feedDAO->beginTransaction();
|
|
|
+ $url = $feed->url();
|
|
|
+ $feed_history = $feed->keepHistory();
|
|
|
+ if ($feed_history == -2) {
|
|
|
+ // TODO: -2 must be a constant!
|
|
|
+ // -2 means we take the default value from configuration
|
|
|
+ $feed_history = $this->view->conf->keep_history_default;
|
|
|
+ }
|
|
|
|
|
|
- // On ne vérifie pas strictement que l'article n'est pas déjà en BDD
|
|
|
- // La BDD refusera l'ajout car (id_feed, guid) doit être unique
|
|
|
- foreach ($entries as $entry) {
|
|
|
- $eDate = $entry->date(true);
|
|
|
- if ((!isset($existingGuids[$entry->guid()])) &&
|
|
|
- (($feedHistory != 0) || ($eDate >= $date_min))) {
|
|
|
- $values = $entry->toArray();
|
|
|
- //Use declared date at first import, otherwise use discovery date
|
|
|
- $values['id'] = ($useDeclaredDate || $eDate < $date_min) ?
|
|
|
- min(time(), $eDate) . uSecString() :
|
|
|
- uTimeString();
|
|
|
- $values['is_read'] = $is_read;
|
|
|
- $entryDAO->addEntry($values, $preparedStatement);
|
|
|
- }
|
|
|
+ // We want chronological order and SimplePie uses reverse order.
|
|
|
+ $entries = array_reverse($feed->entries());
|
|
|
+ if (count($entries) > 0) {
|
|
|
+ // For this feed, check last n entry GUIDs already in database.
|
|
|
+ $existing_guids = array_fill_keys($entryDAO->listLastGuidsByFeed(
|
|
|
+ $feed->id(), count($entries) + 10
|
|
|
+ ), 1);
|
|
|
+ $use_declared_date = empty($existing_guids);
|
|
|
+
|
|
|
+ // Add entries in database if possible.
|
|
|
+ $prepared_statement = $entryDAO->addEntryPrepare();
|
|
|
+ $feedDAO->beginTransaction();
|
|
|
+ foreach ($entries as $entry) {
|
|
|
+ $entry_date = $entry->date(true);
|
|
|
+ if (isset($existing_guids[$entry->guid()]) ||
|
|
|
+ ($feed_history == 0 && $entry_date < $date_min)) {
|
|
|
+ // This entry already exists in DB or should not be added
|
|
|
+ // considering configuration and date.
|
|
|
+ continue;
|
|
|
}
|
|
|
- }
|
|
|
|
|
|
- if (($feedHistory >= 0) && (rand(0, 30) === 1)) {
|
|
|
- if (!$hasTransaction) {
|
|
|
- $feedDAO->beginTransaction();
|
|
|
- }
|
|
|
- $nb = $feedDAO->cleanOldEntries($feed->id(), $date_min, max($feedHistory, count($entries) + 10));
|
|
|
- if ($nb > 0) {
|
|
|
- Minz_Log::debug($nb . ' old entries cleaned in feed [' . $feed->url() . ']');
|
|
|
+ $id = uTimeString();
|
|
|
+ if ($use_declared_date || $entry_date < $date_min) {
|
|
|
+ // Use declared date at first import.
|
|
|
+ $id = min(time(), $entry_date) . uSecString();
|
|
|
}
|
|
|
+
|
|
|
+ $values = $entry->toArray();
|
|
|
+ $values['id'] = $id;
|
|
|
+ $values['is_read'] = $is_read;
|
|
|
+ $entryDAO->addEntry($values, $prepared_statement);
|
|
|
}
|
|
|
+ }
|
|
|
|
|
|
- // on indique que le flux vient d'être mis à jour en BDD
|
|
|
- $feedDAO->updateLastUpdate($feed->id(), 0, $hasTransaction);
|
|
|
- if ($hasTransaction) {
|
|
|
- $feedDAO->commit();
|
|
|
+ if ($feed_history >= 0 && rand(0, 30) === 1) {
|
|
|
+ // TODO: move this function in web cron when available
|
|
|
+ // Remove old entries once in 30.
|
|
|
+ if (!$feedDAO->hasTransaction()) {
|
|
|
+ $feedDAO->beginTransaction();
|
|
|
}
|
|
|
- $flux_update++;
|
|
|
- if (($feed->url() !== $url)) { //HTTP 301 Moved Permanently
|
|
|
- Minz_Log::notice('Feed ' . $url . ' moved permanently to ' . $feed->url());
|
|
|
- $feedDAO->updateFeed($feed->id(), array('url' => $feed->url()));
|
|
|
+
|
|
|
+ $nb = $feedDAO->cleanOldEntries($feed->id(),
|
|
|
+ $date_min,
|
|
|
+ max($feed_history, count($entries) + 10));
|
|
|
+ if ($nb > 0) {
|
|
|
+ Minz_Log::debug($nb . ' old entries cleaned in feed [' .
|
|
|
+ $feed->url() . ']');
|
|
|
}
|
|
|
- } catch (FreshRSS_Feed_Exception $e) {
|
|
|
- Minz_Log::notice($e->getMessage());
|
|
|
- $feedDAO->updateLastUpdate($feed->id(), 1);
|
|
|
+ }
|
|
|
+
|
|
|
+ $feedDAO->updateLastUpdate($feed->id(), 0, $feedDAO->hasTransaction());
|
|
|
+ if ($feedDAO->hasTransaction()) {
|
|
|
+ $feedDAO->commit();
|
|
|
+ }
|
|
|
+
|
|
|
+ if ($feed->url() !== $url) {
|
|
|
+ // HTTP 301 Moved Permanently
|
|
|
+ Minz_Log::notice('Feed ' . $url . ' moved permanently to ' . $feed->url());
|
|
|
+ $feedDAO->updateFeed($feed->id(), array('url' => $feed->url()));
|
|
|
}
|
|
|
|
|
|
$feed->faviconPrepare();
|
|
|
$feed->unlock();
|
|
|
+ $updated_feeds++;
|
|
|
unset($feed);
|
|
|
|
|
|
- // On arrête à 10 flux pour ne pas surcharger le serveur
|
|
|
- // sauf si le paramètre $force est à vrai
|
|
|
- $i++;
|
|
|
- if ($i >= 10 && !$force) {
|
|
|
+ // No more than 10 feeds unless $force is true to avoid overloading
|
|
|
+ // the server.
|
|
|
+ if ($updated_feeds >= 10 && !$force) {
|
|
|
break;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- $url = array();
|
|
|
- if ($flux_update === 1) {
|
|
|
- // on a mis un seul flux à jour
|
|
|
- $feed = reset($feeds);
|
|
|
+ if (Minz_Request::param('ajax')) {
|
|
|
+ // Most of the time, ajax request is for only one feed. But since
|
|
|
+ // there are several parallel requests, we should return that there
|
|
|
+ // are several updated feeds.
|
|
|
$notif = array(
|
|
|
'type' => 'good',
|
|
|
- 'content' => _t('feed_actualized', $feed->name())
|
|
|
- );
|
|
|
- } elseif ($flux_update > 1) {
|
|
|
- // plusieurs flux on été mis à jour
|
|
|
- $notif = array(
|
|
|
- 'type' => 'good',
|
|
|
- 'content' => _t('n_feeds_actualized', $flux_update)
|
|
|
- );
|
|
|
- } else {
|
|
|
- // aucun flux n'a été mis à jour, oups
|
|
|
- $notif = array(
|
|
|
- 'type' => 'good',
|
|
|
- 'content' => _t('no_feed_to_refresh')
|
|
|
+ 'content' => _t('feeds_actualized')
|
|
|
);
|
|
|
+ Minz_Session::_param('notification', $notif);
|
|
|
+ // No layout in ajax request.
|
|
|
+ $this->view->_useLayout(false);
|
|
|
+ return;
|
|
|
}
|
|
|
|
|
|
- if ($i === 1) {
|
|
|
- // Si on a voulu mettre à jour qu'un flux
|
|
|
- // on filtre l'affichage par ce flux
|
|
|
+ // Redirect to the main page with correct notification.
|
|
|
+ if ($updated_feeds === 1) {
|
|
|
$feed = reset($feeds);
|
|
|
- $url['params'] = array('get' => 'f_' . $feed->id());
|
|
|
- }
|
|
|
-
|
|
|
- if (Minz_Request::param('ajax', 0) === 0) {
|
|
|
- Minz_Session::_param('notification', $notif);
|
|
|
- Minz_Request::forward($url, true);
|
|
|
+ Minz_Request::good(_t('feed_actualized', $feed->name()),
|
|
|
+ array('get' => 'f_' . $feed->id()));
|
|
|
+ } elseif ($updated_feeds > 1) {
|
|
|
+ Minz_Request::good(_t('n_feeds_actualized', $updated_feeds), array());
|
|
|
} else {
|
|
|
- // Une requête Ajax met un seul flux à jour.
|
|
|
- // Comme en principe plusieurs requêtes ont lieu,
|
|
|
- // on indique que "plusieurs flux ont été mis à jour".
|
|
|
- // Cela permet d'avoir une notification plus proche du
|
|
|
- // ressenti utilisateur
|
|
|
- $notif = array(
|
|
|
- 'type' => 'good',
|
|
|
- 'content' => _t('feeds_actualized')
|
|
|
- );
|
|
|
- Minz_Session::_param('notification', $notif);
|
|
|
- // et on désactive le layout car ne sert à rien
|
|
|
- $this->view->_useLayout(false);
|
|
|
+ Minz_Request::good(_t('no_feed_to_refresh'), array());
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+ /**
|
|
|
+ * This action changes the category of a feed.
|
|
|
+ *
|
|
|
+ * This page must be reached by a POST request.
|
|
|
+ *
|
|
|
+ * Parameters are:
|
|
|
+ * - f_id (default: false)
|
|
|
+ * - c_id (default: false)
|
|
|
+ * If c_id is false, default category is used.
|
|
|
+ *
|
|
|
+ * @todo should handle order of the feed inside the category.
|
|
|
+ */
|
|
|
public function moveAction() {
|
|
|
- if (Minz_Request::isPost()) {
|
|
|
- $feed_id = Minz_Request::param('f_id');
|
|
|
- $cat_id = Minz_Request::param('c_id');
|
|
|
+ if (!Minz_Request::isPost()) {
|
|
|
+ Minz_Request::forward(array('c' => 'subscription'), true);
|
|
|
+ }
|
|
|
|
|
|
- $feedDAO = FreshRSS_Factory::createFeedDao();
|
|
|
- $values = array(
|
|
|
- 'category' => $cat_id,
|
|
|
- );
|
|
|
+ $feed_id = Minz_Request::param('f_id');
|
|
|
+ $cat_id = Minz_Request::param('c_id');
|
|
|
|
|
|
- $feed = $feedDAO->searchById($feed_id);
|
|
|
+ if ($cat_id === false) {
|
|
|
+ // If category was not given get the default one.
|
|
|
+ $catDAO = new FreshRSS_CategoryDAO();
|
|
|
+ $catDAO->checkDefault();
|
|
|
+ $def_cat = $catDAO->getDefault();
|
|
|
+ $cat_id = $def_cat->id();
|
|
|
+ }
|
|
|
|
|
|
- if ($feed && ($feed->category() == $cat_id ||
|
|
|
- $feedDAO->updateFeed($feed_id, $values))) {
|
|
|
- // TODO: return something useful
|
|
|
- } else {
|
|
|
- Minz_Error::error(
|
|
|
- 404,
|
|
|
- array('error' => array(_t('error_occurred')))
|
|
|
- );
|
|
|
- }
|
|
|
+ $feedDAO = FreshRSS_Factory::createFeedDao();
|
|
|
+ $values = array('category' => $cat_id);
|
|
|
+
|
|
|
+ $feed = $feedDAO->searchById($feed_id);
|
|
|
+ if ($feed && ($feed->category() == $cat_id ||
|
|
|
+ $feedDAO->updateFeed($feed_id, $values))) {
|
|
|
+ // TODO: return something useful
|
|
|
+ } else {
|
|
|
+ Minz_Log::warning('Cannot move feed `' . $feed_id . '` ' .
|
|
|
+ 'in the category `' . $cat_id . '`');
|
|
|
+ Minz_Error::error(
|
|
|
+ 404,
|
|
|
+ array('error' => array(_t('error_occurred')))
|
|
|
+ );
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+ /**
|
|
|
+ * This action deletes a feed.
|
|
|
+ *
|
|
|
+ * This page must be reached by a POST request.
|
|
|
+ * If there are related queries, they are deleted too.
|
|
|
+ *
|
|
|
+ * Parameters are:
|
|
|
+ * - id (default: false)
|
|
|
+ * - r (default: false)
|
|
|
+ * r permits to redirect to a given page at the end of this action.
|
|
|
+ *
|
|
|
+ * @todo handle "r" redirection in Minz_Request::forward()?
|
|
|
+ */
|
|
|
public function deleteAction() {
|
|
|
- if (Minz_Request::isPost()) {
|
|
|
- $id = Minz_Request::param('id');
|
|
|
- $feedDAO = FreshRSS_Factory::createFeedDao();
|
|
|
-
|
|
|
- if ($feedDAO->deleteFeed($id)) {
|
|
|
- // TODO: Delete old favicon
|
|
|
+ $redirect_url = Minz_Request::param('r', false, true);
|
|
|
+ if (!$redirect_url) {
|
|
|
+ $redirect_url = array('c' => 'subscription', 'a' => 'index');
|
|
|
+ }
|
|
|
|
|
|
- // Remove related queries
|
|
|
- $this->view->conf->remove_query_by_get('f_' . $id);
|
|
|
- $this->view->conf->save();
|
|
|
+ if (!Minz_Request::isPost()) {
|
|
|
+ Minz_Request::forward($redirect_url, true);
|
|
|
+ }
|
|
|
|
|
|
- $notif = array(
|
|
|
- 'type' => 'good',
|
|
|
- 'content' => _t('feed_deleted')
|
|
|
- );
|
|
|
- } else {
|
|
|
- $notif = array(
|
|
|
- 'type' => 'bad',
|
|
|
- 'content' => _t('error_occured')
|
|
|
- );
|
|
|
- }
|
|
|
+ $id = Minz_Request::param('id');
|
|
|
+ $feedDAO = FreshRSS_Factory::createFeedDao();
|
|
|
+ if ($feedDAO->deleteFeed($id)) {
|
|
|
+ // TODO: Delete old favicon
|
|
|
|
|
|
- Minz_Session::_param('notification', $notif);
|
|
|
+ // Remove related queries
|
|
|
+ $this->view->conf->remove_query_by_get('f_' . $id);
|
|
|
+ $this->view->conf->save();
|
|
|
|
|
|
- $redirect_url = Minz_Request::param('r', false, true);
|
|
|
- if ($redirect_url) {
|
|
|
- Minz_Request::forward($redirect_url);
|
|
|
- } else {
|
|
|
- Minz_Request::forward(array('c' => 'subscription', 'a' => 'index'), true);
|
|
|
- }
|
|
|
+ Minz_Request::good(_t('feed_deleted'), $redirect_url);
|
|
|
+ } else {
|
|
|
+ Minz_Request::bad(_t('error_occurred'), $redirect_url);
|
|
|
}
|
|
|
}
|
|
|
}
|