dolibarr  9.0.0
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  *
7  * This program is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 3 of the License, or
10  * (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program. If not, see <http://www.gnu.org/licenses/>.
19  */
20 
26 require_once DOL_DOCUMENT_ROOT.'/core/lib/xcal.lib.php';
27 
28 
32 class ICal
33 {
34  var $file_text; // Text in file
35  var $cal; // Array to save iCalendar parse data
36  var $event_count; // Number of Events
37  var $todo_count; // Number of Todos
38  var $freebusy_count; // Number of Freebusy
39  var $last_key; //Help variable save last key (multiline string)
40 
41 
45  public function __construct()
46  {
47  }
48 
49  // phpcs:disable PEAR.NamingConventions.ValidFunctionName.NotCamelCaps
56  function read_file($file)
57  {
58  // phpcs:enable
59  $this->file = $file;
60  $file_text='';
61 
62  $tmparray=file($file);
63  if (is_array($tmparray))
64  {
65  $file_text = join("", $tmparray); //load file
66  $file_text = preg_replace("/[\r\n]{1,} /","",$file_text);
67  }
68  return $file_text; // return all text
69  }
70 
71  // phpcs:disable PEAR.NamingConventions.ValidFunctionName.NotCamelCaps
77  function get_event_count()
78  {
79  // phpcs:enable
80  return $this->event_count;
81  }
82 
83  // phpcs:disable PEAR.NamingConventions.ValidFunctionName.NotCamelCaps
89  function get_todo_count()
90  {
91  // phpcs:enable
92  return $this->todo_count;
93  }
94 
101  function parse($uri)
102  {
103  $this->cal = array(); // new empty array
104 
105  $this->event_count = -1;
106 
107  // read FILE text
108  $this->file_text = $this->read_file($uri);
109 
110  $this->file_text = preg_split("[\n]", $this->file_text);
111 
112  // is this text vcalendar standart text ? on line 1 is BEGIN:VCALENDAR
113  if (!stristr($this->file_text[0],'BEGIN:VCALENDAR')) return 'error not VCALENDAR';
114 
115  $insidealarm=0;
116  $tmpkey='';$tmpvalue=''; $type='';
117  foreach ($this->file_text as $text)
118  {
119  $text = trim($text); // trim one line
120  if (!empty($text))
121  {
122  // get Key and Value VCALENDAR:Begin -> Key = VCALENDAR, Value = begin
123  list($key, $value) = $this->retun_key_value($text);
124  //var_dump($text.' -> '.$key.' - '.$value);
125 
126  switch ($text) // search special string
127  {
128  case "BEGIN:VTODO":
129  $this->todo_count = $this->todo_count+1; // new to do begin
130  $type = "VTODO";
131  break;
132 
133  case "BEGIN:VEVENT":
134  $this->event_count = $this->event_count+1; // new event begin
135  $type = "VEVENT";
136  break;
137 
138  case "BEGIN:VFREEBUSY":
139  $this->freebusy_count = $this->freebusy_count+1; // new event begin
140  $type = "VFREEBUSY";
141  break;
142 
143  case "BEGIN:VCALENDAR": // all other special string
144  case "BEGIN:DAYLIGHT":
145  case "BEGIN:VTIMEZONE":
146  case "BEGIN:STANDARD":
147  $type = $value; // save array under value key
148  break;
149 
150  case "END:VTODO": // end special text - goto VCALENDAR key
151  case "END:VEVENT":
152  case "END:VFREEBUSY":
153 
154  case "END:VCALENDAR":
155  case "END:DAYLIGHT":
156  case "END:VTIMEZONE":
157  case "END:STANDARD":
158  $type = "VCALENDAR";
159  break;
160 
161  // Manage VALARM that are inside a VEVENT to avoid fields of VALARM to overwrites fields of VEVENT
162  case "BEGIN:VALARM":
163  $insidealarm=1;
164  break;
165  case "END:VALARM":
166  $insidealarm=0;
167  break;
168 
169  default: // no special string (SUMMARY, DESCRIPTION, ...)
170  if ($tmpvalue)
171  {
172  $tmpvalue .= $text;
173  if (! preg_match('/=$/',$text)) // No more lines
174  {
175  $key=$tmpkey;
176  $value=quotedPrintDecode(preg_replace('/^ENCODING=QUOTED-PRINTABLE:/i','',$tmpvalue));
177  $tmpkey='';
178  $tmpvalue='';
179  }
180  }
181  elseif (preg_match('/^ENCODING=QUOTED-PRINTABLE:/i',$value))
182  {
183  if (preg_match('/=$/',$value))
184  {
185  $tmpkey=$key;
186  $tmpvalue=$tmpvalue.preg_replace('/=$/',"",$value); // We must wait to have next line to have complete message
187  }
188  else
189  {
190  $value=quotedPrintDecode(preg_replace('/^ENCODING=QUOTED-PRINTABLE:/i','',$tmpvalue.$value));
191  }
192  } //$value=quotedPrintDecode($tmpvalue.$value);
193  if (! $insidealarm && ! $tmpkey) $this->add_to_array($type, $key, $value); // add to array
194  break;
195  }
196  }
197  }
198 
199  //var_dump($this->cal);
200  return $this->cal;
201  }
202 
203  // phpcs:disable PEAR.NamingConventions.ValidFunctionName.NotCamelCaps
212  function add_to_array($type, $key, $value)
213  {
214  // phpcs:enable
215 
216  //print 'type='.$type.' key='.$key.' value='.$value.'<br>'."\n";
217 
218  if (empty($key))
219  {
220  $key = $this->last_key;
221  switch ($type)
222  {
223  case 'VEVENT': $value = $this->cal[$type][$this->event_count][$key].$value;break;
224  case 'VFREEBUSY': $value = $this->cal[$type][$this->freebusy_count][$key].$value;break;
225  case 'VTODO': $value = $this->cal[$type][$this->todo_count][$key].$value;break;
226  }
227  }
228 
229  if (($key == "DTSTAMP") || ($key == "LAST-MODIFIED") || ($key == "CREATED")) $value = $this->ical_date_to_unix($value);
230  //if ($key == "RRULE" ) $value = $this->ical_rrule($value);
231 
232  if (stristr($key,"DTSTART") || stristr($key,"DTEND") || stristr($key,"DTSTART;VALUE=DATE") || stristr($key,"DTEND;VALUE=DATE"))
233  {
234  if (stristr($key,"DTSTART;VALUE=DATE") || stristr($key,"DTEND;VALUE=DATE"))
235  {
236  list($key,$value) = array($key,$value);
237  }
238  else
239  {
240  list($key,$value) = $this->ical_dt_date($key,$value);
241  }
242  }
243 
244  switch ($type)
245  {
246  case "VTODO":
247  $this->cal[$type][$this->todo_count][$key] = $value;
248  break;
249 
250  case "VEVENT":
251  $this->cal[$type][$this->event_count][$key] = $value;
252  break;
253 
254  case "VFREEBUSY":
255  $this->cal[$type][$this->freebusy_count][$key] = $value;
256  break;
257 
258  default:
259  $this->cal[$type][$key] = $value;
260  break;
261  }
262  $this->last_key = $key;
263  }
264 
265  // phpcs:disable PEAR.NamingConventions.ValidFunctionName.NotCamelCaps
272  function retun_key_value($text)
273  {
274  // phpcs:enable
275  /*
276  preg_match("/([^:]+)[:]([\w\W]+)/", $text, $matches);
277 
278  if (empty($matches))
279  {
280  return array(false,$text);
281  }
282  else
283  {
284  $matches = array_splice($matches, 1, 2);
285  return $matches;
286  }*/
287  return explode(':',$text,2);
288  }
289 
290  // phpcs:disable PEAR.NamingConventions.ValidFunctionName.NotCamelCaps
297  function ical_rrule($value)
298  {
299  // phpcs:enable
300  $result = array();
301  $rrule = explode(';',$value);
302  foreach ($rrule as $line)
303  {
304  $rcontent = explode('=', $line);
305  $result[$rcontent[0]] = $rcontent[1];
306  }
307  return $result;
308  }
309 
310  // phpcs:disable PEAR.NamingConventions.ValidFunctionName.NotCamelCaps
317  function ical_date_to_unix($ical_date)
318  {
319  // phpcs:enable
320  $ical_date = str_replace('T', '', $ical_date);
321  $ical_date = str_replace('Z', '', $ical_date);
322 
323  $ntime=0;
324  // TIME LIMITED EVENT
325  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))
326  $ntime=dol_mktime($date[4], $date[5], $date[6], $date[2],$date[3], $date[1], true);
327 
328  //if (empty($date[4])) print 'Error bad date: '.$ical_date.' - date1='.$date[1];
329  //print dol_print_date($ntime,'dayhour');exit;
330  return $ntime; // ntime is a GTM time
331  }
332 
333  // phpcs:disable PEAR.NamingConventions.ValidFunctionName.NotCamelCaps
341  function ical_dt_date($key, $value)
342  {
343  // phpcs:enable
344  $return_value = array();
345  $value = $this->ical_date_to_unix($value);
346 
347  // Analyse TZID
348  $temp = explode(";",$key);
349 
350  if (empty($temp[1])) // not TZID
351  {
352  $value = str_replace('T', '', $value);
353  return array($key,$value);
354  }
355 
356  $key = $temp[0];
357  $temp = explode("=", $temp[1]);
358  $return_value[$temp[0]] = $temp[1];
359  $return_value['unixtime'] = $value;
360 
361  return array($key,$return_value);
362  }
363 
364  // phpcs:disable PEAR.NamingConventions.ValidFunctionName.NotCamelCaps
371  {
372  // phpcs:enable
373  $temp = $this->get_event_list();
374  if (!empty($temp))
375  {
376  usort($temp, array(&$this, "ical_dtstart_compare"));
377  return $temp;
378  }
379  else
380  {
381  return false;
382  }
383  }
384 
385  // phpcs:disable PEAR.NamingConventions.ValidFunctionName.NotCamelCaps
393  function ical_dtstart_compare($a, $b)
394  {
395  // phpcs:enable
396  return strnatcasecmp($a['DTSTART']['unixtime'], $b['DTSTART']['unixtime']);
397  }
398 
399  // phpcs:disable PEAR.NamingConventions.ValidFunctionName.NotCamelCaps
405  function get_event_list()
406  {
407  // phpcs:enable
408  return (! empty($this->cal['VEVENT'])?$this->cal['VEVENT']:'');
409  }
410 
411  // phpcs:disable PEAR.NamingConventions.ValidFunctionName.NotCamelCaps
417  function get_freebusy_list()
418  {
419  // phpcs:enable
420  return $this->cal['VFREEBUSY'];
421  }
422 
423  // phpcs:disable PEAR.NamingConventions.ValidFunctionName.NotCamelCaps
429  function get_todo_list()
430  {
431  // phpcs:enable
432  return $this->cal['VTODO'];
433  }
434 
435  // phpcs:disable PEAR.NamingConventions.ValidFunctionName.NotCamelCaps
441  function get_calender_data()
442  {
443  // phpcs:enable
444  return $this->cal['VCALENDAR'];
445  }
446 
447  // phpcs:disable PEAR.NamingConventions.ValidFunctionName.NotCamelCaps
453  function get_all_data()
454  {
455  // phpcs:enable
456  return $this->cal;
457  }
458 }
ical_rrule($value)
Parse RRULE return array.
Definition: ical.class.php:297
ical_date_to_unix($ical_date)
Return Unix time from ical date time fomrat (YYYYMMDD[T]HHMMSS[Z] or YYYYMMDD[T]HHMMSS) ...
Definition: ical.class.php:317
get_calender_data()
Return base calendar data.
Definition: ical.class.php:441
dol_mktime($hour, $minute, $second, $month, $day, $year, $gm=false, $check=1)
Return a timestamp date built from detailed informations (by default a local PHP server timestamp) Re...
ical_dt_date($key, $value)
Return unix date from iCal date format.
Definition: ical.class.php:341
add_to_array($type, $key, $value)
Add to $this->ical array one value and key.
Definition: ical.class.php:212
ical_dtstart_compare($a, $b)
Compare two unix timestamp.
Definition: ical.class.php:393
__construct()
Constructor.
Definition: ical.class.php:45
retun_key_value($text)
Parse text "XXXX:value text some with : " and return array($key = "XXXX", $value="value");.
Definition: ical.class.php:272
get_all_data()
Return array with all data.
Definition: ical.class.php:453
Class to read/parse ICal calendars.
Definition: ical.class.php:32
get_todo_list()
Return to do array (not sort to do array)
Definition: ical.class.php:429
quotedPrintDecode($str)
Decode vcal format.
Definition: xcal.lib.php:516
read_file($file)
Read text file, icalender text file.
Definition: ical.class.php:56
get_freebusy_list()
Return eventlist array (not sort eventlist array)
Definition: ical.class.php:417
get_todo_count()
Returns the number of to do.
Definition: ical.class.php:89
parse($uri)
Translate Calendar.
Definition: ical.class.php:101
get_event_count()
Returns the number of calendar events.
Definition: ical.class.php:77
get_sort_event_list()
Return sorted eventlist as array or false if calenar is empty.
Definition: ical.class.php:370
get_event_list()
Return eventlist array (not sort eventlist array)
Definition: ical.class.php:405