Added `isBlockElement` for bbcodes
authorAlexander Ebert <ebert@woltlab.com>
Sun, 15 May 2016 11:04:55 +0000 (13:04 +0200)
committerAlexander Ebert <ebert@woltlab.com>
Sun, 15 May 2016 11:04:55 +0000 (13:04 +0200)
com.woltlab.wcf/bbcode.xml
wcfsetup/install/files/acp/templates/bbcodeAdd.tpl
wcfsetup/install/files/lib/acp/form/BBCodeAddForm.class.php
wcfsetup/install/files/lib/acp/form/BBCodeEditForm.class.php
wcfsetup/install/files/lib/data/bbcode/BBCode.class.php
wcfsetup/install/files/lib/system/bbcode/HtmlBBCodeParser.class.php
wcfsetup/install/files/lib/system/html/input/node/HtmlInputNodeWoltlabMetacodeMarker.class.php
wcfsetup/install/files/lib/system/package/plugin/BBCodePackageInstallationPlugin.class.php
wcfsetup/install/lang/de.xml
wcfsetup/install/lang/en.xml
wcfsetup/setup/db/install.sql

index 302db0badcf3f7bf810afe2326588d65a9b94afa..5927a026616301de9666f6ac53fdc258e87f1893 100644 (file)
@@ -4,36 +4,29 @@
                <bbcode name="b">
                        <htmlopen>b</htmlopen>
                        <htmlclose>b</htmlclose>
-                       <allowedchildren>all^b</allowedchildren>
                </bbcode>
                <bbcode name="i">
                        <htmlopen>i</htmlopen>
                        <htmlclose>i</htmlclose>
-                       <allowedchildren>all^i</allowedchildren>
                </bbcode>
                <bbcode name="u">
                        <htmlopen>span style="text-decoration: underline"</htmlopen>
                        <htmlclose>span</htmlclose>
-                       <allowedchildren>all^u</allowedchildren>
                </bbcode>
                <bbcode name="s">
                        <htmlopen>s</htmlopen>
                        <htmlclose>s</htmlclose>
-                       <allowedchildren>all^s</allowedchildren>
                </bbcode>
                <bbcode name="sub">
                        <htmlopen>sub</htmlopen>
                        <htmlclose>sub</htmlclose>
-                       <allowedchildren>all^sub</allowedchildren>
                </bbcode>
                <bbcode name="sup">
                        <htmlopen>sup</htmlopen>
                        <htmlclose>sup</htmlclose>
-                       <allowedchildren>all^sup</allowedchildren>
                </bbcode>
                <bbcode name="email">
                        <classname><![CDATA[wcf\system\bbcode\EmailBBCode]]></classname>
-                       <allowedchildren>none^img,b,i,u,s,sub,sup,color,size,font</allowedchildren>
                        <attributes>
                                <attribute name="0">
                                        <required>1</required>
@@ -86,6 +79,7 @@
                                        <required>1</required>
                                </attribute>
                        </attributes>
+                       <isBlockElement>1</isBlockElement>
                </bbcode>
                <bbcode name="quote">
                        <classname><![CDATA[wcf\system\bbcode\QuoteBBCode]]></classname>
                        </attributes>
                        <wysiwygicon>fa-quote-left</wysiwygicon>
                        <buttonlabel>wcf.bbcode.button.quote</buttonlabel>
+                       <isBlockElement>1</isBlockElement>
                </bbcode>
                <bbcode name="code">
                        <classname><![CDATA[wcf\system\bbcode\CodeBBCode]]></classname>
-                       <allowedchildren>none</allowedchildren>
                        <attributes>
                                <attribute name="0"></attribute>
                                <attribute name="1"></attribute>
                        <sourcecode>1</sourcecode>
                        <wysiwygicon>fa-code</wysiwygicon>
                        <buttonlabel>wcf.bbcode.button.code</buttonlabel>
+                       <isBlockElement>1</isBlockElement>
                </bbcode>
                <bbcode name="img">
                        <classname><![CDATA[wcf\system\bbcode\ImageBBCode]]></classname>
-                       <allowedchildren>none</allowedchildren>
                        <attributes>
                                <attribute name="0">
                                        <required>1</required>
                </bbcode>
                <bbcode name="url">
                        <classname><![CDATA[wcf\system\bbcode\URLBBCode]]></classname>
-                       <allowedchildren>none^img,b,i,u,s,sub,sup,color,size,font</allowedchildren>
                        <attributes>
                                <attribute name="0">
                                        <required>1</required>
                </bbcode>
                <bbcode name="list">
                        <classname><![CDATA[wcf\system\bbcode\ListBBCode]]></classname>
-                       <allowedchildren>none^img,b,i,u,s,sub,sup,color,size,font,list,url,email,attach,tt</allowedchildren>
                        <attributes>
                                <attribute name="0">
                                        <validationpattern>^(1|a|none|circle|square|disc|decimal|lower-roman|upper-roman|decimal-leading-zero|lower-greek|lower-latin|upper-latin|armenian|georgian)$</validationpattern>
                                </attribute>
                        </attributes>
+                       <isBlockElement>1</isBlockElement>
                </bbcode>
                <bbcode name="table">
                        <classname><![CDATA[wcf\system\bbcode\TableBBCode]]></classname>
-                       <allowedchildren>all^table</allowedchildren>
+                       <isBlockElement>1</isBlockElement>
                </bbcode>
                <bbcode name="media">
                        <classname><![CDATA[wcf\system\bbcode\MediaBBCode]]></classname>
                        </attributes>
                        <wysiwygicon>fa-eye-slash</wysiwygicon>
                        <buttonlabel>wcf.bbcode.button.spoiler</buttonlabel>
+                       <isBlockElement>1</isBlockElement>
                </bbcode>
                <bbcode name="tt">
                        <htmlopen>kbd</htmlopen>
                        <htmlclose>kbd</htmlclose>
-                       <allowedchildren>none</allowedchildren>
                        <sourcecode>1</sourcecode>
                        <wysiwygicon>fa-terminal</wysiwygicon>
                        <buttonlabel>wcf.bbcode.button.inlineCode</buttonlabel>
