Beispiel #1
0
 public function nbNotRead()
 {
     if ($this->nbNotRead < 0) {
         $catDAO = new FreshRSS_CategoryDAO();
         $this->nbNotRead = $catDAO->countNotRead($this->id());
     }
     return $this->nbNotRead;
 }
 /**
  * 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);
     }
     $catDAO = new FreshRSS_CategoryDAO();
     $catDAO->checkDefault();
     $this->view->categories = $catDAO->listCategories(false);
     $this->view->default_category = $catDAO->getDefault();
 }
Beispiel #3
0
function opml_import($xml)
{
    $xml = html_only_entity_decode($xml);
    //!\ Assume UTF-8
    $dom = new DOMDocument();
    $dom->recover = true;
    $dom->strictErrorChecking = false;
    $dom->loadXML($xml);
    $dom->encoding = 'UTF-8';
    $opml = simplexml_import_dom($dom);
    if (!$opml) {
        throw new FreshRSS_Opml_Exception();
    }
    $catDAO = new FreshRSS_CategoryDAO();
    $catDAO->checkDefault();
    $defCat = $catDAO->getDefault();
    $categories = array();
    $feeds = array();
    foreach ($opml->body->outline as $outline) {
        if (!isset($outline['xmlUrl'])) {
            // Catégorie
            $title = '';
            if (isset($outline['text'])) {
                $title = (string) $outline['text'];
            } elseif (isset($outline['title'])) {
                $title = (string) $outline['title'];
            }
            if ($title) {
                // Permet d'éviter les soucis au niveau des id :
                // ceux-ci sont générés en fonction de la date,
                // un flux pourrait être dans une catégorie X avec l'id Y
                // alors qu'il existe déjà la catégorie X mais avec l'id Z
                // Y ne sera pas ajouté et le flux non plus vu que l'id
                // de sa catégorie n'exisera pas
                $title = htmlspecialchars($title, ENT_COMPAT, 'UTF-8');
                $catDAO = new FreshRSS_CategoryDAO();
                $cat = $catDAO->searchByName($title);
                if ($cat === false) {
                    $cat = new FreshRSS_Category($title);
                    $values = array('name' => $cat->name());
                    $cat->_id($catDAO->addCategory($values));
                }
                $feeds = array_merge($feeds, getFeedsOutline($outline, $cat->id()));
            }
        } else {
            // Flux rss sans catégorie, on récupère l'ajoute dans la catégorie par défaut
            $feeds[] = getFeed($outline, $defCat->id());
        }
    }
    return array($categories, $feeds);
}
Beispiel #4
0
 public function changeCategory($idOldCat, $idNewCat)
 {
     $catDAO = new FreshRSS_CategoryDAO();
     $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;
     }
 }
 /**
  * This action deletes a category.
  * Feeds in the given category are moved in the default category.
  * Related user queries are deleted too.
  *
  * Request parameter is:
  *   - id (of a category)
  */
 public function deleteAction()
 {
     $feedDAO = FreshRSS_Factory::createFeedDao();
     $catDAO = new FreshRSS_CategoryDAO();
     $default_category = $catDAO->getDefault();
     $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);
         }
         if ($id === $default_category->id()) {
             Minz_Request::bad(_t('feedback.sub.category.not_delete_default'), $url_redirect);
         }
         if ($feedDAO->changeCategory($id, $default_category->id()) === false) {
             Minz_Request::bad(_t('feedback.sub.category.error'), $url_redirect);
         }
         if ($catDAO->deleteCategory($id) === false) {
             Minz_Request::bad(_t('feedback.sub.category.error'), $url_redirect);
         }
         // Remove related queries.
         FreshRSS_Context::$user_conf->queries = remove_query_by_get('c_' . $id, FreshRSS_Context::$user_conf->queries);
         FreshRSS_Context::$user_conf->save();
         Minz_Request::good(_t('feedback.sub.category.deleted'), $url_redirect);
     }
     Minz_Request::forward($url_redirect, 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'] = _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') . ' · ');
 }
