use wcf\system\html\input\filter\MessageHtmlInputFilter;
use wcf\system\html\input\node\HtmlInputNodeProcessor;
use wcf\system\html\input\node\IHtmlInputNodeProcessor;
-use wcf\system\html\node\IHtmlNodeProcessor;
use wcf\util\StringUtil;
/**
- * TOOD documentation
- * @since 3.0
+ * Reads a HTML string, applies filters and parses all nodes including bbcodes.
+ *
+ * @author Alexander Ebert
+ * @copyright 2001-2016 WoltLab GmbH
+ * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package WoltLabSuite\Core\System\Html\Input
+ * @since 3.0
*/
class HtmlInputProcessor {
+ /**
+ * list of embedded content grouped by type
+ * @var array
+ */
protected $embeddedContent = [];
/**
*/
protected $htmlInputNodeProcessor;
+ /**
+ * Processes input HTML by applying filters and parsing all nodes
+ * including bbcodes.
+ *
+ * @param string $html html string
+ */
public function process($html) {
// enforce consistent newlines
$html = StringUtil::unifyNewlines($html);
// TODO
}
+ /**
+ * Returns the parsed HTML ready to store.
+ *
+ * @return string parsed html
+ */
public function getHtml() {
return $this->getHtmlInputNodeProcessor()->getHtml();
}
+ /**
+ * Returns the all embedded content data.
+ *
+ * @return array
+ */
+ public function getEmbeddedContent() {
+ return $this->embeddedContent;
+ }
+
/**
* @return IHtmlInputFilter
*/
- public function getHtmlInputFilter() {
+ protected function getHtmlInputFilter() {
if ($this->htmlInputFilter === null) {
$this->htmlInputFilter = new MessageHtmlInputFilter();
}
return $this->htmlInputFilter;
}
- public function setHtmlInputFilter(IHtmlInputFilter $htmlInputFilter) {
- $this->htmlInputFilter = $htmlInputFilter;
- }
-
/**
* @return IHtmlInputNodeProcessor
*/
- public function getHtmlInputNodeProcessor() {
+ protected function getHtmlInputNodeProcessor() {
if ($this->htmlInputNodeProcessor === null) {
$this->htmlInputNodeProcessor = new HtmlInputNodeProcessor();
}
return $this->htmlInputNodeProcessor;
}
-
- public function setHtmlInputNodeProcessor(IHtmlNodeProcessor $htmlInputNodeProcessor) {
- $this->htmlInputNodeProcessor = $htmlInputNodeProcessor;
- }
-
- public function getEmbeddedContent() {
- return $this->embeddedContent;
- }
}
namespace wcf\system\html\input\filter;
/**
- * TOOD documentation
- * @since 3.0
+ * Default interface for html input filters.
+ *
+ * @author Alexander Ebert
+ * @copyright 2001-2016 WoltLab GmbH
+ * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package WoltLabSuite\Core\System\Html\Input\Filter
+ * @since 3.0
*/
interface IHtmlInputFilter {
/**
<?php
namespace wcf\system\html\input\filter;
+use wcf\system\event\EventHandler;
/**
- * TOOD documentation
- * @since 3.0
+ * HTML input filter using HTMLPurifier.
+ *
+ * @author Alexander Ebert
+ * @copyright 2001-2016 WoltLab GmbH
+ * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package WoltLabSuite\Core\System\Html\Input\Filter
+ * @since 3.0
*/
class MessageHtmlInputFilter implements IHtmlInputFilter {
/**
*/
protected static $purifier;
+ /**
+ * Applies HTMLPurifier's filter on provided HTML.
+ *
+ * @param string $html unsafe HTML
+ * @return string sanitized HTML
+ */
public function apply($html) {
return $this->getPurifier()->purify($html);
}
return self::$purifier;
}
+ /**
+ * Sets required configuration data for HTML filter.
+ *
+ * @param \HTMLPurifier_Config $config HTMLPurifier configuration
+ */
protected function setAttributeDefinitions(\HTMLPurifier_Config $config) {
- // TODO: move this into own PHP classes
$definition = $config->getHTMLDefinition(true);
// quotes
// add data-attachment-id="" for <img>
$definition->addAttribute('img', 'data-attachment-id', 'Number');
+
+ $parameters = [
+ 'config' => $config,
+ 'definition' => $definition
+ ];
+ EventHandler::getInstance()->fireAction($this, 'setAttributeDefinitions', $parameters);
}
}
<?php
namespace wcf\system\html\input\node;
use wcf\system\html\node\AbstractHtmlNode;
-use wcf\system\html\node\HtmlNodeProcessor;
+use wcf\system\html\node\AbstractHtmlNodeProcessor;
use wcf\util\DOMUtil;
use wcf\util\JSON;
/**
- * TOOD documentation
- * @since 3.0
+ * Proccesses `<img>` to handle embedded attachments.
+ *
+ * @author Alexander Ebert
+ * @copyright 2001-2016 WoltLab GmbH
+ * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package WoltLabSuite\Core\System\Html\Input\Node
+ * @since 3.0
*/
class HtmlInputNodeImg extends AbstractHtmlNode {
+ /**
+ * @inheritDoc
+ */
protected $tagName = 'img';
- public function process(array $elements, HtmlNodeProcessor $htmlNodeProcessor) {
+ /**
+ * @inheritDoc
+ */
+ public function process(array $elements, AbstractHtmlNodeProcessor $htmlNodeProcessor) {
/** @var \DOMElement $element */
foreach ($elements as $element) {
$class = $element->getAttribute('class');
- if ($class !== 'woltlabAttachment') {
+ if (!preg_match('~\bwoltlabAttachment\b~', $class)) {
continue;
}
continue;
}
- // TODO: add alignment detection
- $alignment = 'none';
+ $float = 'none';
$thumbnail = false;
if (strpos($element->getAttribute('src'), 'thumbnail=1') !== false) {
$thumbnail = true;
}
+ if (preg_match('~\bmessageFloatObject(?P<float>Left|Right)\b~', $class, $matches)) {
+ $float = ($matches['float'] === 'Left') ? 'left' : 'right';
+ }
+
$attributes = [
$attachmentID,
- $alignment,
+ $float,
$thumbnail
];
<?php
namespace wcf\system\html\input\node;
use wcf\system\event\EventHandler;
-use wcf\system\html\node\HtmlNodeProcessor;
-use wcf\util\DOMUtil;
+use wcf\system\html\node\AbstractHtmlNodeProcessor;
/**
- * TOOD documentation
- * @since 3.0
+ * Processes HTML nodes and handles bbcodes.
+ *
+ * @author Alexander Ebert
+ * @copyright 2001-2016 WoltLab GmbH
+ * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package WoltLabSuite\Core\System\Html\Input\Node
+ * @since 3.0
*/
-class HtmlInputNodeProcessor extends HtmlNodeProcessor implements IHtmlInputNodeProcessor {
+class HtmlInputNodeProcessor extends AbstractHtmlNodeProcessor {
+ /**
+ * list of embedded content grouped by type
+ * @var array
+ */
protected $embeddedContent = [];
- // TODO: this should include other tags
- protected $emptyTags = ['em', 'strong', 'u'];
-
- // TODO: this should include other tags
- protected $mergeTags = ['em', 'strong', 'u'];
-
+ /**
+ * @inheritDoc
+ */
public function process() {
EventHandler::getInstance()->fireAction($this, 'beforeProcess');
$this->invokeHtmlNode(new HtmlInputNodeWoltlabMetacode());
$this->invokeHtmlNode(new HtmlInputNodeImg());
+ // dynamic node handlers
+ $this->invokeNodeHandlers('wcf\system\html\input\node\HtmlInputNode', ['img', 'woltlab-metacode']);
+
// detect mentions, urls, emails and smileys
$textParser = new HtmlInputNodeTextParser($this);
$textParser->parse();
// extract embedded content
$this->parseEmbeddedContent();
- // remove empty elements and join identical siblings if appropriate
- $this->cleanup();
-
EventHandler::getInstance()->fireAction($this, 'afterProcess');
}
/**
- * @inheritDoc
+ * Returns the embedded content grouped by type.
+ *
+ * @return array
*/
public function getEmbeddedContent() {
return $this->embeddedContent;
}
+ /**
+ * Add embedded content for provided type.
+ *
+ * @param string $type type name
+ * @param array $data embedded content
+ */
public function addEmbeddedContent($type, array $data) {
if (isset($this->embeddedContent[$type])) {
$this->embeddedContent[$type] = array_merge($this->embeddedContent[$type], $data);
}
}
+ /**
+ * Parses embedded content containedin metacode elements.
+ */
protected function parseEmbeddedContent() {
// handle `woltlab-metacode`
$elements = $this->getDocument()->getElementsByTagName('woltlab-metacode');
EventHandler::getInstance()->fireAction($this, 'parseEmbeddedContent');
}
- protected function cleanup() {
- // remove emtpy elements
- foreach ($this->emptyTags as $emptyTag) {
- $elements = [];
- foreach ($this->getDocument()->getElementsByTagName($emptyTag) as $element) {
- $elements[] = $element;
- }
-
- /** @var \DOMElement $element */
- foreach ($elements as $element) {
- if (DOMUtil::isEmpty($element)) {
- DOMUtil::removeNode($element);
- }
- }
- }
-
- // find identical siblings
- foreach ($this->mergeTags as $mergeTag) {
- $elements = [];
- foreach ($this->getDocument()->getElementsByTagName($mergeTag) as $element) {
- $elements[] = $element;
- }
-
- /** @var \DOMElement $element */
- foreach ($elements as $element) {
- $sibling = $element->nextSibling;
- if ($sibling === null) {
- continue;
- }
-
- if ($sibling->nodeName === $mergeTag) {
- while ($sibling->hasChildNodes()) {
- $element->appendChild($sibling->childNodes[0]);
- }
-
- DOMUtil::removeNode($sibling);
- }
- }
- }
- }
-
/**
* Creates a new `<woltlab-metacode>` element contained in the same document
* as the provided `$node`.
use wcf\util\StringUtil;
/**
- * TOOD documentation
+ * Parses all text nodes searching for links, media, mentions or smilies.
+ *
+ * @author Alexander Ebert
+ * @copyright 2001-2016 WoltLab GmbH
+ * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package WoltLabSuite\Core\System\Html\Input\Node
* @since 3.0
*/
class HtmlInputNodeTextParser {
+ /**
+ * list of markers per element that will face a replacement
+ * @var \DOMElement[][]
+ */
protected $elementStack = [];
/**
*/
protected $htmlInputNodeProcessor;
+ /**
+ * list of text nodes that will face a replacement
+ * @var \DOMText[]
+ */
protected $nodeStack = [];
+ /**
+ * list of smilies by smiley code
+ * @var string[]
+ */
protected $smilies = [];
/**
*/
protected static $illegalChars = '[^\x0-\x2C\x2E\x2F\x3A-\x40\x5B-\x60\x7B-\x7F]+';
+ /**
+ * regex for user mentions
+ * @var string
+ */
protected static $userRegex = "~
\\B # any non-word character, whitespace, string start is fine
@
)
~x";
+ /**
+ * HtmlInputNodeTextParser constructor.
+ *
+ * @param HtmlInputNodeProcessor $htmlInputNodeProcessor
+ */
public function __construct(HtmlInputNodeProcessor $htmlInputNodeProcessor) {
$this->htmlInputNodeProcessor = $htmlInputNodeProcessor;
$this->sourceBBCodes = HtmlBBCodeParser::getInstance()->getSourceBBCodes();
}
}
+ /**
+ * Parses all text nodes searching for possible replacements.
+ */
public function parse() {
// get all text nodes
$nodes = [];
$users = [];
if (!empty($usernames)) {
- $users = $this->findUsernames($usernames);
+ $users = $this->lookupUsernames($usernames);
}
for ($i = 0, $length = count($nodes); $i < $length; $i++) {
}
}
+ /**
+ * Detects mentions in text nodes.
+ *
+ * @param \DOMText $text text node
+ * @param string $value node value
+ * @param string[] $usernames list of already found usernames
+ */
protected function detectMention(\DOMText $text, $value, array &$usernames) {
if (mb_strpos($value, '@') === false) {
return;
}
}
- protected function findUsernames(array $usernames) {
+ /**
+ * Matches the found usernames agains the user table.
+ *
+ * @param string[] $usernames list of found usernames
+ * @return string[] list of valid usernames
+ */
+ protected function lookupUsernames(array $usernames) {
$exactValues = [];
$likeValues = [];
foreach ($usernames as $username) {
return $users;
}
+ /**
+ * Parses text nodes and searches for mentions.
+ *
+ * @param \DOMText $text text node
+ * @param string $value node value
+ * @param string[] $users list of usernames by user id
+ * @return string modified node value with replacement placeholders
+ */
protected function parseMention(\DOMText $text, $value, array $users) {
if (mb_strpos($value, '@') === false) {
return $value;
return $value;
}
+ /**
+ * Parses regular links and media links contained in text nodes.
+ *
+ * @param \DOMText $text text node
+ * @param string $value node value
+ * @return string modified node value with replacement placeholders
+ */
protected function parseURL(\DOMText $text, $value) {
static $urlPattern = '';
if ($urlPattern === '') {
}, $value);
}
+ /**
+ * Parses text nodes and replaces email addresses.
+ *
+ * @param \DOMText $text text node
+ * @param string $value node value
+ * @return string modified node value with replacement placeholders
+ */
protected function parseEmail(\DOMText $text, $value) {
if (mb_strpos($this->text, '@') === false) {
return $value;
}, $value);
}
+ /**
+ * Parses text nodes and replaces smilies.
+ *
+ * @param \DOMText $text text node
+ * @param string $value node value
+ * @return string modified node value with replacement placeholders
+ */
protected function parseSmiley(\DOMText $text, $value) {
static $smileyPattern = null;
if ($smileyPattern === null) {
}, $value);
}
+ /**
+ * Replaces all found occurences of special text with their new value.
+ *
+ * @param \DOMText $text text node
+ * @param \DOMElement[] $elements elements to be inserted
+ */
protected function replaceMatches(\DOMText $text, array $elements) {
$nodes = [$text];
}
}
+ /**
+ * Returns true if text node is inside a code element, suppresing any
+ * auto-detection of content.
+ *
+ * @param \DOMText $text text node
+ * @return boolean true if text node is inside a code element
+ */
protected function hasCodeParent(\DOMText $text) {
$parent = $text;
/** @var \DOMElement $parent */
while ($parent = $parent->parentNode) {
$nodeName = $parent->nodeName;
- if ($nodeName === 'code' || $nodeName === 'kbd') {
+ if ($nodeName === 'code' || $nodeName === 'kbd' || $nodeName === 'pre') {
return true;
}
else if ($nodeName === 'woltlab-metacode' && in_array($parent->getAttribute('data-name'), $this->sourceBBCodes)) {
return false;
}
+ /**
+ * Returns true if text node is inside a link, preventing the link content
+ * being recognized as a link again.
+ *
+ * @param \DOMText $text text node
+ * @return boolean true if text node is inside a link
+ */
protected function hasLinkParent(\DOMText $text) {
$parent = $text;
/** @var \DOMElement $parent */
return false;
}
+ /**
+ * Uses string markers to replace the matched text. This process prevents multiple
+ * detections being applied to the same target and enables us to delay replacement.
+ *
+ * Immediately replacing matches would potentially cause a lot of DOM modifications
+ * and moving of nodes especially if there are multiple matches per text node.
+ *
+ * @param \DOMText $text text node
+ * @param \DOMElement $element element queued for insertion
+ * @return string replacement marker
+ */
public function addReplacement(\DOMText $text, \DOMElement $element) {
$index = array_search($text, $this->nodeStack, true);
if ($index === false) {
return $marker;
}
+ /**
+ * Returns a random string marker for replacement.
+ *
+ * @return string random string marker
+ */
public function getNewMarker() {
return '@@@' . StringUtil::getUUID() . '@@@';
}
/**
- * Returns the username for the given regular expression match.
- *
- * @param string $match
- * @return string
- * @since 3.0
+ * Returns the username for the given regular expression match and takes care
+ * of any quotes outside the username and certain special characters, such as
+ * colons, that have been incorrectly matched.
+ *
+ * @param string $match matched username
+ * @return string sanitized username
*/
public function getUsername($match) {
// remove escaped single quotation mark
<?php
namespace wcf\system\html\input\node;
use wcf\system\html\node\AbstractHtmlNode;
-use wcf\system\html\node\HtmlNodeProcessor;
+use wcf\system\html\node\AbstractHtmlNodeProcessor;
/**
- * TOOD documentation
- * @since 3.0
+ * Proccesses `<woltlab-mention>`.
+ *
+ * @author Alexander Ebert
+ * @copyright 2001-2016 WoltLab GmbH
+ * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package WoltLabSuite\Core\System\Html\Input\Node
+ * @since 3.0
*/
class HtmlInputNodeWoltlabMention extends AbstractHtmlNode {
+ /**
+ * @inheritDoc
+ */
protected $tagName = 'woltlab-mention';
- public function process(array $elements, HtmlNodeProcessor $htmlNodeProcessor) {
+ /**
+ * @inheritDoc
+ */
+ public function process(array $elements, AbstractHtmlNodeProcessor $htmlNodeProcessor) {
+ // TODO
+
$userIds = [];
/** @var \DOMElement $mention */
}
}
-
- public function replaceTag(array $data) {
- return null;
- }
}
namespace wcf\system\html\input\node;
use wcf\system\html\metacode\converter\IMetacodeConverter;
use wcf\system\html\node\AbstractHtmlNode;
-use wcf\system\html\node\HtmlNodeProcessor;
+use wcf\system\html\node\AbstractHtmlNodeProcessor;
use wcf\util\DOMUtil;
/**
- * TOOD documentation
- * @since 3.0
+ * Proccesses `<woltlab-metacode>` and converts them if appropriate.
+ *
+ * @author Alexander Ebert
+ * @copyright 2001-2016 WoltLab GmbH
+ * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package WoltLabSuite\Core\System\Html\Input\Node
+ * @since 3.0
*/
class HtmlInputNodeWoltlabMetacode extends AbstractHtmlNode {
/**
'u' => 'u'
];
+ /**
+ * @inheritDoc
+ */
protected $tagName = 'woltlab-metacode';
- public function process(array $elements, HtmlNodeProcessor $htmlNodeProcessor) {
+ /**
+ * @inheritDoc
+ */
+ public function process(array $elements, AbstractHtmlNodeProcessor $htmlNodeProcessor) {
/** @var IMetacodeConverter[] $converters */
$converters = [];
}
}
+ /**
+ * @inheritDoc
+ */
public function replaceTag(array $data) {
return $data['parsedTag'];
}
-
- protected function getPlaceholderElement() {
- return new \DOMElement('woltlab-placeholder');
- }
}
namespace wcf\system\html\input\node;
use wcf\system\bbcode\HtmlBBCodeParser;
use wcf\system\html\node\AbstractHtmlNode;
-use wcf\system\html\node\HtmlNodeProcessor;
+use wcf\system\html\node\AbstractHtmlNodeProcessor;
use wcf\util\DOMUtil;
/**
/**
* @inheritDoc
*/
- public function process(array $elements, HtmlNodeProcessor $htmlNodeProcessor) {
+ public function process(array $elements, AbstractHtmlNodeProcessor $htmlNodeProcessor) {
// collect pairs
$pairs = $this->buildPairs($elements);
while ($parent = $parent->parentNode) {
$nodeName = $parent->nodeName;
- if ($nodeName === 'code' || $nodeName === 'kbd') {
+ if ($nodeName === 'code' || $nodeName === 'kbd' || $nodeName === 'pre') {
return true;
}
else if ($nodeName === 'woltlab-metacode') {
use wcf\system\html\node\IHtmlNode;
/**
- * TOOD documentation
- * @since 3.0
+ * Default interface for html input nodes.
+ *
+ * @author Alexander Ebert
+ * @copyright 2001-2016 WoltLab GmbH
+ * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package WoltLabSuite\Core\System\Html\Input\Node
+ * @since 3.0
*/
interface IHtmlInputNode extends IHtmlNode {}
+++ /dev/null
-<?php
-namespace wcf\system\html\input\node;
-use wcf\system\html\node\IHtmlNodeProcessor;
-
-/**
- * @since 3.0
- */
-interface IHtmlInputNodeProcessor extends IHtmlNodeProcessor {
- public function getEmbeddedContent();
-
- public function process();
-}
namespace wcf\system\html\metacode\converter;
/**
- * TOOD documentation
- * @since 3.0
+ * Default implementation for metacode converters.
+ *
+ * @author Alexander Ebert
+ * @copyright 2001-2016 WoltLab GmbH
+ * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package WoltLabSuite\Core\System\Html\Metacode\Converter
+ * @since 3.0
*/
abstract class AbstractMetacodeConverter implements IMetacodeConverter {
/**
namespace wcf\system\html\metacode\converter;
/**
- * TOOD documentation
- * @since 3.0
+ * Converts code bbcode into `<pre>`.
+ *
+ * @author Alexander Ebert
+ * @copyright 2001-2016 WoltLab GmbH
+ * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package WoltLabSuite\Core\System\Html\Metacode\Converter
+ * @since 3.0
*/
class CodeMetacodeConverter extends AbstractMetacodeConverter {
/**
namespace wcf\system\html\metacode\converter;
/**
- * TOOD documentation
- * @since 3.0
+ * Converts color bbcode into `<woltlab-color>`.
+ *
+ * @author Alexander Ebert
+ * @copyright 2001-2016 WoltLab GmbH
+ * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package WoltLabSuite\Core\System\Html\Metacode\Converter
+ * @since 3.0
*/
class ColorMetacodeConverter extends AbstractMetacodeConverter {
/**
namespace wcf\system\html\metacode\converter;
/**
- * TOOD documentation
- * @since 3.0
+ * Default interface for metacode converters.
+ *
+ * @author Alexander Ebert
+ * @copyright 2001-2016 WoltLab GmbH
+ * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package WoltLabSuite\Core\System\Html\Metacode\Converter
+ * @since 3.0
*/
interface IMetacodeConverter {
/**
namespace wcf\system\html\metacode\converter;
/**
- * TOOD documentation
- * @since 3.0
+ * Converts quote bbcode into `<blockquote>`.
+ *
+ * @author Alexander Ebert
+ * @copyright 2001-2016 WoltLab GmbH
+ * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package WoltLabSuite\Core\System\Html\Metacode\Converter
+ * @since 3.0
*/
class QuoteMetacodeConverter extends AbstractMetacodeConverter {
/**
*/
public function convert(\DOMDocumentFragment $fragment, array $attributes) {
$element = $fragment->ownerDocument->createElement('blockquote');
- $element->setAttribute('class', 'quoteBox');
$element->setAttribute('data-quote-title', (isset($attributes[0])) ? $attributes[0] : '');
$element->setAttribute('data-quote-url', (isset($attributes[1])) ? $attributes[1] : '');
$element->appendChild($fragment);
namespace wcf\system\html\metacode\converter;
/**
- * TOOD documentation
- * @since 3.0
+ * Converts size bbcode into `<woltlab-size>`.
+ *
+ * @author Alexander Ebert
+ * @copyright 2001-2016 WoltLab GmbH
+ * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package WoltLabSuite\Core\System\Html\Metacode\Converter
+ * @since 3.0
*/
class SizeMetacodeConverter extends AbstractMetacodeConverter {
protected $sizes = [8, 10, 12, 14, 18, 24, 36];
use wcf\util\StringUtil;
/**
- * TOOD documentation
- * @since 3.0
+ * Converts spoiler bbcode into `<woltlab-spoiler>`.
+ *
+ * @author Alexander Ebert
+ * @copyright 2001-2016 WoltLab GmbH
+ * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package WoltLabSuite\Core\System\Html\Metacode\Converter
+ * @since 3.0
*/
class SpoilerMetacodeConverter extends AbstractMetacodeConverter {
/**
namespace wcf\system\html\node;
/**
- * TOOD documentation
- * @since 3.0
+ * Default implementation for html nodes.
+ *
+ * @author Alexander Ebert
+ * @copyright 2001-2016 WoltLab GmbH
+ * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package WoltLabSuite\Core\System\Html\Node
+ * @since 3.0
*/
abstract class AbstractHtmlNode implements IHtmlNode {
+ /**
+ * tag name used to identify elements consumed by this node
+ * @var string
+ */
protected $tagName = '';
+ /**
+ * placeholder for inner content when performing direct html replacement
+ * @var string
+ */
const PLACEHOLDER = '<!-- META_CODE_INNER_CONTENT -->';
+ /**
+ * @inheritDoc
+ */
public function getTagName() {
return $this->tagName;
}
+ /**
+ * @inheritDoc
+ */
public function replaceTag(array $data) {
throw new \BadMethodCallException("Method replaceTag() is not supported by ".get_class($this));
}
--- /dev/null
+<?php
+namespace wcf\system\html\node;
+use wcf\system\exception\SystemException;
+use wcf\util\JSON;
+
+/**
+ * Default implementation for html node processors.
+ *
+ * @author Alexander Ebert
+ * @copyright 2001-2016 WoltLab GmbH
+ * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package WoltLabSuite\Core\System\Html\Node
+ * @since 3.0
+ */
+abstract class AbstractHtmlNodeProcessor implements IHtmlNodeProcessor {
+ /**
+ * active DOM document
+ * @var \DOMDocument
+ */
+ protected $document;
+
+ /**
+ * storage for node replacements
+ * @var array
+ */
+ protected $nodeData = [];
+
+ /**
+ * XPath instance
+ * @var \DOMXPath
+ */
+ protected $xpath;
+
+ /**
+ * @inheritDOc
+ */
+ public function load($html) {
+ $this->document = new \DOMDocument('1.0', 'UTF-8');
+ $this->xpath = null;
+
+ // Ignore all errors when loading the HTML string, because DOMDocument does not
+ // provide a proper way to add custom HTML elements (even though explicitly allowed
+ // in HTML5) and the input HTML has already been sanitized by HTMLPurifier.
+ //
+ // We're also injecting a bogus meta tag that magically enables DOMDocument
+ // to handle UTF-8 properly. This avoids encoding non-ASCII characters as it
+ // would conflict with already existing entities when reverting them.
+ @$this->document->loadHTML('<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />' . $html);
+
+ $this->nodeData = [];
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function getHtml() {
+ $html = $this->document->saveHTML($this->document->getElementsByTagName('body')->item(0));
+
+ // remove nuisance added by PHP
+ $html = preg_replace('~^<body>~', '', $html);
+ $html = preg_replace('~</body>$~', '', $html);
+
+ /** @var IHtmlNode $obj */
+ foreach ($this->nodeData as $data) {
+ $obj = $data['object'];
+ $string = $obj->replaceTag($data['data']);
+ $html = preg_replace_callback('~<wcfNode-' . $data['identifier'] . '>(?P<content>[\s\S]*)</wcfNode-' . $data['identifier'] . '>~', function($matches) use ($string) {
+ $string = str_replace('<!-- META_CODE_INNER_CONTENT -->', $matches['content'], $string);
+
+ return $string;
+ }, $html);
+
+ }
+
+ return $html;
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function getDocument() {
+ return $this->document;
+ }
+
+ /**
+ * Returns a XPath instance for the current DOM document.
+ *
+ * @return \DOMXPath XPath instance
+ */
+ public function getXPath() {
+ if ($this->xpath === null) {
+ $this->xpath = new \DOMXPath($this->getDocument());
+ }
+
+ return $this->xpath;
+ }
+
+ /**
+ * Renames a tag by creating a new element, moving all child nodes and
+ * eventually removing the original element.
+ *
+ * @param \DOMElement $element old element
+ * @param string $tagName tag name for the new element
+ * @return \DOMElement newly created element
+ */
+ public function renameTag(\DOMElement $element, $tagName) {
+ $newElement = $this->document->createElement($tagName);
+ $element->parentNode->insertBefore($newElement, $element);
+ while ($element->hasChildNodes()) {
+ $newElement->appendChild($element->firstChild);
+ }
+
+ $element->parentNode->removeChild($element);
+
+ return $newElement;
+ }
+
+ /**
+ * Removes an element but preserves child nodes by moving them into
+ * its original position.
+ *
+ * @param \DOMElement $element element to be removed
+ */
+ public function unwrapContent(\DOMElement $element) {
+ while ($element->hasChildNodes()) {
+ $element->parentNode->insertBefore($element->firstChild, $element);
+ }
+
+ $element->parentNode->removeChild($element);
+ }
+
+ /**
+ * Adds node replacement data.
+ *
+ * @param IHtmlNode $htmlNode node processor instance
+ * @param string $nodeIdentifier replacement node identifier
+ * @param array $data replacement data
+ */
+ public function addNodeData(IHtmlNode $htmlNode, $nodeIdentifier, array $data) {
+ $this->nodeData[] = [
+ 'data' => $data,
+ 'identifier' => $nodeIdentifier,
+ 'object' => $htmlNode
+ ];
+ }
+
+ /**
+ * Parses an attribute string.
+ *
+ * @param string $attributes base64 and JSON encoded attributes
+ * @return array parsed attributes
+ */
+ public function parseAttributes($attributes) {
+ if (empty($attributes)) {
+ return [];
+ }
+
+ $parsedAttributes = base64_decode($attributes, true);
+ if ($parsedAttributes !== false) {
+ try {
+ $parsedAttributes = JSON::decode($parsedAttributes);
+ }
+ catch (SystemException $e) {
+ /* parse errors can occur if user provided malicious content - ignore them */
+ $parsedAttributes = [];
+ }
+ }
+
+ return $parsedAttributes;
+ }
+
+ /**
+ * Invokes a html node processor.
+ *
+ * @param IHtmlNode $htmlNode html node processor
+ */
+ protected function invokeHtmlNode(IHtmlNode $htmlNode) {
+ $tagName = $htmlNode->getTagName();
+ if (empty($tagName)) {
+ throw new \UnexpectedValueException("Missing tag name for " . get_class($htmlNode));
+ }
+
+ $elements = [];
+ foreach ($this->getDocument()->getElementsByTagName($tagName) as $element) {
+ $elements[] = $element;
+ }
+
+ if (!empty($elements)) {
+ $htmlNode->process($elements, $this);
+ }
+ }
+
+ /**
+ * Invokes possible html node processors based on found element tag names.
+ *
+ * @param string $classNamePattern full namespace pattern for class guessing
+ * @param string[] $skipTags list of tag names that should be ignored
+ */
+ protected function invokeNodeHandlers($classNamePattern, array $skipTags = []) {
+ $skipTags = array_merge($skipTags, ['html', 'head', 'title', 'meta', 'body', 'link']);
+
+ $tags = [];
+ /** @var \DOMElement $tag */
+ foreach ($this->getDocument()->getElementsByTagName('*') as $tag) {
+ $tagName = $tag->nodeName;
+ if (!isset($tags[$tagName])) $tags[$tagName] = $tagName;
+ }
+
+ foreach ($tags as $tagName) {
+ if (in_array($tagName, $skipTags)) {
+ continue;
+ }
+
+ $tagName = preg_replace_callback('/-([a-z])/', function($matches) {
+ return ucfirst($matches[1]);
+ }, $tagName);
+ $className = $classNamePattern . ucfirst($tagName);
+ if (class_exists($className)) {
+ $this->invokeHtmlNode(new $className);
+ }
+ }
+ }
+}
+++ /dev/null
-<?php
-namespace wcf\system\html\node;
-use wcf\system\exception\SystemException;
-use wcf\util\JSON;
-
-/**
- * TOOD documentation
- * @since 3.0
- */
-class HtmlNodeProcessor implements IHtmlNodeProcessor {
- /**
- * @var \DOMDocument
- */
- protected $document;
-
- protected $nodeData = [];
-
- /**
- * @var \DOMXPath
- */
- protected $xpath;
-
- public function load($html) {
- $this->document = new \DOMDocument('1.0', 'UTF-8');
- $this->xpath = null;
-
- // ignore all errors when loading the HTML string, because DOMDocument does not
- // provide a proper way to add custom HTML elements (even though explicitly allowed
- // in HTML5) and the input HTML has already been sanitized by HTMLPurifier
- //
- // we're also injecting a bogus meta tag that magically enables DOMDocument
- // to handle UTF-8 properly, this avoids encoding non-ASCII characters as it
- // would conflict with already existing entities when reverting them
- @$this->document->loadHTML('<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />' . $html);
-
- $this->nodeData = [];
- }
-
- public function getHtml() {
- $html = $this->document->saveHTML($this->document->getElementsByTagName('body')->item(0));
-
- // remove nuisance added by PHP
- $html = preg_replace('~^<body>~', '', $html);
- $html = preg_replace('~</body>$~', '', $html);
-
- /** @var IHtmlNode $obj */
- foreach ($this->nodeData as $data) {
- $obj = $data['object'];
- $string = $obj->replaceTag($data['data']);
- $html = preg_replace_callback('~<wcfNode-' . $data['identifier'] . '>(?P<content>[\s\S]*)</wcfNode-' . $data['identifier'] . '>~', function($matches) use ($string) {
- $string = str_replace('<!-- META_CODE_INNER_CONTENT -->', $matches['content'], $string);
-
- return $string;
- }, $html);
-
- }
-
- return $html;
- }
-
- public function getDocument() {
- return $this->document;
- }
-
- public function getXPath() {
- if ($this->xpath === null) {
- $this->xpath = new \DOMXPath($this->getDocument());
- }
-
- return $this->xpath;
- }
-
- public function renameTag(\DOMElement $element, $tagName) {
- $newElement = $this->document->createElement($tagName);
- $element->parentNode->insertBefore($newElement, $element);
- while ($element->hasChildNodes()) {
- $newElement->appendChild($element->firstChild);
- }
-
- $element->parentNode->removeChild($element);
-
- return $newElement;
- }
-
- public function unwrapContent(\DOMElement $element) {
- while ($element->hasChildNodes()) {
- $element->parentNode->insertBefore($element->firstChild, $element);
- }
-
- $element->parentNode->removeChild($element);
- }
-
- public function addNodeData(IHtmlNode $htmlNode, $nodeIdentifier, array $data) {
- $this->nodeData[] = [
- 'data' => $data,
- 'identifier' => $nodeIdentifier,
- 'object' => $htmlNode
- ];
- }
-
- public function parseAttributes($attributes) {
- if (empty($attributes)) {
- return [];
- }
-
- $parsedAttributes = base64_decode($attributes, true);
- if ($parsedAttributes !== false) {
- try {
- $parsedAttributes = JSON::decode($parsedAttributes);
- }
- catch (SystemException $e) {
- /* parse errors can occur if user provided malicious content - ignore them */
- $parsedAttributes = [];
- }
- }
-
- return $parsedAttributes;
- }
-
- protected function invokeHtmlNode(IHtmlNode $htmlNode) {
- $tagName = $htmlNode->getTagName();
- if (empty($tagName)) {
- throw new \UnexpectedValueException("Missing tag name for " . get_class($htmlNode));
- }
-
- $elements = [];
- foreach ($this->getDocument()->getElementsByTagName($tagName) as $element) {
- $elements[] = $element;
- }
-
- if (!empty($elements)) {
- $htmlNode->process($elements, $this);
- }
- }
-}
namespace wcf\system\html\node;
/**
- * TOOD documentation
- * @since 3.0
+ * Default interface for html nodes.
+ *
+ * @author Alexander Ebert
+ * @copyright 2001-2016 WoltLab GmbH
+ * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package WoltLabSuite\Core\System\Html\Node
+ * @since 3.0
*/
interface IHtmlNode {
+ /**
+ * Returns the tag name of elements consumed by this node.
+ *
+ * @return string tag name of consumed elements
+ */
public function getTagName();
/**
- * @param \DOMElement[] $elements
- * @param HtmlNodeProcessor $htmlNodeProcessor
- * @return mixed
+ * Processes the provided elements and marks them for replacement if applicable.
+ *
+ * @param \DOMElement[] $elements static list of matched elements, does not change when removing elements
+ * @param AbstractHtmlNodeProcessor $htmlNodeProcessor node processor instance
*/
- public function process(array $elements, HtmlNodeProcessor $htmlNodeProcessor);
+ public function process(array $elements, AbstractHtmlNodeProcessor $htmlNodeProcessor);
+ /**
+ * Replaces a placeholder tag with the provided data.
+ *
+ * @param array $data replacement data
+ */
public function replaceTag(array $data);
}
namespace wcf\system\html\node;
/**
- * @since 3.0
+ * Default interface for html node processors.
+ *
+ * @author Alexander Ebert
+ * @copyright 2001-2016 WoltLab GmbH
+ * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package WoltLabSuite\Core\System\Html\Node
+ * @since 3.0
*/
interface IHtmlNodeProcessor {
/**
- * @return \DOMDocument
+ * Returns the currently loaded DOM document.
+ *
+ * @return \DOMDocument active DOM document
*/
public function getDocument();
+ /**
+ * Returns the final HTML for storage or display.
+ *
+ * @return string parsed HTML
+ */
public function getHtml();
+ /**
+ * Loads a HTML string for processing.
+ *
+ * @param string $html HTML string
+ */
public function load($html);
+
+ /**
+ * Processes the HTML and transforms it depending on the output type.
+ */
+ public function process();
}
namespace wcf\system\html\output\node;
use wcf\system\application\ApplicationHandler;
use wcf\system\html\node\AbstractHtmlNode;
-use wcf\system\html\node\HtmlNodeProcessor;
+use wcf\system\html\node\AbstractHtmlNodeProcessor;
use wcf\system\message\embedded\object\MessageEmbeddedObjectManager;
use wcf\system\request\RouteHandler;
use wcf\system\WCF;
use wcf\util\StringUtil;
/**
- * TOOD documentation
- * @since 3.0
+ * Processes quotes.
+ *
+ * @author Alexander Ebert
+ * @copyright 2001-2016 WoltLab GmbH
+ * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package WoltLabSuite\Core\System\Html\Output\Node
+ * @since 3.0
*/
class HtmlOutputNodeBlockquote extends AbstractHtmlNode {
+ /**
+ * @inheritDoc
+ */
protected $tagName = 'blockquote';
/**
* @inheritDoc
*/
- public function process(array $elements, HtmlNodeProcessor $htmlNodeProcessor) {
+ public function process(array $elements, AbstractHtmlNodeProcessor $htmlNodeProcessor) {
/** @var \DOMElement $element */
foreach ($elements as $element) {
$nodeIdentifier = StringUtil::getRandomID();
}
}
+ /**
+ * @inheritDoc
+ */
public function replaceTag(array $data) {
$externalQuoteLink = (!empty($data['url'])) ? !ApplicationHandler::getInstance()->isInternalURL($data['url']) : false;
if (!$externalQuoteLink) {
use wcf\system\bbcode\highlighter\TexHighlighter;
use wcf\system\bbcode\highlighter\XmlHighlighter;
use wcf\system\html\node\AbstractHtmlNode;
-use wcf\system\html\node\HtmlNodeProcessor;
+use wcf\system\html\node\AbstractHtmlNodeProcessor;
use wcf\system\Regex;
use wcf\system\WCF;
use wcf\util\StringUtil;
/**
- * TOOD documentation
- * @since 3.0
+ * Processes code listings.
+ *
+ * @author Alexander Ebert
+ * @copyright 2001-2016 WoltLab GmbH
+ * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package WoltLabSuite\Core\System\Html\Output\Node
+ * @since 3.0
*/
class HtmlOutputNodePre extends AbstractHtmlNode {
+ /**
+ * @inheritDoc
+ */
protected $tagName = 'pre';
/**
/**
* @inheritDoc
*/
- public function process(array $elements, HtmlNodeProcessor $htmlNodeProcessor) {
+ public function process(array $elements, AbstractHtmlNodeProcessor $htmlNodeProcessor) {
/** @var \DOMElement $element */
foreach ($elements as $element) {
$nodeIdentifier = StringUtil::getRandomID();
}
}
+ /**
+ * @inheritDoc
+ */
public function replaceTag(array $data) {
$content = preg_replace('/^\s*\n/', '', $data['content']);
$content = preg_replace('/\n\s*$/', '', $content);
<?php
namespace wcf\system\html\output\node;
-use wcf\system\html\node\HtmlNodeProcessor;
+use wcf\system\html\node\AbstractHtmlNodeProcessor;
/**
- * TOOD documentation
- * @since 3.0
+ * Processes a HTML string and renders the final output for display.
+ *
+ * @author Alexander Ebert
+ * @copyright 2001-2016 WoltLab GmbH
+ * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package WoltLabSuite\Core\System\Html\Output\Node
+ * @since 3.0
*/
-class HtmlOutputNodeProcessor extends HtmlNodeProcessor {
+class HtmlOutputNodeProcessor extends AbstractHtmlNodeProcessor {
+ /**
+ * @inheritDoc
+ */
public function process() {
$this->invokeHtmlNode(new HtmlOutputNodeWoltlabMetacode());
- // TODO: this should be dynamic to some extent
- $this->invokeHtmlNode(new HtmlOutputNodeBlockquote());
- $this->invokeHtmlNode(new HtmlOutputNodeWoltlabMention());
- $this->invokeHtmlNode(new HtmlOutputNodeWoltlabColor());
- $this->invokeHtmlNode(new HtmlOutputNodeWoltlabSize());
- $this->invokeHtmlNode(new HtmlOutputNodeWoltlabSpoiler());
- $this->invokeHtmlNode(new HtmlOutputNodePre());
+ // dynamic node handlers
+ $this->invokeNodeHandlers('wcf\system\html\output\node\HtmlOutputNode', ['woltlab-metacode']);
}
}
<?php
namespace wcf\system\html\output\node;
use wcf\system\html\node\AbstractHtmlNode;
-use wcf\system\html\node\HtmlNodeProcessor;
+use wcf\system\html\node\AbstractHtmlNodeProcessor;
use wcf\util\StringUtil;
/**
- * TOOD documentation
- * @since 3.0
+ * Processes text color.
+ *
+ * @author Alexander Ebert
+ * @copyright 2001-2016 WoltLab GmbH
+ * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package WoltLabSuite\Core\System\Html\Output\Node
+ * @since 3.0
*/
class HtmlOutputNodeWoltlabColor extends AbstractHtmlNode {
+ /**
+ * @inheritDoc
+ */
protected $tagName = 'woltlab-color';
/**
* @inheritDoc
*/
- public function process(array $elements, HtmlNodeProcessor $htmlNodeProcessor) {
+ public function process(array $elements, AbstractHtmlNodeProcessor $htmlNodeProcessor) {
/** @var \DOMElement $element */
foreach ($elements as $element) {
// parse color
}
}
+ /**
+ * @inheritDoc
+ */
public function replaceTag(array $data) {
return '<span style="color: #' . $data['color'] . '">' . self::PLACEHOLDER . '</span>';
}
use wcf\data\user\UserProfile;
use wcf\system\cache\runtime\UserProfileRuntimeCache;
use wcf\system\html\node\AbstractHtmlNode;
-use wcf\system\html\node\HtmlNodeProcessor;
+use wcf\system\html\node\AbstractHtmlNodeProcessor;
use wcf\system\WCF;
use wcf\util\DOMUtil;
use wcf\util\StringUtil;
/**
- * TOOD documentation
- * @since 3.0
+ * Processes user mentions.
+ *
+ * @author Alexander Ebert
+ * @copyright 2001-2016 WoltLab GmbH
+ * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package WoltLabSuite\Core\System\Html\Output\Node
+ * @since 3.0
*/
class HtmlOutputNodeWoltlabMention extends AbstractHtmlNode {
+ /**
+ * @inheritDoc
+ */
protected $tagName = 'woltlab-mention';
/**
/**
* @inheritDoc
*/
- public function process(array $elements, HtmlNodeProcessor $htmlNodeProcessor) {
+ public function process(array $elements, AbstractHtmlNodeProcessor $htmlNodeProcessor) {
$this->userProfiles = [];
$userIds = [];
+ /** @var \DOMElement $element */
foreach ($elements as $element) {
$userId = ($element->hasAttribute('data-user-id')) ? intval($element->getAttribute('data-user-id')) : 0;
$username = ($element->hasAttribute('data-username')) ? StringUtil::trim($element->getAttribute('data-username')) : '';
}
}
+ /**
+ * @inheritDoc
+ */
public function replaceTag(array $data) {
WCF::getTPL()->assign([
'username' => $data['username'],
namespace wcf\system\html\output\node;
use wcf\system\bbcode\HtmlBBCodeParser;
use wcf\system\html\node\AbstractHtmlNode;
-use wcf\system\html\node\HtmlNodeProcessor;
+use wcf\system\html\node\AbstractHtmlNodeProcessor;
use wcf\util\StringUtil;
/**
- * TOOD documentation
- * @since 3.0
+ * Processes bbcodes represented by `<woltlab-metacode>`.
+ *
+ * @author Alexander Ebert
+ * @copyright 2001-2016 WoltLab GmbH
+ * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package WoltLabSuite\Core\System\Html\Output\Node
+ * @since 3.0
*/
class HtmlOutputNodeWoltlabMetacode extends AbstractHtmlNode {
+ /**
+ * @inheritDoc
+ */
protected $tagName = 'woltlab-metacode';
/**
* @inheritDoc
*/
- public function process(array $elements, HtmlNodeProcessor $htmlNodeProcessor) {
+ public function process(array $elements, AbstractHtmlNodeProcessor $htmlNodeProcessor) {
/** @var \DOMElement $element */
foreach ($elements as $element) {
$name = $element->getAttribute('data-name');
}
}
+ /**
+ * @inheritDoc
+ */
public function replaceTag(array $data) {
return HtmlBBCodeParser::getInstance()->getHtmlOutput($data['name'], $data['attributes']);
}
<?php
namespace wcf\system\html\output\node;
use wcf\system\html\node\AbstractHtmlNode;
-use wcf\system\html\node\HtmlNodeProcessor;
+use wcf\system\html\node\AbstractHtmlNodeProcessor;
use wcf\util\StringUtil;
/**
- * TOOD documentation
- * @since 3.0
+ * Processes text size.
+ *
+ * @author Alexander Ebert
+ * @copyright 2001-2016 WoltLab GmbH
+ * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package WoltLabSuite\Core\System\Html\Output\Node
+ * @since 3.0
*/
class HtmlOutputNodeWoltlabSize extends AbstractHtmlNode {
+ /**
+ * @inheritDoc
+ */
protected $tagName = 'woltlab-size';
/**
* @inheritDoc
*/
- public function process(array $elements, HtmlNodeProcessor $htmlNodeProcessor) {
+ public function process(array $elements, AbstractHtmlNodeProcessor $htmlNodeProcessor) {
/** @var \DOMElement $element */
foreach ($elements as $element) {
// parse color
}
}
+ /**
+ * @inheritDoc
+ */
public function replaceTag(array $data) {
return '<span style="font-size: ' . $data['size'] . 'px">' . self::PLACEHOLDER . '</span>';
}
<?php
namespace wcf\system\html\output\node;
-use wcf\system\application\ApplicationHandler;
use wcf\system\html\node\AbstractHtmlNode;
-use wcf\system\html\node\HtmlNodeProcessor;
-use wcf\system\request\RouteHandler;
+use wcf\system\html\node\AbstractHtmlNodeProcessor;
use wcf\system\WCF;
use wcf\util\StringUtil;
/**
- * TOOD documentation
- * @since 3.0
+ * Processes spoilers.
+ *
+ * @author Alexander Ebert
+ * @copyright 2001-2016 WoltLab GmbH
+ * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package WoltLabSuite\Core\System\Html\Output\Node
+ * @since 3.0
*/
class HtmlOutputNodeWoltlabSpoiler extends AbstractHtmlNode {
+ /**
+ * @inheritDoc
+ */
protected $tagName = 'woltlab-spoiler';
/**
* @inheritDoc
*/
- public function process(array $elements, HtmlNodeProcessor $htmlNodeProcessor) {
+ public function process(array $elements, AbstractHtmlNodeProcessor $htmlNodeProcessor) {
/** @var \DOMElement $element */
foreach ($elements as $element) {
$nodeIdentifier = StringUtil::getRandomID();
}
}
+ /**
+ * @inheritDoc
+ */
public function replaceTag(array $data) {
WCF::getTPL()->assign([
'buttonLabel' => $data['label']
use wcf\system\html\node\IHtmlNode;
/**
- * TOOD documentation
- * @since 3.0
+ * Default interface for html output nodes.
+ *
+ * @author Alexander Ebert
+ * @copyright 2001-2016 WoltLab GmbH
+ * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package WoltLabSuite\Core\System\Html\Output\Node
+ * @since 3.0
*/
interface IHtmlOutputNode extends IHtmlNode {}