diff options
Diffstat (limited to 'classes/feeds.php')
-rwxr-xr-x | classes/feeds.php | 393 |
1 files changed, 192 insertions, 201 deletions
diff --git a/classes/feeds.php b/classes/feeds.php index b1b19500f..68d535481 100755 --- a/classes/feeds.php +++ b/classes/feeds.php @@ -200,17 +200,21 @@ class Feeds extends Handler_Protected { $feed_id = $line["feed_id"]; - $label_cache = $line["label_cache"]; - $labels = false; - - if ($label_cache) { - $label_cache = json_decode($label_cache, true); + if ($line["num_labels"] > 0) { + $label_cache = $line["label_cache"]; + $labels = false; if ($label_cache) { - if ($label_cache["no-labels"] ?? false == 1) - $labels = []; - else - $labels = $label_cache; + $label_cache = json_decode($label_cache, true); + + if ($label_cache) { + if ($label_cache["no-labels"] ?? 0 == 1) + $labels = []; + else + $labels = $label_cache; + } + } else { + $labels = Article::_get_labels($id); } $line["labels"] = $labels; @@ -218,10 +222,6 @@ class Feeds extends Handler_Protected { $line["labels"] = []; } - /*if (!is_array($labels)) $labels = Article::_get_labels($id); - - $line["labels"] = Article::_get_labels($id);*/ - if (count($topmost_article_ids) < 3) { array_push($topmost_article_ids, $id); } @@ -251,21 +251,6 @@ class Feeds extends Handler_Protected { $this->_mark_timestamp(" sanitize"); - PluginHost::getInstance()->chain_hooks_callback(PluginHost::HOOK_RENDER_ARTICLE_CDM, - function ($result, $plugin) use (&$line) { - $line = $result; - $this->_mark_timestamp(" hook_render_cdm: " . get_class($plugin)); - }, - $line); - - $this->_mark_timestamp(" hook_render_cdm"); - - $line['content'] = DiskCache::rewrite_urls($line['content']); - - $this->_mark_timestamp(" disk_cache_rewrite"); - - $this->_mark_timestamp(" note"); - if (!get_pref(Prefs::CDM_EXPANDED)) { $line["cdm_excerpt"] = "<span class='collapse'> <i class='material-icons' onclick='return Article.cdmUnsetActive(event)' @@ -330,6 +315,20 @@ class Feeds extends Handler_Protected { } $this->_mark_timestamp(" color"); + $this->_mark_timestamp(" pre-hook_render_cdm"); + + PluginHost::getInstance()->chain_hooks_callback(PluginHost::HOOK_RENDER_ARTICLE_CDM, + function ($result, $plugin) use (&$line) { + $line = $result; + $this->_mark_timestamp(" hook: " . get_class($plugin)); + }, + $line); + + $this->_mark_timestamp(" hook_render_cdm"); + + $line['content'] = DiskCache::rewrite_urls($line['content']); + + $this->_mark_timestamp(" disk_cache_rewrite"); /* we don't need those */ @@ -474,8 +473,9 @@ class Feeds extends Handler_Protected { /* bump login timestamp if needed */ if (time() - $_SESSION["last_login_update"] > 3600) { - $sth = $this->pdo->prepare("UPDATE ttrss_users SET last_login = NOW() WHERE id = ?"); - $sth->execute([$_SESSION['uid']]); + $user = ORM::for_table('ttrss_users')->find_one($_SESSION["uid"]); + $user->last_login = Db::NOW(); + $user->save(); $_SESSION["last_login_update"] = time(); } @@ -963,7 +963,7 @@ class Feeds extends Handler_Protected { function add() { $feed = clean($_REQUEST['feed']); - $cat = clean($_REQUEST['cat']); + $cat = clean($_REQUEST['cat'] ?? ''); $need_auth = isset($_REQUEST['need_auth']); $login = $need_auth ? clean($_REQUEST['login']) : ''; $pass = $need_auth ? clean($_REQUEST['pass']) : ''; @@ -985,21 +985,18 @@ class Feeds extends Handler_Protected { * to get all possible feeds. * 5 - Couldn't download the URL content. * 6 - Content is an invalid XML. + * 7 - Error while creating feed database entry. */ static function _subscribe($url, $cat_id = 0, - $auth_login = '', $auth_pass = '') { - - global $fetch_last_error; - global $fetch_last_error_content; - global $fetch_last_content_type; + $auth_login = '', $auth_pass = '') : array { $pdo = Db::pdo(); $url = UrlHelper::validate($url); - if (!$url) return array("code" => 2); + if (!$url) return ["code" => 2]; - $contents = @UrlHelper::fetch($url, false, $auth_login, $auth_pass); + $contents = UrlHelper::fetch($url, false, $auth_login, $auth_pass); PluginHost::getInstance()->chain_hooks_callback(PluginHost::HOOK_SUBSCRIBE_FEED, function ($result) use (&$contents) { @@ -1008,14 +1005,14 @@ class Feeds extends Handler_Protected { $contents, $url, $auth_login, $auth_pass); if (empty($contents)) { - if (preg_match("/cloudflare\.com/", $fetch_last_error_content)) { - $fetch_last_error .= " (feed behind Cloudflare)"; + if (preg_match("/cloudflare\.com/", UrlHelper::$fetch_last_error_content)) { + UrlHelper::$fetch_last_error .= " (feed behind Cloudflare)"; } - return array("code" => 5, "message" => $fetch_last_error); + return array("code" => 5, "message" => UrlHelper::$fetch_last_error); } - if (mb_strpos($fetch_last_content_type, "html") !== false && self::_is_html($contents)) { + if (mb_strpos(UrlHelper::$fetch_last_content_type, "html") !== false && self::_is_html($contents)) { $feedUrls = self::_get_feeds_from_html($url, $contents); if (count($feedUrls) == 0) { @@ -1027,35 +1024,33 @@ class Feeds extends Handler_Protected { $url = key($feedUrls); } - if (!$cat_id) $cat_id = null; + $feed = ORM::for_table('ttrss_feeds') + ->where('feed_url', $url) + ->where('owner_uid', $_SESSION['uid']) + ->find_one(); - $sth = $pdo->prepare("SELECT id FROM ttrss_feeds - WHERE feed_url = ? AND owner_uid = ?"); - $sth->execute([$url, $_SESSION['uid']]); - - if ($row = $sth->fetch()) { - return array("code" => 0, "feed_id" => (int) $row["id"]); + if ($feed) { + return ["code" => 0, "feed_id" => $feed->id]; } else { - $sth = $pdo->prepare( - "INSERT INTO ttrss_feeds - (owner_uid,feed_url,title,cat_id, auth_login,auth_pass,update_method,auth_pass_encrypted) - VALUES (?, ?, ?, ?, ?, ?, 0, false)"); - - $sth->execute([$_SESSION['uid'], $url, "[Unknown]", $cat_id, (string)$auth_login, (string)$auth_pass]); - - $sth = $pdo->prepare("SELECT id FROM ttrss_feeds WHERE feed_url = ? - AND owner_uid = ?"); - $sth->execute([$url, $_SESSION['uid']]); - $row = $sth->fetch(); - - $feed_id = $row["id"]; - - if ($feed_id) { - RSSUtils::set_basic_feed_info($feed_id); + $feed = ORM::for_table('ttrss_feeds')->create(); + + $feed->set([ + 'owner_uid' => $_SESSION['uid'], + 'feed_url' => $url, + 'title' => "[Unknown]", + 'cat_id' => $cat_id ? $cat_id : null, + 'auth_login' => (string)$auth_login, + 'auth_pass' => (string)$auth_pass, + 'update_method' => 0, + 'auth_pass_encrypted' => false, + ]); + + if ($feed->save()) { + RSSUtils::update_basic_info($feed->id); + return ["code" => 1, "feed_id" => (int) $feed->id]; } - return array("code" => 1, "feed_id" => (int) $feed_id); - + return ["code" => 7]; } } @@ -1097,19 +1092,20 @@ class Feeds extends Handler_Protected { return false; } - static function _find_by_url($feed_url, $owner_uid) { - $sth = Db::pdo()->prepare("SELECT id FROM ttrss_feeds WHERE - feed_url = ? AND owner_uid = ?"); - $sth->execute([$feed_url, $owner_uid]); + static function _find_by_url(string $feed_url, int $owner_uid) { + $feed = ORM::for_table('ttrss_feeds') + ->where('owner_uid', $owner_uid) + ->where('feed_url', $feed_url) + ->find_one(); - if ($row = $sth->fetch()) { - return $row["id"]; + if ($feed) { + return $feed->id; + } else { + return false; } - - return false; } - static function _get_title($id, $cat = false) { + static function _get_title($id, bool $cat = false) { $pdo = Db::pdo(); if ($cat) { @@ -1156,7 +1152,7 @@ class Feeds extends Handler_Protected { } // only real cats - static function _get_cat_marked($cat, $owner_uid = false) { + static function _get_cat_marked(int $cat, int $owner_uid = 0) { if (!$owner_uid) $owner_uid = $_SESSION["uid"]; @@ -1179,7 +1175,7 @@ class Feeds extends Handler_Protected { } } - static function _get_cat_unread($cat, $owner_uid = false) { + static function _get_cat_unread(int $cat, int $owner_uid = 0) { if (!$owner_uid) $owner_uid = $_SESSION["uid"]; @@ -1213,7 +1209,7 @@ class Feeds extends Handler_Protected { } // only accepts real cats (>= 0) - static function _get_cat_children_unread($cat, $owner_uid = false) { + static function _get_cat_children_unread(int $cat, int $owner_uid = 0) { if (!$owner_uid) $owner_uid = $_SESSION["uid"]; $pdo = Db::pdo(); @@ -1232,7 +1228,7 @@ class Feeds extends Handler_Protected { return $unread; } - static function _get_global_unread($user_id = false) { + static function _get_global_unread(int $user_id = 0) { if (!$user_id) $user_id = $_SESSION["uid"]; @@ -1248,29 +1244,27 @@ class Feeds extends Handler_Protected { return $row["count"]; } - static function _get_cat_title($cat_id) { - - if ($cat_id == -1) { - return __("Special"); - } else if ($cat_id == -2) { - return __("Labels"); - } else { - - $pdo = Db::pdo(); - - $sth = $pdo->prepare("SELECT title FROM ttrss_feed_categories WHERE - id = ?"); - $sth->execute([$cat_id]); - - if ($row = $sth->fetch()) { - return $row["title"]; - } else { + static function _get_cat_title(int $cat_id) { + switch ($cat_id) { + case 0: return __("Uncategorized"); - } + case -1: + return __("Special"); + case -2: + return __("Labels"); + default: + $cat = ORM::for_table('ttrss_feed_categories') + ->find_one($cat_id); + + if ($cat) { + return $cat->title; + } else { + return "UNKNOWN"; + } } } - private static function _get_label_unread($label_id, $owner_uid = false) { + private static function _get_label_unread($label_id, int $owner_uid = 0) { if (!$owner_uid) $owner_uid = $_SESSION["uid"]; $pdo = Db::pdo(); @@ -1574,6 +1568,12 @@ class Feeds extends Handler_Protected { $first_id = 0; + if (Config::get(Config::DB_TYPE) == "pgsql") { + $yyiw_qpart = "to_char(date_entered, 'IYYY-IW') AS yyiw"; + } else { + $yyiw_qpart = "date_format(date_entered, '%Y-%u') AS yyiw"; + } + if (is_numeric($feed)) { // proper override_order applied above if ($vfeed_query_part && !$ignore_vfeed_group && get_pref(Prefs::VFEED_GROUP_BY_FEED, $owner_uid)) { @@ -1611,18 +1611,16 @@ class Feeds extends Handler_Protected { if (Config::get(Config::DB_TYPE) == "pgsql") { $sanity_interval_qpart = "date_entered >= NOW() - INTERVAL '1 hour' AND"; - $yyiw_qpart = "to_char(date_entered, 'IYYY-IW') AS yyiw"; $distinct_columns = str_replace("desc", "", strtolower($order_by)); $distinct_qpart = "DISTINCT ON (id, $distinct_columns)"; } else { $sanity_interval_qpart = "date_entered >= DATE_SUB(NOW(), INTERVAL 1 hour) AND"; - $yyiw_qpart = "date_format(date_entered, '%Y-%u') AS yyiw"; $distinct_qpart = "DISTINCT"; //fallback } // except for Labels category - if (get_pref(Prefs::HEADLINES_NO_DISTINCT) && !($feed == -2 && $cat_view)) { + if (get_pref(Prefs::HEADLINES_NO_DISTINCT, $owner_uid) && !($feed == -2 && $cat_view)) { $distinct_qpart = ""; } @@ -1691,6 +1689,7 @@ class Feeds extends Handler_Protected { $vfeed_query_part $content_query_part author,score, + (SELECT count(label_id) FROM ttrss_user_labels2 WHERE article_id = ttrss_entries.id) AS num_labels, (SELECT count(id) FROM ttrss_enclosures WHERE post_id = ttrss_entries.id) AS num_enclosures FROM $from_qpart @@ -1715,41 +1714,46 @@ class Feeds extends Handler_Protected { } else { // browsing by tag - if (Config::get(Config::DB_TYPE) == "pgsql") { - $distinct_columns = str_replace("desc", "", strtolower($order_by)); - $distinct_qpart = "DISTINCT ON (id, $distinct_columns)"; + if (get_pref(Prefs::HEADLINES_NO_DISTINCT, $owner_uid)) { + $distinct_qpart = ""; } else { - $distinct_qpart = "DISTINCT"; //fallback + if (Config::get(Config::DB_TYPE) == "pgsql") { + $distinct_columns = str_replace("desc", "", strtolower($order_by)); + $distinct_qpart = "DISTINCT ON (id, $distinct_columns)"; + } else { + $distinct_qpart = "DISTINCT"; //fallback + } } $query = "SELECT $distinct_qpart + ttrss_entries.id AS id, date_entered, + $yyiw_qpart, guid, - note, - ttrss_entries.id as id, - title, + ttrss_entries.title, updated, - unread, - feed_id, - marked, - published, + label_cache, + tag_cache, + always_display_enclosures, + site_url, + note, num_comments, comments, int_id, - tag_cache, - label_cache, - link, - lang, uuid, - last_read, - (SELECT hide_images FROM ttrss_feeds WHERE id = feed_id) AS hide_images, + lang, + hide_images, + unread,feed_id,marked,published,link,last_read, last_marked, last_published, $since_id_part $vfeed_query_part $content_query_part - author, score - FROM ttrss_entries, ttrss_user_entries, ttrss_tags + author, score, + (SELECT count(label_id) FROM ttrss_user_labels2 WHERE article_id = ttrss_entries.id) AS num_labels, + (SELECT count(id) FROM ttrss_enclosures WHERE post_id = ttrss_entries.id) AS num_enclosures + FROM ttrss_entries, ttrss_user_entries, ttrss_tags, ttrss_feeds WHERE + ttrss_feeds.id = ttrss_user_entries.feed_id AND ref_id = ttrss_entries.id AND ttrss_user_entries.owner_uid = ".$pdo->quote($owner_uid)." AND post_int_id = int_id AND @@ -1773,7 +1777,7 @@ class Feeds extends Handler_Protected { } - static function _get_parent_cats($cat, $owner_uid) { + static function _get_parent_cats(int $cat, int $owner_uid) { $rv = array(); $pdo = Db::pdo(); @@ -1790,7 +1794,7 @@ class Feeds extends Handler_Protected { return $rv; } - static function _get_child_cats($cat, $owner_uid) { + static function _get_child_cats(int $cat, int $owner_uid) { $rv = array(); $pdo = Db::pdo(); @@ -1835,19 +1839,15 @@ class Feeds extends Handler_Protected { return $rv; } - static function _cat_of_feed($feed) { - $pdo = Db::pdo(); - - $sth = $pdo->prepare("SELECT cat_id FROM ttrss_feeds - WHERE id = ?"); - $sth->execute([$feed]); + // returns Uncategorized as 0 + static function _cat_of(int $feed) : int { + $feed = ORM::for_table('ttrss_feeds')->find_one($feed); - if ($row = $sth->fetch()) { - return $row["cat_id"]; + if ($feed) { + return (int)$feed->cat_id; } else { - return false; + return -1; } - } private function _color_of($name) { @@ -1898,80 +1898,79 @@ class Feeds extends Handler_Protected { return preg_match("/<html|DOCTYPE html/i", substr($content, 0, 8192)) !== 0; } - static function _add_cat($feed_cat, $parent_cat_id = false, $order_id = 0) { + static function _remove_cat(int $id, int $owner_uid) { + $cat = ORM::for_table('ttrss_feed_categories') + ->where('owner_uid', $owner_uid) + ->find_one($id); - if (!$feed_cat) return false; - - $feed_cat = mb_substr($feed_cat, 0, 250); - if (!$parent_cat_id) $parent_cat_id = null; - - $pdo = Db::pdo(); - $tr_in_progress = false; - - try { - $pdo->beginTransaction(); - } catch (Exception $e) { - $tr_in_progress = true; - } + if ($cat) + $cat->delete(); + } - $sth = $pdo->prepare("SELECT id FROM ttrss_feed_categories - WHERE (parent_cat = :parent OR (:parent IS NULL AND parent_cat IS NULL)) - AND title = :title AND owner_uid = :uid"); - $sth->execute([':parent' => $parent_cat_id, ':title' => $feed_cat, ':uid' => $_SESSION['uid']]); + static function _add_cat(string $title, int $owner_uid, int $parent_cat = null, int $order_id = 0) { - if (!$sth->fetch()) { + $cat = ORM::for_table('ttrss_feed_categories') + ->where('owner_uid', $owner_uid) + ->where('parent_cat', $parent_cat) + ->where('title', $title) + ->find_one(); - $sth = $pdo->prepare("INSERT INTO ttrss_feed_categories (owner_uid,title,parent_cat,order_id) - VALUES (?, ?, ?, ?)"); - $sth->execute([$_SESSION['uid'], $feed_cat, $parent_cat_id, (int)$order_id]); + if (!$cat) { + $cat = ORM::for_table('ttrss_feed_categories')->create(); - if (!$tr_in_progress) $pdo->commit(); + $cat->set([ + 'owner_uid' => $owner_uid, + 'parent_cat' => $parent_cat, + 'order_id' => $order_id, + 'title' => $title, + ]); - return true; + return $cat->save(); } - $pdo->commit(); - return false; } - static function _get_access_key($feed_id, $is_cat, $owner_uid = false) { - - if (!$owner_uid) $owner_uid = $_SESSION["uid"]; + static function _clear_access_keys(int $owner_uid) { + $key = ORM::for_table('ttrss_access_keys') + ->where('owner_uid', $owner_uid) + ->delete_many(); + } - $is_cat = bool_to_sql_bool($is_cat); + static function _update_access_key(string $feed_id, bool $is_cat, int $owner_uid) { + $key = ORM::for_table('ttrss_access_keys') + ->where('owner_uid', $owner_uid) + ->where('feed_id', $feed_id) + ->where('is_cat', $is_cat) + ->delete_many(); - $pdo = Db::pdo(); + return self::_get_access_key($feed_id, $is_cat, $owner_uid); + } - $sth = $pdo->prepare("SELECT access_key FROM ttrss_access_keys - WHERE feed_id = ? AND is_cat = ? - AND owner_uid = ?"); - $sth->execute([$feed_id, $is_cat, $owner_uid]); + static function _get_access_key(string $feed_id, bool $is_cat, int $owner_uid) { + $key = ORM::for_table('ttrss_access_keys') + ->where('owner_uid', $owner_uid) + ->where('feed_id', $feed_id) + ->where('is_cat', $is_cat) + ->find_one(); - if ($row = $sth->fetch()) { - return $row["access_key"]; + if ($key) { + return $key->access_key; } else { - $key = uniqid_short(); - - $sth = $pdo->prepare("INSERT INTO ttrss_access_keys - (access_key, feed_id, is_cat, owner_uid) - VALUES (?, ?, ?, ?)"); + $key = ORM::for_table('ttrss_access_keys')->create(); - $sth->execute([$key, $feed_id, $is_cat, $owner_uid]); + $key->owner_uid = $owner_uid; + $key->feed_id = $feed_id; + $key->is_cat = $is_cat; + $key->access_key = uniqid_short(); - return $key; + if ($key->save()) { + return $key->access_key; + } } } - /** - * Purge a feed old posts. - * - * @param mixed $feed_id The id of the purged feed. - * @param mixed $purge_interval Olderness of purged posts. - * @access public - * @return mixed - */ - static function _purge($feed_id, $purge_interval) { + static function _purge(int $feed_id, int $purge_interval) { if (!$purge_interval) $purge_interval = self::_get_purge_interval($feed_id); @@ -2041,22 +2040,14 @@ class Feeds extends Handler_Protected { return $rows_deleted; } - private static function _get_purge_interval($feed_id) { - - $pdo = Db::pdo(); + private static function _get_purge_interval(int $feed_id) { + $feed = ORM::for_table('ttrss_feeds')->find_one($feed_id); - $sth = $pdo->prepare("SELECT purge_interval, owner_uid FROM ttrss_feeds - WHERE id = ?"); - $sth->execute([$feed_id]); - - if ($row = $sth->fetch()) { - $purge_interval = $row["purge_interval"]; - $owner_uid = $row["owner_uid"]; - - if ($purge_interval == 0) - $purge_interval = get_pref(Prefs::PURGE_OLD_DAYS, $owner_uid); - - return $purge_interval; + if ($feed) { + if ($feed->purge_interval != 0) + return $feed->purge_interval; + else + return get_pref(Prefs::PURGE_OLD_DAYS, $feed->owner_uid); } else { return -1; } |