You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
257 lines
9.5 KiB
257 lines
9.5 KiB
6 years ago
|
<?php
|
||
|
/** @license MIT
|
||
|
* Copyright 2018 J. King et al.
|
||
|
* See LICENSE and AUTHORS files for details */
|
||
|
|
||
|
declare(strict_types=1);
|
||
4 years ago
|
namespace JKingWeb\Lax\Parser\XML\Primitives;
|
||
6 years ago
|
|
||
6 years ago
|
use JKingWeb\Lax\Person\Person;
|
||
|
use JKingWeb\Lax\Person\Collection as PersonCollection;
|
||
6 years ago
|
use JKingWeb\Lax\Category\Category;
|
||
|
use JKingWeb\Lax\Category\Collection as CategoryCollection;
|
||
4 years ago
|
use JKingWeb\Lax\Parser\XML\Entry as FeedEntry;
|
||
6 years ago
|
|
||
|
trait Construct {
|
||
6 years ago
|
/** Primitive to fetch an Atom feed/entry title
|
||
|
*
|
||
|
* This fetches the title in plain text rather than HTML, even if HTML is provided in the feed/entry
|
||
|
*/
|
||
|
protected function getTitleAtom() {
|
||
6 years ago
|
return $this->fetchTextAtom("atom:title");
|
||
6 years ago
|
}
|
||
|
|
||
|
/** Primitive to fetch an RSS feed/entry title */
|
||
|
protected function getTitleRss2() {
|
||
6 years ago
|
return $this->fetchText("title");
|
||
6 years ago
|
}
|
||
|
|
||
|
/** Primitive to fetch an RDF feed/entry title */
|
||
|
protected function getTitleRss1() {
|
||
6 years ago
|
return $this->fetchText("rss1:title|rss0:title");
|
||
6 years ago
|
}
|
||
|
|
||
|
/** Primitive to fetch a Dublin Core feed/entry title */
|
||
|
protected function getTitleDC() {
|
||
6 years ago
|
return $this->fetchText("dc:title");
|
||
6 years ago
|
}
|
||
|
|
||
|
/** Primitive to fetch an Apple podcast/episdoe title */
|
||
6 years ago
|
protected function getTitlePod() {
|
||
6 years ago
|
return $this->fetchText("apple:title");
|
||
6 years ago
|
}
|
||
|
|
||
|
/** Primitive to fetch an Atom feed/entry Web-representation URL */
|
||
|
protected function getLinkAtom() {
|
||
6 years ago
|
// FIXME: Atom link fetching should ideally prefer links to text/html resources or the like over e.g. other-format newsfeeds, generic XML, images, etc
|
||
6 years ago
|
$node = $this->fetchAtomRelations();
|
||
6 years ago
|
return $node->length ? $this->resolveNodeUrl($node->item(0), "href") : null;
|
||
6 years ago
|
}
|
||
|
|
||
|
/** Primitive to fetch an RSS feed/entry Web-representation URL */
|
||
|
protected function getLinkRss2() {
|
||
6 years ago
|
return $this->fetchUrl("link") ?? $this->fetchUrl("guid[not(@isPermalink='false')]");
|
||
6 years ago
|
}
|
||
|
|
||
|
/** Primitive to fetch an RDF feed/entry Web-representation URL */
|
||
|
protected function getLinkRss1() {
|
||
6 years ago
|
return $this->fetchUrl("rss1:link|rss0:link");
|
||
6 years ago
|
}
|
||
|
|
||
|
/** Primitive to fetch Atom feed/entry categories */
|
||
6 years ago
|
protected function getCategoriesAtom() {
|
||
|
$out = new CategoryCollection;
|
||
|
foreach ($this->fetchElements("atom:category[@term]") ?? [] as $node) {
|
||
|
$c = new Category;
|
||
|
$c->domain = $this->trimText($node->getAttribute("scheme"));
|
||
|
$c->label = $this->trimText($node->getAttribute("label"));
|
||
|
$c->name = $this->trimText($node->getAttribute("term"));
|
||
|
if (strlen($c->name)) {
|
||
|
$out[] = $c;
|
||
6 years ago
|
}
|
||
|
}
|
||
6 years ago
|
return count($out) ? $out : null;
|
||
6 years ago
|
}
|
||
|
|
||
|
/** Primitive to fetch RSS feed/entry categories */
|
||
6 years ago
|
protected function getCategoriesRss2() {
|
||
|
$out = new CategoryCollection;
|
||
|
foreach ($this->fetchElements("category") ?? [] as $node) {
|
||
|
$c = new Category;
|
||
|
$c->domain = $this->trimText($node->getAttribute("domain"));
|
||
|
$c->name = $this->trimText($node->textContent);
|
||
|
if (strlen($c->name)) {
|
||
|
$out[] = $c;
|
||
6 years ago
|
}
|
||
|
}
|
||
6 years ago
|
return count($out) ? $out : null;
|
||
6 years ago
|
}
|
||
|
|
||
|
/** Primitive to fetch Dublin Core feed/entry categories
|
||
|
*
|
||
|
* Dublin Core doesn't have an obvious category type, so we use 'subject' as a nearest approximation
|
||
|
*/
|
||
6 years ago
|
protected function getCategoriesDC() {
|
||
|
$out = new CategoryCollection;
|
||
|
foreach ($this->fetchTextMulti("dc:subject") ?? [] as $text) {
|
||
4 years ago
|
if (strlen($text)) {
|
||
6 years ago
|
$c = new Category;
|
||
|
$c->name = $text;
|
||
|
$out[] = $c;
|
||
|
}
|
||
6 years ago
|
}
|
||
6 years ago
|
return count($out) ? $out : null;
|
||
6 years ago
|
}
|
||
|
|
||
6 years ago
|
/** Primitive to fetch podcast/episode categories */
|
||
6 years ago
|
protected function getCategoriesPod() {
|
||
|
$out = new CategoryCollection;
|
||
|
foreach ($this->fetchElements("apple:category|gplay:category") ?? [] as $node) {
|
||
|
$c = new Category;
|
||
|
$c->name = $this->trimText($node->getAttribute("text"));
|
||
|
if (strlen($c->name)) {
|
||
|
$out[] = $c;
|
||
6 years ago
|
}
|
||
|
}
|
||
6 years ago
|
return count($out) ? $out : null;
|
||
6 years ago
|
}
|
||
6 years ago
|
|
||
|
/** Primitive to fetch an Atom feed/entry identifier */
|
||
|
protected function getIdAtom() {
|
||
6 years ago
|
return $this->fetchText("atom:id");
|
||
6 years ago
|
}
|
||
|
|
||
|
/** Primitive to fetch an RSS feed/entry identifier
|
||
|
*
|
||
|
* Using RSS' <guid> for feed identifiers is non-standard, but harmless
|
||
|
*/
|
||
|
protected function getIdRss2() {
|
||
6 years ago
|
return $this->fetchText("guid");
|
||
6 years ago
|
}
|
||
|
|
||
|
/** Primitive to fetch a Dublin Core feed/entry identifier */
|
||
|
protected function getIdDC() {
|
||
6 years ago
|
return $this->fetchText("dc:identifier");
|
||
6 years ago
|
}
|
||
6 years ago
|
|
||
6 years ago
|
/** Primitive to fetch a collection of authors associated with a feed/entry via Dublin Core */
|
||
|
protected function getAuthorsDC() {
|
||
|
return $this->fetchPeople("dc:creator", "author");
|
||
|
}
|
||
|
|
||
|
/** Primitive to fetch a collection of contributors associated with a feed/entry via Dublin Core */
|
||
|
protected function getContributorsDC() {
|
||
|
return $this->fetchPeople("dc:ccontributor", "contributor");
|
||
|
}
|
||
|
|
||
|
/** Primitive to fetch a collection of authors associated with an RSS feed/entry */
|
||
|
protected function getAuthorsRss2() {
|
||
|
return $this->fetchPeople("author", "author");
|
||
|
}
|
||
|
|
||
|
/** Primitive to fetch a collection of editors associated with an RSS feed/entry */
|
||
|
protected function getEditorsRss2() {
|
||
|
return $this->fetchPeople("managingEditor", "editor");
|
||
|
}
|
||
|
|
||
|
/** Primitive to fetch a collection of authors associated with an RSS feed/entry */
|
||
|
protected function getWebmastersRss2() {
|
||
|
return $this->fetchPeople("webMaster", "webMaster");
|
||
|
}
|
||
|
|
||
6 years ago
|
/** Primitive to fetch a collection of contributors associated with an Atom feed */
|
||
6 years ago
|
protected function getContributorsAtom() {
|
||
6 years ago
|
return $this->fetchPeopleAtom("atom:contributor", "contributor");
|
||
6 years ago
|
}
|
||
6 years ago
|
|
||
6 years ago
|
/** Primitive to fetch a collection of authors associated with a podcast/episode
|
||
6 years ago
|
*
|
||
|
* The collection only ever contains the first author found: podcasts implicitly have only one author
|
||
|
*/
|
||
6 years ago
|
protected function getAuthorsPod() {
|
||
6 years ago
|
$out = new PersonCollection;
|
||
|
$p = new Person;
|
||
6 years ago
|
$p->name = $this->fetchText("gplay:author|apple:author") ?? "";
|
||
|
$p->mail = $this->fetchText("gplay:email|apple:email") ?? "";
|
||
6 years ago
|
$p->role = "author";
|
||
6 years ago
|
if (strlen($p->name)) {
|
||
|
$out[] = $p;
|
||
|
}
|
||
|
return count($out) ? $out : null;
|
||
|
}
|
||
|
|
||
|
/** Primitive to fetch a collection of webmasters associated with a podcast
|
||
|
*
|
||
|
* The collection only ever contains the first webmaster found: podcasts implicitly have only one webmaster
|
||
|
*/
|
||
|
protected function getWebmastersPod() {
|
||
|
$out = new PersonCollection;
|
||
|
$node = $this->fetchElement("gplay:owner|apple:owner");
|
||
|
if ($node) {
|
||
|
$p = new Person;
|
||
|
$p->name = $this->fetchText("gplay:author|apple:author", $node) ?? "";
|
||
|
$p->mail = $this->fetchText("gplay:email|apple:email", $node) ?? "";
|
||
|
$p->role = "webmaster";
|
||
|
if (strlen($p->name)) {
|
||
|
$out[] = $p;
|
||
|
}
|
||
|
}
|
||
|
return count($out) ? $out : null;
|
||
6 years ago
|
}
|
||
6 years ago
|
|
||
|
/** Primitive to fetch an Atom feed or entry's canonical URL */
|
||
|
protected function getUrlAtom() {
|
||
|
$node = $this->fetchAtomRelations("self");
|
||
|
return $node->length ? $this->resolveNodeUrl($node->item(0), "href") : null;
|
||
|
}
|
||
6 years ago
|
|
||
|
/** Primitive to fetch the modification date of an Atom feed/entry */
|
||
|
protected function getDateModifiedAtom() {
|
||
6 years ago
|
return $this->fetchDate("atom:updated");
|
||
6 years ago
|
}
|
||
|
|
||
|
/** Primitive to fetch the modification date of an Atom feed/entry */
|
||
|
protected function getDateModifiedDC() {
|
||
6 years ago
|
return $this->fetchDate("dc:date");
|
||
6 years ago
|
}
|
||
6 years ago
|
|
||
|
/** Primitive to fetch the modification date of an Atom entry */
|
||
|
protected function getDateCreatedAtom() {
|
||
|
return $this->fetchDate("atom:published");
|
||
|
}
|
||
6 years ago
|
|
||
|
/** Primitive to fetch the list of entries in an Atom feed */
|
||
|
protected function getEntriesAtom() {
|
||
|
$out = [];
|
||
|
foreach ($this->fetchElements("atom:entry") ?? [] as $node) {
|
||
|
$out[] = new FeedEntry($node, $this, $this->xpath);
|
||
|
}
|
||
|
return count($out) ? $out : null;
|
||
|
}
|
||
|
|
||
|
/** Primitive to fetch the list of entries in an RDF feed */
|
||
|
protected function getEntriesRss1() {
|
||
|
$out = [];
|
||
6 years ago
|
foreach ($this->fetchElements("rss1:item", $this->subject->ownerDocument->documentElement) ?? $this->fetchElements("rss1:item") ?? $this->fetchElements("rss0:item", $this->subject->ownerDocument->documentElement) ?? $this->fetchElements("rss0:item") ?? [] as $node) {
|
||
6 years ago
|
$out[] = new FeedEntry($node, $this, $this->xpath);
|
||
|
}
|
||
|
return count($out) ? $out : null;
|
||
|
}
|
||
|
|
||
|
/** Primitive to fetch the list of entries in an RSS feed */
|
||
|
protected function getEntriesRss2() {
|
||
|
$out = [];
|
||
|
foreach ($this->fetchElements("item") ?? [] as $node) {
|
||
|
$out[] = new FeedEntry($node, $this, $this->xpath);
|
||
|
}
|
||
|
return count($out) ? $out : null;
|
||
|
}
|
||
6 years ago
|
|
||
|
/** Primitive to fetch the URL of a article related to the entry */
|
||
|
protected function getRelatedLinkAtom() {
|
||
|
// FIXME: Atom link fetching should ideally prefer links to text/html resources or the like over e.g. other-format newsfeeds, generic XML, images, etc
|
||
|
$node = $this->fetchAtomRelations("related");
|
||
|
return $node->length ? $this->resolveNodeUrl($node->item(0), "href") : null;
|
||
|
}
|
||
6 years ago
|
}
|