Documentation

OpdsParser

Parser for OPDS navigation and acquisition feeds.

Tags
since
3.1.0

Table of Contents

Constants

REL_ACQUISITION  = 'acquisition'
OPDS acquisition link relation prefix.
REL_IMAGE  = 'opds-spec.org/image'
OPDS cover-image link relation.
TYPE_EPUB  = 'application/epub+zip'
MIME type marking the downloadable ePUB acquisition link.

Methods

acquisitionEntries()  : array{results: list, language: string, level: string, summary: string, epubUrl: string, coverUrl: ?string}>, next: ?string}
Parse an acquisition feed into book rows plus a pagination cursor.
findNavHref()  : string|null
Find the sub-feed href for a language or section, matched leniently.
navigationLinks()  : array<int, array{title: string, href: string, lang: string}>
Parse a navigation feed into its sub-feed links.
authors()  : array<int, string>
Collect author names from an entry's <author><name> children.
coverUrl()  : string|null
Resolve the best cover image, preferring full image over thumbnail.
directChildText()  : string
Read the trimmed text of an element's first direct child of a name.
feedNextHref()  : string|null
Find the feed-level pagination "next" link.
linkHref()  : string|null
Return the first acquisition/cover link href matching a predicate.
loadDocument()  : DOMDocument|null
Load OPDS XML into a DOM with the same hardening RssParser uses.
navHref()  : string|null
Return the href of the first navigation sub-feed link on an entry.
readingLevel()  : string
Extract the human-readable reading level from an entry's categories.
summary()  : string
Extract the entry summary, preferring <summary> over <content>.

Constants

REL_ACQUISITION

OPDS acquisition link relation prefix.

private mixed REL_ACQUISITION = 'acquisition'

GDL uses the "open-access" sub-rel; matching on the substring keeps us tolerant of the related "acquisition" and "acquisition/open-access" spellings different OPDS producers emit.

REL_IMAGE

OPDS cover-image link relation.

private mixed REL_IMAGE = 'opds-spec.org/image'

TYPE_EPUB

MIME type marking the downloadable ePUB acquisition link.

private mixed TYPE_EPUB = 'application/epub+zip'

Methods

acquisitionEntries()

Parse an acquisition feed into book rows plus a pagination cursor.

public acquisitionEntries(string $xml) : array{results: list, language: string, level: string, summary: string, epubUrl: string, coverUrl: ?string}>, next: ?string}

Entries without a downloadable ePUB link are skipped, so calling this on a navigation feed (or an empty/malformed document) safely yields an empty result set rather than throwing.

Parameters
$xml : string

Raw OPDS feed XML

Return values
array{results: list, language: string, level: string, summary: string, epubUrl: string, coverUrl: ?string}>, next: ?string}

findNavHref()

Find the sub-feed href for a language or section, matched leniently.

public findNavHref(string $xml, string $needle) : string|null

Tries an exact (case-insensitive) language-code match first, then falls back to a title substring match — so both "en" and "English", or "3" and "Level 3", resolve to the right sub-feed.

Parameters
$xml : string

Raw OPDS navigation feed XML

$needle : string

Language code or section label to look for

Return values
string|null

Matching href, or null if none found

Parse a navigation feed into its sub-feed links.

public navigationLinks(string $xml) : array<int, array{title: string, href: string, lang: string}>
Parameters
$xml : string

Raw OPDS navigation feed XML

Return values
array<int, array{title: string, href: string, lang: string}>

authors()

Collect author names from an entry's <author><name> children.

private authors(DOMElement $entry) : array<int, string>
Parameters
$entry : DOMElement

Acquisition entry node

Return values
array<int, string>

coverUrl()

Resolve the best cover image, preferring full image over thumbnail.

private coverUrl(DOMElement $entry) : string|null
Parameters
$entry : DOMElement

Acquisition entry node

Return values
string|null

Cover URL, or null when no image link is present

directChildText()

Read the trimmed text of an element's first direct child of a name.

private directChildText(DOMElement $el, string $local) : string

Uses local-name matching (namespace-agnostic) and looks only at direct children, so a nested never leaks into a <title> read.

Parameters
$el : DOMElement

Parent element

$local : string

Local element name to look for

Return values
string

Trimmed text, or '' when the child is absent

feedNextHref()

Find the feed-level pagination "next" link.

private feedNextHref(DOMDocument $doc) : string|null

Only direct children of the root are inspected so that an entry-level link with rel="next" cannot be mistaken for the cursor.

Parameters
$doc : DOMDocument

Parsed feed document

Return values
string|null

Next-page URL, or null when this is the last page

linkHref()

Return the first acquisition/cover link href matching a predicate.

private linkHref(DOMElement $entry, callable(DOMElement): bool $match) : string|null
Parameters
$entry : DOMElement

Entry node

$match : callable(DOMElement): bool

Predicate over each link

Return values
string|null

Matching href, or null if none matched

loadDocument()

Load OPDS XML into a DOM with the same hardening RssParser uses.

private loadDocument(string $xml) : DOMDocument|null

LIBXML_NONET blocks libxml's external-entity (XXE/SSRF) fetches and we deliberately omit LIBXML_NOENT to keep billion-laughs expansion off.

Parameters
$xml : string

Raw feed XML

Return values
DOMDocument|null

Parsed document, or null on malformed input

navHref()

Return the href of the first navigation sub-feed link on an entry.

private navHref(DOMElement $entry, string &$lang) : string|null

Cover-image links are skipped; the language code (if advertised via hreflang) is returned through $lang by reference.

Parameters
$entry : DOMElement

Navigation entry node

$lang : string

Out-param: hreflang of the matched link

Return values
string|null

Sub-feed href, or null if the entry has no nav link

readingLevel()

Extract the human-readable reading level from an entry's categories.

private readingLevel(DOMElement $entry) : string

GDL tags books with a whose label reads "Level N", "Read aloud", or "Decodable"; other (genre) categories are ignored.

Parameters
$entry : DOMElement

Acquisition entry node

Return values
string

Reading-level label, or '' when none is present

summary()

Extract the entry summary, preferring <summary> over <content>.

private summary(DOMElement $entry) : string
Parameters
$entry : DOMElement

Acquisition entry node

Return values
string

        
On this page

Search results