1 | <?php |
||
53 | class Setup { |
||
54 | |||
55 | /** |
||
56 | * @var array |
||
57 | */ |
||
58 | const AVAILABLE_HOOKS = [ |
||
59 | 'GalleryGetModes', 'ImageBeforeProduceHTML', 'InternalParseBeforeLinks', |
||
60 | 'OutputPageParserOutput', 'ParserFirstCallInit', 'ScribuntoExternalLibraries', |
||
61 | 'SetupAfterCache', |
||
62 | ]; |
||
63 | // dev note: for modals, please see \BootstrapComponents\ModalBuilder for a list of tested hooks |
||
64 | |||
65 | /** |
||
66 | * @var ComponentLibrary $componentLibrary |
||
67 | */ |
||
68 | private $componentLibrary; |
||
69 | |||
70 | /** |
||
71 | * @var \Config $myConfig |
||
72 | */ |
||
73 | private $myConfig; |
||
74 | |||
75 | /** |
||
76 | * @var NestingController $nestingController |
||
77 | */ |
||
78 | private $nestingController; |
||
79 | |||
80 | /** |
||
81 | * Callback function when extension is loaded via extension.json or composer. |
||
82 | * |
||
83 | * Note: With this we omit hook registration in extension.json and define our own here |
||
84 | * to better allow for unit testing. |
||
85 | * |
||
86 | * @param array $info |
||
87 | * |
||
88 | * @throws \ConfigException cascading {@see Setup::run} |
||
89 | * @throws \MWException cascading {@see Setup::__construct()} and {@see Setup::run} |
||
90 | * |
||
91 | * @return bool |
||
92 | */ |
||
93 | 1 | public static function onExtensionLoad( $info ) { |
|
94 | 1 | $setup = new self( $info ); |
|
95 | |||
96 | 1 | $setup->run(); |
|
97 | 1 | return true; |
|
98 | } |
||
99 | |||
100 | /** |
||
101 | * Setup constructor. |
||
102 | * |
||
103 | * @param $info |
||
104 | * |
||
105 | * @throws \ConfigException cascading {@see \BootstrapComponents\Setup::getHooksToRegister} |
||
106 | * @throws \MWException cascading {@see \BootstrapComponents\Setup::getHooksToRegister} |
||
107 | * |
||
108 | */ |
||
109 | 47 | public function __construct( $info ) { |
|
110 | |||
111 | 47 | $this->assertExtensionBootstrapPresent(); |
|
112 | |||
113 | 47 | if ( !empty( $info['version'] ) ) { |
|
114 | 1 | $this->prepareEnvironment( $info['version'] ); |
|
115 | 1 | } |
|
116 | |||
117 | 47 | $configFactory = MediaWikiServices::getInstance()->getConfigFactory(); |
|
118 | 47 | $this->registerMyConfiguration( $configFactory ); |
|
119 | 47 | $this->myConfig = $configFactory->makeConfig( 'BootstrapComponents' ); |
|
120 | |||
121 | 47 | list( $this->componentLibrary, $this->nestingController ) = $this->initializeApplications( $this->myConfig ); |
|
122 | 47 | } |
|
123 | |||
124 | /** |
||
125 | * @param array $hooksToRegister |
||
126 | * |
||
127 | * @return array |
||
128 | */ |
||
129 | 40 | public function buildHookCallbackListFor( $hooksToRegister ) { |
|
130 | 40 | $hookCallbackList = []; |
|
131 | 40 | $completeHookDefinitionList = $this->getCompleteHookDefinitionList( |
|
132 | 40 | $this->myConfig, $this->componentLibrary, $this->nestingController |
|
133 | 40 | ); |
|
134 | 40 | foreach ( $hooksToRegister as $requestedHook ) { |
|
135 | 39 | if ( isset( $completeHookDefinitionList[$requestedHook] ) ) { |
|
136 | 38 | $hookCallbackList[$requestedHook] = $completeHookDefinitionList[$requestedHook]; |
|
137 | 38 | } |
|
138 | 40 | } |
|
139 | 40 | return $hookCallbackList; |
|
140 | } |
||
141 | |||
142 | /** |
||
143 | * @throws \MWException cascading {@see \Hooks::clear} |
||
144 | */ |
||
145 | 21 | public function clear() { |
|
146 | 21 | foreach ( self::AVAILABLE_HOOKS as $name ) { |
|
147 | 21 | Hooks::clear( $name ); |
|
148 | 21 | } |
|
149 | 21 | } |
|
150 | |||
151 | /** |
||
152 | * @param \Config $myConfig |
||
153 | * |
||
154 | * @throws \ConfigException cascading {@see \Config::get} |
||
155 | * |
||
156 | * @return string[] |
||
157 | */ |
||
158 | 6 | public function compileRequestedHooksListFor( $myConfig ) { |
|
159 | 6 | $requestedHookList = [ 'OutputPageParserOutput', 'ParserFirstCallInit', 'SetupAfterCache', 'ScribuntoExternalLibraries' ]; |
|
160 | 6 | if ( $myConfig->has( 'BootstrapComponentsEnableCarouselGalleryMode' ) |
|
161 | 6 | && $myConfig->get( 'BootstrapComponentsEnableCarouselGalleryMode' ) |
|
162 | 6 | ) { |
|
163 | 4 | $requestedHookList[] = 'GalleryGetModes'; |
|
164 | 4 | } |
|
165 | 6 | if ( $myConfig->has( 'BootstrapComponentsModalReplaceImageTag' ) |
|
166 | 6 | && $myConfig->get( 'BootstrapComponentsModalReplaceImageTag' ) |
|
167 | 6 | ) { |
|
168 | 4 | $requestedHookList[] = 'ImageBeforeProduceHTML'; |
|
169 | 4 | $requestedHookList[] = 'InternalParseBeforeLinks'; |
|
170 | 4 | } |
|
171 | 6 | return $requestedHookList; |
|
172 | } |
||
173 | |||
174 | /** |
||
175 | * @param \Config $myConfig |
||
176 | * @param ComponentLibrary $componentLibrary |
||
177 | * @param NestingController $nestingController |
||
178 | * |
||
179 | * @return \Closure[] |
||
180 | */ |
||
181 | 41 | public function getCompleteHookDefinitionList( $myConfig, $componentLibrary, $nestingController ) { |
|
182 | return [ |
||
183 | /** |
||
184 | * Hook: GalleryGetModes |
||
185 | * |
||
186 | * Allows extensions to add classes that can render different modes of a gallery. |
||
187 | * |
||
188 | * @see https://www.mediawiki.org/wiki/Manual:Hooks/GalleryGetModes |
||
189 | */ |
||
190 | 'GalleryGetModes' => function( &$modeArray ) { |
||
191 | 2 | $modeArray['carousel'] = 'BootstrapComponents\\CarouselGallery'; |
|
192 | 2 | return true; |
|
193 | 41 | }, |
|
194 | |||
195 | /** |
||
196 | * Hook: ImageBeforeProduceHTML |
||
197 | * |
||
198 | * Called before producing the HTML created by a wiki image insertion |
||
199 | * |
||
200 | * @see https://www.mediawiki.org/wiki/Manual:Hooks/ImageBeforeProduceHTML |
||
201 | */ |
||
202 | 41 | 'ImageBeforeProduceHTML' => $this->createImageBeforeProduceHTMLCallback( $nestingController, $myConfig ), |
|
203 | |||
204 | /** |
||
205 | * Hook: InternalParseBeforeLinks |
||
206 | * |
||
207 | * Used to process the expanded wiki code after <nowiki>, HTML-comments, and templates have been treated. |
||
208 | * |
||
209 | * @see https://www.mediawiki.org/wiki/Manual:Hooks/InternalParseBeforeLinks |
||
210 | */ |
||
211 | 41 | 'InternalParseBeforeLinks' => $this->createInternalParseBeforeLinksCallback(), |
|
212 | |||
213 | /** |
||
214 | * Hook: OutputPageParserOutput |
||
215 | * |
||
216 | * Called after parse, before the HTML is added to the output. |
||
217 | * |
||
218 | * @see https://www.mediawiki.org/wiki/Manual:Hooks/OutputPageParserOutput |
||
219 | */ |
||
220 | 'OutputPageParserOutput' => function( \OutputPage &$outputPage, \ParserOutput $parserOutput, ParserOutputHelper &$parserOutputHelper = null ) { |
||
221 | // check, if we need to omit execution on actions edit, submit, or history |
||
222 | // $action = $outputPage->parserOptions()->getUser()->getRequest()->getVal( "action" ); |
||
|
|||
223 | 1 | $hook = new OutputPageParserOutput( $outputPage, $parserOutput, $parserOutputHelper ); |
|
224 | 1 | return $hook->process(); |
|
225 | 41 | }, |
|
226 | |||
227 | /** |
||
228 | * Hook: ParserFirstCallInit |
||
229 | * |
||
230 | * Called when the parser initializes for the first time. |
||
231 | * |
||
232 | * @see https://www.mediawiki.org/wiki/Manual:Hooks/ParserFirstCallInit |
||
233 | */ |
||
234 | 'ParserFirstCallInit' => function( Parser $parser ) use ( $componentLibrary, $nestingController ) { |
||
235 | 1 | $hook = new ParserFirstCallInit( $parser, $componentLibrary, $nestingController ); |
|
236 | 1 | return $hook->process(); |
|
237 | 41 | }, |
|
238 | |||
239 | 'ScribuntoExternalLibraries' => function( $engine, &$extraLibraries ) { |
||
240 | 2 | if ( $engine == 'lua' ) { |
|
241 | 2 | $extraLibraries['mw.bootstrap'] = 'BootstrapComponents\\LuaLibrary'; |
|
242 | 2 | } |
|
243 | 2 | return true; |
|
244 | 41 | }, |
|
245 | |||
246 | /** |
||
247 | * Hook: SetupAfterCache |
||
248 | * |
||
249 | * Called in Setup.php, after cache objects are set |
||
250 | * |
||
251 | * @see https://www.mediawiki.org/wiki/Manual:Hooks/SetupAfterCache |
||
252 | */ |
||
253 | 'SetupAfterCache' => function() { |
||
254 | 1 | BootstrapManager::getInstance()->addAllBootstrapModules(); |
|
255 | 1 | return true; |
|
256 | 41 | }, |
|
257 | 41 | ]; |
|
258 | } |
||
259 | |||
260 | /** |
||
261 | * @param \Config $myConfig |
||
262 | * |
||
263 | * @throws \MWException cascading {@see \BootstrapComponents\ApplicationFactory} calls |
||
264 | * @throws \ConfigException cascading {@see \Config::get} |
||
265 | * |
||
266 | * @return array |
||
267 | */ |
||
268 | 47 | public function initializeApplications( $myConfig ) { |
|
276 | |||
277 | /** |
||
278 | * @param string $hook |
||
279 | * |
||
280 | * @return boolean |
||
281 | */ |
||
282 | 5 | public function isRegistered( $hook ) { |
|
285 | |||
286 | /** |
||
287 | * @param array $hookList |
||
288 | * |
||
289 | * @return int |
||
290 | */ |
||
291 | 27 | public function register( $hookList ) { |
|
297 | |||
298 | /** |
||
299 | * @param \ConfigFactory $configFactory |
||
300 | * Registers my own configuration, so that it is present during onLoad. See phabricator issue T184837 |
||
301 | * |
||
302 | * @see https://phabricator.wikimedia.org/T184837 |
||
303 | */ |
||
304 | 47 | public function registerMyConfiguration( $configFactory ) { |
|
307 | |||
308 | /** |
||
309 | * Executes the setup process. |
||
310 | * |
||
311 | * @throws \ConfigException |
||
312 | * |
||
313 | * @return int |
||
314 | */ |
||
315 | 2 | public function run() { |
|
325 | |||
326 | /** |
||
327 | * @throws \MWException |
||
328 | */ |
||
329 | 47 | private function assertExtensionBootstrapPresent() { |
|
336 | |||
337 | /** |
||
338 | * Callback for Hook: ImageBeforeProduceHTML |
||
339 | * |
||
340 | * Called before producing the HTML created by a wiki image insertion |
||
341 | * |
||
342 | * @param NestingController $nestingController |
||
343 | * @param \Config $myConfig |
||
344 | * |
||
345 | * @see https://www.mediawiki.org/wiki/Manual:Hooks/ImageBeforeProduceHTML |
||
346 | * |
||
347 | * @return \Closure |
||
348 | */ |
||
349 | 41 | private function createImageBeforeProduceHTMLCallback( $nestingController, $myConfig ) { |
|
365 | |||
366 | /** |
||
367 | * Callback for Hook: InternalParseBeforeLinks |
||
368 | * |
||
369 | * Used to process the expanded wiki code after <nowiki>, HTML-comments, and templates have been treated. |
||
370 | * |
||
371 | * @see https://www.mediawiki.org/wiki/Manual:Hooks/InternalParseBeforeLinks |
||
372 | * |
||
373 | * @return \Closure |
||
374 | */ |
||
375 | private function createInternalParseBeforeLinksCallback() { |
||
387 | |||
388 | /** |
||
389 | * Version number retrieved from extension info array. |
||
390 | * |
||
391 | * @param string $version |
||
392 | * |
||
393 | * @return bool |
||
394 | */ |
||
395 | 1 | private function prepareEnvironment( $version ) { |
|
398 | } |
||
399 |
Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.
The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.
This check looks for comments that seem to be mostly valid code and reports them.