Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
92.05% covered (success)
92.05%
81 / 88
91.67% covered (success)
91.67%
11 / 12
CRAP
0.00% covered (danger)
0.00%
0 / 1
ZType
92.05% covered (success)
92.05%
81 / 88
91.67% covered (success)
91.67%
11 / 12
27.37
0.00% covered (danger)
0.00%
0 / 1
 __construct
100.00% covered (success)
100.00%
10 / 10
100.00% covered (success)
100.00%
1 / 1
1
 getDefinition
100.00% covered (success)
100.00%
38 / 38
100.00% covered (success)
100.00%
1 / 1
1
 isValid
74.07% covered (warning)
74.07%
20 / 27
0.00% covered (danger)
0.00%
0 / 1
17.42
 getTypeId
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getTypeKeys
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getTypeValidator
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getEqualityFunction
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getRendererFunction
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getParserFunction
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getDeserialisers
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getSerialisers
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getZKey
100.00% covered (success)
100.00%
5 / 5
100.00% covered (success)
100.00%
1 / 1
3
1<?php
2/**
3 * WikiLambda ZType
4 *
5 * @file
6 * @ingroup Extensions
7 * @copyright 2020– Abstract Wikipedia team; see AUTHORS.txt
8 * @license MIT
9 */
10
11namespace MediaWiki\Extension\WikiLambda\ZObjects;
12
13use MediaWiki\Extension\WikiLambda\Registry\ZTypeRegistry;
14
15class ZType extends ZObject {
16
17    /**
18     * Construct a ZType instance given the identity ZReference, a ZTypedList of ZKeys,
19     * and a ZReference to the type validator
20     *
21     * @param ZObject $identity
22     * @param ZObject $keys
23     * @param ZObject $validator
24     * @param ?ZObject $equality
25     * @param ?ZObject $renderer
26     * @param ?ZObject $parser
27     * @param ?ZTypedList $deserialisers
28     * @param ?ZTypedList $serialisers
29     */
30    public function __construct(
31        $identity, $keys, $validator,
32        ?ZObject $equality = null,
33        ?ZObject $renderer = null, ?ZObject $parser = null,
34        ?ZTypedList $deserialisers = null, ?ZTypedList $serialisers = null
35    ) {
36        $this->data[ ZTypeRegistry::Z_TYPE_IDENTITY ] = $identity;
37        $this->data[ ZTypeRegistry::Z_TYPE_KEYS ] = $keys;
38        $this->data[ ZTypeRegistry::Z_TYPE_VALIDATOR ] = $validator;
39        $this->data[ ZTypeRegistry::Z_TYPE_EQUALITY ] = $equality ?? false;
40        $this->data[ ZTypeRegistry::Z_TYPE_RENDERER ] = $renderer ?? false;
41        $this->data[ ZTypeRegistry::Z_TYPE_PARSER ] = $parser ?? false;
42        $this->data[ ZTypeRegistry::Z_TYPE_DESERIALISERS ] = $deserialisers ??
43            new ZTypedList( ZTypedList::buildType( new ZReference( ZTypeRegistry::Z_DESERIALISER ) ) );
44        $this->data[ ZTypeRegistry::Z_TYPE_SERIALISERS ] = $serialisers ??
45            new ZTypedList( ZTypedList::buildType( new ZReference( ZTypeRegistry::Z_SERIALISER ) ) );
46    }
47
48    /**
49     * @inheritDoc
50     */
51    public static function getDefinition(): array {
52        return [
53            'type' => [
54                'type' => ZTypeRegistry::Z_REFERENCE,
55                'value' => ZTypeRegistry::Z_TYPE,
56            ],
57            'keys' => [
58                ZTypeRegistry::Z_TYPE_IDENTITY => [
59                    // NOTE: Allows Z0.
60                    'type' => ZTypeRegistry::BUILTIN_REFERENCE_NULLABLE,
61                ],
62                ZTypeRegistry::Z_TYPE_KEYS => [
63                    // TODO: Walk the array of ZKeys.
64                    'type' => ZTypeRegistry::HACK_ARRAY_Z_KEY,
65                    'required' => true,
66                ],
67                ZTypeRegistry::Z_TYPE_VALIDATOR => [
68                    // NOTE: Allows Z0 until we support ZFunctions.
69                    'type' => ZTypeRegistry::BUILTIN_REFERENCE_NULLABLE,
70                ],
71                ZTypeRegistry::Z_TYPE_EQUALITY => [
72                    'type' => ZTypeRegistry::Z_FUNCTION,
73                    'required' => false,
74                ],
75                ZTypeRegistry::Z_TYPE_RENDERER => [
76                    'type' => ZTypeRegistry::Z_FUNCTION,
77                    'required' => false,
78                ],
79                ZTypeRegistry::Z_TYPE_PARSER => [
80                    'type' => ZTypeRegistry::Z_FUNCTION,
81                    'required' => false,
82                ],
83                ZTypeRegistry::Z_TYPE_DESERIALISERS => [
84                    'type' => ZTypeRegistry::Z_FUNCTION_TYPED_LIST,
85                    'required' => false,
86                ],
87                ZTypeRegistry::Z_TYPE_SERIALISERS => [
88                    'type' => ZTypeRegistry::Z_FUNCTION_TYPED_LIST,
89                    'required' => false,
90                ],
91            ],
92        ];
93    }
94
95    /**
96     * @inheritDoc
97     */
98    public function isValid(): bool {
99        // Identity must be set to a valid ZReference (or special case of 'Z0')
100        if ( !isset( $this->data[ ZTypeRegistry::Z_TYPE_IDENTITY ] ) ) {
101            return false;
102        }
103        if ( !( $this->data[ ZTypeRegistry::Z_TYPE_IDENTITY ] instanceof ZReference ) ) {
104            return false;
105        }
106        if ( !( $this->data[ ZTypeRegistry::Z_TYPE_IDENTITY ]->isValid() ) ) {
107            return false;
108        }
109
110        // Key map must be set to an array or ZTypedList of zero or more ZKeys, all valid
111        if ( !isset( $this->data[ ZTypeRegistry::Z_TYPE_KEYS ] ) ) {
112            return false;
113        }
114        $keys = $this->data[ ZTypeRegistry::Z_TYPE_KEYS ];
115        if ( !is_array( $keys ) ) {
116            if ( $keys instanceof ZTypedList ) {
117                if ( $keys->getElementType()->getZValue() !== ZTypeRegistry::Z_KEY ) {
118                    return false;
119                }
120                $keys = $keys->getAsArray();
121            } else {
122                return false;
123            }
124        }
125        foreach ( $keys as $key ) {
126            if ( !( $key instanceof ZKey ) ) {
127                return false;
128            }
129            if ( !$key->isValid() ) {
130                return false;
131            }
132        }
133
134        // Validator must be set to a valid ZKey reference
135        if ( !isset( $this->data[ ZTypeRegistry::Z_TYPE_VALIDATOR ] ) ) {
136            return false;
137        }
138        if ( !( $this->data[ ZTypeRegistry::Z_TYPE_VALIDATOR ] instanceof ZReference ) ) {
139            return false;
140        }
141        if ( !( $this->data[ ZTypeRegistry::Z_TYPE_VALIDATOR ]->isValid() ) ) {
142            return false;
143        }
144        // TODO: Actually check that the validator is a ZFunction that applies to us.
145
146        // FIXME: Check the equality, renderer, parser, deserialiser, and serialiser keys.
147
148        return true;
149    }
150
151    /**
152     * Get the representation of th ZType Zid
153     *
154     * @return ZReference|ZFunctionCall
155     */
156    public function getTypeId() {
157        return $this->data[ ZTypeRegistry::Z_TYPE_IDENTITY ];
158    }
159
160    /**
161     * Get a list with the set of ZKeys for this ZType
162     *
163     * @return ZTypedList
164     */
165    public function getTypeKeys() {
166        return $this->data[ ZTypeRegistry::Z_TYPE_KEYS ];
167    }
168
169    /**
170     * Get the string representation of the ZReference to this ZType's validator function
171     *
172     * @return string
173     */
174    public function getTypeValidator() {
175        return $this->data[ ZTypeRegistry::Z_TYPE_VALIDATOR ]->getZValue();
176    }
177
178    /**
179     * Get the string representation of the ZReference to this ZType's equality function,
180     * or false if there is none.
181     *
182     * @return string|false
183     */
184    public function getEqualityFunction() {
185        return $this->data[ ZTypeRegistry::Z_TYPE_EQUALITY ]->getZValue();
186    }
187
188    /**
189     * Get the string representation of the ZReference to this ZType's rendering function,
190     * or false if there is none.
191     *
192     * @return string|false
193     */
194    public function getRendererFunction() {
195        return $this->data[ ZTypeRegistry::Z_TYPE_RENDERER ]->getZValue();
196    }
197
198    /**
199     * Get the string representation of the ZReference to this ZType's parsing function,
200     * or false if there is none.
201     *
202     * @return string|false
203     */
204    public function getParserFunction() {
205        return $this->data[ ZTypeRegistry::Z_TYPE_PARSER ]->getZValue();
206    }
207
208    /**
209     * Get the ZList of this ZType's deserialisers
210     *
211     * @return ZTypedList
212     */
213    public function getDeserialisers() {
214        return $this->data[ ZTypeRegistry::Z_TYPE_DESERIALISERS];
215    }
216
217    /**
218     * Get the ZList of this ZType's serialisers
219     *
220     * @return ZTypedList
221     */
222    public function getSerialisers() {
223        return $this->data[ ZTypeRegistry::Z_TYPE_SERIALISERS ];
224    }
225
226    /**
227     * Get the ZKey of a given key reference from the set of ZKeys of this ZType or
228     * null if the ZKey is not available.
229     *
230     * @param string $key
231     * @return ZKey|null
232     */
233    public function getZKey( $key ) {
234        $keys = $this->getTypeKeys()->getAsArray();
235        foreach ( $keys as $zkey ) {
236            if ( $zkey->getKeyId() === $key ) {
237                return $zkey;
238            }
239        }
240        return null;
241    }
242}