From ea7e79248cbfd907c19e8fee67b77a1c819daec5 Mon Sep 17 00:00:00 2001 From: Thomas Gelf Date: Sun, 27 Nov 2016 23:54:38 +0100 Subject: [PATCH] Html: a bunch of new classes, some changes --- library/Businessprocess/Html/Attribute.php | 2 +- library/Businessprocess/Html/Attributes.php | 23 ++-- library/Businessprocess/Html/BaseElement.php | 130 +++++++++++++++++++ library/Businessprocess/Html/Container.php | 29 ++++- library/Businessprocess/Html/Element.php | 34 +++++ library/Businessprocess/Html/Html.php | 120 +++++++++++++++++ library/Businessprocess/Html/HtmlString.php | 8 ++ library/Businessprocess/Html/Link.php | 20 ++- library/Businessprocess/Html/Renderable.php | 8 ++ library/Businessprocess/Html/Text.php | 61 +++++++++ library/Businessprocess/Html/Util.php | 130 +++++++++++++++++++ 11 files changed, 544 insertions(+), 21 deletions(-) create mode 100644 library/Businessprocess/Html/BaseElement.php create mode 100644 library/Businessprocess/Html/Element.php create mode 100644 library/Businessprocess/Html/Html.php create mode 100644 library/Businessprocess/Html/HtmlString.php create mode 100644 library/Businessprocess/Html/Renderable.php create mode 100644 library/Businessprocess/Html/Text.php create mode 100644 library/Businessprocess/Html/Util.php diff --git a/library/Businessprocess/Html/Attribute.php b/library/Businessprocess/Html/Attribute.php index d0ee15e..9012c3c 100644 --- a/library/Businessprocess/Html/Attribute.php +++ b/library/Businessprocess/Html/Attribute.php @@ -1,6 +1,6 @@ getPhpTypeName($attributes) + Util::getPhpTypeName($attributes) ); } return $self; @@ -74,7 +74,7 @@ class Attributes /** * @return Attribute[] */ - public function attributes() + public function getAttributes() { return $this->attributes; } @@ -87,16 +87,20 @@ class Attributes public function add($attribute, $value = null) { if ($attribute instanceof static) { - foreach ($attribute as $a) { + foreach ($attribute->getAttributes() as $a) { $this->add($a); } - - return $this; } elseif ($attribute instanceof Attribute) { - return $this->addAttribute($attribute); + $this->addAttribute($attribute); + } elseif (is_array($attribute)) { + foreach ($attribute as $name => $value) { + $this->add($name, $value); + } } else { - return $this->addAttribute(Attribute::create($attribute, $value)); + $this->addAttribute(Attribute::create($attribute, $value)); } + + return $this; } /** @@ -151,6 +155,7 @@ class Attributes * * @param $name * @param $callback + * @return $this */ public function registerCallbackFor($name, callable $callback) { diff --git a/library/Businessprocess/Html/BaseElement.php b/library/Businessprocess/Html/BaseElement.php new file mode 100644 index 0000000..8fefed4 --- /dev/null +++ b/library/Businessprocess/Html/BaseElement.php @@ -0,0 +1,130 @@ +attributes === null) { + $default = $this->getDefaultAttributes(); + if (empty($default)) { + $this->attributes = new Attributes(); + } else { + $this->attributes = Attributes::wantAttributes($default); + } + + } + + return $this->attributes; + } + + /** + * @param Attributes|array|null $attributes + * @return $this + */ + public function setAttributes($attributes) + { + $this->attributes = Attributes::wantAttributes($attributes); + return $this; + } + + /** + * @param Attributes|array|null $attributes + * @return $this + */ + public function addAttributes($attributes) + { + $this->attributes = Attributes::wantAttributes($attributes); + return $this; + } + + public function getDefaultAttributes() + { + return $this->defaultAttributes; + } + + public function setTag($tag) + { + $this->tag = $tag; + return $this; + } + + public function getTag() + { + return $this->tag; + } + + public function renderContent() + { + return parent::render(); + } + + /** + * @return string + */ + public function render() + { + $tag = $this->getTag(); + + return sprintf( + '<%s%s>%s', + $tag, + $this->attributes()->render(), + $this->renderContent(), + $tag + ); + } + + protected function translate($msg) + { + // TODO: Not so nice + return mt('businessprocess', $msg); + } + + /** + * Whether the given something can be rendered + * + * @param mixed $any + * @return bool + */ + protected function canBeRendered($any) + { + return is_string($any) || is_int($any) || is_null($any); + } + + /** + * @param Exception|string $error + * @return string + */ + protected function renderError($error) + { + return Util::renderError($error); + } + + /** + * @return string + */ + public function __toString() + { + try { + return $this->render(); + } catch (Exception $e) { + return $this->renderError($e); + } + } +} diff --git a/library/Businessprocess/Html/Container.php b/library/Businessprocess/Html/Container.php index 14e8fc7..6aaba22 100644 --- a/library/Businessprocess/Html/Container.php +++ b/library/Businessprocess/Html/Container.php @@ -1,6 +1,6 @@ setContent($content); + } + + if ($attributes !== null) { + $container->setAttributes($attributes); + } + if ($tag !== null) { + $container->setTag($tag); + } + + return $container; } +} + +class Old { + /** * @inheritdoc */ @@ -64,4 +84,5 @@ class Container extends BaseElement $this->tag ); } -} + +} \ No newline at end of file diff --git a/library/Businessprocess/Html/Element.php b/library/Businessprocess/Html/Element.php new file mode 100644 index 0000000..2f19f7e --- /dev/null +++ b/library/Businessprocess/Html/Element.php @@ -0,0 +1,34 @@ +tag = $tag; + + if ($attributes !== null) { + $this->attributes = $this->attributes()->add($attributes); + } + } + + /** + * Container constructor. + * + * @param string $tag + * @param Attributes|array $attributes + * + * @return static + */ + public static function create($tag, $attributes = null) + { + return new static($tag, $attributes); + } +} diff --git a/library/Businessprocess/Html/Html.php b/library/Businessprocess/Html/Html.php new file mode 100644 index 0000000..eafd2e7 --- /dev/null +++ b/library/Businessprocess/Html/Html.php @@ -0,0 +1,120 @@ +content[] = $element; + return $this; + } + + /** + * @param Renderable|array|string $content + * @return $this + */ + public function setContent($content) + { + $this->content = array( + static::escape($content) + ); + + return $this; + } + + /** + * @param Renderable|array|string $content + * @return $this + */ + public function addContent($content) + { + $this->content[] = static::escape($content); + return $this; + } + + /** + * return Html + */ + public function getContent() + { + if ($this->content === null) { + $this->content = array(new Html()); + } + + return $this->content; + } + + public function hasContent() + { + if ($this->content === null) { + return false; + } + + // TODO: unfinished + // return $this->content->isEmpty(); + return true; + } + + /** + * @param $separator + * @return $this + */ + public function setSeparator($separator) + { + $this->contentSeparator = $separator; + return $this; + } + + /** + * @inheritdoc + */ + public function render() + { + $html = array(); + + foreach ($this->content as $element) { + if (is_string($element)) { + var_dump($this->content); + } + $html[] = $element->render(); + } + + return implode($this->contentSeparator, $html); + } + + public static function element($name, $attributes = null) + { + // TODO: This might be anything here, add a better check + if (! ctype_alnum($name)) { + throw new ProgrammingError('Invalid element requested'); + } + + $class = __NAMESPACE__ . '\\' . $name; + /** @var Element $element */ + $element = new $class(); + if ($attributes !== null) { + $element->setAttributes($attributes); + } + + return $element; + } +} diff --git a/library/Businessprocess/Html/HtmlString.php b/library/Businessprocess/Html/HtmlString.php new file mode 100644 index 0000000..559c903 --- /dev/null +++ b/library/Businessprocess/Html/HtmlString.php @@ -0,0 +1,8 @@ +content = Util::wantHtml($content); - $link->attributes()->registerCallbackFor('href', array($link, 'getHrefAttribute')); + $link->setContent($content); $link->setAttributes($attributes); + $link->attributes()->registerCallbackFor('href', array($link, 'getHrefAttribute')); + $link->setUrl($url, $urlParams); return $link; } @@ -39,15 +44,16 @@ class Link extends BaseElement $url->addParams($urlParams); } - $link->url = $url; + $this->url = $url; } else { if ($urlParams === null) { - $link->url = Url::fromPath($url); + $this->url = Url::fromPath($url); } else { - $link->url = Url::fromPath($url, $urlParams); + $this->url = Url::fromPath($url, $urlParams); } } - $link->url->getParams(); + + $this->url->getParams(); } /** diff --git a/library/Businessprocess/Html/Renderable.php b/library/Businessprocess/Html/Renderable.php new file mode 100644 index 0000000..7c1a560 --- /dev/null +++ b/library/Businessprocess/Html/Renderable.php @@ -0,0 +1,8 @@ +string = (string) $string; + } + + /** + * @return string + */ + public function getText() + { + return $this->string; + } + + /** + * @param bool $escaped + * @return $this + */ + public function setEscaped($escaped = true) + { + $this->escaped = $escaped; + return $this; + } + + /** + * @param $text + * + * @return static + */ + public static function create($text) + { + return new static($text); + } + + /** + * @return string + */ + public function render() + { + if ($this->escaped) { + return $this->string; + } else { + return Util::escapeForHtml($this->string); + } + } +} \ No newline at end of file diff --git a/library/Businessprocess/Html/Util.php b/library/Businessprocess/Html/Util.php new file mode 100644 index 0000000..ee82eb0 --- /dev/null +++ b/library/Businessprocess/Html/Util.php @@ -0,0 +1,130 @@ +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? + } + + return sprintf( + 'ERROR: %s', // TODO: translate? + static::escapeForHtml($msg) + ); + } + + /** + * @param $any + * @return Renderable + * @throws IcingaException + */ + public static function wantHtml($any) + { + if ($any instanceof Renderable) { + return $any; + } elseif (static::canBeRenderedAsString($any)) { + return new Text($any); + } elseif (is_array($any)) { + $html = new Html(); + foreach ($any as $el) { + $html->add(static::wantHtml($el)); + } + + return $html; + } else { + // TODO: Should we add a dedicated Exception class? + throw new IcingaException( + 'String, Html Element or Array of such expected, got "%s"', + Util::getPhpTypeName($any) + ); + } + } + + public static function canBeRenderedAsString($any) + { + return is_string($any) || is_int($any) || is_null($any); + } + + /** + * @param $any + * @return string + */ + public static function getPhpTypeName($any) + { + if (is_object($any)) { + return get_class($any); + } else { + return gettype($any); + } + } + + /** + * 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 � (ENT_SUBSTITUTE) + * - With PHP 5.3 they are ignored (ENT_IGNORE, less secure) + * - Uses HTML5 entities for PHP >= 5.4, disallowing + * + * @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; + } +}