Code Coverage |
||||||||||
Lines |
Functions and Methods |
Classes and Traits |
||||||||
Total | |
0.00% |
0 / 61 |
|
0.00% |
0 / 6 |
CRAP | |
0.00% |
0 / 1 |
DataMw | |
0.00% |
0 / 61 |
|
0.00% |
0 / 6 |
870 | |
0.00% |
0 / 1 |
__construct | |
0.00% |
0 / 3 |
|
0.00% |
0 / 1 |
12 | |||
isEmpty | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
__clone | |
0.00% |
0 / 14 |
|
0.00% |
0 / 1 |
132 | |||
jsonClassHintFor | |
0.00% |
0 / 11 |
|
0.00% |
0 / 1 |
6 | |||
toJsonArray | |
0.00% |
0 / 19 |
|
0.00% |
0 / 1 |
56 | |||
newFromJsonArray | |
0.00% |
0 / 13 |
|
0.00% |
0 / 1 |
30 |
1 | <?php |
2 | declare( strict_types = 1 ); |
3 | |
4 | namespace Wikimedia\Parsoid\NodeData; |
5 | |
6 | use stdClass; |
7 | use Wikimedia\JsonCodec\Hint; |
8 | use Wikimedia\JsonCodec\JsonCodecable; |
9 | use Wikimedia\JsonCodec\JsonCodecableTrait; |
10 | use Wikimedia\Parsoid\Tokens\SourceRange; |
11 | |
12 | /** |
13 | * Editing data for a DOM node. Managed by DOMDataUtils::get/setDataMw(). |
14 | * |
15 | * To reduce memory usage, most of the properties need to be dynamic, but |
16 | * we use the property declarations below to allow type checking. |
17 | * |
18 | * @property list<string|TemplateInfo> $parts |
19 | * @property string $name |
20 | * @property string $extPrefix |
21 | * @property string $extSuffix |
22 | * @property list<DataMwAttrib> $attribs Extended attributes of an HTML tag |
23 | * @property string $src |
24 | * @property string $caption |
25 | * @property string $thumb |
26 | * @property bool $autoGenerated |
27 | * @property list<DataMwError> $errors |
28 | * @property stdClass $body |
29 | * @property mixed $html |
30 | * @property float $scale |
31 | * @property string $starttime |
32 | * @property string $endtime |
33 | * @property string $thumbtime |
34 | * @property string $page |
35 | * == Annotations == |
36 | * @property string $rangeId |
37 | * @property SourceRange $wtOffsets |
38 | * @property bool $extendedRange |
39 | * @property stdClass $attrs Attributes for an extension tag or annotation (T367616 should be renamed) |
40 | */ |
41 | #[\AllowDynamicProperties] |
42 | class DataMw implements JsonCodecable { |
43 | use JsonCodecableTrait; |
44 | |
45 | public function __construct( array $initialVals = [] ) { |
46 | foreach ( $initialVals as $k => $v ) { |
47 | // @phan-suppress-next-line PhanNoopSwitchCases |
48 | switch ( $k ) { |
49 | // Add cases here for components which should be instantiated |
50 | // as proper classes. |
51 | default: |
52 | $this->$k = $v; |
53 | break; |
54 | } |
55 | } |
56 | } |
57 | |
58 | /** Returns true iff there are no dynamic properties of this object. */ |
59 | public function isEmpty(): bool { |
60 | return ( (array)$this ) === []; |
61 | } |
62 | |
63 | public function __clone() { |
64 | // Deep clone non-primitive properties |
65 | if ( isset( $this->parts ) ) { |
66 | foreach ( $this->parts as &$part ) { |
67 | if ( !is_string( $part ) ) { |
68 | $part = clone $part; |
69 | } |
70 | } |
71 | } |
72 | // Properties which are lists of cloneable objects |
73 | foreach ( [ 'attribs', 'errors' ] as $prop ) { |
74 | if ( isset( $this->$prop ) ) { |
75 | foreach ( $this->$prop as &$item ) { |
76 | $item = clone $item; |
77 | } |
78 | } |
79 | } |
80 | // Properties which are cloneable objects |
81 | foreach ( [ 'wtOffsets' ] as $prop ) { |
82 | if ( isset( $this->$prop ) ) { |
83 | $this->$prop = clone $this->$prop; |
84 | } |
85 | } |
86 | // Generic stdClass, use PHP serialization as a kludge |
87 | foreach ( [ 'body', 'attrs' ] as $prop ) { |
88 | if ( isset( $this->$prop ) ) { |
89 | $this->$prop = unserialize( serialize( $this->$prop ) ); |
90 | } |
91 | } |
92 | } |
93 | |
94 | /** @inheritDoc */ |
95 | public static function jsonClassHintFor( string $keyname ) { |
96 | static $hints = null; |
97 | if ( $hints === null ) { |
98 | $hints = [ |
99 | 'attribs' => Hint::build( DataMwAttrib::class, Hint::USE_SQUARE, Hint::LIST ), |
100 | // T367616: 'attrs' should be renamed to 'extAttrs' |
101 | 'attrs' => Hint::build( stdClass::class, Hint::ALLOW_OBJECT ), |
102 | 'body' => Hint::build( stdClass::class, Hint::ALLOW_OBJECT ), |
103 | 'wtOffsets' => Hint::build( SourceRange::class, Hint::USE_SQUARE ), |
104 | 'parts' => Hint::build( TemplateInfo::class, Hint::STDCLASS, Hint::LIST ), |
105 | 'errors' => Hint::build( DataMwError::class, Hint::LIST ), |
106 | ]; |
107 | } |
108 | return $hints[$keyname] ?? null; |
109 | } |
110 | |
111 | /** @inheritDoc */ |
112 | public function toJsonArray(): array { |
113 | $result = (array)$this; |
114 | // T367141: Third party clients (eg Cite) create arrays instead of |
115 | // error objects. We should convert them to proper DataMwError |
116 | // objects once those exist. |
117 | if ( isset( $result['errors'] ) ) { |
118 | $result['errors'] = array_map( |
119 | fn ( $e ) => is_array( $e ) ? DataMwError::newFromJsonArray( $e ) : |
120 | ( $e instanceof DataMwError ? $e : DataMwError::newFromJsonArray( (array)$e ) ), |
121 | $result['errors'] |
122 | ); |
123 | } |
124 | // Legacy encoding of parts. |
125 | if ( isset( $result['parts'] ) ) { |
126 | $result['parts'] = array_map( static function ( $p ) { |
127 | if ( $p instanceof TemplateInfo ) { |
128 | $type = $p->type ?? 'template'; |
129 | if ( $type === 'parserfunction' ) { |
130 | $type = 'template'; |
131 | } |
132 | $pp = (object)[]; |
133 | $pp->$type = $p; |
134 | return $pp; |
135 | } |
136 | return $p; |
137 | }, $result['parts'] ); |
138 | } |
139 | return $result; |
140 | } |
141 | |
142 | /** @inheritDoc */ |
143 | public static function newFromJsonArray( array $json ): DataMw { |
144 | // Decode legacy encoding of parts. |
145 | if ( isset( $json['parts'] ) ) { |
146 | $json['parts'] = array_map( static function ( $p ) { |
147 | if ( is_object( $p ) ) { |
148 | $type = 'template'; |
149 | if ( isset( $p->templatearg ) ) { |
150 | $type = 'templatearg'; |
151 | } |
152 | $p = $p->$type; |
153 | if ( isset( $p->func ) ) { |
154 | $type = 'parserfunction'; |
155 | } |
156 | $p->type = $type; |
157 | } |
158 | return $p; |
159 | }, $json['parts'] ); |
160 | } |
161 | return new DataMw( $json ); |
162 | } |
163 | } |