xref: /dokuwiki/inc/Parsing/ParserMode/Footnote.php (revision 47a02a102092be9e1e6f1ddaf158bdfffdb13d4f)
1be906b56SAndreas Gohr<?php
2be906b56SAndreas Gohr
3be906b56SAndreas Gohrnamespace dokuwiki\Parsing\ParserMode;
4be906b56SAndreas Gohr
571096e46SAndreas Gohruse dokuwiki\Parsing\Handler;
671096e46SAndreas Gohruse dokuwiki\Parsing\Handler\Nest;
7c8dd1b9dSAndreas Gohruse dokuwiki\Parsing\ModeRegistry;
8c8dd1b9dSAndreas Gohr
9be906b56SAndreas Gohrclass Footnote extends AbstractMode
10be906b56SAndreas Gohr{
11*47a02a10SAndreas Gohr    /** @inheritdoc */
12*47a02a10SAndreas Gohr    protected function allowedCategories(): array
13be906b56SAndreas Gohr    {
14*47a02a10SAndreas Gohr        return [
15c8dd1b9dSAndreas Gohr            ModeRegistry::CATEGORY_CONTAINER,
16c8dd1b9dSAndreas Gohr            ModeRegistry::CATEGORY_FORMATTING,
1756c730b5SAndreas Gohr            ModeRegistry::CATEGORY_SUBSTITUTION,
18c8dd1b9dSAndreas Gohr            ModeRegistry::CATEGORY_PROTECTED,
19c8dd1b9dSAndreas Gohr            ModeRegistry::CATEGORY_DISABLED,
20*47a02a10SAndreas Gohr        ];
21*47a02a10SAndreas Gohr    }
22be906b56SAndreas Gohr
23*47a02a10SAndreas Gohr    /**
24*47a02a10SAndreas Gohr     * Footnotes cannot nest, so footnote is excluded from its own content.
25*47a02a10SAndreas Gohr     *
26*47a02a10SAndreas Gohr     * @inheritdoc
27*47a02a10SAndreas Gohr     */
28*47a02a10SAndreas Gohr    protected function filterAllowedModes(array $modes): array
29*47a02a10SAndreas Gohr    {
30*47a02a10SAndreas Gohr        return array_values(array_filter($modes, static fn($m) => $m !== 'footnote'));
31be906b56SAndreas Gohr    }
32be906b56SAndreas Gohr
33be906b56SAndreas Gohr    /** @inheritdoc */
3471096e46SAndreas Gohr    public function getSort()
3571096e46SAndreas Gohr    {
3671096e46SAndreas Gohr        return 150;
3771096e46SAndreas Gohr    }
3871096e46SAndreas Gohr
3971096e46SAndreas Gohr    /** @inheritdoc */
40be906b56SAndreas Gohr    public function connectTo($mode)
41be906b56SAndreas Gohr    {
42be906b56SAndreas Gohr        $this->Lexer->addEntryPattern(
43be906b56SAndreas Gohr            '\x28\x28(?=.*\x29\x29)',
44be906b56SAndreas Gohr            $mode,
45be906b56SAndreas Gohr            'footnote'
46be906b56SAndreas Gohr        );
47be906b56SAndreas Gohr    }
48be906b56SAndreas Gohr
49be906b56SAndreas Gohr    /** @inheritdoc */
50be906b56SAndreas Gohr    public function postConnect()
51be906b56SAndreas Gohr    {
52be906b56SAndreas Gohr        $this->Lexer->addExitPattern(
53be906b56SAndreas Gohr            '\x29\x29',
54be906b56SAndreas Gohr            'footnote'
55be906b56SAndreas Gohr        );
56be906b56SAndreas Gohr    }
57be906b56SAndreas Gohr
58be906b56SAndreas Gohr    /** @inheritdoc */
5971096e46SAndreas Gohr    public function handle($match, $state, $pos, Handler $handler)
60be906b56SAndreas Gohr    {
6171096e46SAndreas Gohr        switch ($state) {
6271096e46SAndreas Gohr            case DOKU_LEXER_ENTER:
6371096e46SAndreas Gohr                // footnotes can not be nested - however due to limitations in lexer it can't be prevented
6471096e46SAndreas Gohr                // we will still enter a new footnote mode, we just do nothing
6571096e46SAndreas Gohr                if ($handler->getStatus('footnote')) {
6671096e46SAndreas Gohr                    $handler->addCall('cdata', [$match], $pos);
6771096e46SAndreas Gohr                    break;
6871096e46SAndreas Gohr                }
6971096e46SAndreas Gohr                $handler->setStatus('footnote', true);
7071096e46SAndreas Gohr
7171096e46SAndreas Gohr                $handler->setCallWriter(new Nest($handler->getCallWriter(), 'footnote_close'));
7271096e46SAndreas Gohr                $handler->addCall('footnote_open', [], $pos);
7371096e46SAndreas Gohr                break;
7471096e46SAndreas Gohr            case DOKU_LEXER_EXIT:
7571096e46SAndreas Gohr                // check whether we have already exited the footnote mode, can happen if the modes were nested
7671096e46SAndreas Gohr                if (!$handler->getStatus('footnote')) {
7771096e46SAndreas Gohr                    $handler->addCall('cdata', [$match], $pos);
7871096e46SAndreas Gohr                    break;
7971096e46SAndreas Gohr                }
8071096e46SAndreas Gohr
8171096e46SAndreas Gohr                $handler->setStatus('footnote', false);
8271096e46SAndreas Gohr                $handler->addCall('footnote_close', [], $pos);
8371096e46SAndreas Gohr
8471096e46SAndreas Gohr                /** @var Nest $reWriter */
8571096e46SAndreas Gohr                $reWriter = $handler->getCallWriter();
8671096e46SAndreas Gohr                $handler->setCallWriter($reWriter->process());
8771096e46SAndreas Gohr                break;
8871096e46SAndreas Gohr            case DOKU_LEXER_UNMATCHED:
8971096e46SAndreas Gohr                $handler->addCall('cdata', [$match], $pos);
9071096e46SAndreas Gohr                break;
9171096e46SAndreas Gohr        }
9271096e46SAndreas Gohr        return true;
93be906b56SAndreas Gohr    }
94be906b56SAndreas Gohr}
95