Completed
Push — master ( d3d832...67979d )
by mw
57:02 queued 55:38
created

vCardFileExportPrinter   F

Complexity

Total Complexity 78

Size/Duplication

Total Lines 382
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 6

Test Coverage

Coverage 63.4%

Importance

Changes 0
Metric Value
wmc 78
lcom 1
cbo 6
dl 0
loc 382
ccs 123
cts 194
cp 0.634
rs 2.16
c 0
b 0
f 0

12 Methods

Rating   Name   Duplication   Size   Complexity  
A getName() 0 3 1
A getMimeType() 0 3 1
A getFileName() 0 8 2
A getQueryMode() 0 3 2
A getResultText() 0 11 2
A getVCardLink() 0 26 4
A getVCardContent() 0 31 3
B newVCard() 0 66 2
A isPublic() 0 13 3
F mapField() 0 146 53
A getFieldCommaList() 0 10 3
A getFieldValue() 0 10 2

How to fix   Complexity   

Complex Class

Complex classes like vCardFileExportPrinter often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes. You can also have a look at the cohesion graph to spot any un-connected, or weakly-connected components.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use vCardFileExportPrinter, and based on these observations, apply Extract Interface, too.

1
<?php
2
3
namespace SRF\vCard;
4
5
use SMWExportPrinter as FileExportPrinter;
6
use SMWQuery as Query;
7
use SMWQueryProcessor as QueryProcessor;
8
use SMWQueryResult as QueryResult;
9
use SMWTimeValue as TimeValue;
10
use WikiPage;
11
12
/**
13
 * Printer class for creating vCard exports
14
 *
15
 * @see http://www.semantic-mediawiki.org/wiki/vCard
16
 * @see https://tools.ietf.org/html/rfc6350
17
 * @see https://www.w3.org/2002/12/cal/vcard-notes.html
18
 *
19
 * @license GNU GPL v2+
20
 * @since 1.5
21
 *
22
 * @author Markus Krötzsch
23
 * @author Denny Vrandecic
24
 * @author Frank Dengler
25
 * @author mwjames
26
 */
