Code Coverage |
||||||||||
Lines |
Functions and Methods |
Classes and Traits |
||||||||
Total | |
0.00% |
0 / 65 |
|
0.00% |
0 / 4 |
CRAP | |
0.00% |
0 / 1 |
TemplateInfo | |
0.00% |
0 / 65 |
|
0.00% |
0 / 4 |
306 | |
0.00% |
0 / 1 |
__clone | |
0.00% |
0 / 2 |
|
0.00% |
0 / 1 |
6 | |||
newFromJsonArray | |
0.00% |
0 / 21 |
|
0.00% |
0 / 1 |
20 | |||
jsonClassHintFor | |
0.00% |
0 / 10 |
|
0.00% |
0 / 1 |
6 | |||
toJsonArray | |
0.00% |
0 / 32 |
|
0.00% |
0 / 1 |
90 |
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 | |
11 | class TemplateInfo implements JsonCodecable { |
12 | use JsonCodecableTrait; |
13 | |
14 | /** |
15 | * The target wikitext |
16 | */ |
17 | public ?string $targetWt = null; |
18 | |
19 | /** |
20 | * The parser function name |
21 | */ |
22 | public ?string $func = null; |
23 | |
24 | /** |
25 | * The URL of the target |
26 | */ |
27 | public ?string $href = null; |
28 | |
29 | /** |
30 | * Param infos indexed by key (ParamInfo->k) |
31 | * @var list<ParamInfo> |
32 | */ |
33 | public array $paramInfos = []; |
34 | |
35 | /** |
36 | * The type of template (template, templatearg, parserfunction). |
37 | * @note For backward-compatibility reasons, this property is |
38 | * not serialized/deserialized. |
39 | * @var 'template'|'templatearg'|'parserfunction'|null |
40 | */ |
41 | public ?string $type = null; |
42 | |
43 | /** |
44 | * The index into data-parsoid.pi |
45 | */ |
46 | public ?int $i = null; |
47 | |
48 | public function __clone() { |
49 | foreach ( $this->paramInfos as &$pi ) { |
50 | $pi = clone $pi; |
51 | } |
52 | } |
53 | |
54 | /** @inheritDoc */ |
55 | public static function newFromJsonArray( array $json ): TemplateInfo { |
56 | $ti = new TemplateInfo; |
57 | $ti->targetWt = $json['target']['wt'] ?? null; |
58 | $ti->href = $json['target']['href'] ?? null; |
59 | $ti->paramInfos = []; |
60 | $params = (array)( $json['params'] ?? null ); |
61 | |
62 | if ( isset( $json['target']['key'] ) ) { |
63 | $ti->func = $json['target']['key']; |
64 | $ti->targetWt .= ':' . $params['1']->wt; |
65 | // Downshift all params by 1 |
66 | $numKeys = count( $params ); |
67 | for ( $i = 1; $i < $numKeys; $i++ ) { |
68 | $params[(string)$i] = $params[(string)( $i + 1 )]; |
69 | } |
70 | unset( $params[(string)$numKeys] ); |
71 | } else { |
72 | $ti->func = $json['target']['function'] ?? null; |
73 | } |
74 | |
75 | foreach ( $params as $k => $v ) { |
76 | // Converting $params to an array can turn the keys into ints, |
77 | // so we need to explicitly cast them back to string. |
78 | $info = new ParamInfo( (string)$k ); |
79 | $info->valueWt = $v->wt ?? null; |
80 | $info->html = $v->html ?? null; |
81 | $info->keyWt = $v->key->wt ?? null; |
82 | $ti->paramInfos[] = $info; |
83 | } |
84 | $ti->i = $json['i'] ?? null; |
85 | return $ti; |
86 | } |
87 | |
88 | /** @inheritDoc */ |
89 | public static function jsonClassHintFor( string $keyname ) { |
90 | static $hints = null; |
91 | if ( $hints === null ) { |
92 | $hints = [ |
93 | // The most deeply nested stdClass structure is "wt" inside |
94 | // "key" inside a parameter: |
95 | // "params":{"1":{"key":{"wt":"..."}}} |
96 | 'params' => Hint::build( |
97 | stdClass::class, Hint::ALLOW_OBJECT, |
98 | Hint::STDCLASS, Hint::ALLOW_OBJECT, |
99 | Hint::STDCLASS, Hint::ALLOW_OBJECT |
100 | ), |
101 | ]; |
102 | } |
103 | return $hints[$keyname] ?? null; |
104 | } |
105 | |
106 | /** @inheritDoc */ |
107 | public function toJsonArray(): array { |
108 | // This is a complicated serialization, but necessary for |
109 | // backward compatibility with existing data-mw |
110 | |
111 | $v3PF = $this->type === 'v3parserfunction'; |
112 | $target = [ 'wt' => $this->targetWt ]; |
113 | if ( $this->func !== null ) { |
114 | $key = $v3PF ? 'key' : 'function'; |
115 | $target[$key] = $this->func; |
116 | } |
117 | if ( $this->href !== null ) { |
118 | $target['href'] = $this->href; |
119 | } |
120 | $params = []; |
121 | foreach ( $this->paramInfos as $info ) { |
122 | // Non-standard serialization of ParamInfo, alas. |
123 | $param = [ |
124 | 'wt' => $info->valueWt, |
125 | ]; |
126 | if ( $info->html !== null ) { |
127 | $param['html'] = $info->html; |
128 | } |
129 | if ( $info->keyWt !== null ) { |
130 | $param['key'] = (object)[ |
131 | 'wt' => $info->keyWt, |
132 | ]; |
133 | } |
134 | $params[$info->k] = (object)$param; |
135 | } |
136 | |
137 | if ( $v3PF ) { |
138 | // Upshift all params by 1 |
139 | $numKeys = count( $params ); |
140 | for ( $i = $numKeys; $i > 0; $i-- ) { |
141 | $params[(string)( $i + 1 )] = $params[(string)$i]; |
142 | } |
143 | |
144 | $matches = null; |
145 | preg_match( '/^([^:]*):(.*)$/', $this->targetWt, $matches ); |
146 | $params['1'] = (object)[ 'wt' => $matches[2] ]; |
147 | $target['wt'] = $matches[1]; |
148 | } |
149 | |
150 | return [ |
151 | 'target' => $target, |
152 | 'params' => (object)$params, |
153 | 'i' => $this->i, |
154 | ]; |
155 | } |
156 | } |