dolibarr 18.0.6
ical.class.php
Go to the documentation of this file.
1<?php
2/* Copyright (C) 2006 Roman Ozana <ozana@omdesign.cz>
3 * Copyright (C) 2011 Juanjo Menent <jmenent@2byte.es>
4 * Copyright (C) 2013-2014 Laurent Destailleur <eldy@users.sourceforge.net>
5 * Copyright (C) 2012 Regis Houssin <regis.houssin@inodbox.com>
6 * Copyright (C) 2019 Frédéric France <frederic.france@netlogic.fr>
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 3 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program. If not, see <https://www.gnu.org/licenses/>.
20 */
21
27require_once DOL_DOCUMENT_ROOT.'/core/lib/xcal.lib.php';
28require_once DOL_DOCUMENT_ROOT.'/core/lib/geturl.lib.php';
29
30
34class ICal
35{
36 // Text in file
37 public $file_text;
38 public $cal; // Array to save iCalendar parse data
39 public $event_count; // Number of Events
40 public $todo_count; // Number of Todos
41 public $freebusy_count; // Number of Freebusy
42 public $last_key; //Help variable save last key (multiline string)
43 public $error;
44
45
49 public function __construct()
50 {
51 }
52
53 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
60 public function read_file($file)
61 {
62 // phpcs:enable
63 $this->file = $file;
64 $file_text = '';
65
66 $tmpresult = getURLContent($file, 'GET');
67 if ($tmpresult['http_code'] != 200) {
68 $file_text = null;
69 $this->error = 'Error: '.$tmpresult['http_code'].' '.$tmpresult['content'];
70 } else {
71 $file_text = preg_replace("/[\r\n]{1,} /", "", $tmpresult['content']);
72 }
73 //var_dump($tmpresult);
74
75 return $file_text; // return all text
76 }
77
78 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
84 public function get_event_count()
85 {
86 // phpcs:enable
87 return $this->event_count;
88 }
89
90 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
96 public function get_todo_count()
97 {
98 // phpcs:enable
99 return $this->todo_count;
100 }
101
110 public function parse($uri, $usecachefile = '', $delaycache = 3600)
111 {
112 $this->cal = array(); // new empty array
113
114 $this->event_count = -1;
115 $this->file_text = null;
116
117 // Save file into a cache
118 if ($usecachefile) {
119 include_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php';
120 $datefile = dol_filemtime($usecachefile);
121 $now = dol_now('gmt');
122 //print $datefile.' '.$now.' ...';
123 if ($datefile && $datefile > ($now - $delaycache)) {
124 // We reuse the cache file
125 $this->file_text = file_get_contents($usecachefile);
126 }
127 }
128
129 // read FILE text
130 if (is_null($this->file_text)) {
131 $this->file_text = $this->read_file($uri);
132
133 if ($usecachefile && !is_null($this->file_text)) {
134 // Save the file content into cache file
135 file_put_contents($usecachefile, $this->file_text, LOCK_EX);
136 dolChmod($usecachefile);
137 }
138 }
139
140 $this->file_text = preg_split("[\n]", $this->file_text);
141
142 // is this text vcalendar standard text ? on line 1 is BEGIN:VCALENDAR
143 if (!stristr($this->file_text[0], 'BEGIN:VCALENDAR')) {
144 return 'error not VCALENDAR';
145 }
146
147 $insidealarm = 0;
148 $tmpkey = ''; $tmpvalue = ''; $type = '';
149 foreach ($this->file_text as $text) {
150 $text = trim($text); // trim one line
151 if (!empty($text)) {
152 // get Key and Value VCALENDAR:Begin -> Key = VCALENDAR, Value = begin
153 list($key, $value) = $this->retun_key_value($text);
154 //var_dump($text.' -> '.$key.' - '.$value);
155
156 switch ($text) { // search special string
157 case "BEGIN:VTODO":
158 $this->todo_count = $this->todo_count + 1; // new to do begin
159 $type = "VTODO";
160 break;
161
162 case "BEGIN:VEVENT":
163 $this->event_count = $this->event_count + 1; // new event begin
164 $type = "VEVENT";
165 break;
166
167 case "BEGIN:VFREEBUSY":
168 $this->freebusy_count = $this->freebusy_count + 1; // new event begin
169 $type = "VFREEBUSY";
170 break;
171
172 case "BEGIN:VCALENDAR": // all other special string
173 case "BEGIN:DAYLIGHT":
174 case "BEGIN:VTIMEZONE":
175 case "BEGIN:STANDARD":
176 $type = $value; // save array under value key
177 break;
178
179 case "END:VTODO": // end special text - goto VCALENDAR key
180 case "END:VEVENT":
181 case "END:VFREEBUSY":
182 case "END:VCALENDAR":
183 case "END:DAYLIGHT":
184 case "END:VTIMEZONE":
185 case "END:STANDARD":
186 $type = "VCALENDAR";
187 break;
188
189 // Manage VALARM that are inside a VEVENT to avoid fields of VALARM to overwrites fields of VEVENT
190 case "BEGIN:VALARM":
191 $insidealarm = 1;
192 break;
193 case "END:VALARM":
194 $insidealarm = 0;
195 break;
196
197 default: // no special string (SUMMARY, DESCRIPTION, ...)
198 if ($tmpvalue) {
199 $tmpvalue .= $text;
200 if (!preg_match('/=$/', $text)) { // No more lines
201 $key = $tmpkey;
202 $value = quotedPrintDecode(preg_replace('/^ENCODING=QUOTED-PRINTABLE:/i', '', $tmpvalue));
203 $tmpkey = '';
204 $tmpvalue = '';
205 }
206 } elseif (preg_match('/^ENCODING=QUOTED-PRINTABLE:/i', $value)) {
207 if (preg_match('/=$/', $value)) {
208 $tmpkey = $key;
209 $tmpvalue = $tmpvalue.preg_replace('/=$/', "", $value); // We must wait to have next line to have complete message
210 } else {
211 $value = quotedPrintDecode(preg_replace('/^ENCODING=QUOTED-PRINTABLE:/i', '', $tmpvalue.$value));
212 }
213 } //$value=quotedPrintDecode($tmpvalue.$value);
214 if (!$insidealarm && !$tmpkey) {
215 $this->add_to_array($type, $key, $value); // add to array
216 }
217 break;
218 }
219 }
220 }
221
222 //var_dump($this->cal);
223 return $this->cal;
224 }
225
226 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
235 public function add_to_array($type, $key, $value)
236 {
237 // phpcs:enable
238
239 //print 'type='.$type.' key='.$key.' value='.$value.'<br>'."\n";
240
241 if (empty($key)) {
242 $key = $this->last_key;
243 switch ($type) {
244 case 'VEVENT':
245 $value = $this->cal[$type][$this->event_count][$key].$value;
246 break;
247 case 'VFREEBUSY':
248 $value = $this->cal[$type][$this->freebusy_count][$key].$value;
249 break;
250 case 'VTODO':
251 $value = $this->cal[$type][$this->todo_count][$key].$value;
252 break;
253 }
254 }
255
256 if (($key == "DTSTAMP") || ($key == "LAST-MODIFIED") || ($key == "CREATED")) {
257 $value = $this->ical_date_to_unix($value);
258 }
259 //if ($key == "RRULE" ) $value = $this->ical_rrule($value);
260
261 if (stristr($key, "DTSTART") || stristr($key, "DTEND") || stristr($key, "DTSTART;VALUE=DATE") || stristr($key, "DTEND;VALUE=DATE")) {
262 if (stristr($key, "DTSTART;VALUE=DATE") || stristr($key, "DTEND;VALUE=DATE")) {
263 list($key, $value) = array($key, $value);
264 } else {
265 list($key, $value) = $this->ical_dt_date($key, $value);
266 }
267 }
268
269 switch ($type) {
270 case "VTODO":
271 $this->cal[$type][$this->todo_count][$key] = $value;
272 break;
273
274 case "VEVENT":
275 $this->cal[$type][$this->event_count][$key] = $value;
276 break;
277
278 case "VFREEBUSY":
279 $this->cal[$type][$this->freebusy_count][$key] = $value;
280 break;
281
282 default:
283 $this->cal[$type][$key] = $value;
284 break;
285 }
286 $this->last_key = $key;
287 }
288
289 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
296 public function retun_key_value($text)
297 {
298 // phpcs:enable
299 /*
300 preg_match("/([^:]+)[:]([\w\W]+)/", $text, $matches);
301
302 if (empty($matches))
303 {
304 return array(false,$text);
305 }
306 else
307 {
308 $matches = array_splice($matches, 1, 2);
309 return $matches;
310 }*/
311 return explode(':', $text, 2);
312 }
313
314 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
321 public function ical_rrule($value)
322 {
323 // phpcs:enable
324 $result = array();
325 $rrule = explode(';', $value);
326 foreach ($rrule as $line) {
327 $rcontent = explode('=', $line);
328 $result[$rcontent[0]] = $rcontent[1];
329 }
330 return $result;
331 }
332
333 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
340 public function ical_date_to_unix($ical_date)
341 {
342 // phpcs:enable
343 $ical_date = str_replace('T', '', $ical_date);
344 $ical_date = str_replace('Z', '', $ical_date);
345
346 $ntime = 0;
347 // TIME LIMITED EVENT
348 if (preg_match('/([0-9]{4})([0-9]{2})([0-9]{2})([0-9]{0,2})([0-9]{0,2})([0-9]{0,2})/', $ical_date, $date)) {
349 $ntime = dol_mktime($date[4], $date[5], $date[6], $date[2], $date[3], $date[1], true);
350 }
351
352 //if (empty($date[4])) print 'Error bad date: '.$ical_date.' - date1='.$date[1];
353 //print dol_print_date($ntime,'dayhour');exit;
354 return $ntime; // ntime is a GTM time
355 }
356
357 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
365 public function ical_dt_date($key, $value)
366 {
367 // phpcs:enable
368 $return_value = array();
369 $value = $this->ical_date_to_unix($value);
370
371 // Analyse TZID
372 $temp = explode(";", $key);
373
374 if (empty($temp[1])) { // not TZID
375 $value = str_replace('T', '', $value);
376 return array($key, $value);
377 }
378
379 $key = $temp[0];
380 $temp = explode("=", $temp[1]);
381 $return_value[$temp[0]] = $temp[1];
382 $return_value['unixtime'] = $value;
383
384 return array($key, $return_value);
385 }
386
387 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
393 public function get_sort_event_list()
394 {
395 // phpcs:enable
396 $temp = $this->get_event_list();
397 if (!empty($temp)) {
398 usort($temp, array(&$this, "ical_dtstart_compare"));
399 return $temp;
400 } else {
401 return false;
402 }
403 }
404
405 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
413 public function ical_dtstart_compare($a, $b)
414 {
415 // phpcs:enable
416 return strnatcasecmp($a['DTSTART']['unixtime'], $b['DTSTART']['unixtime']);
417 }
418
419 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
425 public function get_event_list()
426 {
427 // phpcs:enable
428 return (empty($this->cal['VEVENT']) ? array() : $this->cal['VEVENT']);
429 }
430
431 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
437 public function get_freebusy_list()
438 {
439 // phpcs:enable
440 return (empty($this->cal['VFREEBUSY']) ? array() : $this->cal['VFREEBUSY']);
441 }
442
443 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
449 public function get_todo_list()
450 {
451 // phpcs:enable
452 return $this->cal['VTODO'];
453 }
454
455 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
461 public function get_calender_data()
462 {
463 // phpcs:enable
464 return $this->cal['VCALENDAR'];
465 }
466
467 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
473 public function get_all_data()
474 {
475 // phpcs:enable
476 return $this->cal;
477 }
478}
Class to read/parse ICal calendars.
get_all_data()
Return array with all data.
get_event_list()
Return eventlist array (not sorted eventlist array)
parse($uri, $usecachefile='', $delaycache=3600)
Translate Calendar.
ical_dt_date($key, $value)
Return unix date from iCal date format.
ical_rrule($value)
Parse RRULE return array.
retun_key_value($text)
Parse text "XXXX:value text some with : " and return array($key = "XXXX", $value="value");.
get_todo_count()
Returns the number of to do.
ical_dtstart_compare($a, $b)
Compare two unix timestamp.
get_event_count()
Returns the number of calendar events.
__construct()
Constructor.
add_to_array($type, $key, $value)
Add to $this->ical array one value and key.
read_file($file)
Read text file, icalender text file.
get_sort_event_list()
Return sorted eventlist as array or false if calendar is empty.
get_freebusy_list()
Return freebusy array (not sort eventlist array)
get_todo_list()
Return to do array (not sorted todo array)
get_calender_data()
Return base calendar data.
ical_date_to_unix($ical_date)
Return Unix time from ical date time fomrat (YYYYMMDD[T]HHMMSS[Z] or YYYYMMDD[T]HHMMSS)
dol_filemtime($pathoffile)
Return time of a file.
dol_mktime($hour, $minute, $second, $month, $day, $year, $gm='auto', $check=1)
Return a timestamp date built from detailed informations (by default a local PHP server timestamp) Re...
dolChmod($filepath, $newmask='')
Change mod of a file.
dol_now($mode='auto')
Return date for now.
getURLContent($url, $postorget='GET', $param='', $followlocation=1, $addheaders=array(), $allowedschemes=array('http', 'https'), $localurl=0, $ssl_verifypeer=-1)
Function to get a content from an URL (use proxy if proxy defined).
quotedPrintDecode($str)
Decode vcal format.
Definition xcal.lib.php:590