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(); }
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); }
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') . ' · '); }
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; }
/** * 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); }
/** * 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', ''); }
/** * 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(); }
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; } }
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)); }