1
|
|
|
<?php |
2
|
|
|
|
3
|
|
|
declare( strict_types = 1 ); |
4
|
|
|
|
5
|
|
|
namespace Maps; |
6
|
|
|
|
7
|
|
|
use DataValues\Geo\Parsers\LatLongParser; |
8
|
|
|
use FileFetcher\Cache\Factory as CacheFactory; |
9
|
|
|
use FileFetcher\FileFetcher; |
10
|
|
|
use Geocoder\Provider\Nominatim\Nominatim; |
11
|
|
|
use Http\Client\HttpClient; |
12
|
|
|
use Jeroen\SimpleGeocoder\Geocoder; |
13
|
|
|
use Jeroen\SimpleGeocoder\Geocoders\Adapters\GeocoderPhpAdapter; |
14
|
|
|
use Jeroen\SimpleGeocoder\Geocoders\Decorators\CoordinateFriendlyGeocoder; |
15
|
|
|
use Jeroen\SimpleGeocoder\Geocoders\FileFetchers\GeoNamesGeocoder; |
16
|
|
|
use Jeroen\SimpleGeocoder\Geocoders\FileFetchers\GoogleGeocoder; |
17
|
|
|
use Jeroen\SimpleGeocoder\Geocoders\FileFetchers\NominatimGeocoder; |
18
|
|
|
use Jeroen\SimpleGeocoder\Geocoders\NullGeocoder; |
19
|
|
|
use Maps\DataAccess\CachingGeocoder; |
20
|
|
|
use Maps\DataAccess\JsonFileParser; |
21
|
|
|
use Maps\DataAccess\MapsFileFetcher; |
22
|
|
|
use Maps\DataAccess\MediaWikiFileUrlFinder; |
23
|
|
|
use Maps\DataAccess\PageContentFetcher; |
24
|
|
|
use Maps\MediaWiki\ParserHooks\DisplayMapFunction; |
25
|
|
|
use Maps\Presentation\CoordinateFormatter; |
26
|
|
|
use Maps\Presentation\WikitextParsers\CircleParser; |
27
|
|
|
use Maps\Presentation\WikitextParsers\DistanceParser; |
28
|
|
|
use Maps\Presentation\WikitextParsers\ImageOverlayParser; |
29
|
|
|
use Maps\Presentation\WikitextParsers\LineParser; |
30
|
|
|
use Maps\Presentation\WikitextParsers\LocationParser; |
31
|
|
|
use Maps\Presentation\WikitextParsers\PolygonParser; |
32
|
|
|
use Maps\Presentation\WikitextParsers\RectangleParser; |
33
|
|
|
use Maps\Presentation\WikitextParsers\WmsOverlayParser; |
34
|
|
|
use MediaWiki\MediaWikiServices; |
35
|
|
|
use ParamProcessor\ParamDefinitionFactory; |
36
|
|
|
use Psr\Http\Message\RequestInterface; |
37
|
|
|
use Psr\Http\Message\ResponseInterface; |
38
|
|
|
use SimpleCache\Cache\Cache; |
39
|
|
|
use SimpleCache\Cache\MediaWikiCache; |
40
|
|
|
|
41
|
|
|
/** |
42
|
|
|
* @licence GNU GPL v2+ |
43
|
|
|
* @author Jeroen De Dauw < [email protected] > |
44
|
|
|
*/ |
45
|
|
|
class MapsFactory { |
46
|
|
|
|
47
|
|
|
private $settings; |
48
|
|
|
private $mediaWikiServices; |
49
|
|
|
|
50
|
|
|
private function __construct( array $settings, MediaWikiServices $mediaWikiServices ) { |
51
|
|
|
$this->settings = $settings; |
52
|
|
|
$this->mediaWikiServices = $mediaWikiServices; |
53
|
|
|
} |
54
|
|
|
|
55
|
|
|
public static function newDefault(): self { |
56
|
|
|
return new self( $GLOBALS, MediaWikiServices::getInstance() ); |
57
|
|
|
} |
58
|
|
|
|
59
|
|
|
/** |
60
|
|
|
* Only for legacy code where dependency injection is not possible |
61
|
|
|
*/ |
62
|
|
|
public static function globalInstance(): self { |
63
|
|
|
static $instance = null; |
64
|
|
|
|
65
|
|
|
if ( $instance === null ) { |
66
|
|
|
$instance = self::newDefault(); |
67
|
|
|
} |
68
|
|
|
|
69
|
|
|
return $instance; |
70
|
|
|
} |
71
|
|
|
|
72
|
|
|
public function newLocationParser(): LocationParser { |
73
|
|
|
return LocationParser::newInstance( |
74
|
|
|
$this->getGeocoder(), |
75
|
|
|
$this->getFileUrlFinder() |
76
|
|
|
); |
77
|
|
|
} |
78
|
|
|
|
79
|
|
|
public function getGeocoder(): Geocoder { |
80
|
|
|
$geocoder = new CoordinateFriendlyGeocoder( $this->newCoreGeocoder() ); |
81
|
|
|
|
82
|
|
|
if ( $this->settings['egMapsEnableGeoCache'] ) { |
83
|
|
|
return new CachingGeocoder( |
84
|
|
|
$geocoder, |
85
|
|
|
$this->getMediaWikiCache(), |
86
|
|
|
$this->settings['egMapsGeoCacheTtl'] |
87
|
|
|
); |
88
|
|
|
} |
89
|
|
|
|
90
|
|
|
return $geocoder; |
91
|
|
|
} |
92
|
|
|
|
93
|
|
|
private function newHttpClient(): HttpClient { |
94
|
|
|
return new class() implements HttpClient { |
95
|
|
|
public function sendRequest(RequestInterface $request): ResponseInterface { |
96
|
|
|
// TODO: does MW have the praent of ResponseInterface? |
97
|
|
|
} |
98
|
|
|
}; |
99
|
|
|
} |
100
|
|
|
|
101
|
|
|
private function newCoreGeocoder(): Geocoder { |
102
|
|
|
$l = Nominatim::withOpenStreetMapServer( |
103
|
|
|
$this->newHttpClient(), |
104
|
|
|
'Maps extension for MediaWiki' |
105
|
|
|
); |
106
|
|
|
|
107
|
|
|
return new GeocoderPhpAdapter( $l ); |
108
|
|
|
|
109
|
|
|
switch ( $this->settings['egMapsDefaultGeoService'] ) { |
|
|
|
|
110
|
|
|
case 'geonames': |
111
|
|
|
if ( $this->settings['egMapsGeoNamesUser'] === '' ) { |
112
|
|
|
return $this->newGoogleGeocoder(); |
113
|
|
|
} |
114
|
|
|
|
115
|
|
|
return new GeoNamesGeocoder( |
116
|
|
|
$this->newFileFetcher(), |
117
|
|
|
$this->settings['egMapsGeoNamesUser'] |
118
|
|
|
); |
119
|
|
|
case 'google': |
120
|
|
|
return $this->newGoogleGeocoder(); |
121
|
|
|
case 'nominatim': |
122
|
|
|
return new NominatimGeocoder( |
123
|
|
|
$this->newFileFetcher() |
124
|
|
|
); |
125
|
|
|
default: |
126
|
|
|
return new NullGeocoder(); |
127
|
|
|
} |
128
|
|
|
} |
129
|
|
|
|
130
|
|
|
private function newGoogleGeocoder(): Geocoder { |
131
|
|
|
return new GoogleGeocoder( |
132
|
|
|
$this->newFileFetcher(), |
133
|
|
|
$this->settings['egMapsGMaps3ApiKey'], |
134
|
|
|
$this->settings['egMapsGMaps3ApiVersion'] |
135
|
|
|
); |
136
|
|
|
} |
137
|
|
|
|
138
|
|
|
public function getFileFetcher(): FileFetcher { |
139
|
|
|
return $this->newFileFetcher(); |
140
|
|
|
} |
141
|
|
|
|
142
|
|
|
private function newFileFetcher(): FileFetcher { |
143
|
|
|
return new MapsFileFetcher(); |
144
|
|
|
} |
145
|
|
|
|
146
|
|
|
public function getGeoJsonFileFetcher(): FileFetcher { |
147
|
|
|
if ( $this->settings['egMapsGeoJsonCacheTtl'] === 0 ) { |
148
|
|
|
return $this->getFileFetcher(); |
149
|
|
|
} |
150
|
|
|
|
151
|
|
|
return ( new CacheFactory() )->newJeroenSimpleCacheFetcher( |
152
|
|
|
$this->getFileFetcher(), |
153
|
|
|
$this->getMediaWikiSimpleCache( $this->settings['egMapsGeoJsonCacheTtl'] ) |
154
|
|
|
); |
155
|
|
|
} |
156
|
|
|
|
157
|
|
|
private function getMediaWikiSimpleCache( int $ttlInSeconds ): Cache { |
158
|
|
|
return new MediaWikiCache( |
159
|
|
|
$this->getMediaWikiCache(), |
160
|
|
|
$ttlInSeconds |
161
|
|
|
); |
162
|
|
|
} |
163
|
|
|
|
164
|
|
|
private function getMediaWikiCache(): \BagOStuff { |
165
|
|
|
return wfGetCache( CACHE_ANYTHING ); |
166
|
|
|
} |
167
|
|
|
|
168
|
|
|
public function getPageContentFetcher(): PageContentFetcher { |
169
|
|
|
return new PageContentFetcher( |
170
|
|
|
$this->mediaWikiServices->getTitleParser(), |
171
|
|
|
$this->mediaWikiServices->getRevisionLookup() |
172
|
|
|
); |
173
|
|
|
} |
174
|
|
|
|
175
|
|
|
public function getCoordinateFormatter(): CoordinateFormatter { |
176
|
|
|
return new CoordinateFormatter(); |
177
|
|
|
} |
178
|
|
|
|
179
|
|
|
public function getFileUrlFinder(): FileUrlFinder { |
180
|
|
|
return new MediaWikiFileUrlFinder(); |
181
|
|
|
} |
182
|
|
|
|
183
|
|
|
public function getMappingServices(): MappingServices { |
184
|
|
|
return new MappingServices( |
185
|
|
|
$this->settings['egMapsAvailableServices'], |
186
|
|
|
$this->settings['egMapsDefaultService'], |
187
|
|
|
new GoogleMapsService(), |
188
|
|
|
new LeafletService() |
189
|
|
|
); |
190
|
|
|
} |
191
|
|
|
|
192
|
|
|
public function getDisplayMapFunction(): DisplayMapFunction { |
193
|
|
|
return new DisplayMapFunction( |
194
|
|
|
$this->getMappingServices() |
195
|
|
|
); |
196
|
|
|
} |
197
|
|
|
|
198
|
|
|
public function getParamDefinitionFactory(): ParamDefinitionFactory { |
199
|
|
|
$factory = ParamDefinitionFactory::newDefault(); |
200
|
|
|
|
201
|
|
|
$factory->registerType( 'coordinate', [ 'string-parser' => LatLongParser::class ] ); |
202
|
|
|
$factory->registerType( 'mapslocation', [ 'string-parser' => LocationParser::class ] ); |
203
|
|
|
$factory->registerType( 'mapsline', [ 'string-parser' => LineParser::class ] ); |
204
|
|
|
$factory->registerType( 'mapscircle', [ 'string-parser' => CircleParser::class ] ); |
205
|
|
|
$factory->registerType( 'mapsrectangle', [ 'string-parser' => RectangleParser::class ] ); |
206
|
|
|
$factory->registerType( 'mapspolygon', [ 'string-parser' => PolygonParser::class ] ); |
207
|
|
|
$factory->registerType( 'distance', [ 'string-parser' => DistanceParser::class ] ); |
208
|
|
|
$factory->registerType( 'wmsoverlay', [ 'string-parser' => WmsOverlayParser::class ] ); |
209
|
|
|
$factory->registerType( 'mapsimageoverlay', [ 'string-parser' => ImageOverlayParser::class ] ); |
210
|
|
|
$factory->registerType( 'jsonfile', [ 'string-parser' => JsonFileParser::class ] ); |
211
|
|
|
|
212
|
|
|
return $factory; |
213
|
|
|
} |
214
|
|
|
|
215
|
|
|
} |
216
|
|
|
|
This check looks for unreachable code. It uses sophisticated control flow analysis techniques to find statements which will never be executed.
Unreachable code is most often the result of
return
,die
orexit
statements that have been added for debug purposes.In the above example, the last
return false
will never be executed, because a return statement has already been met in every possible execution path.