]> BookStack Code Mirror - bookstack/blob - app/References/CrossLinkParser.php
Comments: Added HTML filter on load, tinymce elem filtering
[bookstack] / app / References / CrossLinkParser.php
1 <?php
2
3 namespace BookStack\References;
4
5 use BookStack\App\Model;
6 use BookStack\References\ModelResolvers\BookLinkModelResolver;
7 use BookStack\References\ModelResolvers\BookshelfLinkModelResolver;
8 use BookStack\References\ModelResolvers\ChapterLinkModelResolver;
9 use BookStack\References\ModelResolvers\CrossLinkModelResolver;
10 use BookStack\References\ModelResolvers\PageLinkModelResolver;
11 use BookStack\References\ModelResolvers\PagePermalinkModelResolver;
12 use BookStack\Util\HtmlDocument;
13
14 class CrossLinkParser
15 {
16     /**
17      * @var CrossLinkModelResolver[]
18      */
19     protected array $modelResolvers;
20
21     public function __construct(array $modelResolvers)
22     {
23         $this->modelResolvers = $modelResolvers;
24     }
25
26     /**
27      * Extract any found models within the given HTML content.
28      *
29      * @return Model[]
30      */
31     public function extractLinkedModels(string $html): array
32     {
33         $models = [];
34
35         $links = $this->getLinksFromContent($html);
36
37         foreach ($links as $link) {
38             $model = $this->linkToModel($link);
39             if (!is_null($model)) {
40                 $models[get_class($model) . ':' . $model->id] = $model;
41             }
42         }
43
44         return array_values($models);
45     }
46
47     /**
48      * Get a list of href values from the given document.
49      *
50      * @returns string[]
51      */
52     protected function getLinksFromContent(string $html): array
53     {
54         $links = [];
55
56         $doc = new HtmlDocument($html);
57         $anchors = $doc->queryXPath('//a[@href]');
58
59         /** @var \DOMElement $anchor */
60         foreach ($anchors as $anchor) {
61             $links[] = $anchor->getAttribute('href');
62         }
63
64         return $links;
65     }
66
67     /**
68      * Attempt to resolve the given link to a model using the instance model resolvers.
69      */
70     protected function linkToModel(string $link): ?Model
71     {
72         foreach ($this->modelResolvers as $resolver) {
73             $model = $resolver->resolve($link);
74             if (!is_null($model)) {
75                 return $model;
76             }
77         }
78
79         return null;
80     }
81
82     /**
83      * Create a new instance with a pre-defined set of model resolvers, specifically for the
84      * default set of entities within BookStack.
85      */
86     public static function createWithEntityResolvers(): self
87     {
88         return new self([
89             new PagePermalinkModelResolver(),
90             new PageLinkModelResolver(),
91             new ChapterLinkModelResolver(),
92             new BookLinkModelResolver(),
93             new BookshelfLinkModelResolver(),
94         ]);
95     }
96 }