1 | <?php |
||
2 | |||
3 | namespace SCI; |
||
4 | |||
5 | use SMW\Store; |
||
6 | use Onoi\Cache\Cache; |
||
7 | use SMW\Services\ServicesFactory as ApplicationFactory; |
||
8 | use SMW\DataTypeRegistry; |
||
0 ignored issues
–
show
|
|||
9 | use SMW\DIWikiPage; |
||
10 | use SMWDataItem as DataItem; |
||
11 | |||
12 | /** |
||
13 | * @license GNU GPL v2+ |
||
14 | * @since 1.0 |
||
15 | * |
||
16 | * @author mwjames |
||
17 | */ |
||
18 | class HookRegistry { |
||
19 | |||
20 | /** |
||
21 | * @var array |
||
22 | */ |
||
23 | private $handlers = []; |
||
24 | |||
25 | /** |
||
26 | * @var Options |
||
27 | */ |
||
28 | private $options; |
||
29 | |||
30 | /** |
||
31 | * @var CitationReferencePositionJournal |
||
32 | */ |
||
33 | private $citationReferencePositionJournal; |
||
34 | |||
35 | /** |
||
36 | * @since 1.0 |
||
37 | * |
||
38 | * @param Store $store |
||
39 | * @param Cache $cache |
||
40 | * @param Options $options |
||
41 | */ |
||
42 | 16 | public function __construct( Store $store, Cache $cache, Options $options ) { |
|
43 | 16 | $this->options = $options; |
|
44 | |||
45 | 16 | $this->addCallbackHandlers( |
|
46 | 16 | $store, |
|
47 | 16 | $cache, |
|
48 | 16 | $this->options |
|
49 | ); |
||
50 | 16 | } |
|
51 | |||
52 | /** |
||
53 | * @note Usually only used during unit/integration testing |
||
54 | * |
||
55 | * @since 1.0 |
||
56 | * |
||
57 | * @param string $key |
||
58 | * @param mixed $value |
||
59 | */ |
||
60 | 14 | public function setOption( $key, $value ) { |
|
61 | 14 | $this->options->set( $key, $value ); |
|
62 | 14 | } |
|
63 | |||
64 | /** |
||
65 | * @since 1.0 |
||
66 | * |
||
67 | * @param string $name |
||
68 | * |
||
69 | * @return boolean |
||
70 | */ |
||
71 | 1 | public function isRegistered( $name ) { |
|
72 | 1 | return \MediaWiki\MediaWikiServices::getInstance()->getHookContainer()->isRegistered( $name ); |
|
73 | } |
||
74 | |||
75 | /** |
||
76 | * @since 1.0 |
||
77 | */ |
||
78 | 14 | public function clear() { |
|
79 | |||
80 | 14 | if ( !defined( 'MW_PHPUNIT_TEST' ) ) { |
|
81 | return; |
||
82 | } |
||
83 | |||
84 | 14 | foreach ( $this->handlers as $name => $callback ) { |
|
85 | \MediaWiki\MediaWikiServices::getInstance()->getHookContainer()->clear( $name ); |
||
86 | 14 | } |
|
87 | 14 | } |
|
88 | 14 | ||
89 | /** |
||
90 | 14 | * @since 1.0 |
|
91 | * |
||
92 | * @param string $name |
||
93 | 14 | * |
|
94 | * @return Callable|false |
||
95 | */ |
||
96 | public function getHandlerFor( $name ) { |
||
97 | return isset( $this->handlers[$name] ) ? $this->handlers[$name] : false; |
||
98 | } |
||
99 | |||
100 | /** |
||
101 | * @since 1.0 |
||
102 | 1 | */ |
|
103 | 1 | public function register() { |
|
104 | // *** not clear why this has been added |
||
105 | //if ( !defined( 'MW_PHPUNIT_TEST' ) ) { |
||
106 | // return; |
||
107 | //} |
||
108 | |||
109 | 14 | foreach ( $this->handlers as $name => $callback ) { |
|
110 | \MediaWiki\MediaWikiServices::getInstance()->getHookContainer()->register( $name, $callback ); |
||
111 | 14 | } |
|
112 | } |
||
113 | |||
114 | /** |
||
115 | 14 | * @since 1.3 |
|
116 | * |
||
117 | 14 | * @param array &$config |
|
118 | 14 | */ |
|
119 | 14 | public static function onBeforeConfigCompletion( &$config ) { |
|
120 | |||
121 | 14 | if ( !isset( $config['smwgFulltextSearchPropertyExemptionList'] ) ) { |
|
122 | return; |
||
123 | } |
||
124 | 14 | ||
125 | // Exclude those properties from indexing |
||
126 | $config['smwgFulltextSearchPropertyExemptionList'] = array_merge( |
||
127 | $config['smwgFulltextSearchPropertyExemptionList'], |
||
128 | [ PropertyRegistry::SCI_CITE ] |
||
129 | ); |
||
130 | } |
||
131 | |||
132 | /** |
||
133 | * @since 2.0 |
||
134 | */ |
||
135 | public static function initExtension() { |
||
136 | |||
137 | $GLOBALS['wgHooks']['SMW::Config::BeforeCompletion'][] = function( &$config ) { |
||
138 | |||
139 | $exemptionlist = [ |
||
140 | PropertyRegistry::SCI_CITE |
||
141 | ]; |
||
142 | |||
143 | // Exclude listed properties from indexing |
||
144 | if ( isset( $config['smwgFulltextSearchPropertyExemptionList'] ) ) { |
||
145 | $config['smwgFulltextSearchPropertyExemptionList'] = array_merge( |
||
146 | $config['smwgFulltextSearchPropertyExemptionList'], |
||
147 | $exemptionlist |
||
148 | ); |
||
149 | } |
||
150 | |||
151 | 15 | // Exclude listed properties from dependency detection as each of the |
|
152 | // selected object would trigger an automatic change without the necessary |
||
153 | // human intervention and can therefore produce unwanted query updates |
||
154 | 15 | ||
155 | if ( isset( $config['smwgQueryDependencyPropertyExemptionList'] ) ) { |
||
156 | $config['smwgQueryDependencyPropertyExemptionList'] = array_merge( |
||
157 | $config['smwgQueryDependencyPropertyExemptionList'], |
||
158 | 15 | $exemptionlist |
|
159 | 15 | ); |
|
160 | 15 | } |
|
161 | 15 | ||
162 | return true; |
||
163 | }; |
||
164 | } |
||
165 | |||
166 | public function onDataTypeInit() { |
||
167 | $dataTypeRegistry = DataTypeRegistry::getInstance(); |
||
168 | |||
169 | 15 | $dataTypeRegistry->registerDatatype( |
|
170 | 15 | '_sci_ref', |
|
171 | 15 | '\SCI\DataValues\CitationReferenceValue', |
|
172 | 15 | DataItem::TYPE_BLOB |
|
173 | ); |
||
174 | |||
175 | $types = [ |
||
176 | 15 | '_sci_doi', |
|
177 | '_sci_pmcid', |
||
178 | 1 | '_sci_pmid', |
|
179 | '_sci_oclc', |
||
180 | 15 | '_sci_viaf', |
|
181 | '_sci_olid' |
||
182 | 15 | ]; |
|
183 | 15 | ||
184 | 15 | foreach ( $types as $type ) { |
|
185 | 15 | $dataTypeRegistry->registerDatatype( |
|
186 | $type, |
||
187 | '\SCI\DataValues\ResourceIdentifierStringValue', |
||
188 | DataItem::TYPE_BLOB |
||
189 | 15 | ); |
|
190 | } |
||
191 | |||
192 | $callback = function() { |
||
193 | return $this->citationReferencePositionJournal; |
||
194 | }; |
||
195 | |||
196 | // SMW 3.1+ |
||
197 | 15 | if ( method_exists( $dataTypeRegistry, 'registerCallable' ) ) { |
|
198 | 15 | $dataTypeRegistry->registerCallable( '_sci_ref', 'sci.citationreferencepositionjournal', $callback ); |
|
199 | 15 | } else { |
|
200 | 15 | $dataTypeRegistry->registerExtraneousFunction( |
|
201 | 15 | '\SCI\CitationReferencePositionJournal', |
|
202 | $callback |
||
203 | ); |
||
204 | } |
||
205 | 15 | ||
206 | 8 | return true; |
|
207 | 15 | } |
|
208 | |||
209 | private function addCallbackHandlers( $store, $cache, $options ) { |
||
210 | 15 | ||
211 | 15 | $propertyRegistry = new PropertyRegistry(); |
|
212 | $namespaceExaminer = ApplicationFactory::getInstance()->getNamespaceExaminer(); |
||
213 | |||
214 | $cacheKeyProvider = new CacheKeyProvider(); |
||
215 | $cacheKeyProvider->setCachePrefix( $options->get( 'cachePrefix' ) ); |
||
216 | |||
217 | $this->citationReferencePositionJournal = new CitationReferencePositionJournal( |
||
218 | $cache, |
||
219 | 15 | $cacheKeyProvider |
|
220 | ); |
||
221 | |||
222 | 16 | $referenceBacklinksLookup = new ReferenceBacklinksLookup( $store ); |
|
223 | |||
224 | 16 | /** |
|
225 | 16 | * @see https://www.semantic-mediawiki.org/wiki/Hooks/SMW::Property::initProperties |
|
226 | */ |
||
227 | 16 | $this->handlers['SMW::Property::initProperties'] = function ( $corePropertyRegistry ) use ( $propertyRegistry ) { |
|
228 | 16 | return $propertyRegistry->registerTo( $corePropertyRegistry ); |
|
229 | }; |
||
230 | 16 | ||
231 | 16 | /** |
|
232 | 16 | * @see https://www.semantic-mediawiki.org/wiki/Hooks/SMW::DataType::initTypes |
|
233 | */ |
||
234 | $this->handlers['SMW::DataType::initTypes'] = [ $this, 'onDataTypeInit' ]; |
||
235 | 16 | ||
236 | /** |
||
237 | * @see https://www.semantic-mediawiki.org/wiki/Hooks/SMW::Browse::AfterIncomingPropertiesLookupComplete |
||
238 | */ |
||
239 | $this->handlers['SMW::Browse::AfterIncomingPropertiesLookupComplete'] = function ( $store, $semanticData, $requestOptions ) use ( $referenceBacklinksLookup ) { |
||
240 | 15 | ||
241 | 15 | $referenceBacklinksLookup->setRequestOptions( $requestOptions ); |
|
242 | $referenceBacklinksLookup->setStore( $store ); |
||
243 | |||
244 | $referenceBacklinksLookup->addReferenceBacklinksTo( |
||
245 | $semanticData |
||
246 | ); |
||
247 | 16 | ||
248 | return true; |
||
249 | }; |
||
250 | |||
251 | $this->handlers['SMW::Browse::BeforeIncomingPropertyValuesFurtherLinkCreate'] = function ( $property, $subject, &$html ) use ( $referenceBacklinksLookup ) { |
||
252 | 1 | return $referenceBacklinksLookup->getSpecialPropertySearchFurtherLink( $property, $subject, $html ); |
|
253 | }; |
||
254 | 1 | ||
255 | 1 | /** |
|
256 | * @see https://www.semantic-mediawiki.org/wiki/Hooks/SMW::Parser::BeforeMagicWordsFinder |
||
257 | 1 | */ |
|
258 | 1 | $this->handlers['SMW::Parser::BeforeMagicWordsFinder'] = function( array &$magicWords ) { |
|
259 | $magicWords = array_merge( $magicWords, [ 'SCI_NOREFERENCELIST' ] ); |
||
260 | return true; |
||
261 | 1 | }; |
|
262 | |||
263 | /** |
||
264 | 1 | * @see https://www.semantic-mediawiki.org/wiki/Hooks/SMW::SQLStore::AddCustomFixedPropertyTables |
|
265 | 1 | */ |
|
266 | $this->handlers['SMW::SQLStore::AddCustomFixedPropertyTables'] = function( array &$customFixedProperties ) use( $propertyRegistry ) { |
||
267 | |||
268 | $properties = [ |
||
269 | $propertyRegistry::SCI_CITE_KEY, |
||
270 | $propertyRegistry::SCI_CITE_REFERENCE, |
||
271 | 15 | $propertyRegistry::SCI_CITE_TEXT, |
|
272 | 15 | $propertyRegistry::SCI_CITE, |
|
273 | 15 | $propertyRegistry::SCI_DOI, |
|
274 | $propertyRegistry::SCI_PMCID, |
||
275 | $propertyRegistry::SCI_PMID, |
||
276 | $propertyRegistry::SCI_OCLC, |
||
277 | $propertyRegistry::SCI_VIAF, |
||
278 | $propertyRegistry::SCI_OLID |
||
279 | 14 | ]; |
|
280 | |||
281 | foreach ( $properties as $property ) { |
||
282 | 14 | $customFixedProperties[$property] = str_replace( '__', '_', $property ); |
|
283 | 14 | } |
|
284 | 14 | ||
285 | 14 | return true; |
|
286 | 14 | }; |
|
287 | 14 | ||
288 | 14 | /** |
|
289 | 14 | * @see https://www.mediawiki.org/wiki/Manual:Hooks/BeforePageDisplay |
|
290 | 14 | */ |
|
291 | 14 | $this->handlers['BeforePageDisplay'] = function ( &$outputPage, &$skin ) use( $namespaceExaminer ) { |
|
292 | |||
293 | if ( !$namespaceExaminer->isSemanticEnabled( $outputPage->getTitle()->getNamespace() ) ) { |
||
294 | 14 | return true; |
|
295 | 14 | } |
|
296 | |||
297 | $outputPage->addModuleStyles( 'ext.scite.styles' ); |
||
298 | 14 | ||
299 | $outputPage->addModules( |
||
300 | [ |
||
301 | 'ext.scite.styles', |
||
302 | 'ext.scite.tooltip' |
||
303 | ] |
||
304 | 1 | ); |
|
305 | |||
306 | 1 | return true; |
|
307 | }; |
||
308 | |||
309 | /** |
||
310 | 1 | * @note This is bit of a hack but there is no other way to get access to |
|
311 | * the ParserOutput so that it can be used in OutputPageBeforeHTML |
||
312 | 1 | * |
|
313 | * @see https://www.mediawiki.org/wiki/Manual:Hooks/OutputPageParserOutput |
||
314 | 1 | */ |
|
315 | $this->handlers['OutputPageParserOutput'] = function( &$outputPage, $parserOutput ) { |
||
316 | $outputPage->smwmagicwords = $parserOutput->getExtensionData( 'smwmagicwords' ); |
||
317 | return true; |
||
318 | }; |
||
319 | 1 | ||
320 | /** |
||
321 | * @see https://www.mediawiki.org/wiki/Manual:Hooks/OutputPageBeforeHTML |
||
322 | */ |
||
323 | $this->handlers['OutputPageBeforeHTML'] = function( &$outputPage, &$text ) use ( $store, $namespaceExaminer, $cache, $cacheKeyProvider, $options ) { |
||
324 | |||
325 | $referenceListFactory = new ReferenceListFactory( |
||
326 | $store, |
||
327 | $namespaceExaminer, |
||
328 | 10 | $this->citationReferencePositionJournal |
|
329 | 10 | ); |
|
330 | 10 | ||
331 | $cachedReferenceListOutputRenderer = $referenceListFactory->newCachedReferenceListOutputRenderer( |
||
332 | new MediaWikiContextInteractor( $outputPage->getContext() ), |
||
333 | $cache, |
||
334 | $cacheKeyProvider, |
||
335 | $options |
||
336 | 10 | ); |
|
337 | |||
338 | 10 | $cachedReferenceListOutputRenderer->addReferenceListToText( $text ); |
|
339 | 10 | ||
340 | 10 | return true; |
|
341 | 10 | }; |
|
342 | |||
343 | /** |
||
344 | 10 | * @see https://www.semantic-mediawiki.org/wiki/Hooks#SMWStore::updateDataBefore |
|
345 | 10 | */ |
|
346 | 10 | $this->handlers['SMWStore::updateDataBefore'] = function ( $store, $semanticData ) use ( $cache, $cacheKeyProvider ) { |
|
347 | 10 | ||
348 | 10 | $hash = $semanticData->getSubject()->getHash(); |
|
349 | |||
350 | // No remaining reference means it is time to purge the cache once |
||
351 | 10 | // more because as long as a CiteRef exists, CitationReferencePositionJournal |
|
352 | // is able recompute and update the entries but with no CiteRef left |
||
353 | 10 | // the last entry will remain and needs to be purged at this point |
|
354 | if ( !$this->citationReferencePositionJournal->hasCitationReference( $semanticData ) ) { |
||
355 | $cache->delete( |
||
356 | $cacheKeyProvider->getCacheKeyForCitationReference( $hash ) |
||
357 | ); |
||
358 | } |
||
359 | 15 | ||
360 | $cache->delete( |
||
361 | 15 | $cacheKeyProvider->getCacheKeyForReferenceList( $hash ) |
|
362 | ); |
||
363 | |||
364 | return true; |
||
365 | }; |
||
366 | |||
367 | 15 | /** |
|
368 | 14 | * @see https://www.semantic-mediawiki.org/wiki/Hooks#SMW::SQLStore::AfterDeleteSubjectComplete |
|
369 | 14 | */ |
|
370 | $this->handlers['SMW::SQLStore::AfterDeleteSubjectComplete'] = function ( $store, $title ) use ( $cache, $cacheKeyProvider ) { |
||
371 | |||
372 | $hash = DIWikiPage::newFromTitle( $title )->getHash(); |
||
373 | 15 | ||
374 | 15 | $cache->delete( |
|
375 | $cacheKeyProvider->getCacheKeyForCitationReference( $hash ) |
||
376 | ); |
||
377 | 15 | ||
378 | $cache->delete( |
||
379 | $cacheKeyProvider->getCacheKeyForReferenceList( $hash ) |
||
380 | ); |
||
381 | |||
382 | return true; |
||
383 | 15 | }; |
|
384 | |||
385 | 15 | /** |
|
386 | * @see https://www.semantic-mediawiki.org/wiki/Hooks#SMW::SQLStore::AfterDataUpdateComplete |
||
387 | 15 | */ |
|
388 | 15 | $this->handlers['SMW::SQLStore::AfterDataUpdateComplete'] = function ( $store, $semanticData, $compositePropertyTableDiffIterator ) use ( $referenceBacklinksLookup, $options ) { |
|
389 | |||
390 | $referenceBacklinksLookup->setStore( $store ); |
||
391 | 15 | ||
392 | 15 | $citationTextChangeUpdateJobDispatcher = new CitationTextChangeUpdateJobDispatcher( |
|
393 | $store, |
||
394 | $referenceBacklinksLookup |
||
395 | 15 | ); |
|
396 | |||
397 | $citationTextChangeUpdateJobDispatcher->setEnabledUpdateJobState( |
||
398 | $options->get( 'enabledCitationTextChangeUpdateJob' ) |
||
399 | ); |
||
400 | |||
401 | 15 | $citationTextChangeUpdateJobDispatcher->dispatchUpdateJobFor( |
|
402 | $semanticData->getSubject(), |
||
403 | 15 | $compositePropertyTableDiffIterator |
|
404 | ); |
||
405 | 15 | ||
406 | 15 | return true; |
|
407 | 15 | }; |
|
408 | |||
409 | /** |
||
410 | 15 | * @see https://www.mediawiki.org/wiki/Manual:Hooks/ResourceLoaderGetConfigVars |
|
411 | 15 | */ |
|
412 | $this->handlers['ResourceLoaderGetConfigVars'] = function ( &$vars ) use ( $options ) { |
||
413 | |||
414 | 15 | $vars['ext.scite.config'] = [ |
|
415 | 15 | 'showTooltipForCitationReference' => $options->get( 'showTooltipForCitationReference' ), |
|
416 | 15 | 'tooltipRequestCacheTTL' => $options->get( 'tooltipRequestCacheTTL' ), |
|
417 | 'cachePrefix' => $options->get( 'cachePrefix' ) |
||
418 | ]; |
||
419 | 15 | ||
420 | return true; |
||
421 | }; |
||
422 | |||
423 | /** |
||
424 | * @see https://www.mediawiki.org/wiki/Manual:Hooks/ParserFirstCallInit |
||
425 | 1 | */ |
|
426 | $this->handlers['ParserFirstCallInit'] = function ( &$parser ) use ( $namespaceExaminer, $options ) { |
||
427 | 1 | ||
428 | 1 | $parserFunctionFactory = new ParserFunctionFactory(); |
|
429 | 1 | ||
430 | 1 | list( $name, $definition, $flag ) = $parserFunctionFactory->newSciteParserFunctionDefinition( |
|
431 | $namespaceExaminer, |
||
432 | $options |
||
433 | 1 | ); |
|
434 | |||
435 | $parser->setFunctionHook( $name, $definition, $flag ); |
||
436 | |||
437 | list( $name, $definition, $flag ) = $parserFunctionFactory->newReferenceListParserFunctionDefinition(); |
||
438 | |||
439 | 1 | $parser->setFunctionHook( $name, $definition, $flag ); |
|
440 | |||
441 | 1 | return true; |
|
442 | }; |
||
443 | 1 | } |
|
444 | 1 | ||
445 | } |
||
446 |
The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g.
excluded_paths: ["lib/*"]
, you can move it to the dependency path list as follows:For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths