/**
  * 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()
 {
     if (Minz_Request::param('ajax')) {
         $this->view->_useLayout(false);
     }
     $feedDAO = FreshRSS_Factory::createFeedDao();
     $this->view->feeds = $feedDAO->listFeeds();
     $id = Minz_Request::param('id');
     if ($id === false || !isset($this->view->feeds[$id])) {
         Minz_Error::error(404);
         return;
     }
     $this->view->feed = $this->view->feeds[$id];
     Minz_View::prependTitle(_t('sub.title.feed_management') . ' · ' . $this->view->feed->name() . ' · ');
     if (Minz_Request::isPost()) {
         $user = Minz_Request::param('http_user', '');
         $pass = Minz_Request::param('http_pass', '');
         $httpAuth = '';
         if ($user != '' || $pass != '') {
             $httpAuth = $user . ':' . $pass;
         }
         $cat = intval(Minz_Request::param('category', 0));
         $values = array('name' => Minz_Request::param('name', ''), 'description' => sanitizeHTML(Minz_Request::param('description', '', true)), 'website' => Minz_Request::param('website', ''), 'url' => Minz_Request::param('url', ''), 'category' => $cat, 'pathEntries' => Minz_Request::param('path_entries', ''), 'priority' => intval(Minz_Request::param('priority', 0)), 'httpAuth' => $httpAuth, 'keep_history' => intval(Minz_Request::param('keep_history', -2)), 'ttl' => intval(Minz_Request::param('ttl', -2)));
         invalidateHttpCache();
         $url_redirect = array('c' => 'subscription', 'params' => array('id' => $id));
         if ($feedDAO->updateFeed($id, $values) !== false) {
             $this->view->feed->_category($cat);
             $this->view->feed->faviconPrepare();
             Minz_Request::good(_t('feedback.sub.feed.updated'), $url_redirect);
         } else {
             Minz_Request::bad(_t('feedback.sub.feed.error'), $url_redirect);
         }
     }
 }
 /**
  * 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 (!FreshRSS_Auth::hasAccess()) {
         Minz_Error::error(403);
     }
     require_once LIB_PATH . '/lib_opml.php';
     $this->catDAO = new FreshRSS_CategoryDAO();
     $this->entryDAO = FreshRSS_Factory::createEntryDao();
     $this->feedDAO = FreshRSS_Factory::createFeedDao();
 }
Пример #3
0
 public function feeds()
 {
     if ($this->feeds === null) {
         $feedDAO = FreshRSS_Factory::createFeedDao();
         $this->feeds = $feedDAO->listByCategory($this->id());
         $this->nbFeed = 0;
         $this->nbNotRead = 0;
         foreach ($this->feeds as $feed) {
             $this->nbFeed++;
             $this->nbNotRead += $feed->nbNotRead();
         }
     }
     return $this->feeds;
 }
Пример #4
0
 public function changeCategory($idOldCat, $idNewCat)
 {
     $catDAO = FreshRSS_Factory::createCategoryDAO();
     $newCat = $catDAO->searchById($idNewCat);
     if (!$newCat) {
         $newCat = $catDAO->getDefault();
     }
     $sql = 'UPDATE ' . $this->prefix . 'feed SET category=? WHERE category=?';
     $stm = $this->bd->prepare($sql);
     $values = array($newCat->id(), $idOldCat);
     if ($stm && $stm->execute($values)) {
         return $stm->rowCount();
     } else {
         $info = $stm == null ? array(2 => 'syntax error') : $stm->errorInfo();
         Minz_Log::error('SQL error changeCategory: ' . $info[2]);
         return false;
     }
 }
Пример #5
0
 /**
  * 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()
 {
     $redirect_url = Minz_Request::param('r', false, true);
     if (!$redirect_url) {
         $redirect_url = array('c' => 'subscription', 'a' => 'index');
     }
     if (!Minz_Request::isPost()) {
         Minz_Request::forward($redirect_url, true);
     }
     $id = Minz_Request::param('id');
     $feedDAO = FreshRSS_Factory::createFeedDao();
     if ($feedDAO->deleteFeed($id)) {
         // TODO: Delete old favicon
         // Remove related queries
         FreshRSS_Context::$user_conf->queries = remove_query_by_get('f_' . $id, FreshRSS_Context::$user_conf->queries);
         FreshRSS_Context::$user_conf->save();
         Minz_Request::good(_t('feedback.sub.feed.deleted'), $redirect_url);
     } else {
         Minz_Request::bad(_t('feedback.sub.feed.error'), $redirect_url);
     }
 }
Пример #6
0
 /**
  * This method returns a list of entries based on the Context object.
  */
 private function listEntriesByContext()
 {
     $entryDAO = FreshRSS_Factory::createEntryDao();
     $get = FreshRSS_Context::currentGet(true);
     if (count($get) > 1) {
         $type = $get[0];
         $id = $get[1];
     } else {
         $type = $get;
         $id = '';
     }
     return $entryDAO->listWhere($type, $id, FreshRSS_Context::$state, FreshRSS_Context::$order, FreshRSS_Context::$number + 1, FreshRSS_Context::$first_id, FreshRSS_Context::$search);
 }
