Code Coverage |
||||||||||
Lines |
Functions and Methods |
Classes and Traits |
||||||||
Total | |
78.75% |
63 / 80 |
|
50.00% |
1 / 2 |
CRAP | |
0.00% |
0 / 1 |
ZObjectSecondaryDataUpdate | |
78.75% |
63 / 80 |
|
50.00% |
1 / 2 |
29.53 | |
0.00% |
0 / 1 |
__construct | |
100.00% |
2 / 2 |
|
100.00% |
1 / 1 |
1 | |||
doUpdate | |
78.21% |
61 / 78 |
|
0.00% |
0 / 1 |
28.48 |
1 | <?php |
2 | /** |
3 | * WikiLambda ZObject secondary data updater for when ZObjects are edited |
4 | * |
5 | * @file |
6 | * @ingroup Extensions |
7 | * @copyright 2020– Abstract Wikipedia team; see AUTHORS.txt |
8 | * @license MIT |
9 | */ |
10 | |
11 | namespace MediaWiki\Extension\WikiLambda; |
12 | |
13 | use Content; |
14 | use MediaWiki\Deferred\DataUpdate; |
15 | use MediaWiki\Extension\WikiLambda\Registry\ZTypeRegistry; |
16 | use MediaWiki\Extension\WikiLambda\ZObjects\ZReference; |
17 | use MediaWiki\Title\Title; |
18 | |
19 | class ZObjectSecondaryDataUpdate extends DataUpdate { |
20 | |
21 | private Title $title; |
22 | private ZObjectContent $zObject; |
23 | |
24 | /** |
25 | * @param Title $title |
26 | * @param Content $zObject |
27 | */ |
28 | public function __construct( Title $title, $zObject ) { |
29 | $this->title = $title; |
30 | $this->zObject = $zObject; |
31 | } |
32 | |
33 | public function doUpdate() { |
34 | // Given this title, gets ZID |
35 | // Given this zObject, gets ZType |
36 | // 1. Delete labels from wikilambda_zobject_labels for this ZID |
37 | // 2. Delete labels from wikilambda_zobject_label_conflicts for this ZID |
38 | // 3. Gets labels from this zObject (Z2K3 of the ZObjectContent) |
39 | // 4. Finds conflicting labels, e.g. existing labels from other ZIDs that have same language-value |
40 | // 5. Saves conflicting labels in wikilambda_zobject_label_conflicts and |
41 | // 6. Saves non-conflicting labels in wikilambda_zobject_labels |
42 | // 7. If appropriate, clear wikilambda_ztester_results for this ZID |
43 | // 8. If appropriate, add entry to wikilambda_zlanguages for this ZID |
44 | // 9. Add related zobjects, if any, to wikilambda_zobject_join for this ZID |
45 | |
46 | // TODO (T300522): Only re-write the labels if they've changed. |
47 | // TODO (T300522): Use a single fancy upsert to remove/update/insert instead? |
48 | |
49 | $zid = $this->title->getDBkey(); |
50 | |
51 | $zObjectStore = WikiLambdaServices::getZObjectStore(); |
52 | |
53 | // Delete all labels: primary ones and aliases |
54 | $zObjectStore->deleteZObjectLabelsByZid( $zid ); |
55 | $zObjectStore->deleteZObjectLabelConflictsByZid( $zid ); |
56 | |
57 | // Delete language entries, if appropriate |
58 | $zObjectStore->deleteZLanguageFromLanguagesCache( $zid ); |
59 | |
60 | $labels = $this->zObject->getLabels()->getValueAsList(); |
61 | |
62 | // TODO (T357552): This should write the shortform, encoded type (e.g. `Z881(Z6)`) |
63 | $ztype = $this->zObject->getZType(); |
64 | |
65 | $innerZObject = $this->zObject->getInnerZObject(); |
66 | |
67 | // (T262089) Save output type in labels table for function and function call |
68 | $returnType = null; |
69 | // Get Z_FUNCTION_RETURN_TYPE if the ZObject is a Z8 Function |
70 | if ( $ztype === ZTypeRegistry::Z_FUNCTION ) { |
71 | $returnRef = $innerZObject->getValueByKey( ZTypeRegistry::Z_FUNCTION_RETURN_TYPE ); |
72 | if ( $returnRef instanceof ZReference ) { |
73 | $returnType = $returnRef->getZValue(); |
74 | } |
75 | } |
76 | // Get saved Z_FUNCTION_RETURN_TYPE of the Z_FUNCTIONCALL_FUNCTION if it's a Z7 |
77 | if ( $ztype === ZTypeRegistry::Z_FUNCTIONCALL ) { |
78 | $functionRef = $innerZObject->getValueByKey( ZTypeRegistry::Z_FUNCTIONCALL_FUNCTION ); |
79 | if ( $functionRef instanceof ZReference ) { |
80 | $returnType = $zObjectStore->fetchZFunctionReturnType( $functionRef->getZValue() ); |
81 | } |
82 | } |
83 | |
84 | $conflicts = $zObjectStore->findZObjectLabelConflicts( $zid, $ztype, $labels ); |
85 | $newLabels = array_filter( $labels, static function ( $value, $lang ) use ( $conflicts ) { |
86 | return !isset( $conflicts[$lang] ); |
87 | }, ARRAY_FILTER_USE_BOTH ); |
88 | |
89 | $zObjectStore->insertZObjectLabels( $zid, $ztype, $newLabels, $returnType ); |
90 | $zObjectStore->insertZObjectLabelConflicts( $zid, $conflicts ); |
91 | |
92 | // (T285368) Write aliases in the labels table |
93 | $aliases = $this->zObject->getAliases()->getValueAsList(); |
94 | if ( count( $aliases ) > 0 ) { |
95 | $zObjectStore->insertZObjectAliases( $zid, $ztype, $aliases, $returnType ); |
96 | } |
97 | |
98 | // Save function information in function table, if appropriate |
99 | // TODO (T362248): Have insertZFunctionReference do an update, and only delete if changing the type/target? |
100 | $zObjectStore->deleteZFunctionReference( $zid ); |
101 | switch ( $ztype ) { |
102 | case ZTypeRegistry::Z_IMPLEMENTATION: |
103 | $zFunction = $innerZObject->getValueByKey( ZTypeRegistry::Z_IMPLEMENTATION_FUNCTION ); |
104 | break; |
105 | |
106 | case ZTypeRegistry::Z_TESTER: |
107 | $zFunction = $innerZObject->getValueByKey( ZTypeRegistry::Z_TESTER_FUNCTION ); |
108 | break; |
109 | |
110 | default: |
111 | $zFunction = null; |
112 | break; |
113 | } |
114 | |
115 | if ( $zFunction && $zFunction->getZValue() ) { |
116 | $zObjectStore->insertZFunctionReference( $zid, $zFunction->getZValue(), $ztype ); |
117 | } |
118 | |
119 | // If $zid is a function, record each of its input types and its return type |
120 | $zObjectStore->deleteRelatedZObjects( $zid ); |
121 | if ( $ztype === ZTypeRegistry::Z_FUNCTION ) { |
122 | $inputArgumentsObject = $innerZObject->getValueByKey( ZTypeRegistry::Z_FUNCTION_ARGUMENTS ); |
123 | '@phan-var \MediaWiki\Extension\WikiLambda\ZObjects\ZTypedList $inputArgumentsObject'; |
124 | if ( $inputArgumentsObject !== null ) { |
125 | $inputArguments = $inputArgumentsObject->getAsArray(); |
126 | foreach ( $inputArguments as $key => $inputArgument ) { |
127 | $inputTypeObject = $inputArgument->getValueByKey( ZTypeRegistry::Z_ARGUMENTDECLARATION_TYPE ); |
128 | $inputTypeString = ZObjectUtils::makeTypeFingerprint( $inputTypeObject->getSerialized() ); |
129 | if ( $inputTypeString !== null ) { |
130 | $zObjectStore->insertRelatedZObjects( $zid, $ztype, |
131 | ZTypeRegistry::Z_FUNCTION_ARGUMENTS, |
132 | $inputTypeString, ZTypeRegistry::Z_TYPE ); |
133 | } |
134 | } |
135 | } |
136 | // Here we report more return type cases than above; use new vars to avoid confusion |
137 | $returnTypeObject = $innerZObject->getValueByKey( |
138 | ZTypeRegistry::Z_FUNCTION_RETURN_TYPE ); |
139 | $returnTypeString = ZObjectUtils::makeTypeFingerprint( $returnTypeObject->getSerialized() ); |
140 | if ( $returnTypeString !== null ) { |
141 | $zObjectStore->insertRelatedZObjects( $zid, $ztype, |
142 | ZTypeRegistry::Z_FUNCTION_RETURN_TYPE, |
143 | $returnTypeString, ZTypeRegistry::Z_TYPE ); |
144 | } |
145 | } |
146 | |
147 | // If appropriate, clear wikilambda_ztester_results for this ZID |
148 | // TODO (T338247): Only do this for the old revision not the new one. |
149 | switch ( $ztype ) { |
150 | case ZTypeRegistry::Z_FUNCTION: |
151 | $zObjectStore->deleteZFunctionFromZTesterResultsCache( $zid ); |
152 | break; |
153 | |
154 | case ZTypeRegistry::Z_IMPLEMENTATION: |
155 | $zObjectStore->deleteZImplementationFromZTesterResultsCache( $zid ); |
156 | break; |
157 | |
158 | case ZTypeRegistry::Z_TESTER: |
159 | $zObjectStore->deleteZTesterFromZTesterResultsCache( $zid ); |
160 | break; |
161 | |
162 | default: |
163 | // No action. |
164 | } |
165 | |
166 | // If appropriate, add entry to wikilambda_zlanguages for this ZID |
167 | if ( $ztype === ZTypeRegistry::Z_LANGUAGE ) { |
168 | // Clear old values, if any |
169 | $zObjectStore->deleteZLanguageFromLanguagesCache( $zid ); |
170 | |
171 | // Set primary language code |
172 | $targetLanguage = $innerZObject->getValueByKey( ZTypeRegistry::Z_LANGUAGE_CODE )->getZValue(); |
173 | $languageCodes = [ $targetLanguage ]; |
174 | $zObjectStore->insertZLanguageToLanguagesCache( $zid, $targetLanguage ); |
175 | |
176 | // Set secondary language codes, if any |
177 | $secondaryLanguagesObject = $innerZObject->getValueByKey( ZTypeRegistry::Z_LANGUAGE_SECONDARYCODES ); |
178 | if ( $secondaryLanguagesObject !== null ) { |
179 | '@phan-var \MediaWiki\Extension\WikiLambda\ZObjects\ZTypedList $secondaryLanguagesObject'; |
180 | $secondaryLanguages = $secondaryLanguagesObject->getAsArray(); |
181 | |
182 | foreach ( $secondaryLanguages as $key => $secondaryLanguage ) { |
183 | // $secondaryLanguage is a ZString but we want the actual string |
184 | $secondaryLanguageString = $secondaryLanguage->getZValue(); |
185 | $languageCodes[] = $secondaryLanguageString; |
186 | $zObjectStore->insertZLanguageToLanguagesCache( $zid, $secondaryLanguageString ); |
187 | } |
188 | } |
189 | |
190 | // (T343465) Add the language codes as fake aliases under Z1360/MUL (multi-lingual value) |
191 | $zObjectStore->insertZObjectAliases( |
192 | $zid, |
193 | $ztype, |
194 | [ 'Z1360' => $languageCodes ], |
195 | $returnType |
196 | ); |
197 | } |
198 | } |
199 | } |