dolibarr  13.0.2
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 
27 require_once DOL_DOCUMENT_ROOT.'/core/lib/xcal.lib.php';
28 
29 
33 class ICal
34 {
35  // Text in file
36  public $file_text;
37  public $cal; // Array to save iCalendar parse data
38  public $event_count; // Number of Events
39  public $todo_count; // Number of Todos
40  public $freebusy_count; // Number of Freebusy
41  public $last_key; //Help variable save last key (multiline string)
42 
43 
47  public function __construct()
48  {
49  }
50 
51  // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
58  public function read_file($file)
59  {
60  // phpcs:enable
61  $this->file = $file;
62  $file_text = '';
63 
64  $tmparray = file($file);
65  if (is_array($tmparray))
66  {
67  $file_text = join("", $tmparray); //load file
68  $file_text = preg_replace("/[\r\n]{1,} /", "", $file_text);
69  }
70  return $file_text; // return all text
71  }
72 
73  // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
79  public function get_event_count()
80  {
81  // phpcs:enable
82  return $this->event_count;
83  }
84 
85  // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
91  public function get_todo_count()
92  {
93  // phpcs:enable
94  return $this->todo_count;
95  }
96 
103  public function parse($uri)
104  {
105  $this->cal = array(); // new empty array
106 
107  $this->event_count = -1;
108 
109  // read FILE text
110  $this->file_text = $this->read_file($uri);
111 
112  $this->file_text = preg_split("[\n]", $this->file_text);
113 
114  // is this text vcalendar standard text ? on line 1 is BEGIN:VCALENDAR
115  if (!stristr($this->file_text[0], 'BEGIN:VCALENDAR')) return 'error not VCALENDAR';
116 
117  $insidealarm = 0;
118  $tmpkey = ''; $tmpvalue = ''; $type = '';
119  foreach ($this->file_text as $text)
120  {
121  $text = trim($text); // trim one line
122  if (!empty($text))
123  {
124  // get Key and Value VCALENDAR:Begin -> Key = VCALENDAR, Value = begin
125  list($key, $value) = $this->retun_key_value($text);
126  //var_dump($text.' -> '.$key.' - '.$value);
127 
128  switch ($text) // search special string
129  {
130  case "BEGIN:VTODO":
131  $this->todo_count = $this->todo_count + 1; // new to do begin
132  $type = "VTODO";
133  break;
134 
135  case "BEGIN:VEVENT":
136  $this->event_count = $this->event_count + 1; // new event begin
137  $type = "VEVENT";
138  break;
139 
140  case "BEGIN:VFREEBUSY":
141  $this->freebusy_count = $this->freebusy_count + 1; // new event begin
142  $type = "VFREEBUSY";
143  break;
144 
145  case "BEGIN:VCALENDAR": // all other special string
146  case "BEGIN:DAYLIGHT":
147  case "BEGIN:VTIMEZONE":
148  case "BEGIN:STANDARD":
149  $type = $value; // save array under value key
150  break;
151 
152  case "END:VTODO": // end special text - goto VCALENDAR key
153  case "END:VEVENT":
154  case "END:VFREEBUSY":
155 
156  case "END:VCALENDAR":
157  case "END:DAYLIGHT":
158  case "END:VTIMEZONE":
159  case "END:STANDARD":
160  $type = "VCALENDAR";
161  break;
162 
163  // Manage VALARM that are inside a VEVENT to avoid fields of VALARM to overwrites fields of VEVENT
164  case "BEGIN:VALARM":
165  $insidealarm = 1;
166  break;
167  case "END:VALARM":
168  $insidealarm = 0;
169  break;
170 
171  default: // no special string (SUMMARY, DESCRIPTION, ...)
172  if ($tmpvalue)
173  {
174  $tmpvalue .= $text;
175  if (!preg_match('/=$/', $text)) // No more lines
176  {
177  $key = $tmpkey;
178  $value = quotedPrintDecode(preg_replace('/^ENCODING=QUOTED-PRINTABLE:/i', '', $tmpvalue));
179  $tmpkey = '';
180  $tmpvalue = '';
181  }
182  } elseif (preg_match('/^ENCODING=QUOTED-PRINTABLE:/i', $value))
183  {
184  if (preg_match('/=$/', $value))
185  {
186  $tmpkey = $key;
187  $tmpvalue = $tmpvalue.preg_replace('/=$/', "", $value); // We must wait to have next line to have complete message
188  } else {
189  $value = quotedPrintDecode(preg_replace('/^ENCODING=QUOTED-PRINTABLE:/i', '', $tmpvalue.$value));
190  }
191  } //$value=quotedPrintDecode($tmpvalue.$value);
192  if (!$insidealarm && !$tmpkey) $this->add_to_array($type, $key, $value); // add to array
193  break;
194  }
195  }
196  }
197 
198  //var_dump($this->cal);
199  return $this->cal;
200  }
201 
202  // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
211  public function add_to_array($type, $key, $value)
212  {
213  // phpcs:enable
214 
215  //print 'type='.$type.' key='.$key.' value='.$value.'<br>'."\n";
216 
217  if (empty($key))
218  {
219  $key = $this->last_key;
220  switch ($type)
221  {
222  case 'VEVENT': $value = $this->cal[$type][$this->event_count][$key].$value; break;
223  case 'VFREEBUSY': $value = $this->cal[$type][$this->freebusy_count][$key].$value; break;
224  case 'VTODO': $value = $this->cal[$type][$this->todo_count][$key].$value; break;
225  }
226  }
227 
228  if (($key == "DTSTAMP") || ($key == "LAST-MODIFIED") || ($key == "CREATED")) $value = $this->ical_date_to_unix($value);
229  //if ($key == "RRULE" ) $value = $this->ical_rrule($value);
230 
231  if (stristr($key, "DTSTART") || stristr($key, "DTEND") || stristr($key, "DTSTART;VALUE=DATE") || stristr($key, "DTEND;VALUE=DATE"))
232  {
233  if (stristr($key, "DTSTART;VALUE=DATE") || stristr($key, "DTEND;VALUE=DATE"))
234  {
235  list($key, $value) = array($key, $value);
236  } else {
237  list($key, $value) = $this->ical_dt_date($key, $value);
238  }
239  }
240 
241  switch ($type)
242  {
243  case "VTODO":
244  $this->cal[$type][$this->todo_count][$key] = $value;
245  break;
246 
247  case "VEVENT":
248  $this->cal[$type][$this->event_count][$key] = $value;
249  break;
250 
251  case "VFREEBUSY":
252  $this->cal[$type][$this->freebusy_count][$key] = $value;
253  break;
254 
255  default:
256  $this->cal[$type][$key] = $value;
257  break;
258  }
259  $this->last_key = $key;
260  }
261 
262  // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
269  public function retun_key_value($text)
270  {
271  // phpcs:enable
272  /*
273  preg_match("/([^:]+)[:]([\w\W]+)/", $text, $matches);
274 
275  if (empty($matches))
276  {
277  return array(false,$text);
278  }
279  else
280  {
281  $matches = array_splice($matches, 1, 2);
282  return $matches;
283  }*/
284  return explode(':', $text, 2);
285  }
286 
287  // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
294  public function ical_rrule($value)
295  {
296  // phpcs:enable
297  $result = array();
298  $rrule = explode(';', $value);
299  foreach ($rrule as $line)
300  {
301  $rcontent = explode('=', $line);
302  $result[$rcontent[0]] = $rcontent[1];
303  }
304  return $result;
305  }
306 
307  // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
314  public function ical_date_to_unix($ical_date)
315  {
316  // phpcs:enable
317  $ical_date = str_replace('T', '', $ical_date);
318  $ical_date = str_replace('Z', '', $ical_date);
319 
320  $ntime = 0;
321  // TIME LIMITED EVENT
322  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))
323  $ntime = dol_mktime($date[4], $date[5], $date[6], $date[2], $date[3], $date[1], true);
324 
325  //if (empty($date[4])) print 'Error bad date: '.$ical_date.' - date1='.$date[1];
326  //print dol_print_date($ntime,'dayhour');exit;
327  return $ntime; // ntime is a GTM time
328  }
329 
330  // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
338  public function ical_dt_date($key, $value)
339  {
340  // phpcs:enable
341  $return_value = array();
342  $value = $this->ical_date_to_unix($value);
343 
344  // Analyse TZID
345  $temp = explode(";", $key);
346 
347  if (empty($temp[1])) // not TZID
348  {
349  $value = str_replace('T', '', $value);
350  return array($key, $value);
351  }
352 
353  $key = $temp[0];
354  $temp = explode("=", $temp[1]);
355  $return_value[$temp[0]] = $temp[1];
356  $return_value['unixtime'] = $value;
357 
358  return array($key, $return_value);
359  }
360 
361  // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
367  public function get_sort_event_list()
368  {
369  // phpcs:enable
370  $temp = $this->get_event_list();
371  if (!empty($temp))
372  {
373  usort($temp, array(&$this, "ical_dtstart_compare"));
374  return $temp;
375  } else {
376  return false;
377  }
378  }
379 
380  // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
388  public function ical_dtstart_compare($a, $b)
389  {
390  // phpcs:enable
391  return strnatcasecmp($a['DTSTART']['unixtime'], $b['DTSTART']['unixtime']);
392  }
393 
394  // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
400  public function get_event_list()
401  {
402  // phpcs:enable
403  return (!empty($this->cal['VEVENT']) ? $this->cal['VEVENT'] : '');
404  }
405 
406  // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
412  public function get_freebusy_list()
413  {
414  // phpcs:enable
415  return $this->cal['VFREEBUSY'];
416  }
417 
418  // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
424  public function get_todo_list()
425  {
426  // phpcs:enable
427  return $this->cal['VTODO'];
428  }
429 
430  // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
436  public function get_calender_data()
437  {
438  // phpcs:enable
439  return $this->cal['VCALENDAR'];
440  }
441 
442  // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
448  public function get_all_data()
449  {
450  // phpcs:enable
451  return $this->cal;
452  }
453 }
ical_rrule($value)
Parse RRULE return array.
Definition: ical.class.php:294
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:314
get_calender_data()
Return base calendar data.
Definition: ical.class.php:436
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...
ical_dt_date($key, $value)
Return unix date from iCal date format.
Definition: ical.class.php:338
add_to_array($type, $key, $value)
Add to $this-&gt;ical array one value and key.
Definition: ical.class.php:211
ical_dtstart_compare($a, $b)
Compare two unix timestamp.
Definition: ical.class.php:388
__construct()
Constructor.
Definition: ical.class.php:47
retun_key_value($text)
Parse text &quot;XXXX:value text some with : &quot; and return array($key = &quot;XXXX&quot;, $value=&quot;value&quot;);.
Definition: ical.class.php:269
get_all_data()
Return array with all data.
Definition: ical.class.php:448
Class to read/parse ICal calendars.
Definition: ical.class.php:33
get_todo_list()
Return to do array (not sorted todo array)
Definition: ical.class.php:424
quotedPrintDecode($str)
Decode vcal format.
Definition: xcal.lib.php:609
read_file($file)
Read text file, icalender text file.
Definition: ical.class.php:58
get_freebusy_list()
Return eventlist array (not sort eventlist array)
Definition: ical.class.php:412
get_todo_count()
Returns the number of to do.
Definition: ical.class.php:91
parse($uri)
Translate Calendar.
Definition: ical.class.php:103
get_event_count()
Returns the number of calendar events.
Definition: ical.class.php:79
get_sort_event_list()
Return sorted eventlist as array or false if calendar is empty.
Definition: ical.class.php:367
get_event_list()
Return eventlist array (not sorted eventlist array)
Definition: ical.class.php:400