Issues (40)

src/Node/Node.php (1 issue)

Severity
1
<?php
2
3
declare(strict_types=1);
4
5
namespace DH\Adf\Node;
6
7
use DH\Adf\Node\Block\Blockquote;
8
use DH\Adf\Node\Block\BulletList;
9
use DH\Adf\Node\Block\CodeBlock;
10
use DH\Adf\Node\Block\Document;
11
use DH\Adf\Node\Block\Expand;
12
use DH\Adf\Node\Block\Heading;
13
use DH\Adf\Node\Block\MediaGroup;
14
use DH\Adf\Node\Block\MediaSingle;
15
use DH\Adf\Node\Block\OrderedList;
16
use DH\Adf\Node\Block\Panel;
17
use DH\Adf\Node\Block\Paragraph;
18
use DH\Adf\Node\Block\Rule;
19
use DH\Adf\Node\Block\Table;
20
use DH\Adf\Node\Block\TaskList;
21
use DH\Adf\Node\Child\ListItem;
22
use DH\Adf\Node\Child\Media;
23
use DH\Adf\Node\Child\TableCell;
24
use DH\Adf\Node\Child\TableHeader;
25
use DH\Adf\Node\Child\TableRow;
26
use DH\Adf\Node\Child\TaskItem;
27
use DH\Adf\Node\Inline\Date;
28
use DH\Adf\Node\Inline\Emoji;
29
use DH\Adf\Node\Inline\Hardbreak;
30
use DH\Adf\Node\Inline\InlineCard;
31
use DH\Adf\Node\Inline\Mention;
32
use DH\Adf\Node\Inline\Status;
33
use DH\Adf\Node\Inline\Text;
34
use DH\Adf\Node\Mark\Code;
35
use DH\Adf\Node\Mark\Em;
36
use DH\Adf\Node\Mark\Link;
37
use DH\Adf\Node\Mark\Strike;
38
use DH\Adf\Node\Mark\Strong;
39
use DH\Adf\Node\Mark\Subsup;
40
use DH\Adf\Node\Mark\TextColor;
41
use DH\Adf\Node\Mark\Underline;
42
use InvalidArgumentException;
43
use JsonSerializable;
44
45
/**
46
 * @see https://unpkg.com/@atlaskit/[email protected]/dist/json-schema/v1/full.json
47
 */
48
abstract class Node implements JsonSerializable
49
{
50
    public const NODE_MAPPING = [
51
        // block nodes
52
        'doc' => Document::class,
53
        'blockquote' => Blockquote::class,
54
        'bulletList' => BulletList::class,
55
        'taskList' => TaskList::class,
56
        'codeBlock' => CodeBlock::class,
57
        'heading' => Heading::class,
58
        'mediaGroup' => MediaGroup::class,
59
        'mediaSingle' => MediaSingle::class,
60
        'orderedList' => OrderedList::class,
61
        'panel' => Panel::class,
62
        'paragraph' => Paragraph::class,
63
        'rule' => Rule::class,
64
        'table' => Table::class,
65
        'expand' => Expand::class,
66
67
        // child nodes
68
        'listItem' => ListItem::class,
69
        'taskItem' => TaskItem::class,
70
        'tableCell' => TableCell::class,
71
        'tableHeader' => TableHeader::class,
72
        'tableRow' => TableRow::class,
73
        'media' => Media::class,
74
        'inlineCard' => InlineCard::class,
75
76
        // inline nodes
77
        'emoji' => Emoji::class,
78
        'hardBreak' => Hardbreak::class,
79
        'mention' => Mention::class,
80
        'text' => Text::class,
81
        'status' => Status::class,
82
        'date' => Date::class,
83
84
        // mark nodes
85
        'em' => Em::class,
86
        'strong' => Strong::class,
87
        'code' => Code::class,
88
        'strike' => Strike::class,
89
        'subsup' => Subsup::class,
90
        'underline' => Underline::class,
91
        'link' => Link::class,
92
        'textColor' => TextColor::class,
93
    ];
94
95
    protected string $type;
96
    protected ?Node $parent;
97
98
    public function __construct(?self $parent = null)
99
    {
100
        $this->parent = $parent;
101
    }
102
103
    public function end(): ?self
104
    {
105
        return $this->parent;
106
    }
107
108
    public function toJson(): string
109
    {
110
        return json_encode($this, JSON_THROW_ON_ERROR);
111
    }
112
113
    public function jsonSerialize(): array
114
    {
115
        $result = [
116
            'type' => $this->type,
117
        ];
118
119
        $attrs = $this->attrs();
120
        if (\count($attrs) > 0) {
121
            $result['attrs'] = $attrs;
122
        }
123
124
        return $result;
125
    }
126
127
    public static function load(array $data): self
128
    {
129
        self::checkNodeData(static::class, $data);
130
131
        if (static::class !== self::NODE_MAPPING[$data['type']]) {
132
            throw new InvalidArgumentException(\sprintf('Invalid data for "%s" node type', $data['type']));
133
        }
134
135
        $class = self::NODE_MAPPING[$data['type']];
136
        $node = new $class();
137
138
        // set attributes if defined
139
        if (\array_key_exists('attrs', $data)) {
140
            foreach ($data['attrs'] as $key => $value) {
141
                $node->{$key} = $value;
142
            }
143
        }
144
145
        return $node;
146
    }
147
148
    public function getType(): string
149
    {
150
        return $this->type;
151
    }
152
153
    protected function attrs(): array
154
    {
155
        return [];
156
    }
157
158
    protected static function checkRequiredKeys(array $keys, array $data): void
159
    {
160
        foreach ($keys as $key) {
161
            if (!\array_key_exists($key, $data)) {
162
                throw new InvalidArgumentException(\sprintf('Missing "%s" key in node data.', $key));
163
            }
164
        }
165
    }
166
167
    protected static function checkNodeData(string $class, array $data, array $keys = []): void
0 ignored issues
show
The parameter $class is not used and could be removed. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unused  annotation

167
    protected static function checkNodeData(/** @scrutinizer ignore-unused */ string $class, array $data, array $keys = []): void

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
168
    {
169
        self::checkRequiredKeys(array_merge(['type'], $keys), $data);
170
171
        if (static::class !== self::NODE_MAPPING[$data['type']]) {
172
            throw new InvalidArgumentException(\sprintf('Invalid data for "%s" node type', $data['type']));
173
        }
174
    }
175
}
176