Files
2025-08-02 16:30:27 +02:00

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] ?? '';
}
}