3 namespace BookStack\Exports;
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;
13 class ZipReferenceParser
16 * @var CrossLinkModelResolver[]
18 protected array $modelResolvers;
20 public function __construct(EntityQueries $queries)
22 $this->modelResolvers = [
23 new PagePermalinkModelResolver($queries->pages),
24 new PageLinkModelResolver($queries->pages),
25 new ChapterLinkModelResolver($queries->chapters),
26 new BookLinkModelResolver($queries->books),
33 * Parse and replace references in the given content.
34 * @param callable(Model):(string|null) $handler
36 public function parse(string $content, callable $handler): string
38 $escapedBase = preg_quote(url('/'), '/');
39 $linkRegex = "/({$escapedBase}.*?)[\\t\\n\\f>\"'=?#]/";
41 preg_match_all($linkRegex, $content, $matches);
43 if (count($matches) < 2) {
47 foreach ($matches[1] as $link) {
48 $model = $this->linkToModel($link);
50 $result = $handler($model);
51 if ($result !== null) {
52 $content = str_replace($link, $result, $content);
62 * Attempt to resolve the given link to a model using the instance model resolvers.
64 protected function linkToModel(string $link): ?Model
66 foreach ($this->modelResolvers as $resolver) {
67 $model = $resolver->resolve($link);
68 if (!is_null($model)) {