Code Coverage |
||||||||||
Lines |
Functions and Methods |
Classes and Traits |
||||||||
| Total | |
90.23% |
194 / 215 |
|
71.43% |
5 / 7 |
CRAP | |
0.00% |
0 / 1 |
| ZObjectSecondaryDataUpdate | |
90.23% |
194 / 215 |
|
71.43% |
5 / 7 |
49.06 | |
0.00% |
0 / 1 |
| __construct | |
100.00% |
4 / 4 |
|
100.00% |
1 / 1 |
1 | |||
| doUpdate | |
82.95% |
73 / 88 |
|
0.00% |
0 / 1 |
18.43 | |||
| getRelatedZObjects | |
100.00% |
7 / 7 |
|
100.00% |
1 / 1 |
4 | |||
| getRelatedZObjectsOfFunctionCall | |
100.00% |
11 / 11 |
|
100.00% |
1 / 1 |
2 | |||
| getRelatedZObjectsOfFunction | |
100.00% |
50 / 50 |
|
100.00% |
1 / 1 |
13 | |||
| getRelatedZObjectsOfType | |
100.00% |
30 / 30 |
|
100.00% |
1 / 1 |
5 | |||
| getRelatedZObjectsOfInstance | |
76.00% |
19 / 25 |
|
0.00% |
0 / 1 |
5.35 | |||
| 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 MediaWiki\Deferred\DataUpdate; |
| 14 | use MediaWiki\Extension\WikiLambda\Cache\MemcachedWrapper; |
| 15 | use MediaWiki\Extension\WikiLambda\Registry\ZLangRegistry; |
| 16 | use MediaWiki\Extension\WikiLambda\Registry\ZTypeRegistry; |
| 17 | use MediaWiki\Extension\WikiLambda\ZObjects\ZFunction; |
| 18 | use MediaWiki\Extension\WikiLambda\ZObjects\ZFunctionCall; |
| 19 | use MediaWiki\Extension\WikiLambda\ZObjects\ZObject; |
| 20 | use MediaWiki\Extension\WikiLambda\ZObjects\ZReference; |
| 21 | use MediaWiki\Extension\WikiLambda\ZObjects\ZType; |
| 22 | use MediaWiki\Extension\WikiLambda\ZObjects\ZTypedList; |
| 23 | use MediaWiki\Logger\LoggerFactory; |
| 24 | use MediaWiki\Title\Title; |
| 25 | use Psr\Log\LoggerInterface; |
| 26 | |
| 27 | class ZObjectSecondaryDataUpdate extends DataUpdate { |
| 28 | |
| 29 | private Title $title; |
| 30 | private ZObjectContent $zObject; |
| 31 | private ?OrchestratorRequest $orchestrator; |
| 32 | private LoggerInterface $logger; |
| 33 | |
| 34 | public const INSTANCEOFENUM_DB_KEY = 'instanceofenum'; |
| 35 | |
| 36 | /** |
| 37 | * @param Title $title |
| 38 | * @param ZObjectContent $zObject |
| 39 | * @param ZObjectStore $zObjectStore |
| 40 | * @param MemcachedWrapper $zObjectCache |
| 41 | * @param OrchestratorRequest|null $orchestrator |
| 42 | */ |
| 43 | public function __construct( |
| 44 | Title $title, |
| 45 | ZObjectContent $zObject, |
| 46 | private readonly ZObjectStore $zObjectStore, |
| 47 | private readonly MemcachedWrapper $zObjectCache, |
| 48 | ?OrchestratorRequest $orchestrator = null |
| 49 | ) { |
| 50 | $this->title = $title; |
| 51 | $this->zObject = $zObject; |
| 52 | $this->orchestrator = $orchestrator; |
| 53 | $this->logger = LoggerFactory::getInstance( 'WikiLambda' ); |
| 54 | } |
| 55 | |
| 56 | public function doUpdate() { |
| 57 | // Given this title, gets ZID |
| 58 | // Given this zObject, gets ZType |
| 59 | // 1. Delete labels from wikilambda_zobject_labels for this ZID |
| 60 | // 2. Delete labels from wikilambda_zobject_label_conflicts for this ZID |
| 61 | // 3. Gets labels from this zObject (Z2K3 of the ZObjectContent) |
| 62 | // 4. Finds conflicting labels, e.g. existing labels from other ZIDs that have same language-value |
| 63 | // 5. Saves conflicting labels in wikilambda_zobject_label_conflicts and |
| 64 | // 6. Saves non-conflicting labels in wikilambda_zobject_labels |
| 65 | // 7. If appropriate, clear wikilambda_ztester_results for this ZID |
| 66 | // 8. If appropriate, add entry to wikilambda_zlanguages for this ZID |
| 67 | // 9. Add related zobjects, if any, to wikilambda_zobject_join for this ZID |
| 68 | |
| 69 | // TODO (T300522): Only re-write the labels if they've changed. |
| 70 | // TODO (T300522): Use a single fancy upsert to remove/update/insert instead? |
| 71 | |
| 72 | $zid = $this->title->getDBkey(); |
| 73 | |
| 74 | // (T380446) If the object is not valid there's nothing useful to do, except log an error and exit. |
| 75 | if ( !$this->zObject->isValid() ) { |
| 76 | $zerror = $this->zObject->getErrors(); |
| 77 | $this->logger->error( |
| 78 | 'ZObjectSecondaryDataUpdate unable to process, error thrown', |
| 79 | [ |
| 80 | 'zid' => $zid, |
| 81 | 'message' => $zerror->getMessage() |
| 82 | ] |
| 83 | ); |
| 84 | return; |
| 85 | } |
| 86 | |
| 87 | // Object is valid, we go on! |
| 88 | |
| 89 | // Delete all labels: primary ones and aliases |
| 90 | $this->zObjectStore->deleteZObjectLabelsByZid( $zid ); |
| 91 | $this->zObjectStore->deleteZObjectLabelConflictsByZid( $zid ); |
| 92 | |
| 93 | // Delete language entries, if appropriate |
| 94 | $this->zObjectStore->deleteZLanguageFromLanguagesCache( $zid ); |
| 95 | |
| 96 | $labels = $this->zObject->getLabels()->getValueAsList(); |
| 97 | |
| 98 | // TODO (T357552): This should write the shortform, encoded type (e.g. `Z881(Z6)`) |
| 99 | $ztype = $this->zObject->getZType(); |
| 100 | |
| 101 | // Store the ZObject in the object cache, for faster retrieval here and (in future) in the orchestrator |
| 102 | $cacheKey = $this->zObjectCache->makeKey( ZObjectStore::ZOBJECT_CACHE_KEY_PREFIX, $zid ); |
| 103 | $this->logger->debug( |
| 104 | __METHOD__ . ' writing new ZObject value to cache "' . $zid . '": type "' . $ztype . '".', |
| 105 | [ 'instance' => $zid, 'type' => $ztype ] |
| 106 | ); |
| 107 | $cacheResult = $this->zObjectCache->set( |
| 108 | $cacheKey, |
| 109 | $this->zObject->getText(), |
| 110 | $this->zObjectCache::TTL_MONTH |
| 111 | ); |
| 112 | if ( !$cacheResult ) { |
| 113 | $this->logger->warning( __METHOD__ . ' failed to cache new ZObject "' . $zid . '".', [ 'zid' => $zid ] ); |
| 114 | } |
| 115 | if ( $this->orchestrator ) { |
| 116 | $queryZ2 = $this->zObject->getObject(); |
| 117 | $this->orchestrator->persistToCache( $queryZ2 ); |
| 118 | } |
| 119 | |
| 120 | $innerZObject = $this->zObject->getInnerZObject(); |
| 121 | |
| 122 | $returnType = null; |
| 123 | // (T262089) Save output type in labels table for function and function call |
| 124 | // Get Z_FUNCTION_RETURN_TYPE if the ZObject is a Z8 Function |
| 125 | if ( $ztype === ZTypeRegistry::Z_FUNCTION ) { |
| 126 | $returnRef = $innerZObject->getValueByKey( ZTypeRegistry::Z_FUNCTION_RETURN_TYPE ); |
| 127 | // Fallback, save output type as Object/Z1 to avoid NULL returning functions |
| 128 | $returnType = ZTypeRegistry::Z_OBJECT; |
| 129 | if ( ( $returnRef instanceof ZReference ) || ( $returnRef instanceof ZFunctionCall ) ) { |
| 130 | // ZReference->getZValue returns the reference Zid |
| 131 | // ZFunctionCall->getZValue returns the function call function Zid |
| 132 | $returnType = $returnRef->getZValue(); |
| 133 | } |
| 134 | } |
| 135 | |
| 136 | $conflicts = $this->zObjectStore->findZObjectLabelConflicts( $zid, $ztype, $labels ); |
| 137 | $newLabels = array_filter( $labels, static function ( $value, $lang ) use ( $conflicts ) { |
| 138 | return !isset( $conflicts[$lang] ); |
| 139 | }, ARRAY_FILTER_USE_BOTH ); |
| 140 | |
| 141 | $this->zObjectStore->insertZObjectLabels( $zid, $ztype, $newLabels, $returnType ); |
| 142 | $this->zObjectStore->insertZObjectLabelConflicts( $zid, $conflicts ); |
| 143 | |
| 144 | // (T285368) Write aliases in the labels table |
| 145 | $aliases = $this->zObject->getAliases()->getValueAsList(); |
| 146 | // (T358737) Add the zid as fake aliases under Z1360/MUL (multi-lingual value) |
| 147 | $aliases[ ZLangRegistry::MULTILINGUAL_VALUE ] = [ $zid ]; |
| 148 | if ( count( $aliases ) > 0 ) { |
| 149 | $this->zObjectStore->insertZObjectAliases( $zid, $ztype, $aliases, $returnType ); |
| 150 | } |
| 151 | |
| 152 | // ======================================================== |
| 153 | // General delete actions: |
| 154 | // ======================================================== |
| 155 | // * Delete old function reference from wikilambda_zobject_function_join table |
| 156 | // * Delete related ZObjects from wikilambda_zobject_join table |
| 157 | $this->zObjectStore->deleteZFunctionReference( $zid ); |
| 158 | $this->zObjectStore->deleteRelatedZObjects( $zid ); |
| 159 | |
| 160 | // ======================================================== |
| 161 | // Type specific actions: |
| 162 | // ======================================================== |
| 163 | // * Function: |
| 164 | // - clear test results cache |
| 165 | // * Implementation: |
| 166 | // - delete old function→implementation relations |
| 167 | // - clear test results cache |
| 168 | // - insert new function→implementation relation |
| 169 | // * Tester: |
| 170 | // - delete old function→tester relations |
| 171 | // - clear test results cache |
| 172 | // - insert new function→tester relation |
| 173 | // * Type: |
| 174 | // - remove all instanceofenum from wikilambda_zobject_join table |
| 175 | // * Language: |
| 176 | // - remove old language codes from wikilambda_zlanguage |
| 177 | // - add new language codes |
| 178 | // - add as fake aliases under Z1360/MUL (multi-lingual value) |
| 179 | switch ( $ztype ) { |
| 180 | case ZTypeRegistry::Z_FUNCTION: |
| 181 | // TODO (T338247): Only clear test results cache for the old revision, not the new one |
| 182 | $this->zObjectStore->deleteZFunctionFromZTesterResultsCache( $zid ); |
| 183 | break; |
| 184 | |
| 185 | case ZTypeRegistry::Z_IMPLEMENTATION: |
| 186 | $zFunction = $innerZObject->getValueByKey( ZTypeRegistry::Z_IMPLEMENTATION_FUNCTION ); |
| 187 | // TODO (T338247): Only clear test results cache for the old revision, not the new one |
| 188 | $this->zObjectStore->deleteZImplementationFromZTesterResultsCache( $zid ); |
| 189 | // TODO (T362248): Have insertZFunctionReference do an update, |
| 190 | // and only delete if changing the type/target? |
| 191 | $this->zObjectStore->insertZFunctionReference( $zid, $zFunction->getZValue(), $ztype ); |
| 192 | break; |
| 193 | |
| 194 | case ZTypeRegistry::Z_TESTER: |
| 195 | $zFunction = $innerZObject->getValueByKey( ZTypeRegistry::Z_TESTER_FUNCTION ); |
| 196 | // TODO (T338247): Only clear test results cache for the old revision, not the new one |
| 197 | $this->zObjectStore->deleteZTesterFromZTesterResultsCache( $zid ); |
| 198 | // TODO (T362248): Have insertZFunctionReference do an update, |
| 199 | // and only delete if changing the type/target? |
| 200 | $this->zObjectStore->insertZFunctionReference( $zid, $zFunction->getZValue(), $ztype ); |
| 201 | break; |
| 202 | |
| 203 | case ZTypeRegistry::Z_TYPE: |
| 204 | // Remove all instanceofenum from wikilambda_zobject_join table |
| 205 | $this->zObjectStore->deleteRelatedZObjects( null, $zid, self::INSTANCEOFENUM_DB_KEY ); |
| 206 | break; |
| 207 | |
| 208 | case ZTypeRegistry::Z_LANGUAGE: |
| 209 | // Clear old values, if any |
| 210 | $this->zObjectStore->deleteZLanguageFromLanguagesCache( $zid ); |
| 211 | |
| 212 | // Set primary language code |
| 213 | $targetLanguage = $innerZObject->getValueByKey( ZTypeRegistry::Z_LANGUAGE_CODE )->getZValue(); |
| 214 | $languageCodes = [ $targetLanguage ]; |
| 215 | $this->zObjectStore->insertZLanguageToLanguagesCache( $zid, $targetLanguage ); |
| 216 | |
| 217 | // Set secondary language codes, if any |
| 218 | $secondaryLanguagesObject = $innerZObject->getValueByKey( ZTypeRegistry::Z_LANGUAGE_SECONDARYCODES ); |
| 219 | if ( $secondaryLanguagesObject !== null ) { |
| 220 | '@phan-var ZTypedList $secondaryLanguagesObject'; |
| 221 | $secondaryLanguages = $secondaryLanguagesObject->getAsArray(); |
| 222 | |
| 223 | foreach ( $secondaryLanguages as $key => $secondaryLanguage ) { |
| 224 | // $secondaryLanguage is a ZString but we want the actual string |
| 225 | $secondaryLanguageString = $secondaryLanguage->getZValue(); |
| 226 | $languageCodes[] = $secondaryLanguageString; |
| 227 | $this->zObjectStore->insertZLanguageToLanguagesCache( $zid, $secondaryLanguageString ); |
| 228 | } |
| 229 | } |
| 230 | |
| 231 | // (T343465) Add the language codes as fake aliases under Z1360/MUL (multi-lingual value) |
| 232 | $this->zObjectStore->insertZObjectAliases( |
| 233 | $zid, |
| 234 | $ztype, |
| 235 | [ ZLangRegistry::MULTILINGUAL_VALUE => $languageCodes ], |
| 236 | $returnType |
| 237 | ); |
| 238 | break; |
| 239 | |
| 240 | default: |
| 241 | // No action. |
| 242 | } |
| 243 | |
| 244 | // ======================================================== |
| 245 | // General insert actions: |
| 246 | // ======================================================== |
| 247 | // * Add related ZObjects to wikilambda_zobject_join table |
| 248 | $relatedZObjects = $this->getRelatedZObjects( $zid, $ztype, $innerZObject ); |
| 249 | if ( count( $relatedZObjects ) > 0 ) { |
| 250 | $this->zObjectStore->insertRelatedZObjects( $relatedZObjects ); |
| 251 | } |
| 252 | } |
| 253 | |
| 254 | /** |
| 255 | * Return all important relations between the given object and others |
| 256 | * to insert in the wikilambda_zobject_join table. The relations are |
| 257 | * given by the key. Currently finds relations for: |
| 258 | * * Functions/Z8 |
| 259 | * * Types/Z4 |
| 260 | * * Instances of enum types |
| 261 | * |
| 262 | * @param string $zid |
| 263 | * @param string $ztype |
| 264 | * @param ZObject $innerZObject |
| 265 | * @return array Array of rows to insert in the join table |
| 266 | */ |
| 267 | private function getRelatedZObjects( $zid, $ztype, $innerZObject ) { |
| 268 | if ( $innerZObject instanceof ZFunction ) { |
| 269 | return $this->getRelatedZObjectsOfFunction( $zid, $innerZObject ); |
| 270 | } |
| 271 | |
| 272 | if ( $innerZObject instanceof ZType ) { |
| 273 | return $this->getRelatedZObjectsOfType( $zid, $innerZObject ); |
| 274 | } |
| 275 | |
| 276 | if ( $innerZObject instanceof ZFunctionCall ) { |
| 277 | return $this->getRelatedZObjectsOfFunctionCall( $zid, $innerZObject ); |
| 278 | } |
| 279 | |
| 280 | return $this->getRelatedZObjectsOfInstance( $zid, $ztype ); |
| 281 | } |
| 282 | |
| 283 | /** |
| 284 | * Return all important relations between the given function and others. |
| 285 | * Currently returns: |
| 286 | * * key:Z7K1: Function |
| 287 | * |
| 288 | * @param string $zid |
| 289 | * @param ZFunctionCall $innerZObject |
| 290 | * @return array Array of rows to insert in the join table |
| 291 | */ |
| 292 | private function getRelatedZObjectsOfFunctionCall( $zid, $innerZObject ) { |
| 293 | $relatedZObjects = []; |
| 294 | |
| 295 | // Key:Z7K1: Get function zid |
| 296 | $functionZid = $innerZObject->getZValue(); |
| 297 | if ( $functionZid ) { |
| 298 | $relatedZObjects[] = (object)[ |
| 299 | 'zid' => $zid, |
| 300 | 'type' => ZTypeRegistry::Z_FUNCTIONCALL, |
| 301 | 'key' => ZTypeRegistry::Z_FUNCTIONCALL_FUNCTION, |
| 302 | 'related_zid' => $functionZid, |
| 303 | 'related_type' => ZTypeRegistry::Z_FUNCTION |
| 304 | ]; |
| 305 | } |
| 306 | |
| 307 | return $relatedZObjects; |
| 308 | } |
| 309 | |
| 310 | /** |
| 311 | * Return all important relations between the given function and others. |
| 312 | * Currently returns: |
| 313 | * * key:Z8K1: Type of every function input |
| 314 | * * key:Z8K2: Type of the function output |
| 315 | * * key:Z8K3: Test connected to the function |
| 316 | * * key:Z8K4: Implementation connected to the function |
| 317 | * |
| 318 | * @param string $zid |
| 319 | * @param ZFunction $innerZObject |
| 320 | * @return array Array of rows to insert in the join table |
| 321 | */ |
| 322 | private function getRelatedZObjectsOfFunction( $zid, $innerZObject ) { |
| 323 | $relatedZObjects = []; |
| 324 | |
| 325 | // Key:Z8K1: Get input types |
| 326 | $inputs = $innerZObject->getValueByKey( ZTypeRegistry::Z_FUNCTION_ARGUMENTS ); |
| 327 | if ( $inputs instanceof ZTypedList ) { |
| 328 | $inputList = $inputs->getAsArray(); |
| 329 | foreach ( $inputList as $key => $input ) { |
| 330 | $inputTypeObject = $input->getValueByKey( ZTypeRegistry::Z_ARGUMENTDECLARATION_TYPE ); |
| 331 | $inputTypeString = ZObjectUtils::makeTypeFingerprint( $inputTypeObject->getSerialized() ); |
| 332 | if ( $inputTypeString !== null ) { |
| 333 | $relatedZObjects[] = (object)[ |
| 334 | 'zid' => $zid, |
| 335 | 'type' => ZTypeRegistry::Z_FUNCTION, |
| 336 | 'key' => ZTypeRegistry::Z_FUNCTION_ARGUMENTS, |
| 337 | 'related_zid' => $inputTypeString, |
| 338 | 'related_type' => ZTypeRegistry::Z_TYPE |
| 339 | ]; |
| 340 | } |
| 341 | } |
| 342 | } |
| 343 | |
| 344 | // Key:Z8K2: Get output type |
| 345 | $outputType = $innerZObject->getValueByKey( ZTypeRegistry::Z_FUNCTION_RETURN_TYPE ); |
| 346 | $outputTypeString = ZObjectUtils::makeTypeFingerprint( $outputType->getSerialized() ); |
| 347 | if ( $outputTypeString !== null ) { |
| 348 | $relatedZObjects[] = (object)[ |
| 349 | 'zid' => $zid, |
| 350 | 'type' => ZTypeRegistry::Z_FUNCTION, |
| 351 | 'key' => ZTypeRegistry::Z_FUNCTION_RETURN_TYPE, |
| 352 | 'related_zid' => $outputTypeString, |
| 353 | 'related_type' => ZTypeRegistry::Z_TYPE |
| 354 | ]; |
| 355 | } |
| 356 | |
| 357 | // Key:Z8K3: Get tests |
| 358 | $tests = $innerZObject->getValueByKey( ZTypeRegistry::Z_FUNCTION_TESTERS ); |
| 359 | if ( $tests instanceof ZTypedList ) { |
| 360 | $testList = $tests->getAsArray(); |
| 361 | foreach ( $testList as $key => $test ) { |
| 362 | if ( $test instanceof ZReference && $test->isValid() ) { |
| 363 | $relatedZObjects[] = (object)[ |
| 364 | 'zid' => $zid, |
| 365 | 'type' => ZTypeRegistry::Z_FUNCTION, |
| 366 | 'key' => ZTypeRegistry::Z_FUNCTION_TESTERS, |
| 367 | 'related_zid' => $test->getZValue(), |
| 368 | 'related_type' => ZTypeRegistry::Z_TESTER |
| 369 | ]; |
| 370 | } |
| 371 | } |
| 372 | } |
| 373 | |
| 374 | // Key:Z8K4: Get implementations |
| 375 | $implementations = $innerZObject->getValueByKey( ZTypeRegistry::Z_FUNCTION_IMPLEMENTATIONS ); |
| 376 | if ( $implementations instanceof ZTypedList ) { |
| 377 | $implementationList = $implementations->getAsArray(); |
| 378 | foreach ( $implementationList as $key => $implementation ) { |
| 379 | if ( $implementation instanceof ZReference && $implementation->isValid() ) { |
| 380 | $relatedZObjects[] = (object)[ |
| 381 | 'zid' => $zid, |
| 382 | 'type' => ZTypeRegistry::Z_FUNCTION, |
| 383 | 'key' => ZTypeRegistry::Z_FUNCTION_IMPLEMENTATIONS, |
| 384 | 'related_zid' => $implementation->getZValue(), |
| 385 | 'related_type' => ZTypeRegistry::Z_IMPLEMENTATION |
| 386 | ]; |
| 387 | } |
| 388 | } |
| 389 | } |
| 390 | |
| 391 | return $relatedZObjects; |
| 392 | } |
| 393 | |
| 394 | /** |
| 395 | * Return all important relations between the given type and others. |
| 396 | * Currently returns: |
| 397 | * * key:Z4K5: Renderer function for the type |
| 398 | * * key:Z4K6: Parser function for the type |
| 399 | * |
| 400 | * @param string $zid |
| 401 | * @param ZType $innerZObject |
| 402 | * @return array Array of rows to insert in the join table |
| 403 | */ |
| 404 | private function getRelatedZObjectsOfType( $zid, $innerZObject ) { |
| 405 | $relatedZObjects = []; |
| 406 | |
| 407 | // Key:Z4K5: Get renderer function |
| 408 | $rendererFunction = $innerZObject->getRendererFunction(); |
| 409 | if ( $rendererFunction ) { |
| 410 | $relatedZObjects[] = (object)[ |
| 411 | 'zid' => $zid, |
| 412 | 'type' => ZTypeRegistry::Z_TYPE, |
| 413 | 'key' => ZTypeRegistry::Z_TYPE_RENDERER, |
| 414 | 'related_zid' => $rendererFunction, |
| 415 | 'related_type' => ZTypeRegistry::Z_FUNCTION |
| 416 | ]; |
| 417 | } |
| 418 | |
| 419 | // Key:Z4K6: Get parser function |
| 420 | $parserFunction = $innerZObject->getParserFunction(); |
| 421 | if ( $parserFunction ) { |
| 422 | $relatedZObjects[] = (object)[ |
| 423 | 'zid' => $zid, |
| 424 | 'type' => ZTypeRegistry::Z_TYPE, |
| 425 | 'key' => ZTypeRegistry::Z_TYPE_PARSER, |
| 426 | 'related_zid' => $parserFunction, |
| 427 | 'related_type' => ZTypeRegistry::Z_FUNCTION |
| 428 | ]; |
| 429 | } |
| 430 | |
| 431 | // Key:instanceofenum: Get all instances of enum type |
| 432 | if ( $innerZObject->isEnumType() ) { |
| 433 | // Gather all instances of this type, |
| 434 | // add them into the table |
| 435 | $instances = $this->zObjectStore->fetchZidsOfType( $zid ); |
| 436 | foreach ( $instances as $instance ) { |
| 437 | $relatedZObjects[] = (object)[ |
| 438 | 'zid' => $instance, |
| 439 | 'type' => $zid, |
| 440 | 'key' => self::INSTANCEOFENUM_DB_KEY, |
| 441 | 'related_zid' => $zid, |
| 442 | 'related_type' => ZTypeRegistry::Z_TYPE |
| 443 | ]; |
| 444 | } |
| 445 | } |
| 446 | |
| 447 | return $relatedZObjects; |
| 448 | } |
| 449 | |
| 450 | /** |
| 451 | * Return all important relations between arbitrary objects. |
| 452 | * Currently returns: |
| 453 | * * key:instanceofenum: if the given object is an instance of an enum type. |
| 454 | * |
| 455 | * @param string $zid |
| 456 | * @param string $type |
| 457 | * @return array Array of rows to insert in the join table |
| 458 | */ |
| 459 | private function getRelatedZObjectsOfInstance( $zid, $type ) { |
| 460 | $relatedZObjects = []; |
| 461 | |
| 462 | $typeTitle = Title::newFromText( $type, NS_MAIN ); |
| 463 | $typeContent = $this->zObjectStore->fetchZObjectByTitle( $typeTitle ); |
| 464 | if ( !$typeContent ) { |
| 465 | // Error: type is not found, nothing we can do except log |
| 466 | $this->logger->warning( |
| 467 | __METHOD__ . ' failed to update relations for "' . $zid . '": type "' . $type . '" not found', |
| 468 | [ 'instance' => $zid, 'type' => $type ] |
| 469 | ); |
| 470 | return []; |
| 471 | } |
| 472 | |
| 473 | try { |
| 474 | $typeObject = $typeContent->getInnerZObject(); |
| 475 | } catch ( ZErrorException $e ) { |
| 476 | // Error: type is not valid, nothing we can do except log |
| 477 | $this->logger->warning( |
| 478 | __METHOD__ . ' failed to update relations for "' . $zid . '": type "' . $type . '" not valid', |
| 479 | [ 'instance' => $zid, 'type' => $type, 'responseError' => $e ] |
| 480 | ); |
| 481 | return []; |
| 482 | } |
| 483 | |
| 484 | // Key:instanceofenum: If object is an instance of an Enum type |
| 485 | if ( $typeObject instanceof ZType && $typeObject->isEnumType() ) { |
| 486 | $relatedZObjects[] = (object)[ |
| 487 | 'zid' => $zid, |
| 488 | 'type' => $type, |
| 489 | 'key' => self::INSTANCEOFENUM_DB_KEY, |
| 490 | 'related_zid' => $type, |
| 491 | 'related_type' => ZTypeRegistry::Z_TYPE |
| 492 | ]; |
| 493 | } |
| 494 | |
| 495 | return $relatedZObjects; |
| 496 | } |
| 497 | } |