Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
100.00% covered (success)
100.00%
44 / 44
100.00% covered (success)
100.00%
13 / 13
CRAP
100.00% covered (success)
100.00%
1 / 1
ExternalLinksTable
100.00% covered (success)
100.00%
44 / 44
100.00% covered (success)
100.00%
13 / 13
23
100.00% covered (success)
100.00%
1 / 1
 setParserOutput
100.00% covered (success)
100.00%
3 / 3
100.00% covered (success)
100.00%
1 / 1
3
 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
 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%
6 / 6
100.00% covered (success)
100.00%
1 / 1
1
 deleteLink
100.00% covered (success)
100.00%
10 / 10
100.00% covered (success)
100.00%
1 / 1
2
 getStringArray
100.00% covered (success)
100.00%
6 / 6
100.00% covered (success)
100.00%
1 / 1
2
 virtualDomain
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
1<?php
2
3namespace MediaWiki\Deferred\LinksUpdate;
4
5use MediaWiki\ExternalLinks\LinkFilter;
6use MediaWiki\Parser\ParserOutput;
7
8/**
9 * externallinks
10 *
11 * Link ID format: string URL
12 *
13 * @since 1.38
14 */
15class ExternalLinksTable extends LinksTable {
16    /** @var array<string,array<string,true>> */
17    private $newLinks = [];
18    /** @var array<string,array<string,true>>|null */
19    private $existingLinks;
20
21    public function setParserOutput( ParserOutput $parserOutput ) {
22        foreach ( $parserOutput->getExternalLinks() as $url => $unused ) {
23            foreach ( LinkFilter::makeIndexes( $url ) as [ $domainIndex, $path ] ) {
24                $this->newLinks[$domainIndex][$path] = true;
25            }
26        }
27    }
28
29    /** @inheritDoc */
30    protected function getTableName() {
31        return 'externallinks';
32    }
33
34    /** @inheritDoc */
35    protected function getFromField() {
36        return 'el_from';
37    }
38
39    /** @inheritDoc */
40    protected function getExistingFields() {
41        return [ 'el_to_domain_index', 'el_to_path' ];
42    }
43
44    /**
45     * Get the existing links as an array
46     *
47     * @return array
48     */
49    private function getExistingLinks() {
50        if ( $this->existingLinks === null ) {
51            $this->existingLinks = [];
52            foreach ( $this->fetchExistingRows() as $row ) {
53                $this->existingLinks[$row->el_to_domain_index][$row->el_to_path ?? ''] = true;
54            }
55        }
56        return $this->existingLinks;
57    }
58
59    /** @inheritDoc */
60    protected function getNewLinkIDs() {
61        foreach ( $this->newLinks as $domainIndex => $paths ) {
62            foreach ( $paths as $path => $unused ) {
63                yield [ (string)$domainIndex, (string)$path ];
64            }
65        }
66    }
67
68    /** @inheritDoc */
69    protected function getExistingLinkIDs() {
70        foreach ( $this->getExistingLinks() as $domainIndex => $paths ) {
71            foreach ( $paths as $path => $unused ) {
72                yield [ (string)$domainIndex, (string)$path ];
73            }
74        }
75    }
76
77    /** @inheritDoc */
78    protected function isExisting( $linkId ) {
79        [ $domainIndex, $path ] = $linkId;
80        return isset( $this->getExistingLinks()[$domainIndex][$path] );
81    }
82
83    /** @inheritDoc */
84    protected function isInNewSet( $linkId ) {
85        [ $domainIndex, $path ] = $linkId;
86        return isset( $this->newLinks[$domainIndex][$path] );
87    }
88
89    /** @inheritDoc */
90    protected function insertLink( $linkId ) {
91        [ $domainIndex, $path ] = $linkId;
92        $params = [
93            'el_to_domain_index' => substr( $domainIndex, 0, 255 ),
94            'el_to_path' => $path,
95        ];
96        $this->insertRow( $params );
97    }
98
99    /** @inheritDoc */
100    protected function deleteLink( $linkId ) {
101        [ $domainIndex, $path ] = $linkId;
102        $this->deleteRow( [
103            'el_to_domain_index' => substr( $domainIndex, 0, 255 ),
104            'el_to_path' => $path
105        ] );
106        if ( $path === '' ) {
107            // el_to_path is nullable, but null is not valid in php arrays,
108            // so both values are handled as one key, delete both rows when exists
109            $this->deleteRow( [
110                'el_to_domain_index' => substr( $domainIndex, 0, 255 ),
111                'el_to_path' => null
112            ] );
113        }
114    }
115
116    /**
117     * Get an array of URLs of the given type
118     *
119     * @param int $setType One of the link set constants as in LinksTable::getLinkIDs()
120     * @return string[]
121     */
122    public function getStringArray( $setType ) {
123        $ids = $this->getLinkIDs( $setType );
124        $stringArray = [];
125        foreach ( $ids as $linkId ) {
126            [ $domainIndex, $path ] = $linkId;
127            $stringArray[] = LinkFilter::reverseIndexes( $domainIndex ) . $path;
128        }
129        return $stringArray;
130    }
131
132    /** @inheritDoc */
133    protected function virtualDomain() {
134        return self::VIRTUAL_DOMAIN;
135    }
136}