Completed
Branch develop (35ba9e)
by
unknown
21:24
created
includes/sabre/sabre/vobject/lib/TimezoneGuesser/GuessFromLicEntry.php 1 patch
Indentation   +14 added lines, -14 removed lines patch added patch discarded remove patch
@@ -13,21 +13,21 @@
 block discarded – undo
13 13
  */
14 14
 class GuessFromLicEntry implements TimezoneGuesser
15 15
 {
16
-    public function guess(VTimeZone $vtimezone, bool $failIfUncertain = false): ?DateTimeZone
17
-    {
18
-        if (!isset($vtimezone->{'X-LIC-LOCATION'})) {
19
-            return null;
20
-        }
16
+	public function guess(VTimeZone $vtimezone, bool $failIfUncertain = false): ?DateTimeZone
17
+	{
18
+		if (!isset($vtimezone->{'X-LIC-LOCATION'})) {
19
+			return null;
20
+		}
21 21
 
22
-        $lic = (string) $vtimezone->{'X-LIC-LOCATION'};
22
+		$lic = (string) $vtimezone->{'X-LIC-LOCATION'};
23 23
 
24
-        // Libical generators may specify strings like
25
-        // "SystemV/EST5EDT". For those we must remove the
26
-        // SystemV part.
27
-        if ('SystemV/' === substr($lic, 0, 8)) {
28
-            $lic = substr($lic, 8);
29
-        }
24
+		// Libical generators may specify strings like
25
+		// "SystemV/EST5EDT". For those we must remove the
26
+		// SystemV part.
27
+		if ('SystemV/' === substr($lic, 0, 8)) {
28
+			$lic = substr($lic, 8);
29
+		}
30 30
 
31
-        return TimeZoneUtil::getTimeZone($lic, null, $failIfUncertain);
32
-    }
31
+		return TimeZoneUtil::getTimeZone($lic, null, $failIfUncertain);
32
+	}
33 33
 }
Please login to merge, or discard this patch.
htdocs/includes/sabre/sabre/vobject/lib/ITip/Message.php 1 patch
Indentation   +105 added lines, -105 removed lines patch added patch discarded remove patch
@@ -16,121 +16,121 @@
 block discarded – undo
16 16
  */
17 17
 class Message
18 18
 {
19
-    /**
20
-     * The object's UID.
21
-     *
22
-     * @var string
23
-     */
24
-    public $uid;
19
+	/**
20
+	 * The object's UID.
21
+	 *
22
+	 * @var string
23
+	 */
24
+	public $uid;
25 25
 
26
-    /**
27
-     * The component type, such as VEVENT.
28
-     *
29
-     * @var string
30
-     */
31
-    public $component;
26
+	/**
27
+	 * The component type, such as VEVENT.
28
+	 *
29
+	 * @var string
30
+	 */
31
+	public $component;
32 32
 
33
-    /**
34
-     * Contains the ITip method, which is something like REQUEST, REPLY or
35
-     * CANCEL.
36
-     *
37
-     * @var string
38
-     */
39
-    public $method;
33
+	/**
34
+	 * Contains the ITip method, which is something like REQUEST, REPLY or
35
+	 * CANCEL.
36
+	 *
37
+	 * @var string
38
+	 */
39
+	public $method;
40 40
 
41
-    /**
42
-     * The current sequence number for the event.
43
-     *
44
-     * @var int
45
-     */
46
-    public $sequence;
41
+	/**
42
+	 * The current sequence number for the event.
43
+	 *
44
+	 * @var int
45
+	 */
46
+	public $sequence;
47 47
 
48
-    /**
49
-     * The senders' email address.
50
-     *
51
-     * Note that this does not imply that this has to be used in a From: field
52
-     * if the message is sent by email. It may also be populated in Reply-To:
53
-     * or not at all.
54
-     *
55
-     * @var string
56
-     */
57
-    public $sender;
48
+	/**
49
+	 * The senders' email address.
50
+	 *
51
+	 * Note that this does not imply that this has to be used in a From: field
52
+	 * if the message is sent by email. It may also be populated in Reply-To:
53
+	 * or not at all.
54
+	 *
55
+	 * @var string
56
+	 */
57
+	public $sender;
58 58
 
59
-    /**
60
-     * The name of the sender. This is often populated from a CN parameter from
61
-     * either the ORGANIZER or ATTENDEE, depending on the message.
62
-     *
63
-     * @var string|null
64
-     */
65
-    public $senderName;
59
+	/**
60
+	 * The name of the sender. This is often populated from a CN parameter from
61
+	 * either the ORGANIZER or ATTENDEE, depending on the message.
62
+	 *
63
+	 * @var string|null
64
+	 */
65
+	public $senderName;
66 66
 
67
-    /**
68
-     * The recipient's email address.
69
-     *
70
-     * @var string
71
-     */
72
-    public $recipient;
67
+	/**
68
+	 * The recipient's email address.
69
+	 *
70
+	 * @var string
71
+	 */
72
+	public $recipient;
73 73
 
74
-    /**
75
-     * The name of the recipient. This is usually populated with the CN
76
-     * parameter from the ATTENDEE or ORGANIZER property, if it's available.
77
-     *
78
-     * @var string|null
79
-     */
80
-    public $recipientName;
74
+	/**
75
+	 * The name of the recipient. This is usually populated with the CN
76
+	 * parameter from the ATTENDEE or ORGANIZER property, if it's available.
77
+	 *
78
+	 * @var string|null
79
+	 */
80
+	public $recipientName;
81 81
 
82
-    /**
83
-     * After the message has been delivered, this should contain a string such
84
-     * as : 1.1;Sent or 1.2;Delivered.
85
-     *
86
-     * In case of a failure, this will hold the error status code.
87
-     *
88
-     * See:
89
-     * http://tools.ietf.org/html/rfc6638#section-7.3
90
-     *
91
-     * @var string
92
-     */
93
-    public $scheduleStatus;
82
+	/**
83
+	 * After the message has been delivered, this should contain a string such
84
+	 * as : 1.1;Sent or 1.2;Delivered.
85
+	 *
86
+	 * In case of a failure, this will hold the error status code.
87
+	 *
88
+	 * See:
89
+	 * http://tools.ietf.org/html/rfc6638#section-7.3
90
+	 *
91
+	 * @var string
92
+	 */
93
+	public $scheduleStatus;
94 94
 
95
-    /**
96
-     * The iCalendar / iTip body.
97
-     *
98
-     * @var \Sabre\VObject\Component\VCalendar
99
-     */
100
-    public $message;
95
+	/**
96
+	 * The iCalendar / iTip body.
97
+	 *
98
+	 * @var \Sabre\VObject\Component\VCalendar
99
+	 */
100
+	public $message;
101 101
 
102
-    /**
103
-     * This will be set to true, if the iTip broker considers the change
104
-     * 'significant'.
105
-     *
106
-     * In practice, this means that we'll only mark it true, if for instance
107
-     * DTSTART changed. This allows systems to only send iTip messages when
108
-     * significant changes happened. This is especially useful for iMip, as
109
-     * normally a ton of messages may be generated for normal calendar use.
110
-     *
111
-     * To see the list of properties that are considered 'significant', check
112
-     * out Sabre\VObject\ITip\Broker::$significantChangeProperties.
113
-     *
114
-     * @var bool
115
-     */
116
-    public $significantChange = true;
102
+	/**
103
+	 * This will be set to true, if the iTip broker considers the change
104
+	 * 'significant'.
105
+	 *
106
+	 * In practice, this means that we'll only mark it true, if for instance
107
+	 * DTSTART changed. This allows systems to only send iTip messages when
108
+	 * significant changes happened. This is especially useful for iMip, as
109
+	 * normally a ton of messages may be generated for normal calendar use.
110
+	 *
111
+	 * To see the list of properties that are considered 'significant', check
112
+	 * out Sabre\VObject\ITip\Broker::$significantChangeProperties.
113
+	 *
114
+	 * @var bool
115
+	 */
116
+	public $significantChange = true;
117 117
 
118
-    /**
119
-     * Returns the schedule status as a string.
120
-     *
121
-     * For example:
122
-     * 1.2
123
-     *
124
-     * @return mixed bool|string
125
-     */
126
-    public function getScheduleStatus()
127
-    {
128
-        if (!$this->scheduleStatus) {
129
-            return false;
130
-        } else {
131
-            list($scheduleStatus) = explode(';', $this->scheduleStatus);
118
+	/**
119
+	 * Returns the schedule status as a string.
120
+	 *
121
+	 * For example:
122
+	 * 1.2
123
+	 *
124
+	 * @return mixed bool|string
125
+	 */
126
+	public function getScheduleStatus()
127
+	{
128
+		if (!$this->scheduleStatus) {
129
+			return false;
130
+		} else {
131
+			list($scheduleStatus) = explode(';', $this->scheduleStatus);
132 132
 
133
-            return $scheduleStatus;
134
-        }
135
-    }
133
+			return $scheduleStatus;
134
+		}
135
+	}
136 136
 }
