Completed
Branch master (537795)
by
unknown
33:10
created

InterwikiLookupAdapter::getAllPrefixes()   A

Complexity

Conditions 4
Paths 4

Size

Total Lines 12
Code Lines 8

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 4
eloc 8
nc 4
nop 1
dl 0
loc 12
rs 9.2
c 0
b 0
f 0
1
<?php
2
namespace MediaWiki\Interwiki;
3
4
/**
5
 * InterwikiLookupAdapter on top of SiteLookup
6
 *
7
 * This program is free software; you can redistribute it and/or modify
8
 * it under the terms of the GNU General Public License as published by
9
 * the Free Software Foundation; either version 2 of the License, or
10
 * (at your option) any later version.
11
 *
12
 * This program is distributed in the hope that it will be useful,
13
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
 * GNU General Public License for more details.
16
 *
17
 * You should have received a copy of the GNU General Public License along
18
 * with this program; if not, write to the Free Software Foundation, Inc.,
19
 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20
 * http://www.gnu.org/copyleft/gpl.html
21
 *
22
 * @file
23
 *
24
 * @since 1.28
25
 * @ingroup InterwikiLookup
26
 *
27
 * @license GNU GPL v2+
28
 */
29
30
use Interwiki;
31
use Site;
32
use SiteLookup;
33
use MediawikiSite;
34
35
class InterwikiLookupAdapter implements InterwikiLookup {
36
37
	/**
38
	 * @var SiteLookup
39
	 */
40
	private $siteLookup;
41
42
	/**
43
	 * @var Interwiki[]|null associative array mapping interwiki prefixes to Interwiki objects
44
	 */
45
	private $interwikiMap;
46
47
	function __construct(
48
		SiteLookup $siteLookup,
49
		array $interwikiMap = null
50
	) {
51
		$this->siteLookup = $siteLookup;
52
		$this->interwikiMap = $interwikiMap;
53
	}
54
55
	/**
56
	 * See InterwikiLookup::isValidInterwiki
57
	 * It loads the whole interwiki map.
58
	 *
59
	 * @param string $prefix Interwiki prefix to use
60
	 * @return bool Whether it exists
61
	 */
62
	public function isValidInterwiki( $prefix ) {
63
64
		return array_key_exists( $prefix, $this->getInterwikiMap() );
65
	}
66
67
	/**
68
	 * See InterwikiLookup::fetch
69
	 * It loads the whole interwiki map.
70
	 *
71
	 * @param string $prefix Interwiki prefix to use
72
	 * @return Interwiki|null|bool
73
	 */
74
	public function fetch( $prefix ) {
75
		if ( $prefix == '' ) {
76
			return null;
77
		}
78
79
		if ( !$this->isValidInterwiki( $prefix ) ) {
80
			return false;
81
		}
82
83
		return $this->interwikiMap[$prefix];
84
	}
85
86
	/**
87
	 * See InterwikiLookup::getAllPrefixes
88
	 *
89
	 * @param string|null $local If set, limits output to local/non-local interwikis
90
	 * @return string[] List of prefixes
91
	 */
92
	public function getAllPrefixes( $local = null ) {
93
		if ( $local === null ) {
94
			return array_keys( $this->getInterwikiMap() );
95
		}
96
		$res = [];
97
		foreach ( $this->getInterwikiMap() as $interwikiId => $interwiki ) {
0 ignored issues
show
Bug introduced by
The expression $this->getInterwikiMap() of type null|array<integer,object<Interwiki>> is not guaranteed to be traversable. How about adding an additional type check?

There are different options of fixing this problem.

  1. If you want to be on the safe side, you can add an additional type-check:

    $collection = json_decode($data, true);
    if ( ! is_array($collection)) {
        throw new \RuntimeException('$collection must be an array.');
    }
    
    foreach ($collection as $item) { /** ... */ }
    
  2. If you are sure that the expression is traversable, you might want to add a doc comment cast to improve IDE auto-completion and static analysis:

    /** @var array $collection */
    $collection = json_decode($data, true);
    
    foreach ($collection as $item) { /** .. */ }
    
  3. Mark the issue as a false-positive: Just hover the remove button, in the top-right corner of this issue for more options.

Loading history...
98
			if ( $interwiki->isLocal() === $local ) {
99
				$res[] = $interwikiId;
100
			}
101
		}
102
		return $res;
103
	}
104
105
	/**
106
	 * See InterwikiLookup::invalidateCache
107
	 *
108
	 * @param string $prefix
109
	 */
110
	public function invalidateCache( $prefix ) {
111
		if ( !isset( $this->interwikiMap[$prefix] ) ) {
112
			return;
113
		}
114
		$globalId = $this->interwikiMap[$prefix]->getWikiID();
115
		unset( $this->interwikiMap[$prefix] );
116
117
		// Reload the interwiki
118
		$site = $this->siteLookup->getSites()->getSite( $globalId );
119
		$interwikis = $this->getSiteInterwikis( $site );
120
		$this->interwikiMap = array_merge( $this->interwikiMap, [ $interwikis[$prefix] ] );
121
	}
122
123
	/**
124
	 * Load interwiki map to use as cache
125
	 */
126
	private function loadInterwikiMap() {
127
		$interwikiMap = [];
128
		$siteList = $this->siteLookup->getSites();
129
		foreach ( $siteList as $site ) {
130
			$interwikis = $this->getSiteInterwikis( $site );
131
			$interwikiMap = array_merge( $interwikiMap, $interwikis );
132
		}
133
		$this->interwikiMap = $interwikiMap;
134
	}
135
136
	/**
137
	 * Get interwikiMap attribute, load if needed.
138
	 *
139
	 * @return Interwiki[]
140
	 */
141
	private function getInterwikiMap() {
142
		if ( $this->interwikiMap === null ) {
143
			$this->loadInterwikiMap();
144
		}
145
		return $this->interwikiMap;
146
	}
147
148
	/**
149
	 * Load interwikis for the given site
150
	 *
151
	 * @param Site $site
152
	 * @return Interwiki[]
153
	 */
154
	private function getSiteInterwikis( Site $site ) {
155
		$interwikis = [];
156
		foreach ( $site->getInterwikiIds() as $interwiki ) {
157
			$url = $site->getPageUrl();
158
			if ( $site instanceof MediawikiSite ) {
159
				$path = $site->getFileUrl( 'api.php' );
160
			} else {
161
				$path = '';
162
			}
163
			$local = $site->getSource() === 'local';
164
			// TODO: How to adapt trans?
165
			$interwikis[$interwiki] = new Interwiki(
166
				$interwiki,
167
				$url,
0 ignored issues
show
Bug introduced by
It seems like $url defined by $site->getPageUrl() on line 157 can also be of type false or null; however, Interwiki::__construct() does only seem to accept string, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
168
				$path,
169
				$site->getGlobalId(),
170
				$local
171
			);
172
		}
173
		return $interwikis;
174
	}
175
}
176