Completed
Pull Request — master (#308)
by
unknown
16:57
created

SRFiCalendar::getIcalForItem()   D

Complexity

Conditions 18
Paths 320

Size

Total Lines 74
Code Lines 49

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 46
CRAP Score 18

Importance

Changes 0
Metric Value
dl 0
loc 74
ccs 46
cts 46
cp 1
rs 4.0367
c 0
b 0
f 0
cc 18
eloc 49
nc 320
nop 1
crap 18

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
 * Create iCalendar exports
4
 * @file
5
 * @ingroup SemanticResultFormats
6
 */
7
8
/**
9
 * Printer class for creating iCalendar exports
10
 * 
11
 * @author Markus Krötzsch
12
 * @author Denny Vrandecic
13
 * @author Jeroen De Dauw
14
 * 
15
 * @ingroup SemanticResultFormats
16
 */
17
class SRFiCalendar extends SMWExportPrinter {
18
	
19
	protected $m_title;
20
	protected $m_description;
21
	
22
	protected $m_timezones;
23
24 2
	protected function handleParameters( array $params, $outputmode ) {
25 2
		parent::handleParameters( $params, $outputmode );
26
		
27 2
		$this->m_title = trim( $params['title'] );
28 2
		$this->m_description = trim( $params['description'] );
29 2
	}
30
31
	/**
32
	 * @see SMWIExportPrinter::getMimeType
33
	 *
34
	 * @since 1.8
35
	 *
36
	 * @param SMWQueryResult $queryResult
37
	 *
38
	 * @return string
39
	 */
40
	public function getMimeType( SMWQueryResult $queryResult ) {
41
		return 'text/calendar';
42
	}
43
44
	/**
45
	 * @see SMWIExportPrinter::getFileName
46
	 *
47
	 * @since 1.8
48
	 *
49
	 * @param SMWQueryResult $queryResult
50
	 *
51
	 * @return string|boolean
52
	 */
53
	public function getFileName( SMWQueryResult $queryResult ) {
54
		if ( $this->m_title != '' ) {
55
			return str_replace( ' ', '_', $this->m_title ) . '.ics';
56
		} else {
57
			return 'iCalendar.ics';
58
		}
59
	}
60
61 2
	public function getQueryMode( $context ) {
62 2
		return ( $context == SMWQueryProcessor::SPECIAL_PAGE ) ? SMWQuery::MODE_INSTANCES : SMWQuery::MODE_NONE;
63
	}
64
65
	public function getName() {
66
		return wfMessage( 'srf_printername_icalendar' )->text();
67
	}
68
69 2
	protected function getResultText( SMWQueryResult $res, $outputmode ) {
70 2
		return $outputmode == SMW_OUTPUT_FILE ? $this->getIcal( $res ) : $this->getIcalLink( $res, $outputmode );
71
	}
72
	
73
	/**
74
	 * Returns the query result in iCal.
75
	 * 
76
	 * @since 1.5.2
77
	 *  
78
	 * @param SMWQueryResult $res
79
	 * 
80
	 * @return string
81
	 */
82 2
	protected function getIcal( SMWQueryResult $res ) {
83 2
		global $wgSRFTimezoneTransitions;
84
		
85 2
		$this->m_timezones = new SRFTimezones();
86
		
87 2
		$result = '';
88
		
89 2
		if ( $this->m_title == '' ) {
90 2
			global $wgSitename;
91 2
			$this->m_title = $wgSitename;
92
		}
93
		
94 2
		$result .= "BEGIN:VCALENDAR\r\n";
95 2
		$result .= "PRODID:-//SMW Project//Semantic Result Formats\r\n";
96 2
		$result .= "VERSION:2.0\r\n";
97 2
		$result .= "METHOD:PUBLISH\r\n";
98 2
		$result .= "X-WR-CALNAME:" . $this->m_title . "\r\n";
99
		
100 2
		if ( $this->m_description !== '' ) {
101 2
			$result .= "X-WR-CALDESC:" . $this->m_description . "\r\n";
102
		}
103
104 2
		$events = '';
105 2
		$row = $res->getNext();
106 2
		while ( $row !== false ) {
107 2
			$events .= $this->getIcalForItem( $row );
108
			
109 2
			$row = $res->getNext();
110
		}
111
		
112 2
		$this->m_timezones->calcTransitions();
113 2
		$result .= $this->m_timezones->getIcalForTimezone();
114
		
115 2
		$result .= $events;
116
		
117 2
		$result .= "END:VCALENDAR\r\n";
118
119 2
		return $result;
120
	}
121
122
	/**
123
	 * Returns html for a link to a query that returns the iCal.
124
	 * 
125
	 * @since 1.5.2
126
	 *  
127
	 * @param SMWQueryResult $res
128
	 * @param $outputmode
129
	 * 
130
	 * @return string
131
	 */	
132
	protected function getIcalLink( SMWQueryResult $res, $outputmode ) {
133
		if ( $this->getSearchLabel( $outputmode ) ) {
134
			$label = $this->getSearchLabel( $outputmode );
135
		} else {
136
			$label = wfMessage( 'srf_icalendar_link' )->inContentLanguage()->text();
137
		}
138
		
139
		$link = $res->getQueryLink( $label );
0 ignored issues
show
Deprecated Code introduced by
The method SMWQueryResult::getQueryLink() has been deprecated with message: since SMW 1.8

This method has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the method will be removed from the class and what other method or class to use instead.

Loading history...
140
		$link->setParameter( 'icalendar', 'format' );
141
		
142
		if ( $this->m_title !== '' ) {
143
			$link->setParameter( $this->m_title, 'title' );
144
		}
145
		
146
		if ( $this->m_description !== '' ) {
147
			$link->setParameter( $this->m_description, 'description' );
148
		}
149
		
150
		if ( array_key_exists( 'limit', $this->params ) ) {
151
			$link->setParameter( $this->params['limit'], 'limit' );
152
		} else { // use a reasonable default limit
153
			$link->setParameter( 20, 'limit' );
154
		}
155
156
		// yes, our code can be viewed as HTML if requested, no more parsing needed
157
		$this->isHTML = ( $outputmode == SMW_OUTPUT_HTML ); 
158
		return $link->getText( $outputmode, $this->mLinker );
159
	}
160
	
161
	/**
162
	 * Returns the iCal for a single item.
163
	 * 
164
	 * @since 1.5.2
165
	 * 
166
	 * @param array $row
167
	 * 
168
	 * @return string
169
	 */
170 2
	protected function getIcalForItem( array $row ) {
171 2
		$result = '';
172
		
173 2
		$wikipage = $row[0]->getResultSubject(); // get the object
174 2
		$wikipage = SMWDataValueFactory::newDataItemValue( $wikipage, null );
175
176
		$params = [
177 2
			'summary' => $wikipage->getShortWikiText()
178
		];
179
		
180 2
		$from = null;
181 2
		$to = null;
182 2
		foreach ( $row as /* SMWResultArray */ $field ) {
183
			// later we may add more things like a generic
184
			// mechanism to add whatever you want :)
185
			// could include funny things like geo, description etc. though
186 2
			$req = $field->getPrintRequest();
187 2
			$label = strtolower( $req->getLabel() );
188
			
189
			switch ( $label ) {
190 2
				case 'start': case 'end':
191 1
					if ( $req->getTypeID() == '_dat' ) {
192 1
						$dataValue = $field->getNextDataValue();
193
194 1
						if ( $dataValue === false ) {
195 1
							unset( $params[$label] );
196
						}
197
						else {
198 1
							$params[$label] = $this->parsedate( $dataValue, $label == 'end' );
199
							
200 1
							$timestamp = strtotime( $params[$label] );
201 1
							if ( $from === null || $timestamp < $from )
202 1
								$from = $timestamp;
203 1
							if ( $to === null || $timestamp > $to )
204 1
								$to = $timestamp;
205
						}
206
					}
207 1
					break;
208 2
				case 'location': case 'description': case 'summary':
209 1
					$value = $field->getNextDataValue();
210 1
					if ( $value !== false ) {
211 1
						$params[$label] = $value->getShortWikiText();
212
					}
213 2
					break;
214
			}
215
		}
216
		
217 2
		$this->m_timezones->updateRange( $from, $to );
218
		
219 2
		$title = $wikipage->getTitle();
220 2
		$article = new Article( $title );
221 2
		$url = $title->getFullURL();
222
		
223 2
		$result .= "BEGIN:VEVENT\r\n";
224 2
		$result .= "SUMMARY:" . $this->escapeICalendarText( $params['summary'] ) . "\r\n";
225 2
		$result .= "URL:$url\r\n";
226 2
		$result .= "UID:$url\r\n";
227
		
228 2
		if ( array_key_exists( 'start', $params ) ) $result .= "DTSTART:" . $params['start'] . "\r\n";
229 2
		if ( array_key_exists( 'end', $params ) )   $result .= "DTEND:" . $params['end'] . "\r\n";
230 2
		if ( array_key_exists( 'location', $params ) ) {
231 1
			$result .= "LOCATION:" . $this->escapeICalendarText( $params['location'] ) . "\r\n";
232
		}
233 2
		if ( array_key_exists( 'description', $params ) ) {
234 1
			$result .= "DESCRIPTION:" . $this->escapeICalendarText( $params['description'] ) . "\r\n";
235
		}
236
		
237 2
		$t = strtotime( str_replace( 'T', ' ', $article->getTimestamp() ) );
238 2
		$result .= "DTSTAMP:" . date( "Ymd", $t ) . "T" . date( "His", $t ) . "\r\n";
239 2
		$result .= "SEQUENCE:" . $title->getLatestRevID() . "\r\n";
240 2
		$result .= "END:VEVENT\r\n";
241
		
242 2
		return $result;
243
	}
244
245
	/**
246
	 * Extract a date string formatted for iCalendar from a SMWTimeValue object.
247
	 */
248 1
	static private function parsedate( SMWTimeValue $dv, $isend = false ) {
249 1
		$year = $dv->getYear();
250 1
		if ( ( $year > 9999 ) || ( $year < -9998 ) ) return ''; // ISO range is limited to four digits
251
		
252 1
		$year = number_format( $year, 0, '.', '' );
253 1
		$time = str_replace( ':', '', $dv->getTimeString( false ) );
0 ignored issues
show
Documentation introduced by
false is of type boolean, but the function expects a string.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
254
		
255 1
		if ( ( $time == false ) && ( $isend ) ) { // increment by one day, compute date to cover leap years etc.
256
			$dv = SMWDataValueFactory::newTypeIDValue( '_dat', $dv->getWikiValue() . 'T00:00:00-24:00' );
257
		}
258
		
259 1
		$month = $dv->getMonth();
260 1
		if ( strlen( $month ) == 1 ) $month = '0' . $month;
261
		
262 1
		$day = $dv->getDay();
263 1
		if ( strlen( $day ) == 1 ) $day = '0' . $day;
264
		
265 1
		$result = $year . $month . $day;
266
		
267 1
		if ( $time != false ) $result .= "T$time";
268
		
269 1
		return $result;
270
	}
271
	
272
	/**
273
	 * Implements esaping of special characters for iCalendar properties of type TEXT. This is defined
274
	 * in RFC2445 Section 4.3.11.
275
	 */
276 2
	static private function escapeICalendarText( $text ) {
277
		// Note that \\ is a PHP escaped single \ here
278 2
		return str_replace( [ "\\", "\n", ";", "," ], [ "\\\\", "\\n", "\\;", "\\," ], $text );
279
	}
280
281
	/**
282
	 * @see SMWResultPrinter::getParamDefinitions
283
	 *
284
	 * @since 1.8
285
	 *
286
	 * @param $definitions array of IParamDefinition
287
	 *
288
	 * @return array of IParamDefinition|array
289
	 */
290 2
	public function getParamDefinitions( array $definitions ) {
291 2
		$params = parent::getParamDefinitions( $definitions );
292
293 2
		$params['title'] = [
294
			'default' => '',
295
			'message' => 'srf_paramdesc_icalendartitle',
296
		];
297
298 2
		$params['description'] = [
299
			'default' => '',
300
			'message' => 'srf_paramdesc_icalendardescription',
301
		];
302
303 2
		return $params;
304
	}
305
306
}
307