209 lines
4.3 KiB
PHP
209 lines
4.3 KiB
PHP
<?php
|
|
|
|
namespace KupShop\KupShopBundle\Util\HtmlBuilder;
|
|
|
|
class HTML
|
|
{
|
|
/** @var HTML */
|
|
protected static $instance;
|
|
/** @var string */
|
|
private $name = '';
|
|
/** @var array */
|
|
private $attributes = [];
|
|
/** @var HTML[] */
|
|
private $content = [];
|
|
/** @var HTML|null */
|
|
private $parent;
|
|
|
|
protected function __construct(string $name, ?HTML $parent = null)
|
|
{
|
|
$this->name = $name;
|
|
$this->parent = $parent;
|
|
|
|
return $this;
|
|
}
|
|
|
|
public function __toString(): string
|
|
{
|
|
return $this->renderTag();
|
|
}
|
|
|
|
/**
|
|
* @throws \LogicException
|
|
*/
|
|
public function html(bool $pretty = false): string
|
|
{
|
|
if ($pretty) {
|
|
if (!extension_loaded('tidy')) {
|
|
throw new \LogicException('The Tidy extension is not loaded: you cannot pretty-print without it');
|
|
}
|
|
|
|
$tidy = new \Tidy();
|
|
$tidy->parseString($this->renderTag(), ['indent' => true, 'show-body-only' => true, 'indent-spaces' => 4]);
|
|
|
|
return (string) $tidy;
|
|
}
|
|
|
|
return $this->renderTag();
|
|
}
|
|
|
|
/**
|
|
* Create a Html tag.
|
|
*
|
|
* @return HTML
|
|
*/
|
|
public static function create(string $name)
|
|
{
|
|
self::$instance = new static($name);
|
|
|
|
return self::$instance;
|
|
}
|
|
|
|
/**
|
|
* Open a HTML tag.
|
|
*/
|
|
public function tag(string $name): HTML
|
|
{
|
|
$tag = new self($name, $this);
|
|
|
|
$this->content[] = $tag;
|
|
|
|
return $this->content[count($this->content) - 1];
|
|
}
|
|
|
|
/**
|
|
* Add text inside the tag.
|
|
*/
|
|
public function text(?string $text = null): HTML
|
|
{
|
|
$text = new Text($text ?? '', $this);
|
|
|
|
$this->content[] = $text;
|
|
|
|
return $this;
|
|
}
|
|
|
|
/**
|
|
* Close a HTML tag.
|
|
*/
|
|
public function end(): HTML
|
|
{
|
|
if ($this->parent) {
|
|
return $this->getParent();
|
|
}
|
|
|
|
return $this;
|
|
}
|
|
|
|
/**
|
|
* Set an attribute.
|
|
*/
|
|
public function attr(string $key, ?string $value = null): self
|
|
{
|
|
$this->attributes[$key] = $value;
|
|
|
|
return $this;
|
|
}
|
|
|
|
/**
|
|
* Synonym for 'attr'.
|
|
*/
|
|
public function attribute(string $key, ?string $value = null): self
|
|
{
|
|
return $this->attr($key, $value);
|
|
}
|
|
|
|
/**
|
|
* Remove an attribute.
|
|
*/
|
|
public function rattr(string $key): self
|
|
{
|
|
unset($this->attributes[$key]);
|
|
|
|
return $this;
|
|
}
|
|
|
|
/**
|
|
* Synonym for 'rattr'.
|
|
*/
|
|
public function removeAttribute(string $key): self
|
|
{
|
|
return $this->rattr($key);
|
|
}
|
|
|
|
// Attribute shorthands
|
|
|
|
/**
|
|
* Set the id attribute.
|
|
*/
|
|
public function id(?string $value = null): self
|
|
{
|
|
return $this->attr('id', $value);
|
|
}
|
|
|
|
/**
|
|
* Set the class attribute.
|
|
*/
|
|
public function class(?string $value = null): self
|
|
{
|
|
return $this->attr('class', $value);
|
|
}
|
|
|
|
/**
|
|
* @return HTML|null
|
|
*/
|
|
private function getParent()
|
|
{
|
|
return $this->parent;
|
|
}
|
|
|
|
private function renderTag(): string
|
|
{
|
|
return sprintf(
|
|
'<%s%s>%s</%s>',
|
|
$this->name,
|
|
count($this->attributes) === 0 ? '' : ' '.$this->renderAttributes(),
|
|
$this->renderTags(),
|
|
$this->name
|
|
);
|
|
}
|
|
|
|
private function renderAttributes(): string
|
|
{
|
|
ksort($this->attributes);
|
|
|
|
$argumentArray = [];
|
|
foreach ($this->attributes as $argument => $value) {
|
|
$argumentArray[] = sprintf('%s="%s"', $argument, htmlspecialchars($value ?? ''));
|
|
}
|
|
|
|
return implode(' ', $argumentArray);
|
|
}
|
|
|
|
private function renderTags(): string
|
|
{
|
|
$result = '';
|
|
foreach ($this->content as $tag) {
|
|
if ($tag instanceof self) {
|
|
$result .= $tag->html();
|
|
} elseif ($tag instanceof Text) {
|
|
// Make sure the content is 'safe'
|
|
// @see http://php.net/manual/en/function.htmlspecialchars.php
|
|
$result .= htmlspecialchars($tag->render());
|
|
}
|
|
}
|
|
|
|
return $result;
|
|
}
|
|
|
|
public function getName(): string
|
|
{
|
|
return $this->name;
|
|
}
|
|
|
|
public function getAttribute($key): string
|
|
{
|
|
return $this->attributes[$key] ?? '';
|
|
}
|
|
}
|