1<?php
2
3namespace dokuwiki\plugin\prosemirror\parser;
4
5use dokuwiki\plugin\prosemirror\schema\Mark;
6use dokuwiki\File\MediaResolver;
7
8abstract class LinkNode extends Node implements InlineNodeInterface
9{
10    /** @var  InlineNodeInterface */
11    public $previous;
12
13    /** @var  Node */
14    protected $parent;
15
16    /** @var TextNode */
17    protected $textNode;
18
19    protected $attrs = [];
20
21    public function __construct($data, Node $parent, Node $previousNode = null)
22    {
23        $this->parent = &$parent;
24        if ($previousNode !== false) {
25            $this->previous = &$previousNode;
26        }
27
28        $this->attrs = $data['attrs'];
29
30        // every inline node needs a TextNode to track marks
31        $this->textNode = new TextNode(['marks' => $data['marks'] ?? null], $parent, $previousNode);
32    }
33
34
35    /**
36     * @param string $markType
37     */
38    public function increaseMark($markType)
39    {
40        return $this->textNode->increaseMark($markType);
41    }
42
43    public function getStartingNodeMarkScore($markType)
44    {
45        return $this->textNode->getStartingNodeMarkScore($markType);
46    }
47
48    protected function getDefaultLinkSyntax($inner)
49    {
50        $title = '';
51        $prefix = $this->textNode->getPrefixSyntax();
52        $postfix = $this->textNode->getPostfixSyntax();
53
54        if (!empty($this->attrs['data-name'])) {
55            $title = '|' . $this->attrs['data-name'];
56        } elseif (!empty($this->attrs['image-id'])) {
57            $imageAttrs = [];
58            foreach ($this->attrs as $key => $value) {
59                @[$keyPrefix, $attrKey] = explode('-', $key, 2);
60                if ($keyPrefix === 'image') {
61                    $imageAttrs[$attrKey] = $value;
62                }
63            }
64            $imageNode = new ImageNode([
65                'attrs' => $imageAttrs,
66                'marks' => [],
67            ], $this);
68            $title = '|' . $imageNode->toSyntax();
69        }
70
71        return $prefix . '[[' . $inner . $title . ']]' . $postfix;
72    }
73
74    /**
75     * @param \renderer_plugin_prosemirror $renderer
76     * @param string                       $linktype
77     * @param string|array                 $name
78     * @param array                        $additionalAttributes
79     */
80    protected static function renderToJSON(
81        \renderer_plugin_prosemirror $renderer,
82        $linktype,
83        $inner,
84        $name,
85        $additionalAttributes = []
86    ) {
87        global $ID;
88        $isImage = is_array($name);
89        $linkNode = new \dokuwiki\plugin\prosemirror\schema\Node('link');
90        $linkNode->attr('data-type', $linktype);
91        $linkNode->attr('data-inner', $inner);
92        if ($isImage) {
93            ImageNode::addAttributes(
94                $linkNode,
95                $name['src'],
96                $name['title'],
97                $name['align'],
98                $name['width'],
99                $name['height'],
100                $name['cache'],
101                null,
102                'image-'
103            );
104            $linkNode->attr('data-resolvedImage', self::resolveImageTitle(
105                $ID,
106                $name['src'],
107                $name['title'],
108                $name['align'],
109                $name['width'],
110                $name['height'],
111                $name['cache']
112            ));
113        } else {
114            $linkNode->attr('data-name', $name);
115        }
116        foreach ($additionalAttributes as $attributeName => $attributeValue) {
117            $linkNode->attr($attributeName, $attributeValue);
118        }
119        foreach (array_keys($renderer->getCurrentMarks()) as $mark) {
120            $linkNode->addMark(new Mark($mark));
121        }
122        $renderer->addToNodestack($linkNode);
123    }
124
125    public static function resolveImageTitle(
126        $pageId,
127        $imageId,
128        $title = null,
129        $align = null,
130        $width = null,
131        $height = null,
132        $cache = null
133    ) {
134        /** @var \Doku_Renderer_xhtml $xhtml_renderer */
135        $xhtml_renderer = p_get_renderer('xhtml');
136        $src = $imageId;
137        if (!media_isexternal($src)) {
138            $resolver = new MediaResolver(getNS($pageId));
139            $media = $resolver->resolveId($src);
140            if (!media_exists($media)) {
141                return '';
142            }
143        }
144        return $xhtml_renderer->_media(
145            $src,
146            $title ?: $imageId,
147            $align,
148            $width,
149            $height,
150            $cache
151        );
152    }
153}
154