Skip to content

Commit

Permalink
Merge pull request #51 from Icinga/feature/more-strict-interfaces-23
Browse files Browse the repository at this point in the history
More strict interfaces
  • Loading branch information
nilmerg committed Jun 22, 2021
2 parents e23c2f5 + fddcdde commit c49325e
Show file tree
Hide file tree
Showing 15 changed files with 296 additions and 124 deletions.
16 changes: 16 additions & 0 deletions src/Attributes.php
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,22 @@ public function getAttributes()
return $this->attributes;
}

/**
* Merge the given attributes
*
* @param Attributes $attributes
*
* @return $this
*/
public function merge(Attributes $attributes)
{
foreach ($attributes as $attribute) {
$this->addAttribute($attribute);
}

return $this;
}

/**
* Return true if the attribute with the given name exists, false otherwise
*
Expand Down
19 changes: 2 additions & 17 deletions src/BaseHtmlElement.php
Original file line number Diff line number Diff line change
Expand Up @@ -301,26 +301,11 @@ protected function registerAttributeCallbacks(Attributes $attributes)
{
}

public function add($content)
public function addHtml(ValidHtml ...$content)
{
$this->ensureAssembled();

parent::add($content);

return $this;
}

public function setContent($content)
{
// setContent() calls $this->add() which would assemble the element and that does not make any sense here
// Plus, this allows subclasses of BaseHtmlElement to add content before assemble() --
// in the constructor for example

$this->hasBeenAssembled = true;

parent::setContent($content);

$this->hasBeenAssembled = false;
parent::addHtml(...$content);

return $this;
}
Expand Down
4 changes: 2 additions & 2 deletions src/Error.php
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ public static function show($error)

$result = static::renderErrorMessage($msg);
if (static::showTraces()) {
$result->add(Html::tag('pre', $error->getTraceAsString()));
$result->addHtml(Html::tag('pre', $error->getTraceAsString()));
}

return $result;
Expand Down Expand Up @@ -101,7 +101,7 @@ protected static function createMessageForException($exception)
protected static function renderErrorMessage($message)
{
$output = new HtmlDocument();
$output->add(
$output->addHtml(
Html::tag('div', ['class' => 'exception'], [
Html::tag('h1', [
Html::tag('i', ['class' => 'icon-bug']),
Expand Down
4 changes: 2 additions & 2 deletions src/Form.php
Original file line number Diff line number Diff line change
Expand Up @@ -346,11 +346,11 @@ protected function onError()
$message = $message->getMessage();
}

$errors->add(Html::tag('li', $message));
$errors->addHtml(Html::tag('li', $message));
}

if (! $errors->isEmpty()) {
$this->prepend($errors);
$this->prependHtml($errors);
}
}

Expand Down
9 changes: 5 additions & 4 deletions src/FormDecorator/DdDtDecorator.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
use ipl\Html\BaseHtmlElement;
use ipl\Html\FormElement\BaseFormElement;
use ipl\Html\Html;
use ipl\Html\ValidHtml;

class DdDtDecorator extends BaseHtmlElement implements DecoratorInterface
{
Expand Down Expand Up @@ -92,19 +93,19 @@ protected function renderErrors()
return null;
}

public function add($content)
public function addHtml(ValidHtml ...$content)
{
// TODO: is this required?
if ($content !== $this->wrappedElement) {
parent::add($content);
if (! in_array($this->wrappedElement, $content, true)) {
parent::addHtml(...$content);
}

return $this;
}

protected function assemble()
{
$this->add([$this->dt(), $this->dd()]);
$this->addHtml($this->dt(), $this->dd());
$this->ready = true;
}

Expand Down
9 changes: 6 additions & 3 deletions src/FormDecorator/DivDecorator.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
use ipl\Html\FormElement\HiddenElement;
use ipl\Html\Html;
use ipl\Html\HtmlElement;
use ipl\Html\Text;

/**
* Form element decorator based on div elements
Expand Down Expand Up @@ -84,10 +85,12 @@ protected function assembleElement()

protected function assembleErrors()
{
$errors = new HtmlElement('ul', ['class' => static::ERROR_CLASS]);
$errors = new HtmlElement('ul', Attributes::create(['class' => static::ERROR_CLASS]));

foreach ($this->formElement->getMessages() as $message) {
$errors->add(new HtmlElement('li', ['class' => static::ERROR_CLASS], $message));
$errors->addHtml(
new HtmlElement('li', Attributes::create(['class' => static::ERROR_CLASS]), Text::create($message))
);
}

if (! $errors->isEmpty()) {
Expand Down Expand Up @@ -119,7 +122,7 @@ protected function assemble()
$this->getAttributes()->add('class', static::ERROR_HINT_CLASS);
}

$this->add(array_filter([
$this->addHtml(...Html::wantHtmlList([
$this->assembleLabel(),
$this->assembleElement(),
$this->assembleDescription(),
Expand Down
2 changes: 1 addition & 1 deletion src/FormElement/FormElements.php
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,7 @@ public function addElement($typeOrElement, $name = null, $options = null)
$this
->registerElement($element) // registerElement() must be called first because of the name check
->decorate($element)
->add($element);
->addHtml($element);

return $this;
}
Expand Down
6 changes: 2 additions & 4 deletions src/FormElement/SelectElement.php
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,7 @@ protected function makeOption($value, $label)
if (is_array($label)) {
$grp = Html::tag('optgroup', ['label' => $value]);
foreach ($label as $option => $val) {
$grp->add($this->makeOption($option, $val));
$grp->addHtml($this->makeOption($option, $val));
}

return $grp;
Expand All @@ -134,8 +134,6 @@ protected function makeOption($value, $label)

protected function assemble()
{
foreach ($this->optionContent as $value => $option) {
$this->add($option);
}
$this->addHtml(...array_values($this->optionContent));
}
}
57 changes: 49 additions & 8 deletions src/Html.php
Original file line number Diff line number Diff line change
Expand Up @@ -26,17 +26,32 @@ abstract class Html
*/
public static function tag($name, $attributes = null, $content = null)
{
if ($attributes instanceof ValidHtml || is_scalar($attributes)) {
$content = $attributes;
if ($content !== null) {
// If not null, it's html content, no question
$content = static::wantHtmlList($content);
} elseif ($attributes instanceof ValidHtml || is_scalar($attributes)) {
// Otherwise $attributes may be $content, but only if definitely **NOT** attributes
$content = static::wantHtmlList($attributes);
$attributes = null;
} elseif (is_iterable($attributes)) {
if (is_int(iterable_key_first($attributes))) {
$content = $attributes;
}

if ($attributes !== null) {
if (! is_iterable($attributes) || ! is_int(iterable_key_first($attributes))) {
// Not an array (e.g. instance of Attributes) or an associative array
$attributes = Attributes::wantAttributes($attributes);
} elseif (is_iterable($attributes)) {
// $attributes may still be $content, in case of a sequenced array
if ($content !== null) {
// But not if there's already $content
throw new InvalidArgumentException('Value of argument $attributes are no attributes');
}

$content = static::wantHtmlList($attributes);
$attributes = null;
}
}

return new HtmlElement($name, $attributes, $content);
return new HtmlElement($name, $attributes, ...($content ?: []));
}

/**
Expand Down Expand Up @@ -104,7 +119,7 @@ public static function wrapEach($list, $wrapper)
$result = new HtmlDocument();
foreach ($list as $name => $value) {
if (is_string($wrapper)) {
$result->add(Html::tag($wrapper, $value));
$result->addHtml(Html::tag($wrapper, $value));
} elseif (is_callable($wrapper)) {
$result->add($wrapper($name, $value));
} else {
Expand Down Expand Up @@ -139,7 +154,7 @@ public static function wantHtml($any)
$html = new HtmlDocument();
foreach ($any as $el) {
if ($el !== null) {
$html->add(static::wantHtml($el));
$html->addHtml(static::wantHtml($el));
}
}

Expand All @@ -152,6 +167,32 @@ public static function wantHtml($any)
}
}

/**
* Accept any input and return it as list of ValidHtml
*
* @param mixed $content
*
* @return ValidHtml[]
*/
public static function wantHtmlList($content)
{
$list = [];

if ($content === null) {
return $list;
} elseif (! is_iterable($content)) {
$list[] = static::wantHtml($content);
} elseif ($content instanceof ValidHtml) {
$list[] = $content;
} else {
foreach ($content as $part) {
$list = array_merge($list, static::wantHtmlList($part));
}
}

return $list;
}

/**
* Get whether the given variable be rendered as a string
*
Expand Down
65 changes: 50 additions & 15 deletions src/HtmlDocument.php
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,24 @@ public function getContent()
public function setContent($content)
{
$this->content = [];
$this->add($content);
$this->setHtmlContent(...Html::wantHtmlList($content));

return $this;
}

/**
* Set content
*
* @param ValidHtml ...$content
*
* @return $this
*/
public function setHtmlContent(ValidHtml ...$content)
{
$this->content = [];
foreach ($content as $element) {
$this->addIndexedContent($element);
}

return $this;
}
Expand Down Expand Up @@ -144,12 +161,22 @@ public function getFirst($tag)
*/
public function add($content)
{
if (is_iterable($content) && ! $content instanceof ValidHtml) {
foreach ($content as $c) {
$this->add($c);
}
} elseif ($content !== null) {
$this->addIndexedContent(Html::wantHtml($content));
$this->addHtml(...Html::wantHtmlList($content));

return $this;
}

/**
* Add content
*
* @param ValidHtml ...$content
*
* @return $this
*/
public function addHtml(ValidHtml ...$content)
{
foreach ($content as $element) {
$this->addIndexedContent($element);
}

return $this;
Expand Down Expand Up @@ -211,16 +238,24 @@ public function contains(ValidHtml $element)
*/
public function prepend($content)
{
if (is_iterable($content) && ! $content instanceof ValidHtml) {
foreach (array_reverse(is_array($content) ? $content : iterator_to_array($content)) as $c) {
$this->prepend($c);
}
} elseif ($content !== null) {
$pos = 0;
$html = Html::wantHtml($content);
$this->prependHtml(...Html::wantHtmlList($content));

return $this;
}

/**
* Prepend content
*
* @param ValidHtml ...$content
*
* @return $this
*/
public function prependHtml(ValidHtml ...$content)
{
foreach (array_reverse($content) as $html) {
array_unshift($this->content, $html);
$this->incrementIndexKeys();
$this->addObjectPosition($html, $pos);
$this->addObjectPosition($html, 0);
}

return $this;
Expand Down
22 changes: 10 additions & 12 deletions src/HtmlElement.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,34 +12,32 @@ class HtmlElement extends BaseHtmlElement
/**
* Create a new HTML element from the given tag, attributes and content
*
* @param string $tag The tag for the element
* @param Attributes|array $attributes The HTML attributes for the element
* @param ValidHtml|string|array $content The content of the element
* @param string $tag The tag for the element
* @param Attributes $attributes The HTML attributes for the element
* @param ValidHtml ...$content The content of the element
*/
public function __construct($tag, $attributes = null, $content = null)
public function __construct($tag, Attributes $attributes = null, ValidHtml ...$content)
{
$this->tag = $tag;

if ($attributes !== null) {
$this->getAttributes()->add($attributes);
$this->getAttributes()->merge($attributes);
}

if ($content !== null) {
$this->setContent($content);
}
$this->setHtmlContent(...$content);
}

/**
* Create a new HTML element from the given tag, attributes and content
*
* @param string $tag The tag for the element
* @param Attributes|array $attributes The HTML attributes for the element
* @param ValidHtml|string|array $content The content of the element
* @param string $tag The tag for the element
* @param mixed $attributes The HTML attributes for the element
* @param mixed $content The content of the element
*
* @return static
*/
public static function create($tag, $attributes = null, $content = null)
{
return new static($tag, $attributes, $content);
return new static($tag, Attributes::wantAttributes($attributes), ...Html::wantHtmlList($content));
}
}
Loading

0 comments on commit c49325e

Please sign in to comment.