This project does not seem to handle request data directly as such no vulnerable execution paths were found.
include
, or for example
via PHP's auto-loading mechanism.
These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more
1 | <?php |
||
2 | |||
3 | namespace Wikibase\Repo; |
||
4 | |||
5 | use CentralIdLookup; |
||
6 | use DataValues\Deserializers\DataValueDeserializer; |
||
7 | use DataValues\Geo\Values\GlobeCoordinateValue; |
||
8 | use DataValues\MonolingualTextValue; |
||
9 | use DataValues\QuantityValue; |
||
10 | use DataValues\StringValue; |
||
11 | use DataValues\TimeValue; |
||
12 | use DataValues\UnknownValue; |
||
13 | use Deserializers\Deserializer; |
||
14 | use Deserializers\DispatchableDeserializer; |
||
15 | use Deserializers\DispatchingDeserializer; |
||
16 | use Diff\Comparer\ComparableComparer; |
||
17 | use Diff\Differ\OrderedListDiffer; |
||
18 | use Exception; |
||
19 | use ExtensionRegistry; |
||
20 | use HashBagOStuff; |
||
21 | use Hooks; |
||
22 | use HtmlCacheUpdater; |
||
23 | use IContextSource; |
||
24 | use InvalidArgumentException; |
||
25 | use JobQueueGroup; |
||
26 | use Language; |
||
27 | use LogicException; |
||
28 | use MediaWiki\Logger\LoggerFactory; |
||
29 | use MediaWiki\MediaWikiServices; |
||
30 | use MediaWiki\Site\MediaWikiPageNameNormalizer; |
||
31 | use MWException; |
||
32 | use ObjectCache; |
||
33 | use Psr\Log\LoggerInterface; |
||
34 | use RequestContext; |
||
35 | use Serializers\Serializer; |
||
36 | use SiteLookup; |
||
37 | use SpecialPage; |
||
38 | use StubObject; |
||
39 | use Title; |
||
40 | use User; |
||
41 | use ValueFormatters\FormatterOptions; |
||
42 | use ValueFormatters\ValueFormatter; |
||
43 | use ValueParsers\NullParser; |
||
44 | use Wikibase\DataAccess\AliasTermBuffer; |
||
45 | use Wikibase\DataAccess\DataAccessSettings; |
||
46 | use Wikibase\DataAccess\EntitySource; |
||
47 | use Wikibase\DataAccess\EntitySourceDefinitions; |
||
48 | use Wikibase\DataAccess\EntitySourceDefinitionsConfigParser; |
||
49 | use Wikibase\DataAccess\GenericServices; |
||
50 | use Wikibase\DataAccess\MediaWiki\EntitySourceDocumentUrlProvider; |
||
51 | use Wikibase\DataAccess\MultipleEntitySourceServices; |
||
52 | use Wikibase\DataAccess\PrefetchingTermLookup; |
||
53 | use Wikibase\DataAccess\SingleEntitySourceServices; |
||
54 | use Wikibase\DataAccess\WikibaseServices; |
||
55 | use Wikibase\DataModel\DeserializerFactory; |
||
56 | use Wikibase\DataModel\Entity\DispatchingEntityIdParser; |
||
57 | use Wikibase\DataModel\Entity\EntityIdParser; |
||
58 | use Wikibase\DataModel\Entity\EntityIdParsingException; |
||
59 | use Wikibase\DataModel\Entity\EntityIdValue; |
||
60 | use Wikibase\DataModel\Entity\Item; |
||
61 | use Wikibase\DataModel\Entity\ItemIdParser; |
||
62 | use Wikibase\DataModel\Entity\Property; |
||
63 | use Wikibase\DataModel\Entity\PropertyId; |
||
64 | use Wikibase\DataModel\SerializerFactory; |
||
65 | use Wikibase\DataModel\Services\Diff\EntityDiffer; |
||
66 | use Wikibase\DataModel\Services\Diff\EntityPatcher; |
||
67 | use Wikibase\DataModel\Services\EntityId\EntityIdComposer; |
||
68 | use Wikibase\DataModel\Services\EntityId\SuffixEntityIdParser; |
||
69 | use Wikibase\DataModel\Services\Lookup\EntityLookup; |
||
70 | use Wikibase\DataModel\Services\Lookup\EntityRetrievingDataTypeLookup; |
||
71 | use Wikibase\DataModel\Services\Lookup\InProcessCachingDataTypeLookup; |
||
72 | use Wikibase\DataModel\Services\Lookup\ItemLookup; |
||
73 | use Wikibase\DataModel\Services\Lookup\LegacyAdapterItemLookup; |
||
74 | use Wikibase\DataModel\Services\Lookup\LegacyAdapterPropertyLookup; |
||
75 | use Wikibase\DataModel\Services\Lookup\PropertyDataTypeLookup; |
||
76 | use Wikibase\DataModel\Services\Lookup\PropertyLookup; |
||
77 | use Wikibase\DataModel\Services\Lookup\TermLookup; |
||
78 | use Wikibase\DataModel\Services\Statement\GuidGenerator; |
||
79 | use Wikibase\DataModel\Services\Statement\StatementGuidParser; |
||
80 | use Wikibase\DataModel\Services\Statement\StatementGuidValidator; |
||
81 | use Wikibase\DataModel\Services\Term\TermBuffer; |
||
82 | use Wikibase\InternalSerialization\DeserializerFactory as InternalDeserializerFactory; |
||
83 | use Wikibase\Lib\Changes\EntityChangeFactory; |
||
84 | use Wikibase\Lib\ContentLanguages; |
||
85 | use Wikibase\Lib\DataTypeDefinitions; |
||
86 | use Wikibase\Lib\DataTypeFactory; |
||
87 | use Wikibase\Lib\DataValueFactory; |
||
88 | use Wikibase\Lib\EntityFactory; |
||
89 | use Wikibase\Lib\EntityTypeDefinitions; |
||
90 | use Wikibase\Lib\Formatters\CachingKartographerEmbeddingHandler; |
||
91 | use Wikibase\Lib\Formatters\EntityIdLinkFormatter; |
||
92 | use Wikibase\Lib\Formatters\EntityIdPlainLinkFormatter; |
||
93 | use Wikibase\Lib\Formatters\EntityIdValueFormatter; |
||
94 | use Wikibase\Lib\Formatters\FormatterLabelDescriptionLookupFactory; |
||
95 | use Wikibase\Lib\Formatters\MediaWikiNumberLocalizer; |
||
96 | use Wikibase\Lib\Formatters\OutputFormatSnakFormatterFactory; |
||
97 | use Wikibase\Lib\Formatters\OutputFormatValueFormatterFactory; |
||
98 | use Wikibase\Lib\Formatters\SnakFormatter; |
||
99 | use Wikibase\Lib\Formatters\WikibaseSnakFormatterBuilders; |
||
100 | use Wikibase\Lib\Formatters\WikibaseValueFormatterBuilders; |
||
101 | use Wikibase\Lib\Interactors\MatchingTermsLookupSearchInteractor; |
||
102 | use Wikibase\Lib\LanguageFallbackChainFactory; |
||
103 | use Wikibase\Lib\LanguageNameLookup; |
||
104 | use Wikibase\Lib\Modules\PropertyValueExpertsModule; |
||
105 | use Wikibase\Lib\Modules\SettingsValueProvider; |
||
106 | use Wikibase\Lib\PropertyInfoDataTypeLookup; |
||
107 | use Wikibase\Lib\SettingsArray; |
||
108 | use Wikibase\Lib\Store\CachingPropertyOrderProvider; |
||
109 | use Wikibase\Lib\Store\EntityArticleIdLookup; |
||
110 | use Wikibase\Lib\Store\EntityContentDataCodec; |
||
111 | use Wikibase\Lib\Store\EntityExistenceChecker; |
||
112 | use Wikibase\Lib\Store\EntityIdLookup; |
||
113 | use Wikibase\Lib\Store\EntityLinkTargetEntityIdLookup; |
||
114 | use Wikibase\Lib\Store\EntityNamespaceLookup; |
||
115 | use Wikibase\Lib\Store\EntityRedirectChecker; |
||
116 | use Wikibase\Lib\Store\EntityRevisionLookup; |
||
117 | use Wikibase\Lib\Store\EntityStore; |
||
118 | use Wikibase\Lib\Store\EntityStoreWatcher; |
||
119 | use Wikibase\Lib\Store\EntityTermStoreWriter; |
||
120 | use Wikibase\Lib\Store\EntityTitleTextLookup; |
||
121 | use Wikibase\Lib\Store\EntityUrlLookup; |
||
122 | use Wikibase\Lib\Store\ItemTermStoreWriterAdapter; |
||
123 | use Wikibase\Lib\Store\LanguageFallbackLabelDescriptionLookupFactory; |
||
124 | use Wikibase\Lib\Store\LinkTargetEntityIdLookup; |
||
125 | use Wikibase\Lib\Store\LookupConstants; |
||
126 | use Wikibase\Lib\Store\PropertyInfoLookup; |
||
127 | use Wikibase\Lib\Store\PropertyInfoStore; |
||
128 | use Wikibase\Lib\Store\PropertyTermStoreWriterAdapter; |
||
129 | use Wikibase\Lib\Store\Sql\EntityIdLocalPartPageTableEntityQuery; |
||
130 | use Wikibase\Lib\Store\Sql\PrefetchingWikiPageEntityMetaDataAccessor; |
||
131 | use Wikibase\Lib\Store\Sql\Terms\DatabaseTypeIdsStore; |
||
132 | use Wikibase\Lib\Store\Sql\Terms\TermStoreWriterFactory; |
||
133 | use Wikibase\Lib\Store\Sql\TypeDispatchingWikiPageEntityMetaDataAccessor; |
||
134 | use Wikibase\Lib\Store\Sql\WikiPageEntityMetaDataAccessor; |
||
135 | use Wikibase\Lib\Store\Sql\WikiPageEntityMetaDataLookup; |
||
136 | use Wikibase\Lib\Store\ThrowingEntityTermStoreWriter; |
||
137 | use Wikibase\Lib\Store\TitleLookupBasedEntityArticleIdLookup; |
||
138 | use Wikibase\Lib\Store\TitleLookupBasedEntityExistenceChecker; |
||
139 | use Wikibase\Lib\Store\TitleLookupBasedEntityRedirectChecker; |
||
140 | use Wikibase\Lib\Store\TitleLookupBasedEntityTitleTextLookup; |
||
141 | use Wikibase\Lib\Store\TitleLookupBasedEntityUrlLookup; |
||
142 | use Wikibase\Lib\Store\TypeDispatchingArticleIdLookup; |
||
143 | use Wikibase\Lib\Store\TypeDispatchingExistenceChecker; |
||
144 | use Wikibase\Lib\Store\TypeDispatchingRedirectChecker; |
||
145 | use Wikibase\Lib\Store\TypeDispatchingTitleTextLookup; |
||
146 | use Wikibase\Lib\Store\TypeDispatchingUrlLookup; |
||
147 | use Wikibase\Lib\Store\WikiPagePropertyOrderProvider; |
||
148 | use Wikibase\Lib\StringNormalizer; |
||
149 | use Wikibase\Lib\TermFallbackCache\TermFallbackCacheFacade; |
||
150 | use Wikibase\Lib\TermFallbackCache\TermFallbackCacheServiceFactory; |
||
151 | use Wikibase\Lib\TermFallbackCacheFactory; |
||
152 | use Wikibase\Lib\Units\UnitConverter; |
||
153 | use Wikibase\Lib\Units\UnitStorage; |
||
154 | use Wikibase\Lib\WikibaseContentLanguages; |
||
155 | use Wikibase\Lib\WikibaseSettings; |
||
156 | use Wikibase\Repo\Api\ApiHelperFactory; |
||
157 | use Wikibase\Repo\ChangeOp\ChangeOpFactoryProvider; |
||
158 | use Wikibase\Repo\ChangeOp\Deserialization\ChangeOpDeserializerFactory; |
||
159 | use Wikibase\Repo\ChangeOp\Deserialization\SiteLinkBadgeChangeOpSerializationValidator; |
||
160 | use Wikibase\Repo\ChangeOp\Deserialization\TermChangeOpSerializationValidator; |
||
161 | use Wikibase\Repo\ChangeOp\EntityChangeOpProvider; |
||
162 | use Wikibase\Repo\Content\EntityContentFactory; |
||
163 | use Wikibase\Repo\Content\ItemHandler; |
||
164 | use Wikibase\Repo\Content\PropertyHandler; |
||
165 | use Wikibase\Repo\Diff\ClaimDiffer; |
||
166 | use Wikibase\Repo\Diff\ClaimDifferenceVisualizer; |
||
167 | use Wikibase\Repo\Diff\DifferencesSnakVisualizer; |
||
168 | use Wikibase\Repo\Diff\EntityDiffVisualizerFactory; |
||
169 | use Wikibase\Repo\EditEntity\EditFilterHookRunner; |
||
170 | use Wikibase\Repo\EditEntity\MediawikiEditEntityFactory; |
||
171 | use Wikibase\Repo\EditEntity\MediawikiEditFilterHookRunner; |
||
172 | use Wikibase\Repo\EntityReferenceExtractors\EntityReferenceExtractorDelegator; |
||
173 | use Wikibase\Repo\EntityReferenceExtractors\StatementEntityReferenceExtractor; |
||
174 | use Wikibase\Repo\FederatedProperties\ApiServiceFactory; |
||
175 | use Wikibase\Repo\FederatedProperties\FederatedPropertiesEntitySourceDefinitionsConfigParser; |
||
176 | use Wikibase\Repo\FederatedProperties\WrappingEntityIdFormatterFactory; |
||
177 | use Wikibase\Repo\Hooks\Formatters\EntityLinkFormatterFactory; |
||
178 | use Wikibase\Repo\Interactors\ItemMergeInteractor; |
||
179 | use Wikibase\Repo\Interactors\ItemRedirectCreationInteractor; |
||
180 | use Wikibase\Repo\LinkedData\EntityDataFormatProvider; |
||
181 | use Wikibase\Repo\LinkedData\EntityDataUriManager; |
||
182 | use Wikibase\Repo\Localizer\ChangeOpApplyExceptionLocalizer; |
||
183 | use Wikibase\Repo\Localizer\ChangeOpDeserializationExceptionLocalizer; |
||
184 | use Wikibase\Repo\Localizer\ChangeOpValidationExceptionLocalizer; |
||
185 | use Wikibase\Repo\Localizer\DispatchingExceptionLocalizer; |
||
186 | use Wikibase\Repo\Localizer\ExceptionLocalizer; |
||
187 | use Wikibase\Repo\Localizer\GenericExceptionLocalizer; |
||
188 | use Wikibase\Repo\Localizer\MessageExceptionLocalizer; |
||
189 | use Wikibase\Repo\Localizer\MessageParameterFormatter; |
||
190 | use Wikibase\Repo\Localizer\ParseExceptionLocalizer; |
||
191 | use Wikibase\Repo\Notifications\ChangeNotifier; |
||
192 | use Wikibase\Repo\Notifications\DatabaseChangeTransmitter; |
||
193 | use Wikibase\Repo\Notifications\HookChangeTransmitter; |
||
194 | use Wikibase\Repo\Notifications\RepoEntityChange; |
||
195 | use Wikibase\Repo\Notifications\RepoItemChange; |
||
196 | use Wikibase\Repo\ParserOutput\DispatchingEntityMetaTagsCreatorFactory; |
||
197 | use Wikibase\Repo\ParserOutput\DispatchingEntityViewFactory; |
||
198 | use Wikibase\Repo\ParserOutput\EntityParserOutputGenerator; |
||
199 | use Wikibase\Repo\ParserOutput\EntityParserOutputGeneratorFactory; |
||
200 | use Wikibase\Repo\Rdf\EntityRdfBuilderFactory; |
||
201 | use Wikibase\Repo\Rdf\RdfVocabulary; |
||
202 | use Wikibase\Repo\Rdf\ValueSnakRdfBuilderFactory; |
||
203 | use Wikibase\Repo\Search\Fields\FieldDefinitions; |
||
204 | use Wikibase\Repo\Search\Fields\NoFieldDefinitions; |
||
205 | use Wikibase\Repo\Store\EntityPermissionChecker; |
||
206 | use Wikibase\Repo\Store\EntityTitleStoreLookup; |
||
207 | use Wikibase\Repo\Store\IdGenerator; |
||
208 | use Wikibase\Repo\Store\Sql\SqlIdGenerator; |
||
209 | use Wikibase\Repo\Store\Sql\SqlStore; |
||
210 | use Wikibase\Repo\Store\Sql\UpsertSqlIdGenerator; |
||
211 | use Wikibase\Repo\Store\Store; |
||
212 | use Wikibase\Repo\Store\TermsCollisionDetectorFactory; |
||
213 | use Wikibase\Repo\Store\TypeDispatchingEntityTitleStoreLookup; |
||
214 | use Wikibase\Repo\Store\WikiPageEntityStorePermissionChecker; |
||
215 | use Wikibase\Repo\Validators\EntityConstraintProvider; |
||
216 | use Wikibase\Repo\Validators\SnakValidator; |
||
217 | use Wikibase\Repo\Validators\TermValidatorFactory; |
||
218 | use Wikibase\Repo\Validators\ValidatorErrorLocalizer; |
||
219 | use Wikibase\Repo\View\RepoSpecialPageLinker; |
||
220 | use Wikibase\Repo\View\WikibaseHtmlSnakFormatterFactory; |
||
221 | use Wikibase\View\EntityIdFormatterFactory; |
||
222 | use Wikibase\View\Template\TemplateFactory; |
||
223 | use Wikibase\View\ViewFactory; |
||
224 | use Wikimedia\ObjectFactory; |
||
225 | |||
226 | /** |
||
227 | * Top level factory for the WikibaseRepo extension. |
||
228 | * |
||
229 | * @license GPL-2.0-or-later |
||
230 | * @author Jeroen De Dauw < [email protected] > |
||
231 | * @author Daniel Kinzler |
||
232 | * @author Tobias Gritschacher < [email protected] > |
||
233 | */ |
||
234 | class WikibaseRepo { |
||
235 | |||
236 | /** |
||
237 | * @var SettingsArray |
||
238 | */ |
||
239 | private $settings; |
||
240 | |||
241 | /** |
||
242 | * @var DataTypeFactory|null |
||
243 | */ |
||
244 | private $dataTypeFactory = null; |
||
245 | |||
246 | /** |
||
247 | * @var ValueParserFactory|null |
||
248 | */ |
||
249 | private $valueParserFactory = null; |
||
250 | |||
251 | /** |
||
252 | * @var SnakFactory|null |
||
253 | */ |
||
254 | private $snakFactory = null; |
||
255 | |||
256 | /** |
||
257 | * @var PropertyDataTypeLookup|null |
||
258 | */ |
||
259 | private $propertyDataTypeLookup = null; |
||
260 | |||
261 | /** |
||
262 | * @var StatementGuidValidator|null |
||
263 | */ |
||
264 | private $statementGuidValidator = null; |
||
265 | |||
266 | /** |
||
267 | * @var Deserializer|null |
||
268 | */ |
||
269 | private $entityDeserializer = null; |
||
270 | |||
271 | /** |
||
272 | * @var EntityIdParser|null |
||
273 | */ |
||
274 | private $entityIdParser = null; |
||
275 | |||
276 | /** |
||
277 | * @var EntityIdComposer|null |
||
278 | */ |
||
279 | private $entityIdComposer = null; |
||
280 | |||
281 | /** |
||
282 | * @var OutputFormatSnakFormatterFactory|null |
||
283 | */ |
||
284 | private $snakFormatterFactory = null; |
||
285 | |||
286 | /** |
||
287 | * @var OutputFormatValueFormatterFactory|null |
||
288 | */ |
||
289 | private $valueFormatterFactory = null; |
||
290 | |||
291 | /** |
||
292 | * @var SummaryFormatter|null |
||
293 | */ |
||
294 | private $summaryFormatter = null; |
||
295 | |||
296 | /** |
||
297 | * @var ExceptionLocalizer|null |
||
298 | */ |
||
299 | private $exceptionLocalizer = null; |
||
300 | |||
301 | /** |
||
302 | * @var Store|null |
||
303 | */ |
||
304 | private $store = null; |
||
305 | |||
306 | /** |
||
307 | * @var WikibaseContentLanguages|null |
||
308 | */ |
||
309 | private $wikibaseContentLanguages = null; |
||
310 | |||
311 | /** |
||
312 | * @var DataTypeDefinitions |
||
313 | */ |
||
314 | private $dataTypeDefinitions; |
||
315 | |||
316 | /** |
||
317 | * @var EntityTypeDefinitions |
||
318 | */ |
||
319 | private $entityTypeDefinitions; |
||
320 | |||
321 | /** |
||
322 | * @var ValueSnakRdfBuilderFactory |
||
323 | */ |
||
324 | private $valueSnakRdfBuilderFactory; |
||
325 | |||
326 | /** |
||
327 | * @var RdfVocabulary |
||
328 | */ |
||
329 | private $rdfVocabulary; |
||
330 | |||
331 | /** |
||
332 | * @var CachingCommonsMediaFileNameLookup|null |
||
333 | */ |
||
334 | private $cachingCommonsMediaFileNameLookup = null; |
||
335 | |||
336 | /** |
||
337 | * @var WikibaseServices|null |
||
338 | */ |
||
339 | private $wikibaseServices = null; |
||
340 | |||
341 | /** |
||
342 | * @var EntityRdfBuilderFactory|null |
||
343 | */ |
||
344 | private $entityRdfBuilderFactory = null; |
||
345 | |||
346 | /** |
||
347 | * @var CachingKartographerEmbeddingHandler|null |
||
348 | */ |
||
349 | private $kartographerEmbeddingHandler = null; |
||
350 | |||
351 | /** |
||
352 | * @var WikibaseRepo|null |
||
353 | */ |
||
354 | private static $instance = null; |
||
355 | |||
356 | /** |
||
357 | * @var ValidatorBuilders|null |
||
358 | */ |
||
359 | private static $validatorBuilders = null; |
||
360 | |||
361 | /** |
||
362 | * @var WikibaseValueFormatterBuilders|null |
||
363 | */ |
||
364 | private static $valueFormatterBuilders = null; |
||
365 | |||
366 | /** |
||
367 | * @var WikibaseSnakFormatterBuilders|null |
||
368 | */ |
||
369 | private static $snakFormatterBuilders = null; |
||
370 | |||
371 | /** |
||
372 | * @var EntitySourceDefinitions |
||
373 | */ |
||
374 | private $entitySourceDefinitions; |
||
375 | |||
376 | /** |
||
377 | * @var DataAccessSettings |
||
378 | */ |
||
379 | private $dataAccessSettings; |
||
380 | |||
381 | /** |
||
382 | * @var TermFallbackCacheFactory|null |
||
383 | */ |
||
384 | private $termFallbackCacheFactory = null; |
||
385 | |||
386 | public static function resetClassStatics() { |
||
387 | if ( !defined( 'MW_PHPUNIT_TEST' ) ) { |
||
388 | throw new Exception( |
||
389 | 'Cannot reset WikibaseRepo class statics outside of tests.' |
||
390 | ); |
||
391 | } |
||
392 | self::$instance = null; |
||
393 | self::$validatorBuilders = null; |
||
394 | self::$valueFormatterBuilders = null; |
||
395 | self::$snakFormatterBuilders = null; |
||
396 | ApiServiceFactory::resetClassStatics(); |
||
397 | } |
||
398 | |||
399 | /** |
||
400 | * IMPORTANT: Use only when it is not feasible to inject an instance properly. |
||
401 | * |
||
402 | * @throws MWException |
||
403 | * @return self |
||
404 | */ |
||
405 | private static function newInstance() { |
||
406 | $dataTypeDefinitionsArray = self::getDefaultDataTypes(); |
||
407 | Hooks::run( 'WikibaseRepoDataTypes', [ &$dataTypeDefinitionsArray ] ); |
||
408 | |||
409 | $entityTypeDefinitionsArray = self::getDefaultEntityTypes(); |
||
410 | Hooks::run( 'WikibaseRepoEntityTypes', [ &$entityTypeDefinitionsArray ] ); |
||
411 | |||
412 | $settings = WikibaseSettings::getRepoSettings(); |
||
413 | |||
414 | $dataTypeDefinitions = new DataTypeDefinitions( |
||
415 | $dataTypeDefinitionsArray, |
||
416 | $settings->getSetting( 'disabledDataTypes' ) |
||
417 | ); |
||
418 | $entityTypeDefinitions = new EntityTypeDefinitions( $entityTypeDefinitionsArray ); |
||
419 | |||
420 | return new self( |
||
421 | $settings, |
||
422 | $dataTypeDefinitions, |
||
423 | $entityTypeDefinitions, |
||
424 | self::getEntitySourceDefinitionsFromSettings( $settings, $entityTypeDefinitions ) |
||
425 | ); |
||
426 | } |
||
427 | |||
428 | private static function getEntitySourceDefinitionsFromSettings( |
||
429 | SettingsArray $settings, |
||
430 | EntityTypeDefinitions $entityTypeDefinitions |
||
431 | ) { |
||
432 | if ( $settings->hasSetting( 'entitySources' ) && !empty( $settings->getSetting( 'entitySources' ) ) ) { |
||
433 | $configParser = new EntitySourceDefinitionsConfigParser(); |
||
434 | |||
435 | return $configParser->newDefinitionsFromConfigArray( $settings->getSetting( 'entitySources' ), $entityTypeDefinitions ); |
||
436 | } |
||
437 | |||
438 | $parser = new EntitySourceDefinitionsLegacyRepoSettingsParser(); |
||
439 | |||
440 | if ( $settings->getSetting( 'federatedPropertiesEnabled' ) ) { |
||
441 | $configParser = new FederatedPropertiesEntitySourceDefinitionsConfigParser( $settings ); |
||
442 | |||
443 | return $configParser->initializeDefaults( |
||
444 | $parser->newDefinitionsFromSettings( $settings, $entityTypeDefinitions ), |
||
445 | $entityTypeDefinitions |
||
446 | ); |
||
447 | } |
||
448 | |||
449 | return $parser->newDefinitionsFromSettings( $settings, $entityTypeDefinitions ); |
||
450 | } |
||
451 | |||
452 | /** |
||
453 | * IMPORTANT: Use only when it is not feasible to inject an instance properly. |
||
454 | * |
||
455 | * @return self |
||
456 | */ |
||
457 | public static function getDefaultInstance() { |
||
458 | if ( self::$instance === null ) { |
||
459 | self::$instance = self::newInstance(); |
||
460 | } |
||
461 | |||
462 | return self::$instance; |
||
463 | } |
||
464 | |||
465 | /** |
||
466 | * @warning This is for use with bootstrap code in WikibaseRepo.datatypes.php only! |
||
467 | * Program logic should use WikibaseRepo::getDataTypeValidatorFactory() instead! |
||
468 | * |
||
469 | * @return ValidatorBuilders |
||
470 | */ |
||
471 | public static function getDefaultValidatorBuilders() { |
||
472 | if ( self::$validatorBuilders === null ) { |
||
473 | $wikibaseRepo = self::getDefaultInstance(); |
||
474 | self::$validatorBuilders = $wikibaseRepo->newValidatorBuilders(); |
||
475 | } |
||
476 | |||
477 | return self::$validatorBuilders; |
||
478 | } |
||
479 | |||
480 | /** |
||
481 | * Returns a low level factory object for creating validators for well known data types. |
||
482 | * |
||
483 | * @warning This is for use with getDefaultValidatorBuilders() during bootstrap only! |
||
484 | * Program logic should use WikibaseRepo::getDataTypeValidatorFactory() instead! |
||
485 | * |
||
486 | * @return ValidatorBuilders |
||
487 | */ |
||
488 | public function newValidatorBuilders() { |
||
489 | $urlSchemes = $this->settings->getSetting( 'urlSchemes' ); |
||
490 | |||
491 | return new ValidatorBuilders( |
||
492 | $this->getEntityLookup(), |
||
493 | $this->getEntityIdParser(), |
||
494 | $urlSchemes, |
||
495 | $this->getItemVocabularyBaseUri(), |
||
496 | $this->getMonolingualTextLanguages(), |
||
497 | $this->getCachingCommonsMediaFileNameLookup(), |
||
498 | new MediaWikiPageNameNormalizer(), |
||
499 | $this->settings->getSetting( 'geoShapeStorageApiEndpointUrl' ), |
||
500 | $this->settings->getSetting( 'tabularDataStorageApiEndpointUrl' ) |
||
501 | ); |
||
502 | } |
||
503 | |||
504 | /** |
||
505 | * @warning This is for use with bootstrap code in WikibaseRepo.datatypes.php only! |
||
506 | * Program logic should use WikibaseRepo::getSnakFormatterFactory() instead! |
||
507 | * |
||
508 | * @return WikibaseValueFormatterBuilders |
||
509 | */ |
||
510 | public static function getDefaultValueFormatterBuilders() { |
||
511 | if ( self::$valueFormatterBuilders === null ) { |
||
512 | global $wgThumbLimits; |
||
513 | $wikibaseRepo = self::getDefaultInstance(); |
||
514 | self::$valueFormatterBuilders = $wikibaseRepo->newWikibaseValueFormatterBuilders( $wgThumbLimits ); |
||
515 | } |
||
516 | |||
517 | return self::$valueFormatterBuilders; |
||
518 | } |
||
519 | |||
520 | /** |
||
521 | * Returns a low level factory object for creating formatters for well known data types. |
||
522 | * |
||
523 | * @warning This is for use with getDefaultValueFormatterBuilders() during bootstrap only! |
||
524 | * Program logic should use WikibaseRepo::getSnakFormatterFactory() instead! |
||
525 | * |
||
526 | * @param array $thumbLimits |
||
527 | * |
||
528 | * @return WikibaseValueFormatterBuilders |
||
529 | */ |
||
530 | private function newWikibaseValueFormatterBuilders( array $thumbLimits ) { |
||
531 | return new WikibaseValueFormatterBuilders( |
||
532 | new FormatterLabelDescriptionLookupFactory( $this->getTermLookup() ), |
||
533 | $this->getLanguageNameLookup(), |
||
534 | $this->getItemUrlParser(), |
||
535 | $this->settings->getSetting( 'geoShapeStorageBaseUrl' ), |
||
536 | $this->settings->getSetting( 'tabularDataStorageBaseUrl' ), |
||
537 | $this->getTermFallbackCache(), |
||
538 | $this->settings->getSetting( 'sharedCacheDuration' ), |
||
539 | $this->getEntityLookup(), |
||
540 | $this->getEntityRevisionLookup(), |
||
541 | $this->settings->getSetting( 'entitySchemaNamespace' ), |
||
542 | $this->getEntityExistenceChecker(), |
||
543 | $this->getEntityTitleTextLookup(), |
||
544 | $this->getEntityUrlLookup(), |
||
545 | $this->getEntityRedirectChecker(), |
||
546 | $this->getEntityTitleLookup(), |
||
547 | $this->getKartographerEmbeddingHandler(), |
||
548 | $this->settings->getSetting( 'useKartographerMaplinkInWikitext' ), |
||
549 | $thumbLimits |
||
550 | ); |
||
551 | } |
||
552 | |||
553 | /** |
||
554 | * @return CachingKartographerEmbeddingHandler|null |
||
555 | */ |
||
556 | public function getKartographerEmbeddingHandler() { |
||
557 | if ( $this->kartographerEmbeddingHandler === null && $this->useKartographerGlobeCoordinateFormatter() ) { |
||
558 | $this->kartographerEmbeddingHandler = new CachingKartographerEmbeddingHandler( |
||
559 | MediaWikiServices::getInstance()->getParserFactory()->create() |
||
560 | ); |
||
561 | } |
||
562 | |||
563 | return $this->kartographerEmbeddingHandler; |
||
564 | } |
||
565 | |||
566 | /** |
||
567 | * @return bool |
||
568 | */ |
||
569 | private function useKartographerGlobeCoordinateFormatter() { |
||
570 | // FIXME: remove the global out of here |
||
571 | global $wgKartographerEnableMapFrame; |
||
572 | |||
573 | return $this->settings->getSetting( 'useKartographerGlobeCoordinateFormatter' ) && |
||
574 | ExtensionRegistry::getInstance()->isLoaded( 'Kartographer' ) && |
||
575 | isset( $wgKartographerEnableMapFrame ) && |
||
576 | $wgKartographerEnableMapFrame; |
||
577 | } |
||
578 | |||
579 | /** |
||
580 | * @return LanguageNameLookup |
||
581 | */ |
||
582 | public function getLanguageNameLookup() { |
||
583 | return new LanguageNameLookup( $this->getUserLanguage()->getCode() ); |
||
584 | } |
||
585 | |||
586 | /** |
||
587 | * @warning This is for use with bootstrap code in WikibaseRepo.datatypes.php only! |
||
588 | * Program logic should use WikibaseRepo::getSnakFormatterFactory() instead! |
||
589 | * |
||
590 | * @return WikibaseSnakFormatterBuilders |
||
591 | */ |
||
592 | public static function getDefaultSnakFormatterBuilders() { |
||
593 | if ( self::$snakFormatterBuilders === null ) { |
||
594 | self::$snakFormatterBuilders = self::getDefaultInstance()->newWikibaseSnakFormatterBuilders( |
||
595 | self::getDefaultValueFormatterBuilders() |
||
596 | ); |
||
597 | } |
||
598 | |||
599 | return self::$snakFormatterBuilders; |
||
600 | } |
||
601 | |||
602 | /** |
||
603 | * Returns a low level factory object for creating formatters for well known data types. |
||
604 | * |
||
605 | * @warning This is for use with getDefaultValueFormatterBuilders() during bootstrap only! |
||
606 | * Program logic should use WikibaseRepo::getSnakFormatterFactory() instead! |
||
607 | * |
||
608 | * @param WikibaseValueFormatterBuilders $valueFormatterBuilders |
||
609 | * |
||
610 | * @return WikibaseSnakFormatterBuilders |
||
611 | */ |
||
612 | private function newWikibaseSnakFormatterBuilders( WikibaseValueFormatterBuilders $valueFormatterBuilders ) { |
||
613 | return new WikibaseSnakFormatterBuilders( |
||
614 | $valueFormatterBuilders, |
||
615 | $this->getStore()->getPropertyInfoLookup(), |
||
616 | $this->getPropertyDataTypeLookup(), |
||
617 | $this->getDataTypeFactory() |
||
618 | ); |
||
619 | } |
||
620 | |||
621 | public function __construct( |
||
622 | SettingsArray $settings, |
||
623 | DataTypeDefinitions $dataTypeDefinitions, |
||
624 | EntityTypeDefinitions $entityTypeDefinitions, |
||
625 | EntitySourceDefinitions $entitySourceDefinitions |
||
626 | ) { |
||
627 | $this->settings = $settings; |
||
628 | $this->dataTypeDefinitions = $dataTypeDefinitions; |
||
629 | $this->entityTypeDefinitions = $entityTypeDefinitions; |
||
630 | $this->entitySourceDefinitions = $entitySourceDefinitions; |
||
631 | } |
||
632 | |||
633 | /** |
||
634 | * @throws MWException when called to early |
||
635 | * @return Language |
||
636 | */ |
||
637 | private function getContentLanguage() { |
||
638 | /** |
||
639 | * Before this constant is defined, custom config may not have been taken into account. |
||
640 | * So try not to allow code to use a language before that point. |
||
641 | * This code was explicitly mentioning the SetupAfterCache hook. |
||
642 | * With services, that hook won't be a problem anymore. |
||
643 | * So this check may well be unnecessary (but better safe than sorry). |
||
644 | */ |
||
645 | if ( !defined( 'MW_SERVICE_BOOTSTRAP_COMPLETE' ) ) { |
||
646 | throw new MWException( 'Premature access to MediaWiki ContentLanguage!' ); |
||
647 | } |
||
648 | |||
649 | return MediaWikiServices::getInstance()->getContentLanguage(); |
||
650 | } |
||
651 | |||
652 | /** |
||
653 | * @throws MWException when called to early |
||
654 | * @return Language |
||
655 | */ |
||
656 | public function getUserLanguage() { |
||
657 | global $wgLang; |
||
658 | |||
659 | // TODO: define a LanguageProvider service instead of using a global directly. |
||
660 | // NOTE: we cannot inject $wgLang in the constructor, because it may still be null |
||
661 | // when WikibaseRepo is initialized. In particular, the language object may not yet |
||
662 | // be there when the SetupAfterCache hook is run during bootstrapping. |
||
663 | |||
664 | if ( !$wgLang ) { |
||
665 | throw new MWException( 'Premature access: $wgLang is not yet initialized!' ); |
||
666 | } |
||
667 | |||
668 | StubObject::unstub( $wgLang ); |
||
669 | return $wgLang; |
||
670 | } |
||
671 | |||
672 | /** |
||
673 | * @return DataTypeFactory |
||
674 | */ |
||
675 | public function getDataTypeFactory() { |
||
676 | if ( $this->dataTypeFactory === null ) { |
||
677 | $this->dataTypeFactory = new DataTypeFactory( $this->dataTypeDefinitions->getValueTypes() ); |
||
678 | } |
||
679 | |||
680 | return $this->dataTypeFactory; |
||
681 | } |
||
682 | |||
683 | private static function getDefaultDataTypes() { |
||
684 | $baseDataTypes = require __DIR__ . '/../../lib/WikibaseLib.datatypes.php'; |
||
685 | $repoDataTypes = require __DIR__ . '/../WikibaseRepo.datatypes.php'; |
||
686 | |||
687 | return array_merge_recursive( $baseDataTypes, $repoDataTypes ); |
||
688 | } |
||
689 | |||
690 | /** |
||
691 | * @return array[] |
||
692 | */ |
||
693 | private static function getDefaultEntityTypes() { |
||
694 | $baseEntityTypes = require __DIR__ . '/../../lib/WikibaseLib.entitytypes.php'; |
||
695 | $repoEntityTypes = require __DIR__ . '/../WikibaseRepo.entitytypes.php'; |
||
696 | |||
697 | return array_merge_recursive( $baseEntityTypes, $repoEntityTypes ); |
||
698 | } |
||
699 | |||
700 | /** |
||
701 | * @return ValueParserFactory |
||
702 | */ |
||
703 | public function getValueParserFactory() { |
||
704 | if ( $this->valueParserFactory === null ) { |
||
705 | $callbacks = $this->dataTypeDefinitions->getParserFactoryCallbacks(); |
||
706 | |||
707 | // For backwards-compatibility, also register parsers under legacy names, |
||
708 | // for use with the deprecated 'parser' parameter of the wbparsevalue API module. |
||
709 | $prefixedCallbacks = $this->dataTypeDefinitions->getParserFactoryCallbacks( |
||
710 | DataTypeDefinitions::PREFIXED_MODE |
||
711 | ); |
||
712 | if ( isset( $prefixedCallbacks['VT:wikibase-entityid'] ) ) { |
||
713 | $callbacks['wikibase-entityid'] = $prefixedCallbacks['VT:wikibase-entityid']; |
||
714 | } |
||
715 | if ( isset( $prefixedCallbacks['VT:globecoordinate'] ) ) { |
||
716 | $callbacks['globecoordinate'] = $prefixedCallbacks['VT:globecoordinate']; |
||
717 | } |
||
718 | // 'null' is not a datatype. Kept for backwards compatibility. |
||
719 | $callbacks['null'] = function() { |
||
720 | return new NullParser(); |
||
721 | }; |
||
722 | |||
723 | $this->valueParserFactory = new ValueParserFactory( $callbacks ); |
||
724 | } |
||
725 | |||
726 | return $this->valueParserFactory; |
||
727 | } |
||
728 | |||
729 | /** |
||
730 | * @return DataValueFactory |
||
731 | */ |
||
732 | public function getDataValueFactory() { |
||
733 | return new DataValueFactory( $this->getDataValueDeserializer() ); |
||
734 | } |
||
735 | |||
736 | /** |
||
737 | * @return EntityContentFactory |
||
738 | */ |
||
739 | public function getEntityContentFactory() { |
||
740 | return new EntityContentFactory( |
||
741 | $this->getContentModelMappings(), |
||
742 | $this->entityTypeDefinitions->get( EntityTypeDefinitions::CONTENT_HANDLER_FACTORY_CALLBACK ), |
||
743 | $this->entitySourceDefinitions, |
||
744 | $this->getLocalEntitySource(), |
||
745 | MediaWikiServices::getInstance()->getInterwikiLookup() |
||
746 | ); |
||
747 | } |
||
748 | |||
749 | public function getEntityChangeFactory(): EntityChangeFactory { |
||
750 | //TODO: take this from a setting or registry. |
||
751 | $changeClasses = [ |
||
752 | Item::ENTITY_TYPE => RepoItemChange::class, |
||
753 | // Other types of entities will use EntityChange |
||
754 | ]; |
||
755 | |||
756 | return new EntityChangeFactory( |
||
757 | $this->getEntityDiffer(), |
||
758 | $this->getEntityIdParser(), |
||
759 | $changeClasses, |
||
760 | RepoEntityChange::class, |
||
761 | $this->getLogger() |
||
762 | ); |
||
763 | } |
||
764 | |||
765 | /** |
||
766 | * @return EntityDiffer |
||
767 | */ |
||
768 | public function getEntityDiffer() { |
||
769 | $entityDiffer = new EntityDiffer(); |
||
770 | foreach ( $this->entityTypeDefinitions->get( EntityTypeDefinitions::ENTITY_DIFFER_STRATEGY_BUILDER ) as $builder ) { |
||
771 | $entityDiffer->registerEntityDifferStrategy( call_user_func( $builder ) ); |
||
772 | } |
||
773 | return $entityDiffer; |
||
774 | } |
||
775 | |||
776 | /** |
||
777 | * @return EntityPatcher |
||
778 | */ |
||
779 | public function getEntityPatcher() { |
||
780 | $entityPatcher = new EntityPatcher(); |
||
781 | foreach ( $this->entityTypeDefinitions->get( EntityTypeDefinitions::ENTITY_PATCHER_STRATEGY_BUILDER ) as $builder ) { |
||
782 | $entityPatcher->registerEntityPatcherStrategy( call_user_func( $builder ) ); |
||
783 | } |
||
784 | return $entityPatcher; |
||
785 | } |
||
786 | |||
787 | /** |
||
788 | * @return EntityStoreWatcher |
||
789 | */ |
||
790 | public function getEntityStoreWatcher() { |
||
791 | return $this->getStore()->getEntityStoreWatcher(); |
||
792 | } |
||
793 | |||
794 | /** |
||
795 | * @return EntityTitleStoreLookup |
||
796 | */ |
||
797 | public function getEntityTitleLookup() { |
||
798 | return new TypeDispatchingEntityTitleStoreLookup( |
||
799 | $this->entityTypeDefinitions->get( EntityTypeDefinitions::ENTITY_TITLE_STORE_LOOKUP_FACTORY_CALLBACK ), |
||
800 | $this->getEntityContentFactory() |
||
801 | ); |
||
802 | } |
||
803 | |||
804 | public function getEntityTitleTextLookup(): EntityTitleTextLookup { |
||
805 | return new TypeDispatchingTitleTextLookup( |
||
806 | $this->entityTypeDefinitions->get( EntityTypeDefinitions::TITLE_TEXT_LOOKUP_CALLBACK ), |
||
807 | new TitleLookupBasedEntityTitleTextLookup( $this->getEntityTitleLookup() ) |
||
808 | ); |
||
809 | } |
||
810 | |||
811 | public function getEntityUrlLookup(): EntityUrlLookup { |
||
812 | return new TypeDispatchingUrlLookup( |
||
813 | $this->entityTypeDefinitions->get( EntityTypeDefinitions::URL_LOOKUP_CALLBACK ), |
||
814 | new TitleLookupBasedEntityUrlLookup( $this->getEntityTitleLookup() ) |
||
815 | ); |
||
816 | } |
||
817 | |||
818 | public function getEntityArticleIdLookup(): EntityArticleIdLookup { |
||
819 | return new TypeDispatchingArticleIdLookup( |
||
820 | $this->entityTypeDefinitions->get( EntityTypeDefinitions::ARTICLE_ID_LOOKUP_CALLBACK ), |
||
821 | new TitleLookupBasedEntityArticleIdLookup( $this->getEntityTitleLookup() ) |
||
822 | ); |
||
823 | } |
||
824 | |||
825 | public function getEntityExistenceChecker(): EntityExistenceChecker { |
||
826 | return new TypeDispatchingExistenceChecker( |
||
827 | $this->entityTypeDefinitions->get( EntityTypeDefinitions::EXISTENCE_CHECKER_CALLBACK ), |
||
828 | new TitleLookupBasedEntityExistenceChecker( $this->getEntityTitleLookup() ) |
||
829 | ); |
||
830 | } |
||
831 | |||
832 | public function getEntityRedirectChecker(): EntityRedirectChecker { |
||
833 | return new TypeDispatchingRedirectChecker( |
||
834 | $this->entityTypeDefinitions->get( EntityTypeDefinitions::REDIRECT_CHECKER_CALLBACK ), |
||
835 | new TitleLookupBasedEntityRedirectChecker( $this->getEntityTitleLookup() ) |
||
836 | ); |
||
837 | } |
||
838 | |||
839 | /** |
||
840 | * @return EntityIdLookup |
||
841 | */ |
||
842 | public function getEntityIdLookup() { |
||
843 | return $this->getEntityContentFactory(); |
||
844 | } |
||
845 | |||
846 | public function getLocalRepoWikiPageMetaDataAccessor() : WikiPageEntityMetaDataAccessor { |
||
847 | $entityNamespaceLookup = $this->getEntityNamespaceLookup(); |
||
848 | $repoName = ''; // Empty string here means this only works for the local repo |
||
849 | $dbName = false; // false means the local database |
||
850 | return new PrefetchingWikiPageEntityMetaDataAccessor( |
||
851 | new TypeDispatchingWikiPageEntityMetaDataAccessor( |
||
852 | $this->entityTypeDefinitions->get( EntityTypeDefinitions::ENTITY_METADATA_ACCESSOR_CALLBACK ), |
||
853 | new WikiPageEntityMetaDataLookup( |
||
854 | $entityNamespaceLookup, |
||
855 | new EntityIdLocalPartPageTableEntityQuery( |
||
856 | $entityNamespaceLookup, |
||
857 | MediaWikiServices::getInstance()->getSlotRoleStore() |
||
858 | ), |
||
859 | $this->getLocalEntitySource() |
||
860 | ), |
||
861 | $dbName, |
||
862 | $repoName |
||
863 | ), |
||
864 | $this->getLogger() |
||
865 | ); |
||
866 | } |
||
867 | |||
868 | /** |
||
869 | * @see Store::getEntityRevisionLookup |
||
870 | * |
||
871 | * @param string $cache One of Store::LOOKUP_CACHING_* |
||
872 | * Store::LOOKUP_CACHING_DISABLED to get an uncached direct lookup |
||
873 | * Store::LOOKUP_CACHING_RETRIEVE_ONLY to get a lookup which reads from the cache, but doesn't store retrieved entities |
||
874 | * Store::LOOKUP_CACHING_ENABLED to get a caching lookup (default) |
||
875 | * |
||
876 | * @return EntityRevisionLookup |
||
877 | */ |
||
878 | public function getEntityRevisionLookup( $cache = Store::LOOKUP_CACHING_ENABLED ) { |
||
879 | return $this->getStore()->getEntityRevisionLookup( $cache ); |
||
880 | } |
||
881 | |||
882 | /** |
||
883 | * @return callable[] |
||
884 | */ |
||
885 | public function getEntityRevisionLookupFactoryCallbacks() { |
||
886 | return $this->entityTypeDefinitions->get( EntityTypeDefinitions::ENTITY_REVISION_LOOKUP_FACTORY_CALLBACK ); |
||
887 | } |
||
888 | |||
889 | /** |
||
890 | * @param User $user |
||
891 | * @param IContextSource $context |
||
892 | * |
||
893 | * @return ItemRedirectCreationInteractor |
||
894 | */ |
||
895 | public function newItemRedirectCreationInteractor( User $user, IContextSource $context ) { |
||
896 | return new ItemRedirectCreationInteractor( |
||
897 | $this->getEntityRevisionLookup( Store::LOOKUP_CACHING_DISABLED ), |
||
898 | $this->getEntityStore(), |
||
899 | $this->getEntityPermissionChecker(), |
||
900 | $this->getSummaryFormatter(), |
||
901 | $user, |
||
902 | $this->newEditFilterHookRunner( $context ), |
||
903 | $this->getStore()->getEntityRedirectLookup(), |
||
904 | $this->getEntityTitleLookup() |
||
905 | ); |
||
906 | } |
||
907 | |||
908 | /** |
||
909 | * @param IContextSource $context |
||
910 | * |
||
911 | * @return EditFilterHookRunner |
||
912 | */ |
||
913 | private function newEditFilterHookRunner( IContextSource $context ) { |
||
914 | return new MediawikiEditFilterHookRunner( |
||
915 | $this->getEntityNamespaceLookup(), |
||
916 | $this->getEntityTitleLookup(), |
||
917 | $this->getEntityContentFactory(), |
||
918 | $context |
||
919 | ); |
||
920 | } |
||
921 | |||
922 | /** |
||
923 | * @param string $displayLanguageCode |
||
924 | * |
||
925 | * @return MatchingTermsLookupSearchInteractor |
||
926 | */ |
||
927 | public function newTermSearchInteractor( $displayLanguageCode ) { |
||
928 | return $this->getWikibaseServices()->getTermSearchInteractorFactory()->newInteractor( |
||
929 | $displayLanguageCode |
||
930 | ); |
||
931 | } |
||
932 | |||
933 | /** |
||
934 | * @return EntityStore |
||
935 | */ |
||
936 | public function getEntityStore() { |
||
937 | return $this->getStore()->getEntityStore(); |
||
938 | } |
||
939 | |||
940 | /** |
||
941 | * @return callable[] |
||
942 | */ |
||
943 | public function getEntityStoreFactoryCallbacks() { |
||
944 | return $this->entityTypeDefinitions->get( EntityTypeDefinitions::ENTITY_STORE_FACTORY_CALLBACK ); |
||
945 | } |
||
946 | |||
947 | public function getPropertyDataTypeLookup(): PropertyDataTypeLookup { |
||
948 | if ( $this->propertyDataTypeLookup === null ) { |
||
949 | $this->propertyDataTypeLookup = $this->newPropertyDataTypeLookup(); |
||
950 | } |
||
951 | |||
952 | return $this->propertyDataTypeLookup; |
||
953 | } |
||
954 | |||
955 | public function newPropertyDataTypeLookup(): PropertyDataTypeLookup { |
||
956 | if ( $this->inFederatedPropertyMode() ) { |
||
957 | return $this->newFederatedPropertiesServiceFactory()->newApiPropertyDataTypeLookup(); |
||
958 | } |
||
959 | |||
960 | return $this->newPropertyDataTypeLookupForLocalProperties(); |
||
961 | } |
||
962 | |||
963 | private function newPropertyDataTypeLookupForLocalProperties(): PropertyDataTypeLookup { |
||
964 | $infoLookup = $this->getStore()->getPropertyInfoLookup(); |
||
965 | $retrievingLookup = new EntityRetrievingDataTypeLookup( $this->getEntityLookup() ); |
||
966 | return new PropertyInfoDataTypeLookup( |
||
967 | $infoLookup, |
||
968 | $this->getLogger(), |
||
969 | $retrievingLookup |
||
970 | ); |
||
971 | } |
||
972 | |||
973 | /** |
||
974 | * @return StringNormalizer |
||
975 | */ |
||
976 | public function getStringNormalizer() { |
||
977 | return $this->getWikibaseServices()->getStringNormalizer(); |
||
978 | } |
||
979 | |||
980 | /** |
||
981 | * @see Store::getEntityLookup |
||
982 | * |
||
983 | * @param string $cache One of Store::LOOKUP_CACHING_* |
||
984 | * Store::LOOKUP_CACHING_DISABLED to get an uncached direct lookup |
||
985 | * Store::LOOKUP_CACHING_RETRIEVE_ONLY to get a lookup which reads from the cache, but doesn't store retrieved entities |
||
986 | * Store::LOOKUP_CACHING_ENABLED to get a caching lookup (default) |
||
987 | * |
||
988 | * @param string $lookupMode One of the EntityRevisionLookup lookup mode constants |
||
989 | * TODO this should perhaps not refer to EntityRevisionLookup |
||
990 | * |
||
991 | * @return EntityLookup |
||
992 | */ |
||
993 | public function getEntityLookup( $cache = Store::LOOKUP_CACHING_ENABLED, $lookupMode = LookupConstants::LATEST_FROM_REPLICA ) { |
||
994 | return $this->getStore()->getEntityLookup( $cache, $lookupMode ); |
||
995 | } |
||
996 | |||
997 | public function getPropertyLookup( $cacheMode = Store::LOOKUP_CACHING_ENABLED ): PropertyLookup { |
||
998 | return new LegacyAdapterPropertyLookup( $this->getEntityLookup( $cacheMode ) ); |
||
999 | } |
||
1000 | |||
1001 | public function getItemLookup( $cacheMode = Store::LOOKUP_CACHING_ENABLED ): ItemLookup { |
||
1002 | return new LegacyAdapterItemLookup( $this->getEntityLookup( $cacheMode ) ); |
||
1003 | } |
||
1004 | |||
1005 | /** |
||
1006 | * @return SnakFactory |
||
1007 | */ |
||
1008 | public function getSnakFactory() { |
||
1009 | if ( $this->snakFactory === null ) { |
||
1010 | $this->snakFactory = new SnakFactory( |
||
1011 | $this->getPropertyDataTypeLookup(), |
||
1012 | $this->getDataTypeFactory(), |
||
1013 | $this->getDataValueFactory() |
||
1014 | ); |
||
1015 | } |
||
1016 | |||
1017 | return $this->snakFactory; |
||
1018 | } |
||
1019 | |||
1020 | /** |
||
1021 | * @return EntityIdParser |
||
1022 | */ |
||
1023 | public function getEntityIdParser() { |
||
1024 | if ( $this->entityIdParser === null ) { |
||
1025 | $this->entityIdParser = new DispatchingEntityIdParser( |
||
1026 | $this->entityTypeDefinitions->getEntityIdBuilders() |
||
1027 | ); |
||
1028 | } |
||
1029 | |||
1030 | return $this->entityIdParser; |
||
1031 | } |
||
1032 | |||
1033 | /** |
||
1034 | * @return EntityIdComposer |
||
1035 | */ |
||
1036 | public function getEntityIdComposer() { |
||
1037 | if ( $this->entityIdComposer === null ) { |
||
1038 | $this->entityIdComposer = new EntityIdComposer( |
||
1039 | $this->entityTypeDefinitions->get( EntityTypeDefinitions::ENTITY_ID_COMPOSER_CALLBACK ) |
||
1040 | ); |
||
1041 | } |
||
1042 | |||
1043 | return $this->entityIdComposer; |
||
1044 | } |
||
1045 | |||
1046 | /** |
||
1047 | * @return StatementGuidParser |
||
1048 | */ |
||
1049 | public function getStatementGuidParser() { |
||
1050 | return new StatementGuidParser( $this->getEntityIdParser() ); |
||
1051 | } |
||
1052 | |||
1053 | /** |
||
1054 | * @return ChangeOpFactoryProvider |
||
1055 | */ |
||
1056 | public function getChangeOpFactoryProvider() { |
||
1057 | $snakValidator = new SnakValidator( |
||
1058 | $this->getPropertyDataTypeLookup(), |
||
1059 | $this->getDataTypeFactory(), |
||
1060 | $this->getDataTypeValidatorFactory() |
||
1061 | ); |
||
1062 | |||
1063 | return new ChangeOpFactoryProvider( |
||
1064 | $this->getEntityConstraintProvider(), |
||
1065 | new GuidGenerator(), |
||
1066 | $this->getStatementGuidValidator(), |
||
1067 | $this->getStatementGuidParser(), |
||
1068 | $snakValidator, |
||
1069 | $this->getTermValidatorFactory(), |
||
1070 | $this->getSiteLookup(), |
||
1071 | array_keys( $this->settings->getSetting( 'badgeItems' ) ) |
||
1072 | ); |
||
1073 | } |
||
1074 | |||
1075 | public function getSiteLinkBadgeChangeOpSerializationValidator() { |
||
1076 | return new SiteLinkBadgeChangeOpSerializationValidator( |
||
1077 | $this->getEntityTitleLookup(), |
||
1078 | array_keys( $this->settings->getSetting( 'badgeItems' ) ) |
||
1079 | ); |
||
1080 | } |
||
1081 | |||
1082 | /** |
||
1083 | * @return EntityChangeOpProvider |
||
1084 | */ |
||
1085 | public function getEntityChangeOpProvider() { |
||
1086 | return new EntityChangeOpProvider( $this->entityTypeDefinitions->get( EntityTypeDefinitions::CHANGEOP_DESERIALIZER_CALLBACK ) ); |
||
1087 | } |
||
1088 | |||
1089 | /** |
||
1090 | * TODO: this should be probably cached? |
||
1091 | * |
||
1092 | * @return ChangeOpDeserializerFactory |
||
1093 | */ |
||
1094 | public function getChangeOpDeserializerFactory() { |
||
1095 | $changeOpFactoryProvider = $this->getChangeOpFactoryProvider(); |
||
1096 | |||
1097 | return new ChangeOpDeserializerFactory( |
||
1098 | $changeOpFactoryProvider->getFingerprintChangeOpFactory(), |
||
1099 | $changeOpFactoryProvider->getStatementChangeOpFactory(), |
||
1100 | $changeOpFactoryProvider->getSiteLinkChangeOpFactory(), |
||
1101 | new TermChangeOpSerializationValidator( $this->getTermsLanguages() ), |
||
1102 | $this->getSiteLinkBadgeChangeOpSerializationValidator(), |
||
1103 | $this->getExternalFormatStatementDeserializer(), |
||
1104 | new SiteLinkTargetProvider( |
||
1105 | $this->getSiteLookup(), |
||
1106 | $this->settings->getSetting( 'specialSiteLinkGroups' ) |
||
1107 | ), |
||
1108 | $this->getEntityIdParser(), |
||
1109 | $this->getStringNormalizer(), |
||
1110 | $this->settings->getSetting( 'siteLinkGroups' ) |
||
1111 | ); |
||
1112 | } |
||
1113 | |||
1114 | /** |
||
1115 | * @return LanguageFallbackChainFactory |
||
1116 | */ |
||
1117 | public function getLanguageFallbackChainFactory() { |
||
1118 | return $this->getWikibaseServices()->getLanguageFallbackChainFactory(); |
||
1119 | } |
||
1120 | |||
1121 | /** |
||
1122 | * @return LanguageFallbackLabelDescriptionLookupFactory |
||
1123 | */ |
||
1124 | public function getLanguageFallbackLabelDescriptionLookupFactory() { |
||
1125 | return new LanguageFallbackLabelDescriptionLookupFactory( |
||
1126 | $this->getLanguageFallbackChainFactory(), |
||
1127 | $this->getTermLookup(), |
||
1128 | $this->getTermBuffer() |
||
1129 | ); |
||
1130 | } |
||
1131 | |||
1132 | /** |
||
1133 | * @return StatementGuidValidator |
||
1134 | */ |
||
1135 | public function getStatementGuidValidator() { |
||
1136 | if ( $this->statementGuidValidator === null ) { |
||
1137 | $this->statementGuidValidator = new StatementGuidValidator( $this->getEntityIdParser() ); |
||
1138 | } |
||
1139 | |||
1140 | return $this->statementGuidValidator; |
||
1141 | } |
||
1142 | |||
1143 | /** |
||
1144 | * @return SettingsArray |
||
1145 | */ |
||
1146 | public function getSettings() { |
||
1147 | return $this->settings; |
||
1148 | } |
||
1149 | |||
1150 | public function newIdGenerator() : IdGenerator { |
||
1151 | if ( $this->getSettings()->getSetting( 'idGenerator' ) === 'original' ) { |
||
1152 | return new SqlIdGenerator( |
||
1153 | MediaWikiServices::getInstance()->getDBLoadBalancer(), |
||
1154 | $this->getSettings()->getSetting( 'reservedIds' ), |
||
0 ignored issues
–
show
|
|||
1155 | $this->getSettings()->getSetting( 'idGeneratorSeparateDbConnection' ) |
||
1156 | ); |
||
1157 | } |
||
1158 | |||
1159 | if ( $this->getSettings()->getSetting( 'idGenerator' ) === 'mysql-upsert' ) { |
||
1160 | // We could make sure the 'upsert' generator is only being used with mysql dbs here, |
||
1161 | // but perhaps that is an unnecessary check? People will realize when the DB query for |
||
1162 | // ID selection fails anyway... |
||
1163 | return new UpsertSqlIdGenerator( |
||
1164 | MediaWikiServices::getInstance()->getDBLoadBalancer(), |
||
1165 | $this->getSettings()->getSetting( 'reservedIds' ), |
||
0 ignored issues
–
show
$this->getSettings()->getSetting('reservedIds') is of type string , but the function expects a array<integer,array<integer,integer>> .
It seems like the type of the argument is not accepted by the function/method which you are calling. In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug. We suggest to add an explicit type cast like in the following example: function acceptsInteger($int) { }
$x = '123'; // string "123"
// Instead of
acceptsInteger($x);
// we recommend to use
acceptsInteger((integer) $x);
Loading history...
|
|||
1166 | $this->getSettings()->getSetting( 'idGeneratorSeparateDbConnection' ) |
||
1167 | ); |
||
1168 | } |
||
1169 | |||
1170 | throw new InvalidArgumentException( |
||
1171 | 'idGenerator config option must be either \'original\' or \'mysql-upsert\'' |
||
1172 | ); |
||
1173 | } |
||
1174 | |||
1175 | /** |
||
1176 | * @return Store |
||
1177 | */ |
||
1178 | public function getStore() { |
||
1179 | if ( $this->store === null ) { |
||
1180 | $localEntitySource = $this->getLocalEntitySource(); |
||
1181 | // TODO: the idea of local entity source seems not really suitable here. Store should probably |
||
1182 | // get source definitions and pass the right source/sources to services it creates accordingly |
||
1183 | // (as long as what it creates should not migrate to *SourceServices in the first place) |
||
1184 | |||
1185 | $this->store = new SqlStore( |
||
1186 | $this->getEntityChangeFactory(), |
||
1187 | $this->getEntityIdParser(), |
||
1188 | $this->getEntityIdComposer(), |
||
1189 | $this->getEntityIdLookup(), |
||
1190 | $this->getEntityTitleLookup(), |
||
1191 | $this->getEntityNamespaceLookup(), |
||
1192 | $this->newIdGenerator(), |
||
1193 | $this->getWikibaseServices(), |
||
1194 | $localEntitySource |
||
1195 | ); |
||
1196 | } |
||
1197 | |||
1198 | return $this->store; |
||
1199 | } |
||
1200 | |||
1201 | /** |
||
1202 | * @return EntitySource The entity source of the local repository |
||
1203 | */ |
||
1204 | public function getLocalEntitySource() : EntitySource { |
||
1205 | $localEntitySourceName = $this->settings->getSetting( 'localEntitySourceName' ); |
||
1206 | $sources = $this->entitySourceDefinitions->getSources(); |
||
1207 | foreach ( $sources as $source ) { |
||
1208 | if ( $source->getSourceName() === $localEntitySourceName ) { |
||
1209 | return $source; |
||
1210 | } |
||
1211 | } |
||
1212 | |||
1213 | throw new LogicException( 'No source configured: ' . $localEntitySourceName ); |
||
1214 | } |
||
1215 | |||
1216 | /** |
||
1217 | * Returns a OutputFormatSnakFormatterFactory the provides SnakFormatters |
||
1218 | * for different output formats. |
||
1219 | * |
||
1220 | * @return OutputFormatSnakFormatterFactory |
||
1221 | */ |
||
1222 | public function getSnakFormatterFactory() { |
||
1223 | if ( $this->snakFormatterFactory === null ) { |
||
1224 | $this->snakFormatterFactory = new OutputFormatSnakFormatterFactory( |
||
1225 | $this->dataTypeDefinitions->getSnakFormatterFactoryCallbacks(), |
||
1226 | $this->getValueFormatterFactory(), |
||
1227 | $this->getPropertyDataTypeLookup(), |
||
1228 | $this->getDataTypeFactory() |
||
1229 | ); |
||
1230 | } |
||
1231 | |||
1232 | return $this->snakFormatterFactory; |
||
1233 | } |
||
1234 | |||
1235 | /** |
||
1236 | * @return TermBuffer|AliasTermBuffer |
||
1237 | */ |
||
1238 | public function getTermBuffer() { |
||
1239 | return $this->getPrefetchingTermLookup(); |
||
1240 | } |
||
1241 | |||
1242 | /** |
||
1243 | * @return TermLookup |
||
1244 | */ |
||
1245 | public function getTermLookup() { |
||
1246 | return $this->getPrefetchingTermLookup(); |
||
1247 | } |
||
1248 | |||
1249 | /** |
||
1250 | * @return PrefetchingTermLookup |
||
1251 | */ |
||
1252 | public function getPrefetchingTermLookup() { |
||
1253 | return $this->getWikibaseServices()->getTermBuffer(); |
||
1254 | } |
||
1255 | |||
1256 | public function getItemUrlParser(): SuffixEntityIdParser { |
||
1257 | return new SuffixEntityIdParser( |
||
1258 | $this->getItemVocabularyBaseUri(), |
||
1259 | new ItemIdParser() |
||
1260 | ); |
||
1261 | } |
||
1262 | |||
1263 | private function getItemVocabularyBaseUri(): string { |
||
1264 | //@todo: We currently use the local repo concept URI here. This should be configurable, |
||
1265 | // to e.g. allow 3rd parties to use Wikidata as their vocabulary repo. |
||
1266 | return $this->getEntitySourceDefinitions() |
||
1267 | ->getSourceForEntityType( Item::ENTITY_TYPE ) |
||
1268 | ->getConceptBaseUri(); |
||
1269 | } |
||
1270 | |||
1271 | /** |
||
1272 | * Returns a OutputFormatValueFormatterFactory the provides ValueFormatters |
||
1273 | * for different output formats. |
||
1274 | * |
||
1275 | * @return OutputFormatValueFormatterFactory |
||
1276 | */ |
||
1277 | public function getValueFormatterFactory() { |
||
1278 | if ( $this->valueFormatterFactory === null ) { |
||
1279 | $this->valueFormatterFactory = $this->newValueFormatterFactory(); |
||
1280 | } |
||
1281 | |||
1282 | return $this->valueFormatterFactory; |
||
1283 | } |
||
1284 | |||
1285 | /** |
||
1286 | * @return OutputFormatValueFormatterFactory |
||
1287 | */ |
||
1288 | private function newValueFormatterFactory() { |
||
1289 | return new OutputFormatValueFormatterFactory( |
||
1290 | $this->dataTypeDefinitions->getFormatterFactoryCallbacks( DataTypeDefinitions::PREFIXED_MODE ), |
||
1291 | $this->getContentLanguage(), |
||
1292 | new LanguageFallbackChainFactory() |
||
1293 | ); |
||
1294 | } |
||
1295 | |||
1296 | /** |
||
1297 | * @return ValueSnakRdfBuilderFactory |
||
1298 | */ |
||
1299 | public function getValueSnakRdfBuilderFactory() { |
||
1300 | if ( $this->valueSnakRdfBuilderFactory === null ) { |
||
1301 | $this->valueSnakRdfBuilderFactory = new ValueSnakRdfBuilderFactory( |
||
1302 | $this->dataTypeDefinitions->getRdfBuilderFactoryCallbacks( DataTypeDefinitions::PREFIXED_MODE ) |
||
1303 | ); |
||
1304 | } |
||
1305 | |||
1306 | return $this->valueSnakRdfBuilderFactory; |
||
1307 | } |
||
1308 | |||
1309 | /** |
||
1310 | * @return RdfVocabulary |
||
1311 | */ |
||
1312 | public function getRdfVocabulary() { |
||
1313 | global $wgDummyLanguageCodes; |
||
1314 | |||
1315 | if ( $this->rdfVocabulary === null ) { |
||
1316 | $languageCodes = array_merge( |
||
1317 | $wgDummyLanguageCodes, |
||
1318 | $this->settings->getSetting( 'canonicalLanguageCodes' ) |
||
1319 | ); |
||
1320 | |||
1321 | $localEntitySourceName = $this->getLocalEntitySource()->getSourceName(); |
||
1322 | $nodeNamespacePrefixes = $this->entitySourceDefinitions->getRdfNodeNamespacePrefixes(); |
||
1323 | $predicateNamespacePrefixes = $this->entitySourceDefinitions->getRdfPredicateNamespacePrefixes(); |
||
1324 | |||
1325 | $this->rdfVocabulary = new RdfVocabulary( |
||
1326 | $this->entitySourceDefinitions->getConceptBaseUris(), |
||
1327 | $this->getCanonicalDocumentUrls(), |
||
1328 | $this->entitySourceDefinitions, |
||
1329 | $localEntitySourceName, |
||
1330 | $nodeNamespacePrefixes, |
||
1331 | $predicateNamespacePrefixes, |
||
1332 | $languageCodes, |
||
1333 | $this->dataTypeDefinitions->getRdfTypeUris(), |
||
1334 | $this->settings->getSetting( 'pagePropertiesRdf' ) ?: [], |
||
1335 | $this->getSettings()->getSetting( 'rdfDataRightsUrl' ) |
||
1336 | ); |
||
1337 | } |
||
1338 | |||
1339 | return $this->rdfVocabulary; |
||
1340 | } |
||
1341 | |||
1342 | private function getCanonicalDocumentUrls() { |
||
1343 | $urlProvider = new EntitySourceDocumentUrlProvider(); |
||
1344 | |||
1345 | return $urlProvider->getCanonicalDocumentsUrls( $this->entitySourceDefinitions ); |
||
1346 | } |
||
1347 | |||
1348 | /** |
||
1349 | * @return ExceptionLocalizer |
||
1350 | */ |
||
1351 | public function getExceptionLocalizer() { |
||
1352 | if ( $this->exceptionLocalizer === null ) { |
||
1353 | $formatter = $this->getMessageParameterFormatter(); |
||
1354 | $localizers = $this->getExceptionLocalizers( $formatter ); |
||
1355 | |||
1356 | $this->exceptionLocalizer = new DispatchingExceptionLocalizer( $localizers ); |
||
1357 | } |
||
1358 | |||
1359 | return $this->exceptionLocalizer; |
||
1360 | } |
||
1361 | |||
1362 | /** |
||
1363 | * @param ValueFormatter $formatter |
||
1364 | * |
||
1365 | * @return ExceptionLocalizer[] |
||
1366 | */ |
||
1367 | private function getExceptionLocalizers( ValueFormatter $formatter ) { |
||
1368 | return [ |
||
1369 | 'MessageException' => new MessageExceptionLocalizer(), |
||
1370 | 'ParseException' => new ParseExceptionLocalizer(), |
||
1371 | 'ChangeOpValidationException' => new ChangeOpValidationExceptionLocalizer( $formatter ), |
||
1372 | 'ChangeOpDeserializationException' => new ChangeOpDeserializationExceptionLocalizer(), |
||
1373 | 'ChangeOpApplyException' => new ChangeOpApplyExceptionLocalizer(), |
||
1374 | 'Exception' => new GenericExceptionLocalizer() |
||
1375 | ]; |
||
1376 | } |
||
1377 | |||
1378 | /** |
||
1379 | * @return SummaryFormatter |
||
1380 | */ |
||
1381 | public function getSummaryFormatter() { |
||
1382 | if ( $this->summaryFormatter === null ) { |
||
1383 | $this->summaryFormatter = $this->newSummaryFormatter(); |
||
1384 | } |
||
1385 | |||
1386 | return $this->summaryFormatter; |
||
1387 | } |
||
1388 | |||
1389 | /** |
||
1390 | * @return SummaryFormatter |
||
1391 | */ |
||
1392 | private function newSummaryFormatter() { |
||
1393 | // This needs to use an EntityIdPlainLinkFormatter as we want to mangle |
||
1394 | // the links created in HtmlPageLinkRendererEndHookHandler afterwards (the links must not |
||
1395 | // contain a display text: [[Item:Q1]] is fine but [[Item:Q1|Q1]] isn't). |
||
1396 | $idFormatter = new EntityIdPlainLinkFormatter( $this->getEntityTitleLookup() ); |
||
1397 | |||
1398 | // Create a new ValueFormatterFactory, and override the formatter for entity IDs. |
||
1399 | $valueFormatterFactory = $this->newValueFormatterFactory(); |
||
1400 | |||
1401 | // Iterate through all defined entity types |
||
1402 | foreach ( $this->entityTypeDefinitions->getEntityTypes() as $entityType ) { |
||
1403 | $valueFormatterFactory->setFormatterFactoryCallback( |
||
1404 | "PT:wikibase-$entityType", |
||
1405 | function ( $format, FormatterOptions $options ) use ( $idFormatter ) { |
||
1406 | if ( $format === SnakFormatter::FORMAT_PLAIN ) { |
||
1407 | return new EntityIdValueFormatter( $idFormatter ); |
||
1408 | } else { |
||
1409 | return null; |
||
1410 | } |
||
1411 | } |
||
1412 | ); |
||
1413 | } |
||
1414 | |||
1415 | // Create a new SnakFormatterFactory based on the specialized ValueFormatterFactory. |
||
1416 | $snakFormatterFactory = new OutputFormatSnakFormatterFactory( |
||
1417 | [], // XXX: do we want $this->dataTypeDefinitions->getSnakFormatterFactoryCallbacks() |
||
1418 | $valueFormatterFactory, |
||
1419 | $this->getPropertyDataTypeLookup(), |
||
1420 | $this->getDataTypeFactory() |
||
1421 | ); |
||
1422 | |||
1423 | $options = new FormatterOptions(); |
||
1424 | $snakFormatter = $snakFormatterFactory->getSnakFormatter( |
||
1425 | SnakFormatter::FORMAT_PLAIN, |
||
1426 | $options |
||
1427 | ); |
||
1428 | $valueFormatter = $valueFormatterFactory->getValueFormatter( |
||
1429 | SnakFormatter::FORMAT_PLAIN, |
||
1430 | $options |
||
1431 | ); |
||
1432 | |||
1433 | $formatter = new SummaryFormatter( |
||
1434 | $idFormatter, |
||
1435 | $valueFormatter, |
||
1436 | $snakFormatter, |
||
1437 | $this->getContentLanguage(), |
||
1438 | $this->getEntityIdParser() |
||
1439 | ); |
||
1440 | |||
1441 | return $formatter; |
||
1442 | } |
||
1443 | |||
1444 | /** |
||
1445 | * @return EntityPermissionChecker |
||
1446 | */ |
||
1447 | public function getEntityPermissionChecker() { |
||
1448 | global $wgAvailableRights; |
||
1449 | |||
1450 | return new WikiPageEntityStorePermissionChecker( |
||
1451 | $this->getEntityNamespaceLookup(), |
||
1452 | $this->getEntityTitleLookup(), |
||
1453 | MediaWikiServices::getInstance()->getPermissionManager(), |
||
1454 | $wgAvailableRights |
||
1455 | ); |
||
1456 | } |
||
1457 | |||
1458 | /** |
||
1459 | * @return TermValidatorFactory |
||
1460 | */ |
||
1461 | public function getTermValidatorFactory() { |
||
1462 | // Use the old deprecated setting if it exists |
||
1463 | if ( $this->settings->hasSetting( 'multilang-limits' ) ) { |
||
1464 | $constraints = $this->settings->getSetting( 'multilang-limits' ); |
||
1465 | } else { |
||
1466 | $constraints = $this->settings->getSetting( 'string-limits' )['multilang']; |
||
1467 | } |
||
1468 | |||
1469 | $maxLength = $constraints['length']; |
||
1470 | |||
1471 | $languages = $this->getTermsLanguages()->getLanguages(); |
||
1472 | |||
1473 | return new TermValidatorFactory( |
||
1474 | $maxLength, |
||
1475 | $languages, |
||
1476 | $this->getEntityIdParser(), |
||
1477 | $this->getTermsCollisionDetectorFactory(), |
||
1478 | $this->getTermLookup() |
||
1479 | ); |
||
1480 | } |
||
1481 | |||
1482 | public function getTermsCollisionDetectorFactory() { |
||
1483 | $loadBalancerFactory = MediaWikiServices::getInstance()->getDBLoadBalancerFactory(); |
||
1484 | $loadBalancer = $loadBalancerFactory->getMainLB(); |
||
1485 | $typeIdsStore = new DatabaseTypeIdsStore( |
||
1486 | $loadBalancer, |
||
1487 | MediaWikiServices::getInstance()->getMainWANObjectCache() |
||
1488 | ); |
||
1489 | |||
1490 | return new TermsCollisionDetectorFactory( |
||
1491 | $loadBalancer, |
||
1492 | $typeIdsStore |
||
1493 | ); |
||
1494 | } |
||
1495 | |||
1496 | public function getPropertyTermsCollisionDetector() { |
||
1497 | return $this->getTermsCollisionDetectorFactory()->getTermsCollisionDetector( Property::ENTITY_TYPE ); |
||
1498 | } |
||
1499 | |||
1500 | public function getItemTermsCollisionDetector() { |
||
1501 | return $this->getTermsCollisionDetectorFactory()->getTermsCollisionDetector( Item::ENTITY_TYPE ); |
||
1502 | } |
||
1503 | |||
1504 | /** |
||
1505 | * @return EntityConstraintProvider |
||
1506 | */ |
||
1507 | public function getEntityConstraintProvider() { |
||
1508 | return new EntityConstraintProvider( |
||
1509 | $this->getStore()->getSiteLinkConflictLookup() |
||
1510 | ); |
||
1511 | } |
||
1512 | |||
1513 | /** |
||
1514 | * @return ValidatorErrorLocalizer |
||
1515 | */ |
||
1516 | public function getValidatorErrorLocalizer() { |
||
1517 | return new ValidatorErrorLocalizer( $this->getMessageParameterFormatter() ); |
||
1518 | } |
||
1519 | |||
1520 | /** |
||
1521 | * @return SiteLookup |
||
1522 | */ |
||
1523 | public function getSiteLookup() { |
||
1524 | return MediaWikiServices::getInstance()->getSiteLookup(); |
||
1525 | } |
||
1526 | |||
1527 | /** |
||
1528 | * Returns a ValueFormatter suitable for converting message parameters to wikitext. |
||
1529 | * The formatter is most likely implemented to dispatch to different formatters internally, |
||
1530 | * based on the type of the parameter. |
||
1531 | * |
||
1532 | * @return ValueFormatter |
||
1533 | */ |
||
1534 | private function getMessageParameterFormatter() { |
||
1535 | $formatterOptions = new FormatterOptions(); |
||
1536 | $valueFormatterFactory = $this->getValueFormatterFactory(); |
||
1537 | |||
1538 | return new MessageParameterFormatter( |
||
1539 | $valueFormatterFactory->getValueFormatter( SnakFormatter::FORMAT_WIKI, $formatterOptions ), |
||
1540 | new EntityIdLinkFormatter( $this->getEntityTitleLookup() ), |
||
1541 | $this->getSiteLookup(), |
||
1542 | $this->getUserLanguage() |
||
1543 | ); |
||
1544 | } |
||
1545 | |||
1546 | /** |
||
1547 | * @return ChangeNotifier |
||
1548 | */ |
||
1549 | public function getChangeNotifier() { |
||
1550 | $transmitters = [ |
||
1551 | new HookChangeTransmitter( 'WikibaseChangeNotification' ), |
||
1552 | ]; |
||
1553 | |||
1554 | if ( $this->settings->getSetting( 'useChangesTable' ) ) { |
||
1555 | $transmitters[] = new DatabaseChangeTransmitter( $this->getStore()->getChangeStore() ); |
||
1556 | } |
||
1557 | |||
1558 | return new ChangeNotifier( |
||
1559 | $this->getEntityChangeFactory(), |
||
1560 | $transmitters, |
||
1561 | CentralIdLookup::factoryNonLocal() |
||
1562 | ); |
||
1563 | } |
||
1564 | |||
1565 | /** |
||
1566 | * Get the mapping of entity types => content models |
||
1567 | * |
||
1568 | * @return array |
||
1569 | */ |
||
1570 | public function getContentModelMappings() { |
||
1571 | $map = $this->entityTypeDefinitions->get( EntityTypeDefinitions::CONTENT_MODEL_ID ); |
||
1572 | |||
1573 | Hooks::run( 'WikibaseContentModelMapping', [ &$map ] ); |
||
1574 | |||
1575 | return $map; |
||
1576 | } |
||
1577 | |||
1578 | /** |
||
1579 | * @return EntityFactory |
||
1580 | */ |
||
1581 | public function getEntityFactory() { |
||
1582 | $instantiators = $this->entityTypeDefinitions->get( EntityTypeDefinitions::ENTITY_FACTORY_CALLBACK ); |
||
1583 | |||
1584 | return new EntityFactory( $instantiators ); |
||
1585 | } |
||
1586 | |||
1587 | /** |
||
1588 | * @return string[] List of entity type identifiers (typically "item" and "property") |
||
1589 | * that are configured in WikibaseRepo.entitytypes.php and enabled via the |
||
1590 | * $wgWBRepoSettings['entityNamespaces'] setting. |
||
1591 | * This list will also include any sub entity types of entity types defined in $wgWBRepoSettings['entityNamespaces']. |
||
1592 | * Optionally the list also contains entity types from the configured foreign repositories. |
||
1593 | */ |
||
1594 | public function getEnabledEntityTypes() { |
||
1595 | $types = array_keys( $this->entitySourceDefinitions->getEntityTypeToSourceMapping() ); |
||
1596 | $subEntityTypes = $this->entityTypeDefinitions->get( EntityTypeDefinitions::SUB_ENTITY_TYPES ); |
||
1597 | |||
1598 | return array_reduce( |
||
1599 | $types, |
||
1600 | function ( $carry, $x ) use ( $subEntityTypes ) { |
||
1601 | $carry[] = $x; |
||
1602 | if ( array_key_exists( $x, $subEntityTypes ) ) { |
||
1603 | $carry = array_merge( $carry, $subEntityTypes[$x] ); |
||
1604 | } |
||
1605 | return $carry; |
||
1606 | }, |
||
1607 | [] |
||
1608 | ); |
||
1609 | } |
||
1610 | |||
1611 | /** |
||
1612 | * @return string[] List of entity type identifiers (typically "item" and "property") |
||
1613 | * that are configured in WikibaseRepo.entitytypes.php and enabled via the |
||
1614 | * $wgWBRepoSettings['entityNamespaces'] setting. |
||
1615 | * This list will also include any sub entity types of entity types defined in $wgWBRepoSettings['entityNamespaces']. |
||
1616 | */ |
||
1617 | public function getLocalEntityTypes() { |
||
1618 | $localSource = $this->getLocalEntitySource(); |
||
1619 | $types = $localSource->getEntityTypes(); |
||
1620 | $subEntityTypes = $this->entityTypeDefinitions->get( EntityTypeDefinitions::SUB_ENTITY_TYPES ); |
||
1621 | |||
1622 | return array_reduce( |
||
1623 | $types, |
||
1624 | function ( $carry, $x ) use ( $subEntityTypes ) { |
||
1625 | $carry[] = $x; |
||
1626 | if ( array_key_exists( $x, $subEntityTypes ) ) { |
||
1627 | $carry = array_merge( $carry, $subEntityTypes[$x] ); |
||
1628 | } |
||
1629 | return $carry; |
||
1630 | }, |
||
1631 | [] |
||
1632 | ); |
||
1633 | } |
||
1634 | |||
1635 | /** |
||
1636 | * @return EntityContentDataCodec |
||
1637 | */ |
||
1638 | public function getEntityContentDataCodec() { |
||
1639 | return new EntityContentDataCodec( |
||
1640 | $this->getEntityIdParser(), |
||
1641 | $this->getStorageEntitySerializer(), |
||
1642 | $this->getInternalFormatEntityDeserializer(), |
||
1643 | $this->settings->getSetting( 'maxSerializedEntitySize' ) * 1024 |
||
1644 | ); |
||
1645 | } |
||
1646 | |||
1647 | /** |
||
1648 | * @return DeserializerFactory A factory with knowledge about items, properties, and the |
||
1649 | * elements they are made of, but no other entity types. |
||
1650 | */ |
||
1651 | public function getBaseDataModelDeserializerFactory() { |
||
1652 | return new DeserializerFactory( |
||
1653 | $this->getDataValueDeserializer(), |
||
1654 | $this->getEntityIdParser() |
||
1655 | ); |
||
1656 | } |
||
1657 | |||
1658 | /** |
||
1659 | * @return InternalDeserializerFactory |
||
1660 | */ |
||
1661 | private function getInternalFormatDeserializerFactory() { |
||
1662 | return new InternalDeserializerFactory( |
||
1663 | $this->getDataValueDeserializer(), |
||
1664 | $this->getEntityIdParser(), |
||
1665 | $this->getAllTypesEntityDeserializer() |
||
1666 | ); |
||
1667 | } |
||
1668 | |||
1669 | /** |
||
1670 | * @return SerializerFactory A factory with knowledge about items, properties, and the elements |
||
1671 | * they are made of, but no other entity types. Returns serializers that generate the full |
||
1672 | * (expanded) serialization. |
||
1673 | */ |
||
1674 | public function getBaseDataModelSerializerFactory() { |
||
1675 | return $this->getWikibaseServices()->getBaseDataModelSerializerFactory(); |
||
1676 | } |
||
1677 | |||
1678 | /** |
||
1679 | * @return SerializerFactory A factory with knowledge about items, properties, and the elements |
||
1680 | * they are made of, but no other entity types. Returns serializers that generate the most |
||
1681 | * compact serialization. |
||
1682 | */ |
||
1683 | public function getCompactBaseDataModelSerializerFactory() { |
||
1684 | return $this->getWikibaseServices()->getCompactBaseDataModelSerializerFactory(); |
||
1685 | } |
||
1686 | |||
1687 | /** |
||
1688 | * Returns a deserializer to deserialize entities in current serialization only. |
||
1689 | * |
||
1690 | * @return DispatchableDeserializer |
||
1691 | */ |
||
1692 | private function getAllTypesEntityDeserializer() { |
||
1693 | if ( $this->entityDeserializer === null ) { |
||
1694 | $deserializerFactoryCallbacks = $this->entityTypeDefinitions->get( EntityTypeDefinitions::DESERIALIZER_FACTORY_CALLBACK ); |
||
1695 | $baseDeserializerFactory = $this->getBaseDataModelDeserializerFactory(); |
||
1696 | $deserializers = []; |
||
1697 | |||
1698 | foreach ( $deserializerFactoryCallbacks as $callback ) { |
||
1699 | $deserializers[] = call_user_func( $callback, $baseDeserializerFactory ); |
||
1700 | } |
||
1701 | |||
1702 | $this->entityDeserializer = new DispatchingDeserializer( $deserializers ); |
||
1703 | } |
||
1704 | |||
1705 | return $this->entityDeserializer; |
||
1706 | } |
||
1707 | |||
1708 | /** |
||
1709 | * Returns a deserializer to deserialize entities in both current and legacy serialization. |
||
1710 | * |
||
1711 | * @return Deserializer |
||
1712 | */ |
||
1713 | public function getInternalFormatEntityDeserializer() { |
||
1714 | return $this->getInternalFormatDeserializerFactory()->newEntityDeserializer(); |
||
1715 | } |
||
1716 | |||
1717 | /** |
||
1718 | * @return Serializer Entity serializer that generates the full (expanded) serialization. |
||
1719 | */ |
||
1720 | public function getAllTypesEntitySerializer() { |
||
1721 | return $this->getWikibaseServices()->getFullEntitySerializer(); |
||
1722 | } |
||
1723 | |||
1724 | /** |
||
1725 | * @return Serializer Entity serializer that generates the most compact serialization. |
||
1726 | */ |
||
1727 | public function getCompactEntitySerializer() { |
||
1728 | return $this->getWikibaseServices()->getCompactEntitySerializer(); |
||
1729 | } |
||
1730 | |||
1731 | /** |
||
1732 | * Returns the entity serializer that generates serialization that is used in the storage layer. |
||
1733 | * |
||
1734 | * @return Serializer |
||
1735 | */ |
||
1736 | public function getStorageEntitySerializer() { |
||
1737 | return $this->getWikibaseServices()->getStorageEntitySerializer(); |
||
1738 | } |
||
1739 | |||
1740 | /** |
||
1741 | * Returns a deserializer to deserialize statements in both current and legacy serialization. |
||
1742 | * |
||
1743 | * @return Deserializer |
||
1744 | */ |
||
1745 | public function getInternalFormatStatementDeserializer() { |
||
1746 | return $this->getInternalFormatDeserializerFactory()->newStatementDeserializer(); |
||
1747 | } |
||
1748 | |||
1749 | /** |
||
1750 | * Returns a deserializer to deserialize statements in current serialization only. |
||
1751 | * |
||
1752 | * @return Deserializer |
||
1753 | */ |
||
1754 | public function getExternalFormatStatementDeserializer() { |
||
1755 | return $this->getBaseDataModelDeserializerFactory()->newStatementDeserializer(); |
||
1756 | } |
||
1757 | |||
1758 | /** |
||
1759 | * @return Serializer |
||
1760 | */ |
||
1761 | public function getStatementSerializer() { |
||
1762 | return $this->getBaseDataModelSerializerFactory()->newStatementSerializer(); |
||
1763 | } |
||
1764 | |||
1765 | /** |
||
1766 | * @return DataValueDeserializer |
||
1767 | */ |
||
1768 | private function getDataValueDeserializer() { |
||
1769 | return new DataValueDeserializer( [ |
||
1770 | 'string' => StringValue::class, |
||
1771 | 'unknown' => UnknownValue::class, |
||
1772 | 'globecoordinate' => GlobeCoordinateValue::class, |
||
1773 | 'monolingualtext' => MonolingualTextValue::class, |
||
1774 | 'quantity' => QuantityValue::class, |
||
1775 | 'time' => TimeValue::class, |
||
1776 | 'wikibase-entityid' => function ( $value ) { |
||
1777 | // TODO this should perhaps be factored out into a class |
||
1778 | if ( isset( $value['id'] ) ) { |
||
1779 | try { |
||
1780 | return new EntityIdValue( $this->getEntityIdParser()->parse( $value['id'] ) ); |
||
1781 | } catch ( EntityIdParsingException $parsingException ) { |
||
1782 | throw new InvalidArgumentException( |
||
1783 | 'Can not parse id \'' . $value['id'] . '\' to build EntityIdValue with', |
||
1784 | 0, |
||
1785 | $parsingException |
||
1786 | ); |
||
1787 | } |
||
1788 | } else { |
||
1789 | return EntityIdValue::newFromArray( $value ); |
||
1790 | } |
||
1791 | }, |
||
1792 | ] ); |
||
1793 | } |
||
1794 | |||
1795 | public function newItemHandler(): ItemHandler { |
||
1796 | $codec = $this->getEntityContentDataCodec(); |
||
1797 | $constraintProvider = $this->getEntityConstraintProvider(); |
||
1798 | $errorLocalizer = $this->getValidatorErrorLocalizer(); |
||
1799 | $siteLinkStore = $this->getStore()->newSiteLinkStore(); |
||
1800 | $legacyFormatDetector = $this->getLegacyFormatDetectorCallback(); |
||
1801 | |||
1802 | return new ItemHandler( |
||
1803 | $this->getItemTermStoreWriter(), |
||
1804 | $codec, |
||
1805 | $constraintProvider, |
||
1806 | $errorLocalizer, |
||
1807 | $this->getEntityIdParser(), |
||
1808 | $siteLinkStore, |
||
1809 | $this->getEntityIdLookup(), |
||
1810 | $this->getLanguageFallbackLabelDescriptionLookupFactory(), |
||
1811 | $this->getFieldDefinitionsByType( Item::ENTITY_TYPE ), |
||
1812 | $this->getPropertyDataTypeLookup(), |
||
1813 | $legacyFormatDetector |
||
1814 | ); |
||
1815 | } |
||
1816 | |||
1817 | public function getPropertyTermStoreWriter(): EntityTermStoreWriter { |
||
1818 | if ( !in_array( Property::ENTITY_TYPE, $this->getLocalEntitySource()->getEntityTypes() ) ) { |
||
1819 | return new ThrowingEntityTermStoreWriter(); |
||
1820 | } |
||
1821 | |||
1822 | return new PropertyTermStoreWriterAdapter( $this->getNewTermStoreWriterFactory()->newPropertyTermStoreWriter() ); |
||
1823 | } |
||
1824 | |||
1825 | public function getItemTermStoreWriter(): EntityTermStoreWriter { |
||
1826 | if ( !in_array( Item::ENTITY_TYPE, $this->getLocalEntitySource()->getEntityTypes() ) ) { |
||
1827 | return new ThrowingEntityTermStoreWriter(); |
||
1828 | } |
||
1829 | |||
1830 | return new ItemTermStoreWriterAdapter( $this->getNewTermStoreWriterFactory()->newItemTermStoreWriter() ); |
||
1831 | } |
||
1832 | |||
1833 | public function getNewTermStoreWriterFactory(): TermStoreWriterFactory { |
||
1834 | return new TermStoreWriterFactory( |
||
1835 | $this->getLocalEntitySource(), |
||
1836 | $this->getStringNormalizer(), |
||
1837 | MediaWikiServices::getInstance()->getDBLoadBalancerFactory(), |
||
1838 | MediaWikiServices::getInstance()->getMainWANObjectCache(), |
||
1839 | JobQueueGroup::singleton(), |
||
1840 | $this->getLogger() |
||
1841 | ); |
||
1842 | } |
||
1843 | |||
1844 | /** |
||
1845 | * Get field definitions for entity depending on its type. |
||
1846 | * @param string $type Entity type |
||
1847 | * @return FieldDefinitions |
||
1848 | */ |
||
1849 | public function getFieldDefinitionsByType( $type ) { |
||
1850 | $definitions = $this->entityTypeDefinitions->get( EntityTypeDefinitions::SEARCH_FIELD_DEFINITIONS ); |
||
1851 | if ( isset( $definitions[$type] ) && is_callable( $definitions[$type] ) ) { |
||
1852 | return call_user_func( $definitions[$type], $this->getTermsLanguages()->getLanguages(), |
||
1853 | $this->settings ); |
||
1854 | } |
||
1855 | return new NoFieldDefinitions(); |
||
1856 | } |
||
1857 | |||
1858 | public function newPropertyHandler(): PropertyHandler { |
||
1859 | $codec = $this->getEntityContentDataCodec(); |
||
1860 | $constraintProvider = $this->getEntityConstraintProvider(); |
||
1861 | $errorLocalizer = $this->getValidatorErrorLocalizer(); |
||
1862 | $propertyInfoStore = $this->getStore()->getPropertyInfoStore(); |
||
1863 | $propertyInfoBuilder = $this->newPropertyInfoBuilder(); |
||
1864 | $legacyFormatDetector = $this->getLegacyFormatDetectorCallback(); |
||
1865 | |||
1866 | return new PropertyHandler( |
||
1867 | $this->getPropertyTermStoreWriter(), |
||
1868 | $codec, |
||
1869 | $constraintProvider, |
||
1870 | $errorLocalizer, |
||
1871 | $this->getEntityIdParser(), |
||
1872 | $this->getEntityIdLookup(), |
||
1873 | $this->getLanguageFallbackLabelDescriptionLookupFactory(), |
||
1874 | $propertyInfoStore, |
||
1875 | $propertyInfoBuilder, |
||
1876 | $this->getFieldDefinitionsByType( Property::ENTITY_TYPE ), |
||
1877 | $legacyFormatDetector |
||
1878 | ); |
||
1879 | } |
||
1880 | |||
1881 | /** |
||
1882 | * @return PropertyInfoBuilder |
||
1883 | */ |
||
1884 | public function newPropertyInfoBuilder() { |
||
1885 | $propertyIdMap = []; |
||
1886 | |||
1887 | $formatterUrlProperty = $this->settings->getSetting( 'formatterUrlProperty' ); |
||
1888 | if ( $formatterUrlProperty !== null ) { |
||
1889 | $propertyIdMap[PropertyInfoLookup::KEY_FORMATTER_URL] = new PropertyId( |
||
1890 | $formatterUrlProperty |
||
1891 | ); |
||
1892 | } |
||
1893 | |||
1894 | $canonicalUriProperty = $this->settings->getSetting( 'canonicalUriProperty' ); |
||
1895 | if ( $canonicalUriProperty !== null ) { |
||
1896 | $propertyIdMap[PropertyInfoStore::KEY_CANONICAL_URI] = new PropertyId( $canonicalUriProperty ); |
||
1897 | } |
||
1898 | |||
1899 | return new PropertyInfoBuilder( $propertyIdMap ); |
||
1900 | } |
||
1901 | |||
1902 | private function getLegacyFormatDetectorCallback() { |
||
1903 | $transformOnExport = $this->settings->getSetting( 'transformLegacyFormatOnExport' ); |
||
1904 | |||
1905 | if ( !$transformOnExport ) { |
||
1906 | return null; |
||
1907 | } |
||
1908 | |||
1909 | /** |
||
1910 | * Detects blobs that may be using a legacy serialization format. |
||
1911 | * WikibaseRepo uses this for the $legacyExportFormatDetector parameter |
||
1912 | * when constructing EntityHandlers. |
||
1913 | * |
||
1914 | * @see WikibaseRepo::newItemHandler |
||
1915 | * @see WikibaseRepo::newPropertyHandler |
||
1916 | * @see EntityHandler::__construct |
||
1917 | * |
||
1918 | * @note: False positives (detecting a legacy format when really no legacy format was used) |
||
1919 | * are acceptable, false negatives (failing to detect a legacy format when one was used) |
||
1920 | * are not acceptable. |
||
1921 | * |
||
1922 | * @param string $blob |
||
1923 | * @param string $format |
||
1924 | * |
||
1925 | * @return bool True if $blob seems to be using a legacy serialization format. |
||
1926 | */ |
||
1927 | return function ( $blob, $format ) { |
||
1928 | // The legacy serialization uses something like "entity":["item",21] or |
||
1929 | // even "entity":"p21" for the entity ID. |
||
1930 | return preg_match( '/"entity"\s*:/', $blob ) > 0; |
||
1931 | }; |
||
1932 | } |
||
1933 | |||
1934 | /** |
||
1935 | * @param IContextSource $context |
||
1936 | * |
||
1937 | * @return ApiHelperFactory |
||
1938 | */ |
||
1939 | public function getApiHelperFactory( IContextSource $context ) { |
||
1940 | return new ApiHelperFactory( |
||
1941 | $this->getEntityTitleLookup(), |
||
1942 | $this->getExceptionLocalizer(), |
||
1943 | $this->getPropertyDataTypeLookup(), |
||
1944 | $this->getSiteLookup(), |
||
1945 | $this->getSummaryFormatter(), |
||
1946 | $this->getEntityRevisionLookup( Store::LOOKUP_CACHING_DISABLED ), |
||
1947 | $this->newEditEntityFactory( $context ), |
||
1948 | $this->getBaseDataModelSerializerFactory(), |
||
1949 | $this->getAllTypesEntitySerializer(), |
||
1950 | $this->getEntityIdParser(), |
||
1951 | MediaWikiServices::getInstance()->getPermissionManager(), |
||
1952 | $this->getStore()->getEntityByLinkedTitleLookup(), |
||
1953 | $this->getEntityFactory(), |
||
1954 | $this->getEntityStore() |
||
1955 | ); |
||
1956 | } |
||
1957 | |||
1958 | /** |
||
1959 | * @param IContextSource|null $context |
||
1960 | * |
||
1961 | * @return MediawikiEditEntityFactory |
||
1962 | */ |
||
1963 | public function newEditEntityFactory( IContextSource $context = null ) { |
||
1964 | return new MediawikiEditEntityFactory( |
||
1965 | $this->getEntityTitleLookup(), |
||
1966 | $this->getEntityRevisionLookup( Store::LOOKUP_CACHING_DISABLED ), |
||
1967 | $this->getEntityStore(), |
||
1968 | $this->getEntityPermissionChecker(), |
||
1969 | $this->getEntityDiffer(), |
||
1970 | $this->getEntityPatcher(), |
||
1971 | $this->newEditFilterHookRunner( $context ?: RequestContext::getMain() ), |
||
1972 | MediaWikiServices::getInstance()->getStatsdDataFactory(), |
||
1973 | $this->getSettings()->getSetting( 'maxSerializedEntitySize' ) |
||
1974 | ); |
||
1975 | } |
||
1976 | |||
1977 | /** |
||
1978 | * @param IContextSource $context |
||
1979 | * |
||
1980 | * @return ItemMergeInteractor |
||
1981 | */ |
||
1982 | public function newItemMergeInteractor( IContextSource $context ) { |
||
1983 | $user = $context->getUser(); |
||
1984 | |||
1985 | return new ItemMergeInteractor( |
||
1986 | $this->getChangeOpFactoryProvider()->getMergeFactory(), |
||
1987 | $this->getEntityRevisionLookup( Store::LOOKUP_CACHING_DISABLED ), |
||
1988 | $this->getEntityStore(), |
||
1989 | $this->getEntityPermissionChecker(), |
||
1990 | $this->getSummaryFormatter(), |
||
1991 | $user, |
||
1992 | $this->newItemRedirectCreationInteractor( $user, $context ), |
||
1993 | $this->getEntityTitleLookup(), |
||
1994 | MediaWikiServices::getInstance()->getPermissionManager() |
||
1995 | ); |
||
1996 | } |
||
1997 | |||
1998 | /** |
||
1999 | * @return int[] An array mapping entity type identifiers to namespace numbers. |
||
2000 | */ |
||
2001 | public function getLocalEntityNamespaces() { |
||
2002 | return $this->settings->getSetting( 'entityNamespaces' ); |
||
2003 | } |
||
2004 | |||
2005 | /** |
||
2006 | * @return EntityNamespaceLookup |
||
2007 | */ |
||
2008 | public function getEntityNamespaceLookup() { |
||
2009 | return $this->getWikibaseServices()->getEntityNamespaceLookup(); |
||
2010 | } |
||
2011 | |||
2012 | public function getLocalEntityNamespaceLookup(): EntityNamespaceLookup { |
||
2013 | $localEntitySource = $this->getLocalEntitySource(); |
||
2014 | $nsIds = $localEntitySource->getEntityNamespaceIds(); |
||
2015 | $entitySlots = $localEntitySource->getEntitySlotNames(); |
||
2016 | |||
2017 | return new EntityNamespaceLookup( $nsIds, $entitySlots ); |
||
2018 | } |
||
2019 | |||
2020 | /** |
||
2021 | * @return EntityIdFormatterFactory |
||
2022 | */ |
||
2023 | public function getEntityIdHtmlLinkFormatterFactory() { |
||
2024 | $factory = new EntityIdHtmlLinkFormatterFactory( |
||
2025 | $this->getEntityTitleLookup(), |
||
2026 | $this->getLanguageNameLookup(), |
||
2027 | $this->entityTypeDefinitions->get( EntityTypeDefinitions::ENTITY_ID_HTML_LINK_FORMATTER_CALLBACK ) |
||
2028 | ); |
||
2029 | if ( $this->inFederatedPropertyMode() ) { |
||
2030 | $factory = new WrappingEntityIdFormatterFactory( $factory ); |
||
2031 | } |
||
2032 | return $factory; |
||
2033 | } |
||
2034 | |||
2035 | public function getEntityViewFactory() { |
||
2036 | return new DispatchingEntityViewFactory( $this->entityTypeDefinitions->get( EntityTypeDefinitions::VIEW_FACTORY_CALLBACK ) ); |
||
2037 | } |
||
2038 | |||
2039 | public function getEntityMetaTagsCreatorFactory() { |
||
2040 | return new DispatchingEntityMetaTagsCreatorFactory( |
||
2041 | $this->entityTypeDefinitions->get( EntityTypeDefinitions::META_TAGS_CREATOR_CALLBACK ) |
||
2042 | ); |
||
2043 | } |
||
2044 | |||
2045 | public function getEntityDataFormatProvider(): EntityDataFormatProvider { |
||
2046 | $entityDataFormatProvider = new EntityDataFormatProvider(); |
||
2047 | $formats = $this->settings->getSetting( 'entityDataFormats' ); |
||
2048 | $entityDataFormatProvider->setAllowedFormats( $formats ); |
||
2049 | return $entityDataFormatProvider; |
||
2050 | } |
||
2051 | |||
2052 | public function getEntityDataUriManager(): EntityDataUriManager { |
||
2053 | $entityDataFormatProvider = $this->getEntityDataFormatProvider(); |
||
2054 | |||
2055 | // build a mapping of formats to file extensions and include HTML |
||
2056 | $supportedExtensions = []; |
||
2057 | $supportedExtensions['html'] = 'html'; |
||
2058 | foreach ( $entityDataFormatProvider->getSupportedFormats() as $format ) { |
||
2059 | $ext = $entityDataFormatProvider->getExtension( $format ); |
||
2060 | |||
2061 | if ( $ext !== null ) { |
||
2062 | $supportedExtensions[$format] = $ext; |
||
2063 | } |
||
2064 | } |
||
2065 | |||
2066 | return new EntityDataUriManager( |
||
2067 | SpecialPage::getTitleFor( 'EntityData' ), |
||
2068 | $supportedExtensions, |
||
2069 | $this->getSettings()->getSetting( 'entityDataCachePaths' ), |
||
2070 | $this->getEntityTitleLookup() |
||
2071 | ); |
||
2072 | } |
||
2073 | |||
2074 | public function getEntityParserOutputGeneratorFactory(): EntityParserOutputGeneratorFactory { |
||
2075 | $services = MediaWikiServices::getInstance(); |
||
2076 | |||
2077 | return new EntityParserOutputGeneratorFactory( |
||
2078 | $this->getEntityViewFactory(), |
||
2079 | $this->getEntityMetaTagsCreatorFactory(), |
||
2080 | $this->getEntityTitleLookup(), |
||
2081 | $this->getLanguageFallbackChainFactory(), |
||
2082 | TemplateFactory::getDefaultInstance(), |
||
2083 | $this->getEntityDataFormatProvider(), |
||
2084 | // FIXME: Should this be done for all usages of this lookup, or is the impact of |
||
2085 | // CachingPropertyInfoLookup enough? |
||
2086 | new InProcessCachingDataTypeLookup( $this->getPropertyDataTypeLookup() ), |
||
2087 | $this->getCompactEntitySerializer(), |
||
2088 | new EntityReferenceExtractorDelegator( |
||
2089 | $this->entityTypeDefinitions->get( EntityTypeDefinitions::ENTITY_REFERENCE_EXTRACTOR_CALLBACK ), |
||
2090 | new StatementEntityReferenceExtractor( $this->getItemUrlParser() ) |
||
2091 | ), |
||
2092 | $this->getKartographerEmbeddingHandler(), |
||
2093 | $services->getStatsdDataFactory(), |
||
2094 | $services->getRepoGroup(), |
||
2095 | $this->settings->getSetting( 'preferredGeoDataProperties' ), |
||
2096 | $this->settings->getSetting( 'preferredPageImagesProperties' ), |
||
2097 | $this->settings->getSetting( 'globeUris' ) |
||
2098 | ); |
||
2099 | } |
||
2100 | |||
2101 | public function getEntityParserOutputGenerator( Language $userLanguage ): EntityParserOutputGenerator { |
||
2102 | return $this->getEntityParserOutputGeneratorFactory() |
||
2103 | ->getEntityParserOutputGenerator( $userLanguage ); |
||
2104 | } |
||
2105 | |||
2106 | /** |
||
2107 | * @return ViewFactory |
||
2108 | */ |
||
2109 | public function getViewFactory() { |
||
2110 | $lang = $this->getUserLanguage(); |
||
2111 | |||
2112 | $statementGrouperBuilder = new StatementGrouperBuilder( |
||
2113 | $this->settings->getSetting( 'statementSections' ), |
||
2114 | $this->getPropertyDataTypeLookup(), |
||
2115 | $this->getStatementGuidParser() |
||
2116 | ); |
||
2117 | |||
2118 | $propertyOrderProvider = new CachingPropertyOrderProvider( |
||
2119 | new WikiPagePropertyOrderProvider( |
||
2120 | Title::newFromText( 'MediaWiki:Wikibase-SortedProperties' ) |
||
2121 | ), |
||
2122 | ObjectCache::getLocalClusterInstance() |
||
2123 | ); |
||
2124 | |||
2125 | return new ViewFactory( |
||
2126 | $this->getEntityIdHtmlLinkFormatterFactory(), |
||
2127 | new EntityIdLabelFormatterFactory(), |
||
2128 | new WikibaseHtmlSnakFormatterFactory( $this->getSnakFormatterFactory() ), |
||
2129 | $statementGrouperBuilder->getStatementGrouper(), |
||
2130 | $propertyOrderProvider, |
||
2131 | $this->getSiteLookup(), |
||
2132 | $this->getDataTypeFactory(), |
||
2133 | TemplateFactory::getDefaultInstance(), |
||
2134 | $this->getLanguageNameLookup(), |
||
2135 | new MediaWikiLanguageDirectionalityLookup(), |
||
2136 | new MediaWikiNumberLocalizer( $lang ), |
||
2137 | $this->settings->getSetting( 'siteLinkGroups' ), |
||
2138 | $this->settings->getSetting( 'specialSiteLinkGroups' ), |
||
2139 | $this->settings->getSetting( 'badgeItems' ), |
||
2140 | new MediaWikiLocalizedTextProvider( $lang ), |
||
2141 | new RepoSpecialPageLinker() |
||
2142 | ); |
||
2143 | } |
||
2144 | |||
2145 | /** |
||
2146 | * @return DataTypeValidatorFactory |
||
2147 | */ |
||
2148 | public function getDataTypeValidatorFactory() { |
||
2149 | return new BuilderBasedDataTypeValidatorFactory( |
||
2150 | $this->dataTypeDefinitions->getValidatorFactoryCallbacks() |
||
2151 | ); |
||
2152 | } |
||
2153 | |||
2154 | /** |
||
2155 | * @return DataTypeDefinitions |
||
2156 | */ |
||
2157 | public function getDataTypeDefinitions() { |
||
2158 | return $this->dataTypeDefinitions; |
||
2159 | } |
||
2160 | |||
2161 | public function getWikibaseContentLanguages() { |
||
2162 | if ( $this->wikibaseContentLanguages === null ) { |
||
2163 | $this->wikibaseContentLanguages = WikibaseContentLanguages::getDefaultInstance(); |
||
2164 | } |
||
2165 | |||
2166 | return $this->wikibaseContentLanguages; |
||
2167 | } |
||
2168 | |||
2169 | private function getMonolingualTextLanguages() { |
||
2170 | return $this->getWikibaseContentLanguages()->getContentLanguages( WikibaseContentLanguages::CONTEXT_MONOLINGUAL_TEXT ); |
||
2171 | } |
||
2172 | |||
2173 | /** |
||
2174 | * Get a ContentLanguages object holding the languages available for labels, descriptions and aliases. |
||
2175 | * |
||
2176 | * @return ContentLanguages |
||
2177 | */ |
||
2178 | public function getTermsLanguages() { |
||
2179 | return $this->getWikibaseContentLanguages()->getContentLanguages( WikibaseContentLanguages::CONTEXT_TERM ); |
||
2180 | } |
||
2181 | |||
2182 | /** |
||
2183 | * @return CachingCommonsMediaFileNameLookup |
||
2184 | */ |
||
2185 | private function getCachingCommonsMediaFileNameLookup() { |
||
2186 | if ( $this->cachingCommonsMediaFileNameLookup === null ) { |
||
2187 | $this->cachingCommonsMediaFileNameLookup = new CachingCommonsMediaFileNameLookup( |
||
2188 | new MediaWikiPageNameNormalizer(), |
||
2189 | new HashBagOStuff() |
||
2190 | ); |
||
2191 | } |
||
2192 | |||
2193 | return $this->cachingCommonsMediaFileNameLookup; |
||
2194 | } |
||
2195 | |||
2196 | public function getEntityTypesConfigValue() { |
||
2197 | return [ |
||
2198 | 'types' => $this->entityTypeDefinitions->getEntityTypes(), |
||
2199 | 'deserializer-factory-functions' |
||
2200 | => $this->entityTypeDefinitions->get( EntityTypeDefinitions::JS_DESERIALIZER_FACTORY_FUNCTION ) |
||
2201 | ]; |
||
2202 | } |
||
2203 | |||
2204 | public function getSettingsValueProvider( $jsSetting, $phpSetting ) { |
||
2205 | return new SettingsValueProvider( $this->settings, $jsSetting, $phpSetting ); |
||
2206 | } |
||
2207 | |||
2208 | /** |
||
2209 | * Get configure unit converter. |
||
2210 | * @return null|UnitConverter Configured Unit converter, or null if none configured |
||
2211 | */ |
||
2212 | public function getUnitConverter() { |
||
2213 | $unitStorage = $this->getUnitStorage(); |
||
2214 | if ( !$unitStorage ) { |
||
2215 | return null; |
||
2216 | } |
||
2217 | return new UnitConverter( $unitStorage, $this->settings->getSetting( 'conceptBaseUri' ) ); |
||
2218 | } |
||
2219 | |||
2220 | /** |
||
2221 | * Creates configured unit storage. Configuration is in unitStorage parameter, |
||
2222 | * in getObjectFromSpec format. |
||
2223 | * @see ObjectFactory::getObjectFromSpec |
||
2224 | * @return null|UnitStorage Configured unit storage, or null |
||
2225 | */ |
||
2226 | private function getUnitStorage() { |
||
2227 | if ( !$this->settings->hasSetting( 'unitStorage' ) ) { |
||
2228 | return null; |
||
2229 | } |
||
2230 | $storage = |
||
2231 | ObjectFactory::getObjectFromSpec( $this->settings->getSetting( 'unitStorage' ) ); |
||
2232 | if ( !( $storage instanceof UnitStorage ) ) { |
||
2233 | wfWarn( "Bad unit storage configuration, ignoring" ); |
||
2234 | return null; |
||
2235 | } |
||
2236 | return $storage; |
||
2237 | } |
||
2238 | |||
2239 | /** |
||
2240 | * @return EntityRdfBuilderFactory |
||
2241 | */ |
||
2242 | public function getEntityRdfBuilderFactory() { |
||
2243 | if ( $this->entityRdfBuilderFactory === null ) { |
||
2244 | $this->entityRdfBuilderFactory = new EntityRdfBuilderFactory( |
||
2245 | $this->entityTypeDefinitions->get( EntityTypeDefinitions::RDF_BUILDER_FACTORY_CALLBACK ), |
||
2246 | $this->entityTypeDefinitions->get( EntityTypeDefinitions::RDF_LABEL_PREDICATES ) |
||
2247 | ); |
||
2248 | } |
||
2249 | |||
2250 | return $this->entityRdfBuilderFactory; |
||
2251 | } |
||
2252 | |||
2253 | /** |
||
2254 | * @param IContextSource $contextSource |
||
2255 | * @return EntityDiffVisualizerFactory |
||
2256 | */ |
||
2257 | public function getEntityDiffVisualizerFactory( IContextSource $contextSource ) { |
||
2258 | $langCode = $contextSource->getLanguage()->getCode(); |
||
2259 | |||
2260 | $options = new FormatterOptions( [ |
||
2261 | //TODO: fallback chain |
||
2262 | ValueFormatter::OPT_LANG => $langCode |
||
2263 | ] ); |
||
2264 | |||
2265 | $htmlFormatterFactory = $this->getEntityIdHtmlLinkFormatterFactory(); |
||
2266 | $entityIdFormatter = $htmlFormatterFactory->getEntityIdFormatter( $contextSource->getLanguage() ); |
||
2267 | |||
2268 | $formatterFactory = $this->getSnakFormatterFactory(); |
||
2269 | $detailedSnakFormatter = $formatterFactory->getSnakFormatter( SnakFormatter::FORMAT_HTML_DIFF, $options ); |
||
2270 | $terseSnakFormatter = $formatterFactory->getSnakFormatter( SnakFormatter::FORMAT_HTML, $options ); |
||
2271 | |||
2272 | return new EntityDiffVisualizerFactory( |
||
2273 | $this->entityTypeDefinitions->get( EntityTypeDefinitions::ENTITY_DIFF_VISUALIZER_CALLBACK ), |
||
2274 | $contextSource, |
||
2275 | new ClaimDiffer( new OrderedListDiffer( new ComparableComparer() ) ), |
||
2276 | new ClaimDifferenceVisualizer( |
||
2277 | new DifferencesSnakVisualizer( |
||
2278 | $entityIdFormatter, |
||
2279 | $detailedSnakFormatter, |
||
2280 | $terseSnakFormatter, |
||
2281 | $langCode |
||
2282 | ), |
||
2283 | $langCode |
||
2284 | ), |
||
2285 | $this->getSiteLookup(), |
||
2286 | $entityIdFormatter |
||
2287 | ); |
||
2288 | } |
||
2289 | |||
2290 | /** |
||
2291 | * @return string[][] Associative array mapping names of known entity types (strings) to lists of names of |
||
2292 | * repositories providing entities of those types. |
||
2293 | * Note: Currently entities of a given type are only provided by single source. This |
||
2294 | * assumption can be changed in the future. |
||
2295 | */ |
||
2296 | public function getEntityTypeToRepositoryMapping() { |
||
2297 | // Map all entity types to unprefixed repository. |
||
2298 | // TODO: This is a bit of a hack but does the job for EntityIdSearchHelper as long as there are no |
||
2299 | // prefixed IDs in the entity source realm. Probably EntityIdSearchHelper should be changed instead |
||
2300 | // of getting this map passed from Repo |
||
2301 | $entityTypes = array_keys( $this->entitySourceDefinitions->getEntityTypeToSourceMapping() ); |
||
2302 | return array_fill_keys( $entityTypes, [ '' ] ); |
||
2303 | } |
||
2304 | |||
2305 | /** |
||
2306 | * @return string[] Associative array mapping repository or entity source names to base URIs of concept URIs. |
||
2307 | */ |
||
2308 | public function getConceptBaseUris() { |
||
2309 | return $this->entitySourceDefinitions->getConceptBaseUris(); |
||
2310 | } |
||
2311 | |||
2312 | public function getPropertyValueExpertsModule() { |
||
2313 | return new PropertyValueExpertsModule( $this->getDataTypeDefinitions() ); |
||
2314 | } |
||
2315 | |||
2316 | /** |
||
2317 | * @return WikibaseServices |
||
2318 | */ |
||
2319 | public function getWikibaseServices() { |
||
2320 | if ( $this->wikibaseServices === null ) { |
||
2321 | $this->wikibaseServices = $this->newEntitySourceWikibaseServices(); |
||
2322 | } |
||
2323 | |||
2324 | return $this->wikibaseServices; |
||
2325 | } |
||
2326 | |||
2327 | private function newEntitySourceWikibaseServices() { |
||
2328 | $nameTableStoreFactory = MediaWikiServices::getInstance()->getNameTableStoreFactory(); |
||
2329 | $genericServices = new GenericServices( $this->entityTypeDefinitions ); |
||
2330 | |||
2331 | $singleSourceServices = []; |
||
2332 | foreach ( $this->entitySourceDefinitions->getSources() as $source ) { |
||
2333 | // TODO: extract |
||
2334 | $singleSourceServices[$source->getSourceName()] = new SingleEntitySourceServices( |
||
2335 | $genericServices, |
||
2336 | $this->getEntityIdParser(), |
||
2337 | $this->getEntityIdComposer(), |
||
2338 | $this->getDataValueDeserializer(), |
||
2339 | $nameTableStoreFactory->getSlotRoles( $source->getDatabaseName() ), |
||
2340 | $this->getDataAccessSettings(), |
||
2341 | $source, |
||
2342 | $this->entityTypeDefinitions->get( EntityTypeDefinitions::DESERIALIZER_FACTORY_CALLBACK ), |
||
2343 | $this->entityTypeDefinitions->get( EntityTypeDefinitions::ENTITY_METADATA_ACCESSOR_CALLBACK ), |
||
2344 | $this->entityTypeDefinitions->get( EntityTypeDefinitions::PREFETCHING_TERM_LOOKUP_CALLBACK ), |
||
2345 | $this->entityTypeDefinitions->get( EntityTypeDefinitions::ENTITY_REVISION_LOOKUP_FACTORY_CALLBACK ) |
||
2346 | ); |
||
2347 | } |
||
2348 | return new MultipleEntitySourceServices( $this->entitySourceDefinitions, $genericServices, $singleSourceServices ); |
||
2349 | } |
||
2350 | |||
2351 | public function getDataAccessSettings() { |
||
2352 | if ( $this->dataAccessSettings === null ) { |
||
2353 | $this->dataAccessSettings = new DataAccessSettings( |
||
2354 | $this->settings->getSetting( 'maxSerializedEntitySize' ) |
||
2355 | ); |
||
2356 | } |
||
2357 | return $this->dataAccessSettings; |
||
2358 | } |
||
2359 | |||
2360 | public function getEntitySourceDefinitions() { |
||
2361 | return $this->entitySourceDefinitions; |
||
2362 | } |
||
2363 | |||
2364 | /** |
||
2365 | * @return callable[] |
||
2366 | */ |
||
2367 | public function getEntitySearchHelperCallbacks() { |
||
2368 | return $this->entityTypeDefinitions->get( EntityTypeDefinitions::ENTITY_SEARCH_CALLBACK ); |
||
2369 | } |
||
2370 | |||
2371 | public function getEntityLinkFormatterFactory( Language $language ) { |
||
2372 | return new EntityLinkFormatterFactory( |
||
2373 | $language, |
||
2374 | $this->getEntityTitleTextLookup(), |
||
2375 | $this->entityTypeDefinitions->get( EntityTypeDefinitions::LINK_FORMATTER_CALLBACK ) |
||
2376 | ); |
||
2377 | } |
||
2378 | |||
2379 | /** |
||
2380 | * Get entity search helper callbacks. |
||
2381 | * @return string[] |
||
2382 | */ |
||
2383 | public function getFulltextSearchTypes() { |
||
2384 | $searchTypes = $this->entityTypeDefinitions->get( EntityTypeDefinitions::FULLTEXT_SEARCH_CONTEXT ); |
||
2385 | foreach ( $searchTypes as $key => $value ) { |
||
2386 | if ( is_callable( $value ) ) { |
||
2387 | $searchTypes[$key] = $value(); |
||
2388 | } |
||
2389 | } |
||
2390 | return $searchTypes; |
||
2391 | } |
||
2392 | |||
2393 | public function getTermFallbackCache(): TermFallbackCacheFacade { |
||
2394 | return new TermFallbackCacheFacade( |
||
2395 | $this->getTermFallbackCacheFactory()->getTermFallbackCache(), |
||
2396 | $this->getSettings()->getSetting( 'sharedCacheDuration' ) |
||
2397 | ); |
||
2398 | } |
||
2399 | |||
2400 | public function getTermFallbackCacheFactory(): TermFallbackCacheFactory { |
||
2401 | global $wgSecretKey; |
||
2402 | |||
2403 | if ( $this->termFallbackCacheFactory === null ) { |
||
2404 | $this->termFallbackCacheFactory = new TermFallbackCacheFactory( |
||
2405 | $this->settings->getSetting( 'sharedCacheType' ), |
||
2406 | $this->getLogger(), |
||
2407 | MediaWikiServices::getInstance()->getStatsdDataFactory(), |
||
2408 | hash( 'sha256', $wgSecretKey ), |
||
2409 | new TermFallbackCacheServiceFactory(), |
||
2410 | $this->settings->getSetting( 'termFallbackCacheVersion' ) |
||
2411 | ); |
||
2412 | } |
||
2413 | return $this->termFallbackCacheFactory; |
||
2414 | } |
||
2415 | |||
2416 | public function getHtmlCacheUpdater(): HtmlCacheUpdater { |
||
2417 | return MediaWikiServices::getInstance()->getHtmlCacheUpdater(); |
||
2418 | } |
||
2419 | |||
2420 | public function getLogger(): LoggerInterface { |
||
2421 | return LoggerFactory::getInstance( 'Wikibase' ); |
||
2422 | } |
||
2423 | |||
2424 | /** |
||
2425 | * Guard against Federated properties services being constructed in wiring when feature is disabled. |
||
2426 | */ |
||
2427 | private function throwLogicExceptionIfFederatedPropertiesNotEnabledAndConfigured(): void { |
||
2428 | if ( |
||
2429 | !$this->inFederatedPropertyMode() || |
||
2430 | !$this->getSettings()->hasSetting( 'federatedPropertiesSourceScriptUrl' ) |
||
2431 | ) { |
||
2432 | throw new LogicException( |
||
2433 | 'Federated Property services should not be constructed when federatedProperties feature is not enabled or configured.' |
||
2434 | ); |
||
2435 | } |
||
2436 | } |
||
2437 | |||
2438 | public function inFederatedPropertyMode(): bool { |
||
2439 | return $this->getSettings()->getSetting( 'federatedPropertiesEnabled' ); |
||
2440 | } |
||
2441 | |||
2442 | public function newFederatedPropertiesServiceFactory(): ApiServiceFactory { |
||
2443 | $this->throwLogicExceptionIfFederatedPropertiesNotEnabledAndConfigured(); |
||
2444 | |||
2445 | global $wgServerName; |
||
2446 | |||
2447 | return new ApiServiceFactory( |
||
2448 | $this->getSettings()->getSetting( 'federatedPropertiesSourceScriptUrl' ), |
||
2449 | $wgServerName |
||
2450 | ); |
||
2451 | } |
||
2452 | |||
2453 | public function getLinkTargetEntityIdLookup(): LinkTargetEntityIdLookup { |
||
2454 | return new EntityLinkTargetEntityIdLookup( |
||
2455 | $this->getEntityNamespaceLookup(), |
||
2456 | $this->getEntityIdParser(), |
||
2457 | $this->entitySourceDefinitions, |
||
2458 | $this->getLocalEntitySource() |
||
2459 | ); |
||
2460 | } |
||
2461 | |||
2462 | } |
||
2463 |
It seems like the type of the argument is not accepted by the function/method which you are calling.
In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.
We suggest to add an explicit type cast like in the following example: