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