<?php
/**
 * ICS.php
 * =======
 * Use this class to create an .ics file.
 *
 * Usage
 * -----
 * Basic usage - generate ics file contents (see below for available properties):
 *   $ics = new Calendarista_ICSWriterHelper($props);
 *   $ics_file_contents = $ics->to_string();
 *
 * Setting properties after instantiation
 *   $ics = new Calendarista_ICSWriterHelper();
 *   $ics->set('summary', 'My awesome event');
 *
 * You can also set multiple properties at the same time by using an array:
 *   $ics->set(array(
 *     'dtstart' => 'now + 30 minutes',
 *     'dtend' => 'now + 1 hour'
 *   ));
 *
 * Available properties
 * --------------------
 * description
 *   String description of the event.
 * dtend
 *   A date/time stamp designating the end of the event. You can use either a
 *   DateTime object or a PHP datetime format string (e.g. "now + 1 hour").
 * dtstart
 *   A date/time stamp designating the start of the event. You can use either a
 *   DateTime object or a PHP datetime format string (e.g. "now + 1 hour").
 * location
 *   String address or description of the location of the event.
 * summary
 *   String short summary of the event - usually used as the title.
 * url
 *   A url to attach to the the event. Make sure to add the protocol (http://
 *   or https://).
 */
class Calendarista_ICSWriterHelper {
  const DT_FORMAT = 'Ymd\THis';
  const D_FORMAT = 'Ymd';
  protected $properties = array();
  protected $fullDay;
  public function __construct($props, $fullDay = false) {
	$this->fullDay = $fullDay;
    $this->set($props);
  }
  public function set($key, $val = false) {
	if (is_array($key)) {
		foreach ($key as $k => $v) {
			$this->set($k, $v);
		}
	} else {
		if(trim($val) != false){
			$this->properties[$key] = $this->sanitize_val($val, $key);
		}
	}
  }
  public function to_string() {
    $rows = $this->build_props();
    return implode("\r\n", $rows);
  }
  private function build_props() {
    // Build ICS properties - add header
    $ics_props = array(
      'BEGIN:VEVENT'
    );
    // Build ICS properties - add header
    $props = array();
    foreach($this->properties as $k => $v) {
      $props[strtoupper($k . ($k === 'url' ? ';VALUE=URI' : ''))] = $v;
    }
    // Set some default values
    $props['DTSTAMP'] = get_gmt_from_date(date('Y-m-d H:i:s'), 'Ymd\THis');
    // Append properties
    foreach ($props as $k => $v) {
      $ics_props[] = "$k:$v";
    }
    // Build ICS properties - add footer
    $ics_props[] = 'END:VEVENT';
    return $ics_props;
  }
  private function sanitize_val($val, $key = false) {
    switch($key) {
      case 'dtend;value=date':
	  case 'dtend;value=date-time':
	  case 'dtstart;value=date':
	  case 'dtstart;value=date-time':
        $val = $this->format_timestamp($val);
        break;
      default:
        $val = $this->escape_string($val);
    }
    return $val;
  }
  private function format_timestamp($timestamp) {
    $dt = new DateTime($timestamp);
    return $this->fullDay ? $dt->format(self::D_FORMAT) : $dt->format(self::DT_FORMAT);
  }
  private function escape_string($str) {
    return preg_replace('/([\,;])/','\\\$1', $str);
  }
  public static function to_calendar($rows) {
	$begin = implode("\r\n", array(
      'BEGIN:VCALENDAR',
      'VERSION:2.0',
      sprintf('PRODID;X-RICAL-TZSOURCE=TZINFO:-//Calendarista Premium Edition v%s//EN', CALENDARISTA_VERSION),
      'CALSCALE:GREGORIAN',
	  sprintf('X-WR-TIMEZONE:%s', Calendarista_Helper::timezone_string())
	));
	$content = implode("\r\n", $rows);
	$end = implode("\r\n", array('END:VCALENDAR'));
    return implode("\r\n", array($begin, $content, $end));
  }
}
?>