27
class vCardFileExportPrinter extends FileExportPrinter {
28
29
	/**
30
	 * @see FileExportPrinter::getName
31
	 *
32
	 * @since 1.8
33
	 *
34
	 * {@inheritDoc}
35
	 */
36
	public function getName() {
37
		return wfMessage( 'srf_printername_vcard' )->text();
38
	}
39
40
	/**
41
	 * @see FileExportPrinter::getMimeType
42
	 *
43
	 * @since 1.8
44
	 *
45
	 * {@inheritDoc}
46
	 */
47
	public function getMimeType( QueryResult $queryResult ) {
48
		return 'text/x-vcard';
49
	}
50
51
	/**
52
	 * @see FileExportPrinter::getFileName
53
	 *
54
	 * @since 1.8
55
	 *
56
	 * {@inheritDoc}
57
	 */
58 1
	public function getFileName( QueryResult $queryResult ) {
59
60 1
		if ( $this->getSearchLabel( SMW_OUTPUT_WIKI ) != '' ) {
61 1
			return str_replace( ' ', '_', $this->getSearchLabel( SMW_OUTPUT_WIKI ) ) . '.vcf';
62
		}
63
64
		return 'vCard.vcf';
65
	}
66
67
	/**
68
	 * @see FileExportPrinter::getQueryMode
69
	 *
70
	 * @since 1.8
71
	 *
72
	 * {@inheritDoc}
73
	 */
74 1
	public function getQueryMode( $context ) {
75 1
		return ( $context == QueryProcessor::SPECIAL_PAGE ) ? Query::MODE_INSTANCES : Query::MODE_NONE;
76
	}
77
78
	/**
79
	 * @see ResultPrinter::getResultText
80
	 */
81 1
	protected function getResultText( QueryResult $res, $outputMode ) {
82
83
		// Always return a link for when the output mode is not a file request,
84
		// a file request is normally only initiated when resolving the query
85
		// via Special:Ask
86 1
		if ( $outputMode !== SMW_OUTPUT_FILE ) {
87
			return $this->getVCardLink( $res, $outputMode );
88
		}
89
90 1
		return $this->getVCardContent( $res );
91
	}
92
93
	private function getVCardLink( QueryResult $res, $outputMode ) {
94
95
		// Can be viewed as HTML if requested, no more parsing needed
96
		$this->isHTML = $outputMode == SMW_OUTPUT_HTML;
97
98
		if ( $this->getSearchLabel( $outputMode ) ) {
99
			$label = $this->getSearchLabel( $outputMode );
100
		} else {
101
			$label = wfMessage( 'srf_vcard_link' )->inContentLanguage()->text();
102
		}
103
104
		$link = $res->getQueryLink( $label );
105
		$link->setParameter( 'vcard', 'format' );
106
107
		if ( $this->getSearchLabel( SMW_OUTPUT_WIKI ) != '' ) {
108
			$link->setParameter( $this->getSearchLabel( SMW_OUTPUT_WIKI ), 'searchlabel' );
109
		}
110
111
		if ( array_key_exists( 'limit', $this->params ) ) {
112
			$link->setParameter( $this->params['limit'], 'limit' );
113
		} else { // use a reasonable default limit
114
			$link->setParameter( 20, 'limit' );
115
		}
116
117
		return $link->getText( $outputMode, $this->mLinker );
118
	}
119
120
	/**
121
	 * @param QueryResult $res
122
	 *
123
	 * @return string
124
	 * @throws \MWException
125
	 */
126 1
	private function getVCardContent( $res ) {
127
128 1
		$result = '';
129 1
		$vCards = [];
130
131 1
		$row = $res->getNext();
132 1
		$isPublic = $this->isPublic();
133
134 1
		while ( $row !== false ) {
135
			// Subject of the Result
136 1
			$subject = $row[0]->getResultSubject();
137 1
			$title = $subject->getTitle();
138
139
			// Specifies a value that represents a persistent, globally unique
140
			// identifier associated with the object.
141 1
			$uri = $title->getFullURL();
142
143
			// A timestamp for the last time the vCard was updated
144 1
			$timestamp = WikiPage::factory( $title )->getTimestamp();
145 1
			$text = $title->getText();
146
147 1
			$vCards[] = $this->newVCard( $row, $uri, $text, $timestamp, $isPublic );
148 1
			$row = $res->getNext();
149
		}
150
151 1
		foreach ( $vCards as $vCard ) {
152 1
			$result .= $vCard->text();
153
		}
154
155 1
		return $result;
156
	}
157
158 1
	private function newVCard( $row, $uri, $text, $timestamp, $isPublic ) {
159
160 1
		$vCard = new vCard(
161 1
			$uri,
162 1
			$text,
163
			[
164
165
				// something like 'Dr.'
166 1
				'prefix' => '',
167
168
				// given name
169
				'firstname' => '',
170
171
				// family name
172
				'lastname' => '',
173
174
				// typically the "middle" name (second first name)
175
				'additionalname' => '',
176
177
				// things like "jun." or "sen."
178
				'suffix' => '',
179
180
				// the "formatted name", may be independent from
181
				// first/lastname & co.
182
				'fullname' => '',
183
184
				'tel' => [],
185
				'address' => [],
186
				'email' => [],
187
				// a date
188
				'birthday' => '',
189
190
				// organisational details
191
				'organization' => '',
192
				'department' => '',
193
				'title' => '',
194
				'role' => '',
195
				'category' => '',
196
197
				 // homepage, a legal URL
198
				'url' => '',
199
200
				// any text
201
				'note' => ''
202
			]
203
		);
204
205 1
		$tels = [];
206 1
		$emails = [];
207
208 1
		$addresses['work'] = new Address( 'WORK' );
0 ignored issues
show
Coding Style Comprehensibility introduced by
$addresses was never initialized. Although not strictly required by PHP, it is generally a good practice to add $addresses = array(); before regardless.

Adding an explicit array definition is generally preferable to implicit array definition as it guarantees a stable state of the code.

Let’s take a look at an example:

foreach ($collection as $item) {
    $myArray['foo'] = $item->getFoo();

    if ($item->hasBar()) {
        $myArray['bar'] = $item->getBar();
    }

    // do something with $myArray
}

As you can see in this example, the array $myArray is initialized the first time when the foreach loop is entered. You can also see that the value of the bar key is only written conditionally; thus, its value might result from a previous iteration.

This might or might not be intended. To make your intention clear, your code more readible and to avoid accidental bugs, we recommend to add an explicit initialization $myArray = array() either outside or inside the foreach loop.

Loading history...
209 1
		$addresses['home'] = new Address( 'HOME' );
210
211 1
		foreach ( $row as $field ) {
212 1
			$this->mapField( $field, $vCard, $tels, $addresses, $emails );
213
		}
214
215 1
		$vCard->set( 'tel', $tels );
216 1
		$vCard->set( 'address', $addresses );
217 1
		$vCard->set( 'email', $emails );
218
219 1
		$vCard->isPublic( $isPublic );
220 1
		$vCard->setTimestamp( $timestamp );
221
222 1
		return $vCard;
223
	}
224
225 1
	private function isPublic() {
226
		// heuristic for setting confidentiality level of vCard:
227 1
		global $wgGroupPermissions;
228
229 1
		if ( ( array_key_exists( '*', $wgGroupPermissions ) ) && ( array_key_exists(
230 1
				'read',
231 1
				$wgGroupPermissions['*']
232
			) ) ) {
233 1
			return $wgGroupPermissions['*']['read'];
234
		}
235
236
		return true;
237
	}
238
239 1
	private function mapField( $field, $vCard, &$tels, &$addresses, &$emails ) {
240
241 1
		$printRequest = $field->getPrintRequest();
242
243 1
		switch ( strtolower( $printRequest->getLabel() ) ) {
244 1
			case "name":
245 1
				$vCard->set( 'fullname', $this->getFieldValue( $field ) );
246 1
				break;
247 1
			case "prefix":
248
				$vCard->set( 'prefix', $this->getFieldCommaList( $field ) );
249
				break;
250 1
			case "suffix":
251
				$vCard->set( 'suffix', $this->getFieldCommaList( $field ) );
252
				break;
253 1
			case "firstname":
254
				// save only the first
255
				$vCard->set( 'firstname', $this->getFieldValue( $field ) );
256
				break;
257 1
			case "additionalname":
258 1
			case "extraname":
259
				$vCard->set( 'additionalname', $this->getFieldCommaList( $field ) );
260
				break;
261 1
			case "lastname":
262
				// save only the first
263
				$vCard->set( 'lastname', $this->getFieldValue( $field ) );
264
				break;
265 1
			case "note":
266 1
				$vCard->set( 'note', $this->getFieldCommaList( $field ) );
267 1
				break;
268 1
			case "category":
269 1
				$vCard->set( 'category', $this->getFieldCommaList( $field ) );
270 1
			case "email":
271 1
				while ( $value = $field->getNextDataValue() ) {
272 1
					$emails[] = new Email( 'INTERNET', $value->getShortWikiText() );
273
				}
274 1
				break;
275 1
			case "workphone":
276
				while ( $value = $field->getNextDataValue() ) {
277
					$tels[] = new Tel( 'WORK', $value->getShortWikiText() );
278
				}
279
				break;
280 1
			case "cellphone":
281 1
				while ( $value = $field->getNextDataValue() ) {
282 1
					$tels[] = new Tel( 'CELL', $value->getShortWikiText() );
283
				}
284 1
				break;
285 1
			case "homephone":
286 1
				while ( $value = $field->getNextDataValue() ) {
287 1
					$tels[] = new Tel( 'HOME', $value->getShortWikiText() );
288
				}
289 1
				break;
290 1
			case "organization":
291
				$vCard->set( 'organization', $this->getFieldValue( $field ) );
292
				break;
293 1
			case "workpostofficebox":
294
				if ( ( $workpostofficebox = $this->getFieldValue( $field ) ) !== '' ) {
295
					$addresses['work']->set( 'pobox', $workpostofficebox );
296
				}
297
				break;
298 1
			case "workextendedaddress":
299
				if ( ( $workextendedaddress = $this->getFieldValue( $field ) ) !== '' ) {
300
					$addresses['work']->set( 'ext', $workextendedaddress );
301
				}
302
				break;
303 1
			case "workstreet":
304
				if ( ( $workstreet = $this->getFieldValue( $field ) ) !== '' ) {
305
					$addresses['work']->set( 'street', $workstreet );
306
				}
307
				break;
308 1
			case "worklocality":
309
				if ( ( $worklocality = $this->getFieldValue( $field ) ) !== '' ) {
310
					$addresses['work']->set( 'locality', $worklocality );
311
				}
312
				break;
313 1
			case "workregion":
314
				if ( ( $workregion = $this->getFieldValue( $field ) ) !== '' ) {
315
					$addresses['work']->set( 'region', $workregion );
316
				}
317
				break;
318 1
			case "workpostalcode":
319
				if ( ( $workpostalcode = $this->getFieldValue( $field ) ) !== '' ) {
320
					$addresses['work']->set( 'code', $workpostalcode );
321
				}
322
				break;
323 1
			case "workcountry":
324
				if ( ( $workcountry = $this->getFieldValue( $field ) ) !== '' ) {
325
					$addresses['work']->set( 'country', $workcountry );
326
				}
327
				break;
328 1
			case "homepostofficebox":
329
				if ( ( $homepostofficebox = $this->getFieldValue( $field ) ) !== '' ) {
330
					$addresses['home']->set( 'pobox', $homepostofficebox );
331
				}
332
				break;
333 1
			case "homeextendedaddress":
334
				if ( ( $homeextendedaddress = $this->getFieldValue( $field ) ) !== '' ) {
335
					$addresses['home']->set( 'ext', $homeextendedaddress );
336
				}
337
				break;
338 1
			case "homestreet":
339 1
				if ( ( $homestreet = $this->getFieldValue( $field ) ) !== '' ) {
340 1
					$addresses['home']->set( 'street', $homestreet );
341
				}
342 1
				break;
343 1
			case "homelocality":
344 1
				if ( ( $homelocality = $this->getFieldValue( $field ) ) !== '' ) {
345 1
					$addresses['home']->set( 'locality', $homelocality );
346
				}
347 1
				break;
348 1
			case "homeregion":
349
				if ( ( $homeregion = $this->getFieldValue( $field ) ) !== '' ) {
350
					$addresses['home']->set( 'region', $homeregion );
351
				}
352
				break;
353 1
			case "homepostalcode":
354
				if ( ( $homepostalcode = $this->getFieldValue( $field ) ) !== '' ) {
355
					$addresses['home']->set( 'code', $homepostalcode );
356
				}
357
				break;
358 1
			case "homecountry":
359
				if ( ( $homecountry = $this->getFieldValue( $field ) ) !== '' ) {
360
					$addresses['home']->set( 'country', $homecountry );
361
				}
362
				break;
363 1
			case "birthday":
364 1
				if ( $printRequest->getTypeID() == TimeValue::TYPE_ID ) {
365 1
					$value = $field->getNextDataValue();
366
367 1
					if ( $value !== false ) {
368 1
						$birthday = $value->getISO8601Date();
369 1
						$vCard->set( 'birthday', $birthday );
370
					}
371
				}
372 1
				break;
373 1
			case "homepage":
374 1
				if ( $printRequest->getTypeID() == "_uri" ) {
375 1
					$value = $field->getNextDataValue();
376
377 1
					if ( $value !== false ) {
378 1
						$url = $value->getWikiValue();
379 1
						$vCard->set( 'url', $url );
380
					}
381
				}
382 1
				break;
383
		}
384 1
	}
385
386 1
	private function getFieldCommaList( $field ) {
387
388 1
		$list = '';
389
390 1
		while ( $value = $field->getNextDataValue() ) {
391 1
			$list .= ( $list ? ',' : '' ) . $value->getShortWikiText();
392
		}
393
394 1
		return $list;
395
	}
396
397 1
	private function getFieldValue( $field ) {
398
399 1
		$v = '';
400
401 1
		if ( ( $value = $field->getNextDataValue() ) !== false ) {
402 1
			$v = $value->getShortWikiText();
403
		}
404
405 1
		return $v;
406
	}
407
408
}
409