Completed
Pull Request — master (#467)
by
unknown
17:56
created

GanttPrinter::getResultText()   F

Complexity

Conditions 24
Paths 87

Size

Total Lines 115

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 115
rs 3.3333
c 0
b 0
f 0
cc 24
nc 87
nop 2

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
/**
3
 * SMW result printer for Gantt Diagrams using mermaidjs.
4
 * https://github.com/knsv/mermaid
5
 *
6
 * In order to use this printer you need to have
7
 * the Mermaid MediaWiki extension installed.
8
 * https://www.mediawiki.org/wiki/Extension:Mermaid
9
 *
10
 * @file Gantt.php
11
 * @ingroup SemanticResultFormats
12
 *
13
 * @licence GNU GPL v2+
14
 * @author Sebastian Schmid
15
 */
16
17
namespace SRF\Gantt;
18
19
use SMWOutputs;
20
use SMWQueryResult;
21
use SMWResultPrinter;
22
use SMWDITime;
23
use SMWDIBlob;
24
use Html;
25
26
class GanttPrinter extends SMWResultPrinter {
27
28
	protected $mParams = [];
29
	protected $mGantt = null;
30
	protected $mErrors = [];
31
32
	public function getName() {
33
		return wfMessage( 'srf-printername-gantt' )->text();
34
	}
35
36
	public function getParamDefinitions( array $definitions ) {
37
		$params = parent::getParamDefinitions( $definitions );
38
39
		$params[] = [
40
			'type'    => 'string',
41
			'name'    => 'diagramtitle',
42
			'message' => 'srf-paramdesc-gantt-diagramtitle',
43
			'default' => ''
44
		];
45
46
		$params[] = [
47
			'type'    => 'string',
48
			'name'    => 'theme',
49
			'message' => 'srf-paramdesc-gantt-diagramtheme',
50
			'default' => 'default'
51
		];
52
53
		$params[] = [
54
			'type'    => 'string',
55
			'name'    => 'axisformat',
56
			'message' => 'srf-paramdesc-gantt-axisformat',
57
			'default' => '%m/%d/%Y'
58
		];
59
60
		$params[] = [
61
			'type'    => 'string',
62
			'name'    => 'statusmapping',
63
			'message' => 'srf-paramdesc-gantt-statusmapping',
64
			'default' => ''
65
		];
66
67
		$params[] = [
68
			'type'    => 'string',
69
			'name'    => 'prioritymapping',
70
			'message' => 'srf-paramdesc-gantt-prioritymapping',
71
			'default' => ''
72
		];
73
74
		$params[] = [
75
			'type'    => 'integer',
76
			'name'    => 'titletopmargin',
77
			'message' => 'srf-paramdesc-gantt-titletopmargin',
78
			'default' => 25
79
		];
80
81
		$params[] = [
82
			'type'    => 'integer',
83
			'name'    => 'barheight',
84
			'message' => 'srf-paramdesc-gantt-barheight',
85
			'default' => 20
86
		];
87
88
		$params[] = [
89
			'type'    => 'integer',
90
			'name'    => 'leftpadding',
91
			'message' => 'srf-paramdesc-gantt-leftpadding',
92
			'default' => 75
93
		];
94
95
		$params[] = [
96
			'type'    => 'integer',
97
			'name'    => 'bargap',
98
			'message' => 'srf-paramdesc-gantt-bargap',
99
			'default' => 4
100
		];
101
102
		return $params;
103
	}
104
105
	/**
106
	 * Handle (set) the result format parameters
107
	 *
108
	 * @see SMWResultPrinter::handleParameters()
109
	 */
110
	protected function handleParameters( array $params, $outputmode ) {
111
112
		parent::handleParameters( $params, $outputmode );
113
114
		//Set header params
115
		$this->mParams['title'] = trim( $params['diagramtitle'] );
116
		$this->mParams['axisformat'] = trim( $params['axisformat'] );
117
		$this->mParams['statusmapping'] = trim( $params['statusmapping'] );
118
		$this->mParams['prioritymapping'] = trim( $params['prioritymapping'] );
119
		$this->mParams['theme'] = trim( $params['theme'] );
120
121
		//Validate Theme
122
		if ( !in_array( $this->params['theme'], [ 'default', 'neutral', 'dark', 'forest' ] ) ) {
123
			$this->mErrors[] = wfMessage( 'srf-error-gantt-theme' )->text();
124
		}
125
126
		$mapping = [];
127
128
		//Validate mapping
129
		if ( !empty( trim( $params['statusmapping'] ) ) ) {
130
			$paramMapping = explode( ';', trim( $params['statusmapping'] ) );
131
132
			foreach ( $paramMapping as $pm ) {
133
				$pmKeyVal = explode( '=>', $pm, 2);
134
135
				// if no key value pair
136
				if ( count( $pmKeyVal ) !== 2 ) {
137
					$this->mErrors[] = wfMessage( 'srf-error-gantt-mapping-assignment', 'statusmapping' )->text();
138
				} else {
139
					$mapping[trim( $pmKeyVal[0] )] = trim( $pmKeyVal[1] );
140
141
					// check if the common status keys are used
142
					if ( trim( $pmKeyVal[1] ) !== 'active' && trim( $pmKeyVal[1] ) !== 'done' ) {
143
						$this->mErrors[] = wfMessage( 'srf-error-gantt-mapping-keywords' )->text();
144
					}
145
				}
146
			}
147
		}
148
		if ( !empty( trim( $params['prioritymapping'] ) ) ) {
149
			$paramMapping = explode( ';', trim( $params['prioritymapping'] ) );
150
151
			foreach ( $paramMapping as $pm ) {
152
				$pmKeyVal = explode( '=>', $pm, 2 );
153
154
				// if no key value pair
155
				if ( count( $pmKeyVal ) !== 2 ) {
156
					$this->mErrors[] = wfMessage( 'srf-error-gantt-mapping-assignment', 'prioritymapping' )->text();
157
				} else {
158
					$mapping[trim( $pmKeyVal[0] )] = trim( $pmKeyVal[1] );
159
160
					// check if the common status keys are used
161
					if ( trim( $pmKeyVal[1] ) !== 'crit' ) {
162
						$this->mErrors[] = wfMessage( 'srf-error-gantt-mapping-keywords' )->text();
163
					}
164
				}
165
			}
166
		}
167
168
		$this->mGantt = $this->getGantt();
169
170
	}
171
172
	/**
173
	 * Return serialised results in specified format.
174
	 * @param SMWQueryResult $queryResult
175
	 * @param $outputmode
176
	 * @return string
177
	 */
178
	protected function getResultText( SMWQueryResult $queryResult, $outputmode ) {
179
180
		// Show warning if Extension:Mermaid is not available
181
		if ( !class_exists( 'Mermaid' ) && !class_exists( 'Mermaid\\MermaidParserFunction' ) ) {
182
			//wfWarn( 'The SRF Mermaid format needs the Mermaid extension to be installed.' );
183
				$queryResult->addErrors( [wfMessage('')->text()] );
184
			return '';
185
		}
186
187
		// Load general Modules
188
		// First load the dependent modules of Mermaid ext
189
		SMWOutputs::requireResource( 'ext.mermaid' );
190
		SMWOutputs::requireResource( 'ext.mermaid.styles' );
191
		SMWOutputs::requireResource( 'ext.srf.gantt' );
192
193
		//Add Tasks & Sections
194
		while ( $row = $queryResult->getNext() ) {
195
196
			$status = [];
197
			$priority = [];
198
			$startDate = '';
199
			$endDate = '';
200
			$taskID = '';
201
			$taskTitle = '';
202
			$sections = [];
203
204
			// Loop through all field of a row
205
			foreach ( $row as $field ) {
206
207
				$fieldLabel = $field->getPrintRequest()->getLabel();
208
209
				//get values
210
				foreach ( $field->getContent() as $dataItem ) {
211
212
					switch ( $fieldLabel ) {
213
						case 'section':
214
							$sections[$dataItem->getTitle()->getPrefixedDBKey()] = $dataItem->getSortKey();
215
							break;
216
						case 'task':
217
							if ( $dataItem instanceof SMWDIBlob ) {
218
								$taskTitle = $dataItem->getString();
219
								$taskID = $field->getResultSubject()->getTitle()->getPrefixedDBKey();
220
							}
221
							break;
222
						case 'startdate':
223
							if ( $dataItem instanceof SMWDITime ) {
224
								$startDate = $dataItem->getMwTimestamp();
225
							}
226
							break;
227
						case 'enddate':
228
							if ( $dataItem instanceof SMWDITime ) {
229
								$endDate = $dataItem->getMwTimestamp();
230
							}
231
							break;
232
						case 'status':
233
							if ( $dataItem instanceof SMWDIBlob ) {
234
								$status[] = $dataItem->getString();
235
							}
236
							break;
237
						case 'priority':
238
							if ( $dataItem instanceof SMWDIBlob ) {
239
								$priority[] = $dataItem->getString();
240
							}
241
							break;
242
					}
243
				}
244
			}
245
246
			// Add section/Task
247
			// Title, TaskID, StartDate and EndDate are required
248
			if ( $taskID !== '' && $taskTitle !== '' && $startDate !== '' && $endDate !== '' ) {
249
				$this->mGantt->addTask( $taskID, $taskTitle, $status, $priority, $startDate, $endDate );
250
251
				// If no section was found, put task into a dummy section object
252
				// "gantt-no-section#21780240" is used to identify Tasks that with no section (dummy section)
253
				if ( count( $sections ) == 0 ) {
254
					$this->mGantt->addSection( 'gantt-no-section#21780240', '', $startDate, $endDate, $taskID );
255
				} else {
256
					foreach ( $sections as $sectionID => $sectionTitle ) {
257
						$this->mGantt->addSection( $sectionID, $sectionTitle, $startDate, $endDate, $taskID );
258
					}
259
				}
260
			}
261
		}
262
263
		// Improve unique id by adding a random number
264
		$id = uniqid( 'srf-gantt-' . rand( 1, 10000 ) );
265
266
		// Add gantt configurations
267
		$config = [
268
			'theme' => $this->params['theme'],
269
			'gantt' => [
270
				'leftPadding'    => intval( $this->params['leftpadding'] ),
271
				'titleTopMargin' => intval( $this->params['titletopmargin'] ),
272
				'barHeight'      => intval( $this->params['barheight'] ),
273
				'barGap'         => intval( $this->params['bargap'] )
274
			]
275
		];
276
277
		// Manage Output
278
		if ( !empty( $this->mErrors ) ) {
279
			return $queryResult->addErrors( $this->mErrors );
280
		} else {
281
			return Html::rawElement( 'div', [
282
				'id'           => $id,
283
				'class'        => 'srf-gantt',
284
				'data-mermaid' => json_encode( [
285
					'content' => $this->mGantt->getGanttOutput(),
286
					'config'  => $config
287
				], JSON_UNESCAPED_UNICODE )
288
			], Html::rawElement( 'div', [
289
				'class' => 'mermaid-dots',
290
			] ) );
291
		}
292
	}
293
294
	private function getGantt(){
295
		return new Gantt( $this->mParams );
296
	}
297
}