SetupAfterCache   A
last analyzed

Complexity

Total Complexity 15

Size/Duplication

Total Lines 129
Duplicated Lines 0 %

Importance

Changes 8
Bugs 1 Features 0
Metric Value
wmc 15
eloc 52
c 8
b 1
f 0
dl 0
loc 129
rs 10

7 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 2 1
A process() 0 11 1
A isReadablePath() 0 8 2
A registerResourceLoaderModules() 0 31 3
A registerCacheTriggers() 0 13 4
A hasConfiguration() 0 2 1
A assertAcceptableConfiguration() 0 10 3
1
<?php
2
/**
3
 * File holding the SetupAfterCache class
4
 *
5
 * @copyright 2013 - 2019, Stephan Gambke
6
 * @license   GPL-3.0-or-later
7
 *
8
 * This file is part of the MediaWiki extension Bootstrap.
9
 * The Bootstrap extension is free software: you can redistribute it and/or
10
 * modify it under the terms of the GNU General Public License as published by
11
 * the Free Software Foundation, either version 3 of the License, or
12
 * (at your option) any later version.
13
 *
14
 * The Bootstrap extension is distributed in the hope that it will be useful,
15
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17
 * GNU General Public License for more details.
18
 *
19
 * You should have received a copy of the GNU General Public License
20
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
21
 *
22
 * @file
23
 * @ingroup Bootstrap
24
 */
25
26
namespace Bootstrap\Hooks;
27
28
use InvalidArgumentException;
29
use RuntimeException;
30
use SCSS\ResourceLoaderSCSSModule;
31
32
/**
33
 * Handler for the SetupAfterCache hook.
34
 *
35
 * @see https://www.mediawiki.org/wiki/Manual:Hooks/SetupAfterCache
36
 *
37
 * @since 1.0
38
 *
39
 * @author mwjames
40
 * @author Stephan Gambke
41
 * @ingroup Bootstrap
42
 */
43
class SetupAfterCache {
44
45
	protected $configuration = [];
46
47
	/**
48
	 * @since  1.0
49
	 *
50
	 * @param mixed[] $configuration
51
	 */
52
	public function __construct( array $configuration ) {
53
		$this->configuration = $configuration;
54
	}
55
56
	/**
57
	 * Process the hook
58
	 *
59
	 * @codingStandardsIgnoreStart
60
	 * @callgraph
61
	 * @codingStandardsIgnoreEnd
62
	 *
63
	 * @since 1.0
64
	 *
65
	 * @throws InvalidArgumentException
66
	 * @throws RuntimeException
67
	 * @return bool
68
	 */
69
	public function process() {
70
		$this->assertAcceptableConfiguration();
71
72
		$this->registerResourceLoaderModules(
73
			$this->isReadablePath( $this->configuration['localBasePath'] ),
74
			$this->configuration[ 'remoteBasePath' ]
75
		);
76
77
		$this->registerCacheTriggers();
78
79
		return true;
80
	}
81
82
	/**
83
	 * Add paths to resource modules if they are not there yet (e.g. set in LocalSettings.php)
84
	 *
85
	 * @param string $localBasePath
86
	 * @param string $remoteBasePath
87
	 */
88
	protected function registerResourceLoaderModules( $localBasePath, $remoteBasePath ) {
89
		$GLOBALS[ 'wgResourceModules' ][ 'ext.bootstrap.styles' ] = array_replace_recursive(
90
			[
91
				'localBasePath' => $localBasePath . '/scss',
92
				'remoteBasePath' => $remoteBasePath . '/scss',
93
				'class' => ResourceLoaderSCSSModule::class,
94
				'position' => 'top',
95
				'styles' => [],
96
				'variables' => [],
97
				'dependencies' => [],
98
				'cacheTriggers' => [
99
					'LocalSettings.php' => null,
100
					'composer.lock' => null,
101
				],
102
			],
103
			array_key_exists( 'ext.bootstrap.styles', $GLOBALS[ 'wgResourceModules' ] ) ?
104
				$GLOBALS[ 'wgResourceModules' ][ 'ext.bootstrap.styles' ] : []
105
		);
106
107
		$GLOBALS[ 'wgResourceModules' ][ 'ext.bootstrap.scripts' ] = array_replace_recursive(
108
			[
109
				'localBasePath'  => $localBasePath . '/js',
110
				'remoteBasePath' => $remoteBasePath . '/js',
111
				'scripts' => [],
112
			],
113
			array_key_exists( 'ext.bootstrap.scripts', $GLOBALS[ 'wgResourceModules' ] ) ?
114
				$GLOBALS[ 'wgResourceModules' ][ 'ext.bootstrap.scripts' ] : []
115
		);
116
117
		$GLOBALS[ 'wgResourceModules' ][ 'ext.bootstrap' ] = [
118
			'dependencies' => [ 'ext.bootstrap.styles', 'ext.bootstrap.scripts' ],
119
		];
120
	}
121
122
	/**
123
	 * @param string $id
124
	 * @return bool
125
	 */
126
	protected function hasConfiguration( $id ) {
127
		return isset( $this->configuration[ $id ] );
128
	}
129
130
	/**
131
	 * @param string $localBasePath
132
	 * @return string
133
	 * @throws RuntimeException
134
	 */
135
	protected function isReadablePath( $localBasePath ) {
136
		$localBasePath = str_replace( [ '\\', '/' ], DIRECTORY_SEPARATOR, $localBasePath );
137
138
		if ( is_readable( $localBasePath ) ) {
139
			return $localBasePath;
140
		}
141
142
		throw new RuntimeException( "Expected an accessible {$localBasePath} path" );
143
	}
144
145
	protected function registerCacheTriggers() {
146
		$defaultRecacheTriggers = [
147
			'LocalSettings.php' => $this->configuration[ 'IP' ] . '/LocalSettings.php',
148
			'composer.lock' => $this->configuration[ 'IP' ] . '/composer.lock',
149
		];
150
151
		foreach ( $defaultRecacheTriggers as $key => $filename ) {
152
			if ( array_key_exists( $key,
153
				$GLOBALS[ 'wgResourceModules' ][ 'ext.bootstrap.styles' ][ 'cacheTriggers' ] ) &&
154
				$GLOBALS[ 'wgResourceModules' ][ 'ext.bootstrap.styles' ][ 'cacheTriggers' ][ $key ]
155
					=== null ) {
156
				$GLOBALS[ 'wgResourceModules' ][ 'ext.bootstrap.styles' ][ 'cacheTriggers' ][ $key ] =
157
					$filename;
158
			}
159
		}
160
	}
161
162
	protected function assertAcceptableConfiguration() {
163
		$configElements = [
164
			'localBasePath' => 'Local base path to Bootstrap modules not found.',
165
			'remoteBasePath' => 'Remote base path to Bootstrap modules not found.',
166
			'IP' => 'Full path to working directory ($IP) not found.',
167
		];
168
169
		foreach ( $configElements as $key => $errorMessage ) {
170
			if ( !$this->hasConfiguration( $key ) ) {
171
				throw new InvalidArgumentException( $errorMessage );
172
			}
173
		}
174
	}
175
176
}
177