Passed
Pull Request — master (#23)
by
unknown
08:31
created

SetupAfterCache::process()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 12
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 6
nc 1
nop 0
dl 0
loc 12
rs 10
c 0
b 0
f 0
1
<?php
2
/**
3
 * File holding the SetupAfterCache class
4
 *
5
 * @copyright 2013 - 2019, Stephan Gambke
6
 * @license   http://www.gnu.org/licenses/gpl-3.0.html GNU General Public License, version 3 (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 MediaWiki\Extensions\Bootstrap\Hooks;
27
28
use RuntimeException;
29
use InvalidArgumentException;
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
	 * @callgraph
60
	 *
61
	 * @since 1.0
62
	 *
63
	 * @throws InvalidArgumentException
64
	 * @throws RuntimeException
65
	 */
66
	public function process() {
67
68
		$this->assertAcceptableConfiguration();
69
70
		$this->registerResourceLoaderModules(
71
			$this->isReadablePath( $this->configuration['localBasePath'] ),
72
			$this->configuration[ 'remoteBasePath' ]
73
		);
74
75
		$this->registerCacheTriggers();
76
77
		return true;
78
	}
79
80
	/**
81
	 * Add paths to resource modules if they are not there yet (e.g. set in LocalSettings.php)
82
	 *
83
	 * @param string $localBasePath
84
	 * @param string $remoteBasePath
85
	 */
86
	protected function registerResourceLoaderModules( $localBasePath, $remoteBasePath ) {
87
88
		$GLOBALS[ 'wgResourceModules' ][ 'ext.bootstrap.styles' ] = array_replace_recursive(
89
			[
90
				'localBasePath' => $localBasePath . '/scss',
91
				'remoteBasePath' => $remoteBasePath . '/scss',
92
				'class' => ResourceLoaderSCSSModule::class,
93
				'position' => 'top',
94
				'styles' => [],
95
				'variables' => [],
96
				'dependencies' => [],
97
				'cacheTriggers' => [
98
					'LocalSettings.php' => null,
99
					'composer.lock' => null,
100
				],
101
			],
102
			array_key_exists( 'ext.bootstrap.styles', $GLOBALS[ 'wgResourceModules' ] ) ? $GLOBALS[ 'wgResourceModules' ][ 'ext.bootstrap.styles' ] : []
103
		);
104
105
		$GLOBALS[ 'wgResourceModules' ][ 'ext.bootstrap.scripts' ] = array_replace_recursive(
106
			[
107
				'localBasePath'  => $localBasePath . '/js',
108
				'remoteBasePath' => $remoteBasePath . '/js',
109
				'scripts' => [],
110
			],
111
			array_key_exists( 'ext.bootstrap.scripts', $GLOBALS[ 'wgResourceModules' ] ) ? $GLOBALS[ 'wgResourceModules' ][ 'ext.bootstrap.scripts' ] : []
112
		);
113
114
		$GLOBALS[ 'wgResourceModules' ][ 'ext.bootstrap' ] = [
115
			'dependencies' => [ 'ext.bootstrap.styles', 'ext.bootstrap.scripts' ],
116
		];
117
	}
118
119
	/**
120
	 * @param string $id
121
	 * @return bool
122
	 */
123
	protected function hasConfiguration( $id ) {
124
		return isset( $this->configuration[ $id ] );
125
	}
126
127
	/**
128
	 * @param string $localBasePath
129
	 * @return string
130
	 * @throws RuntimeException
131
	 */
132
	protected function isReadablePath( $localBasePath ) {
133
134
		$localBasePath = str_replace( [ '\\', '/' ], DIRECTORY_SEPARATOR, $localBasePath );
135
136
		if ( is_readable( $localBasePath ) ) {
137
			return $localBasePath;
138
		}
139
140
		throw new RuntimeException( "Expected an accessible {$localBasePath} path" );
141
	}
142
143
	protected function registerCacheTriggers() {
144
145
		$defaultRecacheTriggers = [
146
			'LocalSettings.php' => $this->configuration[ 'IP' ] . '/LocalSettings.php',
147
			'composer.lock' => $this->configuration[ 'IP' ] . '/composer.lock',
148
		];
149
150
		foreach ( $defaultRecacheTriggers as $key => $filename ) {
151
			if ( array_key_exists( $key, $GLOBALS[ 'wgResourceModules' ][ 'ext.bootstrap.styles' ][ 'cacheTriggers' ] ) &&
152
				$GLOBALS[ 'wgResourceModules' ][ 'ext.bootstrap.styles' ][ 'cacheTriggers' ][ $key ] === null ) {
153
				$GLOBALS[ 'wgResourceModules' ][ 'ext.bootstrap.styles' ][ 'cacheTriggers' ][ $key ] = $filename;
154
			}
155
		}
156
	}
157
158
	protected function assertAcceptableConfiguration() {
159
160
		$configElements = [
161
			'localBasePath' => 'Local base path to Bootstrap modules not found.',
162
			'remoteBasePath' => 'Remote base path to Bootstrap modules not found.',
163
			'IP' => 'Full path to working directory ($IP) not found.',
164
		];
165
166
		foreach ( $configElements as $key => $errorMessage ) {
167
			if ( !$this->hasConfiguration( $key ) ) {
168
				throw new InvalidArgumentException( $errorMessage );
169
			}
170
		}
171
	}
172
173
}
174