Browse Source

Use structured URLs throughout

master
J. King 4 years ago
parent
commit
a5433f6539
  1. 4
      lib/Entry.php
  2. 6
      lib/Feed.php
  3. 5
      lib/Parser/Construct.php
  4. 7
      lib/Parser/Entry.php
  5. 9
      lib/Parser/Feed.php
  6. 9
      lib/Parser/JSON/Construct.php
  7. 11
      lib/Parser/JSON/Entry.php
  8. 15
      lib/Parser/JSON/Feed.php
  9. 7
      lib/Parser/XML/Entry.php
  10. 11
      lib/Parser/XML/Feed.php
  11. 10
      tests/cases/JSON/JSONTest.php
  12. 1
      tests/cases/Util/UrlTest.php

4
lib/Entry.php

@ -18,9 +18,9 @@ class Entry {
public $id; public $id;
/** @var string $lang The human language of the entry */ /** @var string $lang The human language of the entry */
public $lang; public $lang;
/** @var string $link The URL of the entry as published somwehere else, usually on the World Wide Web */ /** @var \JKingWeb\Lax\Url $link The URL of the entry as published somwehere else, usually on the World Wide Web */
public $link; public $link;
/** @var string $relatedLink The URL of an article related to the entry. For example, if the entry is a commentary on an essay, this property might provide the URL of that essay */ /** @var \JKingWeb\Lax\Url $relatedLink The URL of an article related to the entry. For example, if the entry is a commentary on an essay, this property might provide the URL of that essay */
public $relatedLink; public $relatedLink;
/** @var \JKingWeb\Lax\Text $title The title of the entry */ /** @var \JKingWeb\Lax\Text $title The title of the entry */
public $title; public $title;

6
lib/Feed.php

@ -39,7 +39,7 @@ class Feed {
public $id; public $id;
/** @var string $url The feed's canonical URL. This may differ from the URL used to fetch the newsfeed */ /** @var string $url The feed's canonical URL. This may differ from the URL used to fetch the newsfeed */
public $url; public $url;
/** @var string $link The URL of the Web page associated with the feed */ /** @var \JKingWeb\Lax\Url $link The URL of the Web page associated with the feed */
public $link; public $link;
/** @var \JKingWeb\Lax\Text $title The title of the newsfeed */ /** @var \JKingWeb\Lax\Text $title The title of the newsfeed */
public $title; public $title;
@ -50,9 +50,9 @@ class Feed {
* This property only records a date embedded in the newsfeed itself, not any dates from HTTP or the file system * This property only records a date embedded in the newsfeed itself, not any dates from HTTP or the file system
*/ */
public $dateModified; public $dateModified;
/** @var string $icon URL to a small icon for the newsfeed */ /** @var \JKingWeb\Lax\Url $icon URL to a small icon for the newsfeed */
public $icon; public $icon;
/** @var string $image URL to a large banner or poster image for the newsfeed */ /** @var \JKingWeb\Lax\Url $image URL to a large banner or poster image for the newsfeed */
public $image; public $image;
/** @var \JKingWeb\Lax\Category\Collection $categories A list of categories associated with the newsfeed as a whole */ /** @var \JKingWeb\Lax\Category\Collection $categories A list of categories associated with the newsfeed as a whole */

5
lib/Parser/Construct.php

@ -28,11 +28,6 @@ trait Construct {
} }
} }
/** Resolves a relative URL against a base URL */
protected function resolveUrl(string $url, string $base = null): string {
return \Sabre\Uri\resolve($base ?? "", $url);
}
/** Tests whether a string is a valid e-mail address /** Tests whether a string is a valid e-mail address
* *
* Accepts IDN hosts and (with PHP 7.1 and above) Unicode localparts * Accepts IDN hosts and (with PHP 7.1 and above) Unicode localparts

7
lib/Parser/Entry.php

@ -11,6 +11,7 @@ use JKingWeb\Lax\Category\Collection as CategoryCollection;
use JKingWeb\Lax\Enclosure\Collection as EnclosureCollection; use JKingWeb\Lax\Enclosure\Collection as EnclosureCollection;
use JKingWeb\Lax\Date; use JKingWeb\Lax\Date;
use JKingWeb\Lax\Text; use JKingWeb\Lax\Text;
use JKingWeb\Lax\Url;
interface Entry { interface Entry {
/** Returns the globally unique identifier of the entry; this is usually a URI */ /** Returns the globally unique identifier of the entry; this is usually a URI */
@ -23,10 +24,10 @@ interface Entry {
public function getTitle(): ?Text; public function getTitle(): ?Text;
/** Returns the URL of the published article this entry summarizes */ /** Returns the URL of the published article this entry summarizes */
public function getLink(): ?string; public function getLink(): ?Url;
/** Returns the URL of an article related to the entry */ /** Returns the URL of an article related to the entry */
public function getRelatedLink(): ?string; public function getRelatedLink(): ?Url;
/** Returns the content of the entry, either in plain text or HTML */ /** Returns the content of the entry, either in plain text or HTML */
public function getContent(): ?Text; public function getContent(): ?Text;
@ -44,7 +45,7 @@ interface Entry {
* *
* This is only used by JSON Feed entries * This is only used by JSON Feed entries
*/ */
public function getBanner(): ?string; public function getBanner(): ?Url;
/** Returns a collection of categories associated with the entry */ /** Returns a collection of categories associated with the entry */
public function getCategories(): CategoryCollection; public function getCategories(): CategoryCollection;

9
lib/Parser/Feed.php

@ -11,6 +11,7 @@ use JKingWeb\Lax\Category\Collection as CategoryCollection;
use JKingWeb\Lax\Date; use JKingWeb\Lax\Date;
use JKingWeb\Lax\Text; use JKingWeb\Lax\Text;
use JKingWeb\Lax\Feed as FeedStruct; use JKingWeb\Lax\Feed as FeedStruct;
use JKingWeb\Lax\Url;
interface Feed { interface Feed {
/** Returns the globally unique identifier of the newsfeed; this is usually a URI */ /** Returns the globally unique identifier of the newsfeed; this is usually a URI */
@ -20,13 +21,13 @@ interface Feed {
public function getLang(): ?string; public function getLang(): ?string;
/** Returns the canonical URL of the newsfeed, as contained in the document itself */ /** Returns the canonical URL of the newsfeed, as contained in the document itself */
public function getUrl(): ?string; public function getUrl(): ?Url;
/** Returns the title text of the newsfeed, which may be plain text or HTML */ /** Returns the title text of the newsfeed, which may be plain text or HTML */
public function getTitle(): ?Text; public function getTitle(): ?Text;
/** Returns the URL of the publication this newsfeed summarizes */ /** Returns the URL of the publication this newsfeed summarizes */
public function getLink(): ?string; public function getLink(): ?Url;
/** Returns a short description of the newsfeed, either in plain text or HTML */ /** Returns a short description of the newsfeed, either in plain text or HTML */
public function getSummary(): ?Text; public function getSummary(): ?Text;
@ -35,10 +36,10 @@ interface Feed {
public function getDateModified(): ?Date; public function getDateModified(): ?Date;
/** Returns the URL of a small image used as an icon to identify the newsfeed */ /** Returns the URL of a small image used as an icon to identify the newsfeed */
public function getIcon(): ?string; public function getIcon(): ?Url;
/** Returns the URL of a large image used as a poster or banner to identify the newsfeed */ /** Returns the URL of a large image used as a poster or banner to identify the newsfeed */
public function getImage(): ?string; public function getImage(): ?Url;
/** Returns a collection of categories associated with the newsfeed as a whole. Each category is a structured Category object */ /** Returns a collection of categories associated with the newsfeed as a whole. Each category is a structured Category object */
public function getCategories(): CategoryCollection; public function getCategories(): CategoryCollection;

9
lib/Parser/JSON/Construct.php

@ -10,6 +10,7 @@ use JKingWeb\Lax\Date;
use JKingWeb\Lax\Text; use JKingWeb\Lax\Text;
use JKingWeb\Lax\Person\Collection as PersonCollection; use JKingWeb\Lax\Person\Collection as PersonCollection;
use JKingWeb\Lax\Person\Person; use JKingWeb\Lax\Person\Person;
use JKingWeb\Lax\Url;
trait Construct { trait Construct {
use \JKingWeb\Lax\Parser\Construct; use \JKingWeb\Lax\Parser\Construct;
@ -33,9 +34,13 @@ trait Construct {
} }
/** Returns an object member as a resolved and normalized URL */ /** Returns an object member as a resolved and normalized URL */
protected function fetchUrl(string $key, \stdClass $obj = null): ?string { protected function fetchUrl(string $key, \stdClass $obj = null): ?Url {
$url = $this->fetchMember($key, "str", $obj); $url = $this->fetchMember($key, "str", $obj);
return (!is_null($url)) ? $this->resolveUrl($url, $this->url) : null; try {
return (!is_null($url)) ? new Url($url, $this->url) : null;
} catch (\InvalidArgumentException $e) {
return null;
}
} }
/** Returns an object member as a parsed date */ /** Returns an object member as a parsed date */

11
lib/Parser/JSON/Entry.php

@ -15,6 +15,7 @@ use JKingWeb\Lax\Category\Category;
use JKingWeb\Lax\Date; use JKingWeb\Lax\Date;
use JKingWeb\Lax\Enclosure\Enclosure; use JKingWeb\Lax\Enclosure\Enclosure;
use JKingWeb\Lax\Text; use JKingWeb\Lax\Text;
use JKingWeb\Lax\Url;
class Entry implements \JKingWeb\Lax\Parser\Entry { class Entry implements \JKingWeb\Lax\Parser\Entry {
use Construct; use Construct;
@ -28,7 +29,7 @@ class Entry implements \JKingWeb\Lax\Parser\Entry {
public function __construct(\stdClass $data, FeedStruct $feed) { public function __construct(\stdClass $data, FeedStruct $feed) {
$this->data = $data; $this->data = $data;
$this->feed = $feed; $this->feed = $feed;
$this->url = $feed->meta->url ?? ""; $this->url = $feed->meta->url ?? null;
} }
protected function init(EntryStruct $entry): EntryStruct { protected function init(EntryStruct $entry): EntryStruct {
@ -109,11 +110,11 @@ class Entry implements \JKingWeb\Lax\Parser\Entry {
return $this->fetchDate("date_published"); return $this->fetchDate("date_published");
} }
public function getLink(): ?string { public function getLink(): ?Url {
return $this->fetchUrl("url"); return $this->fetchUrl("url");
} }
public function getRelatedLink(): ?string { public function getRelatedLink(): ?Url {
return $this->fetchUrl("external_url"); return $this->fetchUrl("external_url");
} }
@ -135,7 +136,7 @@ class Entry implements \JKingWeb\Lax\Parser\Entry {
return $out; return $out;
} }
public function getBanner(): ?string { public function getBanner(): ?Url {
return $this->fetchUrl("banner_image"); return $this->fetchUrl("banner_image");
} }
@ -152,7 +153,7 @@ class Entry implements \JKingWeb\Lax\Parser\Entry {
$m->duration = $this->fetchMember("duration_in_seconds", "int", $attachment); $m->duration = $this->fetchMember("duration_in_seconds", "int", $attachment);
// detect media type from file name if no type is provided // detect media type from file name if no type is provided
if (!$m->type) { if (!$m->type) {
$ext = ""; $ext = substr();
$m->type = ($this->mime ?? ($this->mime = new \Mimey\MimeTypes))->getMimeType($ext); $m->type = ($this->mime ?? ($this->mime = new \Mimey\MimeTypes))->getMimeType($ext);
} }
$out[] = $m; $out[] = $m;

15
lib/Parser/JSON/Feed.php

@ -14,6 +14,7 @@ use JKingWeb\Lax\Person\Collection as PersonCollection;
use JKingWeb\Lax\Category\Collection as CategoryCollection; use JKingWeb\Lax\Category\Collection as CategoryCollection;
use JKingWeb\Lax\Parser\Exception; use JKingWeb\Lax\Parser\Exception;
use JKingWeb\Lax\Parser\JSON\Entry as EntryParser; use JKingWeb\Lax\Parser\JSON\Entry as EntryParser;
use JKingWeb\Lax\Url;
class Feed implements \JKingWeb\Lax\Parser\Feed { class Feed implements \JKingWeb\Lax\Parser\Feed {
use Construct; use Construct;
@ -36,7 +37,9 @@ class Feed implements \JKingWeb\Lax\Parser\Feed {
public function __construct(string $data, string $contentType = null, string $url = null) { public function __construct(string $data, string $contentType = null, string $url = null) {
$this->data = $data; $this->data = $data;
$this->contentType = $contentType; $this->contentType = $contentType;
$this->url = $url; if (strlen($url ?? "")) {
$this->url = new Url($url);
}
} }
/** Performs format-specific preparation and validation */ /** Performs format-specific preparation and validation */
@ -83,18 +86,18 @@ class Feed implements \JKingWeb\Lax\Parser\Feed {
* For JSON feeds this is always the feed URL specified in the feed * For JSON feeds this is always the feed URL specified in the feed
*/ */
public function getId(): ?string { public function getId(): ?string {
return $this->fetchUrl("feed_url"); return $this->fetchMember("feed_url", "str");
} }
public function getLang(): ?string { public function getLang(): ?string {
return $this->fetchMember("language", "str"); return $this->fetchMember("language", "str");
} }
public function getUrl(): ?string { public function getUrl(): ?Url {
return $this->fetchUrl("feed_url"); return $this->fetchUrl("feed_url");
} }
public function getLink(): ?string { public function getLink(): ?Url {
return $this->fetchUrl("home_page_url"); return $this->fetchUrl("home_page_url");
} }
@ -126,11 +129,11 @@ class Feed implements \JKingWeb\Lax\Parser\Feed {
return $this->getAuthorsV1() ?? $this->getAuthorV1() ?? new PersonCollection; return $this->getAuthorsV1() ?? $this->getAuthorV1() ?? new PersonCollection;
} }
public function getIcon(): ?string { public function getIcon(): ?Url {
return $this->fetchUrl("favicon"); return $this->fetchUrl("favicon");
} }
public function getImage(): ?string { public function getImage(): ?Url {
return $this->fetchUrl("icon"); return $this->fetchUrl("icon");
} }

7
lib/Parser/XML/Entry.php

@ -11,6 +11,7 @@ use JKingWeb\Lax\Category\Collection as CategoryCollection;
use JKingWeb\Lax\Enclosure\Collection as EnclosureCollection; use JKingWeb\Lax\Enclosure\Collection as EnclosureCollection;
use JKingWeb\Lax\Date; use JKingWeb\Lax\Date;
use JKingWeb\Lax\Text; use JKingWeb\Lax\Text;
use JKingWeb\Lax\Url;
class Entry implements \JKingWeb\Lax\Parser\Entry { class Entry implements \JKingWeb\Lax\Parser\Entry {
use Construct; use Construct;
@ -80,7 +81,7 @@ class Entry implements \JKingWeb\Lax\Parser\Entry {
} }
/** General function to fetch the Web URL of the entry */ /** General function to fetch the Web URL of the entry */
public function getLink(): ?string { public function getLink(): ?Url {
return $this->getLinkAtom() ?? $this->getLinkRss1() ?? $this->getLinkRss2() ?? ""; return $this->getLinkAtom() ?? $this->getLinkRss1() ?? $this->getLinkRss2() ?? "";
} }
@ -88,11 +89,11 @@ class Entry implements \JKingWeb\Lax\Parser\Entry {
* *
* This is only reliable with Atom feeds * This is only reliable with Atom feeds
*/ */
public function getRelatedLink(): ?string { public function getRelatedLink(): ?Url {
return $this->getRelatedLinkAtom() ?? ""; return $this->getRelatedLinkAtom() ?? "";
} }
public function getBanner(): ?string { public function getBanner(): ?Url {
return null; return null;
} }

11
lib/Parser/XML/Feed.php

@ -11,6 +11,7 @@ use JKingWeb\Lax\Category\Collection as CategoryCollection;
use JKingWeb\Lax\Feed as FeedStruct; use JKingWeb\Lax\Feed as FeedStruct;
use JKingWeb\Lax\Date; use JKingWeb\Lax\Date;
use JKingWeb\Lax\Text; use JKingWeb\Lax\Text;
use JKingWeb\Lax\Url;
class Feed implements \JKingWeb\Lax\Parser\Feed { class Feed implements \JKingWeb\Lax\Parser\Feed {
use Construct; use Construct;
@ -81,7 +82,7 @@ class Feed implements \JKingWeb\Lax\Parser\Feed {
* *
* If the feed does not include a canonical URL, the request URL is returned instead * If the feed does not include a canonical URL, the request URL is returned instead
*/ */
public function getUrl(): string { public function getUrl(): ?Url {
return $this->getUrlAtom() ?? $this->getUrlRss1() ?? $this->getUrlPod() ?? $this->reqUrl; return $this->getUrlAtom() ?? $this->getUrlRss1() ?? $this->getUrlPod() ?? $this->reqUrl;
} }
@ -91,7 +92,7 @@ class Feed implements \JKingWeb\Lax\Parser\Feed {
} }
/** General function to fetch the feed's Web-representation URL */ /** General function to fetch the feed's Web-representation URL */
public function getLink(): string { public function getLink(): ?Url {
return $this->getLinkAtom() ?? $this->getLinkRss1() ?? $this->getLinkRss2() ?? ""; return $this->getLinkAtom() ?? $this->getLinkRss1() ?? $this->getLinkRss2() ?? "";
} }
@ -107,7 +108,7 @@ class Feed implements \JKingWeb\Lax\Parser\Feed {
} }
/** General function to fetch the feed identifier */ /** General function to fetch the feed identifier */
public function getId(): string { public function getId(): ?string {
return $this->getIdAtom() ?? $this->getIdDC() ?? $this->getIdRss2() ?? ""; return $this->getIdAtom() ?? $this->getIdDC() ?? $this->getIdRss2() ?? "";
} }
@ -138,11 +139,11 @@ class Feed implements \JKingWeb\Lax\Parser\Feed {
return null; return null;
} }
public function getIcon(): ?string { public function getIcon(): ?Url {
return null; return null;
} }
public function getImage(): ?string { public function getImage(): ?Url {
return null; return null;
} }
} }

10
tests/cases/JSON/JSONTest.php

@ -13,7 +13,7 @@ use JKingWeb\Lax\Feed;
use JKingWeb\Lax\Text; use JKingWeb\Lax\Text;
use JKingWeb\Lax\Person\Person; use JKingWeb\Lax\Person\Person;
use JKingWeb\Lax\Person\Collection as PersonCollection; use JKingWeb\Lax\Person\Collection as PersonCollection;
use JKingWeb\Lax\Url;
/** @covers JKingWeb\Lax\Parser\JSON\Feed<extended> */ /** @covers JKingWeb\Lax\Parser\JSON\Feed<extended> */
class JSONTest extends \PHPUnit\Framework\TestCase { class JSONTest extends \PHPUnit\Framework\TestCase {
@ -75,6 +75,8 @@ class JSONTest extends \PHPUnit\Framework\TestCase {
foreach ($v as $kk => $vv) { foreach ($v as $kk => $vv) {
$f->$k->$kk = $vv; $f->$k->$kk = $vv;
} }
} elseif (in_array($k, ["url", "link", "icon", "image"])) {
$f->$k = new Url($v);
} else { } else {
$f->$k = $v; $f->$k = $v;
} }
@ -85,7 +87,11 @@ class JSONTest extends \PHPUnit\Framework\TestCase {
protected function makeEntry(\stdClass $entry): Entry { protected function makeEntry(\stdClass $entry): Entry {
$e = new Entry; $e = new Entry;
foreach ($entry as $k => $v) { foreach ($entry as $k => $v) {
$e->$k = $v; if (in_array($k, ["url", "link", "icon", "image"])) {
$e->$k = new Url($v);
} else {
$e->$k = $v;
}
} }
return $e; return $e;
} }

1
tests/cases/Util/UrlTest.php

@ -11,7 +11,6 @@ use JKingWeb\Lax\TestCase\Util\Url\AbstractUriTestCase;
/** @covers JKingWeb\Lax\Url<extended> */ /** @covers JKingWeb\Lax\Url<extended> */
class UrlTest extends AbstractUriTestCase { class UrlTest extends AbstractUriTestCase {
//class UrlTest extends \PHPUnit\Framework\TestCase {
protected function createUri($uri = '') { protected function createUri($uri = '') {
return new Url($uri); return new Url($uri);
} }

Loading…
Cancel
Save