index 99bc608606ac252a75af009634c383959b25184e..661e19c1e3d068173114552451c678ff358d6743 100644 (file)
                        </dd>
                </dl>
                
-               <dl{if $errorField == 'allowedChildren'} class="formError"{/if}>
-                       <dt><label for="allowedChildren">{lang}wcf.acp.bbcode.allowedChildren{/lang}</label></dt>
+               <dl>
+                       <dt></dt>
                        <dd>
-                               <input type="text" id="allowedChildren" name="allowedChildren" value="{$allowedChildren}" class="long" required="required" pattern="^((all|none)\^)?([a-zA-Z0-9]+,)*[a-zA-Z0-9]+$" />
-                               {if $errorField == 'allowedChildren'}
-                                       <small class="innerError">
-                                               {if $errorType == 'empty'}
-                                                       {lang}wcf.global.form.error.empty{/lang}
-                                               {else}
-                                                       {lang}wcf.acp.bbcode.allowedChildren.error.{$errorType}{/lang}
-                                               {/if}
-                                       </small>
-                               {/if}
+                               <label for="isBlockElement"><input type="checkbox" id="isBlockElement" name="isBlockElement" value="1"{if $isBlockElement} checked{/if}> {lang}wcf.acp.bbcode.isBlockElement{/lang}</label>
+                               <small>{lang}wcf.acp.bbcode.isBlockElement.description{/lang}</small>
                        </dd>
                </dl>
                
index f5c9585985afdc61390112216fe919e89f26f3ca..531ff8223d898e23ee6ca41567303164596cfe18 100644 (file)
@@ -15,7 +15,7 @@ use wcf\util\StringUtil;
  * Shows the bbcode add form.
  * 
  * @author     Tim Duesterhus
- * @copyright  2001-2015 WoltLab GmbH
+ * @copyright  2001-2016 WoltLab GmbH
  * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
  * @package    com.woltlab.wcf
  * @subpackage acp.form