Please login to merge, or discard this patch.
htdocs/includes/sabre/sabre/vobject/lib/Writer.php 1 patch
Indentation   +42 added lines, -42 removed lines patch added patch discarded remove patch
@@ -16,53 +16,53 @@
 block discarded – undo
16 16
  */
17 17
 class Writer
18 18
 {
19
-    /**
20
-     * Serializes a vCard or iCalendar object.
21
-     *
22
-     * @return string
23
-     */
24
-    public static function write(Component $component)
25
-    {
26
-        return $component->serialize();
27
-    }
19
+	/**
20
+	 * Serializes a vCard or iCalendar object.
21
+	 *
22
+	 * @return string
23
+	 */
24
+	public static function write(Component $component)
25
+	{
26
+		return $component->serialize();
27
+	}
28 28
 
29
-    /**
30
-     * Serializes a jCal or jCard object.
31
-     *
32
-     * @param int $options
33
-     *
34
-     * @return string
35
-     */
36
-    public static function writeJson(Component $component, $options = 0)
37
-    {
38
-        return json_encode($component, $options);
39
-    }
29
+	/**
30
+	 * Serializes a jCal or jCard object.
31
+	 *
32
+	 * @param int $options
33
+	 *
34
+	 * @return string
35
+	 */
36
+	public static function writeJson(Component $component, $options = 0)
37
+	{
38
+		return json_encode($component, $options);
39
+	}
40 40
 
41
-    /**
42
-     * Serializes a xCal or xCard object.
43
-     *
44
-     * @return string
45
-     */
46
-    public static function writeXml(Component $component)
47
-    {
48
-        $writer = new Xml\Writer();
49
-        $writer->openMemory();
50
-        $writer->setIndent(true);
41
+	/**
42
+	 * Serializes a xCal or xCard object.
43
+	 *
44
+	 * @return string
45
+	 */
46
+	public static function writeXml(Component $component)
47
+	{
48
+		$writer = new Xml\Writer();
49
+		$writer->openMemory();
50
+		$writer->setIndent(true);
51 51
 
52
-        $writer->startDocument('1.0', 'utf-8');
52
+		$writer->startDocument('1.0', 'utf-8');
53 53
 
54
-        if ($component instanceof Component\VCalendar) {
55
-            $writer->startElement('icalendar');
56
-            $writer->writeAttribute('xmlns', Parser\XML::XCAL_NAMESPACE);
57
-        } else {
58
-            $writer->startElement('vcards');
59
-            $writer->writeAttribute('xmlns', Parser\XML::XCARD_NAMESPACE);
60
-        }
54
+		if ($component instanceof Component\VCalendar) {
55
+			$writer->startElement('icalendar');
56
+			$writer->writeAttribute('xmlns', Parser\XML::XCAL_NAMESPACE);
57
+		} else {
58
+			$writer->startElement('vcards');
59
+			$writer->writeAttribute('xmlns', Parser\XML::XCARD_NAMESPACE);
60
+		}
61 61
 
62
-        $component->xmlSerialize($writer);
62
+		$component->xmlSerialize($writer);
63 63
 
64
-        $writer->endElement();
64
+		$writer->endElement();
65 65
 
66
-        return $writer->outputMemory();
67
-    }
66
+		return $writer->outputMemory();
67
+	}
68 68
 }
Please login to merge, or discard this patch.
htdocs/includes/sabre/sabre/vobject/lib/ElementList.php 1 patch
Indentation   +25 added lines, -25 removed lines patch added patch discarded remove patch
@@ -17,32 +17,32 @@
 block discarded – undo
17 17
  */
18 18
 class ElementList extends ArrayIterator
19 19
 {
20
-    /* {{{ ArrayAccess Interface */
20
+	/* {{{ ArrayAccess Interface */
21 21
 
22
-    /**
23
-     * Sets an item through ArrayAccess.
24
-     *
25
-     * @param int   $offset
26
-     * @param mixed $value
27
-     */
28
-    #[\ReturnTypeWillChange]
29
-    public function offsetSet($offset, $value)
30
-    {
31
-        throw new LogicException('You can not add new objects to an ElementList');
32
-    }
22
+	/**
23
+	 * Sets an item through ArrayAccess.
24
+	 *
25
+	 * @param int   $offset
26
+	 * @param mixed $value
27
+	 */
28
+	#[\ReturnTypeWillChange]
29
+	public function offsetSet($offset, $value)
30
+	{
31
+		throw new LogicException('You can not add new objects to an ElementList');
32
+	}
33 33
 
34
-    /**
35
-     * Sets an item through ArrayAccess.
36
-     *
37
-     * This method just forwards the request to the inner iterator
38
-     *
39
-     * @param int $offset
40
-     */
41
-    #[\ReturnTypeWillChange]
42
-    public function offsetUnset($offset)
43
-    {
44
-        throw new LogicException('You can not remove objects from an ElementList');
45
-    }
34
+	/**
35
+	 * Sets an item through ArrayAccess.
36
+	 *
37
+	 * This method just forwards the request to the inner iterator
38
+	 *
39
+	 * @param int $offset
40
+	 */
41
+	#[\ReturnTypeWillChange]
42
+	public function offsetUnset($offset)
43
+	{
44
+		throw new LogicException('You can not remove objects from an ElementList');
45
+	}
46 46
 
47
-    /* }}} */
47
+	/* }}} */
48 48
 }
Please login to merge, or discard this patch.
htdocs/includes/sabre/sabre/vobject/lib/Settings.php 1 patch
Indentation   +33 added lines, -33 removed lines patch added patch discarded remove patch
@@ -17,39 +17,39 @@
 block discarded – undo
17 17
  */
18 18
 class Settings
19 19
 {
20
-    /**
21
-     * The minimum date we accept for various calculations with dates, such as
22
-     * recurrences.
23
-     *
24
-     * The choice of 1900 is pretty arbitrary, but it covers most common
25
-     * use-cases. In particular, it covers birthdates for virtually everyone
26
-     * alive on earth, which is less than 5 people at the time of writing.
27
-     */
28
-    public static $minDate = '1900-01-01';
20
+	/**
21
+	 * The minimum date we accept for various calculations with dates, such as
22
+	 * recurrences.
23
+	 *
24
+	 * The choice of 1900 is pretty arbitrary, but it covers most common
25
+	 * use-cases. In particular, it covers birthdates for virtually everyone
26
+	 * alive on earth, which is less than 5 people at the time of writing.
27
+	 */
28
+	public static $minDate = '1900-01-01';
29 29
 
30
-    /**
31
-     * The maximum date we accept for various calculations with dates, such as
32
-     * recurrences.
33
-     *
34
-     * The choice of 2100 is pretty arbitrary, but should cover most
35
-     * appointments made for many years to come.
36
-     */
37
-    public static $maxDate = '2100-01-01';
30
+	/**
31
+	 * The maximum date we accept for various calculations with dates, such as
32
+	 * recurrences.
33
+	 *
34
+	 * The choice of 2100 is pretty arbitrary, but should cover most
35
+	 * appointments made for many years to come.
36
+	 */
37
+	public static $maxDate = '2100-01-01';
38 38
 
39
-    /**
40
-     * The maximum number of recurrences that will be generated.
41
-     *
42
-     * This setting limits the maximum of recurring events that this library
43
-     * generates in its recurrence iterators.
44
-     *
45
-     * This is a security measure. Without this, it would be possible to craft
46
-     * specific events that recur many, many times, potentially DDOSing the
47
-     * server.
48
-     *
49
-     * The default (3500) allows creation of a daily event that goes on for 10
50
-     * years, which is hopefully long enough for most.
51
-     *
52
-     * Set this value to -1 to disable this control altogether.
53
-     */
54
-    public static $maxRecurrences = 3500;
39
+	/**
40
+	 * The maximum number of recurrences that will be generated.
41
+	 *
42
+	 * This setting limits the maximum of recurring events that this library
43
+	 * generates in its recurrence iterators.
44
+	 *
45
+	 * This is a security measure. Without this, it would be possible to craft
46
+	 * specific events that recur many, many times, potentially DDOSing the
47
+	 * server.
48
+	 *
49
+	 * The default (3500) allows creation of a daily event that goes on for 10
50
+	 * years, which is hopefully long enough for most.
51
+	 *
52
+	 * Set this value to -1 to disable this control altogether.
53
+	 */
54
+	public static $maxRecurrences = 3500;
55 55
 }
