From: Jan Schneider Date: Thu, 10 Sep 2009 21:15:17 +0000 (+0200) Subject: Start working on a new iCalendar library. X-Git-Url: https://git.internetallee.de/?a=commitdiff_plain;h=3bb6a41bb44e24953a2d8b9b04ecf8fc4904f57e;p=horde.git Start working on a new iCalendar library. It's only 20% done, and I'm still not happy with the name, thus in the hatchery. --- diff --git a/framework/Icalendar/lib/Horde/Icalendar/Base.php b/framework/Icalendar/lib/Horde/Icalendar/Base.php new file mode 100644 index 000000000..b455f1977 --- /dev/null +++ b/framework/Icalendar/lib/Horde/Icalendar/Base.php @@ -0,0 +1,32 @@ +_params = $params; + } + + public function addComponent(Horde_Icalendar_Component_Base $component) + { + $this->_components[] = $component; + } + + /** + * @todo Use LSB (static::__CLASS__) once we require PHP 5.3 + */ + public function export() + { + $writer = Horde_Icalendar_Writer::factory( + str_replace('Horde_Icalendar_', '', get_class($this)), + str_replace('.', '', $this->_params['version'])); + } + +} diff --git a/framework/Icalendar/lib/Horde/Icalendar/Component/Base.php b/framework/Icalendar/lib/Horde/Icalendar/Component/Base.php new file mode 100644 index 000000000..d2ead5a7c --- /dev/null +++ b/framework/Icalendar/lib/Horde/Icalendar/Component/Base.php @@ -0,0 +1,199 @@ +_properties[$property])) { + throw new InvalidArgumentException($property . ' is not a valid property'); + } + $myProperty = &$this->_properties[$property]; + if (isset($myProperty['type'])) { + $func = 'is_' . $myProperty['type']; + if (!$func) { + throw new InvalidArgumentException($value . ' is not a ' . $myProperty['type']); + } + } elseif (isset($myProperty['class'])) { + if (!($value instanceof $myProperty['class'])) { + throw new InvalidArgumentException($value . ' is not of class ' . $myProperty['class']); + } + } + if ($property == 'stamp') { + $value->setTimezone('UTC'); + } + } + + /** + * Setter. + * + * @throws InvalidArgumentException + */ + public function __set($property, $value) + { + $this->_validate($property, $value); + if ($this->_properties[$property]['multiple']) { + $this->_properties[$property]['value'] = array($value); + $this->_properties[$property]['params'] = array(); + } else { + $this->_properties[$property]['value'] = $value; + $this->_properties[$property]['params'] = null; + } + } + + /** + * Sets the value of a property. + * + * @param string $property The name of the property. + * @param string $value The value of the property. + * @param array $params Array containing any addition parameters for + * this property. + * + * @throws InvalidArgumentException + */ + public function setProperty($property, $value, $params = array()) + { + $this->$name = $value; + $this->_properties[$property]['params'] = array($params); + } + + /** + * Adds the value of a property. + * + * @param string $property The name of the property. + * @param string $value The value of the property. + * @param array $params Array containing any addition parameters for + * this property. + * + * @throws InvalidArgumentException + * @throws Horde_Icalendar_Exception + */ + public function addProperty($property, $value, $params = array()) + { + $this->_validate($property, $value); + if (!$this->_properties[$property]['multiple'] && + !isset($this->_properties[$property]['value'])) { + throw new Horde_Icalendar_Exception($property . ' properties must not occur more than once.'); + } + if (isset($this->_properties[$property]['value'])) { + $this->_properties[$property]['value'][] = $value; + $this->_properties[$property]['params'][] = $params; + } else { + $this->setProperty($property, $value, $params); + } + } + + /** + * Getter. + * + * @throws InvalidArgumentException + */ + public function __get($property) + { + if (!isset($this->_properties[$property])) { + throw new InvalidArgumentException($property . ' is not a valid property'); + } + return isset ($this->_properties[$property]['value']) + ? $this->_properties[$property]['value'] + : null; + } + + /** + * Returns the value of an property. + * + * @param string $name The name of the property. + * @param boolean $params Return the parameters for this property instead + * of its value. + * + * @return mixed (object) PEAR_Error if the property does not exist. + * (string) The value of the property. + * (array) The parameters for the property or + * multiple values for an property. + */ + function getProperty($name, $params = false) + { + $result = array(); + foreach ($this->_properties as $property) { + if ($property['name'] == $name) { + if ($params) { + $result[] = $property['params']; + } else { + $result[] = $property['value']; + } + } + } + if (!count($result)) { + require_once 'PEAR.php'; + return PEAR::raiseError('Property "' . $name . '" Not Found'); + } if (count($result) == 1 && !$params) { + return $result[0]; + } else { + return $result; + } + } + + public function getProperties() + { + return $this->_properties; + } + + /** + * Validates the complete component for missing properties or invalid + * property combinations. + * + * @throws Horde_Icalendar_Exception + */ + public function validate() + { + foreach ($this->_properties as $name => $property) { + if (!empty($property['required']) && !isset($property['value'])) { + switch ($name) { + case 'uid': + $this->uid = (string)new Horde_Support_Guid; + break; + case 'stamp': + $this->stamp = new Horde_Date(time()); + break; + default: + $component = Horde_String::upper(str_replace('Horde_Icalendar_Component_', '', get_class($this))); + throw new Horde_Icalendar_Exception($component . ' components must have a ' . $name . ' property set'); + } + } + } + } + + public function current() + { + return current($this->_properties); + } + + public function key() + { + return key($this->_properties); + } + + public function next() + { + next($this->_properties); + } + + public function rewind() + { + reset($this->_properties); + } + + public function valid() + { + return current($this->_properties) !== false; + } + +} diff --git a/framework/Icalendar/lib/Horde/Icalendar/Component/Valarm.php b/framework/Icalendar/lib/Horde/Icalendar/Component/Valarm.php new file mode 100644 index 000000000..b1556ad07 --- /dev/null +++ b/framework/Icalendar/lib/Horde/Icalendar/Component/Valarm.php @@ -0,0 +1,19 @@ +_properties += array( + 'summary' => array('required' => false, + 'multiple' => false, + 'type' => 'string'), + 'description' => array('required' => false, + 'multiple' => false, + 'type' => 'string')); + } + +} diff --git a/framework/Icalendar/lib/Horde/Icalendar/Component/Vevent.php b/framework/Icalendar/lib/Horde/Icalendar/Component/Vevent.php new file mode 100644 index 000000000..d82a00de6 --- /dev/null +++ b/framework/Icalendar/lib/Horde/Icalendar/Component/Vevent.php @@ -0,0 +1,40 @@ +_properties += array( + 'uid' => array('required' => true, + 'multiple' => false, + 'type' => 'string'), + 'start' => array('required' => false, + 'multiple' => false, + 'class' => 'Horde_Date'), + 'startDate' => array('required' => false, + 'multiple' => false, + 'class' => 'Horde_Date'), + 'stamp' => array('required' => true, + 'multiple' => false, + 'class' => 'Horde_Date'), + 'summary' => array('required' => false, + 'multiple' => false, + 'type' => 'string'), + 'description' => array('required' => false, + 'multiple' => false, + 'type' => 'string')); + } + + public function validate() + { + parent::validate(); + if (!isset($this->_properties['start']['value']) && + !isset($this->_properties['startDate']['value'])) { + throw new Horde_Icalendar_Exception('VEVENT components must have a start property set'); + } + } + +} diff --git a/framework/Icalendar/lib/Horde/Icalendar/Component/Vfreebusy.php b/framework/Icalendar/lib/Horde/Icalendar/Component/Vfreebusy.php new file mode 100644 index 000000000..929555415 --- /dev/null +++ b/framework/Icalendar/lib/Horde/Icalendar/Component/Vfreebusy.php @@ -0,0 +1,36 @@ +_properties += array( + 'uid' => array('required' => true, + 'multiple' => false, + 'type' => 'string'), + 'start' => array('required' => true, + 'multiple' => false, + 'class' => 'Horde_Date'), + 'stamp' => array('required' => true, + 'multiple' => false, + 'class' => 'Horde_Date'), + ); + } + + /** + * Validates a property-value-pair. + * + * @throws InvalidArgumentException + */ + protected function _validate($property, &$value) + { + parent::_validate($property, $value); + if ($property == 'start') { + $value->setTimezone('UTC'); + } + } + +} diff --git a/framework/Icalendar/lib/Horde/Icalendar/Component/Vjournal.php b/framework/Icalendar/lib/Horde/Icalendar/Component/Vjournal.php new file mode 100644 index 000000000..d4a81552d --- /dev/null +++ b/framework/Icalendar/lib/Horde/Icalendar/Component/Vjournal.php @@ -0,0 +1,25 @@ +_properties += array( + 'uid' => array('required' => true, + 'multiple' => false, + 'type' => 'string'), + 'stamp' => array('required' => true, + 'multiple' => false, + 'class' => 'Horde_Date'), + 'summary' => array('required' => false, + 'multiple' => false, + 'type' => 'string'), + 'description' => array('required' => false, + 'multiple' => false, + 'type' => 'string')); + } + +} diff --git a/framework/Icalendar/lib/Horde/Icalendar/Component/Vtimezone.php b/framework/Icalendar/lib/Horde/Icalendar/Component/Vtimezone.php new file mode 100644 index 000000000..197f2654d --- /dev/null +++ b/framework/Icalendar/lib/Horde/Icalendar/Component/Vtimezone.php @@ -0,0 +1,24 @@ +_properties += array( + /* + Within the "VTIMEZONE" calendar component, this property defines the + effective start date and time for a time zone specification. This + property is REQUIRED within each STANDARD and DAYLIGHT part included + in "VTIMEZONE" calendar components and MUST be specified as a local + DATE-TIME without the "TZID" property parameter. + */ + 'start' => array('required' => true, + 'multiple' => false, + 'class' => 'Horde_Date'), + ); + } + +} diff --git a/framework/Icalendar/lib/Horde/Icalendar/Component/Vtodo.php b/framework/Icalendar/lib/Horde/Icalendar/Component/Vtodo.php new file mode 100644 index 000000000..0235baf61 --- /dev/null +++ b/framework/Icalendar/lib/Horde/Icalendar/Component/Vtodo.php @@ -0,0 +1,31 @@ +_properties += array( + 'uid' => array('required' => true, + 'multiple' => false, + 'type' => 'string'), + 'start' => array('required' => false, + 'multiple' => false, + 'class' => 'Horde_Date'), + 'startDate' => array('required' => false, + 'multiple' => false, + 'class' => 'Horde_Date'), + 'stamp' => array('required' => true, + 'multiple' => false, + 'class' => 'Horde_Date'), + 'summary' => array('required' => false, + 'multiple' => false, + 'type' => 'string'), + 'description' => array('required' => false, + 'multiple' => false, + 'type' => 'string')); + } + +} diff --git a/framework/Icalendar/lib/Horde/Icalendar/Exception.php b/framework/Icalendar/lib/Horde/Icalendar/Exception.php new file mode 100644 index 000000000..9c7fc1c50 --- /dev/null +++ b/framework/Icalendar/lib/Horde/Icalendar/Exception.php @@ -0,0 +1,5 @@ + '2.0'), $params); + parent::__construct($params); + } + +} diff --git a/framework/Icalendar/lib/Horde/Icalendar/Writer.php b/framework/Icalendar/lib/Horde/Icalendar/Writer.php new file mode 100644 index 000000000..d59d3ed71 --- /dev/null +++ b/framework/Icalendar/lib/Horde/Icalendar/Writer.php @@ -0,0 +1,27 @@ +isFile() && preg_match('/Test.php$/', $file->getFilename())) { + $pathname = $file->getPathname(); + require $pathname; + + $class = str_replace(DIRECTORY_SEPARATOR, '_', + preg_replace("/^$baseregexp(.*)\.php/", '\\1', $pathname)); + $suite->addTestSuite('Horde_Icalendar_' . $class); + } + } + + return $suite; + } + +} + +if (PHPUnit_MAIN_METHOD == 'Horde_Icalendar_AllTests::main') { + Horde_Icalendar_AllTests::main(); +} diff --git a/framework/Icalendar/test/Horde/Icalendar/WriterTest.php b/framework/Icalendar/test/Horde/Icalendar/WriterTest.php new file mode 100644 index 000000000..c91782c9b --- /dev/null +++ b/framework/Icalendar/test/Horde/Icalendar/WriterTest.php @@ -0,0 +1,66 @@ + '2.0')); + $event1 = new Horde_Icalendar_Component_Vevent(); + $event2 = new Horde_Icalendar_Component_Vevent(); + + $event1->uid = '20041120-8550-innerjoin-org'; + $event1->startDate = new Horde_Date(array('year' => 2005, 'month' => 5, 'mday' => 3)); + $event1->stamp = new Horde_Date(array('year' => 2004, 'month' => 11, 'mday' => 20)); + $event1->summary = 'Escaped Comma in Description Field'; + $event1->description = 'There is a comma (escaped with a baskslash) in this sentence and some important words after it, see anything here?'; + + $event2->uid = '20041120-8549-innerjoin-org'; + $event2->startDate = new Horde_Date(array('year' => 2005, 'month' => 5, 'mday' => 4)); + $event2->stamp = new Horde_Date(array('year' => 2004, 'month' => 11, 'mday' => 20)); + $event2->summary = 'Dash (rather than Comma) in the Description Field'; + $event2->description = 'There are important words after this dash - see anything here or have the words gone?'; + + $ical->addComponent($event1); + $ical->addComponent($event2); + + $this->assertEquals('BEGIN:VCALENDAR +VERSION:2.0 +PRODID:-//The Horde Project//Horde_iCalendar Library//EN +METHOD:PUBLISH +BEGIN:VEVENT +UID:20041120-8550-innerjoin-org +DTSTART;VALUE=DATE:20050503 +DTSTAMP:20041120T000000Z +SUMMARY:Escaped Comma in Description Field +DESCRIPTION:There is a comma (escaped with a baskslash) in this sentence + and some important words after it\, see anything here? +END:VEVENT +BEGIN:VEVENT +UID:20041120-8549-innerjoin-org +DTSTART;VALUE=DATE:20050504 +DTSTAMP:20041120T000000Z +SUMMARY:Dash (rather than Comma) in the Description Field +DESCRIPTION:There are important words after this dash - see anything here + or have the words gone? +END:VEVENT +END:VCALENDAR', + $ical->export()); + } + +} \ No newline at end of file