Passed
Push — main ( e16d46...16e3d2 )
by Damien
07:21
created

Node   A

Complexity

Total Complexity 15

Size/Duplication

Total Lines 118
Duplicated Lines 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
wmc 15
eloc 62
dl 0
loc 118
c 1
b 0
f 0
rs 10

8 Methods

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

158
    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...
159
    {
160
        self::checkRequiredKeys(array_merge(['type'], $keys), $data);
161
162
        if (static::class !== self::NODE_MAPPING[$data['type']]) {
163
            throw new InvalidArgumentException(sprintf('Invalid data for "%s" node type', $data['type']));
164
        }
165
    }
166
}
167