xref: /webtrees/app/CommonMark/XrefParser.php (revision 054771e94ab58244acfab4da8ab0752d96fe7fb5)
1<?php
2
3/**
4 * webtrees: online genealogy
5 * Copyright (C) 2019 webtrees development team
6 * This program is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation, either version 3 of the License, or
9 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program. If not, see <http://www.gnu.org/licenses/>.
16 */
17
18declare(strict_types=1);
19
20namespace Fisharebest\Webtrees\CommonMark;
21
22use Fisharebest\Webtrees\Gedcom;
23use Fisharebest\Webtrees\GedcomRecord;
24use Fisharebest\Webtrees\Tree;
25use League\CommonMark\Inline\Parser\InlineParserInterface;
26use League\CommonMark\InlineParserContext;
27
28use function is_string;
29use function trim;
30
31/**
32 * Convert XREFs within markdown text to links
33 */
34class XrefParser implements InlineParserInterface
35{
36    /** @var Tree - match XREFs in this tree */
37    private $tree;
38
39    /**
40     * MarkdownXrefParser constructor.
41     *
42     * @param Tree $tree
43     */
44    public function __construct(Tree $tree)
45    {
46        $this->tree = $tree;
47    }
48
49    /**
50     * We are only interested in text that begins with '@'.
51     *
52     * @return string[]
53     */
54    public function getCharacters(): array
55    {
56        return ['@'];
57    }
58
59    /**
60     * @param InlineParserContext $context
61     *
62     * @return bool
63     */
64    public function parse(InlineParserContext $context): bool
65    {
66        // The cursor should be positioned on the opening '@'.
67        $cursor = $context->getCursor();
68
69        // If this isn't the start of an XREF, we'll need to rewind to here.
70        $previous_state = $cursor->saveState();
71
72        $xref = $cursor->match('/@' . Gedcom::REGEX_XREF . '@/');
73
74        if (is_string($xref)) {
75            $xref   = trim($xref, '@');
76            $record = GedcomRecord::getInstance($xref, $this->tree);
77
78            if ($record instanceof GedcomRecord) {
79                $context->getContainer()->appendChild(new XrefNode($record));
80
81                return true;
82            }
83        }
84
85        // Not an XREF? Linked record does not exist?
86        $cursor->restoreState($previous_state);
87
88        return false;
89    }
90}
91