@@ -23,7 +23,7 @@ use wcf\util\StringUtil;
  */
 class BBCodeAddForm extends AbstractForm {
        /**
-        * @see \wcf\page\AbstractPage::$activeMenuItem
+        * @inheritDoc
         */
        public $activeMenuItem = 'wcf.acp.menu.link.bbcode.add';
        
@@ -37,7 +37,7 @@ class BBCodeAddForm extends AbstractForm {
         * list of attributes
         * @var object[]
         */
-       public $attributes = array();
+       public $attributes = [];
        
        /**
         * tag name
@@ -69,6 +69,12 @@ class BBCodeAddForm extends AbstractForm {
         */
        public $htmlOpen = '';
        
+       /**
+        * true if bbcode is a block element
+        * @var boolean
+        */
+       public $isBlockElement = false;
+       
        /**
         * true, if bbcode contains source code
         * @var boolean
@@ -76,12 +82,12 @@ class BBCodeAddForm extends AbstractForm {
        public $isSourceCode = false;
        
        /**
-        * @see \wcf\page\AbstractPage::$neededPermissions
+        * @inheritDoc
         */
-       public $neededPermissions = array('admin.content.bbcode.canManageBBCode');
+       public $neededPermissions = ['admin.content.bbcode.canManageBBCode'];
        
        /**
-        * @see \wcf\page\AbstractPage::$templateName
+        * @inheritDoc
         */
        public $templateName = 'bbcodeAdd';
        
@@ -98,7 +104,7 @@ class BBCodeAddForm extends AbstractForm {
        public $wysiwygIcon = '';
        
        /**
-        * @see \wcf\page\IPage::readParameters()
+        * @inheritDoc
         */
        public function readParameters() {
                parent::readParameters();
@@ -107,7 +113,7 @@ class BBCodeAddForm extends AbstractForm {
        }
        
        /**
-        * @see \wcf\form\IForm::readFormParameters()
+        * @inheritDoc
         */
        public function readFormParameters() {
                parent::readFormParameters();
@@ -118,6 +124,7 @@ class BBCodeAddForm extends AbstractForm {
                if (isset($_POST['className'])) $this->className = StringUtil::trim($_POST['className']);
                if (isset($_POST['htmlClose'])) $this->htmlClose = StringUtil::trim($_POST['htmlClose']);
                if (isset($_POST['htmlOpen'])) $this->htmlOpen = StringUtil::trim($_POST['htmlOpen']);
+               if (isset($_POST['isBlockElement'])) $this->isBlockElement = true;
                if (isset($_POST['isSourceCode'])) $this->isSourceCode = true;
                if (isset($_POST['showButton'])) $this->showButton = true;
                if (isset($_POST['wysiwygIcon'])) $this->wysiwygIcon = StringUtil::trim($_POST['wysiwygIcon']);
@@ -143,7 +150,7 @@ class BBCodeAddForm extends AbstractForm {
        }
        
        /**
-        * @see \wcf\form\IForm::validate()
+        * @inheritDoc
         */
        public function validate() {
                parent::validate();
@@ -169,16 +176,6 @@ class BBCodeAddForm extends AbstractForm {
                        throw new UserInputException('bbcodeTag', 'inUse');
                }
                
-               // handle empty case first
-               if (empty($this->allowedChildren)) {
-                       throw new UserInputException('allowedChildren');
-               }
-               
-               // validate syntax of allowedChildren: Optional all|none^ followed by a comma-separated list of bbcodes
-               if (!empty($this->allowedChildren) && !Regex::compile('^(?:(?:all|none)\^)?(?:[a-zA-Z0-9]+,)*[a-zA-Z0-9]+$')->match($this->allowedChildren)) {
-                       throw new UserInputException('allowedChildren', 'notValid');
-               }
-               
                // validate class
                if (!empty($this->className) && !class_exists($this->className)) {
                        throw new UserInputException('className', 'notFound');
@@ -215,34 +212,34 @@ class BBCodeAddForm extends AbstractForm {
        }
        
        /**
-        * @see \wcf\form\IForm::save()
+        * @inheritDoc
         */
        public function save() {
                parent::save();
                
                // save bbcode
-               $this->objectAction = new BBCodeAction(array(), 'create', array('data' => array_merge($this->additionalFields, array(
-                       'allowedChildren' => $this->allowedChildren,
+               $this->objectAction = new BBCodeAction([], 'create', ['data' => array_merge($this->additionalFields, [
                        'bbcodeTag' => $this->bbcodeTag,
                        'buttonLabel' => $this->buttonLabel,
                        'className' => $this->className,
                        'htmlOpen' => $this->htmlOpen,
                        'htmlClose' => $this->htmlClose,
+                       'isBlockElement' => ($this->isBlockElement ? 1 : 0),
                        'isSourceCode' => ($this->isSourceCode ? 1 : 0),
                        'packageID' => 1,
                        'showButton' => ($this->showButton ? 1 : 0),
                        'wysiwygIcon' => $this->wysiwygIcon
-               ))));
+               ])]);
                $returnValues = $this->objectAction->executeAction();
                foreach ($this->attributes as $attribute) {
-                       $attributeAction = new BBCodeAttributeAction(array(), 'create', array('data' => array(
+                       $attributeAction = new BBCodeAttributeAction([], 'create', ['data' => [
                                'bbcodeID' => $returnValues['returnValues']->bbcodeID,
                                'attributeNo' => $attribute->attributeNo,
                                'attributeHtml' => $attribute->attributeHtml,
                                'validationPattern' => $attribute->validationPattern,
                                'required' => $attribute->required,
                                'useText' => $attribute->useText,
-                       )));
+                       ]]);
                        $attributeAction->executeAction();
                }
                
@@ -252,47 +249,46 @@ class BBCodeAddForm extends AbstractForm {
                        
                        // update button label
                        $bbcodeEditor = new BBCodeEditor($returnValues['returnValues']);
-                       $bbcodeEditor->update(array(
+                       $bbcodeEditor->update([
                                'buttonLabel' => 'wcf.bbcode.buttonLabel'.$bbcodeID
-                       ));
+                       ]);
                }
                
                $this->saved();
                
                // reset values
                $this->bbcodeTag = $this->htmlOpen = $this->htmlClose = $this->className = $this->buttonLabel = $this->wysiwygIcon = '';
-               $this->allowedChildren = 'all';
-               $this->attributes = array();
-               $this->isSourceCode = $this->showButton = false;
+               $this->attributes = [];
+               $this->isBlockElement = $this->isSourceCode = $this->showButton = false;
                
                I18nHandler::getInstance()->reset();
                
                // show success
-               WCF::getTPL()->assign(array(
+               WCF::getTPL()->assign([
                        'success' => true
-               ));
+               ]);
        }
        
        /**
-        * @see \wcf\page\IPage::assignVariables()
+        * @inheritDoc
         */
        public function assignVariables() {
                parent::assignVariables();
                
                I18nHandler::getInstance()->assignVariables();
                
-               WCF::getTPL()->assign(array(
+               WCF::getTPL()->assign([
                        'action' => 'add',
-                       'allowedChildren' => $this->allowedChildren,
                        'attributes' => $this->attributes,
                        'bbcodeTag' => $this->bbcodeTag,
                        'buttonLabel' => $this->buttonLabel,
                        'className' => $this->className,
                        'htmlOpen' => $this->htmlOpen,
                        'htmlClose' => $this->htmlClose,
+                       'isBlockElement' => $this->isBlockElement,
                        'isSourceCode' => $this->isSourceCode,
                        'showButton' => $this->showButton,
                        'wysiwygIcon' => $this->wysiwygIcon
-               ));
+               ]);
        }
 }
index 67b38a10e3fdcb060af34a4df12f882764948f3f..358f7b92ad42ac8f54a1550c97fc73fe79160576 100644 (file)
@@ -13,7 +13,7 @@ use wcf\system\WCF;
  * Shows the bbcode edit form.
  * 
  * @author     Tim Duesterhus
- * @copyright  2001-2015 WoltLab GmbH
+ * @copyright  2001-2016 WoltLab GmbH
  * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
  * @package    com.woltlab.wcf
  * @subpackage acp.form
@@ -21,14 +21,14 @@ use wcf\system\WCF;
  */
 class BBCodeEditForm extends BBCodeAddForm {
        /**
-        * @see \wcf\page\AbstractPage::$activeMenuItem
+        * @inheritDoc
         */
        public $activeMenuItem = 'wcf.acp.menu.link.bbcode';
        
        /**
-        * @see \wcf\page\AbstractPage::$neededPermissions
+        * @inheritDoc
         */
-       public $neededPermissions = array('admin.content.bbcode.canManageBBCode');
+       public $neededPermissions = ['admin.content.bbcode.canManageBBCode'];
        
        /**
         * bbcode id
@@ -46,10 +46,10 @@ class BBCodeEditForm extends BBCodeAddForm {
         * list of native bbcodes
         * @var string[]
         */
-       public static $nativeBBCodes = array('b', 'i', 'u', 's', 'sub', 'sup', 'list', 'align', 'color', 'size', 'font', 'url', 'img', 'email', 'table');
+       public static $nativeBBCodes = ['b', 'i', 'u', 's', 'sub', 'sup', 'list', 'align', 'color', 'size', 'font', 'url', 'img', 'email', 'table'];
        
        /**
-        * @see \wcf\page\IPage::readParameters()
+        * @inheritDoc
         */
        public function readParameters() {
                AbstractForm::readParameters();
@@ -66,7 +66,7 @@ class BBCodeEditForm extends BBCodeAddForm {
        }
        
        /**
-        * @see \wcf\acp\form\BBCodeAddForm::readButtonLabelFormParameter()
+        * @inheritDoc
         */
        protected function readButtonLabelFormParameter() {
                if (!in_array($this->bbcode->bbcodeTag, self::$nativeBBCodes)) {
@@ -75,7 +75,7 @@ class BBCodeEditForm extends BBCodeAddForm {
        }
        
        /**
-        * @see \wcf\form\IForm::save()
+        * @inheritDoc
         */
        public function save() {
                AbstractForm::save();
@@ -92,47 +92,47 @@ class BBCodeEditForm extends BBCodeAddForm {
                }
                
                // update bbcode
-               $this->objectAction = new BBCodeAction(array($this->bbcodeID), 'update', array('data' => array_merge($this->additionalFields, array(
-                       'allowedChildren' => $this->allowedChildren,
+               $this->objectAction = new BBCodeAction([$this->bbcodeID], 'update', ['data' => array_merge($this->additionalFields, [
                        'bbcodeTag' => $this->bbcodeTag,
                        'buttonLabel' => $this->buttonLabel,
                        'className' => $this->className,
                        'htmlClose' => $this->htmlClose,
                        'htmlOpen' => $this->htmlOpen,
+                       'isBlockElement' => ($this->isBlockElement ? 1 : 0),
                        'isSourceCode' => ($this->isSourceCode ? 1 : 0),
                        'showButton' => ($this->showButton ? 1 : 0),
                        'wysiwygIcon' => $this->wysiwygIcon
-               ))));
+               ])]);
                $this->objectAction->executeAction();
                
                // clear existing attributes
                $sql = "DELETE FROM     wcf".WCF_N."_bbcode_attribute
                        WHERE           bbcodeID = ?";
                $statement = WCF::getDB()->prepareStatement($sql);
-               $statement->execute(array($this->bbcodeID));
+               $statement->execute([$this->bbcodeID]);
                
                foreach ($this->attributes as $attribute) {
-                       $attributeAction = new BBCodeAttributeAction(array(), 'create', array('data' => array(
+                       $attributeAction = new BBCodeAttributeAction([], 'create', ['data' => [
                                'bbcodeID' => $this->bbcodeID,
                                'attributeNo' => $attribute->attributeNo,
                                'attributeHtml' => $attribute->attributeHtml,
                                'validationPattern' => $attribute->validationPattern,
                                'required' => $attribute->required,
                                'useText' => $attribute->useText,
-                       )));
+                       ]]);
                        $attributeAction->executeAction();
                }
                
                $this->saved();
                
                // show success
-               WCF::getTPL()->assign(array(
+               WCF::getTPL()->assign([
                        'success' => true
-               ));
+               ]);
        }
        
        /**
-        * @see \wcf\page\IPage::readData()
+        * @inheritDoc
         */
        public function readData() {
                parent::readData();
@@ -145,7 +145,7 @@ class BBCodeEditForm extends BBCodeAddForm {
                        $this->bbcodeTag = $this->bbcode->bbcodeTag;
                        $this->htmlOpen = $this->bbcode->htmlOpen;
                        $this->htmlClose = $this->bbcode->htmlClose;
-                       $this->allowedChildren = $this->bbcode->allowedChildren;
+                       $this->isBlockElement = $this->bbcode->isBlockElement;
                        $this->isSourceCode = $this->bbcode->isSourceCode;
                        $this->className = $this->bbcode->className;
                        $this->showButton = $this->bbcode->showButton;
@@ -154,17 +154,17 @@ class BBCodeEditForm extends BBCodeAddForm {
        }
        
        /**
-        * @see \wcf\page\IPage::assignVariables()
+        * @inheritDoc
         */
        public function assignVariables() {
                parent::assignVariables();
                
                I18nHandler::getInstance()->assignVariables(!empty($_POST));
                
-               WCF::getTPL()->assign(array(
+               WCF::getTPL()->assign([
                        'bbcode' => $this->bbcode,
                        'action' => 'edit',
                        'nativeBBCode' => (in_array($this->bbcode->bbcodeTag, self::$nativeBBCodes))
-               ));
+               ]);
        }
 }
index 55c51269162596e11dd0ad43844f2fd4d8d3bc4f..1d34e2818d0ad0b9467d7d4eaeee6186c0d67794 100644 (file)
@@ -21,8 +21,8 @@ use wcf\system\WCF;
  * @property-read      integer         $packageID
  * @property-read      string          $htmlOpen
  * @property-read      string          $htmlClose
- * @property-read      string          $allowedChildren
  * @property-read      string          $className
+ * @property-read       integer         $isBlockElement
  * @property-read      string          $wysiwygIcon
  * @property-read      string          $buttonLabel
  * @property-read      integer         $isSourceCode
index 73048ecbd5780e644056a60c332ad43d4e354cfa..a6f9b239c32d8d4ac37a49882404de55bc909be7 100644 (file)
@@ -13,12 +13,13 @@ use wcf\util\StringUtil;
  * are <iframe> or other embedded media that is allowed as a result of a bbcode, but
  * not allowed to be directly provided by a user. 
  * 
- * @author     Alexander Ebert
- * @copyright  2001-2016 WoltLab GmbH
- * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
- * @package    com.woltlab.wcf
- * @subpackage system.bbcode
- * @category   Community Framework
+ * @author      Alexander Ebert
+ * @copyright   2001-2016 WoltLab GmbH
+ * @license     GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package     com.woltlab.wcf
+ * @subpackage  system.bbcode
+ * @category    Community Framework
+ * @since       2.2
  */
 class HtmlBBCodeParser extends BBCodeParser {
        /**
@@ -169,11 +170,12 @@ class HtmlBBCodeParser extends BBCodeParser {
        /**
         * Builds a plain bbcode string, used for unknown bbcodes.
         * 
-        * @param       string          $name           bbcode identifier
-        * @param       array           $attributes     list of attributes
+        * @param       string          $name                   bbcode identifier
+        * @param       array           $attributes             list of attributes
+        * @param       boolean         $openingTagOnly         only render the opening tag
         * @return      string
         */
-       protected function buildBBCodeTag($name, $attributes) {
+       public function buildBBCodeTag($name, $attributes, $openingTagOnly = false) {
                if (!empty($attributes)) {
                        foreach ($attributes as &$attribute) {
                                $attribute = "'" . addcslashes($attribute, "'") . "'";
@@ -186,9 +188,45 @@ class HtmlBBCodeParser extends BBCodeParser {
                        $attributes = '';
                }
                
+               if ($openingTagOnly) {
+                       return '[' . $name . $attributes . ']';
+               }
+               
                return '[' . $name . $attributes . ']<!-- META_CODE_INNER_CONTENT -->[/' . $name . ']';
        }
        
+       /**
+        * Returns the list of bbcodes that represent block elements.
+        * 
+        * @return      string[]        list of bbcode block elements
+        */
+       public function getBlockBBCodes() {
+               $bbcodes = [];
+               foreach ($this->bbcodes as $name => $bbcode) {
+                       if ($bbcode->isBlockElement) {
+                               $bbcodes[] = $name;
+                       }
+               }
+               
+               return $bbcodes;
+       }
+       
+       /**
+        * Returns the list of bbcodes that represent source code elements.
+        * 
+        * @return      string[]        list of bbcode source code elements
+        */
+       public function getSourceBBCodes() {
+               $bbcodes = [];
+               foreach ($this->bbcodes as $name => $bbcode) {
+                       if ($bbcode->isSourceCode) {
+                               $bbcodes[] = $name;
+                       }
+               }
+               
+               return $bbcodes;
+       }
+       
        /**
         * Compiles tag fragments into the custom HTML element.
         * 
index 05c5fc39c0b621daf8212585aed70dbff59443a2..4948e6fcbf53f5912cc06dc7b3f14dec785335b5 100644 (file)
@@ -1,23 +1,51 @@
 <?php
 namespace wcf\system\html\input\node;
 use wcf\system\bbcode\HtmlBBCodeParser;
-use wcf\system\exception\SystemException;
 use wcf\system\html\node\AbstractHtmlNode;
 use wcf\system\html\node\HtmlNodeProcessor;
 use wcf\util\DOMUtil;
-use wcf\util\JSON;
 
 /**
- * TOOD documentation
- * @since      2.2
+ * Transforms bbcode markers into the custom HTML element `<woltlab-metacode>`. This process
+ * outputs well-formed markup with proper element nesting.
+ * 
+ * @author      Alexander Ebert
+ * @copyright   2001-2016 WoltLab GmbH
+ * @license     GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package     com.woltlab.wcf
+ * @subpackage  system.html.input.node
+ * @category    Community Framework
+ * @since       2.2
  */
 class HtmlInputNodeWoltlabMetacodeMarker extends AbstractHtmlNode {
-       public $blockElements = ['code', 'quote'];
-       public $inlineElements = ['b', 'color', 'i', 'tt', 'u'];
-       public $sourceElements = ['code', 'tt'];
+       /**
+        * list of bbcodes that represent block elements
+        * @var string[]
+        */
+       public $blockElements = [];
+       
+       /**
+        * list of bbcodes that represent source code elements
+        * @var string[]
+        */
+       public $sourceElements = [];
        
+       /**
+        * @inheritDoc
+        */
        protected $tagName = 'woltlab-metacode-marker';
        
+       /**
+        * HtmlInputNodeWoltlabMetacodeMarker constructor.
+        */
+       public function __construct() {
+               $this->blockElements = HtmlBBCodeParser::getInstance()->getBlockBBCodes();
+               $this->sourceElements = HtmlBBCodeParser::getInstance()->getSourceBBCodes();
+       }
+       
+       /**
+        * @inheritDoc
+        */
        public function process(array $elements, HtmlNodeProcessor $htmlNodeProcessor) {
                // collect pairs
                $pairs = $this->buildPairs($elements);
@@ -34,13 +62,11 @@ class HtmlInputNodeWoltlabMetacodeMarker extends AbstractHtmlNode {
                $this->convertGroups($groups);
        }
        
-       public function replaceTag(array $data) {
-               return $data['parsedTag'];
-       }
-       
        /**
-        * @param array $pairs
-        * @return array
+        * Transforms bbcode markers inside source code elements into their plain bbcode representation.
+        * 
+        * @param       array           $pairs          list of bbcode marker pairs
+        * @return      array           filtered list of bbcode marker pairs
         */
        protected function revertMarkerInsideCodeBlocks(array $pairs) {
                $isInsideCode = function(\DOMElement $element) {
@@ -73,6 +99,12 @@ class HtmlInputNodeWoltlabMetacodeMarker extends AbstractHtmlNode {
                return $pairs;
        }
        
+       /**
+        * Builds the list of paired bbcode markers.
+        * 
+        * @param       \DOMElement[]           $elements       list of marker elements
+        * @return      array                   list of paired bbcode markers
+        */
        protected function buildPairs(array $elements) {
                $pairs = [];
                /** @var \DOMElement $element */
@@ -103,6 +135,12 @@ class HtmlInputNodeWoltlabMetacodeMarker extends AbstractHtmlNode {
                return $pairs;
        }
        
+       /**
+        * Validates bbcode marker pairs to include both an opening and closing element.
+        * 
+        * @param       array           $pairs          list of paired bbcode markers
+        * @return      array           filtered list of paired bbcode markers
+        */
        protected function validatePairs(array $pairs) {
                foreach ($pairs as $uuid => $data) {
                        if ($data['close'] === null) {
@@ -121,6 +159,12 @@ class HtmlInputNodeWoltlabMetacodeMarker extends AbstractHtmlNode {
                return $pairs;
        }
        
+       /**
+        * Groups bbcode marker pairs by their common bbcode identifier.
+        * 
+        * @param       array           $pairs          list of paired bbcode markers
+        * @return      array           grouped list of bbcode marker pairs
+        */
        protected function groupPairsByName(array $pairs) {
                $groups = [];
                foreach ($pairs as $uuid => $data) {
@@ -140,6 +184,11 @@ class HtmlInputNodeWoltlabMetacodeMarker extends AbstractHtmlNode {
                return $groups;
        }
        
+       /**
+        * Converts bbcode marker pairs into block- or inline-elements.
+        * 
+        * @param       array           $groups         grouped list of bbcode marker pairs
+        */
        protected function convertGroups(array $groups) {
                // process source elements first
                foreach ($this->sourceElements as $name) {
@@ -187,10 +236,12 @@ class HtmlInputNodeWoltlabMetacodeMarker extends AbstractHtmlNode {
        }
        
        /**
-        * @param string $name
-        * @param \DOMElement $start
-        * @param \DOMElement $end
-        * @param string $attributes
+        * Converts a block-level bbcode marker pair.
+        * 
+        * @param       string          $name           bbcode identifier
+        * @param       \DOMElement     $start          start node
+        * @param       \DOMElement     $end            end node
+        * @param       string          $attributes     encoded attribute string
         */
        protected function convertBlockElement($name, $start, $end, $attributes) {
                $commonAncestor = DOMUtil::getCommonAncestor($start, $end);
@@ -209,10 +260,12 @@ class HtmlInputNodeWoltlabMetacodeMarker extends AbstractHtmlNode {
        }
        
        /**
-        * @param string $name
-        * @param \DOMElement $start
-        * @param \DOMElement $end
-        * @param string $attributes
+        * Converts an inline bbcode marker pair.
+        * 
+        * @param       string          $name           bbcode identifier
+        * @param       \DOMElement     $start          start node
+        * @param       \DOMElement     $end            end node
+        * @param       string          $attributes     encoded attribute string
         */
        protected function convertInlineElement($name, $start, $end, $attributes) {
                if ($start->parentNode === $end->parentNode) {
@@ -254,13 +307,21 @@ class HtmlInputNodeWoltlabMetacodeMarker extends AbstractHtmlNode {
        }
        
        /**
-        * @param string $name
-        * @param string $attributes
-        * @param \DOMElement|null $startNode
-        * @param \DOMElement|null $endNode
-        * @return      \DOMElement
+        * Wraps a sequence of nodes using a newly created element. If `$startNode` is `null` the end
+        * node and all previous siblings will be added to the element. The reverse takes place if
+        * `$endNode` is `null`.
+        * 
+        * @param       string                  $name           element tag name
+        * @param       string                  $attributes     encoded attribute string
+        * @param       \DOMElement|null        $startNode      first node to wrap
+        * @param       \DOMElement|null        $endNode        last node to wrap
+        * @return      \DOMElement             newly created element
         */
        protected function wrapContent($name, $attributes, $startNode, $endNode) {
+               if ($startNode === null && $endNode === null) {
+                       throw new \InvalidArgumentException("Must provide an existing element for start node or end node, both cannot be null.");
+               }
+               
                $element = ($startNode) ? $startNode->ownerDocument->createElement('woltlab-metacode') : $endNode->ownerDocument->createElement('woltlab-metacode');
                $element->setAttribute('data-name', $name);
                $element->setAttribute('data-attributes', $attributes);
@@ -309,6 +370,12 @@ class HtmlInputNodeWoltlabMetacodeMarker extends AbstractHtmlNode {
                return false;
        }
        
+       /**
+        * Converts a bbcode marker pair into their plain bbcode representation. This method is used
+        * to convert markers inside source code elements.
+        * 
+        * @param       array           $pair           bbcode marker pair
+        */
        protected function convertToBBCode(array $pair) {
                /** @var \DOMElement $start */
                $start = $pair['open'];
@@ -316,7 +383,7 @@ class HtmlInputNodeWoltlabMetacodeMarker extends AbstractHtmlNode {
                $end = $pair['close'];
                
                $attributes = (isset($pair['attributes'])) ? $pair['attributes'] : '';
-               $textNode = $start->ownerDocument->createTextNode(HtmlBBCodeParser::getInstance()->buildBBCodeTag($pair['name'], $attributes));
+               $textNode = $start->ownerDocument->createTextNode(HtmlBBCodeParser::getInstance()->buildBBCodeTag($pair['name'], $attributes, true));
                DOMUtil::insertBefore($textNode, $start);
                DOMUtil::removeNode($start);
                
index 5e9d05c9e6ea4bc4e6a15fdff35157cf9fb62d3c..29cbc5495af0612d2c95b0aa9ac60c10492fef52 100644 (file)
@@ -1,6 +1,7 @@
 <?php
 namespace wcf\system\package\plugin;
 use wcf\data\bbcode\attribute\BBCodeAttributeEditor;
+use wcf\data\bbcode\BBCodeEditor;
 use wcf\data\package\PackageCache;
 use wcf\system\database\util\PreparedStatementConditionBuilder;
 use wcf\system\exception\SystemException;
@@ -11,7 +12,7 @@ use wcf\util\StringUtil;
  * Installs, updates and deletes bbcodes.
  * 
  * @author     Marcel Werk
- * @copyright  2001-2015 WoltLab GmbH
+ * @copyright  2001-2016 WoltLab GmbH
  * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
  * @package    com.woltlab.wcf
  * @subpackage acp.package.plugin
@@ -19,17 +20,17 @@ use wcf\util\StringUtil;
  */
 class BBCodePackageInstallationPlugin extends AbstractXMLPackageInstallationPlugin {
        /**
-        * @see \wcf\system\package\plugin\AbstractXMLPackageInstallationPlugin::$className
+        * @inheritDoc
         */
-       public $className = 'wcf\data\bbcode\BBCodeEditor';
+       public $className = BBCodeEditor::class;
        
        /**
-        * @see \wcf\system\package\plugin\AbstractPackageInstallationPlugin::$tableName
+        * @inheritDoc
         */
        public $tableName = 'bbcode';
        
        /**
-        * @see \wcf\system\package\plugin\AbstractXMLPackageInstallationPlugin::$tagName
+        * @see @inheritDoc
         */
        public $tagName = 'bbcode';
        
@@ -37,10 +38,10 @@ class BBCodePackageInstallationPlugin extends AbstractXMLPackageInstallationPlug
         * list of attributes per bbcode id
         * @var mixed[][]
         */
-       protected $attributes = array();
+       protected $attributes = [];
        
        /**
-        * @see \wcf\system\package\plugin\AbstractXMLPackageInstallationPlugin::handleDelete()
+        * @inheritDoc
         */
        protected function handleDelete(array $items) {
                $sql = "DELETE FROM     wcf".WCF_N."_".$this->tableName."
@@ -48,27 +49,28 @@ class BBCodePackageInstallationPlugin extends AbstractXMLPackageInstallationPlug
                                        AND packageID = ?";
                $statement = WCF::getDB()->prepareStatement($sql);
                foreach ($items as $item) {
-                       $statement->execute(array(
+                       $statement->execute([
                                $item['attributes']['name'],
                                $this->installation->getPackageID()
-                       ));
+                       ]);
                }
        }
        
        /**
-        * @see \wcf\system\package\plugin\AbstractXMLPackageInstallationPlugin::getElement()
+        * @inheritDoc
         */
        protected function getElement(\DOMXPath $xpath, array &$elements, \DOMElement $element) {
                $nodeValue = $element->nodeValue;
                
                // read pages
                if ($element->tagName == 'attributes') {
-                       $nodeValue = array();
+                       $nodeValue = [];
                        
                        $attributes = $xpath->query('child::*', $element);
+                       /** @var \DOMElement $attribute */
                        foreach ($attributes as $attribute) {
                                $attributeNo = $attribute->getAttribute('name');
-                               $nodeValue[$attributeNo] = array();
+                               $nodeValue[$attributeNo] = [];
                                
                                $attributeValues = $xpath->query('child::*', $attribute);
                                foreach ($attributeValues as $attributeValue) {
@@ -81,21 +83,21 @@ class BBCodePackageInstallationPlugin extends AbstractXMLPackageInstallationPlug
        }
        
        /**
-        * @see \wcf\system\package\plugin\AbstractXMLPackageInstallationPlugin::prepareImport()
+        * @inheritDoc
         */
        protected function prepareImport(array $data) {
-               $data = array(
+               $data = [
                        'bbcodeTag' => mb_strtolower(StringUtil::trim($data['attributes']['name'])),
                        'htmlOpen' => (!empty($data['elements']['htmlopen']) ? $data['elements']['htmlopen'] : ''),
                        'htmlClose' => (!empty($data['elements']['htmlclose']) ? $data['elements']['htmlclose'] : ''),
-                       'allowedChildren' => (!empty($data['elements']['allowedchildren']) ? $data['elements']['allowedchildren'] : 'all'),
                        'wysiwygIcon' => (!empty($data['elements']['wysiwygicon']) ? $data['elements']['wysiwygicon'] : ''),
-                       'attributes' => (isset($data['elements']['attributes']) ? $data['elements']['attributes'] : array()),
+                       'attributes' => (isset($data['elements']['attributes']) ? $data['elements']['attributes'] : []),
                        'className' => (!empty($data['elements']['classname']) ? $data['elements']['classname'] : ''),
+                       'isBlockElement' => (!empty($data['elements']['isBlockElement']) ? 1 : 0),
                        'isSourceCode' => (!empty($data['elements']['sourcecode']) ? 1 : 0),
                        'buttonLabel' => (isset($data['elements']['buttonlabel']) ? $data['elements']['buttonlabel'] : ''),
                        'originIsSystem' => 1
-               );
+               ];
                
                if ($data['wysiwygIcon'] && $data['buttonLabel']) {
                        $data['showButton'] = 1;
@@ -105,13 +107,9 @@ class BBCodePackageInstallationPlugin extends AbstractXMLPackageInstallationPlug
        }
        
        /**
-        * @see \wcf\system\package\plugin\AbstractXMLPackageInstallationPlugin::validateImport()
+        * @inheritDoc
         */
        protected function validateImport(array $data) {
-               if ($data['bbcodeTag'] == 'all' || $data['bbcodeTag'] == 'none') {
-                       throw new SystemException("BBCodes can't be called 'all' or 'none'");
-               }
-               
                // check if bbcode tag already exists
                $sqlData = $this->findExistingItem($data);
                $statement = WCF::getDB()->prepareStatement($sqlData['sql']);
@@ -124,26 +122,26 @@ class BBCodePackageInstallationPlugin extends AbstractXMLPackageInstallationPlug
        }
        
        /**
-        * @see \wcf\system\package\plugin\AbstractXMLPackageInstallationPlugin::findExistingItem()
+        * @inheritDoc
         */
        protected function findExistingItem(array $data) {
                $sql = "SELECT  *
                        FROM    wcf".WCF_N."_".$this->tableName."
                        WHERE   bbcodeTag = ?
                                AND packageID = ?";
-               $parameters = array(
+               $parameters = [
                        $data['bbcodeTag'],
                        $this->installation->getPackageID()
-               );
+               ];
                
-               return array(
+               return [
                        'sql' => $sql,
                        'parameters' => $parameters
-               );
+               ];
        }
        
        /**
-        * @see \wcf\system\package\plugin\AbstractXMLPackageInstallationPlugin::import()
+        * @inheritDoc
         */
        protected function import(array $row, array $data) {
                // extract attributes
@@ -158,11 +156,11 @@ class BBCodePackageInstallationPlugin extends AbstractXMLPackageInstallationPlug
        }
        
        /**
-        * @see \wcf\system\package\plugin\AbstractXMLPackageInstallationPlugin::postImport()
+        * @inheritDoc
         */
        protected function postImport() {
                $condition = new PreparedStatementConditionBuilder();
-               $condition->add('bbcodeID IN (?)', array(array_keys($this->attributes)));
+               $condition->add('bbcodeID IN (?)', [array_keys($this->attributes)]);
                
                // clear attributes
                $sql = "DELETE FROM     wcf".WCF_N."_bbcode_attribute
@@ -173,21 +171,21 @@ class BBCodePackageInstallationPlugin extends AbstractXMLPackageInstallationPlug
                if (!empty($this->attributes)) {
                        foreach ($this->attributes as $bbcodeID => $bbcodeAttributes) {
                                foreach ($bbcodeAttributes as $attributeNo => $attribute) {
-                                       BBCodeAttributeEditor::create(array(
+                                       BBCodeAttributeEditor::create([
                                                'bbcodeID' => $bbcodeID,
                                                'attributeNo' => $attributeNo,
                                                'attributeHtml' => (!empty($attribute['html']) ? $attribute['html'] : ''),
                                                'validationPattern' => (!empty($attribute['validationpattern']) ? $attribute['validationpattern'] : ''),
                                                'required' => (!empty($attribute['required']) ? $attribute['required'] : 0),
                                                'useText' => (!empty($attribute['usetext']) ? $attribute['usetext'] : 0),
-                                       ));
+                                       ]);
                                }
                        }
                }
        }
        
        /**
-        * @see \wcf\system\package\plugin\IPackageInstallationPlugin::getDefaultFilename()
+        * @inheritDoc
         * @since       2.2
         */
        public static function getDefaultFilename() {
index 6513048bd35ccaaa43e47951e902fde0580a22c8..afd1f68f367959389842062e8112610f0597e84f 100644 (file)
@@ -69,8 +69,6 @@
        <category name="wcf.acp.bbcode">
                <item name="wcf.acp.bbcode.add"><![CDATA[BBCode hinzufügen]]></item>
                <item name="wcf.acp.bbcode.add.userGroupOptionInfo"><![CDATA[Beachten Sie, dass der neu erstellte BBCode standardmäßig überall verwendet werden kann. Soll das nicht der Fall sein, bearbeiten Sie nach der Erstellung des BBCodes die entsprechenden Benutzergruppenrechte.]]></item>
-               <item name="wcf.acp.bbcode.allowedChildren"><![CDATA[Erlaubte Kindelemente]]></item>
-               <item name="wcf.acp.bbcode.allowedChildren.error.notValid"><![CDATA[Die Form für die erlaubten Kindelemente ist ungültig.]]></item>
                <item name="wcf.acp.bbcode.attribute"><![CDATA[Attribut]]></item>
                <item name="wcf.acp.bbcode.attribute.attributeHtml"><![CDATA[HTML-Code des Attributs]]></item>
                <item name="wcf.acp.bbcode.attribute.validationPattern"><![CDATA[Regulärer Ausdruck zur Validierung]]></item>
@@ -89,6 +87,8 @@
                <item name="wcf.acp.bbcode.edit"><![CDATA[BBCode bearbeiten]]></item>
                <item name="wcf.acp.bbcode.htmlClose"><![CDATA[Schließendes HTML-Tag]]></item>
                <item name="wcf.acp.bbcode.htmlOpen"><![CDATA[Öffnendes HTML-Tag]]></item>
+               <item name="wcf.acp.bbcode.isBlockElement"><![CDATA[BBCode als Block-Element behandeln]]></item>
+               <item name="wcf.acp.bbcode.isBlockElement.description"><![CDATA[Bei der Verarbeitung von BBCodes gelten abweichende Regeln für die Behandlung von Block-Elementen. Diese können Zeilenumbrüche und Absätze enthalten und beanspruchen immer die volle Breite; Typische Beispiele sind Zitate oder Listen.<br>Hinweis: Diese Option darf nicht für Inline-Elemente (z.B. Fettdruck oder Links) gesetzt werden.]]></item>
                <item name="wcf.acp.bbcode.isSourceCode"><![CDATA[Inhalt als Quelltext behandeln]]></item>
                <item name="wcf.acp.bbcode.isSourceCode.description"><![CDATA[Der Inhalt dieses BBCodes wird als Quelltext interpretiert, BBCodes und Smileys werden nicht umgewandelt.]]></item>
                <item name="wcf.acp.bbcode.list"><![CDATA[BBCodes]]></item>
index b9ea8f117722eb5e8ca1c73070ee31dceedaeba7..3e1fcecd2de4ae0bab6577caac926a9cb8a0edb8 100644 (file)
@@ -69,8 +69,6 @@
        <category name="wcf.acp.bbcode">
                <item name="wcf.acp.bbcode.add"><![CDATA[Add BBCode]]></item>
                <item name="wcf.acp.bbcode.add.userGroupOptionInfo"><![CDATA[Newly created BBCodes will be accessible for everyone. You can restrict usage by editing the specific user group permissions.]]></item>
-               <item name="wcf.acp.bbcode.allowedChildren"><![CDATA[Allowed Children]]></item>
-               <item name="wcf.acp.bbcode.allowedChildren.error.notValid"><![CDATA[List of allowed children is invalid.]]></item>
                <item name="wcf.acp.bbcode.attribute"><![CDATA[Attribute]]></item>
                <item name="wcf.acp.bbcode.attribute.attributeHtml"><![CDATA[Attribute HTML code]]></item>
                <item name="wcf.acp.bbcode.attribute.validationPattern"><![CDATA[Regular Expression for Validation]]></item>
@@ -89,6 +87,8 @@
                <item name="wcf.acp.bbcode.edit"><![CDATA[Edit BBCode]]></item>
                <item name="wcf.acp.bbcode.htmlClose"><![CDATA[Closing HTML tag]]></item>
                <item name="wcf.acp.bbcode.htmlOpen"><![CDATA[Opening HTML tag]]></item>
+               <item name="wcf.acp.bbcode.isBlockElement"><![CDATA[BBCode represents a block element]]></item>
+               <item name="wcf.acp.bbcode.isBlockElement.description"><![CDATA[Block elements are treated differently when processed. They can contain line breaks and paragraphs, and generally take up the entire available width. Common examples for block elements include quotes and lists.<br>Heads up! You must not set this option for inline elements such as bold or links.]]></item>
                <item name="wcf.acp.bbcode.isSourceCode"><![CDATA[Content represents source code]]></item>
                <item name="wcf.acp.bbcode.isSourceCode.description"><![CDATA[Disables conversion of BBCodes and smilies.]]></item>
                <item name="wcf.acp.bbcode.list"><![CDATA[BBCodes]]></item>
index 3f1df99cfefb58ad779a9dfc37c15ff8724b250a..673229551091ed74ea3d3ddfedffd0abe54a9df7 100644 (file)
@@ -192,10 +192,10 @@ CREATE TABLE wcf1_bbcode (
        packageID INT(10) NOT NULL,
        htmlOpen VARCHAR(255) NOT NULL DEFAULT '',
        htmlClose VARCHAR(255) NOT NULL DEFAULT '',
-       allowedChildren VARCHAR(255) NOT NULL DEFAULT 'all',
        className VARCHAR(255) NOT NULL DEFAULT '',
        wysiwygIcon varchar(255) NOT NULL DEFAULT '',
        buttonLabel VARCHAR(255) NOT NULL DEFAULT '',
+       isBlockElement TINYINT(1) NOT NULL DEFAULT 0,
        isSourceCode TINYINT(1) NOT NULL DEFAULT 0,
        isDisabled TINYINT(1) NOT NULL DEFAULT 0,
        showButton TINYINT(1) NOT NULL DEFAULT 0,