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        'blockquote' => QuoteNode::class,
20        'image' => ImageNode::class,
21        'hard_break' => HardBreakNode::class,
22        'horizontal_rule' => HruleNode::class,
23        'footnote' => FootnoteNode::class,
24        'smiley' => SmileyNode::class,
25        'table' => TableNode::class,
26        'table_row' => TableRowNode::class,
27        'table_cell' => TableCellNode::class,
28        'table_header' => TableCellNode::class,
29        'rss' => RSSNode::class,
30        'dwplugin_inline' => PluginNode::class,
31        'dwplugin_block' => PluginNode::class,
32    ];
33
34    private static $linkClasses = [
35        'interwikilink' => InterwikiLinkNode::class,
36        'internallink' => InternalLinkNode::class,
37        'emaillink' => EmailLinkNode::class,
38        'externallink' => ExternalLinkNode::class,
39        'windowssharelink' => WindowsShareLinkNode::class,
40        'other' => ExternalLinkNode::class,
41    ];
42
43    /**
44     * Get a Node instance of the correct type
45     *
46     * @param array     $node
47     * @param Node      $parent
48     * @param Node|null $previous
49     *
50     * @return Node
51     */
52    public static function getSubNode($node, Node $parent, Node $previous = null)
53    {
54        try {
55            if ($node['type'] === 'link') {
56                $linkType = $node['attrs']['data-type'];
57                return new self::$linkClasses[$linkType]($node, $parent, $previous);
58            }
59
60            if (isset(self::$nodeclass[$node['type']])) {
61                return new self::$nodeclass[$node['type']]($node, $parent, $previous);
62            }
63            $eventData = [
64                'node' => $node,
65                'parent' => $parent,
66                'previous' => $previous,
67                'newNode' => null,
68            ];
69            $event = new \Doku_Event('PROSEMIRROR_PARSE_UNKNOWN', $eventData);
70            if ($event->advise_before() || !is_a($eventData['newNode'], __CLASS__)) {
71                $exception = new ProsemirrorException('Invalid node type received: ' . $node['type'], 0);
72                $exception->addExtraData('nodeData', $node);
73                $exception->addExtraData('parentNodeType', get_class($parent));
74
75                throw $exception;
76            }
77            return $eventData['newNode'];
78
79        } catch (\Error $e) {
80            $exception = new ProsemirrorException('FIXME: better message for general error! Invalid node type received: ' . $node['type'], 0, $e);
81            $exception->addExtraData('nodeData', $node);
82            $exception->addExtraData('parentNodeType', get_class($parent));
83
84            throw $exception;
85        }
86    }
87
88    /**
89     * Get the node's representation as DokuWiki Syntax
90     *
91     * @return string
92     */
93    abstract public function toSyntax();
94}
95