xref: /webtrees/app/CommonMark/XrefParser.php (revision 56d475424b46df195a76f2a149ee5a07327497e8)
10a016d04SGreg Roach<?php
23976b470SGreg Roach
30a016d04SGreg Roach/**
40a016d04SGreg Roach * webtrees: online genealogy
589f7189bSGreg Roach * Copyright (C) 2021 webtrees development team
60a016d04SGreg Roach * This program is free software: you can redistribute it and/or modify
70a016d04SGreg Roach * it under the terms of the GNU General Public License as published by
80a016d04SGreg Roach * the Free Software Foundation, either version 3 of the License, or
90a016d04SGreg Roach * (at your option) any later version.
100a016d04SGreg Roach * This program is distributed in the hope that it will be useful,
110a016d04SGreg Roach * but WITHOUT ANY WARRANTY; without even the implied warranty of
120a016d04SGreg Roach * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
130a016d04SGreg Roach * GNU General Public License for more details.
140a016d04SGreg Roach * You should have received a copy of the GNU General Public License
1589f7189bSGreg Roach * along with this program. If not, see <https://www.gnu.org/licenses/>.
160a016d04SGreg Roach */
17fcfa147eSGreg Roach
18e7f56f2aSGreg Roachdeclare(strict_types=1);
19e7f56f2aSGreg Roach
200a016d04SGreg Roachnamespace Fisharebest\Webtrees\CommonMark;
210a016d04SGreg Roach
228d0ebef0SGreg Roachuse Fisharebest\Webtrees\Gedcom;
230a016d04SGreg Roachuse Fisharebest\Webtrees\GedcomRecord;
246b9cb339SGreg Roachuse Fisharebest\Webtrees\Registry;
250a016d04SGreg Roachuse Fisharebest\Webtrees\Tree;
264a1f1d43SGreg Roachuse League\CommonMark\Inline\Parser\InlineParserInterface;
270a016d04SGreg Roachuse League\CommonMark\InlineParserContext;
280a016d04SGreg Roach
29eec99f1aSGreg Roachuse function is_string;
30eec99f1aSGreg Roachuse function trim;
31eec99f1aSGreg Roach
320a016d04SGreg Roach/**
330a016d04SGreg Roach * Convert XREFs within markdown text to links
340a016d04SGreg Roach */
354a1f1d43SGreg Roachclass XrefParser implements InlineParserInterface
36c1010edaSGreg Roach{
370a016d04SGreg Roach    /** @var Tree - match XREFs in this tree */
380a016d04SGreg Roach    private $tree;
390a016d04SGreg Roach
400a016d04SGreg Roach    /**
410a016d04SGreg Roach     * MarkdownXrefParser constructor.
420a016d04SGreg Roach     *
430a016d04SGreg Roach     * @param Tree $tree
440a016d04SGreg Roach     */
45c1010edaSGreg Roach    public function __construct(Tree $tree)
46c1010edaSGreg Roach    {
470a016d04SGreg Roach        $this->tree = $tree;
480a016d04SGreg Roach    }
490a016d04SGreg Roach
500a016d04SGreg Roach    /**
510a016d04SGreg Roach     * We are only interested in text that begins with '@'.
520a016d04SGreg Roach     *
5324f2a3afSGreg Roach     * @return array<string>
540a016d04SGreg Roach     */
558f53f488SRico Sonntag    public function getCharacters(): array
56c1010edaSGreg Roach    {
570a016d04SGreg Roach        return ['@'];
580a016d04SGreg Roach    }
590a016d04SGreg Roach
600a016d04SGreg Roach    /**
61*56d47542SGreg Roach     * @param InlineParserContext $inlineContext
620a016d04SGreg Roach     *
630a016d04SGreg Roach     * @return bool
640a016d04SGreg Roach     */
65*56d47542SGreg Roach    public function parse(InlineParserContext $inlineContext): bool
66c1010edaSGreg Roach    {
670a016d04SGreg Roach        // The cursor should be positioned on the opening '@'.
68*56d47542SGreg Roach        $cursor = $inlineContext->getCursor();
690a016d04SGreg Roach
70eec99f1aSGreg Roach        // If this isn't the start of an XREF, we'll need to rewind to here.
710a016d04SGreg Roach        $previous_state = $cursor->saveState();
720a016d04SGreg Roach
73eec99f1aSGreg Roach        $xref = $cursor->match('/@' . Gedcom::REGEX_XREF . '@/');
740a016d04SGreg Roach
75eec99f1aSGreg Roach        if (is_string($xref)) {
76eec99f1aSGreg Roach            $xref   = trim($xref, '@');
776b9cb339SGreg Roach            $record = Registry::gedcomRecordFactory()->make($xref, $this->tree);
780a016d04SGreg Roach
79eec99f1aSGreg Roach            if ($record instanceof GedcomRecord) {
80*56d47542SGreg Roach                $inlineContext->getContainer()->appendChild(new XrefNode($record));
81eec99f1aSGreg Roach
82eec99f1aSGreg Roach                return true;
83eec99f1aSGreg Roach            }
84eec99f1aSGreg Roach        }
85eec99f1aSGreg Roach
86eec99f1aSGreg Roach        // Not an XREF? Linked record does not exist?
870a016d04SGreg Roach        $cursor->restoreState($previous_state);
880a016d04SGreg Roach
890a016d04SGreg Roach        return false;
900a016d04SGreg Roach    }
910a016d04SGreg Roach}
92