Please login to merge, or discard this patch.
htdocs/includes/sabre/sabre/vobject/lib/Reader.php 1 patch
Indentation   +71 added lines, -71 removed lines patch added patch discarded remove patch
@@ -14,82 +14,82 @@
 block discarded – undo
14 14
  */
15 15
 class Reader
16 16
 {
17
-    /**
18
-     * If this option is passed to the reader, it will be less strict about the
19
-     * validity of the lines.
20
-     */
21
-    const OPTION_FORGIVING = 1;
17
+	/**
18
+	 * If this option is passed to the reader, it will be less strict about the
19
+	 * validity of the lines.
20
+	 */
21
+	const OPTION_FORGIVING = 1;
22 22
 
23
-    /**
24
-     * If this option is turned on, any lines we cannot parse will be ignored
25
-     * by the reader.
26
-     */
27
-    const OPTION_IGNORE_INVALID_LINES = 2;
23
+	/**
24
+	 * If this option is turned on, any lines we cannot parse will be ignored
25
+	 * by the reader.
26
+	 */
27
+	const OPTION_IGNORE_INVALID_LINES = 2;
28 28
 
29
-    /**
30
-     * Parses a vCard or iCalendar object, and returns the top component.
31
-     *
32
-     * The options argument is a bitfield. Pass any of the OPTIONS constant to
33
-     * alter the parsers' behaviour.
34
-     *
35
-     * You can either supply a string, or a readable stream for input.
36
-     *
37
-     * @param string|resource $data
38
-     * @param int             $options
39
-     * @param string          $charset
40
-     *
41
-     * @return Document
42
-     */
43
-    public static function read($data, $options = 0, $charset = 'UTF-8')
44
-    {
45
-        $parser = new Parser\MimeDir();
46
-        $parser->setCharset($charset);
47
-        $result = $parser->parse($data, $options);
29
+	/**
30
+	 * Parses a vCard or iCalendar object, and returns the top component.
31
+	 *
32
+	 * The options argument is a bitfield. Pass any of the OPTIONS constant to
33
+	 * alter the parsers' behaviour.
34
+	 *
35
+	 * You can either supply a string, or a readable stream for input.
36
+	 *
37
+	 * @param string|resource $data
38
+	 * @param int             $options
39
+	 * @param string          $charset
40
+	 *
41
+	 * @return Document
42
+	 */
43
+	public static function read($data, $options = 0, $charset = 'UTF-8')
44
+	{
45
+		$parser = new Parser\MimeDir();
46
+		$parser->setCharset($charset);
47
+		$result = $parser->parse($data, $options);
48 48
 
49
-        return $result;
50
-    }
49
+		return $result;
50
+	}
51 51
 
52
-    /**
53
-     * Parses a jCard or jCal object, and returns the top component.
54
-     *
55
-     * The options argument is a bitfield. Pass any of the OPTIONS constant to
56
-     * alter the parsers' behaviour.
57
-     *
58
-     * You can either a string, a readable stream, or an array for its input.
59
-     * Specifying the array is useful if json_decode was already called on the
60
-     * input.
61
-     *
62
-     * @param string|resource|array $data
63
-     * @param int                   $options
64
-     *
65
-     * @return Document
66
-     */
67
-    public static function readJson($data, $options = 0)
68
-    {
69
-        $parser = new Parser\Json();
70
-        $result = $parser->parse($data, $options);
52
+	/**
53
+	 * Parses a jCard or jCal object, and returns the top component.
54
+	 *
55
+	 * The options argument is a bitfield. Pass any of the OPTIONS constant to
56
+	 * alter the parsers' behaviour.
57
+	 *
58
+	 * You can either a string, a readable stream, or an array for its input.
59
+	 * Specifying the array is useful if json_decode was already called on the
60
+	 * input.
61
+	 *
62
+	 * @param string|resource|array $data
63
+	 * @param int                   $options
64
+	 *
65
+	 * @return Document
66
+	 */
67
+	public static function readJson($data, $options = 0)
68
+	{
69
+		$parser = new Parser\Json();
70
+		$result = $parser->parse($data, $options);
71 71
 
72
-        return $result;
73
-    }
72
+		return $result;
73
+	}
74 74
 
75
-    /**
76
-     * Parses a xCard or xCal object, and returns the top component.
77
-     *
78
-     * The options argument is a bitfield. Pass any of the OPTIONS constant to
79
-     * alter the parsers' behaviour.
80
-     *
81
-     * You can either supply a string, or a readable stream for input.
82
-     *
83
-     * @param string|resource $data
84
-     * @param int             $options
85
-     *
86
-     * @return Document
87
-     */
88
-    public static function readXML($data, $options = 0)
89
-    {
90
-        $parser = new Parser\XML();
91
-        $result = $parser->parse($data, $options);
75
+	/**
76
+	 * Parses a xCard or xCal object, and returns the top component.
77
+	 *
78
+	 * The options argument is a bitfield. Pass any of the OPTIONS constant to
79
+	 * alter the parsers' behaviour.
80
+	 *
81
+	 * You can either supply a string, or a readable stream for input.
82
+	 *
83
+	 * @param string|resource $data
84
+	 * @param int             $options
85
+	 *
86
+	 * @return Document
87
+	 */
88
+	public static function readXML($data, $options = 0)
89
+	{
90
+		$parser = new Parser\XML();
91
+		$result = $parser->parse($data, $options);
92 92
 
93
-        return $result;
94
-    }
93
+		return $result;
94
+	}
95 95
 }
Please login to merge, or discard this patch.
htdocs/includes/sabre/sabre/vobject/lib/StringUtil.php 1 patch
Indentation   +33 added lines, -33 removed lines patch added patch discarded remove patch
@@ -11,40 +11,40 @@
 block discarded – undo
11 11
  */
12 12
 class StringUtil
13 13
 {
14
-    /**
15
-     * Returns true or false depending on if a string is valid UTF-8.
16
-     *
17
-     * @param string $str
18
-     *
19
-     * @return bool
20
-     */
21
-    public static function isUTF8($str)
22
-    {
23
-        // Control characters
24
-        if (preg_match('%[\x00-\x08\x0B-\x0C\x0E\x0F]%', $str)) {
25
-            return false;
26
-        }
14
+	/**
15
+	 * Returns true or false depending on if a string is valid UTF-8.
16
+	 *
17
+	 * @param string $str
18
+	 *
19
+	 * @return bool
20
+	 */
21
+	public static function isUTF8($str)
22
+	{
23
+		// Control characters
24
+		if (preg_match('%[\x00-\x08\x0B-\x0C\x0E\x0F]%', $str)) {
25
+			return false;
26
+		}
27 27
 
28
-        return (bool) preg_match('%%u', $str);
29
-    }
28
+		return (bool) preg_match('%%u', $str);
29
+	}
30 30
 
31
-    /**
32
-     * This method tries its best to convert the input string to UTF-8.
33
-     *
34
-     * Currently only ISO-5991-1 input and UTF-8 input is supported, but this
35
-     * may be expanded upon if we receive other examples.
36
-     *
37
-     * @param string $str
38
-     *
39
-     * @return string
40
-     */
41
-    public static function convertToUTF8($str)
42
-    {
43
-        if (!mb_check_encoding($str, 'UTF-8') && mb_check_encoding($str, 'ISO-8859-1')) {
44
-            $str = mb_convert_encoding($str, 'UTF-8', 'ISO-8859-1');
45
-        }
31
+	/**
32
+	 * This method tries its best to convert the input string to UTF-8.
33
+	 *
34
+	 * Currently only ISO-5991-1 input and UTF-8 input is supported, but this
35
+	 * may be expanded upon if we receive other examples.
36
+	 *
37
+	 * @param string $str
38
+	 *
39
+	 * @return string
40
+	 */
41
+	public static function convertToUTF8($str)
42
+	{
43
+		if (!mb_check_encoding($str, 'UTF-8') && mb_check_encoding($str, 'ISO-8859-1')) {
44
+			$str = mb_convert_encoding($str, 'UTF-8', 'ISO-8859-1');
45
+		}
46 46
 
47
-        // Removing any control characters
48
-        return preg_replace('%(?:[\x00-\x08\x0B-\x0C\x0E-\x1F\x7F])%', '', $str);
49
-    }
47
+		// Removing any control characters
48
+		return preg_replace('%(?:[\x00-\x08\x0B-\x0C\x0E-\x1F\x7F])%', '', $str);
49
+	}
50 50
 }
