xref: /plugin/combo/ComboStrap/EditButton.php (revision 20eb9985c467941ebe097c0d06f192ce9fbdfa05)
104fd306cSNickeau<?php
204fd306cSNickeau
304fd306cSNickeau
404fd306cSNickeaunamespace ComboStrap;
504fd306cSNickeau
604fd306cSNickeauuse ComboStrap\TagAttribute\StyleAttribute;
704fd306cSNickeau
804fd306cSNickeau/**
904fd306cSNickeau * Class SectionEdit
1004fd306cSNickeau * @package ComboStrap
1104fd306cSNickeau * Manage the edit button
1204fd306cSNickeau * (ie add HTML comment that are parsed into forms
1304fd306cSNickeau * for editor user)
1404fd306cSNickeau */
1504fd306cSNickeauclass EditButton
1604fd306cSNickeau{
1704fd306cSNickeau
1804fd306cSNickeau
1904fd306cSNickeau    const SEC_EDIT_PATTERN = "/" . self::ENTER_HTML_COMMENT . "\s*" . self::EDIT_BUTTON_PREFIX . "({.*?})\s*" . self::CLOSE_HTML_COMMENT . "/";
2004fd306cSNickeau    const EDIT_BUTTON_PREFIX = "EDIT";
2104fd306cSNickeau    const WIKI_ID = "wiki-id";
2204fd306cSNickeau
2304fd306cSNickeau    const FORM_ID = "hid"; // id to be dokuwiki conform
2404fd306cSNickeau    const EDIT_MESSAGE = "name"; // name to be dokuwiki conform
2504fd306cSNickeau
2604fd306cSNickeau    const CANONICAL = "edit-button";
2704fd306cSNickeau    const ENTER_HTML_COMMENT = "<!--";
2804fd306cSNickeau    const CLOSE_HTML_COMMENT = "-->";
2904fd306cSNickeau    const SNIPPET_ID = "edit-button";
3004fd306cSNickeau
3104fd306cSNickeau
3204fd306cSNickeau    /**
3304fd306cSNickeau     * The target drive the type of editor
3404fd306cSNickeau     * As of today, there is two type
3504fd306cSNickeau     * section and table
3604fd306cSNickeau     */
3704fd306cSNickeau    const TARGET_ATTRIBUTE_NAME = "target";
3804fd306cSNickeau    const TARGET_SECTION_VALUE = "section";
3904fd306cSNickeau    /**
4004fd306cSNickeau     * The table does not have an edit form at all
4104fd306cSNickeau     * It's created by {@link \Doku_Renderer_xhtml::table_close()}
4204fd306cSNickeau     * They are not printed by default via CSS. Edittable show them by default via Javascript
4304fd306cSNickeau     */
4404fd306cSNickeau    const TARGET_TABLE_VALUE = "table";
4504fd306cSNickeau    public const EDIT_SECTION_TARGET = 'section';
4604fd306cSNickeau    const RANGE = "range";
4704fd306cSNickeau    const DOKUWIKI_FORMAT = "dokuwiki";
4804fd306cSNickeau    const COMBO_FORMAT = "combo";
4904fd306cSNickeau    const TAG = "edit-button";
5004fd306cSNickeau    const CLASS_SUFFIX = "edit-button";
5104fd306cSNickeau
5204fd306cSNickeau
5304fd306cSNickeau    private $label;
5404fd306cSNickeau    /**
5504fd306cSNickeau     * @var string
5604fd306cSNickeau     */
5704fd306cSNickeau    private $wikiId;
5804fd306cSNickeau
5904fd306cSNickeau    /**
6004fd306cSNickeau     * Edit type
6104fd306cSNickeau     * @var string
6204fd306cSNickeau     * This is the default
6304fd306cSNickeau     */
6404fd306cSNickeau    private string $target = self::TARGET_SECTION_VALUE;
6504fd306cSNickeau    /**
6604fd306cSNickeau     * @var int
6704fd306cSNickeau     */
6804fd306cSNickeau    private int $startPosition;
6904fd306cSNickeau
7004fd306cSNickeau    private ?int $endPosition;
7104fd306cSNickeau    /**
7204fd306cSNickeau     * @var string $format - to conform or not to dokuwiki format
7304fd306cSNickeau     */
7404fd306cSNickeau    private string $format = self::COMBO_FORMAT;
7504fd306cSNickeau
7604fd306cSNickeau    /**
7704fd306cSNickeau     * the id of the heading, ie the id of the section
7804fd306cSNickeau     * Not really needed, just to be conform with Dokuwiki
7904fd306cSNickeau     * When the edit button is not for an outline may be null
8004fd306cSNickeau     */
8104fd306cSNickeau    private ?string $outlineHeadingId = null;
8204fd306cSNickeau    /**
8304fd306cSNickeau     * @var ?int $sectionid - sequence id of the section used only by dokuwiki
8404fd306cSNickeau     * When the edit button is not for an outline may be null
8504fd306cSNickeau     */
8604fd306cSNickeau    private ?int $outlineSectionId = null;
8704fd306cSNickeau
8804fd306cSNickeau
8904fd306cSNickeau    /**
9004fd306cSNickeau     * Section constructor.
9104fd306cSNickeau     */
9204fd306cSNickeau    public function __construct($label)
9304fd306cSNickeau    {
9404fd306cSNickeau        $this->label = $label;
9504fd306cSNickeau    }
9604fd306cSNickeau
9704fd306cSNickeau
9804fd306cSNickeau    public static function create($label): EditButton
9904fd306cSNickeau    {
10004fd306cSNickeau        return new EditButton($label);
10104fd306cSNickeau    }
10204fd306cSNickeau
10304fd306cSNickeau    public static function createFromCallStackArray($attributes): EditButton
10404fd306cSNickeau    {
10504fd306cSNickeau        $label = $attributes[\syntax_plugin_combo_edit::LABEL];
10604fd306cSNickeau        $startPosition = $attributes[\syntax_plugin_combo_edit::START_POSITION];
10704fd306cSNickeau        $endPosition = $attributes[\syntax_plugin_combo_edit::END_POSITION];
10804fd306cSNickeau        $wikiId = $attributes[TagAttributes::WIKI_ID];
10904fd306cSNickeau        $editButton = EditButton::create($label)
11004fd306cSNickeau            ->setStartPosition($startPosition)
11104fd306cSNickeau            ->setEndPosition($endPosition)
11204fd306cSNickeau            ->setWikiId($wikiId);
11304fd306cSNickeau        $headingId = $attributes[\syntax_plugin_combo_edit::HEADING_ID];
11404fd306cSNickeau        if ($headingId !== null) {
11504fd306cSNickeau            $editButton->setOutlineHeadingId($headingId);
11604fd306cSNickeau        }
11704fd306cSNickeau        $sectionId = $attributes[\syntax_plugin_combo_edit::SECTION_ID];
11804fd306cSNickeau        if ($sectionId !== null) {
11904fd306cSNickeau            $editButton->setOutlineSectionId($sectionId);
12004fd306cSNickeau        }
12104fd306cSNickeau        $format = $attributes[\syntax_plugin_combo_edit::FORMAT];
12204fd306cSNickeau        if ($format !== null) {
12304fd306cSNickeau            $editButton->setFormat($format);
12404fd306cSNickeau        }
12504fd306cSNickeau        return $editButton;
12604fd306cSNickeau
12704fd306cSNickeau
12804fd306cSNickeau    }
12904fd306cSNickeau
13004fd306cSNickeau    public static function deleteAll(string $html)
13104fd306cSNickeau    {
13204fd306cSNickeau        // Dokuwiki way is to delete
13304fd306cSNickeau        // but because they are comment, they are not shown
13404fd306cSNickeau        // We delete to serve clean page to search engine
13504fd306cSNickeau        return preg_replace(SEC_EDIT_PATTERN, '', $html);
13604fd306cSNickeau    }
13704fd306cSNickeau
13804fd306cSNickeau    public static function replaceOrDeleteAll(string $html_output)
13904fd306cSNickeau    {
14004fd306cSNickeau        try {
14104fd306cSNickeau            return EditButton::replaceAll($html_output);
14204fd306cSNickeau        } catch (ExceptionNotAuthorized|ExceptionBadState $e) {
14304fd306cSNickeau            return EditButton::deleteAll($html_output);
14404fd306cSNickeau        }
14504fd306cSNickeau    }
14604fd306cSNickeau
14704fd306cSNickeau    /**
14804fd306cSNickeau     * See {@link \Doku_Renderer_xhtml::finishSectionEdit()}
14904fd306cSNickeau     */
15004fd306cSNickeau    public function toTag(): string
15104fd306cSNickeau    {
15204fd306cSNickeau
15304fd306cSNickeau        /**
15404fd306cSNickeau         * The following data are mandatory from:
15504fd306cSNickeau         * {@link html_secedit_get_button}
15604fd306cSNickeau         */
15704fd306cSNickeau        $wikiId = $this->getWikiId();
15804fd306cSNickeau
15904fd306cSNickeau
16004fd306cSNickeau        /**
16104fd306cSNickeau         * We follow the order of Dokuwiki for compatibility purpose
16204fd306cSNickeau         */
16304fd306cSNickeau        $data[self::TARGET_ATTRIBUTE_NAME] = $this->target;
16404fd306cSNickeau
16504fd306cSNickeau        if ($this->format === self::COMBO_FORMAT) {
16604fd306cSNickeau            /**
16704fd306cSNickeau             * In the combo edit format, we had the dokuwiki id
16804fd306cSNickeau             * because the edit button may also be on the secondary slot
16904fd306cSNickeau             */
17004fd306cSNickeau            $data[self::WIKI_ID] = $wikiId;
17104fd306cSNickeau        }
17204fd306cSNickeau        $data[self::EDIT_MESSAGE] = $this->label;
17304fd306cSNickeau        if ($this->format === self::COMBO_FORMAT) {
17404fd306cSNickeau            /**
17504fd306cSNickeau             * In the combo edit format, we had the dokuwiki id as form id
17604fd306cSNickeau             * to make it unique on the whole page
17704fd306cSNickeau             * because the edit button may also be on the secondary slot
17804fd306cSNickeau             */
17904fd306cSNickeau            $slotPath = WikiPath::createMarkupPathFromId($wikiId);
18004fd306cSNickeau            $formId = ExecutionContext::getActualOrCreateFromEnv()
18104fd306cSNickeau                ->getIdManager()
18204fd306cSNickeau                ->generateNewHtmlIdForComponent(self::CANONICAL, $slotPath);
18304fd306cSNickeau            $data[self::FORM_ID] = $formId;
18404fd306cSNickeau
18504fd306cSNickeau
18604fd306cSNickeau        } else {
18704fd306cSNickeau            $data[self::FORM_ID] = $this->getHeadingId();
18804fd306cSNickeau            $data["codeblockOffset"] = 0; // what is that ?
18904fd306cSNickeau            $data["secid"] = $this->getSectionId();
19004fd306cSNickeau        }
19104fd306cSNickeau        $data[self::RANGE] = $this->getRange();
19204fd306cSNickeau
19304fd306cSNickeau
19404fd306cSNickeau        return self::EDIT_BUTTON_PREFIX . Html::encode(json_encode($data));
19504fd306cSNickeau    }
19604fd306cSNickeau
19704fd306cSNickeau    /**
19804fd306cSNickeau     *
19904fd306cSNickeau     * @throws ExceptionBadArgument - if the wiki id could not be found
20004fd306cSNickeau     * @throws ExceptionNotEnabled
20104fd306cSNickeau     */
20204fd306cSNickeau    public function toHtmlComment(): string
20304fd306cSNickeau    {
20404fd306cSNickeau        global $ACT;
20504fd306cSNickeau        if ($ACT === FetcherMarkup::MARKUP_DYNAMIC_EXECUTION_NAME) {
20604fd306cSNickeau            // ie weblog, they are generated via dynamic markup
20704fd306cSNickeau            // meaning that there is no button to edit the file
20804fd306cSNickeau            if (!PluginUtility::isTest()) {
20904fd306cSNickeau                return "";
21004fd306cSNickeau            }
21104fd306cSNickeau        }
21204fd306cSNickeau        /**
21304fd306cSNickeau         * We don't encode there is only internal information
21404fd306cSNickeau         * and this is easier to see / debug the output
21504fd306cSNickeau         */
21604fd306cSNickeau        return self::ENTER_HTML_COMMENT . " " . $this->toTag() . " " . self::CLOSE_HTML_COMMENT;
21704fd306cSNickeau    }
21804fd306cSNickeau
21904fd306cSNickeau    public function __toString()
22004fd306cSNickeau    {
22104fd306cSNickeau        return "Section Edit $this->label";
22204fd306cSNickeau    }
22304fd306cSNickeau
22404fd306cSNickeau
22504fd306cSNickeau    /**
22604fd306cSNickeau     * @throws ExceptionNotAuthorized - if the user cannot modify the page
22704fd306cSNickeau     * @throws ExceptionBadState - if the page is a revision page or the HTML is not the output of a page
22804fd306cSNickeau     */
22904fd306cSNickeau    public static function replaceAll($html)
23004fd306cSNickeau    {
23104fd306cSNickeau
23204fd306cSNickeau        if (!Identity::isWriter()) {
23304fd306cSNickeau            throw new ExceptionNotAuthorized("Page is not writable by the user");
23404fd306cSNickeau        }
23504fd306cSNickeau        /**
23604fd306cSNickeau         * Delete the edit comment
23704fd306cSNickeau         *   * if not writable
23804fd306cSNickeau         *   * or an old revision
23904fd306cSNickeau         * Original: {@link html_secedit()} {@link html_secedit_get_button()}
24004fd306cSNickeau         */
24104fd306cSNickeau        global $INFO;
24204fd306cSNickeau        if (isset($INFO)) {
24304fd306cSNickeau            // the page is a revision page
24439026d0aSgerardnico            $rev = $INFO['rev'] ?? 0;
24539026d0aSgerardnico            if ($rev !== 0) {
24604fd306cSNickeau                throw new ExceptionBadState("Internal Error: No edit button can be added to a revision page");
24704fd306cSNickeau            }
24804fd306cSNickeau        }
24904fd306cSNickeau
25004fd306cSNickeau
25104fd306cSNickeau        /**
25204fd306cSNickeau         * Request based because the button are added only for a user that can write
25304fd306cSNickeau         */
25404fd306cSNickeau        $snippetManager = PluginUtility::getSnippetManager();
25504fd306cSNickeau        $snippetManager->attachCssInternalStylesheet(self::SNIPPET_ID);
25604fd306cSNickeau        $snippetManager->attachJavascriptFromComponentId(self::SNIPPET_ID);
25704fd306cSNickeau
25804fd306cSNickeau        /**
25904fd306cSNickeau         * The callback function on all edit comment
26004fd306cSNickeau         * @param $matches
26104fd306cSNickeau         * @return string
26204fd306cSNickeau         */
26304fd306cSNickeau        $editFormCallBack = function ($matches) {
26404fd306cSNickeau            $json = Html::decode($matches[1]);
26504fd306cSNickeau            $data = json_decode($json, true);
26604fd306cSNickeau
26704fd306cSNickeau            $target = $data[self::TARGET_ATTRIBUTE_NAME];
26804fd306cSNickeau
269*20eb9985SNico            $message = $data[self::EDIT_MESSAGE] ?? null;
27004fd306cSNickeau            unset($data[self::EDIT_MESSAGE]);
27104fd306cSNickeau            if ($message === null || trim($message) === "") {
27204fd306cSNickeau                $message = "Edit {$target}";
27304fd306cSNickeau            }
27404fd306cSNickeau
27504fd306cSNickeau            if ($data === NULL) {
27604fd306cSNickeau                LogUtility::internalError("No data found in the edit comment", self::CANONICAL);
27704fd306cSNickeau                return "";
27804fd306cSNickeau            }
279d899a2a6Sgerardnico            $wikiId = $data[self::WIKI_ID] ?? null;
28004fd306cSNickeau            unset($data[self::WIKI_ID]);
28104fd306cSNickeau            if ($wikiId === null) {
28204fd306cSNickeau                try {
28304fd306cSNickeau                    $page = MarkupPath::createPageFromExecutingId();
28404fd306cSNickeau                } catch (ExceptionNotFound $e) {
28504fd306cSNickeau                    LogUtility::internalError("A page id is mandatory for a edit button (no wiki id, no global ID were found). No edit buttons was created then.", self::CANONICAL);
28604fd306cSNickeau                    return "";
28704fd306cSNickeau                }
28804fd306cSNickeau            } else {
28904fd306cSNickeau                $page = MarkupPath::createMarkupFromId($wikiId);
29004fd306cSNickeau            }
29104fd306cSNickeau            $formId = $data[self::FORM_ID];
29204fd306cSNickeau            unset($data[self::FORM_ID]);
29304fd306cSNickeau            $data["summary"] = $message;
29404fd306cSNickeau            try {
29504fd306cSNickeau                $data['rev'] = $page->getPathObject()->getRevisionOrDefault();
29604fd306cSNickeau            } catch (ExceptionNotFound $e) {
29704fd306cSNickeau                //LogUtility::internalError("The file ({$page->getPathObject()}) does not exist, we cannot set the last modified time on the edit buttons.", self::CANONICAL);
29804fd306cSNickeau            }
29904fd306cSNickeau            $hiddenInputs = "";
30004fd306cSNickeau            foreach ($data as $key => $val) {
30104fd306cSNickeau                $inputAttributes = TagAttributes::createEmpty()
30204fd306cSNickeau                    ->addOutputAttributeValue("name", $key)
30304fd306cSNickeau                    ->addOutputAttributeValue("value", $val)
30404fd306cSNickeau                    ->addOutputAttributeValue("type", "hidden");
30504fd306cSNickeau                $hiddenInputs .= $inputAttributes->toHtmlEmptyTag("input");
30604fd306cSNickeau            }
30704fd306cSNickeau            $url = $page->getUrl()
30804fd306cSNickeau                ->withoutRewrite()
30904fd306cSNickeau                ->toHtmlString();
31004fd306cSNickeau            $classPageEdit = StyleAttribute::addComboStrapSuffix(self::CLASS_SUFFIX);
31104fd306cSNickeau
31204fd306cSNickeau            /**
31304fd306cSNickeau             * Important Note: the first div and the public class is mandatory for the edittable plugin
31404fd306cSNickeau             * See {@link editbutton.js file}
31504fd306cSNickeau             */
31604fd306cSNickeau            $editTableClass = "editbutton_{$target}";
31704fd306cSNickeau            return <<<EOF
31804fd306cSNickeau<div class="$classPageEdit $editTableClass">
31904fd306cSNickeau    <form id="$formId" method="post" action="{$url}">
32004fd306cSNickeau    $hiddenInputs
32104fd306cSNickeau    <input name="do" type="hidden" value="edit"/>
32204fd306cSNickeau    <button type="submit" title="$message">
32304fd306cSNickeau    </button>
32404fd306cSNickeau    </form>
32504fd306cSNickeau</div>
32604fd306cSNickeauEOF;
32704fd306cSNickeau        };
32804fd306cSNickeau
32904fd306cSNickeau        /**
33004fd306cSNickeau         * The replacement
33104fd306cSNickeau         */
33204fd306cSNickeau        return preg_replace_callback(self::SEC_EDIT_PATTERN, $editFormCallBack, $html);
33304fd306cSNickeau    }
33404fd306cSNickeau
33504fd306cSNickeau
33604fd306cSNickeau    public function setWikiId(string $id): EditButton
33704fd306cSNickeau    {
33804fd306cSNickeau        $this->wikiId = $id;
33904fd306cSNickeau        return $this;
34004fd306cSNickeau    }
34104fd306cSNickeau
34204fd306cSNickeau    /**
34304fd306cSNickeau     * Page / Section edit
34404fd306cSNickeau     * (This is known as the target for dokuwiki)
34504fd306cSNickeau     * @param string $target
34604fd306cSNickeau     * @return $this
34704fd306cSNickeau     *
34804fd306cSNickeau     */
34904fd306cSNickeau    public function setTarget(string $target): EditButton
35004fd306cSNickeau    {
35104fd306cSNickeau        $this->target = $target;
35204fd306cSNickeau        return $this;
35304fd306cSNickeau    }
35404fd306cSNickeau
35504fd306cSNickeau    public function setStartPosition(int $startPosition): EditButton
35604fd306cSNickeau    {
35704fd306cSNickeau        $this->startPosition = $startPosition;
35804fd306cSNickeau        return $this;
35904fd306cSNickeau    }
36004fd306cSNickeau
36104fd306cSNickeau    public function setEndPosition(?int $endPosition): EditButton
36204fd306cSNickeau    {
36304fd306cSNickeau        $this->endPosition = $endPosition;
36404fd306cSNickeau        return $this;
36504fd306cSNickeau    }
36604fd306cSNickeau
36704fd306cSNickeau    /**
36804fd306cSNickeau     * @return string the file character position range of the section to edit
36904fd306cSNickeau     */
37004fd306cSNickeau    private function getRange(): string
37104fd306cSNickeau    {
37204fd306cSNickeau        $range = "";
37304fd306cSNickeau        if (isset($this->startPosition)) {
37404fd306cSNickeau            $range = $this->startPosition;
37504fd306cSNickeau        }
37604fd306cSNickeau        $range = "$range-";
37704fd306cSNickeau        if (isset($this->endPosition)) {
37804fd306cSNickeau            $range = "$range{$this->endPosition}";
37904fd306cSNickeau        }
38004fd306cSNickeau        return $range;
38104fd306cSNickeau
38204fd306cSNickeau    }
38304fd306cSNickeau
38404fd306cSNickeau    public function toComboCallComboFormat(): Call
38504fd306cSNickeau    {
38604fd306cSNickeau        return $this->toComboCall(self::COMBO_FORMAT);
38704fd306cSNickeau    }
38804fd306cSNickeau
38904fd306cSNickeau    public function toComboCall($format): Call
39004fd306cSNickeau    {
39104fd306cSNickeau        return Call::createComboCall(
39204fd306cSNickeau            \syntax_plugin_combo_edit::TAG,
39304fd306cSNickeau            DOKU_LEXER_SPECIAL,
39404fd306cSNickeau            [
39504fd306cSNickeau                \syntax_plugin_combo_edit::START_POSITION => $this->startPosition,
39604fd306cSNickeau                \syntax_plugin_combo_edit::END_POSITION => $this->endPosition,
39704fd306cSNickeau                \syntax_plugin_combo_edit::LABEL => $this->label,
39804fd306cSNickeau                \syntax_plugin_combo_edit::FORMAT => $format,
39904fd306cSNickeau                \syntax_plugin_combo_edit::HEADING_ID => $this->getHeadingId(),
40004fd306cSNickeau                \syntax_plugin_combo_edit::SECTION_ID => $this->getSectionId(),
40104fd306cSNickeau                TagAttributes::WIKI_ID => $this->getWikiId()
40204fd306cSNickeau            ]
40304fd306cSNickeau        );
40404fd306cSNickeau    }
40504fd306cSNickeau
40604fd306cSNickeau
40704fd306cSNickeau    /**
40804fd306cSNickeau     *
40904fd306cSNickeau     */
41004fd306cSNickeau    private function getWikiId(): string
41104fd306cSNickeau    {
41204fd306cSNickeau
41304fd306cSNickeau        $wikiId = $this->wikiId;
41404fd306cSNickeau        if ($wikiId !== null) {
41504fd306cSNickeau            return $wikiId;
41604fd306cSNickeau        }
41704fd306cSNickeau
41804fd306cSNickeau        return ExecutionContext::getActualOrCreateFromEnv()->getRequestedPath()->getWikiId();
41904fd306cSNickeau
42004fd306cSNickeau
42104fd306cSNickeau    }
42204fd306cSNickeau
42304fd306cSNickeau
42404fd306cSNickeau    public function toComboCallDokuWikiForm(): Call
42504fd306cSNickeau    {
42604fd306cSNickeau        return $this->toComboCall(self::DOKUWIKI_FORMAT);
42704fd306cSNickeau    }
42804fd306cSNickeau
42904fd306cSNickeau    /** @noinspection PhpReturnValueOfMethodIsNeverUsedInspection */
43004fd306cSNickeau    private function setFormat($format): EditButton
43104fd306cSNickeau    {
43204fd306cSNickeau
43304fd306cSNickeau        if (!in_array($format, [self::DOKUWIKI_FORMAT, self::COMBO_FORMAT])) {
43404fd306cSNickeau            LogUtility::internalError("The tag format ($format) is not valid", self::CANONICAL);
43504fd306cSNickeau            return $this;
43604fd306cSNickeau        }
43704fd306cSNickeau        $this->format = $format;
43804fd306cSNickeau        return $this;
43904fd306cSNickeau    }
44004fd306cSNickeau
44104fd306cSNickeau    public function setOutlineHeadingId($id): EditButton
44204fd306cSNickeau    {
44304fd306cSNickeau        $this->outlineHeadingId = $id;
44404fd306cSNickeau        return $this;
44504fd306cSNickeau    }
44604fd306cSNickeau
44704fd306cSNickeau    /**
44804fd306cSNickeau     * @return string|null
44904fd306cSNickeau     */
45004fd306cSNickeau    private function getHeadingId(): ?string
45104fd306cSNickeau    {
45204fd306cSNickeau        return $this->outlineHeadingId;
45304fd306cSNickeau    }
45404fd306cSNickeau
45504fd306cSNickeau    private function getSectionId(): ?int
45604fd306cSNickeau    {
45704fd306cSNickeau        return $this->outlineSectionId;
45804fd306cSNickeau    }
45904fd306cSNickeau
46004fd306cSNickeau    public function setOutlineSectionId(int $sectionSequenceId): EditButton
46104fd306cSNickeau    {
46204fd306cSNickeau        $this->outlineSectionId = $sectionSequenceId;
46304fd306cSNickeau        return $this;
46404fd306cSNickeau    }
46504fd306cSNickeau
46604fd306cSNickeau}
467