dipl: align with ipl-html, stop using deprecated

...method Html::escapeForHtml
This commit is contained in:
Thomas Gelf 2018-05-25 19:09:42 +02:00
parent ec0beb5de8
commit 5a8c785b7c
15 changed files with 433 additions and 317 deletions

View File

@ -46,7 +46,7 @@ class SuggestController extends ActionController
$matches[] = $this->highlight($str, $search); $matches[] = $this->highlight($str, $search);
} }
} else { } else {
$matches[] = Html::escapeForHtml($str); $matches[] = Html::escape($str);
} }
} }
@ -260,7 +260,7 @@ class SuggestController extends ActionController
protected function highlight($val, $search) protected function highlight($val, $search)
{ {
$search = ($search); $search = ($search);
$val = Html::escapeForHtml($val); $val = Html::escape($val);
return preg_replace( return preg_replace(
'/(' . preg_quote($search, '/') . ')/i', '/(' . preg_quote($search, '/') . ')/i',
'<strong>\1</strong>', '<strong>\1</strong>',

View File

@ -64,7 +64,7 @@ abstract class Dashboard extends HtmlDocument
$this->add(Html::tag( $this->add(Html::tag(
'p', 'p',
null, null,
HtmlString::create(nl2br(Html::escapeForHtml($description))) HtmlString::create(nl2br(Html::escape($description)))
)); ));
} }

View File

@ -20,7 +20,7 @@ class StartupLogRenderer implements ValidHtml
public function render() public function render()
{ {
$deployment = $this->deployment; $deployment = $this->deployment;
$log = Html::escapeForHtml($deployment->get('startup_log')); $log = Html::escape($deployment->get('startup_log'));
$lines = array(); $lines = array();
$severity = 'information'; $severity = 'information';
$sevPattern = '/^(debug|notice|information|warning|critical)\/(\w+)/'; $sevPattern = '/^(debug|notice|information|warning|critical)\/(\w+)/';

View File

@ -34,7 +34,7 @@ class ShowConfigFile extends HtmlDocument
*/ */
protected function assemble() protected function assemble()
{ {
$source = $this->linkObjects(Html::escapeForHtml($this->file->getContent())); $source = $this->linkObjects(Html::escape($this->file->getContent()));
if ($this->highlight) { if ($this->highlight) {
$source = $this->highlight( $source = $this->highlight(
$source, $source,

View File

@ -2,7 +2,7 @@
namespace dipl\Html; namespace dipl\Html;
use Icinga\Exception\ProgrammingError; use InvalidArgumentException;
/** /**
* HTML Attribute * HTML Attribute
@ -27,7 +27,7 @@ class Attribute
* *
* @param $name * @param $name
* @param $value * @param $value
* @throws ProgrammingError * @throws InvalidArgumentException
*/ */
public function __construct($name, $value = null) public function __construct($name, $value = null)
{ {
@ -38,7 +38,7 @@ class Attribute
* @param $name * @param $name
* @param $value * @param $value
* @return static * @return static
* @throws ProgrammingError * @throws InvalidArgumentException
*/ */
public static function create($name, $value) public static function create($name, $value)
{ {
@ -56,15 +56,15 @@ class Attribute
/** /**
* @param $name * @param $name
* @return $this * @return $this
* @throws ProgrammingError * @throws InvalidArgumentException
*/ */
public function setName($name) public function setName($name)
{ {
if (! preg_match('/^[a-z][a-z0-9:-]*$/i', $name)) { if (! preg_match('/^[a-z][a-z0-9:-]*$/i', $name)) {
throw new ProgrammingError( throw new InvalidArgumentException(sprintf(
'Attribute names with special characters are not yet allowed: %s', 'Attribute names with special characters are not yet allowed: %s',
$name $name
); ));
} }
$this->name = $name; $this->name = $name;
@ -160,7 +160,7 @@ class Attribute
/** /**
* @param $name * @param $name
* @return static * @return static
* @throws ProgrammingError * @throws InvalidArgumentException
*/ */
public static function createEmpty($name) public static function createEmpty($name)
{ {
@ -185,9 +185,9 @@ class Attribute
{ {
// TODO: escape differently // TODO: escape differently
if (is_array($value)) { if (is_array($value)) {
return Html::escapeForHtml(implode(' ', $value)); return Html::escape(implode(' ', $value));
} else { } else {
return Html::escapeForHtml((string) $value); return Html::escape((string) $value);
} }
} }
} }

View File

@ -2,8 +2,7 @@
namespace dipl\Html; namespace dipl\Html;
use Icinga\Exception\IcingaException; use InvalidArgumentException;
use Icinga\Exception\ProgrammingError;
class Attributes class Attributes
{ {
@ -22,7 +21,7 @@ class Attributes
/** /**
* Attributes constructor. * Attributes constructor.
* @param Attribute[] $attributes * @param Attribute[] $attributes
* @throws ProgrammingError * @throws InvalidArgumentException
*/ */
public function __construct(array $attributes = null) public function __construct(array $attributes = null)
{ {
@ -44,7 +43,7 @@ class Attributes
/** /**
* @param Attribute[] $attributes * @param Attribute[] $attributes
* @return static * @return static
* @throws ProgrammingError * @throws InvalidArgumentException
*/ */
public static function create(array $attributes = null) public static function create(array $attributes = null)
{ {
@ -54,7 +53,7 @@ class Attributes
/** /**
* @param Attributes|array|null $attributes * @param Attributes|array|null $attributes
* @return Attributes * @return Attributes
* @throws IcingaException * @throws InvalidArgumentException
*/ */
public static function wantAttributes($attributes) public static function wantAttributes($attributes)
{ {
@ -69,10 +68,10 @@ class Attributes
return $self; return $self;
} elseif ($attributes !== null) { } elseif ($attributes !== null) {
throw new IcingaException( throw new InvalidArgumentException(sprintf(
'Attributes, Array or Null expected, got %s', 'Attributes, Array or Null expected, got %s',
Html::getPhpTypeName($attributes) Html::getPhpTypeName($attributes)
); ));
} }
return $self; return $self;
} }
@ -90,7 +89,7 @@ class Attributes
* @param Attribute|string $attribute * @param Attribute|string $attribute
* @param string|array $value * @param string|array $value
* @return $this * @return $this
* @throws ProgrammingError * @throws InvalidArgumentException
*/ */
public function add($attribute, $value = null) public function add($attribute, $value = null)
{ {
@ -121,7 +120,7 @@ class Attributes
* @param Attribute|array|string $attribute * @param Attribute|array|string $attribute
* @param string|array $value * @param string|array $value
* @return $this * @return $this
* @throws ProgrammingError * @throws InvalidArgumentException
*/ */
public function set($attribute, $value = null) public function set($attribute, $value = null)
{ {
@ -154,7 +153,7 @@ class Attributes
/** /**
* @param $name * @param $name
* @return Attribute * @return Attribute
* @throws ProgrammingError * @throws InvalidArgumentException
*/ */
public function get($name) public function get($name)
{ {
@ -226,20 +225,20 @@ class Attributes
* @param callable $callback * @param callable $callback
* @param callable $setterCallback * @param callable $setterCallback
* @return $this * @return $this
* @throws ProgrammingError * @throws InvalidArgumentException
*/ */
public function registerAttributeCallback($name, $callback, $setterCallback = null) public function registerAttributeCallback($name, $callback, $setterCallback = null)
{ {
if ($callback !== null) { if ($callback !== null) {
if (! is_callable($callback)) { if (! is_callable($callback)) {
throw new ProgrammingError(__METHOD__ . ' expects a callable callback'); throw new InvalidArgumentException(__METHOD__ . ' expects a callable callback');
} }
$this->callbacks[$name] = $callback; $this->callbacks[$name] = $callback;
} }
if ($setterCallback !== null) { if ($setterCallback !== null) {
if (! is_callable($setterCallback)) { if (! is_callable($setterCallback)) {
throw new ProgrammingError(__METHOD__ . ' expects a callable setterCallback'); throw new InvalidArgumentException(__METHOD__ . ' expects a callable setterCallback');
} }
$this->setterCallbacks[$name] = $setterCallback; $this->setterCallbacks[$name] = $setterCallback;
} }
@ -249,7 +248,7 @@ class Attributes
/** /**
* @return string * @return string
* @throws ProgrammingError * @throws InvalidArgumentException
*/ */
public function render() public function render()
{ {
@ -265,7 +264,7 @@ class Attributes
} elseif (null === $attribute) { } elseif (null === $attribute) {
continue; continue;
} else { } else {
throw new ProgrammingError( throw new InvalidArgumentException(
'A registered attribute callback must return string, null' 'A registered attribute callback must return string, null'
. ' or an Attribute' . ' or an Attribute'
); );

View File

@ -2,6 +2,8 @@
namespace dipl\Html; namespace dipl\Html;
use RuntimeException;
abstract class BaseHtmlElement extends HtmlDocument abstract class BaseHtmlElement extends HtmlDocument
{ {
/** @var array You may want to set default attributes when extending this class */ /** @var array You may want to set default attributes when extending this class */
@ -13,31 +15,40 @@ abstract class BaseHtmlElement extends HtmlDocument
/** @var string */ /** @var string */
protected $tag; protected $tag;
protected $hasBeenAssembled = false; /**
* List of void elements which must not contain end tags or content
*
* If {@link $isVoid} is null, this property should be used to decide whether the content and end tag has to be
* rendered.
*
* @var array
*
* @see https://www.w3.org/TR/html5/syntax.html#void-elements
*/
protected static $voidElements = [ protected static $voidElements = [
'area', 'area' => 1,
'base', 'base' => 1,
'br', 'br' => 1,
'col', 'col' => 1,
'embed', 'embed' => 1,
'hr', 'hr' => 1,
'img', 'img' => 1,
'input', 'input' => 1,
'link', 'link' => 1,
'meta', 'meta' => 1,
'param', 'param' => 1,
'source', 'source' => 1,
'track', 'track' => 1,
'wbr' 'wbr' => 1
]; ];
/** @var bool|null Whether the element is void. If null, void check should use {@link $voidElements} */
protected $isVoid; protected $isVoid;
/** /**
* Get the attributes of the element
*
* @return Attributes * @return Attributes
* @throws \Icinga\Exception\IcingaException
* @throws \Icinga\Exception\ProgrammingError
*/ */
public function getAttributes() public function getAttributes()
{ {
@ -54,9 +65,11 @@ abstract class BaseHtmlElement extends HtmlDocument
} }
/** /**
* Set the attributes of the element
*
* @param Attributes|array|null $attributes * @param Attributes|array|null $attributes
*
* @return $this * @return $this
* @throws \Icinga\Exception\IcingaException
*/ */
public function setAttributes($attributes) public function setAttributes($attributes)
{ {
@ -66,24 +79,28 @@ abstract class BaseHtmlElement extends HtmlDocument
} }
/** /**
* @param string $key * Set the attribute with the given name and value
* @param mixed $value *
* If the attribute with the given name already exists, it gets overridden.
*
* @param string $name The name of the attribute
* @param string|bool|array $value The value of the attribute
*
* @return $this * @return $this
* @throws \Icinga\Exception\ProgrammingError
* @throws \Icinga\Exception\IcingaException
*/ */
public function setAttribute($key, $value) public function setAttribute($name, $value)
{ {
$this->getAttributes()->set($key, $value); $this->getAttributes()->set($name, $value);
return $this; return $this;
} }
/** /**
* @param Attributes|array|null $attributes * Add the given attributes
*
* @param Attributes|array $attributes
*
* @return $this * @return $this
* @throws \Icinga\Exception\ProgrammingError
* @throws \Icinga\Exception\IcingaException
*/ */
public function addAttributes($attributes) public function addAttributes($attributes)
{ {
@ -93,6 +110,8 @@ abstract class BaseHtmlElement extends HtmlDocument
} }
/** /**
* Get the default attributes of the element
*
* @return array * @return array
*/ */
public function getDefaultAttributes() public function getDefaultAttributes()
@ -100,6 +119,45 @@ abstract class BaseHtmlElement extends HtmlDocument
return $this->defaultAttributes; return $this->defaultAttributes;
} }
/**
* Get the tag of the element
*
* Since HTML Elements must have a tag, this method throws an exception if the element does not have a tag.
*
* @return string
*
* @throws RuntimeException If the element does not have a tag
*/
final public function getTag()
{
$tag = $this->tag();
if (! strlen($tag)) {
throw new RuntimeException('Element must have a tag');
}
return $tag;
}
/**
* Internal method for accessing the tag
*
* You may override this method in order to provide the tag dynamically
*
* @return string
*/
protected function tag()
{
return $this->tag;
}
/**
* Set the tag of the element
*
* @param string $tag
*
* @return $this
*/
public function setTag($tag) public function setTag($tag)
{ {
$this->tag = $tag; $this->tag = $tag;
@ -107,21 +165,16 @@ abstract class BaseHtmlElement extends HtmlDocument
return $this; return $this;
} }
public function getTag() /**
{ * Render the content of the element to HTML
return $this->tag; *
} * @return string
*/
public function renderContent() public function renderContent()
{ {
return parent::renderUnwrapped(); return parent::renderUnwrapped();
} }
/**
* @param array|ValidHtml|string $content
* @return $this
* @throws \Icinga\Exception\IcingaException
*/
public function add($content) public function add($content)
{ {
$this->ensureAssembled(); $this->ensureAssembled();
@ -132,49 +185,40 @@ abstract class BaseHtmlElement extends HtmlDocument
} }
/** /**
* @return string * @inheritdoc
* @throws \Icinga\Exception\ProgrammingError *
* @throws \Icinga\Exception\IcingaException * @throws RuntimeException If the element does not have a tag or is void but has content
*/ */
public function renderUnwrapped() public function renderUnwrapped()
{ {
$this->ensureAssembled(); $this->ensureAssembled();
$tag = $this->getTag();
$tag = $this->getTag();
$attributes = $this->getAttributes()->render();
$content = $this->renderContent(); $content = $this->renderContent();
if (strlen($content) || $this->wantsClosingTag()) {
if (! $this->wantsClosingTag()) {
if (strlen($content)) {
throw new RuntimeException('Void elements must not have content');
}
return sprintf('<%s%s />', $tag, $attributes);
}
return sprintf( return sprintf(
'<%s%s>%s</%s>', '<%s%s>%s</%s>',
$tag, $tag,
$this->renderAttributes(), $attributes,
$content, $content,
$tag $tag
); );
} else {
return sprintf(
'<%s%s />',
$tag,
$this->renderAttributes()
);
}
}
/**
* @return string
* @throws \Icinga\Exception\ProgrammingError
* @throws \Icinga\Exception\IcingaException
*/
public function renderAttributes()
{
if ($this->attributes === null && empty($this->defaultAttributes)) {
return '';
} else {
return $this->getAttributes()->render();
}
} }
/** /**
* Use this element to wrap the given document
*
* @param HtmlDocument $document * @param HtmlDocument $document
*
* @return $this * @return $this
*/ */
public function wrap(HtmlDocument $document) public function wrap(HtmlDocument $document)
@ -184,36 +228,54 @@ abstract class BaseHtmlElement extends HtmlDocument
return $this; return $this;
} }
/**
* Get whether the closing tag should be rendered
*
* @return bool True for void elements, false otherwise
*/
public function wantsClosingTag() public function wantsClosingTag()
{ {
// TODO: There is more. SVG and MathML namespaces // TODO: There is more. SVG and MathML namespaces
return ! $this->isVoidElement(); return ! $this->isVoid();
}
public function isVoidElement()
{
if ($this->isVoid === null) {
$this->isVoid = in_array($this->tag, self::$voidElements);
}
return $this->isVoid;
}
public function setVoid($void = true)
{
$this->isVoid = $void;
return $this;
} }
/** /**
* Whether the given something can be rendered * Get whether the element is void
*
* The default void detection which checks whether the element's tag is in the list of void elements according to
* https://www.w3.org/TR/html5/syntax.html#void-elements.
*
* If you want to override this behavior, use {@link setVoid()}.
* *
* @param mixed $any
* @return bool * @return bool
*/ */
protected function canBeRendered($any) public function isVoid()
{ {
return is_string($any) || is_int($any) || is_null($any); if ($this->isVoid !== null) {
return $this->isVoid;
}
$tag = $this->getTag();
return isset(self::$voidElements[$tag]);
}
/**
* Set whether the element is void
*
* You may use this method to override the default void detection which checks whether the element's tag is in the
* list of void elements according to https://www.w3.org/TR/html5/syntax.html#void-elements.
*
* If you specify null, void detection is reset to its default behavior.
*
* @param bool|null $void
*
* @return $this
*/
public function setVoid($void = true)
{
$this->isVoid = $void === null ?: (bool) $void;
return $this;
} }
} }

View File

@ -55,7 +55,7 @@ class DeferredText implements ValidHtml
if ($this->escaped) { if ($this->escaped) {
return $callback(); return $callback();
} else { } else {
return Html::escapeForHtml($callback()); return Html::escape($callback());
} }
} }
@ -80,7 +80,7 @@ class DeferredText implements ValidHtml
try { try {
return $this->render(); return $this->render();
} catch (Exception $e) { } catch (Exception $e) {
return Html::renderError($e); return Error::render($e);
} }
} }
} }

118
library/vendor/ipl/Html/Error.php vendored Normal file
View File

@ -0,0 +1,118 @@
<?php
namespace dipl\Html;
use Error as PhpError;
use Exception;
/**
* Class Error
*
* TODO: Eventually allow to (statically) inject a custom error renderer.
*
* @package ipl\Html
*/
abstract class Error
{
/** @var bool */
protected static $showTraces = true;
/**
*
* @param Exception|PhpError|string $error
* @return HtmlDocument
*/
public static function show($error)
{
if ($error instanceof Exception) {
$msg = static::createMessageForException($error);
} elseif ($error instanceof PhpError) {
$msg = static::createMessageForException($error);
} elseif (is_string($error)) {
$msg = $error;
} else {
// TODO: translate?
$msg = 'Got an invalid error';
}
$result = static::renderErrorMessage($msg);
if (static::showTraces()) {
$result->add(Html::tag('pre', $error->getTraceAsString()));
}
return $result;
}
/**
*
* @param Exception|PhpError|string $error
* @return string
*/
public static function render($error)
{
return static::show($error)->render();
}
/**
* @param string
* @return HtmlDocument
*/
protected static function renderErrorMessage($message)
{
$output = new HtmlDocument();
$output->add(
Html::tag('div', ['class' => 'exception'], [
Html::tag('h1', [
Html::tag('i', ['class' => 'icon-bug']),
// TODO: Translate? More hints?
'Oops, an error occurred!'
]),
Html::tag('pre', $message)
])
);
return $output;
}
/**
* @param PhpError|Exception $exception
* @return string
*/
protected static function createMessageForException($exception)
{
$file = preg_split('/[\/\\\]/', $exception->getFile(), -1, PREG_SPLIT_NO_EMPTY);
$file = array_pop($file);
return sprintf(
'%s (%s:%d)',
$exception->getMessage(),
$file,
$exception->getLine()
);
}
/**
* @param bool|null $show
* @return bool
*/
public static function showTraces($show = null)
{
if ($show !== null) {
self::$showTraces = (bool) $show;
}
return self::$showTraces;
}
/**
* @param $any
* @return string
*/
public static function getPhpTypeName($any)
{
if (is_object($any)) {
return get_class($any);
} else {
return gettype($any);
}
}
}

View File

@ -16,7 +16,6 @@ class FormattedString implements ValidHtml
* FormattedString constructor. * FormattedString constructor.
* @param $string * @param $string
* @param array $arguments * @param array $arguments
* @throws \Icinga\Exception\IcingaException
*/ */
public function __construct($string, array $arguments = []) public function __construct($string, array $arguments = [])
{ {
@ -30,7 +29,6 @@ class FormattedString implements ValidHtml
/** /**
* @param $string * @param $string
* @return static * @return static
* @throws \Icinga\Exception\IcingaException
*/ */
public static function create($string) public static function create($string)
{ {
@ -47,4 +45,16 @@ class FormattedString implements ValidHtml
$this->arguments $this->arguments
); );
} }
/**
* @return string
*/
public function __toString()
{
try {
return $this->render();
} catch (Exception $e) {
return Error::render($e);
}
}
} }

View File

@ -2,35 +2,80 @@
namespace dipl\Html; namespace dipl\Html;
use Exception; use InvalidArgumentException;
use Icinga\Exception\IcingaException;
class Html /**
{ * Class Html
/** Charset to be used - we only support UTF-8 */ *
const CHARSET = 'UTF-8'; * This is your main utility class when working with ipl\Html
*
/** @var int The flags we use for htmlspecialchars depend on our PHP version */ * @package ipl\Html
protected static $htmlEscapeFlags;
/** @var bool */
protected static $showTraces = true;
/**
* @param $tag
* @param null $attributes
* @param null $content
* @return HtmlElement
*/ */
public static function tag($tag, $attributes = null, $content = null) abstract class Html
{
/**
* Create a HTML element from the given tag, attributes and content
*
* This method does not render the HTML element but creates a {@link HtmlElement}
* instance from the given tag, attributes and content
*
* @param string $name The desired HTML tag name
* @param mixed $attributes HTML attributes or content for the element
* @param mixed $content The content of the element if no attributes have been given
*
* @return HtmlElement The created element
*/
public static function tag($name, $attributes = null, $content = null)
{ {
return HtmlElement::create($tag, $attributes, $content); if ($attributes instanceof ValidHtml || is_string($attributes)) {
$content = $attributes;
$attributes = null;
} elseif (is_array($attributes)) {
reset($attributes);
if (is_int(key($attributes))) {
$content = $attributes;
$attributes = null;
}
}
return new HtmlElement($name, $attributes, $content);
} }
/** /**
* Convert special characters to HTML5 entities using the UTF-8 character
* set for encoding
*
* This method internally uses {@link htmlspecialchars} with the following
* flags:
*
* * Single quotes are not escaped (ENT_COMPAT)
* * Uses HTML5 entities, disallowing &#013; (ENT_HTML5)
* * Invalid characters are replaced with <EFBFBD> (ENT_SUBSTITUTE)
*
* Already existing HTML entities will be encoded as well.
*
* @param string $content The content to encode
*
* @return string The encoded content
*/
public static function escape($content)
{
return htmlspecialchars($content, ENT_COMPAT | ENT_HTML5 | ENT_SUBSTITUTE, 'UTF-8');
}
/**
* sprintf()-like helper method
*
* This allows to use sprintf with ValidHtml elements, but with the
* advantage that they'll not be rendered immediately. The result is an
* instance of FormattedString, being ValidHtml
*
* Usage:
*
* echo Html::sprintf('Hello %s!', Html::tag('strong', $name));
*
* @param $string * @param $string
* @return FormattedString * @return FormattedString
* @throws IcingaException
*/ */
public static function sprintf($string) public static function sprintf($string)
{ {
@ -41,25 +86,13 @@ class Html
} }
/** /**
* Escape the given value top be safely used in view scripts * Accept any input and try to convert it to ValidHtml
*
* Returns the very same element in case it's already valid
* *
* @param string $value The output to be escaped
* @return string
*/
public static function escapeForHtml($value)
{
return htmlspecialchars(
$value,
static::htmlEscapeFlags(),
self::CHARSET,
true
);
}
/**
* @param $any * @param $any
* @return ValidHtml * @return ValidHtml
* @throws IcingaException * @throws InvalidArgumentException
*/ */
public static function wantHtml($any) public static function wantHtml($any)
{ {
@ -75,30 +108,22 @@ class Html
return $html; return $html;
} else { } else {
// TODO: Should we add a dedicated Exception class? throw new InvalidArgumentException(sprintf(
throw new IcingaException(
'String, Html Element or Array of such expected, got "%s"', 'String, Html Element or Array of such expected, got "%s"',
Html::getPhpTypeName($any) Error::getPhpTypeName($any)
); ));
} }
} }
public static function canBeRenderedAsString($any)
{
return is_string($any) || is_int($any) || is_null($any) || is_float($any);
}
/** /**
* Whether a given variable can be rendered as a string
*
* @param $any * @param $any
* @return string * @return bool
*/ */
public static function getPhpTypeName($any) public static function canBeRenderedAsString($any)
{ {
if (is_object($any)) { return is_string($any) || is_int($any) || is_null($any) || is_float($any);
return get_class($any);
} else {
return gettype($any);
}
} }
/** /**
@ -109,101 +134,24 @@ class Html
public static function __callStatic($name, $arguments) public static function __callStatic($name, $arguments)
{ {
$attributes = array_shift($arguments); $attributes = array_shift($arguments);
$content = null; $content = array_shift($arguments);
if ($attributes instanceof ValidHtml || is_string($attributes)) {
$content = $attributes;
$attributes = null;
} elseif (is_array($attributes)) {
if (empty($attributes)) {
$attributes = null;
} elseif (is_int(key($attributes))) {
$content = $attributes;
$attributes = null;
}
}
if (!empty($arguments)) { return static::tag($name, $attributes, $content);
if (null === $content) {
$content = $arguments;
} else {
$content = [$content, $arguments];
}
}
return HtmlElement::create($name, $attributes, $content);
} }
/** /**
* @param Exception|string $error * @deprecated Use {@link Html::encode()} instead
* @return string */
public static function escapeForHtml($content)
{
return static::escape($content);
}
/**
* @deprecated Use {@link Error::render()} instead
*/ */
public static function renderError($error) public static function renderError($error)
{ {
if ($error instanceof Exception) { return Error::render($error);
$file = preg_split('/[\/\\\]/', $error->getFile(), -1, PREG_SPLIT_NO_EMPTY);
$file = array_pop($file);
$msg = sprintf(
'%s (%s:%d)',
$error->getMessage(),
$file,
$error->getLine()
);
} elseif (is_string($error)) {
$msg = $error;
} else {
$msg = 'Got an invalid error'; // TODO: translate?
}
$output = sprintf(
// TODO: translate? Be careful when doing so, it must be failsafe!
"<div class=\"exception\">\n<h1><i class=\"icon-bug\">"
. "</i>Oops, an error occurred!</h1>\n<pre>%s</pre>\n",
static::escapeForHtml($msg)
);
if (static::showTraces()) {
$output .= sprintf(
"<pre>%s</pre>\n",
static::escapeForHtml($error->getTraceAsString())
);
}
$output .= "</div>\n";
return $output;
}
/**
* @param null $show
* @return bool|null
*/
public static function showTraces($show = null)
{
if ($show !== null) {
self::$showTraces = $show;
}
return self::$showTraces;
}
/**
* This defines the flags used when escaping for HTML
*
* - Single quotes are not escaped (ENT_COMPAT)
* - With PHP >= 5.4, invalid characters are replaced with <EFBFBD> (ENT_SUBSTITUTE)
* - With PHP 5.3 they are ignored (ENT_IGNORE, less secure)
* - Uses HTML5 entities for PHP >= 5.4, disallowing &#013;
*
* @return int
*/
protected static function htmlEscapeFlags()
{
if (self::$htmlEscapeFlags === null) {
if (version_compare(PHP_VERSION, '5.4.0') >= 0) {
self::$htmlEscapeFlags = ENT_COMPAT | ENT_SUBSTITUTE | ENT_HTML5;
} else {
self::$htmlEscapeFlags = ENT_COMPAT | ENT_IGNORE;
}
}
return self::$htmlEscapeFlags;
} }
} }

View File

@ -4,13 +4,13 @@ namespace dipl\Html;
use Countable; use Countable;
use Exception; use Exception;
use Icinga\Exception\ProgrammingError; use InvalidArgumentException;
/** /**
* Class Html * Class Html
* @package dipl\Html * @package ipl\Html
*/ */
class HtmlDocument implements ValidHtml, Countable class HtmlDocument implements Countable, ValidHtml
{ {
protected $contentSeparator = ''; protected $contentSeparator = '';
@ -28,7 +28,6 @@ class HtmlDocument implements ValidHtml, Countable
/** /**
* @param ValidHtml|array|string $content * @param ValidHtml|array|string $content
* @return $this * @return $this
* @throws \Icinga\Exception\IcingaException
*/ */
public function add($content) public function add($content)
{ {
@ -96,7 +95,7 @@ class HtmlDocument implements ValidHtml, Countable
/** /**
* @param $tag * @param $tag
* @return BaseHtmlElement * @return BaseHtmlElement
* @throws ProgrammingError * @throws InvalidArgumentException
*/ */
public function getFirst($tag) public function getFirst($tag)
{ {
@ -106,16 +105,15 @@ class HtmlDocument implements ValidHtml, Countable
} }
} }
throw new ProgrammingError( throw new InvalidArgumentException(sprintf(
'Trying to get first %s, but there is no such', 'Trying to get first %s, but there is no such',
$tag $tag
); ));
} }
/** /**
* @param $content * @param $content
* @return $this * @return $this
* @throws \Icinga\Exception\IcingaException
*/ */
public function prepend($content) public function prepend($content)
{ {
@ -149,7 +147,6 @@ class HtmlDocument implements ValidHtml, Countable
/** /**
* @param $string * @param $string
* @return HtmlDocument * @return HtmlDocument
* @throws \Icinga\Exception\IcingaException
*/ */
public function addPrintf($string) public function addPrintf($string)
{ {
@ -164,7 +161,6 @@ class HtmlDocument implements ValidHtml, Countable
/** /**
* @param HtmlDocument|array|string $content * @param HtmlDocument|array|string $content
* @return $this * @return $this
* @throws \Icinga\Exception\IcingaException
*/ */
public function setContent($content) public function setContent($content)
{ {
@ -190,8 +186,6 @@ class HtmlDocument implements ValidHtml, Countable
/** /**
* @return string * @return string
* @throws ProgrammingError
* @throws \Icinga\Exception\IcingaException
*/ */
public function render() public function render()
{ {
@ -204,8 +198,6 @@ class HtmlDocument implements ValidHtml, Countable
/** /**
* @return string * @return string
* @throws ProgrammingError
* @throws \Icinga\Exception\IcingaException
*/ */
protected function renderWrapped() protected function renderWrapped()
{ {
@ -222,8 +214,6 @@ class HtmlDocument implements ValidHtml, Countable
/** /**
* @param HtmlDocument $document * @param HtmlDocument $document
* @return string * @return string
* @throws ProgrammingError
* @throws \Icinga\Exception\IcingaException
*/ */
protected function renderWrappedDocument(HtmlDocument $document) protected function renderWrappedDocument(HtmlDocument $document)
{ {
@ -271,7 +261,7 @@ class HtmlDocument implements ValidHtml, Countable
try { try {
return $this->render(); return $this->render();
} catch (Exception $e) { } catch (Exception $e) {
return Html::renderError($e); return Error::render($e);
} }
} }

View File

@ -2,21 +2,26 @@
namespace dipl\Html; namespace dipl\Html;
/**
* The HtmlElement represents any HTML element
*
* A typical HTML element includes a tag, attributes and content.
*/
class HtmlElement extends BaseHtmlElement class HtmlElement extends BaseHtmlElement
{ {
/** /**
* Container constructor. * Create a new HTML element from the given tag, attributes and content
* *
* @param string $tag * @param string $tag The tag for the element
* @param Attributes|array $attributes * @param Attributes|array $attributes The HTML attributes for the element
* @param ValidHtml|array|string $content * @param ValidHtml|string|array $content The content of the element
*/ */
public function __construct($tag, $attributes = null, $content = null) public function __construct($tag, $attributes = null, $content = null)
{ {
$this->tag = $tag; $this->tag = $tag;
if ($attributes !== null) { if ($attributes !== null) {
$this->attributes = $this->getAttributes()->add($attributes); $this->getAttributes()->add($attributes);
} }
if ($content !== null) { if ($content !== null) {

View File

@ -57,22 +57,10 @@ class Text implements ValidHtml
if ($this->escaped) { if ($this->escaped) {
return $this->string; return $this->string;
} else { } else {
return Html::escapeForHtml($this->string); return Html::escape($this->string);
} }
} }
/**
* TODO: Allow to (statically) inject an error renderer. This will allow
* us to satisfy "Show exceptions" settings and/or preferences
*
* @param Exception|string $error
* @return string
*/
protected function renderError($error)
{
return Html::renderError($error);
}
/** /**
* @return string * @return string
*/ */
@ -81,7 +69,7 @@ class Text implements ValidHtml
try { try {
return $this->render(); return $this->render();
} catch (Exception $e) { } catch (Exception $e) {
return $this->renderError($e); return Error::render($e);
} }
} }
} }

View File

@ -3,19 +3,15 @@
namespace dipl\Html; namespace dipl\Html;
/** /**
* Interface ValidHtml * Interface for HTML elements or primitives that promise to render valid UTF-8 encoded HTML5 with special characters
* * converted to HTML entities
* Implementations of this interface MUST guarantee, that the result of the
* render() method gives valid UTF-8 encoded HTML5.
*/ */
interface ValidHtml interface ValidHtml
{ {
/** /**
* Renders to HTML * Render to HTML
* *
* The result of this method is a valid UTF8-encoded HTML5 string. * @return string UTF-8 encoded HTML5 with special characters converted to HTML entities
*
* @return string
*/ */
public function render(); public function render();
} }