Пример #7
0
 public function getCounters()
 {
     $categoryDAO = new FreshRSS_CategoryDAO();
     $counters = array();
     $total_unreads = 0;
     // Get feed unread counters
     $categories = $categoryDAO->listCategories(true, true);
     foreach ($categories as $cat) {
         foreach ($cat->feeds() as $feed) {
             $counters[] = array('id' => $feed->id(), 'counter' => $feed->nbNotRead());
         }
         $total_unreads += $cat->nbNotRead();
     }
     // Get global unread counter
     $counters[] = array('id' => 'global-unread', 'counter' => $total_unreads);
     // Get favorite unread counter
     $entryDAO = FreshRSS_Factory::createEntryDao();
     $fav_counters = $entryDAO->countUnreadReadFavorites();
     $counters[] = array('id' => -1, 'counter' => $fav_counters['unread']);
     $this->good($counters);
 }
Пример #8
0
 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 = FreshRSS_Factory::createEntryDao();
         $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é)
             }
         }
     }
 }
Пример #9
0
function markAllAsRead($streamId, $olderThanId)
{
    logMe("markAllAsRead({$streamId}, {$olderThanId})\n");
    $entryDAO = FreshRSS_Factory::createEntryDao();
    if (strpos($streamId, 'feed/') === 0) {
        $f_id = basename($streamId);
        $entryDAO->markReadFeed($f_id, $olderThanId);
    } elseif (strpos($streamId, 'user/-/label/') === 0) {
        $c_name = basename($streamId);
        $categoryDAO = new FreshRSS_CategoryDAO();
        $cat = $categoryDAO->searchByName($c_name);
        $entryDAO->markReadCat($cat === null ? -1 : $cat->id(), $olderThanId);
    } elseif ($streamId === 'user/-/state/com.google/reading-list') {
        $entryDAO->markReadEntries($olderThanId, false, -1);
    }
    echo 'OK';
    exit;
}
Пример #10
0
 public function actualizeAction()
 {
     header('Content-Type: text/javascript; charset=UTF-8');
     $feedDAO = FreshRSS_Factory::createFeedDao();
     $this->view->feeds = $feedDAO->listFeedsOrderUpdate(FreshRSS_Context::$user_conf->ttl_default);
 }
Пример #11
0
 /**
  * This action displays the user management page.
  */
 public function manageAction()
 {
     if (!FreshRSS_Auth::hasAccess('admin')) {
         Minz_Error::error(403);
     }
     Minz_View::prependTitle(_t('admin.user.title') . ' · ');
     // Get the correct current user.
     $username = Minz_Request::param('u', Minz_Session::param('currentUser'));
     if (!FreshRSS_UserDAO::exist($username)) {
         $username = Minz_Session::param('currentUser');
     }
     $this->view->current_user = $username;
     // Get information about the current user.
     $entryDAO = FreshRSS_Factory::createEntryDao($this->view->current_user);
     $this->view->nb_articles = $entryDAO->count();
     $this->view->size_user = $entryDAO->size();
 }
Пример #12
0
 public function nbUnreadsPerFeedAction()
 {
     header('Content-Type: application/json; charset=UTF-8');
     $catDAO = FreshRSS_Factory::createCategoryDAO();
     $this->view->categories = $catDAO->listCategories(true, false);
 }
