Completed
Push — master ( 4a8b61...552173 )
by Tobias
10:10
created

LuaLibrary::processKeyValuePair()   B

Complexity

Conditions 5
Paths 4

Size

Total Lines 11
Code Lines 8

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 4
CRAP Score 6.9683

Importance

Changes 1
Bugs 0 Features 1
Metric Value
c 1
b 0
f 1
dl 0
loc 11
ccs 4
cts 7
cp 0.5714
rs 8.8571
cc 5
eloc 8
nc 4
nop 2
crap 6.9683
1
<?php
2
/**
3
 * Contains the class handling the scribunto lua support.
4
 *
5
 * @copyright (C) 2018, Tobias Oetterer, Paderborn University
6
 * @license       https://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 BootstrapComponents.
9
 * The BootstrapComponents extension is free software: you can redistribute it
10
 * and/or modify it under the terms of the GNU General Public License as published
11
 * by the Free Software Foundation, either version 3 of the License, or
12
 * (at your option) any later version.
13
 *
14
 * The BootstrapComponents 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 <https://www.gnu.org/licenses/>.
21
 *
22
 * @file
23
 * @ingroup       BootstrapComponents
24
 * @author        Tobias Oetterer
25
 */
26
27
namespace BootstrapComponents;
28
29
use \ReflectionClass;
30
use \Scribunto_LuaEngine;
31
use \Scribunto_LuaLibraryBase;
32
33
/**
34
 * Class LuaLibrary
35
 *
36
 * Class to handle the scribunto lua support.
37
 *
38
 * @since 1.1
39
 */
40
class LuaLibrary extends Scribunto_LuaLibraryBase {
41
42
	/**
43
	 * @var ApplicationFactory $applicationFactory;
44
	 */
45
	private $applicationFactory;
46
47
	/**
48
	 * LuaLibrary constructor.
49
	 *
50
	 * @param Scribunto_LuaEngine $engine
51
	 */
52 19
	public function __construct( $engine ) {
53 19
		parent::__construct( $engine );
54 19
		$this->applicationFactory = ApplicationFactory::getInstance();
55 19
	}
56
57
	/**
58
	 * @return array
59
	 */
60 11
	public function register() {
61
62
		$lib = [
63 11
			'parse'   => [ $this, 'parse' ],
64 11
			'getSkin' => [ $this, 'getSkin' ],
65 11
		];
66
67 11
		return $this->getEngine()->registerInterface( __DIR__ . '/../lua/mw.bootstrap.lua', $lib, [] );
68
	}
69
70
	/**
71
	 * @param string $componentName
72
	 * @param string $input
73
	 * @param array  $arguments
74
	 *
75
	 * @throws \ReflectionException
76
	 * @throws \MWException
77
	 *
78
	 * @return string[]
79
	 */
80 8
	public function parse( $componentName, $input, $arguments ) {
81
82 8
		if ( empty( $componentName ) ) {
83 5
			return [ wfMessage( 'bootstrap-components-lua-error-no-component' )->text() ];
84
		}
85 5
		$componentLibrary = $this->getApplicationFactory()->getComponentLibrary();
86 5
		if ( !in_array( $componentName, $componentLibrary->getRegisteredComponents() ) ) {
87 3
			return [ wfMessage( 'bootstrap-components-lua-error-invalid-component', $componentName )->text() ];
88
		}
89 4
		$componentClass = $componentLibrary->getClassFor( $componentName );
90 4
		$parserRequest = $this->buildParserRequest( $input, $arguments, $componentName );
91 4
		$component = $this->getComponent( $componentClass );
92
93 4
		$parsedComponent = $component->parseComponent( $parserRequest );
94 4
		if ( is_array( $parsedComponent ) ) {
95
			$parsedComponent = $parsedComponent[0];
96
		}
97
98 4
		return [ $parsedComponent ];
99
	}
100
101
	/**
102
	 * @throws \MWException
103
	 *
104
	 * @return string[]
105
	 */
106 4
	public function getSkin() {
107 4
		return [ $this->getApplicationFactory()->getParserOutputHelper( $this->getParser() )->getNameOfActiveSkin() ];
108
	}
109
110
	/**
111
	 * @param string      $input
112
	 * @param array       $arguments
113
	 * @param null|string $component
114
	 *
115
	 * @throws \MWException
116
	 *
117
	 * @return \BootstrapComponents\ParserRequest
118
	 */
119 4
	protected function buildParserRequest( $input, $arguments, $component = null ) {
120
121
		// prepare the arguments array
122 4
		$parserRequestArguments = $this->processLuaArguments( $arguments );
123 4
		array_unshift( $parserRequestArguments, $input );
124 4
		array_unshift( $parserRequestArguments, $this->getParser() );
125
126 4
		return ApplicationFactory::getInstance()->getNewParserRequest( $parserRequestArguments, true, $component );
127
	}
128
129
	/**
130
	 * @param string $componentClass
131
	 *
132
	 * @throws \MWException
133
	 * @throws \ReflectionException
134
	 *
135
	 * @return AbstractComponent
136
	 */
137 4
	protected function getComponent( $componentClass ) {
138
139 4
		$objectReflection = new ReflectionClass( $componentClass );
140
		/** @var AbstractComponent $component */
141 4
		$component = $objectReflection->newInstanceArgs(
142
			[
143 4
				$this->getApplicationFactory()->getComponentLibrary(),
144 4
				$this->getApplicationFactory()->getParserOutputHelper( $this->getParser() ),
145 4
				$this->getApplicationFactory()->getNestingController(),
146
			]
147 4
		);
148 4
		return $component;
149
	}
150
151
	/**
152
	 * @return ApplicationFactory
153
	 */
154 8
	protected function getApplicationFactory() {
155 8
		return $this->applicationFactory;
156
	}
157
158
	/**
159
	 * Takes the $arguments passed from lua and pre-processes them: make sure,
160
	 * we have a sequence array (not associative)
161
	 *
162
	 * @param string|array $arguments
163
	 *
164
	 * @return array
165
	 */
166 4
	private function processLuaArguments( $arguments ) {
167
168
		// make sure, we have an array of parameters
169 4
		if ( !is_array( $arguments ) ) {
170
			$arguments = preg_split( "/(?<=[^\|])\|(?=[^\|])/", $arguments );
171
		}
172
173
		// if $arguments were supplied as key => value pair (aka associative array),
174
		// we rectify this here
175 4
		$processedArguments = [];
176 4
		foreach ( $arguments as $key => $value ) {
177 2
			$processedArguments[] = $this->processKeyValuePair( $key, $value );
178 4
		}
179
180 4
		return $processedArguments;
181
	}
182
183
	/**
184
	 * @param string $key
185
	 * @param string $value
186
	 *
187
	 * @return string
188
	 */
189 2
	private function processKeyValuePair( $key, $value ) {
190 2
		if ( is_int( $key ) || preg_match( '/[0-9]+/', $key ) ) {
191
			return trim( $value );
192
		}
193 2
		if ( is_array( $value ) ) {
194
			$glue = $key == 'style' ? ';' : ' ';
195
			return (string) $key . '=' . implode( $glue, $value );
196
		} else {
197 2
			return (string) $key . '=' . (string) $value;
198
		}
199
	}
200
}