Please login to merge, or discard this patch.
htdocs/includes/sabre/sabre/vobject/lib/BirthdayCalendarGenerator.php 1 patch
Indentation   +156 added lines, -156 removed lines patch added patch discarded remove patch
@@ -13,160 +13,160 @@
 block discarded – undo
13 13
  */
14 14
 class BirthdayCalendarGenerator
15 15
 {
16
-    /**
17
-     * Input objects.
18
-     *
19
-     * @var array
20
-     */
21
-    protected $objects = [];
22
-
23
-    /**
24
-     * Default year.
25
-     * Used for dates without a year.
26
-     */
27
-    const DEFAULT_YEAR = 2000;
28
-
29
-    /**
30
-     * Output format for the SUMMARY.
31
-     *
32
-     * @var string
33
-     */
34
-    protected $format = '%1$s\'s Birthday';
35
-
36
-    /**
37
-     * Creates the generator.
38
-     *
39
-     * Check the setTimeRange and setObjects methods for details about the
40
-     * arguments.
41
-     *
42
-     * @param mixed $objects
43
-     */
44
-    public function __construct($objects = null)
45
-    {
46
-        if ($objects) {
47
-            $this->setObjects($objects);
48
-        }
49
-    }
50
-
51
-    /**
52
-     * Sets the input objects.
53
-     *
54
-     * You must either supply a vCard as a string or as a Component/VCard object.
55
-     * It's also possible to supply an array of strings or objects.
56
-     *
57
-     * @param mixed $objects
58
-     */
59
-    public function setObjects($objects)
60
-    {
61
-        if (!is_array($objects)) {
62
-            $objects = [$objects];
63
-        }
64
-
65
-        $this->objects = [];
66
-        foreach ($objects as $object) {
67
-            if (is_string($object)) {
68
-                $vObj = Reader::read($object);
69
-                if (!$vObj instanceof Component\VCard) {
70
-                    throw new \InvalidArgumentException('String could not be parsed as \\Sabre\\VObject\\Component\\VCard by setObjects');
71
-                }
72
-
73
-                $this->objects[] = $vObj;
74
-            } elseif ($object instanceof Component\VCard) {
75
-                $this->objects[] = $object;
76
-            } else {
77
-                throw new \InvalidArgumentException('You can only pass strings or \\Sabre\\VObject\\Component\\VCard arguments to setObjects');
78
-            }
79
-        }
80
-    }
81
-
82
-    /**
83
-     * Sets the output format for the SUMMARY.
84
-     *
85
-     * @param string $format
86
-     */
87
-    public function setFormat($format)
88
-    {
89
-        $this->format = $format;
90
-    }
91
-
92
-    /**
93
-     * Parses the input data and returns a VCALENDAR.
94
-     *
95
-     * @return Component/VCalendar
96
-     */
97
-    public function getResult()
98
-    {
99
-        $calendar = new VCalendar();
100
-
101
-        foreach ($this->objects as $object) {
102
-            // Skip if there is no BDAY property.
103
-            if (!$object->select('BDAY')) {
104
-                continue;
105
-            }
106
-
107
-            // We've seen clients (ez-vcard) putting "BDAY:" properties
108
-            // without a value into vCards. If we come across those, we'll
109
-            // skip them.
110
-            if (empty($object->BDAY->getValue())) {
111
-                continue;
112
-            }
113
-
114
-            // We're always converting to vCard 4.0 so we can rely on the
115
-            // VCardConverter handling the X-APPLE-OMIT-YEAR property for us.
116
-            $object = $object->convert(Document::VCARD40);
117
-
118
-            // Skip if the card has no FN property.
119
-            if (!isset($object->FN)) {
120
-                continue;
121
-            }
122
-
123
-            // Skip if the BDAY property is not of the right type.
124
-            if (!$object->BDAY instanceof Property\VCard\DateAndOrTime) {
125
-                continue;
126
-            }
127
-
128
-            // Skip if we can't parse the BDAY value.
129
-            try {
130
-                $dateParts = DateTimeParser::parseVCardDateTime($object->BDAY->getValue());
131
-            } catch (InvalidDataException $e) {
132
-                continue;
133
-            }
134
-
135
-            // Set a year if it's not set.
136
-            $unknownYear = false;
137
-
138
-            if (!$dateParts['year']) {
139
-                $object->BDAY = self::DEFAULT_YEAR.'-'.$dateParts['month'].'-'.$dateParts['date'];
140
-
141
-                $unknownYear = true;
142
-            }
143
-
144
-            // Create event.
145
-            $event = $calendar->add('VEVENT', [
146
-                'SUMMARY' => sprintf($this->format, $object->FN->getValue()),
147
-                'DTSTART' => new \DateTime($object->BDAY->getValue()),
148
-                'RRULE' => 'FREQ=YEARLY',
149
-                'TRANSP' => 'TRANSPARENT',
150
-            ]);
151
-
152
-            // add VALUE=date
153
-            $event->DTSTART['VALUE'] = 'DATE';
154
-
155
-            // Add X-SABRE-BDAY property.
156
-            if ($unknownYear) {
157
-                $event->add('X-SABRE-BDAY', 'BDAY', [
158
-                    'X-SABRE-VCARD-UID' => $object->UID->getValue(),
159
-                    'X-SABRE-VCARD-FN' => $object->FN->getValue(),
160
-                    'X-SABRE-OMIT-YEAR' => self::DEFAULT_YEAR,
161
-                ]);
162
-            } else {
163
-                $event->add('X-SABRE-BDAY', 'BDAY', [
164
-                    'X-SABRE-VCARD-UID' => $object->UID->getValue(),
165
-                    'X-SABRE-VCARD-FN' => $object->FN->getValue(),
166
-                ]);
167
-            }
168
-        }
169
-
170
-        return $calendar;
171
-    }
16
+	/**
17
+	 * Input objects.
18
+	 *
19
+	 * @var array
20
+	 */
21
+	protected $objects = [];
22
+
23
+	/**
24
+	 * Default year.
25
+	 * Used for dates without a year.
26
+	 */
27
+	const DEFAULT_YEAR = 2000;
28
+
29
+	/**
30
+	 * Output format for the SUMMARY.
31
+	 *
32
+	 * @var string
33
+	 */
34
+	protected $format = '%1$s\'s Birthday';
35
+
36
+	/**
37
+	 * Creates the generator.
38
+	 *
39
+	 * Check the setTimeRange and setObjects methods for details about the
40
+	 * arguments.
41
+	 *
42
+	 * @param mixed $objects
43
+	 */
44
+	public function __construct($objects = null)
45
+	{
46
+		if ($objects) {
47
+			$this->setObjects($objects);
48
+		}
49
+	}
50
+
51
+	/**
52
+	 * Sets the input objects.
53
+	 *
54
+	 * You must either supply a vCard as a string or as a Component/VCard object.
55
+	 * It's also possible to supply an array of strings or objects.
56
+	 *
57
+	 * @param mixed $objects
58
+	 */
59
+	public function setObjects($objects)
60
+	{
61
+		if (!is_array($objects)) {
62
+			$objects = [$objects];
63
+		}
64
+
65
+		$this->objects = [];
66
+		foreach ($objects as $object) {
67
+			if (is_string($object)) {
68
+				$vObj = Reader::read($object);
69
+				if (!$vObj instanceof Component\VCard) {
70
+					throw new \InvalidArgumentException('String could not be parsed as \\Sabre\\VObject\\Component\\VCard by setObjects');
71
+				}
72
+
73
+				$this->objects[] = $vObj;
74
+			} elseif ($object instanceof Component\VCard) {
75
+				$this->objects[] = $object;
76
+			} else {
77
+				throw new \InvalidArgumentException('You can only pass strings or \\Sabre\\VObject\\Component\\VCard arguments to setObjects');
78
+			}
79
+		}
80
+	}
81
+
82
+	/**
83
+	 * Sets the output format for the SUMMARY.
84
+	 *
85
+	 * @param string $format
86
+	 */
87
+	public function setFormat($format)
88
+	{
89
+		$this->format = $format;
90
+	}
91
+
92
+	/**
93
+	 * Parses the input data and returns a VCALENDAR.
94
+	 *
95
+	 * @return Component/VCalendar
96
+	 */
97
+	public function getResult()
98
+	{
99
+		$calendar = new VCalendar();
100
+
101
+		foreach ($this->objects as $object) {
102
+			// Skip if there is no BDAY property.
103
+			if (!$object->select('BDAY')) {
104
+				continue;
105
+			}
106
+
107
+			// We've seen clients (ez-vcard) putting "BDAY:" properties
108
+			// without a value into vCards. If we come across those, we'll
109
+			// skip them.
110
+			if (empty($object->BDAY->getValue())) {
111
+				continue;
112
+			}
113
+
114
+			// We're always converting to vCard 4.0 so we can rely on the
115
+			// VCardConverter handling the X-APPLE-OMIT-YEAR property for us.
116
+			$object = $object->convert(Document::VCARD40);
117
+
118
+			// Skip if the card has no FN property.
119
+			if (!isset($object->FN)) {
120
+				continue;
121
+			}
122
+
123
+			// Skip if the BDAY property is not of the right type.
124
+			if (!$object->BDAY instanceof Property\VCard\DateAndOrTime) {
125
+				continue;
126
+			}
127
+
128
+			// Skip if we can't parse the BDAY value.
129
+			try {
130
+				$dateParts = DateTimeParser::parseVCardDateTime($object->BDAY->getValue());
131
+			} catch (InvalidDataException $e) {
132
+				continue;
133
+			}
134
+
135
+			// Set a year if it's not set.
136
+			$unknownYear = false;
137
+
138
+			if (!$dateParts['year']) {
139
+				$object->BDAY = self::DEFAULT_YEAR.'-'.$dateParts['month'].'-'.$dateParts['date'];
140
+
141
+				$unknownYear = true;
142
+			}
143
+
144
+			// Create event.
145
+			$event = $calendar->add('VEVENT', [
146
+				'SUMMARY' => sprintf($this->format, $object->FN->getValue()),
147
+				'DTSTART' => new \DateTime($object->BDAY->getValue()),
148
+				'RRULE' => 'FREQ=YEARLY',
149
+				'TRANSP' => 'TRANSPARENT',
150
+			]);
151
+
152
+			// add VALUE=date
153
+			$event->DTSTART['VALUE'] = 'DATE';
154
+
155
+			// Add X-SABRE-BDAY property.
156
+			if ($unknownYear) {
157
+				$event->add('X-SABRE-BDAY', 'BDAY', [
158
+					'X-SABRE-VCARD-UID' => $object->UID->getValue(),
159
+					'X-SABRE-VCARD-FN' => $object->FN->getValue(),
160
+					'X-SABRE-OMIT-YEAR' => self::DEFAULT_YEAR,
161
+				]);
162
+			} else {
163
+				$event->add('X-SABRE-BDAY', 'BDAY', [
164
+					'X-SABRE-VCARD-UID' => $object->UID->getValue(),
165
+					'X-SABRE-VCARD-FN' => $object->FN->getValue(),
166
+				]);
167
+			}
168
+		}
169
+
170
+		return $calendar;
171
+	}
172 172
 }
