Browse Source

Apply house style

master
J. King 4 years ago
parent
commit
2e9598b18b
  1. 3
      .gitignore
  2. 79
      .php_cs.dist
  3. 14
      RoboFile.php
  4. 2
      lib/Category/Category.php
  5. 10
      lib/Category/Collection.php
  6. 19
      lib/Collection.php
  7. 2
      lib/Date.php
  8. 6
      lib/Enclosure/Collection.php
  9. 4
      lib/Entry.php
  10. 8
      lib/Exception.php
  11. 22
      lib/Feed.php
  12. 2
      lib/Metadata.php
  13. 9
      lib/Parser/Construct.php
  14. 2
      lib/Parser/Entry.php
  15. 2
      lib/Parser/Exception.php
  16. 2
      lib/Parser/Feed.php
  17. 2
      lib/Parser/JSON/Construct.php
  18. 10
      lib/Parser/JSON/Entry.php
  19. 13
      lib/Parser/JSON/Feed.php
  20. 34
      lib/Parser/XML/Construct.php
  21. 8
      lib/Parser/XML/Entry.php
  22. 22
      lib/Parser/XML/Feed.php
  23. 22
      lib/Parser/XML/Primitives/Construct.php
  24. 9
      lib/Parser/XML/Primitives/Entry.php
  25. 7
      lib/Parser/XML/Primitives/Feed.php
  26. 12
      lib/Person/Collection.php
  27. 2
      lib/Person/Person.php
  28. 32
      lib/Sanitizer.php
  29. 2
      lib/Schedule.php
  30. 2
      lib/Text.php
  31. 16
      lib/Url.php
  32. 7
      tests/cases/JSON/JSONTest.php
  33. 118
      tests/cases/Util/Url/AbstractUriTestCase.php
  34. 2
      tests/cases/Util/UrlTest.php
  35. 5
      vendor-bin/csfixer/composer.json
  36. 1383
      vendor-bin/csfixer/composer.lock

3
.gitignore

