1<?php
2
3namespace dokuwiki\plugin\prosemirror\parser;
4
5use dokuwiki\plugin\prosemirror\ProsemirrorException;
6
7abstract class Node implements NodeInterface
8{
9
10    private static $nodeclass = [
11        'text' => TextNode::class,
12        'paragraph' => ParagraphNode::class,
13        'list_paragraph' => ParagraphNode::class,
14        'bullet_list' => ListNode::class,
15        'ordered_list' => ListNode::class,
16        'heading' => HeadingNode::class,
17        'preformatted' => PreformattedNode::class,
18        'code_block' => CodeBlockNode::class,
19        'html_inline' => HtmlPhpNode::class,
20        'html_block' => HtmlPhpNode::class,
21        'php_inline' => HtmlPhpNode::class,
22        'php_block' => HtmlPhpNode::class,
23        'blockquote' => QuoteNode::class,
24        'image' => ImageNode::class,
25        'hard_break' => HardBreakNode::class,
26        'horizontal_rule' => HruleNode::class,
27        'footnote' => FootnoteNode::class,
28        'smiley' => SmileyNode::class,
29        'table' => TableNode::class,
30        'table_row' => TableRowNode::class,
31        'table_cell' => TableCellNode::class,
32        'table_header' => TableCellNode::class,
33        'rss' => RSSNode::class,
34        'dwplugin_inline' => PluginNode::class,
35        'dwplugin_block' => PluginNode::class,
36    ];
37
38    private static $linkClasses = [
39        'interwikilink' => InterwikiLinkNode::class,
40        'internallink' => InternalLinkNode::class,
41        'emaillink' => EmailLinkNode::class,
42        'externallink' => ExternalLinkNode::class,
43        'windowssharelink' => WindowsShareLinkNode::class,
44        'other' => ExternalLinkNode::class,
45    ];
46
47    /**
48     * Get a Node instance of the correct type
49     *
50     * @param array     $node
51     * @param Node      $parent
52     * @param Node|null $previous
53     *
54     * @return Node
55     */
56    public static function getSubNode($node, Node $parent, Node $previous = null)
57    {
58        try {
59            if ($node['type'] === 'link') {
60                $linkType = $node['attrs']['data-type'];
61                return new self::$linkClasses[$linkType]($node, $parent, $previous);
62            }
63
64            if (isset(self::$nodeclass[$node['type']])) {
65                return new self::$nodeclass[$node['type']]($node, $parent, $previous);
66            }
67            $eventData = [
68                'node' => $node,
69                'parent' => $parent,
70                'previous' => $previous,
71                'newNode' => null,
72            ];
73            $event = new \Doku_Event('PROSEMIRROR_PARSE_UNKNOWN', $eventData);
74            if ($event->advise_before() || !is_a($eventData['newNode'], __CLASS__)) {
75                $exception = new ProsemirrorException('Invalid node type received: ' . $node['type'], 0);
76                $exception->addExtraData('nodeData', $node);
77                $exception->addExtraData('parentNodeType', get_class($parent));
78
79                throw $exception;
80            }
81            return $eventData['newNode'];
82
83        } catch (\Error $e) {
84            $exception = new ProsemirrorException('FIXME: better message for general error! Invalid node type received: ' . $node['type'], 0, $e);
85            $exception->addExtraData('nodeData', $node);
86            $exception->addExtraData('parentNodeType', get_class($parent));
87
88            throw $exception;
89        }
90    }
91
92    /**
93     * Get the node's representation as DokuWiki Syntax
94     *
95     * @return string
96     */
97    abstract public function toSyntax();
98}
99