Completed
Push — master ( eadb3e...25e675 )
by
unknown
10:12
created

ParserRequest   A

Complexity

Total Complexity 19

Size/Duplication

Total Lines 169
Duplicated Lines 0 %

Coupling/Cohesion

Components 0
Dependencies 0

Test Coverage

Coverage 96.08%

Importance

Changes 0
Metric Value
wmc 19
lcom 0
cbo 0
dl 0
loc 169
rs 10
c 0
b 0
f 0
ccs 49
cts 51
cp 0.9608

8 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 8 3
A getAttributes() 0 3 1
A getInput() 0 3 1
A getFrame() 0 3 1
A getParser() 0 3 1
A extractParserFunctionOptions() 0 16 5
A getKeyValuePairFrom() 0 16 3
A processArguments() 0 17 4
1
<?php
2
/**
3
 * Contains the class handling the parameters passed by the parser to the parser function / tag.
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 MWException;
30
31
/**
32
 * Class ParserRequest
33
 *
34
 * Class to handle the data passed by the parser to a component.
35
 *
36
 * @since 1.0
37
 */
38
class ParserRequest {
39
	/**
40
	 * @var string[] $attributes
41
	 */
42
	private $attributes;
43
44
	/**
45
	 * @var string $input
46
	 */
47
	private $input;
48
49
	/**
50
	 * @var \PPFrame $frame
51
	 */
52
	private $frame;
53
54
	/**
55
	 * @var \Parser $parser
56
	 */
57
	private $parser;
58
59
	/**
60
	 * ParserRequest constructor.
61
	 *
62
	 * Do not instantiate directly, but use {@see ApplicationFactory::getNewParserRequest}
63
	 * instead.
64
	 *
65
	 * @param array  $argumentsPassedByParser
66
	 * @param bool   $isParserFunction
67
	 * @param string $componentName
68
	 *
69
	 * @see ApplicationFactory::getNewParserRequest
70
	 *
71
	 * @throws MWException
72
	 */
73 36
	public function __construct( $argumentsPassedByParser, $isParserFunction, $componentName = 'unknown' ) {
74 32
		list( $this->input, $attributes, $this->parser, $this->frame ) =
75 36
			$this->processArguments( $argumentsPassedByParser, $isParserFunction, $componentName );
76 32
		$this->attributes = (array)$attributes;
77 32
		if ( !$this->parser || !is_a( $this->parser, 'Parser' ) ) {
78 3
			throw new MWException( 'Invalid parser object passed to component ' . $componentName . '!' );
79
		}
80 29
	}
81
82
	/**
83
	 * Returns the tag attributes / parser function options supplies by the parser.
84
	 *
85
	 * @return string[] associative array `attribute => value`
86
	 */
87 23
	public function getAttributes() {
88 23
		return $this->attributes;
89
	}
90
91
	/**
92
	 * Gets the input supplied by the parser. For tag extensions this is the string between opening and closing tag. For
93
	 * parser functions this is the first option after the double colon.
94
	 *
95
	 * <code>
96
	 *  <bootstrap_panel>This is the input</bootstrap_panel>
97
	 *  {{#bootstrap_icon:This is the input}}
98
	 * </code>
99
	 *
100
	 * @return string
101
	 */
102 23
	public function getInput() {
103 23
		return $this->input;
104
	}
105
106
	/**
107
	 * Tag extensions supply a frame.
108
	 *
109
	 * @return \PPFrame
110
	 */
111 23
	public function getFrame() {
112 23
		return $this->frame;
113
	}
114
115
	/**
116
	 * This is the parser object passed to the parser function or the tag extension.
117
	 *
118
	 * @return \Parser
119
	 */
120 23
	public function getParser() {
121 23
		return $this->parser;
122
	}
123
124
	/**
125
	 * Converts an array of values in form [0] => "name=value" into a real
126
	 * associative array in form [name] => value. If no = is provided,
127
	 * true is assumed like this: [name] => true
128
	 *
129
	 * Note: shamelessly copied, see link below
130
	 *
131
	 * @see https://www.mediawiki.org/w/index.php?title=Manual:Parser_functions&oldid=2572048
132
	 *
133
	 * @param array  $options
134
	 * @param string $componentName
135
	 *
136
	 * @throws MWException
137
	 * @return array $results
138
	 */
139 17
	private function extractParserFunctionOptions( $options, $componentName ) {
140 17
		if ( empty( $options ) ) {
141 12
			return [];
142
		}
143 12
		$results = [];
144 12
		foreach ( $options as $option ) {
145 12
			if ( !is_string( $option ) ) {
146 1
				throw new MWException( 'Arguments passed to bootstrap component "' . $componentName . '" are invalid!' );
147
			}
148 11
			list( $key, $value ) = $this->getKeyValuePairFrom( $option );
149 11
			if ( strlen( $key ) ) {
150 11
				$results[$key] = $value;
151 11
			}
152 11
		}
153 11
		return $results;
154
	}
155
156
	/**
157
	 * @param string $option
158
	 *
159
	 * @return string[]
160
	 */
161 11
	private function getKeyValuePairFrom( $option ) {
162
163 11
		$pair = explode( '=', $option, 2 );
164
165 11
		if ( count( $pair ) === 2 ) {
166 11
			$name = trim( $pair[0] );
167 11
			$value = trim( $pair[1] );
168 11
		} elseif ( count( $pair ) === 1 ) {
169 5
			$name = trim( $pair[0] );
170 5
			$value = true;
171 5
		} else {
172
			$name = '';
173
			$value = false;
174
		}
175 11
		return [ $name, $value ];
176
	}
177
178
	/**
179
	 * Parses the arguments passed to parse() method depending on handler type
180
	 * (parser function or tag extension).
181
	 *
182
	 * @param array  $argumentsPassedByParser
183
	 * @param bool   $isParserFunction
184
	 * @param string $componentName
185
	 *
186
	 * @throws MWException if argument list does not match handler type or unknown handler type detected
187
	 * @return array array consisting of (string) $input, (array) $options, (Parser) $parser, and optional (PPFrame) $frame
188
	 */
189 36
	private function processArguments( $argumentsPassedByParser, $isParserFunction, $componentName ) {
190 36
		$argumentsPassedByParser = (array)$argumentsPassedByParser;
191 36
		if ( $isParserFunction ) {
192 17
			$parser = array_shift( $argumentsPassedByParser );
193 17
			$input = isset( $argumentsPassedByParser[0] ) ? $argumentsPassedByParser[0] : '';
194 17
			unset( $argumentsPassedByParser[0] );
195
196 17
			$attributes = $this->extractParserFunctionOptions( $argumentsPassedByParser, $componentName );
197
198 16
			return [ $input, $attributes, $parser, null ];
199
		} else {
200 20
			if ( count( $argumentsPassedByParser ) != 4 ) {
201 3
				throw new MWException( 'Argument list passed to bootstrap tag component "' . $componentName . '" is invalid!' );
202
			}
203 17
			return $argumentsPassedByParser;
204
		}
205
	}
206
}