Пример #13
0
 /**
  * This action purges old entries from feeds.
  *
  * @todo should be a POST request
  * @todo should be in feedController
  */
 public function purgeAction()
 {
     @set_time_limit(300);
     $nb_month_old = max(FreshRSS_Context::$user_conf->old_entries, 1);
     $date_min = time() - 3600 * 24 * 30 * $nb_month_old;
     $feedDAO = FreshRSS_Factory::createFeedDao();
     $feeds = $feedDAO->listFeeds();
     $nb_total = 0;
     invalidateHttpCache();
     foreach ($feeds as $feed) {
         $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 = FreshRSS_Context::$user_conf->keep_history_default;
         }
         if ($feed_history >= 0) {
             $nb = $feedDAO->cleanOldEntries($feed->id(), $date_min, $feed_history);
             if ($nb > 0) {
                 $nb_total += $nb;
                 Minz_Log::debug($nb . ' old entries cleaned in feed [' . $feed->url() . ']');
             }
         }
     }
     $feedDAO->updateCachedValues();
     invalidateHttpCache();
     Minz_Request::good(_t('feedback.sub.purge_completed', $nb_total), array('c' => 'configure', 'a' => 'archiving'));
 }
Пример #14
0
 /**
  * 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()
 {
     $category_dao = FreshRSS_Factory::createCategoryDAO();
     $feed_dao = FreshRSS_Factory::createFeedDao();
     $queries = array();
     foreach (FreshRSS_Context::$user_conf->queries as $key => $query) {
         $queries[$key] = new FreshRSS_UserQuery($query, $feed_dao, $category_dao);
     }
     $params = Minz_Request::params();
     $params['url'] = Minz_Url::display(array('params' => $params));
     $params['name'] = _t('conf.query.number', count($queries) + 1);
     $queries[] = new FreshRSS_UserQuery($params, $feed_dao, $category_dao);
     FreshRSS_Context::$user_conf->queries = $queries;
     FreshRSS_Context::$user_conf->save();
     Minz_Request::good(_t('feedback.conf.query_created', $query['name']), array('c' => 'configure', 'a' => 'queries'));
 }
Пример #15
0
 public static function daoToCategoryPrepopulated($listDAO)
 {
     $list = array();
     if (!is_array($listDAO)) {
         $listDAO = array($listDAO);
     }
     $previousLine = null;
     $feedsDao = array();
     $feedDao = FreshRSS_Factory::createFeedDAO();
     foreach ($listDAO as $line) {
         if ($previousLine['c_id'] != null && $line['c_id'] !== $previousLine['c_id']) {
             // End of the current category, we add it to the $list
             $cat = new FreshRSS_Category($previousLine['c_name'], $feedDao->daoToFeed($feedsDao, $previousLine['c_id']));
             $cat->_id($previousLine['c_id']);
             $list[$previousLine['c_id']] = $cat;
             $feedsDao = array();
             //Prepare for next category
         }
         $previousLine = $line;
         $feedsDao[] = $line;
     }
     // add the last category
     if ($previousLine != null) {
         $cat = new FreshRSS_Category($previousLine['c_name'], $feedDao->daoToFeed($feedsDao, $previousLine['c_id']));
         $cat->_id($previousLine['c_id']);
         $list[$previousLine['c_id']] = $cat;
     }
     return $list;
 }
Пример #16
0
 /**
  * Set the current $get attribute.
  *
  * Valid $get parameter are:
  *   - a
  *   - s
  *   - f_<feed id>
  *   - c_<category id>
  *
  * $name and $get_unread attributes are also updated as $next_get
  * Raise an exception if id or $get is invalid.
  */
 public static function _get($get)
 {
     $type = $get[0];
     $id = substr($get, 2);
     $nb_unread = 0;
     switch ($type) {
         case 'a':
             self::$current_get['all'] = true;
             self::$name = _t('index.feed.title');
             self::$get_unread = self::$total_unread;
             break;
         case 's':
             self::$current_get['starred'] = true;
             self::$name = _t('index.feed.title_fav');
             self::$get_unread = self::$total_starred['unread'];
             // Update state if favorite is not yet enabled.
             self::$state = self::$state | FreshRSS_Entry::STATE_FAVORITE;
             break;
         case 'f':
             // We try to find the corresponding feed. When allowing robots, always retrieve the full feed including description
             $catDAO = FreshRSS_Factory::createCategoryDAO();
             $feed = FreshRSS_Context::$system_conf->allow_robots ? null : $catDAO->findFeed(self::$categories, $id);
             if ($feed === null) {
                 $feedDAO = FreshRSS_Factory::createFeedDao();
                 $feed = $feedDAO->searchById($id);
                 if (!$feed) {
                     throw new FreshRSS_Context_Exception('Invalid feed: ' . $id);
                 }
             }
             self::$current_get['feed'] = $id;
             self::$current_get['category'] = $feed->category();
             self::$name = $feed->name();
             self::$description = $feed->description();
             self::$get_unread = $feed->nbNotRead();
             break;
         case 'c':
             // We try to find the corresponding category.
             self::$current_get['category'] = $id;
             if (!isset(self::$categories[$id])) {
                 $catDAO = FreshRSS_Factory::createCategoryDAO();
                 $cat = $catDAO->searchById($id);
                 if (!$cat) {
                     throw new FreshRSS_Context_Exception('Invalid category: ' . $id);
                 }
             } else {
                 $cat = self::$categories[$id];
             }
             self::$name = $cat->name();
             self::$get_unread = $cat->nbNotRead();
             break;
         default:
             throw new FreshRSS_Context_Exception('Invalid getter: ' . $get);
     }
     self::_nextGet();
 }
