From 5c92c8c7d6701c11c96a8a586784b9320b1a782e Mon Sep 17 00:00:00 2001 From: "Daniel J. Summers" Date: Tue, 9 Apr 2024 21:16:34 -0400 Subject: [PATCH] Retrieve feed, add to database (#4) --- src/lib/Data.php | 34 ++++++++++++++++++++++ src/lib/Feed.php | 69 +++++++++++++++++++++++++++++++++++++++++++++ src/public/feed.php | 1 + 3 files changed, 104 insertions(+) create mode 100644 src/lib/Feed.php diff --git a/src/lib/Data.php b/src/lib/Data.php index 2bd5e7a..e8e8b91 100644 --- a/src/lib/Data.php +++ b/src/lib/Data.php @@ -96,4 +96,38 @@ class Data { $query->bindValue(':password', password_hash($password, PASSWORD_DEFAULT)); $query->execute(); } + + /** + * Add an RSS feed + * @param string $url The URL for the RSS feed + * @param string $title The title of the RSS feed + * @param string $updatedOn The date/time the RSS feed was last updated (from the XML, not when we checked) + * @return int The ID of the added feed + */ + public static function addFeed(string $url, string $title, string $updatedOn): int { + $db = self::getConnection(); + if ($updatedOn) { + try { + $updated = (new DateTimeImmutable($updatedOn))->format(DateTimeInterface::ATOM); + } catch (Exception $ex) { + $updated = null; + } + } else { + $updated = null; + } + $query = $db->prepare('INSERT INTO feed (user_id, url, title, updated_on, checked_on)' + . ' VALUES (:user, :url, :title, :updated, :checked)'); + $query->bindValue(':user', $_REQUEST['FRC_USER_ID']); + $query->bindValue(':url', $url); + $query->bindValue(':title', $title); + $query->bindValue(':updated', $updated); + $query->bindValue(':checked', (new DateTimeImmutable())->format(DateTimeInterface::ATOM)); + $result = $query->execute(); + if ($result) { + $idQuery = $db->prepare('SELECT last_insert_rowid()'); + $idResult = $idQuery->execute(); + if ($idResult) return $idResult->fetchArray(SQLITE3_NUM)[0]; + } + return -1; + } } diff --git a/src/lib/Feed.php b/src/lib/Feed.php new file mode 100644 index 0000000..0a1cfd0 --- /dev/null +++ b/src/lib/Feed.php @@ -0,0 +1,69 @@ + feed ] if successful, [ 'error' => message] if not + */ + public static function parseFeed(string $content): array { + try { + return [ 'ok' => new SimpleXMLElement($content) ]; + } catch (Exception $ex) { + return [ 'error' => $ex->getMessage() ]; + } + } + + /** + * Retrieve the feed + * @param string $url + * @return array|SimpleXMLElement[]|string[] [ 'ok' => feedXml, 'url' => actualUrl ] if successful, [ 'error' => message ] if not + */ + public static function retrieveFeed(string $url): array { + $feedReq = curl_init($url); + curl_setopt($feedReq, CURLOPT_FOLLOWLOCATION, true); + curl_setopt($feedReq, CURLOPT_RETURNTRANSFER, true); + curl_setopt($feedReq, CURLOPT_CONNECTTIMEOUT, 5); + curl_setopt($feedReq, CURLOPT_TIMEOUT, 15); + + $feedContent = curl_exec($feedReq); + + $result = array(); + $error = curl_error($feedReq); + $code = curl_getinfo($feedReq, CURLINFO_RESPONSE_CODE); + if ($error) { + $result['error'] = $error; + } else if ($code == 200) { + $parsed = self::parseFeed($feedContent); + if (array_key_exists('error', $parsed)) { + $result['error'] = $parsed['error']; + } else { + $result['ok'] = $parsed['ok']; + $result['url'] = curl_getinfo($feedReq, CURLINFO_EFFECTIVE_URL); + } + } else { + $result['error'] = "HTTP Code $code: $feedContent"; + } + + curl_close($feedReq); + return $result; + } + + /** + * Add an RSS feed + * @param string $url The URL of the RSS feed to add + * @return array [ 'ok' => true ] if successful, [ 'error' => message ] if not + */ + public static function add(string $url): array { + $feed = self::retrieveFeed($url); + if (array_key_exists('error', $feed)) return $feed; + + $channel = $feed['ok']->channel; + $feedId = Data::addFeed($feed['url'], (string) $channel->title, (string) $channel->lastBuildDate); + + return [ 'ok' => true ]; + } +} diff --git a/src/public/feed.php b/src/public/feed.php index ef1d0f4..59b4014 100644 --- a/src/public/feed.php +++ b/src/public/feed.php @@ -11,6 +11,7 @@ Security::verifyUser(); if ($_SERVER['REQUEST_METHOD'] == 'POST') { // TODO: get feed, add if new, reject if existing but not owned by this user, update otherwise + $result = Feed::add($_POST['url']); $feed = [ 'id' => $_POST['id'], 'url' => $_POST['url'] ]; $title = 'TODO'; } else {