]> BookStack Code Mirror - bookstack/blob - app/Exports/ZipReferenceParser.php
ZIP Export: Started building link/ref handling
[bookstack] / app / Exports / ZipReferenceParser.php
1 <?php
2
3 namespace BookStack\Exports;
4
5 use BookStack\App\Model;
6 use BookStack\Entities\Queries\EntityQueries;
7 use BookStack\References\ModelResolvers\BookLinkModelResolver;
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
13 class ZipReferenceParser
14 {
15     /**
16      * @var CrossLinkModelResolver[]
17      */
18     protected array $modelResolvers;
19
20     public function __construct(EntityQueries $queries)
21     {
22         $this->modelResolvers = [
23             new PagePermalinkModelResolver($queries->pages),
24             new PageLinkModelResolver($queries->pages),
25             new ChapterLinkModelResolver($queries->chapters),
26             new BookLinkModelResolver($queries->books),
27             // TODO - Image
28             // TODO - Attachment
29         ];
30     }
31
32     /**
33      * Parse and replace references in the given content.
34      * @param callable(Model):(string|null) $handler
35      */
36     public function parse(string $content, callable $handler): string
37     {
38         $escapedBase = preg_quote(url('/'), '/');
39         $linkRegex = "/({$escapedBase}.*?)[\\t\\n\\f>\"'=?#]/";
40         $matches = [];
41         preg_match_all($linkRegex, $content, $matches);
42
43         if (count($matches) < 2) {
44             return $content;
45         }
46
47         foreach ($matches[1] as $link) {
48             $model = $this->linkToModel($link);
49             if ($model) {
50                 $result = $handler($model);
51                 if ($result !== null) {
52                     $content = str_replace($link, $result, $content);
53                 }
54             }
55         }
56
57         return $content;
58     }
59
60
61     /**
62      * Attempt to resolve the given link to a model using the instance model resolvers.
63      */
64     protected function linkToModel(string $link): ?Model
65     {
66         foreach ($this->modelResolvers as $resolver) {
67             $model = $resolver->resolve($link);
68             if (!is_null($model)) {
69                 return $model;
70             }
71         }
72
73         return null;
74     }
75 }