CWIS Developer Documentation
iCalendar.php
Go to the documentation of this file.
1 <?PHP
2 #
3 # FILE: iCalendar.php
4 #
5 # Part of the Collection Workflow Integration System (CWIS)
6 # Copyright 2013-2015 Edward Almasy and Internet Scout Research Group
7 # http://scout.wisc.edu/cwis/
8 #
9 
13 class iCalendar
14 {
15 
25  public function __construct($ID, $StartDate, $EndDate, $AllDay, $TimeZoneID=NULL)
26  {
27  # generate the UID and add it to the document
28  $this->AddProperty("VEVENT", "UID", $this->GenerateUID($ID, $StartDate));
29 
30  # need to use the time zone parameter if a time zone ID is given
31  $DateParameters = is_null($TimeZoneID) ? array() : array("TZID" => $TimeZoneID);
32 
33  if ($AllDay)
34  {
35  # need to offset the end date by one day so that the range spans the
36  # entire 24 hours of the last day
37  $EndDate = date("Y-m-d", strtotime($EndDate)+86400);
38 
39  $this->AddDateProperty("VEVENT", "DTSTART", $StartDate, $DateParameters);
40  $this->AddDateProperty("VEVENT", "DTEND", $EndDate, $DateParameters);
41  }
42 
43  else
44  {
45  $this->AddDateTimeProperty("VEVENT", "DTSTART", $StartDate, $DateParameters);
46  $this->AddDateTimeProperty("VEVENT", "DTEND", $EndDate, $DateParameters);
47  }
48  }
49 
55  public function AddCreated($Value)
56  {
57  $this->AddTextProperty(
58  "VEVENT", "CREATED", $this->GenerateUTCDateTimeString($Value));
59  }
60 
66  public function AddSummary($Value)
67  {
68  # add the property
69  $this->AddTextProperty("VEVENT", "SUMMARY", $Value);
70 
71  # save the summary for use in generating the file name
72  $this->Summary = $Value;
73  }
74 
80  public function AddDescription($Value)
81  {
82  $this->AddTextProperty("VEVENT", "DESCRIPTION", $Value);
83  }
84 
90  public function AddCategories(array $Categories)
91  {
92  # don't add the property if there are no categories to add
93  if (!count($Categories))
94  {
95  return;
96  }
97 
98  $this->AddProperty(
99  "VEVENT",
100  "CATEGORIES",
101  implode(",", array_map(array($this, "EscapeTextValue"), $Categories)));
102  }
103 
109  public function AddURL($Value)
110  {
111  # don't add a blank URL
112  if (!strlen($Value))
113  {
114  return;
115  }
116 
117  $this->AddProperty("VEVENT", "URL", $Value);
118  }
119 
126  public function AddGeographicPosition($Latitude, $Longitude)
127  {
128  # construct the value for the property
129  $Value = floatval($Latitude) . ";" . floatval($Longitude);
130 
131  # add the property to the list
132  $this->AddProperty("VEVENT", "GEO", $Value);
133  }
134 
140  public function AddLocation($Value)
141  {
142  $this->AddTextProperty("VEVENT", "LOCATION", $Value);
143  }
144 
149  public function GenerateDocument()
150  {
151  # generate a timestamp and add it
152  $Timestamp = $this->GenerateUTCDateTimeString(date("Y-m-d H:i:s"));
153  $this->AddProperty("VEVENT", "DTSTAMP", $Timestamp);
154 
155  # start the iCalendar definition
156  $Document = "BEGIN:VCALENDAR\r\n";
157 
158  # add basic headers
159  $Document .= "CALSCALE:GREGORIAN\r\n";
160  $Document .= "PRODID:-//Internet Scout//CWIS//EN\r\n";
161  $Document .= "VERSION:2.0\r\n";
162 
163  # add each component
164  foreach ($this->Properties as $Component => $Properties)
165  {
166  # don't add empty components
167  if (!count($Properties))
168  {
169  continue;
170  }
171 
172  # begin the component definition
173  $Document .= "BEGIN:" . $Component . "\r\n";
174 
175  # add each property line
176  foreach ($Properties as $Property => $PropertyLine)
177  {
178  $Document .= $PropertyLine;
179  }
180 
181  # end the component definition
182  $Document .= "END:" . $Component . "\r\n";
183  }
184 
185  # end the iCalendar definition
186  $Document .= "END:VCALENDAR\r\n";
187 
188  # return the generated document
189  return $Document;
190  }
191 
199  public function GenerateFileName()
200  {
201  return self::GenerateFileNameFromSummary($this->Summary);
202  }
203 
212  public static function GenerateFileNameFromSummary($Summary=NULL)
213  {
214  # just use the date/time if the summary isn't given
215  if (!$Summary)
216  {
217  return date("Ymd-His") . ".ics";
218  }
219 
220  # remove any HTML from the summary
221  $Name = strip_tags($Summary);
222 
223  # replace problematic characters for most filesystems
224  $Name = str_replace(
225  array("/", "?", "<", ">", "\\", ":", "*", "|", '"', "^"),
226  "-",
227  $Name);
228 
229  # remove whitespace at the beginning and end
230  $Name = trim($Name);
231 
232  # make sure the name isn't too long because it can cause problems for
233  # some browsers and file systems
234  $Name = substr($Name, 0, 75);
235 
236  # return the name plus extension
237  return $Name . ".ics";
238  }
239 
245  public static function TransformHTMLToPlainText($HTML)
246  {
247  # remove HTML tags
248  $HTML = strip_tags($HTML);
249 
250  # handle a few replacements separately because they aren't handled by
251  # html_entity_decode() or are replaced by a character that isn't ideal.
252  # string to replace => replacement
253  $Replace = array(
254  "&nbsp;" => " ",
255  "&ndash;" => "-",
256  "&mdash;" => "--",
257  "&ldquo;" => '"',
258  "&rdquo;" => '"',
259  "&lsquo;" => "'",
260  "&rsquo;" => "'");
261 
262  # do the first pass of replacements
263  $HTML = str_replace(array_keys($Replace), array_values($Replace), $HTML);
264 
265  # do the final pass of replacements and return
266  return html_entity_decode($HTML);
267  }
268 
281  protected function AddProperty($Component, $Property, $Value,
282  array $Parameters=array())
283  {
284  # construct the property line
285  $Line = $this->GeneratePropertyString($Property, $Parameters) . $Value;
286 
287  # fold the line if necessary and add the line ending sequence
288  $Line = $this->FoldString($Line) . "\r\n";
289 
290  # add the property line to the list of properties
291  $this->Properties[$Component][$Property] = $Line;
292  }
293 
306  protected function AddTextProperty($Component, $Property, $Value,
307  array $Parameters=array())
308  {
309  # don't add empty properties
310  if (!strlen($Value))
311  {
312  return;
313  }
314 
315  $this->AddProperty(
316  $Component,
317  $Property,
318  $this->EscapeTextValue($Value),
319  $Parameters);
320  }
321 
334  protected function AddDateProperty($Component, $Property, $Value,
335  array $Parameters=array())
336  {
337  $this->AddProperty(
338  $Component,
339  $Property,
340  $this->GenerateDateString($Value),
341  array("VALUE" => "DATE") + $Parameters);
342  }
343 
356  protected function AddDateTimeProperty($Component, $Property, $Value,
357  array $Parameters=array())
358  {
359  $this->AddProperty(
360  $Component,
361  $Property,
362  $this->GenerateDateTimeString($Value),
363  $Parameters);
364  }
365 
371  protected function EscapeTextValue($Value)
372  {
373  # escape most characters
374  $Value = preg_replace('/([\\;,])/', "\\\\\\1", $Value);
375 
376  # escape newlines
377  $Value = preg_replace('/\n/', "\\n", $Value);
378 
379  return $Value;
380  }
381 
388  protected function GenerateUID($ID, $StartDate)
389  {
390  # concatenate the date string, ID, and host name as in the spec
391  $UID = $this->GenerateUTCDateTimeString($StartDate);
392  $UID .= "-" . $ID;
393  $UID .= "@" . gethostname();
394 
395  return $UID;
396  }
397 
403  protected function GenerateDateString($Date)
404  {
405  return date("Ymd", strtotime($Date));
406  }
407 
413  protected function GenerateDateTimeString($DateTime)
414  {
415  return date("Ymd\THis", strtotime($DateTime));
416  }
417 
423  protected function GenerateUTCDateTimeString($DateTime)
424  {
425  return gmdate("Ymd\THis\Z", strtotime($DateTime));
426  }
427 
435  protected function GeneratePropertyString($Property, array $Parameters=array())
436  {
437  # start the property string off with the property name
438  $String = $Property;
439 
440  # add each property parameter, if any
441  foreach ($Parameters as $Parameter => $Value)
442  {
443  $String .= ";" . $Parameter . "=" . $Value;
444  }
445 
446  # add the colon separator and return
447  return $String . ":";
448  }
449 
456  protected function FoldString($String, $End="\r\n ")
457  {
458  # split the line into chunks
459  $FoldedString = chunk_split($String, 75, $End);
460 
461  # chunk_split() unnecessarily adds the line ending sequence to the end
462  # of the string, so remove it
463  $FoldedString = substr($FoldedString, 0, -strlen($End));
464 
465  return $FoldedString;
466  }
467 
472  protected $Properties = array(
473  "VEVENT" => array(),
474  "VTODO" => array(),
475  "VJOURNAL" => array(),
476  "VFREEBUSY" => array(),
477  "VTIMEZONE" => array(),
478  "VALARM" => array());
479 
484  protected $Summary;
485 }
GenerateUID($ID, $StartDate)
Generate a full UID from an event ID and start date.
Definition: iCalendar.php:388
FoldString($String, $End="\r\n ")
Fold a string so that lines are never longer than 75 characters.
Definition: iCalendar.php:456
$Summary
The summary property for the iCalendar document.
Definition: iCalendar.php:484
AddCategories(array $Categories)
Add the categories property to the iCalendar document.
Definition: iCalendar.php:90
AddDescription($Value)
Add the description property to the iCalendar document.
Definition: iCalendar.php:80
GenerateFileName()
Generate a file name for the iCalendar document.
Definition: iCalendar.php:199
EscapeTextValue($Value)
Escape a text value for inserting into a property line.
Definition: iCalendar.php:371
AddTextProperty($Component, $Property, $Value, array $Parameters=array())
Add a text property to the list.
Definition: iCalendar.php:306
Class to generate a simple iCalendar document.
Definition: iCalendar.php:13
GenerateDateTimeString($DateTime)
Generate a date/time string from a date parsable by strtotime().
Definition: iCalendar.php:413
AddCreated($Value)
Add the created property to the iCalendar document.
Definition: iCalendar.php:55
static GenerateFileNameFromSummary($Summary=NULL)
Create a file name for an iCalendar document using a given summary.
Definition: iCalendar.php:212
$Properties
The list of components and properties.
Definition: iCalendar.php:472
AddSummary($Value)
Add the summary property to the iCalendar document.
Definition: iCalendar.php:66
__construct($ID, $StartDate, $EndDate, $AllDay, $TimeZoneID=NULL)
Construct a basic iCalendar document.
Definition: iCalendar.php:25
GenerateDocument()
Generate the iCalendar document based on the current list of properties.
Definition: iCalendar.php:149
static TransformHTMLToPlainText($HTML)
Helper method to transform an HTML string to plain text.
Definition: iCalendar.php:245
AddURL($Value)
Add the URL property to the iCalendar document.
Definition: iCalendar.php:109
AddDateProperty($Component, $Property, $Value, array $Parameters=array())
Add a date property to the list.
Definition: iCalendar.php:334
AddLocation($Value)
Add the location property to the iCalendar document.
Definition: iCalendar.php:140
GeneratePropertyString($Property, array $Parameters=array())
Generate a property string (property + parameters + ":").
Definition: iCalendar.php:435
AddProperty($Component, $Property, $Value, array $Parameters=array())
Add a generic property, i.e., one whose value is already in the proper form.
Definition: iCalendar.php:281
AddGeographicPosition($Latitude, $Longitude)
Add the geographic position property to the iCalendar document.
Definition: iCalendar.php:126
GenerateUTCDateTimeString($DateTime)
Generate a UTC date/time string from a date parsable by strtotime().
Definition: iCalendar.php:423
AddDateTimeProperty($Component, $Property, $Value, array $Parameters=array())
Add a date/time property to the list.
Definition: iCalendar.php:356
GenerateDateString($Date)
Generate a date string from a date parsable by strtotime().
Definition: iCalendar.php:403