Add subjects OPDS feeds, and switch to a more object-oriented approach to generating the OPDS feeds

This commit is contained in:
Alex Cabal 2020-06-25 12:56:14 -05:00
parent a42de8ef4d
commit 133f93cdce
11 changed files with 187 additions and 51 deletions

View file

@ -8,18 +8,16 @@ class OpdsFeed{
public $Id;
public $Url;
public $Title;
public $Ebooks = [];
public $IsCrawlable;
public $ParentUrl;
public function __construct(string $url, string $title, array $ebooks, bool $isCrawlable = false){
public function __construct(string $url, string $title, ?string $parentUrl){
$this->Url = $url;
$this->Id = $url;
$this->Id = SITE_URL . $url;
$this->Title = $title;
$this->Ebooks = $ebooks;
$this->IsCrawlable = $isCrawlable;
$this->ParentUrl = $parentUrl;
}
private function Sha1Entries(string $xmlString): string{
protected function Sha1Entries(string $xmlString): string{
try{
$xml = new SimpleXMLElement(str_replace('xmlns=', 'ns=', $xmlString));
$xml->registerXPathNamespace('dc', 'http://purl.org/dc/elements/1.1/');
@ -28,6 +26,13 @@ class OpdsFeed{
$output = '';
foreach($entries as $entry){
// Remove any <updated> elements, we don't want to compare against those.
// This makes it easier to for example generate a new subjects index,
// while updating it at the same time.
foreach($xml->xpath('/feed/entry/updated') as $element){
unset($element[0]);
}
$output .= $entry->asXml();
}
@ -39,31 +44,25 @@ class OpdsFeed{
}
}
public function Save(string $filename): void{
$updatedTimestamp = gmdate('Y-m-d\TH:i:s\Z');
$feed = Template::OpdsFeed(['id' => $this->Url, 'url' => $this->Url, 'title' => $this->Title, 'updatedTimestamp' => $updatedTimestamp, 'isCrawlable' => $this->IsCrawlable, 'entries' => $this->Ebooks]);
protected function SaveIfChanged(string $path, string $feed, string $updatedTimestamp): void{
$tempFilename = tempnam('/tmp/', 'se-opds-');
file_put_contents($tempFilename, $feed);
exec('se clean ' . escapeshellarg($tempFilename));
// Did we actually update the feed? If so, write to file and update the index
if(!is_file($filename)){
// File doesn't exist, write it out
rename($tempFilename, $filename);
}
elseif($this->Sha1Entries($feed) != $this->Sha1Entries(file_get_contents($filename))){
// Files don't match, save the file and update the index feed with the last updated timestamp
$xml = new SimpleXMLElement(str_replace('xmlns=', 'ns=', file_get_contents(WEB_ROOT . '/opds/index.xml')));
$xml->registerXPathNamespace('dc', 'http://purl.org/dc/elements/1.1/');
$xml->registerXPathNamespace('schema', 'http://schema.org/');
if(!is_file($path) || ($this->Sha1Entries($feed) != $this->Sha1Entries(file_get_contents($path)))){
// Files don't match, save the file and update the parent navigation feed with the last updated timestamp
$parentFilepath = WEB_ROOT . str_replace(SITE_URL, '', $this->ParentUrl);
if(!is_file($parentFilepath)){
$parentFilepath .= '/index.xml';
}
$xml = new SimpleXMLElement(str_replace('xmlns=', 'ns=', file_get_contents($parentFilepath)));
$feedEntry = ($xml->xpath('/feed/entry[id="' . $this->Id . '"]/updated') ?? [])[0];
$feedEntry[0] = $updatedTimestamp;
file_put_contents(WEB_ROOT . '/opds/index.xml', str_replace(" ns=", " xmlns=", $xml->asXml() ?? ''));
file_put_contents($parentFilepath, str_replace(" ns=", " xmlns=", $xml->asXml() ?? ''));
rename($tempFilename, $filename);
rename($tempFilename, $path);
}
}
}