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

SRFTimezones::setRange()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 0
Metric Value
dl 0
loc 4
ccs 0
cts 4
cp 0
rs 10
c 0
b 0
f 0
cc 1
eloc 3
nc 1
nop 2
crap 2
1
<?php
2
3
/**
4
 * Create the iCalendar's vTimezone component
5
 *
6
 * @author HgO
7
 *
8
 * @ingroup SemanticResultFormats
9
 */
10
class SRFTimezones {
11
	private $localTimezones;
12
	
13
	private $transitions;
14
	
15
	private $dateFrom;
16
	private $dateTo;
17
	
18
	private $offsets;
19
20 2
	public function __construct() {
21 2
		global $wgSRFTimezones;
22
		
23 2
		if ( empty( $wgSRFTimezones ) )
24 2
			$this->localTimezones = [];
25
		elseif ( is_array( $wgSRFTimezones ) )
26
			$this->localTimezones = $wgSRFTimezones;
27
		else
28
			$this->localTimezones = [ date_default_timezone_get() ];
29 2
	}
30
	
31
	/**
32
	 * @param array $localTimezones A list of local timezones.
33
	 */
34
	public function setLocalTimezones( $localTimezones ) {
35
		$this->localTimezones = $localTimezones;
36
	}
37
	
38
	/**
39
	 * Set a new range for the generated transitions.
40
	 * 
41
	 * @param $from Timestamp from which transitions are generated.
42
	 * @param $to Timestamp until which transitions are generated.
43
	 */
44
	public function setRange( $from, $to ) {
45
		$this->dateFrom = $from;
46
		$this->dateTo = $to;
47
	}
48
	
49
	/**
50
	 * Increase the range of the generated transitions. 
51
	 *
52
	 * @param int $from Timestamp from which transitions are generated.
53
	 * @param int $to Timestamp until which transitions are generated.
54
	 */
55 2
	public function updateRange( $from, $to ) {
56 2
		if ( $this->dateFrom === null || $from < $this->dateFrom )
57 2
			$this->dateFrom = $from;
58
		
59 2
		if ( $this->dateTo === null || $to > $this->dateTo )
60 2
			$this->dateTo = $to;
61 2
	}
62
	
63
	/**
64
	 * Calculate transitions for each timezone.
65
	 */
66 2
	public function calcTransitions() {
67 2
		$this->transitions = [];
68
	
69 2
		if ( $this->dateFrom === null || $this->dateTo === null )
70 1
			return false;
71
		
72 1
		foreach ( $this->localTimezones as $timezone ) {
73
			try {
74
				$dateTimezone = new DateTimeZone( $timezone );
75
			} catch( Exception $e ) {
76
				continue;
77
			}
78
			
79
			$transitions = $dateTimezone->getTransitions();
80
			
81
			$min = 0;
82
			$max = 1;
83
			foreach ( $transitions as $i => $transition ) {
84
				if ( $transition['ts'] < $this->dateFrom ) {
85
					$min = $i;
86
					continue;
87
				}
88
89
				if ( $transition['ts'] > $this->dateTo ) {
90
					$max = $i;
91
					break;
92
				}
93
			}
94
			
95
			$this->offsets[$timezone] = $transitions[max( $min-1, 0 )]['offset'];
96
			$this->transitions[$timezone] = array_slice( $transitions, $min, $max - $min );
97
		}
98 1
	}
99
	
100
	/**
101
	 * Generate the transitions for a given range, for each timezones, in the iCalendar format.
102
	 */
103 2
	public function getIcalForTimezone() {
104 2
		if ( $this->transitions === null )
105
			return false;
106
		
107 2
		$result = '';
108
		
109 2
		foreach ( $this->transitions as $timezone => $transitions ) {
110
			// cf. http://www.kanzaki.com/docs/ical/vtimezone.html
111
			$result .= "BEGIN:VTIMEZONE\r\n";
112
			$result .= "TZID:$timezone\r\n";
113
		
114
			$tzfrom = $this->offsets[$timezone] / 3600;
115
			foreach ( $transitions as $transition ) {
116
				$dst = ( $transition['isdst'] ) ? "DAYLIGHT" : "STANDARD";
117
				$result .= "BEGIN:$dst\r\n";
118
				
119
				$start_date = date( 'Ymd\THis', $transition['ts'] );
120
				$result .= "DTSTART:$start_date\r\n";
121
				
122
				$offset = $transition['offset'] / 3600;
123
				
124
				$offset_from = $this->formatTimezoneOffset( $tzfrom );
125
				$result .= "TZOFFSETFROM:$offset_from\r\n";
126
127
				$offset_to = $this->formatTimezoneOffset( $offset );
128
				$result .= "TZOFFSETTO:$offset_to\r\n";
129
				
130
				if ( !empty( $transition['abbr'] ) )
131
					$result .= "TZNAME:{$transition['abbr']}\r\n";
132
				
133
				$result .= "END:$dst\r\n";
134
				
135
				$tzfrom = $offset;
136
			}
137
			
138
			$result .= "END:VTIMEZONE\r\n";
139
		}
140
		
141 2
		return $result;
142
	}
143
	
144
	/**
145
	 * Format an integer offset to '+hhii', where hh are the hours, and ii the minutes
146
	 *
147
	 * @param int $offset
148
	 */
149
	private function formatTimezoneOffset( $offset ) {
150
		return sprintf('%s%02d%02d', $offset >= 0 ? '+' : '', floor($offset), ($offset - floor($offset)) * 60);
151
	}
152
}
153