Please login to merge, or discard this patch.
htdocs/includes/sabre/sabre/vobject/lib/Recur/EventIterator.php 1 patch
Indentation   +434 added lines, -434 removed lines patch added patch discarded remove patch
@@ -60,438 +60,438 @@
 block discarded – undo
60 60
  */
61 61
 class EventIterator implements \Iterator
62 62
 {
63
-    /**
64
-     * Reference timeZone for floating dates and times.
65
-     *
66
-     * @var DateTimeZone
67
-     */
68
-    protected $timeZone;
69
-
70
-    /**
71
-     * True if we're iterating an all-day event.
72
-     *
73
-     * @var bool
74
-     */
75
-    protected $allDay = false;
76
-
77
-    /**
78
-     * Creates the iterator.
79
-     *
80
-     * There's three ways to set up the iterator.
81
-     *
82
-     * 1. You can pass a VCALENDAR component and a UID.
83
-     * 2. You can pass an array of VEVENTs (all UIDS should match).
84
-     * 3. You can pass a single VEVENT component.
85
-     *
86
-     * Only the second method is recommended. The other 1 and 3 will be removed
87
-     * at some point in the future.
88
-     *
89
-     * The $uid parameter is only required for the first method.
90
-     *
91
-     * @param Component|array $input
92
-     * @param string|null     $uid
93
-     * @param DateTimeZone    $timeZone reference timezone for floating dates and
94
-     *                                  times
95
-     */
96
-    public function __construct($input, $uid = null, DateTimeZone $timeZone = null)
97
-    {
98
-        if (is_null($timeZone)) {
99
-            $timeZone = new DateTimeZone('UTC');
100
-        }
101
-        $this->timeZone = $timeZone;
102
-
103
-        if (is_array($input)) {
104
-            $events = $input;
105
-        } elseif ($input instanceof VEvent) {
106
-            // Single instance mode.
107
-            $events = [$input];
108
-        } else {
109
-            // Calendar + UID mode.
110
-            $uid = (string) $uid;
111
-            if (!$uid) {
112
-                throw new InvalidArgumentException('The UID argument is required when a VCALENDAR is passed to this constructor');
113
-            }
114
-            if (!isset($input->VEVENT)) {
115
-                throw new InvalidArgumentException('No events found in this calendar');
116
-            }
117
-            $events = $input->getByUID($uid);
118
-        }
119
-
120
-        foreach ($events as $vevent) {
121
-            if (!isset($vevent->{'RECURRENCE-ID'})) {
122
-                $this->masterEvent = $vevent;
123
-            } else {
124
-                $this->exceptions[
125
-                    $vevent->{'RECURRENCE-ID'}->getDateTime($this->timeZone)->getTimeStamp()
126
-                ] = true;
127
-                $this->overriddenEvents[] = $vevent;
128
-            }
129
-        }
130
-
131
-        if (!$this->masterEvent) {
132
-            // No base event was found. CalDAV does allow cases where only
133
-            // overridden instances are stored.
134
-            //
135
-            // In this particular case, we're just going to grab the first
136
-            // event and use that instead. This may not always give the
137
-            // desired result.
138
-            if (!count($this->overriddenEvents)) {
139
-                throw new InvalidArgumentException('This VCALENDAR did not have an event with UID: '.$uid);
140
-            }
141
-            $this->masterEvent = array_shift($this->overriddenEvents);
142
-        }
143
-
144
-        $this->startDate = $this->masterEvent->DTSTART->getDateTime($this->timeZone);
145
-        $this->allDay = !$this->masterEvent->DTSTART->hasTime();
146
-
147
-        if (isset($this->masterEvent->EXDATE)) {
148
-            foreach ($this->masterEvent->EXDATE as $exDate) {
149
-                foreach ($exDate->getDateTimes($this->timeZone) as $dt) {
150
-                    $this->exceptions[$dt->getTimeStamp()] = true;
151
-                }
152
-            }
153
-        }
154
-
155
-        if (isset($this->masterEvent->DTEND)) {
156
-            $this->eventDuration =
157
-                $this->masterEvent->DTEND->getDateTime($this->timeZone)->getTimeStamp() -
158
-                $this->startDate->getTimeStamp();
159
-        } elseif (isset($this->masterEvent->DURATION)) {
160
-            $duration = $this->masterEvent->DURATION->getDateInterval();
161
-            $end = clone $this->startDate;
162
-            $end = $end->add($duration);
163
-            $this->eventDuration = $end->getTimeStamp() - $this->startDate->getTimeStamp();
164
-        } elseif ($this->allDay) {
165
-            $this->eventDuration = 3600 * 24;
166
-        } else {
167
-            $this->eventDuration = 0;
168
-        }
169
-
170
-        if (isset($this->masterEvent->RDATE)) {
171
-            $this->recurIterator = new RDateIterator(
172
-                $this->masterEvent->RDATE->getParts(),
173
-                $this->startDate
174
-            );
175
-        } elseif (isset($this->masterEvent->RRULE)) {
176
-            $this->recurIterator = new RRuleIterator(
177
-                $this->masterEvent->RRULE->getParts(),
178
-                $this->startDate
179
-            );
180
-        } else {
181
-            $this->recurIterator = new RRuleIterator(
182
-                [
183
-                    'FREQ' => 'DAILY',
184
-                    'COUNT' => 1,
185
-                ],
186
-                $this->startDate
187
-            );
188
-        }
189
-
190
-        $this->rewind();
191
-        if (!$this->valid()) {
192
-            throw new NoInstancesException('This recurrence rule does not generate any valid instances');
193
-        }
194
-    }
195
-
196
-    /**
197
-     * Returns the date for the current position of the iterator.
198
-     *
199
-     * @return DateTimeImmutable
200
-     */
201
-    #[\ReturnTypeWillChange]
202
-    public function current()
203
-    {
204
-        if ($this->currentDate) {
205
-            return clone $this->currentDate;
206
-        }
207
-    }
208
-
209
-    /**
210
-     * This method returns the start date for the current iteration of the
211
-     * event.
212
-     *
213
-     * @return DateTimeImmutable
214
-     */
215
-    public function getDtStart()
216
-    {
217
-        if ($this->currentDate) {
218
-            return clone $this->currentDate;
219
-        }
220
-    }
221
-
222
-    /**
223
-     * This method returns the end date for the current iteration of the
224
-     * event.
225
-     *
226
-     * @return DateTimeImmutable
227
-     */
228
-    public function getDtEnd()
229
-    {
230
-        if (!$this->valid()) {
231
-            return;
232
-        }
233
-        if ($this->currentOverriddenEvent && $this->currentOverriddenEvent->DTEND) {
234
-            return $this->currentOverriddenEvent->DTEND->getDateTime($this->timeZone);
235
-        } else {
236
-            $end = clone $this->currentDate;
237
-
238
-            return $end->modify('+'.$this->eventDuration.' seconds');
239
-        }
240
-    }
241
-
242
-    /**
243
-     * Returns a VEVENT for the current iterations of the event.
244
-     *
245
-     * This VEVENT will have a recurrence id, and its DTSTART and DTEND
246
-     * altered.
247
-     *
248
-     * @return VEvent
249
-     */
250
-    public function getEventObject()
251
-    {
252
-        if ($this->currentOverriddenEvent) {
253
-            return $this->currentOverriddenEvent;
254
-        }
255
-
256
-        $event = clone $this->masterEvent;
257
-
258
-        // Ignoring the following block, because PHPUnit's code coverage
259
-        // ignores most of these lines, and this messes with our stats.
260
-        //
261
-        // @codeCoverageIgnoreStart
262
-        unset(
263
-            $event->RRULE,
264
-            $event->EXDATE,
265
-            $event->RDATE,
266
-            $event->EXRULE,
267
-            $event->{'RECURRENCE-ID'}
268
-        );
269
-        // @codeCoverageIgnoreEnd
270
-
271
-        $event->DTSTART->setDateTime($this->getDtStart(), $event->DTSTART->isFloating());
272
-        if (isset($event->DTEND)) {
273
-            $event->DTEND->setDateTime($this->getDtEnd(), $event->DTEND->isFloating());
274
-        }
275
-        $recurid = clone $event->DTSTART;
276
-        $recurid->name = 'RECURRENCE-ID';
277
-        $event->add($recurid);
278
-
279
-        return $event;
280
-    }
281
-
282
-    /**
283
-     * Returns the current position of the iterator.
284
-     *
285
-     * This is for us simply a 0-based index.
286
-     *
287
-     * @return int
288
-     */
289
-    #[\ReturnTypeWillChange]
290
-    public function key()
291
-    {
292
-        // The counter is always 1 ahead.
293
-        return $this->counter - 1;
294
-    }
295
-
296
-    /**
297
-     * This is called after next, to see if the iterator is still at a valid
298
-     * position, or if it's at the end.
299
-     *
300
-     * @return bool
301
-     */
302
-    #[\ReturnTypeWillChange]
303
-    public function valid()
304
-    {
305
-        if ($this->counter > Settings::$maxRecurrences && -1 !== Settings::$maxRecurrences) {
306
-            throw new MaxInstancesExceededException('Recurring events are only allowed to generate '.Settings::$maxRecurrences);
307
-        }
308
-
309
-        return (bool) $this->currentDate;
310
-    }
311
-
312
-    /**
313
-     * Sets the iterator back to the starting point.
314
-     *
315
-     * @return void
316
-     */
317
-    #[\ReturnTypeWillChange]
318
-    public function rewind()
319
-    {
320
-        $this->recurIterator->rewind();
321
-        // re-creating overridden event index.
322
-        $index = [];
323
-        foreach ($this->overriddenEvents as $key => $event) {
324
-            $stamp = $event->DTSTART->getDateTime($this->timeZone)->getTimeStamp();
325
-            $index[$stamp][] = $key;
326
-        }
327
-        krsort($index);
328
-        $this->counter = 0;
329
-        $this->overriddenEventsIndex = $index;
330
-        $this->currentOverriddenEvent = null;
331
-
332
-        $this->nextDate = null;
333
-        $this->currentDate = clone $this->startDate;
334
-
335
-        $this->next();
336
-    }
337
-
338
-    /**
339
-     * Advances the iterator with one step.
340
-     *
341
-     * @return void
342
-     */
343
-    #[\ReturnTypeWillChange]
344
-    public function next()
345
-    {
346
-        $this->currentOverriddenEvent = null;
347
-        ++$this->counter;
348
-        if ($this->nextDate) {
349
-            // We had a stored value.
350
-            $nextDate = $this->nextDate;
351
-            $this->nextDate = null;
352
-        } else {
353
-            // We need to ask rruleparser for the next date.
354
-            // We need to do this until we find a date that's not in the
355
-            // exception list.
356
-            do {
357
-                if (!$this->recurIterator->valid()) {
358
-                    $nextDate = null;
359
-                    break;
360
-                }
361
-                $nextDate = $this->recurIterator->current();
362
-                $this->recurIterator->next();
363
-            } while (isset($this->exceptions[$nextDate->getTimeStamp()]));
364
-        }
365
-
366
-        // $nextDate now contains what rrule thinks is the next one, but an
367
-        // overridden event may cut ahead.
368
-        if ($this->overriddenEventsIndex) {
369
-            $offsets = end($this->overriddenEventsIndex);
370
-            $timestamp = key($this->overriddenEventsIndex);
371
-            $offset = end($offsets);
372
-            if (!$nextDate || $timestamp < $nextDate->getTimeStamp()) {
373
-                // Overridden event comes first.
374
-                $this->currentOverriddenEvent = $this->overriddenEvents[$offset];
375
-
376
-                // Putting the rrule next date aside.
377
-                $this->nextDate = $nextDate;
378
-                $this->currentDate = $this->currentOverriddenEvent->DTSTART->getDateTime($this->timeZone);
379
-
380
-                // Ensuring that this item will only be used once.
381
-                array_pop($this->overriddenEventsIndex[$timestamp]);
382
-                if (!$this->overriddenEventsIndex[$timestamp]) {
383
-                    array_pop($this->overriddenEventsIndex);
384
-                }
385
-
386
-                // Exit point!
387
-                return;
388
-            }
389
-        }
390
-
391
-        $this->currentDate = $nextDate;
392
-    }
393
-
394
-    /**
395
-     * Quickly jump to a date in the future.
396
-     */
397
-    public function fastForward(DateTimeInterface $dateTime)
398
-    {
399
-        while ($this->valid() && $this->getDtEnd() <= $dateTime) {
400
-            $this->next();
401
-        }
402
-    }
403
-
404
-    /**
405
-     * Returns true if this recurring event never ends.
406
-     *
407
-     * @return bool
408
-     */
409
-    public function isInfinite()
410
-    {
411
-        return $this->recurIterator->isInfinite();
412
-    }
413
-
414
-    /**
415
-     * RRULE parser.
416
-     *
417
-     * @var RRuleIterator
418
-     */
419
-    protected $recurIterator;
420
-
421
-    /**
422
-     * The duration, in seconds, of the master event.
423
-     *
424
-     * We use this to calculate the DTEND for subsequent events.
425
-     */
426
-    protected $eventDuration;
427
-
428
-    /**
429
-     * A reference to the main (master) event.
430
-     *
431
-     * @var VEVENT
432
-     */
433
-    protected $masterEvent;
434
-
435
-    /**
436
-     * List of overridden events.
437
-     *
438
-     * @var array
439
-     */
440
-    protected $overriddenEvents = [];
441
-
442
-    /**
443
-     * Overridden event index.
444
-     *
445
-     * Key is timestamp, value is the list of indexes of the item in the $overriddenEvent
446
-     * property.
447
-     *
448
-     * @var array
449
-     */
450
-    protected $overriddenEventsIndex;
451
-
452
-    /**
453
-     * A list of recurrence-id's that are either part of EXDATE, or are
454
-     * overridden.
455
-     *
456
-     * @var array
457
-     */
458
-    protected $exceptions = [];
459
-
460
-    /**
461
-     * Internal event counter.
462
-     *
463
-     * @var int
464
-     */
465
-    protected $counter;
466
-
467
-    /**
468
-     * The very start of the iteration process.
469
-     *
470
-     * @var DateTimeImmutable
471
-     */
472
-    protected $startDate;
473
-
474
-    /**
475
-     * Where we are currently in the iteration process.
476
-     *
477
-     * @var DateTimeImmutable
478
-     */
479
-    protected $currentDate;
480
-
481
-    /**
482
-     * The next date from the rrule parser.
483
-     *
484
-     * Sometimes we need to temporary store the next date, because an
485
-     * overridden event came before.
486
-     *
487
-     * @var DateTimeImmutable
488
-     */
489
-    protected $nextDate;
490
-
491
-    /**
492
-     * The event that overwrites the current iteration.
493
-     *
494
-     * @var VEVENT
495
-     */
496
-    protected $currentOverriddenEvent;
63
+	/**
64
+	 * Reference timeZone for floating dates and times.
65
+	 *
66
+	 * @var DateTimeZone
67
+	 */
68
+	protected $timeZone;
69
+
70
+	/**
71
+	 * True if we're iterating an all-day event.
72
+	 *
73
+	 * @var bool
74
+	 */
75
+	protected $allDay = false;
76
+
77
+	/**
78
+	 * Creates the iterator.
79
+	 *
80
+	 * There's three ways to set up the iterator.
81
+	 *
82
+	 * 1. You can pass a VCALENDAR component and a UID.
83
+	 * 2. You can pass an array of VEVENTs (all UIDS should match).
84
+	 * 3. You can pass a single VEVENT component.
85
+	 *
86
+	 * Only the second method is recommended. The other 1 and 3 will be removed
87
+	 * at some point in the future.
88
+	 *
89
+	 * The $uid parameter is only required for the first method.
90
+	 *
91
+	 * @param Component|array $input
92
+	 * @param string|null     $uid
93
+	 * @param DateTimeZone    $timeZone reference timezone for floating dates and
94
+	 *                                  times
95
+	 */
96
+	public function __construct($input, $uid = null, DateTimeZone $timeZone = null)
97
+	{
98
+		if (is_null($timeZone)) {
99
+			$timeZone = new DateTimeZone('UTC');
100
+		}
101
+		$this->timeZone = $timeZone;
102
+
103
+		if (is_array($input)) {
104
+			$events = $input;
105
+		} elseif ($input instanceof VEvent) {
106
+			// Single instance mode.
107
+			$events = [$input];
108
+		} else {
109
+			// Calendar + UID mode.
110
+			$uid = (string) $uid;
111
+			if (!$uid) {
112
+				throw new InvalidArgumentException('The UID argument is required when a VCALENDAR is passed to this constructor');
113
+			}
114
+			if (!isset($input->VEVENT)) {
115
+				throw new InvalidArgumentException('No events found in this calendar');
116
+			}
117
+			$events = $input->getByUID($uid);
118
+		}
119
+
120
+		foreach ($events as $vevent) {
121
+			if (!isset($vevent->{'RECURRENCE-ID'})) {
122
+				$this->masterEvent = $vevent;
123
+			} else {
124
+				$this->exceptions[
125
+					$vevent->{'RECURRENCE-ID'}->getDateTime($this->timeZone)->getTimeStamp()
126
+				] = true;
127
+				$this->overriddenEvents[] = $vevent;
128
+			}
129
+		}
130
+
131
+		if (!$this->masterEvent) {
132
+			// No base event was found. CalDAV does allow cases where only
133
+			// overridden instances are stored.
134
+			//
135
+			// In this particular case, we're just going to grab the first
136
+			// event and use that instead. This may not always give the
137
+			// desired result.
138
+			if (!count($this->overriddenEvents)) {
139
+				throw new InvalidArgumentException('This VCALENDAR did not have an event with UID: '.$uid);
140
+			}
141
+			$this->masterEvent = array_shift($this->overriddenEvents);
142
+		}
143
+
144
+		$this->startDate = $this->masterEvent->DTSTART->getDateTime($this->timeZone);
145
+		$this->allDay = !$this->masterEvent->DTSTART->hasTime();
146
+
147
+		if (isset($this->masterEvent->EXDATE)) {
148
+			foreach ($this->masterEvent->EXDATE as $exDate) {
149
+				foreach ($exDate->getDateTimes($this->timeZone) as $dt) {
150
+					$this->exceptions[$dt->getTimeStamp()] = true;
151
+				}
152
+			}
153
+		}
154
+
155
+		if (isset($this->masterEvent->DTEND)) {
156
+			$this->eventDuration =
157
+				$this->masterEvent->DTEND->getDateTime($this->timeZone)->getTimeStamp() -
158
+				$this->startDate->getTimeStamp();
159
+		} elseif (isset($this->masterEvent->DURATION)) {
160
+			$duration = $this->masterEvent->DURATION->getDateInterval();
161
+			$end = clone $this->startDate;
162
+			$end = $end->add($duration);
163
+			$this->eventDuration = $end->getTimeStamp() - $this->startDate->getTimeStamp();
164
+		} elseif ($this->allDay) {
165
+			$this->eventDuration = 3600 * 24;
166
+		} else {
167
+			$this->eventDuration = 0;
168
+		}
169
+
170
+		if (isset($this->masterEvent->RDATE)) {
171
+			$this->recurIterator = new RDateIterator(
172
+				$this->masterEvent->RDATE->getParts(),
173
+				$this->startDate
174
+			);
175
+		} elseif (isset($this->masterEvent->RRULE)) {
176
+			$this->recurIterator = new RRuleIterator(
177
+				$this->masterEvent->RRULE->getParts(),
178
+				$this->startDate
179
+			);
180
+		} else {
181
+			$this->recurIterator = new RRuleIterator(
182
+				[
183
+					'FREQ' => 'DAILY',
184
+					'COUNT' => 1,
185
+				],
186
+				$this->startDate
187
+			);
188
+		}
189
+
190
+		$this->rewind();
191
+		if (!$this->valid()) {
192
+			throw new NoInstancesException('This recurrence rule does not generate any valid instances');
193
+		}
194
+	}
195
+
196
+	/**
197
+	 * Returns the date for the current position of the iterator.
198
+	 *
199
+	 * @return DateTimeImmutable
200
+	 */
201
+	#[\ReturnTypeWillChange]
202
+	public function current()
203
+	{
204
+		if ($this->currentDate) {
205
+			return clone $this->currentDate;
206
+		}
207
+	}
208
+
209
+	/**
210
+	 * This method returns the start date for the current iteration of the
211
+	 * event.
212
+	 *
213
+	 * @return DateTimeImmutable
214
+	 */
215
+	public function getDtStart()
216
+	{
217
+		if ($this->currentDate) {
218
+			return clone $this->currentDate;
219
+		}
220
+	}
221
+
222
+	/**
223
+	 * This method returns the end date for the current iteration of the
224
+	 * event.
225
+	 *
226
+	 * @return DateTimeImmutable
227
+	 */
228
+	public function getDtEnd()
229
+	{
230
+		if (!$this->valid()) {
231
+			return;
232
+		}
233
+		if ($this->currentOverriddenEvent && $this->currentOverriddenEvent->DTEND) {
234
+			return $this->currentOverriddenEvent->DTEND->getDateTime($this->timeZone);
235
+		} else {
236
+			$end = clone $this->currentDate;
237
+
238
+			return $end->modify('+'.$this->eventDuration.' seconds');
239
+		}
240
+	}
241
+
242
+	/**
243
+	 * Returns a VEVENT for the current iterations of the event.
244
+	 *
245
+	 * This VEVENT will have a recurrence id, and its DTSTART and DTEND
246
+	 * altered.
247
+	 *
248
+	 * @return VEvent
249
+	 */
250
+	public function getEventObject()
251
+	{
252
+		if ($this->currentOverriddenEvent) {
253
+			return $this->currentOverriddenEvent;
254
+		}
255
+
256
+		$event = clone $this->masterEvent;
257
+
258
+		// Ignoring the following block, because PHPUnit's code coverage
259
+		// ignores most of these lines, and this messes with our stats.
260
+		//
261
+		// @codeCoverageIgnoreStart
262
+		unset(
263
+			$event->RRULE,
264
+			$event->EXDATE,
265
+			$event->RDATE,
266
+			$event->EXRULE,
267
+			$event->{'RECURRENCE-ID'}
268
+		);
269
+		// @codeCoverageIgnoreEnd
270
+
271
+		$event->DTSTART->setDateTime($this->getDtStart(), $event->DTSTART->isFloating());
272
+		if (isset($event->DTEND)) {
273
+			$event->DTEND->setDateTime($this->getDtEnd(), $event->DTEND->isFloating());
274
+		}
275
+		$recurid = clone $event->DTSTART;
276
+		$recurid->name = 'RECURRENCE-ID';
277
+		$event->add($recurid);
278
+
279
+		return $event;
280
+	}
281
+
282
+	/**
283
+	 * Returns the current position of the iterator.
284
+	 *
285
+	 * This is for us simply a 0-based index.
286
+	 *
287
+	 * @return int
288
+	 */
289
+	#[\ReturnTypeWillChange]
290
+	public function key()
291
+	{
292
+		// The counter is always 1 ahead.
293
+		return $this->counter - 1;
294
+	}
295
+
296
+	/**
297
+	 * This is called after next, to see if the iterator is still at a valid
298
+	 * position, or if it's at the end.
299
+	 *
300
+	 * @return bool
301
+	 */
302
+	#[\ReturnTypeWillChange]
303
+	public function valid()
304
+	{
305
+		if ($this->counter > Settings::$maxRecurrences && -1 !== Settings::$maxRecurrences) {
306
+			throw new MaxInstancesExceededException('Recurring events are only allowed to generate '.Settings::$maxRecurrences);
307
+		}
308
+
309
+		return (bool) $this->currentDate;
310
+	}
311
+
312
+	/**
313
+	 * Sets the iterator back to the starting point.
314
+	 *
315
+	 * @return void
316
+	 */
317
+	#[\ReturnTypeWillChange]
318
+	public function rewind()
319
+	{
320
+		$this->recurIterator->rewind();
321
+		// re-creating overridden event index.
322
+		$index = [];
323
+		foreach ($this->overriddenEvents as $key => $event) {
324
+			$stamp = $event->DTSTART->getDateTime($this->timeZone)->getTimeStamp();
325
+			$index[$stamp][] = $key;
326
+		}
327
+		krsort($index);
328
+		$this->counter = 0;
329
+		$this->overriddenEventsIndex = $index;
330
+		$this->currentOverriddenEvent = null;
331
+
332
+		$this->nextDate = null;
333
+		$this->currentDate = clone $this->startDate;
334
+
335
+		$this->next();
336
+	}
337
+
338
+	/**
339
+	 * Advances the iterator with one step.
340
+	 *
341
+	 * @return void
342
+	 */
343
+	#[\ReturnTypeWillChange]
344
+	public function next()
345
+	{
346
+		$this->currentOverriddenEvent = null;
347
+		++$this->counter;
348
+		if ($this->nextDate) {
349
+			// We had a stored value.
350
+			$nextDate = $this->nextDate;
351
+			$this->nextDate = null;
352
+		} else {
353
+			// We need to ask rruleparser for the next date.
354
+			// We need to do this until we find a date that's not in the
355
+			// exception list.
356
+			do {
357
+				if (!$this->recurIterator->valid()) {
358
+					$nextDate = null;
359
+					break;
360
+				}
361
+				$nextDate = $this->recurIterator->current();
362
+				$this->recurIterator->next();
363
+			} while (isset($this->exceptions[$nextDate->getTimeStamp()]));
364
+		}
365
+
366
+		// $nextDate now contains what rrule thinks is the next one, but an
367
+		// overridden event may cut ahead.
368
+		if ($this->overriddenEventsIndex) {
369
+			$offsets = end($this->overriddenEventsIndex);
370
+			$timestamp = key($this->overriddenEventsIndex);
371
+			$offset = end($offsets);
372
+			if (!$nextDate || $timestamp < $nextDate->getTimeStamp()) {
373
+				// Overridden event comes first.
374
+				$this->currentOverriddenEvent = $this->overriddenEvents[$offset];
375
+
376
+				// Putting the rrule next date aside.
377
+				$this->nextDate = $nextDate;
378
+				$this->currentDate = $this->currentOverriddenEvent->DTSTART->getDateTime($this->timeZone);
379
+
380
+				// Ensuring that this item will only be used once.
381
+				array_pop($this->overriddenEventsIndex[$timestamp]);
382
+				if (!$this->overriddenEventsIndex[$timestamp]) {
383
+					array_pop($this->overriddenEventsIndex);
384
+				}
385
+
386
+				// Exit point!
387
+				return;
388
+			}
389
+		}
390
+
391
+		$this->currentDate = $nextDate;
392
+	}
393
+
394
+	/**
395
+	 * Quickly jump to a date in the future.
396
+	 */
397
+	public function fastForward(DateTimeInterface $dateTime)
398
+	{
399
+		while ($this->valid() && $this->getDtEnd() <= $dateTime) {
400
+			$this->next();
401
+		}
402
+	}
403
+
404
+	/**
405
+	 * Returns true if this recurring event never ends.
406
+	 *
407
+	 * @return bool
408
+	 */
409
+	public function isInfinite()
410
+	{
411
+		return $this->recurIterator->isInfinite();
412
+	}
413
+
414
+	/**
415
+	 * RRULE parser.
416
+	 *
417
+	 * @var RRuleIterator
418
+	 */
419
+	protected $recurIterator;
420
+
421
+	/**
422
+	 * The duration, in seconds, of the master event.
423
+	 *
424
+	 * We use this to calculate the DTEND for subsequent events.
425
+	 */
426
+	protected $eventDuration;
427
+
428
+	/**
429
+	 * A reference to the main (master) event.
430
+	 *
431
+	 * @var VEVENT
432
+	 */
433
+	protected $masterEvent;
434
+
435
+	/**
436
+	 * List of overridden events.
437
+	 *
438
+	 * @var array
439
+	 */
440
+	protected $overriddenEvents = [];
441
+
442
+	/**
443
+	 * Overridden event index.
444
+	 *
445
+	 * Key is timestamp, value is the list of indexes of the item in the $overriddenEvent
446
+	 * property.
447
+	 *
448
+	 * @var array
449
+	 */
450
+	protected $overriddenEventsIndex;
451
+
452
+	/**
453
+	 * A list of recurrence-id's that are either part of EXDATE, or are
454
+	 * overridden.
455
+	 *
456
+	 * @var array
457
+	 */
458
+	protected $exceptions = [];
459
+
460
+	/**
461
+	 * Internal event counter.
462
+	 *
463
+	 * @var int
464
+	 */
465
+	protected $counter;
466
+
467
+	/**
468
+	 * The very start of the iteration process.
469
+	 *
470
+	 * @var DateTimeImmutable
471
+	 */
472
+	protected $startDate;
473
+
474
+	/**
475
+	 * Where we are currently in the iteration process.
476
+	 *
477
+	 * @var DateTimeImmutable
478
+	 */
479
+	protected $currentDate;
480
+
481
+	/**
482
+	 * The next date from the rrule parser.
483
+	 *
484
+	 * Sometimes we need to temporary store the next date, because an
485
+	 * overridden event came before.
486
+	 *
487
+	 * @var DateTimeImmutable
488
+	 */
489
+	protected $nextDate;
490
+
491
+	/**
492
+	 * The event that overwrites the current iteration.
493
+	 *
494
+	 * @var VEVENT
495
+	 */
496
+	protected $currentOverriddenEvent;
497 497
 }
Please login to merge, or discard this patch.