/** * Render any component */ public function render(qCal_Component $component) { $return = "BEGIN:" . $component->getName() . self::LINE_ENDING; foreach ($component->getProperties() as $property) { if (is_array($property)) { foreach ($property as $prop) { $return .= $this->renderProperty($prop); } } else { $return .= $this->renderProperty($property); } } foreach ($component->getChildren() as $children) { if (is_array($children)) { foreach ($children as $child) { $return .= $this->render($child); } } else { $return .= $this->render($children); } } return $return . "END:" . $component->getName() . self::LINE_ENDING; }
/** * Attach a component to this component (alarm inside event for example) * @param qCal_Component $component The component to be attached to this component * @access public * @return $this * @todo There may be an issue with the way this is done. When parsing a file, if a component * or property with a tzid comes before its corresponding vtimezone component, an exception * will be thrown. I'm don't think the RFC specifies that requirement (that timezone components * must come before their corresponding tzids) * @todo Sub-components such as Vevent need to be able to access the main vcalendar object * for several reasons. * - If a vtodo has a tzid, it needs to be able to determine that the corresponding * vtimezone component is available. * - If components need to relate to eachother, they can only find eachother through * the main vcalendar object. * - Freebusy time can only be determined by polling all components in the main vcalendar * object. * - More to come probably */ public function attach(qCal_Component $component) { if (!$component->canAttachTo($this)) { throw new qCal_Exception_InvalidComponent($component->getName() . ' cannot be attached to ' . $this->getName()); } $component->setParent($this); // make sure if a timezone is requested that it is available... $timezones = $this->getTimezones(); // we only need to check if tzid exists if we are attaching something other than a timezone... if (!$component instanceof qCal_Component_Vtimezone) { foreach ($component->getProperties() as $pname => $properties) { $pname = strtoupper($pname); // probably redundant... foreach ($properties as $property) { switch ($pname) { case "TZID": $tzid = strtoupper($property->getValue()); if (!array_key_exists($tzid, $timezones)) { throw new qCal_Exception_MissingComponent('TZID "' . $tzid . '" not defined'); } break; } $params = $property->getParams(); foreach ($params as $param => $val) { $param = strtoupper($param); // probably redundant... switch ($param) { case "TZID": $tzid = strtoupper($val); if (!array_key_exists($tzid, $timezones)) { throw new qCal_Exception_MissingComponent('TZID "' . $tzid . '" not defined'); } break; } } } } } $this->children[$component->getName()][] = $component; return $this; }
/** * Check if this is a property of a certain component. Some properties * can only be set on certain Components. This method looks inside this * property's $allowedComponents and returns true if $component is allowed * * @return boolean True if this is a property of $component, false otherwise * @param qCal_Component The component we're evaluating **/ public function of(qCal_Component $component) { return in_array($component->getName(), $this->allowedComponents); }
/** * The factory method is used in the parser. It may eventually be used in the facade methods as well * The factory should accept the name of the component as the first param and the properties as the second * It should also be completely case-insensitive */ public function testFactoryMethod() { $component = qCal_Component::factory('VALARM', array('action' => 'audio', 'TriggER' => 'P1w3Dt2H3M45S')); $this->assertIsA($component, 'qCal_Component_Valarm'); }
/** * Parses any of several iCalendar formats (iCalendar, xCalendar, hCalendar) into qCal's native qCal components * Override doParse in a child class if necessary * @param array $tokens An array of arrays containing components, properties and parameters * @return qCal_Component_Vcalendar * @access protected */ protected function doParse($tokens) { $properties = array(); foreach ($tokens['properties'] as $propertytoken) { $params = array(); foreach ($propertytoken['params'] as $paramtoken) { $params[$paramtoken['param']] = $paramtoken['value']; } try { $properties[] = qCal_Property::factory($propertytoken['property'], $propertytoken['value'], $params); } catch (qCal_Exception $e) { // @todo There should be a better way of determining what went wrong during parsing/lexing than this // do nothing... // pr($e); } } $component = qCal_Component::factory($tokens['component'], $properties); foreach ($tokens['children'] as $child) { $childcmpnt = $this->doParse($child); $component->attach($childcmpnt); } return $component; }
/** * converts VEVENT to an Calendar_Model_Event * * @param qCal_Component $vevent * @return Calendar_Model_Event */ protected function _getEvent(qCal_Component $vevent) { $eventData = array(); // timezone if ($vevent->hasComponent('VTIMEZONE')) { $tz = array_value(0, $vevent->getComponent('VTIMEZONE')); $eventData['originator_tz'] = array_value(0, $tz->getProperty('TZID'))->getValue(); } else { $eventData['originator_tz'] = $this->_defaultTimezoneId; } foreach ($this->_eventPropertyMap as $tineName => $icalName) { if ($vevent->hasProperty($icalName)) { $icalValue = array_value(0, $vevent->getProperty($icalName)); switch ($icalValue->getType()) { case 'DATE': $value = new Tinebase_DateTime($icalValue->getValue() . 'T000000', $eventData['originator_tz']); // events with dtstart given as date are allday events! if ($tineName == 'dtstart') { $eventData['is_all_day_event'] = true; } if ($tineName == 'dtend') { $value = $value->addSecond(-1); } break; case 'DATE-TIME': $value = new Tinebase_DateTime($icalValue->getValue(), $eventData['originator_tz']); case 'TEXT': $value = str_replace(array('\\,', '\\n'), array(',', "\n"), $icalValue->getValue()); break; default: $value = $icalValue->getValue(); break; } $eventData[$tineName] = $value; } } // truncate string if (array_key_exists('uid', $eventData) && strlen($eventData['uid']) > 40) { $eventData['uid'] = substr($eventData['uid'], 0, 40); } $event = new Calendar_Model_Event($eventData); $event->setTimezone('UTC'); return $event; }