Пример #17
0
 public function nbNotRead()
 {
     if ($this->nbNotRead < 0) {
         $feedDAO = FreshRSS_Factory::createFeedDao();
         $this->nbNotRead = $feedDAO->countNotRead($this->id());
     }
     return $this->nbNotRead;
 }
Пример #18
0
 /**
  * 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'] = _t('conf.query.number', $key + 1);
             }
         }
         FreshRSS_Context::$user_conf->queries = $queries;
         FreshRSS_Context::$user_conf->save();
         Minz_Request::good(_t('feedback.conf.updated'), array('c' => 'configure', 'a' => 'queries'));
     } else {
         $this->view->query_get = array();
         $cat_dao = new FreshRSS_CategoryDAO();
         $feed_dao = FreshRSS_Factory::createFeedDao();
         foreach (FreshRSS_Context::$user_conf->queries as $key => $query) {
             if (!isset($query['get'])) {
                 continue;
             }
             switch ($query['get'][0]) {
                 case 'c':
                     $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' => $cat_name, 'deprecated' => $deprecated);
                     break;
                 case 'f':
                     $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, '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(_t('conf.query.title') . ' · ');
 }
Пример #19
0
/**
 * Check database is well-installed.
 *
 * @return array of tested values.
 */
function check_install_database()
{
    $status = array('connection' => true, 'tables' => false, 'categories' => false, 'feeds' => false, 'entries' => false);
    try {
        $dbDAO = FreshRSS_Factory::createDatabaseDAO();
        $status['tables'] = $dbDAO->tablesAreCorrect();
        $status['categories'] = $dbDAO->categoryIsCorrect();
        $status['feeds'] = $dbDAO->feedIsCorrect();
        $status['entries'] = $dbDAO->entryIsCorrect();
    } catch (Minz_PDOConnectionException $e) {
        $status['connection'] = false;
    }
    return $status;
}
Пример #20
0
 /**
  * This action deletes all the feeds relative to a given category.
  * Feed-related queries are deleted.
  *
  * Request parameter is:
  *   - id (of a category)
  */
 public function emptyAction()
 {
     $feedDAO = FreshRSS_Factory::createFeedDao();
     $url_redirect = array('c' => 'subscription', 'a' => 'index');
     if (Minz_Request::isPost()) {
         invalidateHttpCache();
         $id = Minz_Request::param('id');
         if (!$id) {
             Minz_Request::bad(_t('feedback.sub.category.no_id'), $url_redirect);
         }
         // List feeds to remove then related user queries.
         $feeds = $feedDAO->listByCategory($id);
         if ($feedDAO->deleteFeedByCategory($id)) {
             // TODO: Delete old favicons
             // Remove related queries
             foreach ($feeds as $feed) {
                 FreshRSS_Context::$user_conf->queries = remove_query_by_get('f_' . $feed->id(), FreshRSS_Context::$user_conf->queries);
             }
             FreshRSS_Context::$user_conf->save();
             Minz_Request::good(_t('feedback.sub.category.emptied'), $url_redirect);
         } else {
             Minz_Request::bad(_t('feedback.sub.category.error'), $url_redirect);
         }
     }
     Minz_Request::forward($url_redirect, true);
 }
Пример #21
0
 /**
  * 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();
     $feedDAO = FreshRSS_Factory::createFeedDao();
     Minz_View::appendScript(Minz_Url::display('/scripts/flotr2.min.js?' . @filemtime(PUBLIC_PATH . '/scripts/flotr2.min.js')));
     $id = Minz_Request::param('id', null);
     $this->view->categories = $categoryDAO->listCategories();
     $this->view->feed = $feedDAO->searchById($id);
     $this->view->days = $statsDAO->getDays();
     $this->view->months = $statsDAO->getMonths();
     $this->view->repartition = $statsDAO->calculateEntryRepartitionPerFeed($id);
     $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);
 }