public function optimizeAction() { if (Minz_Request::isPost()) { @set_time_limit(300); // La table des entrées a tendance à grossir énormément // Cette action permet d'optimiser cette table permettant de grapiller un peu de place // Cette fonctionnalité n'est à appeler qu'occasionnellement $entryDAO = new FreshRSS_EntryDAO(); $entryDAO->optimizeTable(); invalidateHttpCache(); $notif = array('type' => 'good', 'content' => Minz_Translate::t('optimization_complete')); Minz_Session::_param('notification', $notif); } Minz_Request::forward(array('c' => 'configure', 'a' => 'archiving'), true); }
public function addEntry($valuesTmp, $preparedStatement = null) { $stm = $preparedStatement === null ? FreshRSS_EntryDAO::addEntryPrepare() : $preparedStatement; $values = array($valuesTmp['id'], substr($valuesTmp['guid'], 0, 760), substr($valuesTmp['title'], 0, 255), substr($valuesTmp['author'], 0, 255), $valuesTmp['content'], substr($valuesTmp['link'], 0, 1023), $valuesTmp['date'], $valuesTmp['is_read'] ? 1 : 0, $valuesTmp['is_favorite'] ? 1 : 0, $valuesTmp['id_feed'], substr($valuesTmp['tags'], 0, 1023)); if ($stm && $stm->execute($values)) { return $this->bd->lastInsertId(); } else { $info = $stm == null ? array(2 => 'syntax error') : $stm->errorInfo(); if ((int) ($info[0] / 1000) !== 23) { //Filter out "SQLSTATE Class code 23: Constraint Violation" because of expected duplicate entries Minz_Log::error('SQL error addEntry: ' . $info[0] . ': ' . $info[1] . ' ' . $info[2] . ' while adding entry in feed ' . $valuesTmp['id_feed'] . ' with title: ' . $valuesTmp['title']); } /*else { Minz_Log::debug('SQL error ' . $info[0] . ': ' . $info[1] . ' ' . $info[2] . ' while adding entry in feed ' . $valuesTmp['id_feed'] . ' with title: ' . $valuesTmp['title']); }*/ return false; } }
public function archivingAction() { if (Minz_Request::isPost()) { $old = Minz_Request::param('old_entries', 3); $keepHistoryDefault = Minz_Request::param('keep_history_default', 0); $this->view->conf->_old_entries($old); $this->view->conf->_keep_history_default($keepHistoryDefault); $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_View::prependTitle(Minz_Translate::t('archiving_configuration') . ' · '); $entryDAO = new FreshRSS_EntryDAO(); $this->view->nb_total = $entryDAO->count(); $this->view->size_user = $entryDAO->size(); if (Minz_Configuration::isAdmin(Minz_Session::param('currentUser', '_'))) { $this->view->size_total = $entryDAO->size(true); } }
public function loadCompleteContent($pathEntries) { // Gestion du contenu // On cherche à récupérer les articles en entier... même si le flux ne le propose pas if ($pathEntries) { $entryDAO = new FreshRSS_EntryDAO(); $entry = $entryDAO->searchByGuid($this->feed, $this->guid); if ($entry) { // l'article existe déjà en BDD, en se contente de recharger ce contenu $this->content = $entry->content(); } else { try { // l'article n'est pas en BDD, on va le chercher sur le site $this->content = get_content_by_parsing(htmlspecialchars_decode($this->link(), ENT_QUOTES), $pathEntries); } catch (Exception $e) { // rien à faire, on garde l'ancien contenu (requête a échoué) } } } }
public function indexAction() { $output = Minz_Request::param('output'); $token = $this->view->conf->token; // check if user is logged in if (!$this->view->loginOk && !Minz_Configuration::allowAnonymous()) { $token_param = Minz_Request::param('token', ''); $token_is_ok = $token != '' && $token === $token_param; if ($output === 'rss' && !$token_is_ok) { Minz_Error::error(403, array('error' => array(Minz_Translate::t('access_denied')))); return; } elseif ($output !== 'rss') { // "hard" redirection is not required, just ask dispatcher to // forward to the login form without 302 redirection Minz_Request::forward(array('c' => 'index', 'a' => 'formLogin')); return; } } // construction of RSS url of this feed $params = Minz_Request::params(); $params['output'] = 'rss'; if (isset($params['search'])) { $params['search'] = urlencode($params['search']); } if (!Minz_Configuration::allowAnonymous()) { $params['token'] = $token; } $this->view->rss_url = array('c' => 'index', 'a' => 'index', 'params' => $params); if ($output === 'rss') { // no layout for RSS output $this->view->_useLayout(false); header('Content-Type: application/rss+xml; charset=utf-8'); } elseif ($output === 'global') { Minz_View::appendScript(Minz_Url::display('/scripts/global_view.js?' . @filemtime(PUBLIC_PATH . '/scripts/global_view.js'))); } $catDAO = new FreshRSS_CategoryDAO(); $entryDAO = new FreshRSS_EntryDAO(); $this->view->cat_aside = $catDAO->listCategories(); $this->view->nb_favorites = $entryDAO->countUnreadReadFavorites(); $this->view->nb_not_read = FreshRSS_CategoryDAO::CountUnreads($this->view->cat_aside, 1); $this->view->currentName = ''; $this->view->get_c = ''; $this->view->get_f = ''; $get = Minz_Request::param('get', 'a'); $getType = $get[0]; $getId = substr($get, 2); if (!$this->checkAndProcessType($getType, $getId)) { Minz_Log::record('Not found [' . $getType . '][' . $getId . ']', Minz_Log::DEBUG); Minz_Error::error(404, array('error' => array(Minz_Translate::t('page_not_found')))); return; } // mise à jour des titres $this->view->rss_title = $this->view->currentName . ' | ' . Minz_View::title(); if ($this->view->nb_not_read > 0) { Minz_View::appendTitle(' (' . formatNumber($this->view->nb_not_read) . ')'); } Minz_View::prependTitle($this->view->currentName . ($this->nb_not_read_cat > 0 ? ' (' . formatNumber($this->nb_not_read_cat) . ')' : '') . ' · '); // On récupère les différents éléments de filtrage $this->view->state = $state = Minz_Request::param('state', $this->view->conf->default_view); $filter = Minz_Request::param('search', ''); if (!empty($filter)) { $state = 'all'; //Search always in read and unread articles } $this->view->order = $order = Minz_Request::param('order', $this->view->conf->sort_order); $nb = Minz_Request::param('nb', $this->view->conf->posts_per_page); $first = Minz_Request::param('next', ''); if ($state === 'not_read') { //Any unread article in this category at all? switch ($getType) { case 'a': $hasUnread = $this->view->nb_not_read > 0; break; case 's': $hasUnread = $this->view->nb_favorites['unread'] > 0; break; case 'c': $hasUnread = !isset($this->view->cat_aside[$getId]) || $this->view->cat_aside[$getId]->nbNotRead() > 0; break; case 'f': $myFeed = FreshRSS_CategoryDAO::findFeed($this->view->cat_aside, $getId); $hasUnread = $myFeed === null || $myFeed->nbNotRead() > 0; break; default: $hasUnread = true; break; } if (!$hasUnread) { $this->view->state = $state = 'all'; } } $today = @strtotime('today'); $this->view->today = $today; // on calcule la date des articles les plus anciens qu'on affiche $nb_month_old = $this->view->conf->old_entries; $date_min = $today - 3600 * 24 * 30 * $nb_month_old; //Do not use a fast changing value such as time() to allow SQL caching $keepHistoryDefault = $this->view->conf->keep_history_default; try { $entries = $entryDAO->listWhere($getType, $getId, $state, $order, $nb + 1, $first, $filter, $date_min, $keepHistoryDefault); // Si on a récupéré aucun article "non lus" // on essaye de récupérer tous les articles if ($state === 'not_read' && empty($entries)) { Minz_Log::record('Conflicting information about nbNotRead!', Minz_Log::DEBUG); $this->view->state = 'all'; $entries = $entryDAO->listWhere($getType, $getId, 'all', $order, $nb, $first, $filter, $date_min, $keepHistoryDefault); } if (count($entries) <= $nb) { $this->view->nextId = ''; } else { //We have more elements for pagination $lastEntry = array_pop($entries); $this->view->nextId = $lastEntry->id(); } $this->view->entries = $entries; } catch (FreshRSS_EntriesGetter_Exception $e) { Minz_Log::record($e->getMessage(), Minz_Log::NOTICE); Minz_Error::error(404, array('error' => array(Minz_Translate::t('page_not_found')))); } }
public function actualizeAction() { @set_time_limit(300); $feedDAO = new FreshRSS_FeedDAO(); $entryDAO = new FreshRSS_EntryDAO(); Minz_Session::_param('actualize_feeds', false); $id = Minz_Request::param('id'); $force = Minz_Request::param('force', false); // 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) $feeds = array(); if ($id) { $feed = $feedDAO->searchById($id); if ($feed) { $feeds = array($feed); } } else { $feeds = $feedDAO->listFeedsOrderUpdate(); } // on calcule la date des articles les plus anciens qu'on accepte $nb_month_old = max($this->view->conf->old_entries, 1); $date_min = time() - 3600 * 24 * 30 * $nb_month_old; $i = 0; $flux_update = 0; $is_read = $this->view->conf->mark_when['reception'] ? 1 : 0; foreach ($feeds as $feed) { if (!$feed->lock()) { Minz_Log::record('Feed already being actualized: ' . $feed->url(), Minz_Log::NOTICE); continue; } try { $url = $feed->url(); $feedHistory = $feed->keepHistory(); $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; } $hasTransaction = true; $feedDAO->beginTransaction(); // 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); } } } 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::record($nb . ' old entries cleaned in feed [' . $feed->url() . ']', Minz_Log::DEBUG); } } // on indique que le flux vient d'être mis à jour en BDD $feedDAO->updateLastUpdate($feed->id(), 0, $hasTransaction); if ($hasTransaction) { $feedDAO->commit(); } $flux_update++; if ($feed->url() !== $url) { //URL has changed (auto-discovery) $feedDAO->updateFeed($feed->id(), array('url' => $feed->url())); } } catch (FreshRSS_Feed_Exception $e) { Minz_Log::record($e->getMessage(), Minz_Log::NOTICE); $feedDAO->updateLastUpdate($feed->id(), 1); } $feed->faviconPrepare(); $feed->unlock(); 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) { break; } } $url = array(); if ($flux_update === 1) { // on a mis un seul flux à jour $feed = reset($feeds); $notif = array('type' => 'good', 'content' => Minz_Translate::t('feed_actualized', $feed->name())); } elseif ($flux_update > 1) { // plusieurs flux on été mis à jour $notif = array('type' => 'good', 'content' => Minz_Translate::t('n_feeds_actualized', $flux_update)); } else { // aucun flux n'a été mis à jour, oups $notif = array('type' => 'good', 'content' => Minz_Translate::t('no_feed_to_refresh')); } if ($i === 1) { // Si on a voulu mettre à jour qu'un flux // on filtre l'affichage par ce flux $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); } 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' => Minz_Translate::t('feeds_actualized')); Minz_Session::_param('notification', $notif); // et on désactive le layout car ne sert à rien $this->view->_useLayout(false); } }