3 namespace BookStack\References;
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;
17 * @var CrossLinkModelResolver[]
19 protected array $modelResolvers;
21 public function __construct(array $modelResolvers)
23 $this->modelResolvers = $modelResolvers;
27 * Extract any found models within the given HTML content.
31 public function extractLinkedModels(string $html): array
35 $links = $this->getLinksFromContent($html);
37 foreach ($links as $link) {
38 $model = $this->linkToModel($link);
39 if (!is_null($model)) {
40 $models[get_class($model) . ':' . $model->id] = $model;
44 return array_values($models);
48 * Get a list of href values from the given document.
52 protected function getLinksFromContent(string $html): array
56 $doc = new HtmlDocument($html);
57 $anchors = $doc->queryXPath('//a[@href]');
59 /** @var \DOMElement $anchor */
60 foreach ($anchors as $anchor) {
61 $links[] = $anchor->getAttribute('href');
68 * Attempt to resolve the given link to a model using the instance model resolvers.
70 protected function linkToModel(string $link): ?Model
72 foreach ($this->modelResolvers as $resolver) {
73 $model = $resolver->resolve($link);
74 if (!is_null($model)) {
83 * Create a new instance with a pre-defined set of model resolvers, specifically for the
84 * default set of entities within BookStack.
86 public static function createWithEntityResolvers(): self
89 new PagePermalinkModelResolver(),
90 new PageLinkModelResolver(),
91 new ChapterLinkModelResolver(),
92 new BookLinkModelResolver(),
93 new BookshelfLinkModelResolver(),