--- /dev/null
+<section id="{@$container->getPrefixedId()}" class="section{foreach from=$container->getClasses() item='class'} {$class}{/foreach}"{foreach from=$container->getAttributes() key='attributeName' item='attributeValue'} {$attributeName}="{$attributeValue}"{/foreach}>
+ {if $container->getLabel() !== null}
+ {if $container->getDescription() !== null}
+ <header class="sectionHeader">
+ <h2 class="sectionTitle">{@$container->getLabel()}</h2>
+ <p class="sectionDescription">{@$container->getDescription()}</p>
+ </header>
+ {else}
+ <h2 class="sectionTitle">{@$container->getLabel()}</h2>
+ {/if}
+ {/if}
+
+ {include file='__formContainerChildren'}
+</section>
--- /dev/null
+{foreach from=$container item='child'}
+ {@$child->getHtml()}
+{/foreach}
\ No newline at end of file
--- /dev/null
+<div id="{@$container->getPrefixedId()}" class="tabMenuContent{foreach from=$container->getClasses() item='class'} {$class}{/foreach}"{foreach from=$container->getAttributes() key='attributeName' item='attributeValue'} {$attributeName}="{$attributeValue}"{/foreach}>
+ {include file='__formContainerChildren'}
+</div>
--- /dev/null
+<div id="{@$container->getPrefixedId()}" class="section tabMenuContainer{foreach from=$container->getClasses() item='class'} {$class}{/foreach}"{foreach from=$container->getAttributes() key='attributeName' item='attributeValue'} {$attributeName}="{$attributeValue}"{/foreach}>
+ <nav class="tabMenu">
+ <ul>
+ {foreach from=$container item='child'}
+ <li><a href="{@$__wcf->getAnchor($child->getPrefixedId())}">{@$child->getLabel()}</a></li>
+ {/foreach}
+ </ul>
+ </nav>
+
+ {include file='__formContainerChildren'}
+</div>
--- /dev/null
+<div id="{@$container->getPrefixedId()}" class="tabMenuContainer tabMenuContent{foreach from=$container->getClasses() item='class'} {$class}{/foreach}"{foreach from=$container->getAttributes() key='attributeName' item='attributeValue'} {$attributeName}="{$attributeValue}"{/foreach}>
+ <nav class="menu">
+ <ul>
+ {foreach from=$container item='child'}
+ <li><a href="{@$__wcf->getAnchor($child->getPrefixedId())}">{@$container->getLabel()}</a></li>
+ {/foreach}
+ </ul>
+ </nav>
+
+ {include file='__formContainerChildren'}
+</div>
--- /dev/null
+<?php
+namespace wcf\system\form\builder\container;
+use wcf\system\form\builder\IFormChildNode;
+use wcf\system\form\builder\IFormDocument;
+use wcf\system\form\builder\TFormChildNode;
+use wcf\system\form\builder\TFormElement;
+use wcf\system\form\builder\TFormParentNode;
+use wcf\system\WCF;
+
+/**
+ * Represents a default container.
+ *
+ * @author Matthias Schmidt
+ * @copyright 2001-2018 WoltLab GmbH
+ * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package WoltLabSuite\Core\System\Form\Builder\Container
+ * @since 3.2
+ */
+class FormContainer implements IFormContainer {
+ use TFormChildNode;
+ use TFormElement;
+ use TFormParentNode {
+ validateChild as protected defaultValidateChild;
+ }
+
+ /**
+ * name of container template
+ * @var string
+ */
+ protected $templateName = '__formContainer';
+
+ /**
+ * @inheritDoc
+ */
+ public function getHtml() {
+ return WCF::getTPL()->fetch($this->templateName, 'wcf', [
+ 'container' => $this
+ ], true);
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function validateChild(IFormChildNode $child) {
+ $this->defaultValidateChild($child);
+
+ if ($this instanceof ITabFormMenuContainer) {
+ if (!($child instanceof ITabFormContainer)) {
+ throw new \InvalidArgumentException("Cannot append non-tab container ".get_class($child)."('{$child->getId()}') to tab menu container '{$this->getId()}'");
+ }
+
+ if ($child instanceof ITabMenuFormContainer) {
+ if ($this->parent() instanceof ITabMenuFormContainer) {
+ throw new \InvalidArgumentException("Tab menus can only be nested once.");
+ }
+ }
+ }
+ else if ($child instanceof ITabFormContainer) {
+ throw new \InvalidArgumentException("Cannot append tab container '{$child->getId()}' to non-tab menu container '{$this->getId()}'.");
+ }
+
+ if ($this instanceof ITabFormContainer && !($child instanceof IFormContainer)) {
+ throw new \InvalidArgumentException("Child ".get_class($child)."('{$child->getId()}') has to be a form container to be appended to tab container '{$this->getId()}'.");
+ }
+
+ if ($child instanceof ITabMenuFormContainer) {
+ $parent = $this;
+ while (!($parent instanceof IFormDocument) && $parent = $parent->getParent()) {
+ if ($parent instanceof ITabMenuFormContainer) {
+ throw new \InvalidArgumentException("A tab menu container may only have another tab menu container as a parent, not as an earlier ancestor.");
+ }
+ }
+ }
+ }
+}
--- /dev/null
+<?php
+namespace wcf\system\form\builder\container;
+
+/**
+ * Represents a container that is a tab of a tab menu.
+ *
+ * @author Matthias Schmidt
+ * @copyright 2001-2018 WoltLab GmbH
+ * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package WoltLabSuite\Core\System\Form\Builder\Container
+ * @since 3.2
+ */
+class TabFormContainer extends FormContainer implements ITabFormContainer {
+ /**
+ * @inheritDoc
+ */
+ protected $templateName = '__tabFormContainer';
+}
--- /dev/null
+<?php
+namespace wcf\system\form\builder\container;
+
+/**
+ * Represents a container whose children are tabs of a tab menu.
+ *
+ * @author Matthias Schmidt
+ * @copyright 2001-2018 WoltLab GmbH
+ * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package WoltLabSuite\Core\System\Form\Builder\Container
+ * @since 3.2
+ */
+class TabMenuFormContainer extends FormContainer implements ITabMenuFormContainer {
+ /**
+ * @inheritDoc
+ */
+ protected $templateName = '__tabMenuFormContainer';
+}
--- /dev/null
+<?php
+namespace wcf\system\form\builder\container;
+
+/**
+ * Represents a container that is a tab of a tab menu and a tab menu itself.
+ *
+ * @author Matthias Schmidt
+ * @copyright 2001-2018 WoltLab GmbH
+ * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package WoltLabSuite\Core\System\Form\Builder\Container
+ * @since 3.2
+ */
+class TabTabMenuFormContainer extends FormContainer implements ITabFormContainer, ITabMenuFormContainer {
+ /**
+ * @inheritDoc
+ */
+ protected $templateName = '__formTabTabMenuContainer';
+}