@ -1,4 +1,5 @@
/vendor
/vendor-bin/*/vendor
/tests/coverage
/tests/.phpunit.result.cache
/tests/.phpunit.result.cache
/.php_cs.cache

79
.php_cs.dist

@ -0,0 +1,79 @@
<?php
declare(strict_types=1);
const BASE = __DIR__.DIRECTORY_SEPARATOR;
$paths = [
__FILE__,
BASE."RoboFile.php",
BASE."lib",
BASE."tests",
];
$rules = [
// house rules where PSR series is silent
'align_multiline_comment' => ['comment_type' => "phpdocs_only"],
'array_syntax' => ['syntax' => "short"],
'binary_operator_spaces' => [
'default' => "single_space",
'operators' => ['=>' => "align_single_space"],
],
'cast_spaces' => ['space' => "single"],
'concat_space' => ['spacing' => "none"],
'list_syntax' => ['syntax' => "short"],
'magic_constant_casing' => true,
'magic_method_casing' => true,
'modernize_types_casting' => true,
'native_function_casing' => true,
'native_function_type_declaration_casing' => true,
'no_binary_string' => true,
'no_blank_lines_after_phpdoc' => true,
'no_empty_comment' => true,
'no_empty_phpdoc' => true,
'no_extra_blank_lines' => true, // this could probably use more configuration
'no_mixed_echo_print' => ['use' => "echo"],
'no_short_bool_cast' => true,
'no_trailing_comma_in_singleline_array' => true,
'no_unneeded_control_parentheses' => true,
'no_unneeded_curly_braces' => true,
'no_unused_imports' => true,
'no_whitespace_before_comma_in_array' => true,
'normalize_index_brace' => true,
'object_operator_without_whitespace' => true,
'pow_to_exponentiation' => true,
'set_type_to_cast' => true,
'standardize_not_equals' => true,
'trailing_comma_in_multiline_array' => true,
'unary_operator_spaces' => true,
'yoda_style' => false,
// PSR standard to apply
'@PSR2' => true,
// PSR-12 rules; php-cs-fixer does not yet support PSR-12 natively
'compact_nullable_typehint' => true,
'declare_equal_normalize' => ['space' => "none"],
'function_typehint_space' => true,
'lowercase_cast' => true,
'lowercase_static_reference' => true,
'no_alternative_syntax' => true,
'no_empty_statement' => true,
'no_leading_import_slash' => true,
'no_leading_namespace_whitespace' => true,
'no_whitespace_in_blank_line' => true,
'return_type_declaration' => ['space_before' => "none"],
'single_trait_insert_per_statement' => true,
'short_scalar_cast' => true,
'visibility_required' => ['elements' => ["const", "property", "method"]],
// house exceptions to PSR rules
'braces' => ['position_after_functions_and_oop_constructs' => "same"],
'function_declaration' => ['closure_function_spacing' => "none"],
'new_with_braces' => false, // no option to specify absence of braces
];
$finder = \PhpCsFixer\Finder::create();
foreach ($paths as $path) {
if (is_file($path)) {
$finder = $finder->append([$path]);
} else {
$finder = $finder->in($path);
}
}
return \PhpCsFixer\Config::create()->setRiskyAllowed(true)->setRules($rules)->setFinder($finder);

14
RoboFile.php

@ -24,7 +24,7 @@ class RoboFile extends \Robo\Tasks {
* ./robo test --testsuite TTRSS --exclude-group slow --testdox
*
* Please see the PHPUnit documentation for available options.
*/
*/
public function test(array $args): Result {
return $this->runTests(escapeshellarg(\PHP_BINARY), "typical", $args);
}
@ -33,7 +33,7 @@ class RoboFile extends \Robo\Tasks {
*
* This includes pedantic tests which may help to identify problems.
* See help for the "test" task for more details.
*/
*/
public function testFull(array $args): Result {
return $this->runTests(escapeshellarg(\PHP_BINARY), "full", $args);
}
@ -42,7 +42,7 @@ class RoboFile extends \Robo\Tasks {
* Runs a quick subset of the test suite
*
* See help for the "test" task for more details.
*/
*/
public function testQuick(array $args): Result {
return $this->runTests(escapeshellarg(\PHP_BINARY), "quick", $args);
}
@ -54,9 +54,9 @@ class RoboFile extends \Robo\Tasks {
* arguments to this task as one would to PHPUnit.
*
* Robo first tries to use pcov and will fall back first to xdebug then
* phpdbg. Neither pcov nor xdebug need to be enabled to be used; they
* phpdbg. Neither pcov nor xdebug need to be enabled to be used; they
* only need to be present in the extension load path to be used.
*/
*/
public function coverage(array $args): Result {
// run tests with code coverage reporting enabled
$exec = $this->findCoverageEngine();
@ -71,7 +71,7 @@ class RoboFile extends \Robo\Tasks {
* run all tests which may cover code.
*
* See also help for the "coverage" task for more details.
*/
*/
public function coverageFull(array $args): Result {
// run tests with code coverage reporting enabled
$exec = $this->findCoverageEngine();
@ -121,7 +121,7 @@ class RoboFile extends \Robo\Tasks {
return $all ? ">$hole 2>&1" : "2>$hole";
}
protected function runTests(string $executor, string $set, array $args) : Result {
protected function runTests(string $executor, string $set, array $args): Result {
switch ($set) {
case "typical":
$set = ["--exclude-group", "optional"];

2
lib/Category/Category.php

@ -9,7 +9,7 @@ namespace JKingWeb\Lax\Category;
class Category {
public $name = "";
public $label = "";
public $domain = "";
public $domain = "";
public function __toString() {
return strlen(strlen((string) $this->label)) ? $this->label : $this->name;

10
lib/Category/Collection.php

@ -8,16 +8,16 @@ namespace JKingWeb\Lax\Category;
class Collection extends \JKingWeb\Lax\Collection {
protected static $ranks = [
'webmaster' => 10,
'editor' => 20,
'webmaster' => 10,
'editor' => 20,
'contributor' => 30,
'author' => 40,
'author' => 40,
];
/** Returns the collection formatted as an array of strings
*
*
* The $humanFriendly parameter controls whether or not an effort is made to return human-friendly category names. Only Atom categories have this distinction
*
*
*/
public function list(bool $humanFriendly = true) {
$out = [];

19
lib/Collection.php

@ -7,7 +7,6 @@ declare(strict_types=1);
namespace JKingWeb\Lax;
abstract class Collection implements \IteratorAggregate, \ArrayAccess, \Countable, \JsonSerializable {
protected $data = [];
/** Implementation for IteratorAggregate */
@ -49,10 +48,10 @@ abstract class Collection implements \IteratorAggregate, \ArrayAccess, \Countabl
unset($this->data[$offset]);
}
/** Merges one or more other collections' items into this one
*
/** Merges one or more other collections' items into this one
*
* The returned collection is the original instance, modified
*/
*/
public function merge(Collection ...$coll): self {
foreach ($coll as $c) {
foreach ($c as $p) {
@ -62,14 +61,14 @@ abstract class Collection implements \IteratorAggregate, \ArrayAccess, \Countabl
return $this;
}
/** Returns a collection filtered along a given axis which includes or excludes only the specified terms
*
/** Returns a collection filtered along a given axis which includes or excludes only the specified terms
*
* $terms is the list of values to include or exclude in the result
*
* $axis is the property of each collection member which value is to be checked against the terms
*
*
* $axis is the property of each collection member which value is to be checked against the terms
*
* $inclusive specified whether the terms are to included in (true) or excluded from (false) the result
*/
*/
protected function filter(array $terms, string $axis, bool $inclusive): self {
$out = new static;
foreach ($this as $item) {

2
lib/Date.php

@ -7,7 +7,7 @@ declare(strict_types=1);
namespace JKingWeb\Lax;
class Date extends \DateTimeImmutable implements \JsonSerializable {
static public $supportedFormats = [
public static $supportedFormats = [
// RFC 3339 formats
'Y-m-d\TH:i:s.u\Z',
'Y-m-d\TH:i:s.u\z',

6
lib/Enclosure/Collection.php

@ -9,11 +9,11 @@ namespace JKingWeb\Lax\Enclosure;
class Collection extends \JKingWeb\Lax\Collection {
/** Returns the primary ("best") enclosure of the collection
*
*
* Videos are preferred over audios, which are preferred over images, which are preferred over anything else
*
*
* Videos are first ranked by length, then resolution (total pixels), then bitrate, then size; audios are ranked by length, then bitrate, then size; images are ranked by resolution (total pixels), then size
*
*
*/
public function primary(): ?Enclosure {
# stub

4
lib/Entry.php

@ -12,7 +12,7 @@ use JKingWeb\Lax\Enclosure\Collection as EnclosureCollection;
class Entry {
/** @var string $id The persistent identifier of the entry. This is often identical to the URL of the entry, but the latter may change
*
*
* While identifiers are usually supposed to be globally unique, in practice they are frequently only unique within the context of a particular newsfeed
*/
public $id;
@ -25,7 +25,7 @@ class Entry {
/** @var \JKingWeb\Lax\Text $title The title of the entry */
public $title;
/** @var \JKingWeb\Lax\Text $content The content of the entry
*
*
* This may be merely a summary or excerpt for many newsfeeds */
public $content;
/** @var \JKingWeb\Lax\Text $summary A short summary or excerpt of the entry, distinct from the content */

8
lib/Exception.php

@ -9,9 +9,9 @@ namespace JKingWeb\Lax;
abstract class Exception extends \Exception {
public const SYMBOLS = [
// Parsing: 0x1100
"notJSONType" => [0x1111, "Document Content-Type is not either that of JSON Feed or generic JSON"],
"notJSONType" => [0x1111, "Document Content-Type is not either that of JSON Feed or generic JSON"],
"notJSON" => [0x1112, "Document is not valid JSON"],
"notJSONFeed" => [0x1113, "Document is not a JSON Feed document"]
"notJSONFeed" => [0x1113, "Document is not a JSON Feed document"],
];
public function __construct(string $symbol, \Exception $e = null) {
@ -19,7 +19,7 @@ abstract class Exception extends \Exception {
if (!$data) {
throw new \Exception("Exception symbol \"$symbol\" does not exist");
}
list($code, $msg) = $data;
[$code, $msg] = $data;
parent::__construct($msg, $code, $e);
}
}
}

22
lib/Feed.php

@ -10,30 +10,30 @@ use JKingWeb\Lax\Category\Collection as CategoryCollection;
use JKingWeb\Lax\Person\Collection as PersonCollection;
/** Represents a newsfeed, in arbitrary format
*
*
* All properties may be null.
*/
class Feed {
/** @var string $format The format of newsfeed, one of the following:
*
*
* - `rss` for RSS 0.9x or RSS 2.0.x
* - `rdf` for RSS 1.0
* - `atom` for Atom feeds
* - `json` for JSON Feed
* - `hfeed` for a microformat h-feeds
*
*
* The format is largely advisory, but may be used when converting between formats
*/
public $format;
/** @var string $version The format version of the newsfeed
*
*
* The version is largely advisory, but may be used when converting between formats
*/
public $version;
/** @var string $lang The human language of the newsfeed as a whole */
public $lang;
/** @var string $id The globally unique identifier for the newsfeed
*
*
* For some formats, such as RSS 2.0 and JSON Feed, this may be he same as the newsfeed URL
*/
public $id;
@ -46,7 +46,7 @@ class Feed {
/** @var \JKingWeb\Lax\Text $summary A short description or summary of the newsfeed */
public $summary;
/** @var \JKingWeb\Lax\Date $dateModified The date at which the newsfeed was last modified
*
*
* This property only records a date embedded in the newsfeed itself, not any dates from HTTP or the file system
*/
public $dateModified;
@ -54,7 +54,7 @@ class Feed {
public $icon;
/** @var \JKingWeb\Lax\Url $image URL to a large banner or poster image for the newsfeed */
public $image;
/** @var \JKingWeb\Lax\Category\Collection $categories A list of categories associated with the newsfeed as a whole */
public $categories;
/** @var \JKingWeb\Lax\Person\Collection $people A list of people (e.g. authors, contributors) associated with the newsfeed as a whole */
@ -73,14 +73,14 @@ class Feed {
$this->categories = new CategoryCollection;
$this->sched = new Schedule;
}
/** Parses a string to produce a Feed object
*
*
* Most users will probably rather want the Feed::fetch() method
*
*
* @param string $data The newsfeed to parse
* @param string|null $contentType The HTTP Content-Type of the document, if available
* @param string|null $url The URL used to retrieve the newsfeed, if applicable
* @param string|null $url The URL used to retrieve the newsfeed, if applicable
*/
public static function parse(string $data, ?string $contentType = null, ?string $url = null): self {
$out = new self;

2
lib/Metadata.php

@ -14,4 +14,4 @@ class Metadata {
public $etag;
public $expires;
public $maxAge;
}
}

9
lib/Parser/Construct.php

@ -17,7 +17,7 @@ trait Construct {
}
/** Takes an HTML string as input and returns a sanitized version of that string
*
*
* The $outputHtml parameter, when false, outputs only the plain-text content of the sanitized HTML
*/
protected function sanitizeString(string $markup, bool $outputHtml = true): string {
@ -30,7 +30,7 @@ trait Construct {
}
/** Tests whether a string is a valid e-mail address
*
*
* Accepts IDN hosts and Unicode localparts
*/
protected function validateMail(string $addr): bool {
@ -42,7 +42,8 @@ trait Construct {
$domain = $match[2];
// PHP's filter_var does not accept IDN hosts, so we have to perform an IDNA transformation first
$domain = idn_to_ascii($domain, \IDNA_NONTRANSITIONAL_TO_ASCII | \IDNA_CHECK_BIDI | \IDNA_CHECK_CONTEXTJ, \INTL_IDNA_VARIANT_UTS46); // settings for IDNA2008 algorithm (I think)
if ($domain !== false) {$addr = "$local@$domain";
if ($domain !== false) {
$addr = "$local@$domain";
return (bool) filter_var($addr, \FILTER_VALIDATE_EMAIL, \FILTER_FLAG_EMAIL_UNICODE);
}
return false;
@ -65,7 +66,7 @@ trait Construct {
protected function parseMediaType(string $type, ?Url $url = null): ?string {
if (preg_match('<^\s*([0-9a-z]+(?:/[!#$%&\'\*\+\-\.^_`|~0-9a-z]+)?)(?:\s|;|,|$)>i', $type, $match)) {
/* NOTE: The pattern used here is a subset of what is
/* NOTE: The pattern used here is a subset of what is
technically allowed by RFC 7231: the "type" portion
is supposed to be as general as the "subtype" portion,
but in practice only alphabetic types have ever been

2
lib/Parser/Entry.php

@ -42,7 +42,7 @@ interface Entry {
public function getDateModified(): ?Date;
/** Returns the URL of a large image used as a banner when displaying the entry
*
*
* This is only used by JSON Feed entries
*/
public function getBanner(): ?Url;

2
lib/Parser/Exception.php

@ -9,4 +9,4 @@ namespace JKingWeb\Lax\Parser;
use JKingWeb\Lax\Exception as BaseException;
class Exception extends BaseException {
}
}

2
lib/Parser/Feed.php

@ -48,7 +48,7 @@ interface Feed {
public function getPeople(): PersonCollection;
/** Returns the list of entries
*
*
* @param \JKingWeb\Lax\Feed $feed The newsfeed to which the entry belongs. Some data from the newsfeed may be used in parsing the entry
*/
public function getEntries(FeedStruct $feed = null): array;

2
lib/Parser/JSON/Construct.php

@ -16,7 +16,7 @@ trait Construct {
use \JKingWeb\Lax\Parser\Construct;
/** Returns an object member if the member exists and is of the expected type
*
*
* Returns null otherwise
*/
protected function fetchMember(string $key, string $type, ?\stdClass $obj = null) {

10
lib/Parser/JSON/Entry.php

@ -51,7 +51,7 @@ class Entry implements \JKingWeb\Lax\Parser\Entry {
$entry->people = $this->getPeople();
$entry->categories = $this->getCategories();
$entry->enclosures = $this->getEnclosures();
return $entry;
return $entry;
}
public function getId(): ?string {
@ -69,7 +69,7 @@ class Entry implements \JKingWeb\Lax\Parser\Entry {
$exp = (int) $id[1];
$mul = $exp > -1;
$exp = abs($exp);
list($int, $dec) = explode(".", $id[0]);
[$int, $dec] = explode(".", $id[0]);
$dec = strlen($dec) ? str_split($dec, 1) : [];
$int = str_split($int, 1);
if ($int[0] === "-") {
@ -89,7 +89,7 @@ class Entry implements \JKingWeb\Lax\Parser\Entry {
array_unshift($dec, "0");
}
}
return ($neg ? "-" : "") . ($int ? implode("", $int) : "0") . ($dec ? ("." . rtrim(implode("", $dec), "0")) : "");
return ($neg ? "-" : "").($int ? implode("", $int) : "0").($dec ? (".".rtrim(implode("", $dec), "0")) : "");
}
}
} else {
@ -156,9 +156,9 @@ class Entry implements \JKingWeb\Lax\Parser\Entry {
$out[] = $m;
}
// handle other attachments
foreach ($this->fetchMember("attachments", "array") ?? [] as $attachment) {
foreach ($this->fetchMember("attachments", "array") ?? [] as $attachment) {
$url = $this->fetchUrl("url", $attachment);
if ($url) {
if ($url) {
$m = new Enclosure;
$m->url = $url;
$m->type = $this->fetchType("mime_type", $url, $attachment);

13
lib/Parser/JSON/Feed.php

@ -8,7 +8,6 @@ namespace JKingWeb\Lax\Parser\JSON;
use JKingWeb\Lax\Text;
use JKingWeb\Lax\Date;
use JKingWeb\Lax\Entry;
use JKingWeb\Lax\Feed as FeedStruct;
use JKingWeb\Lax\Person\Collection as PersonCollection;
use JKingWeb\Lax\Category\Collection as CategoryCollection;
@ -82,9 +81,9 @@ class Feed implements \JKingWeb\Lax\Parser\Feed {
}
/** {@inheritdoc}
*
*
* For JSON feeds this is always the feed URL specified in the feed
*/
*/
public function getId(): ?string {
return $this->fetchMember("feed_url", "str");
}
@ -106,9 +105,9 @@ class Feed implements \JKingWeb\Lax\Parser\Feed {
}
/** {@inheritdoc}
*
*
* JSON feeds themselves don't have dates, so this always returns null
*/
*/
public function getDateModified(): ?Date {
return null;
}
@ -118,9 +117,9 @@ class Feed implements \JKingWeb\Lax\Parser\Feed {
}
/** {@inheritdoc}
*
*
* JSON Feed does not have categories at the feed level, so this always returns and empty collection
*/
*/
public function getCategories(): CategoryCollection {
return new CategoryCollection;
}

34
lib/Parser/XML/Construct.php

@ -15,7 +15,7 @@ trait Construct {
use \JKingWeb\Lax\Parser\Construct;
/** @var \DOMDocument */
public $document;
protected $document;
/** @var \DOMXPath */
protected $xpath;
/** @var \DOMElement */
@ -24,7 +24,7 @@ trait Construct {
/** Retrieves an element node based on an XPath query */
protected function fetchElement(string $query, \DOMNode $context = null) {
$node = @$this->xpath->query("(".$query.")[1]", $context ?? $this->subject);
if ($node===false) {
if ($node === false) {
throw new \Exception("Invalid XPath query: $query"); // @codeCoverageIgnore
}
return ($node->length) ? $node->item(0) : null;
@ -55,12 +55,12 @@ trait Construct {
protected function fetchStringAtom(string $query, bool $html = false): ?Text {
$node = $this->fetchElement($query);
if ($node) {
if (!$node->hasAttribute("type") || $node->getAttribute("type")=="text") {
if (!$node->hasAttribute("type") || $node->getAttribute("type") == "text") {
return $html ? htmlspecialchars($this->trimText($node->textContent), \ENT_QUOTES | \ENT_HTML5) : $this->trimText($node->textContent);
} elseif ($node->getAttribute("type")=="xhtml") {
} elseif ($node->getAttribute("type") == "xhtml") {
$node = $node->getElementsByTagNameNS(self::NS['xhtml'], "div")->item(0);
return $node ? $this->sanitizeElement($node, $html) : null;
} elseif ($node->getAttribute("type")=="html") {
} elseif ($node->getAttribute("type") == "html") {
return $this->sanitizeString($node->textContent, $html);
} else {
return null;
@ -76,19 +76,19 @@ trait Construct {
}
/** Returns a node-list of Atom link elements with the desired relation or equivalents.
*
*
* Links without an href attribute are excluded.
*
*
* @see https://tools.ietf.org/html/rfc4287#section-4.2.7.2
*/
protected function fetchAtomRelations(string $rel = ""): \DOMNodeList {
// FIXME: The XPath evaluation will fail if the relation contains an apostrophe. This is a known and difficult-to-overcome limitation of XPath 1.0 which I consider not worth the effort to address at this time
if ($rel=="" || $rel=="alternate" || $rel=="http://www.iana.org/assignments/relation/alternate") {
if ($rel == "" || $rel == "alternate" || $rel == "http://www.iana.org/assignments/relation/alternate") {
$cond = "not(@rel) or @rel='' or @rel='alternate' or @rel='http://www.iana.org/assignments/relation/alternate'";
} elseif (strpos($rel, ":")===false) {
} elseif (strpos($rel, ":") === false) {
// FIXME: Checking only for a colon in a link relation is a hack that does not strictly follow IRI rules, but it's adequate for our needs
$cond = "@rel='$rel' or @rel='http://www.iana.org/assignments/relation/$rel'";
} elseif (strlen($rel) > 41 && strpos($rel, "http://www.iana.org/assignments/relation/")===0) {
} elseif (strlen($rel) > 41 && strpos($rel, "http://www.iana.org/assignments/relation/") === 0) {
$rel = substr($rel, 41);
$cond = "@rel='$rel' or @rel='http://www.iana.org/assignments/relation/$rel'";
} else {
@ -98,11 +98,11 @@ trait Construct {
}
/** Finds and parses RSS person-texts and returns a collection of person objects
*
*
* Each can have a name, e-mail address, or both
*
*
* The following forms will yield both a name and address:
*
*
* - user@example.com (Full Name)
* - Full Name <user@example.com>
*/
@ -157,12 +157,12 @@ trait Construct {
return count($out) ? $out : null;
}
/** Resolves a URL contained in a DOM element's atrribute or text
*
/** Resolves a URL contained in a DOM element's atrribute or text
*
* This automatically performs xml:base and HTML <base> resolution
*
*
* Specifying the empty string for $attr results in the element content being used as a URL
*/
*/
protected function resolveNodeUrl(\DOMElement $node = null, string $attr = "", string $ns = null): string {
$base = $node->baseURI;
$url = strlen($attr) ? $node->getAttributeNS($ns, $attr) : $this->trimText($node->textContent);

8
lib/Parser/XML/Entry.php

@ -45,9 +45,9 @@ class Entry implements \JKingWeb\Lax\Parser\Entry {
$entry->title = strlen($this->title) ? $this->title : $this->link;
// do extra stuff just to test it
$entry->categories = $this->getCategories();
return $entry;
return $entry;
}
/** General function to fetch the entry title */
public function getTitle(): ?Text {
return $this->getTitleAtom() ?? $this->getTitleRss1() ?? $this->getTitleRss2() ?? $this->getTitleDC() ?? $this->getTitlePod() ?? "";
@ -86,7 +86,7 @@ class Entry implements \JKingWeb\Lax\Parser\Entry {
}
/** General function to fetch the URL of a article related to the entry
*
*
* This is only reliable with Atom feeds
*/
public function getRelatedLink(): ?Url {
@ -102,7 +102,7 @@ class Entry implements \JKingWeb\Lax\Parser\Entry {
}
public function getEnclosures(): EnclosureCollection {
return new EnclosureCollection;
return new EnclosureCollection;
}
public function getLang(): ?string {

22
lib/Parser/XML/Feed.php

@ -24,8 +24,6 @@ class Feed implements \JKingWeb\Lax\Parser\Feed {
protected $contentType;
/** @var \JKingWeb\Lax\Url */
protected $url;
/** @var \DOMDocument */
protected $document;
/** @var \DOMElement */
protected $subject;
/** @var \DOMXpath */
@ -49,23 +47,23 @@ class Feed implements \JKingWeb\Lax\Parser\Feed {
$this->subject = $this->document->documentElement;
$ns = $this->subject->namespaceURI;
$name = $this->subject->localName;
if (is_null($ns) && $name=="rss") {
if (is_null($ns) && $name === "rss") {
$this->subject = $this->fetchElement("channel") ?? $this->subject;
$feed->format = "rss";
$feed->version = $this->document->documentElement->getAttribute("version");
} elseif ($ns==XPath::NS['rdf'] && $name=="RDF") {
} elseif ($ns === XPath::NS['rdf'] && $name === "RDF") {
$feed->format = "rdf";
$channel = $this->fetchElement("rss1:channel|rss0:channel");
if ($channel) {
$this->subject = $channel;
$feed->version = ($channel->namespaceURI==XPath::NS['rss1']) ? "1.0" : "0.90";
$feed->version = ($channel->namespaceURI === XPath::NS['rss1']) ? "1.0" : "0.90";
} else {
$element = $this->fetchElement("rss1:item|rss0:item|rss1:image|rss0:image");
if ($element) {
$feed->version = ($element->namespaceURI==XPath::NS['rss1']) ? "1.0" : "0.90";
}
$element = $this->fetchElement("rss1:item|rss0:item|rss1:image|rss0:image");
if ($element) {
$feed->version = ($element->namespaceURI === XPath::NS['rss1']) ? "1.0" : "0.90";
}
}
} elseif ($ns==XPath::NS['atom'] && $name=="feed") {
} elseif ($ns === XPath::NS['atom'] && $name === "feed") {
$feed->format = "atom";
$feed->version = "1.0";
} else {
@ -98,11 +96,11 @@ class Feed implements \JKingWeb\Lax\Parser\Feed {
public function getId(): ?string {
return $this->getIdAtom() ?? $this->getIdDC() ?? $this->getIdRss2() ?? "";
}
public function getUrl(): ?Url {
return $this->getUrlAtom() ?? $this->getUrlRss1() ?? $this->getUrlPod() ?? $this->reqUrl;
}
public function getTitle(): ?Text {
return $this->getTitleAtom() ?? $this->getTitleRss1() ?? $this->getTitleRss2() ?? $this->getTitleDC() ?? $this->getTitlePod() ?? "";
}

22
lib/Parser/XML/Primitives/Construct.php

@ -90,9 +90,9 @@ trait Construct {
}
/** 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
*/
*/
protected function getCategoriesDC(): ?CategoryCollection {
$out = new CategoryCollection;
foreach ($this->fetchStringMulti("dc:subject") ?? [] as $text) {
@ -123,10 +123,10 @@ trait Construct {
return $this->fetchString("atom:id");
}
/** Primitive to fetch an RSS feed/entry identifier
*
/** Primitive to fetch an RSS feed/entry identifier
*
* Using RSS' <guid> for feed identifiers is non-standard, but harmless
*/
*/
protected function getIdRss2(): ?string {
return $this->fetchString("guid");
}
@ -166,10 +166,10 @@ trait Construct {
return $this->fetchPeopleAtom("atom:contributor", "contributor");
}
/** Primitive to fetch a collection of authors associated with a podcast/episode
*
/** Primitive to fetch a collection of authors associated with a podcast/episode
*
* The collection only ever contains the first author found: podcasts implicitly have only one author
*/
*/
protected function getAuthorsPod(): ?PersonCollection {
$out = new PersonCollection;
$p = new Person;
@ -182,10 +182,10 @@ trait Construct {
return count($out) ? $out : null;
}
/** Primitive to fetch a collection of webmasters associated with a podcast
*
/** 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(): ?PersonCollection {
$out = new PersonCollection;
$node = $this->fetchElement("gplay:owner|apple:owner");

9
lib/Parser/XML/Primitives/Entry.php

@ -6,14 +6,13 @@
declare(strict_types=1);
namespace JKingWeb\Lax\Parser\XML\Primitives;
use JKingWeb\Lax\Person\Collection as PersonCollection;
use JKingWeb\Lax\Parser\XML\XPath;
trait Entry {
/** Primitive to fetch a collection of authors associated with an Atom entry
*
/** Primitive to fetch a collection of authors associated with an Atom entry
*
* This differs from feeds in that an entry's <source> element (which possibly contains metadata for the source feed) is checked for authors if the entry itself has none
*/
*/
protected function getAuthorsAtom() {
return $this->fetchPeopleAtom("atom:author", "author") ?? $this->fetchPeopleAtom("atom:source[1]/atom:author", "author");
}
@ -22,7 +21,7 @@ trait Entry {
protected function getUrlRss1() {
// XPath doesn't seem to like the query we'd need for this, so it must be done the hard way.
$node = $this->subject;
if ($node->localName=="item" && ($node->namespaceURI==XPath::NS['rss1'] || $node->namespaceURI==XPath::NS['rss0']) && $node->hasAttributeNS(XPath::NS['rdf'], "about")) {
if ($node->localName === "item" && ($node->namespaceURI === XPath::NS['rss1'] || $node->namespaceURI == XPath::NS['rss0']) && $node->hasAttributeNS(XPath::NS['rdf'], "about")) {
return $this->resolveNodeUrl($node, "about", XPath::NS['rdf']);
} else {
return null;

7
lib/Parser/XML/Primitives/Feed.php

@ -6,12 +6,11 @@
declare(strict_types=1);
namespace JKingWeb\Lax\Parser\XML\Primitives;
use JKingWeb\Lax\Person\Collection as PersonCollection;
use JKingWeb\Lax\Parser\XML\XPath;
trait Feed {
/** Primitive to fetch an Atom feed summary
*
*
* Atom does not have a 'description' element like the RSSes, but it does have 'subtitle', which fills roughly the same function
*/
protected function getSummaryAtom() {
@ -49,8 +48,8 @@ trait Feed {
$node = $this->subject;
if ($node->hasAttributeNS(XPath::NS['rdf'], "about")) {
if (
($node->localName=="channel" && ($node->namespaceURI==XPath::NS['rss1'] || $node->namespaceURI==XPath::NS['rss0'])) ||
($node==$node->ownerDocument->documentElement && $node->localName=="RDF" && $node->namespaceURI==XPath::NS['rdf'])
($node->localName === "channel" && ($node->namespaceURI === XPath::NS['rss1'] || $node->namespaceURI === XPath::NS['rss0'])) ||
($node === $node->ownerDocument->documentElement && $node->localName === "RDF" && $node->namespaceURI === XPath::NS['rdf'])
) {
return $this->resolveNodeUrl($node, "about", XPath::NS['rdf']);
}

12
lib/Person/Collection.php

@ -9,18 +9,18 @@ namespace JKingWeb\Lax\Person;
class Collection extends \JKingWeb\Lax\Collection {
protected static $ranks = [
'contributor' => -10,
'webmaster' => 10,
'editor' => 20,
'author' => 30,
'webmaster' => 10,
'editor' => 20,
'author' => 30,
];
/** Returns the primary person of the collection
*
*
* The primary is the first member of the highest-weight role
*
*
* Roles are ranked thus:
* author > contributor > editor > webmaster > (anything else)
*
*
*/
public function primary() {
$out = null;

2
lib/Person/Person.php

@ -9,7 +9,7 @@ namespace JKingWeb\Lax\Person;
class Person {
public $name = null;
public $mail = null;
public $url = null;
public $url = null;
public $role = null;
public $avatar = null;

32
lib/Sanitizer.php

@ -172,24 +172,24 @@ class Sanitizer {
//"autocapitalize", // not useful for static content
//"contenteditable", // not useful for static content
"class",
"dir",
"dir",
//"draggable", // not useful for static content
"hidden",
"hidden",
//"inputmode", // not useful for static content
//"is", // only used with custom elements
"id",
"itemid",
"itemprop",
"itemref",
"itemscope",
"itemtype",
"lang",
"itemid",
"itemprop",
"itemref",
"itemscope",
"itemtype",
"lang",
//"nonce", // only used via scripts (I think)
//"slot", // only used via scripts (I think)
//"spellcheck", // not useful for static content
//"style", // arbitrary styling; potentially unsafe
"tabindex",
"title",
"title",
"translate",
// WAI-ARIA
"aria-describedby",
@ -207,22 +207,22 @@ class Sanitizer {
"poster",
];
/**
/**
* Sanitizes a DOMDocument object, returning the same document, modified
*
*
* The document may be an HTML document or or any partial XHTML tree, possibly mixed with other XML vocabularies
*
*
* The document's documentURI is assumed to already be set
*/
public function processDocument(\DOMDocument $doc, string $url): \DOMDocument {
// determine if the document is non-XML HTML
$isHtml = ($doc->documentElement->tagName=="html" && $doc->documentElement->namespaceURI=="");
$isHtml = ($doc->documentElement->tagName === "html" && $doc->documentElement->namespaceURI === "");
// loop through each element in the document
foreach ((new \DOMXPath($doc))->query("//*") as $node) {
// resolve a qualified name for the element
if (($isHtml && $node->namespaceURI=="") || $node->namespaceURI=="http://www.w3.org/1999/xhtml") {
if (($isHtml && $node->namespaceURI === "") || $node->namespaceURI === "http://www.w3.org/1999/xhtml") {
$qName = "html:".$node->tagName;
} elseif ($node->namespaceURI=="") {
} elseif ($node->namespaceURI === "") {
$qName = $node->tagName;
} elseif (isset($this->namespaces[$node->namespaceURI])) {
$qName = $this->namespaces[$node->namespaceURI].":".$node->tagName;
@ -244,7 +244,7 @@ class Sanitizer {
$node->parentNode->removeChild($node);
} else {
// if the element is in the keep list, clean up its attributes
foreach (iterator_to_array($node->attributes) as $attr) { // we use an array
foreach (iterator_to_array($node->attributes) as $attr) { // we use an array
if (!in_array($attr->name, $this->attrKeep) && !(isset($this->elemKeep[$qName]) && in_array($attr->name, $this->elemKeep[$qName]))) {
// if the attribute is not allowed globally or for the element, remove it
$attr->ownerElement->removeAttributeNode($attr);

2
lib/Schedule.php

@ -8,4 +8,4 @@ namespace JKingWeb\Lax;
class Schedule {
public $expired;
}
}

2
lib/Text.php

@ -19,4 +19,4 @@ class Text {
assert(in_array($type, ["plain", "html", "xhtml", "loose"]), new \InvalidArgumentException);
$this->$type = $data;
}
}
}

16
lib/Url.php

@ -9,9 +9,9 @@ namespace JKingWeb\Lax;
use Psr\Http\Message\UriInterface;
/** Normalized URI representation, compatible with the PSR-7 URI interface
*
*
* The following features are implemented:
*
*
* - The full PSR-7 `UriInterface` interface
* - Correct handling of both URLs and URNs
* - Relative URL resolution
@ -20,13 +20,13 @@ use Psr\Http\Message\UriInterface;
* - IDNA normalization
* - IPv6 address normalization
* - Empty query and fragment removal
*
*
* Some things this class does not do:
*
*
* - Handle non-standard schemes (e.g. ed2k)
* - Collapse paths
* - Drop default ports
*
*
* This class should not be used with XML namespace URIs,
* as the normalizations performed will change the values
* of some namespaces.
@ -243,7 +243,7 @@ PCRE;
}
break;
default:
$this->$name = $this->normalizeEncoding((string) $value, $name);
$this->$name = $this->normalizeEncoding((string) $value, $name);
}
}
@ -266,7 +266,7 @@ PCRE;
$this->fragment = $fragment;
}
}
} elseif(strlen($path)) {
} elseif (strlen($path)) {
if ($this->path[0] !== "/") {
if ($path[-1] === "/") {
$this->path = $path.$this->path;
@ -345,4 +345,4 @@ PCRE;
}
return $host;
}
}
}

7
tests/cases/JSON/JSONTest.php

@ -26,11 +26,11 @@ namespace JKingWeb\Lax\TestCase\JSON;
be applied to it
- Any collections should be represented as sequences of maps, which will
all be transformed accordingly
- Rich text can either be supplied as a string (which will yield a Text object
- Rich text can either be supplied as a string (which will yield a Text object
with plain-text content) or as a map with any of the properties of the
Text class listed
The transformations as performed by the `makeFeed` and `makeEntry` methods
The transformations as performed by the `makeFeed` and `makeEntry` methods
of the abstract test case.
*/
@ -51,8 +51,7 @@ use JKingWeb\Lax\Enclosure\Collection as EnclosureCollection;
use Symfony\Component\Yaml\Yaml;
use Symfony\Component\Yaml\Parser as YamlParser;
/**
/**
* @covers JKingWeb\Lax\Parser\Construct<extended>
* @covers JKingWeb\Lax\Parser\JSON\Feed<extended>
* @covers JKingWeb\Lax\Parser\JSON\Entry<extended>

118
tests/cases/Util/Url/AbstractUriTestCase.php

@ -6,8 +6,7 @@ use Psr\Http\Message\UriInterface;
use PHPUnit\Framework\TestCase;
use InvalidArgumentException;
abstract class AbstractUriTestCase extends TestCase
{
abstract class AbstractUriTestCase extends TestCase {
/**
* @var UriInterface
*/
@ -24,13 +23,11 @@ abstract class AbstractUriTestCase extends TestCase
*/
abstract protected function createUri($uri = '');
protected function setUp(): void
{
protected function setUp(): void {
$this->uri = $this->createUri($this->uri_string);
}
protected function tearDown(): void
{
protected function tearDown(): void {
$this->uri = null;
}
@ -41,15 +38,13 @@ abstract class AbstractUriTestCase extends TestCase
* The value returned MUST be normalized to lowercase, per RFC 3986
* Section 3.1.
*/
public function testGetScheme($scheme, $expected)
{
public function testGetScheme($scheme, $expected) {
$uri = $this->uri->withScheme($scheme);
$this->assertInstanceOf(UriInterface::class, $uri);
$this->assertSame($expected, $uri->getScheme(), 'Scheme must be normalized according to RFC3986');
}
public function schemeProvider()
{
public function schemeProvider() {
return [
'normalized scheme' => ['HtTpS', 'https'],
'simple scheme' => ['http', 'http'],
@ -66,15 +61,13 @@ abstract class AbstractUriTestCase extends TestCase
* user value, with a colon (":") separating the values.
*
*/
public function testGetUserInfo($user, $pass, $expected)
{
public function testGetUserInfo($user, $pass, $expected) {
$uri = $this->uri->withUserInfo($user, $pass);
$this->assertInstanceOf(UriInterface::class, $uri);
$this->assertSame($expected, $uri->getUserInfo(), 'UserInfo must be normalized according to RFC3986');
}
public function userInfoProvider()
{
public function userInfoProvider() {
return [
'with userinfo' => ['iGoR', 'rAsMuZeN', 'iGoR:rAsMuZeN'],
'no userinfo' => ['', '', ''],
@ -92,15 +85,13 @@ abstract class AbstractUriTestCase extends TestCase
* Section 3.2.2.
*
*/
public function testGetHost($host, $expected)
{
public function testGetHost($host, $expected) {
$uri = $this->uri->withHost($host);
$this->assertInstanceOf(UriInterface::class, $uri);
$this->assertSame($expected, $uri->getHost(), 'Host must be normalized according to RFC3986');
}
public function hostProvider()
{
public function hostProvider() {
return [
'normalized host' => ["MaStEr.eXaMpLe.CoM", "master.example.com"],
"simple host" => ["www.example.com", "www.example.com"],
@ -122,18 +113,16 @@ abstract class AbstractUriTestCase extends TestCase
* If no port is present, but a scheme is present, this method MAY return
* the standard port for that scheme, but SHOULD return null.
*/
public function testPort($uri, $port, $expected)
{
public function testPort($uri, $port, $expected) {
$uri = $this->createUri($uri)->withPort($port);
$this->assertInstanceOf(UriInterface::class, $uri);
$this->assertSame($expected, $uri->getPort(), 'port must be an int or null');
}
public function portProvider()
{
public function portProvider() {
return [
'non standard port for http' => ['http://www.example.com', 443, 443],
'remove port' => ['http://www.example.com', null, null],
'non standard port for http' => ['http://www.example.com', 443, 443],
'remove port' => ['http://www.example.com', null, null],
'standard port on schemeless http url' => ['//www.example.com', 80, 80],
];
}
@ -141,13 +130,11 @@ abstract class AbstractUriTestCase extends TestCase
/**
* @group port
*/
public function testUriWithStandardPort()
{
public function testUriWithStandardPort() {
$uri = $this->createUri('http://example.com:80');
$this->assertContains($uri->getPort(), [80, null], "If no port is present, but a scheme is present, this method MAY return the standard port for that scheme, but SHOULD return null.");
}
/**
* @group authority
* @dataProvider authorityProvider
@ -155,8 +142,7 @@ abstract class AbstractUriTestCase extends TestCase
* If the port component is not set or is the standard port for the current
* scheme, it SHOULD NOT be included.
*/
public function testGetAuthority($scheme, $user, $pass, $host, $port, $authority)
{
public function testGetAuthority($scheme, $user, $pass, $host, $port, $authority) {
$uri = $this
->createUri()
->withHost($host)
@ -168,8 +154,7 @@ abstract class AbstractUriTestCase extends TestCase
$this->assertSame($authority, $uri->getAuthority());
}
public function authorityProvider()
{
public function authorityProvider() {
return [
'authority' => [
'scheme' => 'http',
@ -222,15 +207,13 @@ abstract class AbstractUriTestCase extends TestCase
* any characters. To determine what characters to encode, please refer to
* RFC 3986, Sections 2 and 3.4.
*/
public function testGetQuery($query, $expected)
{
public function testGetQuery($query, $expected) {
$uri = $this->uri->withQuery($query);
$this->assertInstanceOf(UriInterface::class, $uri);
$this->assertSame($expected, $uri->getQuery(), 'Query must be normalized according to RFC3986');
}
public function queryProvider()
{
public function queryProvider() {
return [
'normalized query' => ['foo.bar=%7evalue', 'foo.bar=~value'],
'empty query' => ['', ''],
@ -247,15 +230,13 @@ abstract class AbstractUriTestCase extends TestCase
* any characters. To determine what characters to encode, please refer to
* RFC 3986, Sections 2 and 3.5.
*/
public function testGetFragment($fragment, $expected)
{
public function testGetFragment($fragment, $expected) {
$uri = $this->uri->withFragment($fragment);
$this->assertInstanceOf(UriInterface::class, $uri);
$this->assertSame($expected, $uri->getFragment(), 'Fragment must be normalized according to RFC3986');
}
public function fragmentProvider()
{
public function fragmentProvider() {
return [
'URL with full components' => ['fragment', 'fragment'],
'URL with non-encodable fragment' => ["azAZ0-9/?-._~!$&'()*+,;=:@", "azAZ0-9/?-._~!$&'()*+,;=:@"],
@ -278,8 +259,7 @@ abstract class AbstractUriTestCase extends TestCase
* - If a query is present, it MUST be prefixed by "?".
* - If a fragment is present, it MUST be prefixed by "#".
*/
public function testToString($scheme, $user, $pass, $host, $port, $path, $query, $fragment, $expected)
{
public function testToString($scheme, $user, $pass, $host, $port, $path, $query, $fragment, $expected) {
$uri = $this->createUri()
->withHost($host)
->withScheme($scheme)
@ -295,8 +275,7 @@ abstract class AbstractUriTestCase extends TestCase
'URI string must be normalized according to RFC3986 rules'
);
}
public function stringProvider()
{
public function stringProvider() {
return [
'URL normalized' => [
'scheme' => 'HtTps',
@ -307,7 +286,7 @@ abstract class AbstractUriTestCase extends TestCase
'path' => '/%7ejohndoe/%a1/index.php',
'query' => 'foo.bar=%7evalue',
'fragment' => 'fragment',
'uri' => 'https://iGoR:rAsMuZeN@master.example.com:443/~johndoe/%A1/index.php?foo.bar=~value#fragment'
'uri' => 'https://iGoR:rAsMuZeN@master.example.com:443/~johndoe/%A1/index.php?foo.bar=~value#fragment',
],
'URL without scheme' => [
'scheme' => '',
@ -337,8 +316,7 @@ abstract class AbstractUriTestCase extends TestCase
/**
* @group fragment
*/
public function testRemoveFragment()
{
public function testRemoveFragment() {
$uri = 'http://example.com/path/to/me';
$this->assertSame($uri, (string) $this->createUri($uri.'#doc')->withFragment(''));
}
@ -346,8 +324,7 @@ abstract class AbstractUriTestCase extends TestCase
/**
* @group query
*/
public function testRemoveQuery()
{
public function testRemoveQuery() {
$uri = 'http://example.com/path/to/me';
$this->assertSame($uri, (string) (string) $this->createUri($uri.'?name=value')->withQuery(''));
}
@ -355,8 +332,7 @@ abstract class AbstractUriTestCase extends TestCase
/**
* @group path
*/
public function testRemovePath()
{
public function testRemovePath() {
$uri = 'http://example.com';
$this->assertContains(
(string) $this->createUri($uri.'/path/to/me')->withPath(''),
@ -367,8 +343,7 @@ abstract class AbstractUriTestCase extends TestCase
/**
* @group port
*/
public function testRemovePort()
{
public function testRemovePort() {
$this->assertSame(
'http://example.com/path/to/me',
(string) $this->createUri('http://example.com:81/path/to/me')->withPort(null)
@ -378,8 +353,7 @@ abstract class AbstractUriTestCase extends TestCase
/**
* @group userinfo
*/
public function testRemoveUserInfo()
{
public function testRemoveUserInfo() {
$this->assertSame(
'http://example.com/path/to/me',
(string) $this->createUri('http://user:pass@example.com/path/to/me')->withUserInfo('')
@ -389,8 +363,7 @@ abstract class AbstractUriTestCase extends TestCase
/**
* @group scheme
*/
public function testRemoveScheme()
{
public function testRemoveScheme() {
$this->assertSame(
'//example.com/path/to/me',
(string) $this->createUri('http://example.com/path/to/me')->withScheme('')
@ -400,8 +373,7 @@ abstract class AbstractUriTestCase extends TestCase
/**
* @group authority
*/
public function testRemoveAuthority()
{
public function testRemoveAuthority() {
$uri = 'http://user:login@example.com:82/path?q=v#doc';
$uri_with_host = $this->createUri($uri)
@ -418,14 +390,12 @@ abstract class AbstractUriTestCase extends TestCase
* @group scheme
* @dataProvider withSchemeFailedProvider
*/
public function testWithSchemeFailed($scheme)
{
public function testWithSchemeFailed($scheme) {
$this->expectException(InvalidArgumentException::class);
$this->uri->withScheme($scheme);
}
public function withSchemeFailedProvider()
{
public function withSchemeFailedProvider() {
return [
'invalid char' => ['in,valid'],
'integer like string' => ['123'],
@ -436,14 +406,12 @@ abstract class AbstractUriTestCase extends TestCase
* @group host
* @dataProvider withHostFailedProvider
*/
public function testWithHostFailed($host)
{
public function testWithHostFailed($host) {
$this->expectException(InvalidArgumentException::class);
$this->uri->withHost($host);
}
public function withHostFailedProvider()
{
public function withHostFailedProvider() {
return [
'dot in front' => ['.example.com'],
'hyphen suffix' => ['host.com-'],
@ -469,8 +437,7 @@ abstract class AbstractUriTestCase extends TestCase
/**
* @group host
*/
public function testModificationFailedWithInvalidHost()
{
public function testModificationFailedWithInvalidHost() {
$this->expectException(InvalidArgumentException::class);
$this->createUri('http://example.com')->withHost('?');
}
@ -479,15 +446,12 @@ abstract class AbstractUriTestCase extends TestCase
* @group uri
* @dataProvider invalidURI
*/
public function testCreateFromInvalidUrlKO($uri)
{
public function testCreateFromInvalidUrlKO($uri) {
$this->expectException(InvalidArgumentException::class);
$this->createUri($uri);
}
public function invalidURI()
{
public function invalidURI() {
return [
['http://user@:80'],
];
@ -496,8 +460,7 @@ abstract class AbstractUriTestCase extends TestCase
/**
* @group uri
*/
public function testEmptyValueDetection()
{
public function testEmptyValueDetection() {
$expected = '//0:0@0/0?0#0';
$this->assertSame($expected, (string) $this->createUri($expected));
}
@ -506,9 +469,8 @@ abstract class AbstractUriTestCase extends TestCase
* @group path
* @group uri
*/
public function testPathDetection()
{
public function testPathDetection() {
$expected = 'foo/bar:';
$this->assertSame($expected, $this->createUri($expected)->getPath());
}
}
}

2
tests/cases/Util/UrlTest.php

@ -14,4 +14,4 @@ class UrlTest extends AbstractUriTestCase {
protected function createUri($uri = '') {
return new Url($uri);
}
}
}

5
vendor-bin/csfixer/composer.json

@ -0,0 +1,5 @@
{
"require-dev": {
"friendsofphp/php-cs-fixer": "^2.16"
}
}

1383
vendor-bin/csfixer/composer.lock

File diff suppressed because it is too large
Loading…
Cancel
Save