diff --git a/composer.json b/composer.json
index f3e7561..f5a1fbb 100644
--- a/composer.json
+++ b/composer.json
@@ -3,14 +3,16 @@
"description": "Abstraction layer for constructing arbitrary HTML tags and documents in PHP",
"type": "library",
"require": {
- "php": ">=8.1",
+ "php": ">=8.1",
"myclabs/deep-copy": "^1"
},
"license": "MIT",
- "authors": [{
- "name": "Joby Elliott",
- "email": "joby@byjoby.com"
- }],
+ "authors": [
+ {
+ "name": "Joby Elliott",
+ "email": "joby@byjoby.com"
+ }
+ ],
"minimum-stability": "dev",
"prefer-stable": true,
"autoload": {
@@ -25,10 +27,12 @@
},
"scripts": {
"test": "phpunit",
- "stan": "phpstan"
+ "stan": "phpstan",
+ "sniff": "phpcs"
},
"require-dev": {
"phpstan/phpstan": "^1.9",
- "phpunit/phpunit": "^9.5"
+ "phpunit/phpunit": "^9.5",
+ "squizlabs/php_codesniffer": "^3.7"
}
-}
+}
\ No newline at end of file
diff --git a/phpcs.xml b/phpcs.xml
new file mode 100644
index 0000000..5064e75
--- /dev/null
+++ b/phpcs.xml
@@ -0,0 +1,19 @@
+
+
+ Coding Standard
+
+ src
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/AbstractParser.php b/src/AbstractParser.php
index 5db0afd..73eef23 100644
--- a/src/AbstractParser.php
+++ b/src/AbstractParser.php
@@ -4,7 +4,6 @@ namespace ByJoby\HTML;
use ByJoby\HTML\Containers\Fragment;
use ByJoby\HTML\Containers\FragmentInterface;
-use ByJoby\HTML\Containers\GenericHtmlDocument;
use ByJoby\HTML\Containers\HtmlDocumentInterface;
use ByJoby\HTML\Nodes\CData;
use ByJoby\HTML\Nodes\CDataInterface;
@@ -109,8 +108,10 @@ abstract class AbstractParser
{
// build object
$class = $this->tagClass($node->tagName);
- if (!$class) return null;
- $tag = new $class;
+ if (!$class) {
+ return null;
+ }
+ $tag = new $class();
// tool for settin gup content tags
if ($tag instanceof ContentTagInterface) {
$tag->setContent($node->textContent);
@@ -124,12 +125,11 @@ abstract class AbstractParser
protected function processAttributes(DOMElement $node, TagInterface $tag): void
{
- if (!$node->attributes) return;
/** @var array */
$attributes = [];
// absorb attributes
/** @var DOMNode $attribute */
- foreach ($node->attributes as $attribute) {
+ foreach ($node->attributes ?? [] as $attribute) {
if ($attribute->nodeValue) {
$attributes[$attribute->nodeName] = $attribute->nodeValue;
} else {
@@ -148,10 +148,9 @@ abstract class AbstractParser
// make an effort to set ID
try {
$tag->attributes()["$k"] = $v;
- }
- // it is correct to ignore attributes that are unsettable
- catch (\Throwable $th) { // @codeCoverageIgnore
+ } catch (\Throwable $th) { // @codeCoverageIgnore
// does nothing
+ // it is correct to ignore attributes that are unsettable
}
}
}
diff --git a/src/Containers/ContainerGroup.php b/src/Containers/ContainerGroup.php
index 024175a..993c499 100644
--- a/src/Containers/ContainerGroup.php
+++ b/src/Containers/ContainerGroup.php
@@ -29,7 +29,7 @@ class ContainerGroup implements ContainerInterface, NodeInterface
protected $limit = 0;
/**
- * @param int $limit
+ * @param int $limit
* @return ContainerGroup
*/
public static function catchAll(int $limit = 0): ContainerGroup
@@ -44,8 +44,8 @@ class ContainerGroup implements ContainerInterface, NodeInterface
/**
* @template C of T
- * @param class-string $class
- * @param int $limit
+ * @param class-string $class
+ * @param int $limit
* @return ContainerGroup
*/
public static function ofClass(string $class, int $limit = 0): ContainerGroup
@@ -60,7 +60,7 @@ class ContainerGroup implements ContainerInterface, NodeInterface
/**
* @param string $tag
- * @param int $limit
+ * @param int $limit
* @return ContainerGroup
*/
public static function ofTag(string $tag, int $limit = 0): ContainerGroup
diff --git a/src/Containers/Fragment.php b/src/Containers/Fragment.php
index 66c14c6..b9aeca2 100644
--- a/src/Containers/Fragment.php
+++ b/src/Containers/Fragment.php
@@ -16,7 +16,9 @@ class Fragment implements FragmentInterface
*/
public function __construct(null|array|Traversable $children = null)
{
- if (!$children) return;
+ if (!$children) {
+ return;
+ }
foreach ($children as $child) {
$this->addChild($child);
}
diff --git a/src/ContentCategories/SectioningRoot.php b/src/ContentCategories/SectioningRoot.php
index 4552771..4657bbc 100644
--- a/src/ContentCategories/SectioningRoot.php
+++ b/src/ContentCategories/SectioningRoot.php
@@ -4,4 +4,4 @@ namespace ByJoby\HTML\ContentCategories;
interface SectioningRoot
{
-}
\ No newline at end of file
+}
diff --git a/src/Helpers/Attributes.php b/src/Helpers/Attributes.php
index d014900..405fbcd 100644
--- a/src/Helpers/Attributes.php
+++ b/src/Helpers/Attributes.php
@@ -11,7 +11,7 @@ use Traversable;
/**
* Holds and validates a set of HTML attribute name/value pairs for use in tags.
- *
+ *
* @implements ArrayAccess
* @implements IteratorAggregate
*/
@@ -25,48 +25,59 @@ class Attributes implements IteratorAggregate, ArrayAccess
protected $disallowed = [];
/**
- * @param null|array $array
+ * @param null|array $array
* @param array $disallowed
- * @return void
+ * @return void
*/
public function __construct(null|array $array = null, $disallowed = [])
{
$this->disallowed = $disallowed;
- if (!$array) return;
+ if (!$array) {
+ return;
+ }
foreach ($array as $key => $value) {
$this[$key] = $value;
}
}
- function offsetExists(mixed $offset): bool
+ public function offsetExists(mixed $offset): bool
{
$offset = static::sanitizeOffset($offset);
return isset($this->array[$offset]);
}
- function offsetGet(mixed $offset): mixed
+ public function offsetGet(mixed $offset): mixed
{
$offset = static::sanitizeOffset($offset);
return @$this->array[$offset];
}
- function offsetSet(mixed $offset, mixed $value): void
+ public function offsetSet(mixed $offset, mixed $value): void
{
- if (!$offset || !trim($offset)) throw new Exception('Attribute name must be specified when setting');
+ if (!$offset || !trim($offset)) {
+ throw new Exception('Attribute name must be specified when setting');
+ }
$offset = static::sanitizeOffset($offset);
- if (in_array($offset, $this->disallowed)) throw new Exception('Setting attribute is disallowed');
- if (!isset($this->array[$offset])) $this->sorted = false;
+ if (in_array($offset, $this->disallowed)) {
+ throw new Exception('Setting attribute is disallowed');
+ }
+ if (!isset($this->array[$offset])) {
+ $this->sorted = false;
+ }
$this->array[$offset] = $value;
}
public function string(string $offset): null|string
{
$value = $this->offsetGet($offset);
- if (is_string($value)) return $value;
- else return null;
+ if (is_string($value)) {
+ return $value;
+ } else {
+ return null;
+ }
}
- function offsetUnset(mixed $offset): void
+ public function offsetUnset(mixed $offset): void
{
$offset = static::sanitizeOffset($offset);
unset($this->array[$offset]);
@@ -75,7 +86,7 @@ class Attributes implements IteratorAggregate, ArrayAccess
/**
* @return array
*/
- function getArray(): array
+ public function getArray(): array
{
if (!$this->sorted) {
ksort($this->array);
@@ -84,7 +95,7 @@ class Attributes implements IteratorAggregate, ArrayAccess
return $this->array;
}
- function getIterator(): Traversable
+ public function getIterator(): Traversable
{
return new ArrayIterator($this->getArray());
}
@@ -93,7 +104,9 @@ class Attributes implements IteratorAggregate, ArrayAccess
{
$offset = trim($offset);
$offset = strtolower($offset);
- if (preg_match('/[\t\n\f \/>"\'=]/', $offset)) throw new Exception('Invalid character in attribute name');
+ if (preg_match('/[\t\n\f \/>"\'=]/', $offset)) {
+ throw new Exception('Invalid character in attribute name');
+ }
return $offset;
}
}
diff --git a/src/Helpers/Classes.php b/src/Helpers/Classes.php
index 3283579..4c46a75 100644
--- a/src/Helpers/Classes.php
+++ b/src/Helpers/Classes.php
@@ -24,7 +24,9 @@ class Classes implements Countable
*/
public function __construct(null|array|Traversable $array = null, bool $no_exception = true)
{
- if (!$array) return;
+ if (!$array) {
+ return;
+ }
foreach ($array as $class) {
$this->add($class, $no_exception);
}
@@ -34,7 +36,9 @@ class Classes implements Countable
{
foreach (explode(' ', $class_string) as $class) {
$class = trim($class);
- if ($class) $this->add($class);
+ if ($class) {
+ $this->add($class);
+ }
}
}
@@ -46,7 +50,7 @@ class Classes implements Countable
/**
* @return array
*/
- function getArray(): array
+ public function getArray(): array
{
if (!$this->sorted) {
sort($this->classes);
@@ -60,8 +64,11 @@ class Classes implements Countable
try {
$class = static::sanitizeClassName($class, true);
} catch (\Throwable $th) {
- if ($no_exception) return $this;
- else throw $th;
+ if ($no_exception) {
+ return $this;
+ } else {
+ throw $th;
+ }
}
if (!in_array($class, $this->classes)) {
$this->classes[] = $class;
@@ -91,7 +98,9 @@ class Classes implements Countable
protected static function sanitizeClassName(string $class, bool $validate = false): string
{
$class = trim($class);
- if ($validate && !preg_match('/^[_\-a-z][_\-a-z0-9]*$/i', $class)) throw new Exception('Invalid class name');
+ if ($validate && !preg_match('/^[_\-a-z][_\-a-z0-9]*$/i', $class)) {
+ throw new Exception('Invalid class name');
+ }
return $class;
}
}
diff --git a/src/Helpers/Styles.php b/src/Helpers/Styles.php
index 18affe4..5dff577 100644
--- a/src/Helpers/Styles.php
+++ b/src/Helpers/Styles.php
@@ -8,13 +8,13 @@ use Stringable;
use Traversable;
/**
- * A key difference in strategy between this class and Attributes or Classes is
+ * A key difference in strategy between this class and Attributes or Classes is
* that it does not make significant validation attempts. CSS is an evolving
* language, and it would be a fool's errand to try and thoroughly validate it.
- *
+ *
* To that end, this class is very accepting of not-obviously-malformed property
* names and values.
- *
+ *
* @implements ArrayAccess
*/
class Styles implements Countable, ArrayAccess, Stringable
@@ -29,7 +29,9 @@ class Styles implements Countable, ArrayAccess, Stringable
*/
public function __construct(null|array|Traversable $classes = null)
{
- if (!$classes) return;
+ if (!$classes) {
+ return;
+ }
foreach ($classes as $name => $value) {
$this[$name] = $value;
}
@@ -39,7 +41,9 @@ class Styles implements Countable, ArrayAccess, Stringable
{
foreach (explode(';', $css_string) as $rule) {
$rule = explode(':', trim($rule));
- if (count($rule) == 2) $this[$rule[0]] = $rule[1];
+ if (count($rule) == 2) {
+ $this[$rule[0]] = $rule[1];
+ }
}
}
@@ -50,8 +54,7 @@ class Styles implements Countable, ArrayAccess, Stringable
public function offsetExists(mixed $offset): bool
{
- if (!$offset) return false;
- return isset($this->styles[$offset]);
+ return @isset($this->styles[$offset]);
}
public function offsetGet(mixed $offset): mixed
@@ -61,13 +64,16 @@ class Styles implements Countable, ArrayAccess, Stringable
public function offsetSet(mixed $offset, mixed $value): void
{
- if (!$offset) return;
- if ($value) $value = trim($value);
- if (!$value) unset($this->styles[$offset]);
- else {
- if (!static::validate($offset, $value)) return;
- if (!isset($this->styles[$offset])) $this->sorted = false;
- $this->styles[$offset] = $value;
+ if (!$value) {
+ unset($this->styles[$offset]);
+ } else {
+ if (!static::validate($offset, $value)) {
+ return;
+ }
+ if (!isset($this->styles[$offset])) {
+ $this->sorted = false;
+ }
+ $this->styles[$offset] = trim($value);
}
}
@@ -97,15 +103,19 @@ class Styles implements Countable, ArrayAccess, Stringable
return implode(';', $styles);
}
- protected static function validate(null|string $property, null|string $value): bool
+ protected static function validate(null|string $property, string $value): bool
{
- if (!$property) return false;
- elseif (!preg_match('/[a-z]/', $property)) return false;
+ if (!$property) {
+ return false;
+ } elseif (!preg_match('/[a-z]/', $property)) {
+ return false;
+ }
- if ($value) $value = trim($value);
- if (!$value) return false;
- elseif (str_contains($value, ';')) return false;
- elseif (str_contains($value, ':')) return false;
+ if (str_contains($value, ';')) {
+ return false;
+ } elseif (str_contains($value, ':')) {
+ return false;
+ }
return true;
}
diff --git a/src/Html5/DocumentTags/HeadTag.php b/src/Html5/DocumentTags/HeadTag.php
index 9d4bfc6..da61119 100644
--- a/src/Html5/DocumentTags/HeadTag.php
+++ b/src/Html5/DocumentTags/HeadTag.php
@@ -10,10 +10,10 @@ use ByJoby\HTML\Traits\GroupedContainerTrait;
class HeadTag extends AbstractGroupedTag implements HeadTagInterface
{
- const TAG = 'head';
-
use GroupedContainerTrait;
+ const TAG = 'head';
+
/** @var ContainerGroup */
protected $title;
@@ -22,7 +22,7 @@ class HeadTag extends AbstractGroupedTag implements HeadTagInterface
parent::__construct();
$this->title = ContainerGroup::ofClass(TitleTagInterface::class, 1);
$this->addGroup($this->title);
- $this->addChild(new TitleTag);
+ $this->addChild(new TitleTag());
$this->addGroup(ContainerGroup::ofTag('meta'));
$this->addGroup(ContainerGroup::ofTag('base', 1));
$this->addGroup(ContainerGroup::ofTag('style'));
diff --git a/src/Html5/DocumentTags/HtmlTag.php b/src/Html5/DocumentTags/HtmlTag.php
index ab15c2e..7e99e9d 100644
--- a/src/Html5/DocumentTags/HtmlTag.php
+++ b/src/Html5/DocumentTags/HtmlTag.php
@@ -11,10 +11,10 @@ use ByJoby\HTML\Traits\GroupedContainerTrait;
class HtmlTag extends AbstractGroupedTag implements HtmlTagInterface
{
- const TAG = 'html';
-
use GroupedContainerTrait;
+ const TAG = 'html';
+
/** @var ContainerGroup */
protected $head;
/** @var ContainerGroup */
@@ -27,8 +27,8 @@ class HtmlTag extends AbstractGroupedTag implements HtmlTagInterface
$this->body = ContainerGroup::ofClass(BodyTagInterface::class, 1);
$this->addGroup($this->head);
$this->addGroup($this->body);
- $this->addChild(new HeadTag);
- $this->addChild(new BodyTag);
+ $this->addChild(new HeadTag());
+ $this->addChild(new BodyTag());
}
public function head(): HeadTagInterface
diff --git a/src/Html5/Html5Document.php b/src/Html5/Html5Document.php
index e92fa31..795a42a 100644
--- a/src/Html5/Html5Document.php
+++ b/src/Html5/Html5Document.php
@@ -27,8 +27,8 @@ class Html5Document implements HtmlDocumentInterface
$this->html = ContainerGroup::ofClass(HtmlTagInterface::class, 1);
$this->addGroup($this->doctype);
$this->addGroup($this->html);
- $this->addChild(new Doctype);
- $this->addChild(new HtmlTag);
+ $this->addChild(new Doctype());
+ $this->addChild(new HtmlTag());
}
public function doctype(): DoctypeInterface
diff --git a/src/Html5/Tags/BaseTag.php b/src/Html5/Tags/BaseTag.php
index da499d1..d55859a 100644
--- a/src/Html5/Tags/BaseTag.php
+++ b/src/Html5/Tags/BaseTag.php
@@ -16,8 +16,11 @@ class BaseTag extends AbstractTag implements MetadataContent
public function setHref(null|string $href): static
{
- if (!$href) $this->attributes()['href'] = false;
- else $this->attributes()['href'] = $href;
+ if (!$href) {
+ $this->attributes()['href'] = false;
+ } else {
+ $this->attributes()['href'] = $href;
+ }
return $this;
}
@@ -34,8 +37,11 @@ class BaseTag extends AbstractTag implements MetadataContent
public function setTarget(null|string $target): static
{
- if (!$target) $this->attributes()['target'] = false;
- else $this->attributes()['target'] = $target;
+ if (!$target) {
+ $this->attributes()['target'] = false;
+ } else {
+ $this->attributes()['target'] = $target;
+ }
return $this;
}
diff --git a/src/Html5/Tags/LinkTag.php b/src/Html5/Tags/LinkTag.php
index b8cff37..99a4804 100644
--- a/src/Html5/Tags/LinkTag.php
+++ b/src/Html5/Tags/LinkTag.php
@@ -16,8 +16,11 @@ class LinkTag extends AbstractTag implements MetadataContent
public function setRel(null|string $rel): static
{
- if (!$rel) $this->attributes()['rel'] = false;
- else $this->attributes()['rel'] = $rel;
+ if (!$rel) {
+ $this->attributes()['rel'] = false;
+ } else {
+ $this->attributes()['rel'] = $rel;
+ }
return $this;
}
@@ -34,8 +37,11 @@ class LinkTag extends AbstractTag implements MetadataContent
public function setAs(null|string $as): static
{
- if (!$as) $this->attributes()['as'] = false;
- else $this->attributes()['as'] = $as;
+ if (!$as) {
+ $this->attributes()['as'] = false;
+ } else {
+ $this->attributes()['as'] = $as;
+ }
return $this;
}
@@ -52,8 +58,11 @@ class LinkTag extends AbstractTag implements MetadataContent
public function setCrossorigin(null|string $crossorigin): static
{
- if (!$crossorigin) $this->attributes()['crossorigin'] = false;
- else $this->attributes()['crossorigin'] = $crossorigin;
+ if (!$crossorigin) {
+ $this->attributes()['crossorigin'] = false;
+ } else {
+ $this->attributes()['crossorigin'] = $crossorigin;
+ }
return $this;
}
@@ -70,8 +79,11 @@ class LinkTag extends AbstractTag implements MetadataContent
public function setHref(null|string $href): static
{
- if (!$href) $this->attributes()['href'] = false;
- else $this->attributes()['href'] = $href;
+ if (!$href) {
+ $this->attributes()['href'] = false;
+ } else {
+ $this->attributes()['href'] = $href;
+ }
return $this;
}
@@ -88,8 +100,11 @@ class LinkTag extends AbstractTag implements MetadataContent
public function setHreflang(null|string $hreflang): static
{
- if (!$hreflang) $this->attributes()['hreflang'] = false;
- else $this->attributes()['hreflang'] = $hreflang;
+ if (!$hreflang) {
+ $this->attributes()['hreflang'] = false;
+ } else {
+ $this->attributes()['hreflang'] = $hreflang;
+ }
return $this;
}
@@ -106,8 +121,11 @@ class LinkTag extends AbstractTag implements MetadataContent
public function setImagesizes(null|string $imagesizes): static
{
- if (!$imagesizes) $this->attributes()['imagesizes'] = false;
- else $this->attributes()['imagesizes'] = $imagesizes;
+ if (!$imagesizes) {
+ $this->attributes()['imagesizes'] = false;
+ } else {
+ $this->attributes()['imagesizes'] = $imagesizes;
+ }
return $this;
}
@@ -124,8 +142,11 @@ class LinkTag extends AbstractTag implements MetadataContent
public function setImagesrcset(null|string $imagesrcset): static
{
- if (!$imagesrcset) $this->attributes()['imagesrcset'] = false;
- else $this->attributes()['imagesrcset'] = $imagesrcset;
+ if (!$imagesrcset) {
+ $this->attributes()['imagesrcset'] = false;
+ } else {
+ $this->attributes()['imagesrcset'] = $imagesrcset;
+ }
return $this;
}
@@ -142,8 +163,11 @@ class LinkTag extends AbstractTag implements MetadataContent
public function setIntegrity(null|string $integrity): static
{
- if (!$integrity) $this->attributes()['integrity'] = false;
- else $this->attributes()['integrity'] = $integrity;
+ if (!$integrity) {
+ $this->attributes()['integrity'] = false;
+ } else {
+ $this->attributes()['integrity'] = $integrity;
+ }
return $this;
}
@@ -160,8 +184,11 @@ class LinkTag extends AbstractTag implements MetadataContent
public function setMedia(null|string $media): static
{
- if (!$media) $this->attributes()['media'] = false;
- else $this->attributes()['media'] = $media;
+ if (!$media) {
+ $this->attributes()['media'] = false;
+ } else {
+ $this->attributes()['media'] = $media;
+ }
return $this;
}
@@ -178,8 +205,11 @@ class LinkTag extends AbstractTag implements MetadataContent
public function setReferrerpolicy(null|string $referrerpolicy): static
{
- if (!$referrerpolicy) $this->attributes()['referrerpolicy'] = false;
- else $this->attributes()['referrerpolicy'] = $referrerpolicy;
+ if (!$referrerpolicy) {
+ $this->attributes()['referrerpolicy'] = false;
+ } else {
+ $this->attributes()['referrerpolicy'] = $referrerpolicy;
+ }
return $this;
}
@@ -196,8 +226,11 @@ class LinkTag extends AbstractTag implements MetadataContent
public function setType(null|string $type): static
{
- if (!$type) $this->attributes()['type'] = false;
- else $this->attributes()['type'] = $type;
+ if (!$type) {
+ $this->attributes()['type'] = false;
+ } else {
+ $this->attributes()['type'] = $type;
+ }
return $this;
}
diff --git a/src/Html5/Tags/MetaTag.php b/src/Html5/Tags/MetaTag.php
index 2a9dc62..07d6709 100644
--- a/src/Html5/Tags/MetaTag.php
+++ b/src/Html5/Tags/MetaTag.php
@@ -16,8 +16,11 @@ class MetaTag extends AbstractTag implements MetadataContent
public function setName(null|string $name): static
{
- if (!$name) $this->attributes()['name'] = false;
- else $this->attributes()['name'] = $name;
+ if (!$name) {
+ $this->attributes()['name'] = false;
+ } else {
+ $this->attributes()['name'] = $name;
+ }
return $this;
}
@@ -34,8 +37,11 @@ class MetaTag extends AbstractTag implements MetadataContent
public function setContent(null|string $content): static
{
- if (!$content) $this->attributes()['content'] = false;
- else $this->attributes()['content'] = $content;
+ if (!$content) {
+ $this->attributes()['content'] = false;
+ } else {
+ $this->attributes()['content'] = $content;
+ }
return $this;
}
@@ -52,8 +58,11 @@ class MetaTag extends AbstractTag implements MetadataContent
public function setHttpEquiv(null|string $http_equiv): static
{
- if (!$http_equiv) $this->attributes()['http-equiv'] = false;
- else $this->attributes()['http-equiv'] = $http_equiv;
+ if (!$http_equiv) {
+ $this->attributes()['http-equiv'] = false;
+ } else {
+ $this->attributes()['http-equiv'] = $http_equiv;
+ }
return $this;
}
@@ -70,8 +79,11 @@ class MetaTag extends AbstractTag implements MetadataContent
public function setCharset(null|string $charset): static
{
- if (!$charset) $this->attributes()['charset'] = false;
- else $this->attributes()['charset'] = $charset;
+ if (!$charset) {
+ $this->attributes()['charset'] = false;
+ } else {
+ $this->attributes()['charset'] = $charset;
+ }
return $this;
}
diff --git a/src/Html5/Tags/ScriptTag.php b/src/Html5/Tags/ScriptTag.php
index 1e71fd2..a60850c 100644
--- a/src/Html5/Tags/ScriptTag.php
+++ b/src/Html5/Tags/ScriptTag.php
@@ -40,8 +40,11 @@ class ScriptTag extends AbstractContentTag implements MetadataContent, PhrasingC
public function setCrossorigin(null|string $crossorigin): static
{
- if (!$crossorigin) $this->attributes()['crossorigin'] = false;
- else $this->attributes()['crossorigin'] = $crossorigin;
+ if (!$crossorigin) {
+ $this->attributes()['crossorigin'] = false;
+ } else {
+ $this->attributes()['crossorigin'] = $crossorigin;
+ }
return $this;
}
@@ -58,8 +61,11 @@ class ScriptTag extends AbstractContentTag implements MetadataContent, PhrasingC
public function setIntegrity(null|string $integrity): static
{
- if (!$integrity) $this->attributes()['integrity'] = false;
- else $this->attributes()['integrity'] = $integrity;
+ if (!$integrity) {
+ $this->attributes()['integrity'] = false;
+ } else {
+ $this->attributes()['integrity'] = $integrity;
+ }
return $this;
}
@@ -87,8 +93,11 @@ class ScriptTag extends AbstractContentTag implements MetadataContent, PhrasingC
public function setNonce(null|string $nonce): static
{
- if (!$nonce) $this->attributes()['nonce'] = false;
- else $this->attributes()['nonce'] = $nonce;
+ if (!$nonce) {
+ $this->attributes()['nonce'] = false;
+ } else {
+ $this->attributes()['nonce'] = $nonce;
+ }
return $this;
}
@@ -105,8 +114,11 @@ class ScriptTag extends AbstractContentTag implements MetadataContent, PhrasingC
public function setReferrerpolicy(null|string $referrerpolicy): static
{
- if (!$referrerpolicy) $this->attributes()['referrerpolicy'] = false;
- else $this->attributes()['referrerpolicy'] = $referrerpolicy;
+ if (!$referrerpolicy) {
+ $this->attributes()['referrerpolicy'] = false;
+ } else {
+ $this->attributes()['referrerpolicy'] = $referrerpolicy;
+ }
return $this;
}
@@ -123,8 +135,11 @@ class ScriptTag extends AbstractContentTag implements MetadataContent, PhrasingC
public function setSrc(null|string $src): static
{
- if (!$src) $this->attributes()['src'] = false;
- else $this->attributes()['src'] = $src;
+ if (!$src) {
+ $this->attributes()['src'] = false;
+ } else {
+ $this->attributes()['src'] = $src;
+ }
return $this;
}
@@ -141,8 +156,11 @@ class ScriptTag extends AbstractContentTag implements MetadataContent, PhrasingC
public function setType(null|string $type): static
{
- if (!$type) $this->attributes()['type'] = false;
- else $this->attributes()['type'] = $type;
+ if (!$type) {
+ $this->attributes()['type'] = false;
+ } else {
+ $this->attributes()['type'] = $type;
+ }
return $this;
}
diff --git a/src/Html5/Tags/StyleTag.php b/src/Html5/Tags/StyleTag.php
index 9d2656a..3993eb4 100644
--- a/src/Html5/Tags/StyleTag.php
+++ b/src/Html5/Tags/StyleTag.php
@@ -16,8 +16,11 @@ class StyleTag extends AbstractContentTag implements MetadataContent
public function setMedia(null|string $media): static
{
- if (!$media) $this->attributes()['media'] = false;
- else $this->attributes()['media'] = $media;
+ if (!$media) {
+ $this->attributes()['media'] = false;
+ } else {
+ $this->attributes()['media'] = $media;
+ }
return $this;
}
@@ -34,8 +37,11 @@ class StyleTag extends AbstractContentTag implements MetadataContent
public function setNonce(null|string $nonce): static
{
- if (!$nonce) $this->attributes()['nonce'] = false;
- else $this->attributes()['nonce'] = $nonce;
+ if (!$nonce) {
+ $this->attributes()['nonce'] = false;
+ } else {
+ $this->attributes()['nonce'] = $nonce;
+ }
return $this;
}
diff --git a/src/Html5/TextContentTags/BlockquoteTag.php b/src/Html5/TextContentTags/BlockquoteTag.php
index a3569cc..141e432 100644
--- a/src/Html5/TextContentTags/BlockquoteTag.php
+++ b/src/Html5/TextContentTags/BlockquoteTag.php
@@ -18,8 +18,11 @@ class BlockquoteTag extends AbstractContainerTag implements FlowContent, Section
public function setCite(null|string $cite): static
{
- if (!$cite) $this->attributes()['cite'] = false;
- else $this->attributes()['cite'] = $cite;
+ if (!$cite) {
+ $this->attributes()['cite'] = false;
+ } else {
+ $this->attributes()['cite'] = $cite;
+ }
return $this;
}
diff --git a/src/Html5/TextContentTags/OlTag.php b/src/Html5/TextContentTags/OlTag.php
index 3c8051e..63afc4c 100644
--- a/src/Html5/TextContentTags/OlTag.php
+++ b/src/Html5/TextContentTags/OlTag.php
@@ -28,7 +28,7 @@ class OlTag extends AbstractContainerTag implements FlowContent, DisplayBlock
public function start(): null|int
{
- if (isset($this->attributes['start'])) {
+ if ($this->attributes()['start']) {
return intval($this->attributes()->string('start'));
} else {
return null;
@@ -37,8 +37,11 @@ class OlTag extends AbstractContainerTag implements FlowContent, DisplayBlock
public function setStart(null|int $start): static
{
- if (!$start) $this->attributes()['start'] = false;
- else $this->attributes()['start'] = strval($start);
+ if (!$start) {
+ $this->attributes()['start'] = false;
+ } else {
+ $this->attributes()['start'] = strval($start);
+ }
return $this;
}
diff --git a/src/Tags/AbstractContainerTag.php b/src/Tags/AbstractContainerTag.php
index 7618f89..0826d65 100644
--- a/src/Tags/AbstractContainerTag.php
+++ b/src/Tags/AbstractContainerTag.php
@@ -8,21 +8,25 @@ use ByJoby\HTML\Traits\NodeTrait;
abstract class AbstractContainerTag extends AbstractTag implements ContainerTagInterface
{
- use NodeTrait, TagTrait;
+ use NodeTrait;
+ use TagTrait;
use ContainerTrait;
public function __toString(): string
{
$openingTag = sprintf('<%s>', implode(' ', $this->openingTagStrings()));
$closingTag = sprintf('%s>', $this->tag());
- if (!$this->children()) return $openingTag . $closingTag;
- else return implode(
- PHP_EOL,
- [
+ if (!$this->children()) {
+ return $openingTag . $closingTag;
+ } else {
+ return implode(
+ PHP_EOL,
+ [
$openingTag,
implode(PHP_EOL, $this->children()),
$closingTag
- ]
- );
+ ]
+ );
+ }
}
}
diff --git a/src/Tags/AbstractContentTag.php b/src/Tags/AbstractContentTag.php
index 93d33c5..d1734b3 100644
--- a/src/Tags/AbstractContentTag.php
+++ b/src/Tags/AbstractContentTag.php
@@ -25,14 +25,17 @@ abstract class AbstractContentTag extends AbstractTag implements ContentTagInter
$openingTag = sprintf('<%s>', implode(' ', $this->openingTagStrings()));
$closingTag = sprintf('%s>', $this->tag());
$content = $this->content();
- if (!$content) return $openingTag . $closingTag;
- else return implode(
- PHP_EOL,
- [
+ if (!$content) {
+ return $openingTag . $closingTag;
+ } else {
+ return implode(
+ PHP_EOL,
+ [
$openingTag,
$content,
$closingTag
- ]
- );
+ ]
+ );
+ }
}
}
diff --git a/src/Tags/AbstractGroupedTag.php b/src/Tags/AbstractGroupedTag.php
index 4188ca3..1a89305 100644
--- a/src/Tags/AbstractGroupedTag.php
+++ b/src/Tags/AbstractGroupedTag.php
@@ -19,14 +19,17 @@ abstract class AbstractGroupedTag extends AbstractTag implements ContainerTagInt
return !!$group->children();
}
);
- if (!$groups) return $openingTag . $closingTag;
- else return implode(
- PHP_EOL,
- [
+ if (!$groups) {
+ return $openingTag . $closingTag;
+ } else {
+ return implode(
+ PHP_EOL,
+ [
$openingTag,
implode(PHP_EOL, $groups),
$closingTag
- ]
- );
+ ]
+ );
+ }
}
}
diff --git a/src/Tags/AbstractTag.php b/src/Tags/AbstractTag.php
index 8ae7706..aed0ed5 100644
--- a/src/Tags/AbstractTag.php
+++ b/src/Tags/AbstractTag.php
@@ -7,7 +7,8 @@ use ByJoby\HTML\Traits\NodeTrait;
abstract class AbstractTag implements TagInterface
{
- use NodeTrait, TagTrait;
+ use NodeTrait;
+ use TagTrait;
public function tag(): string
{
diff --git a/src/Tags/ContainerTagInterface.php b/src/Tags/ContainerTagInterface.php
index 6d1af2f..2f7afc7 100644
--- a/src/Tags/ContainerTagInterface.php
+++ b/src/Tags/ContainerTagInterface.php
@@ -9,7 +9,7 @@ use ByJoby\HTML\ContainerInterface;
* child tags. They can all have tags added and removed from them as well.
* Container Tags always render as a full opening and closing tag, even when
* they are empty.
- *
+ *
* @package ByJoby\HTML\Tags
*/
interface ContainerTagInterface extends TagInterface, ContainerInterface
diff --git a/src/Tags/ContentTagInterface.php b/src/Tags/ContentTagInterface.php
index 9347f3a..13f4469 100644
--- a/src/Tags/ContentTagInterface.php
+++ b/src/Tags/ContentTagInterface.php
@@ -8,7 +8,7 @@ use Stringable;
* Content Tags contain a single string or Stringable, which may or may not be
* valid HTML. They render as full opening/closing HTML tags which wrap the
* content stored in the tag.
- *
+ *
* @package ByJoby\HTML\Tags
*/
interface ContentTagInterface extends TagInterface
diff --git a/src/Tags/TagInterface.php b/src/Tags/TagInterface.php
index ffbcf21..b0884a1 100644
--- a/src/Tags/TagInterface.php
+++ b/src/Tags/TagInterface.php
@@ -11,7 +11,7 @@ use Stringable;
/**
* Simple tags represent self-closing tags that cannot contain anything else
* within them.
- *
+ *
* @package ByJoby\HTML\Tags
*/
interface TagInterface extends NodeInterface
diff --git a/src/Traits/ContainerTrait.php b/src/Traits/ContainerTrait.php
index 5d50ff9..2f25ca0 100644
--- a/src/Traits/ContainerTrait.php
+++ b/src/Traits/ContainerTrait.php
@@ -35,8 +35,11 @@ trait ContainerTrait
bool $skip_sanitize = false
): static {
$child = $this->prepareChildToAdd($child, $skip_sanitize);
- if ($prepend) array_unshift($this->children, $child);
- else $this->children[] = $child;
+ if ($prepend) {
+ array_unshift($this->children, $child);
+ } else {
+ $this->children[] = $child;
+ }
return $this;
}
@@ -46,8 +49,11 @@ trait ContainerTrait
$this->children = array_filter(
$this->children,
function (NodeInterface $e) use ($child) {
- if (is_object($child)) $keep = $e !== $child;
- else $keep = $e != $child;
+ if (is_object($child)) {
+ $keep = $e !== $child;
+ } else {
+ $keep = $e != $child;
+ }
if (!$keep) {
$e->setParent(null);
}
@@ -89,8 +95,11 @@ trait ContainerTrait
{
// turn strings into nodes
if (!($child instanceof NodeInterface)) {
- if ($skip_sanitize) $child = new UnsanitizedText($child);
- else $child = new Text($child);
+ if ($skip_sanitize) {
+ $child = new UnsanitizedText($child);
+ } else {
+ $child = new Text($child);
+ }
}
// remove from parent, move it here, and return
if ($parent = $child->parent()) {
@@ -104,11 +113,15 @@ trait ContainerTrait
{
if ($child instanceof NodeInterface) {
foreach ($this->children as $i => $v) {
- if ($v === $child) return $i;
+ if ($v === $child) {
+ return $i;
+ }
}
} else {
foreach ($this->children as $i => $v) {
- if ($v == $child) return $i;
+ if ($v == $child) {
+ return $i;
+ }
}
}
return null;
diff --git a/src/Traits/GroupedContainerTrait.php b/src/Traits/GroupedContainerTrait.php
index 0ec88e2..6283895 100644
--- a/src/Traits/GroupedContainerTrait.php
+++ b/src/Traits/GroupedContainerTrait.php
@@ -21,7 +21,7 @@ trait GroupedContainerTrait
}
/**
- * @return array>
+ * @return array>
*/
public function groups(): array
{
@@ -36,7 +36,9 @@ trait GroupedContainerTrait
public function willAccept(NodeInterface|Stringable|string $child): bool
{
foreach ($this->groups() as $group) {
- if ($group->willAccept($child)) return true;
+ if ($group->willAccept($child)) {
+ return true;
+ }
}
return false;
}
diff --git a/src/Traits/NodeTrait.php b/src/Traits/NodeTrait.php
index 35fd34d..11fc961 100644
--- a/src/Traits/NodeTrait.php
+++ b/src/Traits/NodeTrait.php
@@ -13,7 +13,7 @@ trait NodeTrait
/** @var null|ContainerInterface */
protected $parent;
- abstract function __toString();
+ abstract public function __toString();
public function parent(): null|ContainerInterface
{
diff --git a/src/Traits/TagTrait.php b/src/Traits/TagTrait.php
index a5371f7..74a4c4f 100644
--- a/src/Traits/TagTrait.php
+++ b/src/Traits/TagTrait.php
@@ -19,7 +19,7 @@ trait TagTrait
/** @var Styles */
protected $styles;
- abstract function tag(): string;
+ abstract public function tag(): string;
public function __construct()
{
@@ -35,15 +35,20 @@ trait TagTrait
public function setID(null|string|Stringable $id): static
{
- if ($id) $this->id = static::sanitizeID($id);
- else $this->id = null;
+ if ($id) {
+ $this->id = static::sanitizeID($id);
+ } else {
+ $this->id = null;
+ }
return $this;
}
protected static function sanitizeID(string|Stringable $id): string
{
$id = trim($id);
- if (!preg_match('/^[_\-a-z][_\-a-z0-9]*$/i', $id)) throw new Exception('Invalid ID name');
+ if (!preg_match('/^[_\-a-z][_\-a-z0-9]*$/i', $id)) {
+ throw new Exception('Invalid tag ID');
+ }
return $id;
}
@@ -73,7 +78,9 @@ trait TagTrait
protected function openingTagStrings(): array
{
$strings = [$this->tag()];
- if ($this->id) $strings[] = sprintf('id="%s"', $this->id);
+ if ($this->id) {
+ $strings[] = sprintf('id="%s"', $this->id);
+ }
if ($this->classes()->count()) {
$strings[] = sprintf('class="%s"', implode(' ', $this->classes()->getArray()));
}
diff --git a/tests/Helpers/StylesTest.php b/tests/Helpers/StylesTest.php
index 15cd6cc..d7eb6bb 100644
--- a/tests/Helpers/StylesTest.php
+++ b/tests/Helpers/StylesTest.php
@@ -33,4 +33,29 @@ class StylesTest extends TestCase
$styles = new Styles(['a' => 'b', 'b' => 'c']);
$this->assertEquals('a:b;b:c', $styles->__toString());
}
+
+ /**
+ * @depends clone testConstruction
+ */
+ public function testInvalidInputs(Styles $styles): void
+ {
+ // null assignments don't work
+ $styles[] = 'b';
+ $this->assertEquals(['foo' => 'bar'], $styles->getArray());
+ // empty attribute doesn't work
+ $styles[''] = 'b';
+ $this->assertEquals(['foo' => 'bar'], $styles->getArray());
+ // attributes that trim to nothing don't work
+ $styles[' '] = 'b';
+ $this->assertEquals(['foo' => 'bar'], $styles->getArray());
+ // empty values don't work
+ $styles['quux'] = '';
+ $this->assertEquals(['foo' => 'bar'], $styles->getArray());
+ // values containing ; don't work
+ $styles['quux'] = 'x;y';
+ $this->assertEquals(['foo' => 'bar'], $styles->getArray());
+ // values containing : don't work
+ $styles['quux'] = 'x:y';
+ $this->assertEquals(['foo' => 'bar'], $styles->getArray());
+ }
}
diff --git a/tests/Html5/Tags/TagTestCase.php b/tests/Html5/Tags/TagTestCase.php
index 201503d..77c7718 100644
--- a/tests/Html5/Tags/TagTestCase.php
+++ b/tests/Html5/Tags/TagTestCase.php
@@ -26,6 +26,10 @@ abstract class TagTestCase extends TestCase
// test unsetting via unset
call_user_func([$tag, $unsetFn]);
$this->assertNull(call_user_func([$tag, $getFn]));
+ // test setting and unsetting via null value
+ call_user_func([$tag, $setFn], $test_value);
+ call_user_func([$tag, $setFn], null);
+ $this->assertNull(call_user_func([$tag, $getFn]));
}
protected function assertBooleanAttributeHelperMethods(string $attribute, string $class): void
diff --git a/tests/Tags/AbstractGroupedTagTest.php b/tests/Tags/AbstractGroupedTagTest.php
new file mode 100644
index 0000000..4c16465
--- /dev/null
+++ b/tests/Tags/AbstractGroupedTagTest.php
@@ -0,0 +1,21 @@
+getMockForAbstractClass(AbstractGroupedTag::class, [], '', true, true, true, ['tag']);
+ $tag->method('tag')->willReturn($name);
+ return $tag;
+ }
+
+ public function testEmptyRendering(): void
+ {
+ $tag = $this->tag('div');
+ $this->assertEquals('', $tag->__toString());
+ }
+}
diff --git a/tests/Tags/AbstractTagTest.php b/tests/Tags/AbstractTagTest.php
index f799827..1b81918 100644
--- a/tests/Tags/AbstractTagTest.php
+++ b/tests/Tags/AbstractTagTest.php
@@ -28,7 +28,7 @@ class AbstractTagTest extends TestCase
/**
* @depends clone testBR
*/
- public function testID(AbstractTag $tag): void
+ public function testID(AbstractTag $tag): AbstractTag
{
$this->assertNull($tag->id());
$tag->setID('foo');
@@ -37,6 +37,16 @@ class AbstractTagTest extends TestCase
$tag->setID(null);
$this->assertNull($tag->id());
$this->assertEquals('
', $tag->__toString());
+ return $tag;
+ }
+
+ /**
+ * @depends clone testID
+ */
+ public function testIDValidation(AbstractTag $tag): void
+ {
+ $this->expectExceptionMessage('Invalid tag ID');
+ $tag->setID('0abc');
}
/**