From 088fcf8131a0d5b612362c2fecf337df6ef754bb Mon Sep 17 00:00:00 2001 From: Andrew Dolgov Date: Thu, 20 Jun 2019 08:40:02 +0300 Subject: move more globals to more appropriate places set libxml to always use internal errors --- classes/feeds.php | 254 +++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 251 insertions(+), 3 deletions(-) (limited to 'classes/feeds.php') diff --git a/classes/feeds.php b/classes/feeds.php index 75ca83957..c1f973830 100755 --- a/classes/feeds.php +++ b/classes/feeds.php @@ -860,7 +860,7 @@ class Feeds extends Handler_Protected { // fall back in case of no plugins if (!$search_qpart) { - list($search_qpart, $search_words) = search_to_sql($search[0], $search[1]); + list($search_qpart, $search_words) = Feeds::search_to_sql($search[0], $search[1]); } } else { $search_qpart = "true"; @@ -1456,7 +1456,7 @@ class Feeds extends Handler_Protected { // fall back in case of no plugins if (!$search_query_part) { - list($search_query_part, $search_words) = search_to_sql($search, $search_language); + list($search_query_part, $search_words) = Feeds::search_to_sql($search, $search_language); } if (DB_TYPE == "pgsql") { @@ -1927,7 +1927,6 @@ class Feeds extends Handler_Protected { $url = Feeds::fix_url($url); $baseUrl = substr($url, 0, strrpos($url, '/') + 1); - libxml_use_internal_errors(true); $feedUrls = []; $doc = new DOMDocument(); @@ -2070,5 +2069,254 @@ class Feeds extends Handler_Protected { return $key; } } + + /** + * Purge a feed old posts. + * + * @param mixed $link A database connection. + * @param mixed $feed_id The id of the purged feed. + * @param mixed $purge_interval Olderness of purged posts. + * @param boolean $debug Set to True to enable the debug. False by default. + * @access public + * @return void + */ + static function purge_feed($feed_id, $purge_interval) { + + if (!$purge_interval) $purge_interval = Feeds::feed_purge_interval($feed_id); + + $pdo = Db::pdo(); + + $sth = $pdo->prepare("SELECT owner_uid FROM ttrss_feeds WHERE id = ?"); + $sth->execute([$feed_id]); + + $owner_uid = false; + + if ($row = $sth->fetch()) { + $owner_uid = $row["owner_uid"]; + } + + if ($purge_interval == -1 || !$purge_interval) { + if ($owner_uid) { + CCache::update($feed_id, $owner_uid); + } + return; + } + + if (!$owner_uid) return; + + if (FORCE_ARTICLE_PURGE == 0) { + $purge_unread = get_pref("PURGE_UNREAD_ARTICLES", + $owner_uid, false); + } else { + $purge_unread = true; + $purge_interval = FORCE_ARTICLE_PURGE; + } + + if (!$purge_unread) + $query_limit = " unread = false AND "; + else + $query_limit = ""; + + $purge_interval = (int) $purge_interval; + + if (DB_TYPE == "pgsql") { + $sth = $pdo->prepare("DELETE FROM ttrss_user_entries + USING ttrss_entries + WHERE ttrss_entries.id = ref_id AND + marked = false AND + feed_id = ? AND + $query_limit + ttrss_entries.date_updated < NOW() - INTERVAL '$purge_interval days'"); + $sth->execute([$feed_id]); + + } else { + $sth = $pdo->prepare("DELETE FROM ttrss_user_entries + USING ttrss_user_entries, ttrss_entries + WHERE ttrss_entries.id = ref_id AND + marked = false AND + feed_id = ? AND + $query_limit + ttrss_entries.date_updated < DATE_SUB(NOW(), INTERVAL $purge_interval DAY)"); + $sth->execute([$feed_id]); + + } + + $rows = $sth->rowCount(); + + CCache::update($feed_id, $owner_uid); + + Debug::log("Purged feed $feed_id ($purge_interval): deleted $rows articles"); + + return $rows; + } + + static function feed_purge_interval($feed_id) { + + $pdo = DB::pdo(); + + $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( + 'PURGE_OLD_DAYS', $owner_uid); + + return $purge_interval; + + } else { + return -1; + } + } + + static function search_to_sql($search, $search_language) { + + $keywords = str_getcsv(trim($search), " "); + $query_keywords = array(); + $search_words = array(); + $search_query_leftover = array(); + + $pdo = Db::pdo(); + + if ($search_language) + $search_language = $pdo->quote(mb_strtolower($search_language)); + else + $search_language = $pdo->quote("english"); + + foreach ($keywords as $k) { + if (strpos($k, "-") === 0) { + $k = substr($k, 1); + $not = "NOT"; + } else { + $not = ""; + } + + $commandpair = explode(":", mb_strtolower($k), 2); + + switch ($commandpair[0]) { + case "title": + if ($commandpair[1]) { + array_push($query_keywords, "($not (LOWER(ttrss_entries.title) LIKE ". + $pdo->quote('%' . mb_strtolower($commandpair[1]) . '%') ."))"); + } else { + array_push($query_keywords, "(UPPER(ttrss_entries.title) $not LIKE UPPER('%$k%') + OR UPPER(ttrss_entries.content) $not LIKE UPPER(".$pdo->quote("%$k%")."))"); + array_push($search_words, $k); + } + break; + case "author": + if ($commandpair[1]) { + array_push($query_keywords, "($not (LOWER(author) LIKE ". + $pdo->quote('%' . mb_strtolower($commandpair[1]) . '%')."))"); + } else { + array_push($query_keywords, "(UPPER(ttrss_entries.title) $not LIKE UPPER('%$k%') + OR UPPER(ttrss_entries.content) $not LIKE UPPER(".$pdo->quote("%$k%")."))"); + array_push($search_words, $k); + } + break; + case "note": + if ($commandpair[1]) { + if ($commandpair[1] == "true") + array_push($query_keywords, "($not (note IS NOT NULL AND note != ''))"); + else if ($commandpair[1] == "false") + array_push($query_keywords, "($not (note IS NULL OR note = ''))"); + else + array_push($query_keywords, "($not (LOWER(note) LIKE ". + $pdo->quote('%' . mb_strtolower($commandpair[1]) . '%')."))"); + } else { + array_push($query_keywords, "(UPPER(ttrss_entries.title) $not LIKE UPPER(".$pdo->quote("%$k%").") + OR UPPER(ttrss_entries.content) $not LIKE UPPER(".$pdo->quote("%$k%")."))"); + if (!$not) array_push($search_words, $k); + } + break; + case "star": + + if ($commandpair[1]) { + if ($commandpair[1] == "true") + array_push($query_keywords, "($not (marked = true))"); + else + array_push($query_keywords, "($not (marked = false))"); + } else { + array_push($query_keywords, "(UPPER(ttrss_entries.title) $not LIKE UPPER(".$pdo->quote("%$k%").") + OR UPPER(ttrss_entries.content) $not LIKE UPPER(".$pdo->quote("%$k%")."))"); + if (!$not) array_push($search_words, $k); + } + break; + case "pub": + if ($commandpair[1]) { + if ($commandpair[1] == "true") + array_push($query_keywords, "($not (published = true))"); + else + array_push($query_keywords, "($not (published = false))"); + + } else { + array_push($query_keywords, "(UPPER(ttrss_entries.title) $not LIKE UPPER('%$k%') + OR UPPER(ttrss_entries.content) $not LIKE UPPER(".$pdo->quote("%$k%")."))"); + if (!$not) array_push($search_words, $k); + } + break; + case "unread": + if ($commandpair[1]) { + if ($commandpair[1] == "true") + array_push($query_keywords, "($not (unread = true))"); + else + array_push($query_keywords, "($not (unread = false))"); + + } else { + array_push($query_keywords, "(UPPER(ttrss_entries.title) $not LIKE UPPER(".$pdo->quote("%$k%").") + OR UPPER(ttrss_entries.content) $not LIKE UPPER(".$pdo->quote("%$k%")."))"); + if (!$not) array_push($search_words, $k); + } + break; + default: + if (strpos($k, "@") === 0) { + + $user_tz_string = get_pref('USER_TIMEZONE', $_SESSION['uid']); + $orig_ts = strtotime(substr($k, 1)); + $k = date("Y-m-d", convert_timestamp($orig_ts, $user_tz_string, 'UTC')); + + //$k = date("Y-m-d", strtotime(substr($k, 1))); + + array_push($query_keywords, "(".SUBSTRING_FOR_DATE."(updated,1,LENGTH('$k')) $not = '$k')"); + } else { + + if (DB_TYPE == "pgsql") { + $k = mb_strtolower($k); + array_push($search_query_leftover, $not ? "!$k" : $k); + } else { + array_push($query_keywords, "(UPPER(ttrss_entries.title) $not LIKE UPPER(".$pdo->quote("%$k%").") + OR UPPER(ttrss_entries.content) $not LIKE UPPER(".$pdo->quote("%$k%")."))"); + } + + if (!$not) array_push($search_words, $k); + } + } + } + + if (count($search_query_leftover) > 0) { + + if (DB_TYPE == "pgsql") { + + // if there's no joiners consider this a "simple" search and + // concatenate everything with &, otherwise don't try to mess with tsquery syntax + if (preg_match("/[&|]/", implode(" " , $search_query_leftover))) { + $tsquery = $pdo->quote(implode(" ", $search_query_leftover)); + } else { + $tsquery = $pdo->quote(implode(" & ", $search_query_leftover)); + } + + array_push($query_keywords, + "(tsvector_combined @@ to_tsquery($search_language, $tsquery))"); + } + + } + + $search_query_part = implode("AND", $query_keywords); + + return array($search_query_part, $search_words); + } } -- cgit v1.2.3