Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
88.10% covered (warning)
88.10%
37 / 42
91.67% covered (success)
91.67%
11 / 12
CRAP
0.00% covered (danger)
0.00%
0 / 1
GenericPageLinksTable
88.10% covered (warning)
88.10%
37 / 42
91.67% covered (success)
91.67%
11 / 12
21.74
0.00% covered (danger)
0.00%
0 / 1
 getFromNamespaceField
n/a
0 / 0
n/a
0 / 0
0
 getExistingFields
100.00% covered (success)
100.00%
4 / 4
100.00% covered (success)
100.00%
1 / 1
1
 getExistingLinks
100.00% covered (success)
100.00%
5 / 5
100.00% covered (success)
100.00%
1 / 1
3
 getNewLinkIDs
100.00% covered (success)
100.00%
3 / 3
100.00% covered (success)
100.00%
1 / 1
3
 getExistingLinkIDs
100.00% covered (success)
100.00%
3 / 3
100.00% covered (success)
100.00%
1 / 1
3
 isExisting
100.00% covered (success)
100.00%
2 / 2
100.00% covered (success)
100.00%
1 / 1
1
 isInNewSet
100.00% covered (success)
100.00%
2 / 2
100.00% covered (success)
100.00%
1 / 1
1
 insertLink
100.00% covered (success)
100.00%
9 / 9
100.00% covered (success)
100.00%
1 / 1
2
 deleteLink
100.00% covered (success)
100.00%
6 / 6
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
 makePageReferenceValue
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 makeTitle
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 deduplicateLinkIds
0.00% covered (danger)
0.00%
0 / 5
0.00% covered (danger)
0.00%
0 / 1
12
1<?php
2
3namespace MediaWiki\Deferred\LinksUpdate;
4
5use MediaWiki\Page\PageReferenceValue;
6use MediaWiki\Title\Title;
7
8/**
9 * Shared code for pagelinks, templatelinks and existencelinks. These tables
10 * all link to an arbitrary page identified by namespace and title.
11 *
12 * Link ID format: string[]:
13 *   - 0: namespace ID
14 *   - 1: title DB key
15 *
16 * @since 1.38
17 */
18abstract class GenericPageLinksTable extends TitleLinksTable {
19    /**
20     * A 2d array representing the new links, with the namespace ID in the
21     * first key, the DB key in the second key, and the value arbitrary.
22     *
23     * @var array
24     */
25    protected $newLinks = [];
26
27    /**
28     * The existing links in the same format as self::$newLinks, or null if it
29     * has not been loaded yet.
30     *
31     * @var array|null
32     */
33    private $existingLinks;
34
35    /**
36     * @return string|null
37     */
38    abstract protected function getFromNamespaceField();
39
40    /** @inheritDoc */
41    protected function getExistingFields() {
42        return [
43            'ns' => 'lt_namespace',
44            'title' => 'lt_title',
45        ];
46    }
47
48    /**
49     * Get existing links as an associative array
50     *
51     * @return array
52     */
53    private function getExistingLinks() {
54        if ( $this->existingLinks === null ) {
55            $this->existingLinks = [];
56            foreach ( $this->fetchExistingRows() as $row ) {
57                $this->existingLinks[$row->ns][$row->title] = 1;
58            }
59        }
60
61        return $this->existingLinks;
62    }
63
64    /** @inheritDoc */
65    protected function getNewLinkIDs() {
66        foreach ( $this->newLinks as $ns => $links ) {
67            foreach ( $links as $dbk => $unused ) {
68                yield [ $ns, (string)$dbk ];
69            }
70        }
71    }
72
73    /** @inheritDoc */
74    protected function getExistingLinkIDs() {
75        foreach ( $this->getExistingLinks() as $ns => $links ) {
76            foreach ( $links as $dbk => $unused ) {
77                yield [ $ns, (string)$dbk ];
78            }
79        }
80    }
81
82    /** @inheritDoc */
83    protected function isExisting( $linkId ) {
84        [ $ns, $dbk ] = $linkId;
85        return isset( $this->getExistingLinks()[$ns][$dbk] );
86    }
87
88    /** @inheritDoc */
89    protected function isInNewSet( $linkId ) {
90        [ $ns, $dbk ] = $linkId;
91        return isset( $this->newLinks[$ns][$dbk] );
92    }
93
94    /** @inheritDoc */
95    protected function insertLink( $linkId ) {
96        $row = [];
97        $fromNamespaceField = $this->getFromNamespaceField();
98        if ( $fromNamespaceField !== null ) {
99            $row[$fromNamespaceField] = $this->getSourcePage()->getNamespace();
100        }
101        $row[$this->getTargetIdField()] = $this->linkTargetLookup->acquireLinkTargetId(
102            $this->makeTitle( $linkId ),
103            $this->getDB()
104        );
105        $this->insertRow( $row );
106    }
107
108    /** @inheritDoc */
109    protected function deleteLink( $linkId ) {
110        $this->deleteRow( [
111            $this->getTargetIdField() => $this->linkTargetLookup->acquireLinkTargetId(
112                $this->makeTitle( $linkId ),
113                $this->getDB()
114            )
115        ] );
116    }
117
118    /** @inheritDoc */
119    protected function needForcedLinkRefresh() {
120        return $this->isCrossNamespaceMove();
121    }
122
123    /** @inheritDoc */
124    protected function makePageReferenceValue( $linkId ): PageReferenceValue {
125        return PageReferenceValue::localReference( $linkId[0], $linkId[1] );
126    }
127
128    /** @inheritDoc */
129    protected function makeTitle( $linkId ): Title {
130        return Title::makeTitle( $linkId[0], $linkId[1] );
131    }
132
133    /** @inheritDoc */
134    protected function deduplicateLinkIds( $linkIds ) {
135        $seen = [];
136        foreach ( $linkIds as $linkId ) {
137            if ( !isset( $seen[$linkId[0]][$linkId[1]] ) ) {
138                $seen[$linkId[0]][$linkId[1]] = true;
139                yield $linkId;
140            }
141        }
142    }
143}