beta4 changes #26

Merged
danieljsummers merged 7 commits from beta5 into main 2024-08-06 23:20:17 +00:00
4 changed files with 78 additions and 84 deletions
Showing only changes of commit adcfd9d02a - Show all commits

12
src/composer.lock generated
View File

@ -8,11 +8,11 @@
"packages": [
{
"name": "bit-badger/inspired-by-fsharp",
"version": "v1.0.0-beta1",
"version": "v1.0.0-beta2",
"source": {
"type": "git",
"url": "https://git.bitbadger.solutions/bit-badger/inspired-by-fsharp",
"reference": "efb3a4461edcb23e0dd82068adeb0591240870b0"
"reference": "fad428a4e40b606987499b17bb2d5b7d4b04502d"
},
"require": {
"php": "^8.2"
@ -49,15 +49,15 @@
"rss": "https://git.bitbadger.solutions/bit-badger/inspired-by-fsharp.rss",
"source": "https://git.bitbadger.solutions/bit-badger/inspired-by-fsharp"
},
"time": "2024-07-28T21:35:11+00:00"
"time": "2024-07-29T17:58:33+00:00"
},
{
"name": "bit-badger/pdo-document",
"version": "v1.0.0-beta8",
"version": "v1.0.0-beta9",
"source": {
"type": "git",
"url": "https://git.bitbadger.solutions/bit-badger/pdo-document",
"reference": "039283224a173bd3e8a9bc5de0caf349ba7b58e6"
"reference": "9e0e663811d9dbbdb94a2c04ce8b874e91a7c85b"
},
"require": {
"bit-badger/inspired-by-fsharp": "^1",
@ -103,7 +103,7 @@
"rss": "https://git.bitbadger.solutions/bit-badger/pdo-document.rss",
"source": "https://git.bitbadger.solutions/bit-badger/pdo-document"
},
"time": "2024-07-29T00:08:44+00:00"
"time": "2024-07-29T20:57:51+00:00"
},
{
"name": "netresearch/jsonmapper",

View File

@ -175,34 +175,31 @@ class Feed
* @param int $feedId The ID of the feed to be refreshed
* @param string $url The URL of the feed to be refreshed
* @return Result<true, string> True if successful, an error message if not
* @throws DocumentException If any is encountered
*/
public static function refreshFeed(int $feedId, string $url): Result
{
$tryRetrieve = ParsedFeed::retrieve($url);
if ($tryRetrieve->isError()) return $tryRetrieve;
$feed = $tryRetrieve->getOK();
return ParsedFeed::retrieve($url)
->bind(function (ParsedFeed $feed) use ($feedId, $url) {
try {
$feedDoc = Find::byId(Table::Feed, $feedId, self::class);
if ($feedDoc->isNone()) return Result::Error('Could not derive date last checked for feed');
$lastChecked = date_create_immutable($feedDoc->get()->checked_on ?? WWW_EPOCH);
try {
$feedDoc = Find::byId(Table::Feed, $feedId, self::class);
if ($feedDoc->isNone()) return Result::Error('Could not derive date last checked for feed');
$lastChecked = date_create_immutable($feedDoc->get()->checked_on ?? WWW_EPOCH);
$itemUpdate = self::updateItems($feedId, $feed, $lastChecked);
if ($itemUpdate->isError()) return $itemUpdate;
$patch = [
'title' => $feed->title,
'updated_on' => $feed->updatedOn,
'checked_on' => Data::formatDate('now')
];
if ($url !== $feed->url) $patch['url'] = $feed->url;
Patch::byId(Table::Feed, $feedId, $patch);
} catch (DocumentException $ex) {
return Result::Error("$ex");
}
return PURGE_TYPE === self::PurgeNone ? Result::OK(true) : self::purgeItems($feedId);
return self::updateItems($feedId, $feed, $lastChecked)
->bind(function () use ($feed, $feedId, $url) {
$patch = [
'title' => $feed->title,
'updated_on' => $feed->updatedOn,
'checked_on' => Data::formatDate('now')
];
if ($url !== $feed->url) $patch['url'] = $feed->url;
Patch::byId(Table::Feed, $feedId, $patch);
})
->bind(fn() => PURGE_TYPE === self::PurgeNone ? Result::OK(true) : self::purgeItems($feedId));
} catch (DocumentException $ex) {
return Result::Error("$ex");
}
});
}
/**
@ -213,27 +210,25 @@ class Feed
*/
public static function add(string $url): Result
{
$tryRetrieve = ParsedFeed::retrieve($url);
if ($tryRetrieve->isError()) return $tryRetrieve;
$feed = $tryRetrieve->getOK();
return ParsedFeed::retrieve($url)
->bind(function (ParsedFeed $feed) {
try {
$fields = [Field::EQ('user_id', $_SESSION[Key::UserId]), Field::EQ('url', $feed->url)];
if (Exists::byFields(Table::Feed, $fields)) {
return Result::Error("Already subscribed to feed $feed->url");
}
try {
$fields = [Field::EQ('user_id', $_SESSION[Key::UserId]), Field::EQ('url', $feed->url)];
if (Exists::byFields(Table::Feed, $fields)) {
return Result::Error("Already subscribed to feed $feed->url");
}
Document::insert(Table::Feed, self::fromParsed($feed));
Document::insert(Table::Feed, self::fromParsed($feed));
$doc = Find::firstByFields(Table::Feed, $fields, self::class);
if ($doc->isNone()) return Result::Error('Could not retrieve inserted feed');
$tryDoc = Find::firstByFields(Table::Feed, $fields, self::class);
if ($tryDoc->isNone()) return Result::Error('Could not retrieve inserted feed');
$doc = $tryDoc->get();
$result = self::updateItems($doc->id, $feed, date_create_immutable(WWW_EPOCH));
return $result->isError() ? $result : Result::OK($doc->id);
} catch (DocumentException $ex) {
return Result::Error("$ex");
}
return self::updateItems($doc->get()->id, $feed, date_create_immutable(WWW_EPOCH))
->bind(fn() => Result::OK($doc->get()->id));
} catch (DocumentException $ex) {
return Result::Error("$ex");
}
});
}
/**

View File

@ -239,39 +239,38 @@ readonly class ParsedFeed
*/
public static function retrieve(string $url): Result
{
$tryDoc = self::retrieveDocument($url);
if ($tryDoc->isError()) return $tryDoc;
$doc = $tryDoc->getOK();
if ($doc['code'] !== 200) {
return Result::Error("Prospective feed URL $url returned HTTP Code {$doc['code']}: {$doc['content']}");
}
$start = strtolower(strlen($doc['content']) >= 9 ? substr($doc['content'], 0, 9) : $doc['content']);
if ($start === '<!doctype' || str_starts_with($start, '<html')) {
$derivedURL = self::deriveFeedFromHTML($doc['content']);
if ($derivedURL->isError()) return $derivedURL;
$feedURL = $derivedURL->getOK();
if (!str_starts_with($feedURL, 'http')) {
// Relative URL; feed should be retrieved in the context of the original URL
$original = parse_url($url);
$port = key_exists('port', $original) ? ":{$original['port']}" : '';
$feedURL = $original['scheme'] . '://' . $original['host'] . $port . $feedURL;
}
$tryDoc = self::retrieveDocument($feedURL);
if ($tryDoc->isError()) return $tryDoc;
$doc = $tryDoc->getOK();
if ($doc['code'] !== 200) {
return Result::Error("Derived feed URL $url returned HTTP Code {$doc['code']}: {$doc['content']}");
}
}
$tryParse = self::parseFeed($doc['content']);
if ($tryParse->isError()) return $tryParse;
$parsed = $tryParse->getOK();
$extract = $parsed->getElementsByTagNameNS(self::ATOM_NS, 'feed')->length > 0
? self::fromAtom(...) : self::fromRSS(...);
return $extract($parsed, $doc['url']);
$doc = self::retrieveDocument($url)
->bind(fn(array $doc) => match ($doc['code']) {
200 => Result::OK($doc),
default => Result::Error(
"Prospective feed URL $url returned HTTP Code {$doc['code']}: {$doc['content']}"),
})
->bind(function (array $doc) use ($url) {
$start = strtolower(strlen($doc['content']) >= 9 ? substr($doc['content'], 0, 9) : $doc['content']);
return $start === '<!doctype' || str_starts_with($start, '<html')
? self::deriveFeedFromHTML($doc['content'])
->bind(function (string $feedURL) use ($url) {
if (!str_starts_with($feedURL, 'http')) {
// Relative URL; feed should be retrieved in the context of the original URL
$original = parse_url($url);
$port = key_exists('port', $original) ? ":{$original['port']}" : '';
$feedURL = $original['scheme'] . '://' . $original['host'] . $port . $feedURL;
}
return self::retrieveDocument($feedURL);
})
->bind(fn($doc) => match ($doc['code']) {
200 => Result::OK($doc),
default => Result::Error(
"Derived feed URL {$doc['url']} returned HTTP Code {$doc['code']}: {$doc['content']}"),
})
: Result::OK($doc);
});
return $doc
->bind(fn($doc) => self::parseFeed($doc['content']))
->bind(function (DOMDocument $parsed) use ($doc) {
$extract = $parsed->getElementsByTagNameNS(self::ATOM_NS, 'feed')->length > 0
? self::fromAtom(...) : self::fromRSS(...);
return $extract($parsed, $doc['url']);
});
}
}

View File

@ -44,10 +44,10 @@ switch ($_SERVER['REQUEST_METHOD']) {
? Feed::update($toEdit->get(), $_POST['url'])
: Result::Error("Feed $feedId not found");
}
if ($result->isOK()) {
$result->iter(function () {
add_info('Feed saved successfully');
frc_redirect('/feeds');
}
});
add_error($result->getError());
$feedId = 'error';
} catch (DocumentException $ex) {