Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
100.00% covered (success)
100.00%
56 / 56
100.00% covered (success)
100.00%
2 / 2
CRAP
100.00% covered (success)
100.00%
1 / 1
UpdateImplementationsJob
100.00% covered (success)
100.00%
56 / 56
100.00% covered (success)
100.00%
2 / 2
6
100.00% covered (success)
100.00%
1 / 1
 __construct
100.00% covered (success)
100.00%
2 / 2
100.00% covered (success)
100.00%
1 / 1
1
 run
100.00% covered (success)
100.00%
54 / 54
100.00% covered (success)
100.00%
1 / 1
5
1<?php
2
3/**
4 * @file
5 * @ingroup Extensions
6 * @copyright 2020– Abstract Wikipedia team; see AUTHORS.txt
7 * @license MIT
8 */
9
10namespace MediaWiki\Extension\WikiLambda\Jobs;
11
12use MediaWiki\Context\RequestContext;
13use MediaWiki\Extension\WikiLambda\Registry\ZTypeRegistry;
14use MediaWiki\Extension\WikiLambda\WikiLambdaServices;
15use MediaWiki\Extension\WikiLambda\ZErrorException;
16use MediaWiki\Extension\WikiLambda\ZObjects\ZReference;
17use MediaWiki\Extension\WikiLambda\ZObjects\ZTypedList;
18use MediaWiki\JobQueue\GenericParameterJob;
19use MediaWiki\JobQueue\Job;
20use MediaWiki\Logger\LoggerFactory;
21use MediaWiki\Title\Title;
22use Psr\Log\LoggerInterface;
23
24class UpdateImplementationsJob extends Job implements GenericParameterJob {
25
26    private LoggerInterface $logger;
27
28    /**
29     * @param array $params
30     */
31    public function __construct( array $params ) {
32        parent::__construct( 'updateImplementations', $params );
33
34        // Non-injected items
35        $this->logger = LoggerFactory::getInstance( 'WikiLambda' );
36    }
37
38    /**
39     * @return bool
40     * @throws ZErrorException from ZFunction::getImplementationZids
41     */
42    public function run() {
43        // ZID of the function whose Z8K4/implementations are to be updated
44        $functionZid = $this->params[ 'functionZid' ];
45        // Function revision detected by the creator/caller of this job
46        $functionRevision = $this->params[ 'functionRevision' ];
47        // List of newly-ranked Zids of implementations
48        $implementationRankingZids = $this->params[ 'implementationRankingZids' ];
49
50        $targetTitle = Title::newFromText( $functionZid, NS_MAIN );
51        $currentRevision = $targetTitle->getLatestRevID();
52        // TODO (T330030): Consider accessing the ZObjectStore as an injected service
53        $zObjectStore = WikiLambdaServices::getZObjectStore();
54        '@phan-var \MediaWiki\Extension\WikiLambda\ZObjectStore $zObjectStore';
55        $targetObject = $zObjectStore->fetchZObjectByTitle( $targetTitle );
56        $targetFunction = $targetObject->getInnerZObject();
57        '@phan-var \MediaWiki\Extension\WikiLambda\ZObjects\ZFunction $targetFunction';
58        // Last-moment update-compatibility check
59        if ( $currentRevision !== $functionRevision ) {
60            // If Z8K4/implementations elements are different than those in the ranking, bail out
61            $currentImplementationZids = $targetFunction->getImplementationZids();
62            if (
63                ( count( $implementationRankingZids ) !== count( $currentImplementationZids ) )
64                || array_diff( $implementationRankingZids, $currentImplementationZids )
65            ) {
66                $this->logger->debug(
67                    __CLASS__ . ' Bailing on {functionZid}: attached ZIDs have changed!',
68                    [
69                        'functionZid' => $functionZid,
70                        'functionRevision' => $functionRevision,
71                        'implementationRankingZids' => $implementationRankingZids,
72                        'currentImplementationZids' => $currentImplementationZids
73                    ]
74                );
75                return false;
76            }
77        }
78
79        $this->logger->debug(
80            __CLASS__ . ' Editing Function {functionZid} to update Implementations order',
81            [
82                'functionZid' => $functionZid,
83                'functionRevision' => $functionRevision,
84                'implementationRankingZids' => $implementationRankingZids
85            ]
86        );
87
88        $implementationRanking = [];
89        foreach ( $implementationRankingZids as $implementationZid ) {
90            $implementationRanking[] = new ZReference( $implementationZid );
91        }
92
93        // Update function with the new ranking
94        $targetFunction->setValueByKey(
95            ZTypeRegistry::Z_FUNCTION_IMPLEMENTATIONS,
96            new ZTypedList(
97                ZTypedList::buildType( new ZReference( ZTypeRegistry::Z_IMPLEMENTATION ) ),
98                $implementationRanking
99            )
100        );
101        // TODO (T330032): Consider accessing wfMessage as an injected service
102        $updatingComment = wfMessage( 'wikilambda-updated-implementations-summary' )
103            ->inLanguage( 'en' )->text();
104        $editStatus = $zObjectStore->updateZObjectAsSystemUser( RequestContext::getMain(), $functionZid,
105            $targetObject->getZObject()->__toString(), $updatingComment );
106
107        $this->logger->info(
108            __CLASS__ . ' Edited Function {functionZid} to update Implementations order',
109            [
110                'functionZid' => $functionZid,
111                'functionRevision' => $functionRevision,
112                'statusOK' => $editStatus->isOK(),
113                'statusErrors' => $editStatus->getErrors(),
114            ]
115        );
116
117        return true;
118    }
119}