Completed
Branch master (ecb46d)
by Tobias
01:39
created

Carousel::buildImageString()   A

Complexity

Conditions 4
Paths 8

Size

Total Lines 14
Code Lines 10

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 12
CRAP Score 4

Importance

Changes 0
Metric Value
dl 0
loc 14
ccs 12
cts 12
cp 1
rs 9.2
c 0
b 0
f 0
cc 4
eloc 10
nc 8
nop 2
crap 4
1
<?php
2
/**
3
 * Contains the component class for rendering a carousel.
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\Component;
28
29
use BootstrapComponents\AbstractComponent;
30
use BootstrapComponents\ParserRequest;
31
use \Html;
32
33
/**
34
 * Class Carousel
35
 *
36
 * Class for component 'carousel'
37
 *
38
 * @see   https://github.com/oetterer/BootstrapComponents/blob/master/docs/components.md#Carousel
39
 * @since 1.0
40
 */
41
class Carousel extends AbstractComponent {
42
	/**
43
	 * @inheritdoc
44
	 *
45
	 * @param string $input
46
	 */
47 5
	public function placeMe( $input ) {
48 5
		$images = $this->extractAndParseImageList( $this->getParserRequest() );
49 5
		if ( !count( $images ) ) {
50 2
			return $this->getParserOutputHelper()->renderErrorMessage( 'bootstrap-components-carousel-images-missing' );
51
		}
52
53 4
		$class = [ 'carousel', 'slide' ];
54 4
		list ( $class, $style ) = $this->processCss( $class, [] );
55
56
		return [
57 4
			Html::rawElement(
58 4
				'div',
59
				[
60 4
					'class'     => $this->arrayToString( $class, ' ' ),
61 4
					'style'     => $this->arrayToString( $style, ';' ),
62 4
					'id'        => $this->getId(),
63 4
					'data-ride' => 'carousel',
64 4
				],
65 4
				$this->generateIndicators( count( $images ) )
66 4
				. Html::rawElement(
67 4
					'div',
68 4
					[ 'class' => 'carousel-inner' ],
69 4
					$this->convertImagesIntoSlides( $images )
70 4
				)
71 4
				. $this->buildControls()
72 4
			),
73 4
			"isHTML"  => true,
74 4
			"noparse" => true,
75 4
		];
76
	}
77
78
	/**
79
	 * Responsible for generating the a tags that make up the prev and next controls.
80
	 *
81
	 * @return string
82
	 */
83 4
	private function buildControls() {
84 4
		return Html::rawElement(
85 4
				'a',
86
				[
87 4
					'class'      => 'left carousel-control',
88 4
					'href'       => '#' . $this->getId(),
89 4
					'data-slide' => 'prev',
90 4
				],
91 4
				Html::rawElement( 'span', [ 'class' => 'glyphicon glyphicon-chevron-left' ] )
92 4
			) . Html::rawElement(
93 4
				'a',
94
				[
95 4
					'class'      => 'right carousel-control',
96 4
					'href'       => '#' . $this->getId(),
97 4
					'data-slide' => 'next',
98 4
				],
99 4
				Html::rawElement( 'span', [ 'class' => 'glyphicon glyphicon-chevron-right' ] )
100 4
			);
101
	}
102
103
	/**
104
	 * @param string $attribute
105
	 * @param string $value
106
	 *
107
	 * @return false|string
108
	 */
109 5
	private function buildImageString( $attribute, $value ) {
110 5
		$imageParts = [];
111 5
		if ( !is_int( $attribute ) ) {
112 5
			$imageParts[] = $attribute;
113 5
		}
114 5
		if ( is_string( $value ) ) {
115 5
			$imageParts[] = $value;
116 5
		}
117 5
		$imageString = implode( '=', $imageParts );
118 5
		if ( preg_match( '/\[.+\]/', $imageString ) ) {
119 4
			return $imageString;
120
		}
121 4
		return false;
122
	}
123
124
	/**
125
	 * Converts the carousel image into slides.
126
	 *
127
	 * @param string[] $images
128
	 *
129
	 * @return string
130
	 */
131 4
	private function convertImagesIntoSlides( $images ) {
132 4
		$slides = PHP_EOL;
133 4
		$active = ' active';
134 4
		foreach ( $images as $image ) {
135 4
			$slides .= "\t" . Html::rawElement(
136 4
					'div',
137 4
					[ 'class' => 'item' . $active ],
138
					$image
139 4
				) . PHP_EOL;
140 4
			$active = '';
141 4
		}
142 4
		return $slides;
143
	}
144
145
	/**
146
	 * Extracts and parses all images for the carousel.
147
	 *
148
	 * @param ParserRequest $parserRequest
149
	 *
150
	 * @return string[]
151
	 */
152 5
	private function extractAndParseImageList( ParserRequest $parserRequest ) {
153 5
		$elements = [];
154 5
		if ( !empty( $parserRequest->getInput() ) ) {
155 5
			$elements[] = $parserRequest->getInput();
156 5
		}
157 5
		$elements = array_merge( $elements, $parserRequest->getAttributes() );
158 5
		$images = [];
159 5
		foreach ( $elements as $key => $val ) {
160 5
			$imageString = $this->buildImageString( $key, $val );
161 5
			if ( is_string( $imageString ) ) {
162
				// we assume an image, local or remote
163 4
				$images[] = $parserRequest->getParser()->recursiveTagParse(
164 4
					$imageString,
165 4
					$parserRequest->getFrame()
166 4
				);
167 4
			}
168 5
		}
169 5
		return $images;
170
	}
171
172
	/**
173
	 * Generates the dots in the bottom section that let you jump to a specific image.
174
	 *
175
	 * @param int $num
176
	 *
177
	 * @return string
178
	 */
179 4
	private function generateIndicators( $num ) {
180 4
		$inner = PHP_EOL;
181 4
		$class = 'active';
182 4
		for ( $i = 0; $i < $num; $i++ ) {
183 4
			$inner .= "\t" . Html::rawElement(
184 4
					'li',
185
					[
186 4
						'data-target'   => '#' . $this->getId(),
187 4
						'data-slide-to' => $i,
188 4
						'class'         => $class,
189
					]
190 4
				) . PHP_EOL;
191 4
			$class = false;
192 4
		}
193 4
		return PHP_EOL . Html::rawElement(
194 4
				'ol',
195 4
				[ 'class' => 'carousel-indicators' ],
196
				$inner
197 4
			) . PHP_EOL;
198
	}
199
}