Beispiel #7
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;
}
Beispiel #8
0
 /**
  * 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()) {
         Minz_Request::forward(array('c' => 'subscription'), true);
     }
     $feed_id = Minz_Request::param('f_id');
     $cat_id = Minz_Request::param('c_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();
     }
     $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);
     }
 }
 /**
  * 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);
 }
 public function importExportAction()
 {
     require_once LIB_PATH . '/lib_opml.php';
     $catDAO = new FreshRSS_CategoryDAO();
     $this->view->categories = $catDAO->listCategories();
     $this->view->req = Minz_Request::param('q');
     if ($this->view->req == 'export') {
         Minz_View::_title('freshrss_feeds.opml');
         $this->view->_useLayout(false);
         header('Content-Type: application/xml; charset=utf-8');
         header('Content-disposition: attachment; filename=freshrss_feeds.opml');
         $feedDAO = new FreshRSS_FeedDAO();
         $catDAO = new FreshRSS_CategoryDAO();
         $list = array();
         foreach ($catDAO->listCategories() as $key => $cat) {
             $list[$key]['name'] = $cat->name();
             $list[$key]['feeds'] = $feedDAO->listByCategory($cat->id());
         }
         $this->view->categories = $list;
     } elseif ($this->view->req == 'import' && Minz_Request::isPost()) {
         if ($_FILES['file']['error'] == 0) {
             invalidateHttpCache();
             // on parse le fichier OPML pour récupérer les catégories et les flux associés
             try {
                 list($categories, $feeds) = opml_import(file_get_contents($_FILES['file']['tmp_name']));
                 // On redirige vers le controller feed qui va se charger d'insérer les flux en BDD
                 // les flux sont mis au préalable dans des variables de Request
                 Minz_Request::_param('q', 'null');
                 Minz_Request::_param('categories', $categories);
                 Minz_Request::_param('feeds', $feeds);
                 Minz_Request::forward(array('c' => 'feed', 'a' => 'massiveImport'));
             } catch (FreshRSS_Opml_Exception $e) {
                 Minz_Log::record($e->getMessage(), Minz_Log::WARNING);
                 $notif = array('type' => 'bad', 'content' => Minz_Translate::t('bad_opml_file'));
                 Minz_Session::_param('notification', $notif);
                 Minz_Request::forward(array('c' => 'configure', 'a' => 'importExport'), true);
             }
         }
     }
     $feedDAO = new FreshRSS_FeedDAO();
     $this->view->feeds = $feedDAO->listFeeds();
     // au niveau de la vue, permet de ne pas voir un flux sélectionné dans la liste
     $this->view->flux = false;
     Minz_View::prependTitle(Minz_Translate::t('import_export_opml') . ' · ');
 }
 public function nbUnreadsPerFeedAction()
 {
     header('Content-Type: application/json; charset=UTF-8');
     $catDAO = new FreshRSS_CategoryDAO();
     $this->view->categories = $catDAO->listCategories(true, false);
 }
Beispiel #12
0
 /**
  * This action updates the Context object by using request parameters.
  *
  * Parameters are:
  *   - state (default: conf->default_view)
  *   - search (default: empty string)
  *   - order (default: conf->sort_order)
  *   - nb (default: conf->posts_per_page)
  *   - next (default: empty string)
  */
 private function updateContext()
 {
     // Update number of read / unread variables.
     $entryDAO = FreshRSS_Factory::createEntryDao();
     FreshRSS_Context::$total_starred = $entryDAO->countUnreadReadFavorites();
     FreshRSS_Context::$total_unread = FreshRSS_CategoryDAO::CountUnreads(FreshRSS_Context::$categories, 1);
     FreshRSS_Context::_get(Minz_Request::param('get', 'a'));
     FreshRSS_Context::$state = Minz_Request::param('state', FreshRSS_Context::$user_conf->default_state);
     $state_forced_by_user = Minz_Request::param('state', false) !== false;
     if (FreshRSS_Context::$user_conf->default_view === 'adaptive' && FreshRSS_Context::$get_unread <= 0 && !FreshRSS_Context::isStateEnabled(FreshRSS_Entry::STATE_READ) && !$state_forced_by_user) {
         FreshRSS_Context::$state |= FreshRSS_Entry::STATE_READ;
     }
     FreshRSS_Context::$search = new FreshRSS_Search(Minz_Request::param('search', ''));
     FreshRSS_Context::$order = Minz_Request::param('order', FreshRSS_Context::$user_conf->sort_order);
     FreshRSS_Context::$number = Minz_Request::param('nb', FreshRSS_Context::$user_conf->posts_per_page);
     FreshRSS_Context::$first_id = Minz_Request::param('next', '');
 }
