3 namespace BookStack\Exports;
5 use BookStack\App\Model;
6 use BookStack\Entities\Queries\EntityQueries;
7 use BookStack\References\ModelResolvers\AttachmentModelResolver;
8 use BookStack\References\ModelResolvers\BookLinkModelResolver;
9 use BookStack\References\ModelResolvers\ChapterLinkModelResolver;
10 use BookStack\References\ModelResolvers\CrossLinkModelResolver;
11 use BookStack\References\ModelResolvers\ImageModelResolver;
12 use BookStack\References\ModelResolvers\PageLinkModelResolver;
13 use BookStack\References\ModelResolvers\PagePermalinkModelResolver;
15 class ZipReferenceParser
18 * @var CrossLinkModelResolver[]
20 protected array $modelResolvers;
22 public function __construct(EntityQueries $queries)
24 $this->modelResolvers = [
25 new PagePermalinkModelResolver($queries->pages),
26 new PageLinkModelResolver($queries->pages),
27 new ChapterLinkModelResolver($queries->chapters),
28 new BookLinkModelResolver($queries->books),
29 new ImageModelResolver(),
30 new AttachmentModelResolver(),
35 * Parse and replace references in the given content.
36 * @param callable(Model):(string|null) $handler
38 public function parse(string $content, callable $handler): string
40 $escapedBase = preg_quote(url('/'), '/');
41 $linkRegex = "/({$escapedBase}.*?)[\\t\\n\\f>\"'=?#]/";
43 preg_match_all($linkRegex, $content, $matches);
45 if (count($matches) < 2) {
49 foreach ($matches[1] as $link) {
50 $model = $this->linkToModel($link);
52 $result = $handler($model);
53 if ($result !== null) {
54 $content = str_replace($link, $result, $content);
64 * Attempt to resolve the given link to a model using the instance model resolvers.
66 protected function linkToModel(string $link): ?Model
68 foreach ($this->modelResolvers as $resolver) {
69 $model = $resolver->resolve($link);
70 if (!is_null($model)) {