Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
85.29% covered (warning)
85.29%
29 / 34
82.35% covered (warning)
82.35%
14 / 17
CRAP
0.00% covered (danger)
0.00%
0 / 1
ImageLinksTable
85.29% covered (warning)
85.29%
29 / 34
82.35% covered (warning)
82.35%
14 / 17
23.54
0.00% covered (danger)
0.00%
0 / 1
 setParserOutput
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getTableName
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getFromField
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getExistingFields
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getNewLinkIDs
100.00% covered (success)
100.00%
2 / 2
100.00% covered (success)
100.00%
1 / 1
2
 getExistingLinks
100.00% covered (success)
100.00%
5 / 5
100.00% covered (success)
100.00%
1 / 1
3
 getExistingLinkIDs
100.00% covered (success)
100.00%
2 / 2
100.00% covered (success)
100.00%
1 / 1
2
 isExisting
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 isInNewSet
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 needForcedLinkRefresh
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 insertLink
100.00% covered (success)
100.00%
4 / 4
100.00% covered (success)
100.00%
1 / 1
1
 deleteLink
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 makePageReferenceValue
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 makeTitle
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 deduplicateLinkIds
0.00% covered (danger)
0.00%
0 / 3
0.00% covered (danger)
0.00%
0 / 1
6
 finishUpdate
100.00% covered (success)
100.00%
5 / 5
100.00% covered (success)
100.00%
1 / 1
1
 invalidateImageDescriptions
100.00% covered (success)
100.00%
3 / 3
100.00% covered (success)
100.00%
1 / 1
1
1<?php
2
3namespace MediaWiki\Deferred\LinksUpdate;
4
5use MediaWiki\DAO\WikiAwareEntity;
6use MediaWiki\Page\PageReferenceValue;
7use MediaWiki\Parser\ParserOutput;
8use MediaWiki\Title\Title;
9use PurgeJobUtils;
10
11/**
12 * imagelinks
13 *
14 * Link ID format: string image name
15 *
16 * @since 1.38
17 */
18class ImageLinksTable extends TitleLinksTable {
19    /**
20     * @var array New links with the name in the key, value arbitrary
21     */
22    private $newLinks;
23
24    /**
25     * @var array Existing links with the name in the key, value arbitrary
26     */
27    private $existingLinks;
28
29    public function setParserOutput( ParserOutput $parserOutput ) {
30        $this->newLinks = $parserOutput->getImages();
31    }
32
33    protected function getTableName() {
34        return 'imagelinks';
35    }
36
37    protected function getFromField() {
38        return 'il_from';
39    }
40
41    protected function getExistingFields() {
42        return [ 'il_to' ];
43    }
44
45    protected function getNewLinkIDs() {
46        foreach ( $this->newLinks as $link => $unused ) {
47            yield (string)$link;
48        }
49    }
50
51    /**
52     * Get existing links with the name in the key, value arbitrary.
53     *
54     * @return array
55     */
56    private function getExistingLinks() {
57        if ( $this->existingLinks === null ) {
58            $this->existingLinks = [];
59            foreach ( $this->fetchExistingRows() as $row ) {
60                $this->existingLinks[$row->il_to] = true;
61            }
62        }
63        return $this->existingLinks;
64    }
65
66    protected function getExistingLinkIDs() {
67        foreach ( $this->getExistingLinks() as $link => $unused ) {
68            yield (string)$link;
69        }
70    }
71
72    protected function isExisting( $linkId ) {
73        return \array_key_exists( $linkId, $this->getExistingLinks() );
74    }
75
76    protected function isInNewSet( $linkId ) {
77        return \array_key_exists( $linkId, $this->newLinks );
78    }
79
80    protected function needForcedLinkRefresh() {
81        return $this->isCrossNamespaceMove();
82    }
83
84    protected function insertLink( $linkId ) {
85        $this->insertRow( [
86            'il_from_namespace' => $this->getSourcePage()->getNamespace(),
87            'il_to' => $linkId
88        ] );
89    }
90
91    protected function deleteLink( $linkId ) {
92        $this->deleteRow( [ 'il_to' => $linkId ] );
93    }
94
95    protected function makePageReferenceValue( $linkId ): PageReferenceValue {
96        return new PageReferenceValue( NS_FILE, $linkId, WikiAwareEntity::LOCAL );
97    }
98
99    protected function makeTitle( $linkId ): Title {
100        return Title::makeTitle( NS_FILE, $linkId );
101    }
102
103    protected function deduplicateLinkIds( $linkIds ) {
104        if ( !is_array( $linkIds ) ) {
105            $linkIds = iterator_to_array( $linkIds );
106        }
107        return array_unique( $linkIds );
108    }
109
110    protected function finishUpdate() {
111        // A update of namespace on cross namespace move is detected as insert + delete,
112        // but the updates are not needed there.
113        $allInsertedLinks = array_column( $this->insertedLinks, 0 );
114        $allDeletedLinks = array_column( $this->deletedLinks, 0 );
115        $insertedLinks = array_diff( $allInsertedLinks, $allDeletedLinks );
116        $deletedLinks = array_diff( $allDeletedLinks, $allInsertedLinks );
117
118        $this->invalidateImageDescriptions( $insertedLinks, $deletedLinks );
119    }
120
121    /**
122     * Invalidate all image description pages which had links added or removed
123     * @param array $insertedLinks
124     * @param array $deletedLinks
125     */
126    private function invalidateImageDescriptions( array $insertedLinks, array $deletedLinks ) {
127        PurgeJobUtils::invalidatePages(
128            $this->getDB(), NS_FILE,
129            array_merge( $insertedLinks, $deletedLinks ) );
130    }
131}