Beispiel #13
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.
             $feed = FreshRSS_CategoryDAO::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::$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 = new FreshRSS_CategoryDAO();
                 $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();
 }
Beispiel #14
0
 private function checkAndProcessType($getType, $getId)
 {
     switch ($getType) {
         case 'a':
             $this->view->currentName = Minz_Translate::t('your_rss_feeds');
             $this->nb_not_read_cat = $this->view->nb_not_read;
             $this->view->get_c = $getType;
             return true;
         case 's':
             $this->view->currentName = Minz_Translate::t('your_favorites');
             $this->nb_not_read_cat = $this->view->nb_favorites['unread'];
             $this->view->get_c = $getType;
             return true;
         case 'c':
             $cat = isset($this->view->cat_aside[$getId]) ? $this->view->cat_aside[$getId] : null;
             if ($cat === null) {
                 $catDAO = new FreshRSS_CategoryDAO();
                 $cat = $catDAO->searchById($getId);
             }
             if ($cat) {
                 $this->view->currentName = $cat->name();
                 $this->nb_not_read_cat = $cat->nbNotRead();
                 $this->view->get_c = $getId;
                 return true;
             } else {
                 return false;
             }
         case 'f':
             $feed = FreshRSS_CategoryDAO::findFeed($this->view->cat_aside, $getId);
             if (empty($feed)) {
                 $feedDAO = new FreshRSS_FeedDAO();
                 $feed = $feedDAO->searchById($getId);
             }
             if ($feed) {
                 $this->view->currentName = $feed->name();
                 $this->nb_not_read_cat = $feed->nbNotRead();
                 $this->view->get_f = $getId;
                 $this->view->get_c = $feed->category();
                 return true;
             } else {
                 return false;
             }
         default:
             return false;
     }
 }
Beispiel #15
0
 public function getFeedTree()
 {
     $include_empty = $this->param('include_empty', true);
     $tree = array('identifier' => 'id', 'label' => 'name', 'items' => array());
     $categoryDAO = new FreshRSS_CategoryDAO();
     $categories = $categoryDAO->listCategories(true, true);
     foreach ($categories as $cat) {
         $tree_cat = array('id' => 'CAT:' . $cat->id(), 'name' => $cat->name(), 'unread' => $cat->nbNotRead(), 'type' => 'category', 'bare_id' => $cat->id(), 'items' => array());
         foreach ($cat->feeds() as $feed) {
             $tree_cat['items'][] = array('id' => 'FEED:' . $feed->id(), 'name' => $feed->name(), 'unread' => $feed->nbNotRead(), 'type' => 'feed', 'error' => $feed->inError(), 'updated' => $feed->lastUpdate(), 'bare_id' => $feed->id());
         }
         if (count($tree_cat['items']) > 0 || $include_empty) {
             $tree['items'][] = $tree_cat;
         }
     }
     $this->good(array('categories' => $tree));
 }