Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
96.43% covered (success)
96.43%
81 / 84
85.71% covered (warning)
85.71%
6 / 7
CRAP
0.00% covered (danger)
0.00%
0 / 1
ZKey
96.43% covered (success)
96.43%
81 / 84
85.71% covered (warning)
85.71%
6 / 7
35
0.00% covered (danger)
0.00%
0 / 1
 __construct
100.00% covered (success)
100.00%
5 / 5
100.00% covered (success)
100.00%
1 / 1
2
 getDefinition
100.00% covered (success)
100.00%
23 / 23
100.00% covered (success)
100.00%
1 / 1
1
 isValid
93.33% covered (success)
93.33%
42 / 45
0.00% covered (danger)
0.00%
0 / 1
24.17
 getKeyType
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getKeyId
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getKeyLabel
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getIsIdentity
100.00% covered (success)
100.00%
8 / 8
100.00% covered (success)
100.00%
1 / 1
5
1<?php
2/**
3 * WikiLambda ZKey
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;
14use MediaWiki\Extension\WikiLambda\ZObjectUtils;
15
16class ZKey extends ZObject {
17
18    /**
19     * Construct a new ZKey instance
20     *
21     * @param ZObject $type ZReference to the type for this key value
22     * @param ZObject $identity ZString with the key ID
23     * @param ZObject $label ZMultiLingualString that contains the label of this key
24     * @param ZObject|null $isIdentity optional ZObject that contains the isIdentity flag
25     */
26    public function __construct( $type, $identity, $label, $isIdentity = null ) {
27        $this->data[ ZTypeRegistry::Z_KEY_TYPE ] = $type;
28        $this->data[ ZTypeRegistry::Z_KEY_ID ] = $identity;
29        $this->data[ ZTypeRegistry::Z_KEY_LABEL ] = $label;
30        if ( $isIdentity ) {
31            $this->data[ ZTypeRegistry::Z_KEY_IS_IDENTITY ] = $isIdentity;
32        }
33    }
34
35    /**
36     * @inheritDoc
37     */
38    public static function getDefinition(): array {
39        return [
40            'type' => [
41                'type' => ZTypeRegistry::Z_REFERENCE,
42                'value' => ZTypeRegistry::Z_KEY,
43            ],
44            'keys' => [
45                ZTypeRegistry::Z_KEY_TYPE => [
46                    'type' => ZTypeRegistry::HACK_REFERENCE_TYPE,
47                    'required' => true,
48                ],
49                ZTypeRegistry::Z_KEY_ID => [
50                    'type' => ZTypeRegistry::Z_STRING,
51                    'required' => true,
52                ],
53                ZTypeRegistry::Z_KEY_LABEL => [
54                    'type' => ZTypeRegistry::Z_MULTILINGUALSTRING,
55                ],
56                ZTypeRegistry::Z_KEY_IS_IDENTITY => [
57                    'type' => ZTypeRegistry::Z_BOOLEAN,
58                    'required' => false,
59                ],
60            ],
61        ];
62    }
63
64    /**
65     * @inheritDoc
66     */
67    public function isValid(): bool {
68        if ( !isset( $this->data[ ZTypeRegistry::Z_KEY_TYPE ] ) ) {
69            return false;
70        }
71        if ( !( $this->data[ ZTypeRegistry::Z_KEY_TYPE ] instanceof ZReference ) ) {
72            return false;
73        }
74        $type = $this->data[ ZTypeRegistry::Z_KEY_TYPE ]->getZValue();
75        if ( !ZObjectUtils::isValidZObjectReference( $type ) ) {
76            return false;
77        }
78
79        // Identity must be a global reference (LATER: or a built instance of global references)
80        if ( !isset( $this->data[ ZTypeRegistry::Z_KEY_ID ] ) ) {
81            return false;
82        }
83        if ( !( $this->data[ ZTypeRegistry::Z_KEY_ID ] instanceof ZString ) ) {
84            return false;
85        }
86        $identity = $this->data[ ZTypeRegistry::Z_KEY_ID ]->getZValue();
87        if ( !ZObjectUtils::isValidZObjectGlobalKey( $identity ) ) {
88            return false;
89        }
90
91        // Label must be an array of valid ZMonoLingualStrings or a valid ZMultiLingualString
92        if ( !isset( $this->data[ ZTypeRegistry::Z_KEY_LABEL ] ) ) {
93            return false;
94        }
95        $labels = $this->data[ ZTypeRegistry::Z_KEY_LABEL ];
96        if ( $labels instanceof ZMultiLingualString ) {
97            return $labels->isValid();
98        }
99        if ( !is_array( $labels ) ) {
100            return false;
101        }
102        foreach ( $labels as $label ) {
103            if ( !( $label instanceof ZMonoLingualString ) ) {
104                return false;
105            }
106            if ( !$label->isValid() ) {
107                return false;
108            }
109        }
110
111        // Is identity is an optional key, but if present it should be a valid ZBoolean
112        if ( isset( $this->data[ ZTypeRegistry::Z_KEY_IS_IDENTITY ] ) ) {
113            $isIdentity = $this->data[ ZTypeRegistry::Z_KEY_IS_IDENTITY ];
114
115            if ( $isIdentity instanceof ZReference ) {
116                // Either a reference to True or False...
117                if ( !$isIdentity->isValid() || (
118                    ( $isIdentity->getZValue() !== ZTypeRegistry::Z_BOOLEAN_TRUE ) &&
119                    ( $isIdentity->getZValue() !== ZTypeRegistry::Z_BOOLEAN_FALSE )
120                ) ) {
121                    return false;
122                }
123            } elseif ( $isIdentity instanceof ZObject ) {
124                // ... or a literal Z40 with a valid Z40K1.
125                if ( $isIdentity->getZType() !== ZTypeRegistry::Z_BOOLEAN ) {
126                    return false;
127                }
128                $booleanValue = $isIdentity->getValueByKey( ZTypeRegistry::Z_BOOLEAN_VALUE );
129                if ( !$booleanValue instanceof ZReference ) {
130                    return false;
131                }
132                if ( !$booleanValue->isValid() || (
133                    ( $booleanValue->getZValue() !== ZTypeRegistry::Z_BOOLEAN_TRUE ) &&
134                    ( $booleanValue->getZValue() !== ZTypeRegistry::Z_BOOLEAN_FALSE )
135                ) ) {
136                    return false;
137                }
138            } else {
139                // Has isIdentity field but the value is invalid
140                return false;
141            }
142        }
143
144        return true;
145    }
146
147    /**
148     * Get the Zid for the type that describes the value of this key.
149     *
150     * @return string
151     */
152    public function getKeyType() {
153        return $this->data[ ZTypeRegistry::Z_KEY_TYPE ]->getZValue();
154    }
155
156    /**
157     * Get the ZKey Id
158     *
159     * @return string
160     */
161    public function getKeyId() {
162        return $this->data[ ZTypeRegistry::Z_KEY_ID ]->getZValue();
163    }
164
165    /**
166     * Get the ZMultilingualString that contains the label for this key
167     *
168     * @return ZMultiLingualString
169     */
170    public function getKeyLabel() {
171        return $this->data[ ZTypeRegistry::Z_KEY_LABEL ];
172    }
173
174    /**
175     * Returns whether the key is identity or not
176     *
177     * @return bool
178     */
179    public function getIsIdentity() {
180        if ( isset( $this->data[ ZTypeRegistry::Z_KEY_IS_IDENTITY ] ) ) {
181            $isIdentity = $this->data[ ZTypeRegistry::Z_KEY_IS_IDENTITY ];
182            if ( $isIdentity->getZType() === ZTypeRegistry::Z_REFERENCE ) {
183                // Return true if it references Z41/True
184                return ( $isIdentity->getZValue() === ZTypeRegistry::Z_BOOLEAN_TRUE );
185            } elseif ( $isIdentity->getZType() === ZTypeRegistry::Z_BOOLEAN ) {
186                // Return true if the value of the literal Boolean is Z41/True
187                $booleanValue = $isIdentity->getValueByKey( ZTypeRegistry::Z_BOOLEAN_VALUE );
188                return $booleanValue && ( $booleanValue->getZValue() === ZTypeRegistry::Z_BOOLEAN_TRUE );
189            }
190        }
191        return false;
192    }
193}