Merge branch 'master' of ssh://git.kolabsys.com/git/roundcube
This commit is contained in:
commit
da4fea3a3d
5 changed files with 435 additions and 356 deletions
|
@ -314,8 +314,8 @@ class kolab_format_contact extends kolab_format
|
||||||
// read object properties into local data object
|
// read object properties into local data object
|
||||||
$object = array(
|
$object = array(
|
||||||
'uid' => $this->obj->uid(),
|
'uid' => $this->obj->uid(),
|
||||||
# 'changed' => $this->obj->lastModified(),
|
|
||||||
'name' => $this->obj->name(),
|
'name' => $this->obj->name(),
|
||||||
|
'changed' => self::php_datetime($this->obj->lastModified()),
|
||||||
);
|
);
|
||||||
|
|
||||||
$nc = $this->obj->nameComponents();
|
$nc = $this->obj->nameComponents();
|
||||||
|
|
|
@ -117,7 +117,7 @@ class kolab_format_distributionlist extends kolab_format
|
||||||
// read object properties
|
// read object properties
|
||||||
$object = array(
|
$object = array(
|
||||||
'uid' => $this->obj->uid(),
|
'uid' => $this->obj->uid(),
|
||||||
'changed' => $this->obj->lastModified(),
|
'changed' => self::php_datetime($this->obj->lastModified()),
|
||||||
'name' => $this->obj->name(),
|
'name' => $this->obj->name(),
|
||||||
'member' => array(),
|
'member' => array(),
|
||||||
);
|
);
|
||||||
|
|
|
@ -22,62 +22,13 @@
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
class kolab_format_event extends kolab_format
|
class kolab_format_event extends kolab_format_xcal
|
||||||
{
|
{
|
||||||
public $CTYPE = 'application/calendar+xml';
|
|
||||||
|
|
||||||
protected $read_func = 'kolabformat::readEvent';
|
protected $read_func = 'kolabformat::readEvent';
|
||||||
protected $write_func = 'kolabformat::writeEvent';
|
protected $write_func = 'kolabformat::writeEvent';
|
||||||
|
|
||||||
public static $fulltext_cols = array('title', 'description', 'location', 'attendees:name', 'attendees:email');
|
public static $fulltext_cols = array('title', 'description', 'location', 'attendees:name', 'attendees:email');
|
||||||
|
|
||||||
private $sensitivity_map = array(
|
|
||||||
'public' => kolabformat::ClassPublic,
|
|
||||||
'private' => kolabformat::ClassPrivate,
|
|
||||||
'confidential' => kolabformat::ClassConfidential,
|
|
||||||
);
|
|
||||||
|
|
||||||
private $role_map = array(
|
|
||||||
'REQ-PARTICIPANT' => kolabformat::Required,
|
|
||||||
'OPT-PARTICIPANT' => kolabformat::Optional,
|
|
||||||
'NON-PARTICIPANT' => kolabformat::NonParticipant,
|
|
||||||
'CHAIR' => kolabformat::Chair,
|
|
||||||
);
|
|
||||||
|
|
||||||
private $rrule_type_map = array(
|
|
||||||
'MINUTELY' => RecurrenceRule::Minutely,
|
|
||||||
'HOURLY' => RecurrenceRule::Hourly,
|
|
||||||
'DAILY' => RecurrenceRule::Daily,
|
|
||||||
'WEEKLY' => RecurrenceRule::Weekly,
|
|
||||||
'MONTHLY' => RecurrenceRule::Monthly,
|
|
||||||
'YEARLY' => RecurrenceRule::Yearly,
|
|
||||||
);
|
|
||||||
|
|
||||||
private $weekday_map = array(
|
|
||||||
'MO' => kolabformat::Monday,
|
|
||||||
'TU' => kolabformat::Tuesday,
|
|
||||||
'WE' => kolabformat::Wednesday,
|
|
||||||
'TH' => kolabformat::Thursday,
|
|
||||||
'FR' => kolabformat::Friday,
|
|
||||||
'SA' => kolabformat::Saturday,
|
|
||||||
'SU' => kolabformat::Sunday,
|
|
||||||
);
|
|
||||||
|
|
||||||
private $alarm_type_map = array(
|
|
||||||
'DISPLAY' => Alarm::DisplayAlarm,
|
|
||||||
'EMAIL' => Alarm::EMailAlarm,
|
|
||||||
'AUDIO' => Alarm::AudioAlarm,
|
|
||||||
);
|
|
||||||
|
|
||||||
private $status_map = array(
|
|
||||||
'UNKNOWN' => kolabformat::PartNeedsAction,
|
|
||||||
'NEEDS-ACTION' => kolabformat::PartNeedsAction,
|
|
||||||
'TENTATIVE' => kolabformat::PartTentative,
|
|
||||||
'ACCEPTED' => kolabformat::PartAccepted,
|
|
||||||
'DECLINED' => kolabformat::PartDeclined,
|
|
||||||
'DELEGATED' => kolabformat::PartDelegated,
|
|
||||||
);
|
|
||||||
|
|
||||||
private $kolab2_rolemap = array(
|
private $kolab2_rolemap = array(
|
||||||
'required' => 'REQ-PARTICIPANT',
|
'required' => 'REQ-PARTICIPANT',
|
||||||
'optional' => 'OPT-PARTICIPANT',
|
'optional' => 'OPT-PARTICIPANT',
|
||||||
|
@ -103,36 +54,20 @@ class kolab_format_event extends kolab_format
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set contact properties to the kolabformat object
|
* Set event properties to the kolabformat object
|
||||||
*
|
*
|
||||||
* @param array Contact data as hash array
|
* @param array Event data as hash array
|
||||||
*/
|
*/
|
||||||
public function set(&$object)
|
public function set(&$object)
|
||||||
{
|
{
|
||||||
$this->init();
|
$this->init();
|
||||||
|
|
||||||
// set some automatic values if missing
|
// set common xcal properties
|
||||||
if (!$this->obj->created()) {
|
parent::set($object);
|
||||||
if (!empty($object['created']))
|
|
||||||
$object['created'] = new DateTime('now', self::$timezone);
|
|
||||||
$this->obj->setCreated(self::get_datetime($object['created']));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!empty($object['uid']))
|
|
||||||
$this->obj->setUid($object['uid']);
|
|
||||||
|
|
||||||
// increment sequence
|
|
||||||
$this->obj->setSequence($this->obj->sequence()+1);
|
|
||||||
|
|
||||||
// do the hard work of setting object values
|
// do the hard work of setting object values
|
||||||
$this->obj->setStart(self::get_datetime($object['start'], null, $object['allday']));
|
$this->obj->setStart(self::get_datetime($object['start'], null, $object['allday']));
|
||||||
$this->obj->setEnd(self::get_datetime($object['end'], null, $object['allday']));
|
$this->obj->setEnd(self::get_datetime($object['end'], null, $object['allday']));
|
||||||
$this->obj->setSummary($object['title']);
|
|
||||||
$this->obj->setLocation($object['location']);
|
|
||||||
$this->obj->setDescription($object['description']);
|
|
||||||
$this->obj->setPriority($object['priority']);
|
|
||||||
$this->obj->setClassification($this->sensitivity_map[$object['sensitivity']]);
|
|
||||||
$this->obj->setCategories(self::array2vector($object['categories']));
|
|
||||||
$this->obj->setTransparency($object['free_busy'] == 'free');
|
$this->obj->setTransparency($object['free_busy'] == 'free');
|
||||||
|
|
||||||
$status = kolabformat::StatusUndefined;
|
$status = kolabformat::StatusUndefined;
|
||||||
|
@ -142,130 +77,6 @@ class kolab_format_event extends kolab_format
|
||||||
$status = kolabformat::StatusCancelled;
|
$status = kolabformat::StatusCancelled;
|
||||||
$this->obj->setStatus($status);
|
$this->obj->setStatus($status);
|
||||||
|
|
||||||
// process event attendees
|
|
||||||
$organizer = new ContactReference;
|
|
||||||
$attendees = new vectorattendee;
|
|
||||||
foreach ((array)$object['attendees'] as $attendee) {
|
|
||||||
$cr = new ContactReference(ContactReference::EmailReference, $attendee['email']);
|
|
||||||
$cr->setName($attendee['name']);
|
|
||||||
|
|
||||||
if ($attendee['role'] == 'ORGANIZER') {
|
|
||||||
$organizer = $cr;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
$att = new Attendee;
|
|
||||||
$att->setContact($cr);
|
|
||||||
$att->setPartStat($this->status_map[$attendee['status']]);
|
|
||||||
$att->setRole($this->role_map[$attendee['role']] ? $this->role_map[$attendee['role']] : kolabformat::Required);
|
|
||||||
$att->setRSVP((bool)$attendee['rsvp']);
|
|
||||||
|
|
||||||
if ($att->isValid()) {
|
|
||||||
$attendees->push($att);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
raise_error(array(
|
|
||||||
'code' => 600, 'type' => 'php',
|
|
||||||
'file' => __FILE__, 'line' => __LINE__,
|
|
||||||
'message' => "Invalid event attendee: " . json_encode($attendee),
|
|
||||||
), true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
$this->obj->setOrganizer($organizer);
|
|
||||||
$this->obj->setAttendees($attendees);
|
|
||||||
|
|
||||||
// save recurrence rule
|
|
||||||
if ($object['recurrence']) {
|
|
||||||
$rr = new RecurrenceRule;
|
|
||||||
$rr->setFrequency($this->rrule_type_map[$object['recurrence']['FREQ']]);
|
|
||||||
|
|
||||||
if ($object['recurrence']['INTERVAL'])
|
|
||||||
$rr->setInterval(intval($object['recurrence']['INTERVAL']));
|
|
||||||
|
|
||||||
if ($object['recurrence']['BYDAY']) {
|
|
||||||
$byday = new vectordaypos;
|
|
||||||
foreach (explode(',', $object['recurrence']['BYDAY']) as $day) {
|
|
||||||
$occurrence = 0;
|
|
||||||
if (preg_match('/^([\d-]+)([A-Z]+)$/', $day, $m)) {
|
|
||||||
$occurrence = intval($m[1]);
|
|
||||||
$day = $m[2];
|
|
||||||
}
|
|
||||||
if (isset($this->weekday_map[$day]))
|
|
||||||
$byday->push(new DayPos($occurrence, $this->weekday_map[$day]));
|
|
||||||
}
|
|
||||||
$rr->setByday($byday);
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($object['recurrence']['BYMONTHDAY']) {
|
|
||||||
$bymday = new vectori;
|
|
||||||
foreach (explode(',', $object['recurrence']['BYMONTHDAY']) as $day)
|
|
||||||
$bymday->push(intval($day));
|
|
||||||
$rr->setBymonthday($bymday);
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($object['recurrence']['BYMONTH']) {
|
|
||||||
$bymonth = new vectori;
|
|
||||||
foreach (explode(',', $object['recurrence']['BYMONTH']) as $month)
|
|
||||||
$bymonth->push(intval($month));
|
|
||||||
$rr->setBymonth($bymonth);
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($object['recurrence']['COUNT'])
|
|
||||||
$rr->setCount(intval($object['recurrence']['COUNT']));
|
|
||||||
else if ($object['recurrence']['UNTIL'])
|
|
||||||
$rr->setEnd(self::get_datetime($object['recurrence']['UNTIL'], null, true));
|
|
||||||
|
|
||||||
if ($rr->isValid()) {
|
|
||||||
$this->obj->setRecurrenceRule($rr);
|
|
||||||
|
|
||||||
// add exception dates (only if recurrence rule is valid)
|
|
||||||
$exdates = new vectordatetime;
|
|
||||||
foreach ((array)$object['recurrence']['EXDATE'] as $exdate)
|
|
||||||
$exdates->push(self::get_datetime($exdate, null, true));
|
|
||||||
$this->obj->setExceptionDates($exdates);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
raise_error(array(
|
|
||||||
'code' => 600, 'type' => 'php',
|
|
||||||
'file' => __FILE__, 'line' => __LINE__,
|
|
||||||
'message' => "Invalid event recurrence rule: " . json_encode($object['recurrence']),
|
|
||||||
), true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// save alarm
|
|
||||||
$valarms = new vectoralarm;
|
|
||||||
if ($object['alarms']) {
|
|
||||||
list($offset, $type) = explode(":", $object['alarms']);
|
|
||||||
|
|
||||||
if ($type == 'EMAIL') { // email alarms implicitly go to event owner
|
|
||||||
$recipients = new vectorcontactref;
|
|
||||||
$recipients->push(new ContactReference(ContactReference::EmailReference, $object['_owner']));
|
|
||||||
$alarm = new Alarm($object['title'], strval($object['description']), $recipients);
|
|
||||||
}
|
|
||||||
else { // default: display alarm
|
|
||||||
$alarm = new Alarm($object['title']);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (preg_match('/^@(\d+)/', $offset, $d)) {
|
|
||||||
$alarm->setStart(self::get_datetime($d[1], new DateTimeZone('UTC')));
|
|
||||||
}
|
|
||||||
else if (preg_match('/^([-+]?)(\d+)([SMHDW])/', $offset, $d)) {
|
|
||||||
$days = $hours = $minutes = $seconds = 0;
|
|
||||||
switch ($d[3]) {
|
|
||||||
case 'W': $days = 7*intval($d[2]); break;
|
|
||||||
case 'D': $days = intval($d[2]); break;
|
|
||||||
case 'H': $hours = intval($d[2]); break;
|
|
||||||
case 'M': $minutes = intval($d[2]); break;
|
|
||||||
case 'S': $seconds = intval($d[2]); break;
|
|
||||||
}
|
|
||||||
$alarm->setRelativeStart(new Duration($days, $hours, $minutes, $seconds, $d[1] == '-'), $d[1] == '-' ? kolabformat::Start : kolabformat::End);
|
|
||||||
}
|
|
||||||
|
|
||||||
$valarms->push($alarm);
|
|
||||||
}
|
|
||||||
$this->obj->setAlarms($valarms);
|
|
||||||
|
|
||||||
// save attachments
|
// save attachments
|
||||||
$vattach = new vectorattachment;
|
$vattach = new vectorattachment;
|
||||||
foreach ((array)$object['_attachments'] as $name => $attr) {
|
foreach ((array)$object['_attachments'] as $name => $attr) {
|
||||||
|
@ -292,9 +103,9 @@ class kolab_format_event extends kolab_format
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Convert the Contact object into a hash array data structure
|
* Convert the Event object into a hash array data structure
|
||||||
*
|
*
|
||||||
* @return array Contact data as hash array
|
* @return array Event data as hash array
|
||||||
*/
|
*/
|
||||||
public function to_array()
|
public function to_array()
|
||||||
{
|
{
|
||||||
|
@ -304,24 +115,24 @@ class kolab_format_event extends kolab_format
|
||||||
|
|
||||||
$this->init();
|
$this->init();
|
||||||
|
|
||||||
$sensitivity_map = array_flip($this->sensitivity_map);
|
// read common xcal props
|
||||||
|
$object = parent::to_array();
|
||||||
|
|
||||||
// read object properties
|
// read object properties
|
||||||
$object = array(
|
$object += array(
|
||||||
'uid' => $this->obj->uid(),
|
|
||||||
'changed' => self::php_datetime($this->obj->lastModified()),
|
|
||||||
'title' => $this->obj->summary(),
|
|
||||||
'location' => $this->obj->location(),
|
|
||||||
'description' => $this->obj->description(),
|
|
||||||
'allday' => $this->obj->start()->isDateOnly(),
|
'allday' => $this->obj->start()->isDateOnly(),
|
||||||
'start' => self::php_datetime($this->obj->start()),
|
'start' => self::php_datetime($this->obj->start()),
|
||||||
'end' => self::php_datetime($this->obj->end()),
|
'end' => self::php_datetime($this->obj->end()),
|
||||||
'categories' => self::vector2array($this->obj->categories()),
|
|
||||||
'free_busy' => $this->obj->transparency() ? 'free' : 'busy', // TODO: transparency is only boolean
|
'free_busy' => $this->obj->transparency() ? 'free' : 'busy', // TODO: transparency is only boolean
|
||||||
'sensitivity' => $sensitivity_map[$this->obj->classification()],
|
'attendees' => array(),
|
||||||
'priority' => $this->obj->priority(),
|
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// organizer is part of the attendees list in Roundcube
|
||||||
|
if ($object['organizer']) {
|
||||||
|
$object['organizer']['role'] = 'ORGANIZER';
|
||||||
|
array_unshift($object['attendees'], $object['organizer']);
|
||||||
|
}
|
||||||
|
|
||||||
// status defines different event properties...
|
// status defines different event properties...
|
||||||
$status = $this->obj->status();
|
$status = $this->obj->status();
|
||||||
if ($status == kolabformat::StatusTentative)
|
if ($status == kolabformat::StatusTentative)
|
||||||
|
@ -329,100 +140,6 @@ class kolab_format_event extends kolab_format
|
||||||
else if ($status == kolabformat::StatusCancelled)
|
else if ($status == kolabformat::StatusCancelled)
|
||||||
$objec['cancelled'] = true;
|
$objec['cancelled'] = true;
|
||||||
|
|
||||||
// read organizer and attendees
|
|
||||||
if ($organizer = $this->obj->organizer()) {
|
|
||||||
$object['attendees'][] = array(
|
|
||||||
'role' => 'ORGANIZER',
|
|
||||||
'email' => $organizer->email(),
|
|
||||||
'name' => $organizer->name(),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
$role_map = array_flip($this->role_map);
|
|
||||||
$status_map = array_flip($this->status_map);
|
|
||||||
$attvec = $this->obj->attendees();
|
|
||||||
for ($i=0; $i < $attvec->size(); $i++) {
|
|
||||||
$attendee = $attvec->get($i);
|
|
||||||
$cr = $attendee->contact();
|
|
||||||
$object['attendees'][] = array(
|
|
||||||
'role' => $role_map[$attendee->role()],
|
|
||||||
'status' => $status_map[$attendee->partStat()],
|
|
||||||
'rsvp' => $attendee->rsvp(),
|
|
||||||
'email' => $cr->email(),
|
|
||||||
'name' => $cr->name(),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
// read recurrence rule
|
|
||||||
if (($rr = $this->obj->recurrenceRule()) && $rr->isValid()) {
|
|
||||||
$rrule_type_map = array_flip($this->rrule_type_map);
|
|
||||||
$object['recurrence'] = array('FREQ' => $rrule_type_map[$rr->frequency()]);
|
|
||||||
|
|
||||||
if ($intvl = $rr->interval())
|
|
||||||
$object['recurrence']['INTERVAL'] = $intvl;
|
|
||||||
|
|
||||||
if (($count = $rr->count()) && $count > 0) {
|
|
||||||
$object['recurrence']['COUNT'] = $count;
|
|
||||||
}
|
|
||||||
else if ($until = self::php_datetime($rr->end())) {
|
|
||||||
$until->setTime($object['start']->format('G'), $object['start']->format('i'), 0);
|
|
||||||
$object['recurrence']['UNTIL'] = $until->format('U');
|
|
||||||
}
|
|
||||||
|
|
||||||
if (($byday = $rr->byday()) && $byday->size()) {
|
|
||||||
$weekday_map = array_flip($this->weekday_map);
|
|
||||||
$weekdays = array();
|
|
||||||
for ($i=0; $i < $byday->size(); $i++) {
|
|
||||||
$daypos = $byday->get($i);
|
|
||||||
$prefix = $daypos->occurence();
|
|
||||||
$weekdays[] = ($prefix ? $prefix : '') . $weekday_map[$daypos->weekday()];
|
|
||||||
}
|
|
||||||
$object['recurrence']['BYDAY'] = join(',', $weekdays);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (($bymday = $rr->bymonthday()) && $bymday->size()) {
|
|
||||||
$object['recurrence']['BYMONTHDAY'] = join(',', self::vector2array($bymday));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (($bymonth = $rr->bymonth()) && $bymonth->size()) {
|
|
||||||
$object['recurrence']['BYMONTH'] = join(',', self::vector2array($bymonth));
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($exceptions = $this->obj->exceptionDates()) {
|
|
||||||
for ($i=0; $i < $exceptions->size(); $i++) {
|
|
||||||
if ($exdate = self::php_datetime($exceptions->get($i)))
|
|
||||||
$object['recurrence']['EXDATE'][] = $exdate->format('U');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// read alarm
|
|
||||||
$valarms = $this->obj->alarms();
|
|
||||||
$alarm_types = array_flip($this->alarm_type_map);
|
|
||||||
for ($i=0; $i < $valarms->size(); $i++) {
|
|
||||||
$alarm = $valarms->get($i);
|
|
||||||
$type = $alarm_types[$alarm->type()];
|
|
||||||
|
|
||||||
if ($type == 'DISPLAY' || $type == 'EMAIL') { // only DISPLAY and EMAIL alarms are supported
|
|
||||||
if ($start = self::php_datetime($alarm->start())) {
|
|
||||||
$object['alarms'] = '@' . $start->format('U');
|
|
||||||
}
|
|
||||||
else if ($offset = $alarm->relativeStart()) {
|
|
||||||
$value = $alarm->relativeTo() == kolabformat::End ? '+' : '-';
|
|
||||||
if ($w = $offset->weeks()) $value .= $w . 'W';
|
|
||||||
else if ($d = $offset->days()) $value .= $d . 'D';
|
|
||||||
else if ($h = $offset->hours()) $value .= $h . 'H';
|
|
||||||
else if ($m = $offset->minutes()) $value .= $m . 'M';
|
|
||||||
else if ($s = $offset->seconds()) $value .= $s . 'S';
|
|
||||||
else continue;
|
|
||||||
|
|
||||||
$object['alarms'] = $value;
|
|
||||||
}
|
|
||||||
$object['alarms'] .= ':' . $type;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// handle attachments
|
// handle attachments
|
||||||
$vattach = $this->obj->attachments();
|
$vattach = $this->obj->attachments();
|
||||||
for ($i=0; $i < $vattach->size(); $i++) {
|
for ($i=0; $i < $vattach->size(); $i++) {
|
||||||
|
|
|
@ -22,19 +22,11 @@
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
class kolab_format_task extends kolab_format
|
class kolab_format_task extends kolab_format_xcal
|
||||||
{
|
{
|
||||||
public $CTYPE = 'application/calendar+xml';
|
|
||||||
|
|
||||||
protected $read_func = 'kolabformat::readTodo';
|
protected $read_func = 'kolabformat::readTodo';
|
||||||
protected $write_func = 'kolabformat::writeTodo';
|
protected $write_func = 'kolabformat::writeTodo';
|
||||||
|
|
||||||
private $status_map = array(
|
|
||||||
'NEEDS-ACTION' => kolabformat::StatusNeedsAction,
|
|
||||||
'IN-PROCESS' => kolabformat::StatusInProcess,
|
|
||||||
'COMPLETED' => kolabformat::StatusCompleted,
|
|
||||||
'CANCELLED' => kolabformat::StatusCancelled,
|
|
||||||
);
|
|
||||||
|
|
||||||
function __construct($xmldata = null)
|
function __construct($xmldata = null)
|
||||||
{
|
{
|
||||||
|
@ -51,11 +43,22 @@ class kolab_format_task extends kolab_format
|
||||||
{
|
{
|
||||||
$this->init();
|
$this->init();
|
||||||
|
|
||||||
// set some automatic values if missing
|
// set common xcal properties
|
||||||
if (!empty($object['uid']))
|
parent::set($object);
|
||||||
$this->obj->setUid($object['uid']);
|
|
||||||
|
|
||||||
// TODO: set object propeties
|
$this->obj->setPercentComplete(intval($object['complete']));
|
||||||
|
|
||||||
|
if (isset($object['start']))
|
||||||
|
$this->obj->setStart(self::get_datetime($object['start']));
|
||||||
|
if (isset($object['end']))
|
||||||
|
$this->obj->setEnd(self::get_datetime($object['end']));
|
||||||
|
|
||||||
|
$this->obj->setDue(self::get_datetime($object['due'], null, $object['due']->_dateonly));
|
||||||
|
|
||||||
|
$related = new vectors;
|
||||||
|
if (!empty($object['parent_id']))
|
||||||
|
$related->push($object['parent_id']);
|
||||||
|
$this->obj->setRelatedTo($related);
|
||||||
|
|
||||||
// cache this data
|
// cache this data
|
||||||
$this->data = $object;
|
$this->data = $object;
|
||||||
|
@ -70,6 +73,45 @@ class kolab_format_task extends kolab_format
|
||||||
return $this->data || (is_object($this->obj) && $this->obj->isValid());
|
return $this->data || (is_object($this->obj) && $this->obj->isValid());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Convert the Configuration object into a hash array data structure
|
||||||
|
*
|
||||||
|
* @return array Config object data as hash array
|
||||||
|
*/
|
||||||
|
public function to_array()
|
||||||
|
{
|
||||||
|
// return cached result
|
||||||
|
if (!empty($this->data))
|
||||||
|
return $this->data;
|
||||||
|
|
||||||
|
$this->init();
|
||||||
|
|
||||||
|
// read common xcal props
|
||||||
|
$object = parent::to_array();
|
||||||
|
|
||||||
|
$object['complete'] = intval($this->obj->percentComplete());
|
||||||
|
|
||||||
|
// if start/end date is set
|
||||||
|
if ($dtstart = $this->obj->start())
|
||||||
|
$object['start'] = self::php_datetime($dtstart);
|
||||||
|
if ($dtend = $this->obj->end())
|
||||||
|
$object['end'] = self::php_datetime($dtend);
|
||||||
|
|
||||||
|
// if due date is set
|
||||||
|
if ($due = $this->obj->due())
|
||||||
|
$object['due'] = self::php_datetime($due);
|
||||||
|
|
||||||
|
// related-to points to parent taks; we only support one relation
|
||||||
|
$related = self::vector2array($this->obj->relatedTo());
|
||||||
|
if (count($related))
|
||||||
|
$object['parent_id'] = $related[0];
|
||||||
|
|
||||||
|
// TODO: map more properties
|
||||||
|
|
||||||
|
$this->data = $object;
|
||||||
|
return $this->data;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Load data from old Kolab2 format
|
* Load data from old Kolab2 format
|
||||||
*/
|
*/
|
||||||
|
@ -85,45 +127,4 @@ class kolab_format_task extends kolab_format
|
||||||
$this->data = $object;
|
$this->data = $object;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Convert the Configuration object into a hash array data structure
|
|
||||||
*
|
|
||||||
* @return array Config object data as hash array
|
|
||||||
*/
|
|
||||||
public function to_array()
|
|
||||||
{
|
|
||||||
// return cached result
|
|
||||||
if (!empty($this->data))
|
|
||||||
return $this->data;
|
|
||||||
|
|
||||||
$this->init();
|
|
||||||
|
|
||||||
// read object properties
|
|
||||||
$status_map = array_flip($this->status_map);
|
|
||||||
$object = array(
|
|
||||||
'uid' => $this->obj->uid(),
|
|
||||||
'changed' => $this->obj->lastModified(),
|
|
||||||
'summary' => $this->obj->summary(),
|
|
||||||
'description' => $this->obj->description(),
|
|
||||||
'location' => $this->obj->location(),
|
|
||||||
'status' => $this->status_map[$this->obj->status()],
|
|
||||||
'complete' => intval($this->obj->percentComplete()),
|
|
||||||
'priority' => $this->obj->priority(),
|
|
||||||
);
|
|
||||||
|
|
||||||
// if due date is set
|
|
||||||
if ($dtstart = $this->obj->start()) {
|
|
||||||
$object['start'] = self::php_datetime($dtstart);
|
|
||||||
}
|
|
||||||
// if due date is set
|
|
||||||
if ($due = $this->obj->due()) {
|
|
||||||
$object['due'] = self::php_datetime($due);
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: map more properties
|
|
||||||
|
|
||||||
$this->data = $object;
|
|
||||||
return $this->data;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
361
plugins/libkolab/lib/kolab_format_xcal.php
Normal file
361
plugins/libkolab/lib/kolab_format_xcal.php
Normal file
|
@ -0,0 +1,361 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Xcal based Kolab format class wrapping libkolabxml bindings
|
||||||
|
*
|
||||||
|
* Base class for xcal-based Kolab groupware objects such as event, todo, journal
|
||||||
|
*
|
||||||
|
* @version @package_version@
|
||||||
|
* @author Thomas Bruederli <bruederli@kolabsys.com>
|
||||||
|
*
|
||||||
|
* Copyright (C) 2012, Kolab Systems AG <contact@kolabsys.com>
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Affero General Public License as
|
||||||
|
* published by the Free Software Foundation, either version 3 of the
|
||||||
|
* License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Affero General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Affero General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
abstract class kolab_format_xcal extends kolab_format
|
||||||
|
{
|
||||||
|
public $CTYPE = 'application/calendar+xml';
|
||||||
|
|
||||||
|
protected $sensitivity_map = array(
|
||||||
|
'public' => kolabformat::ClassPublic,
|
||||||
|
'private' => kolabformat::ClassPrivate,
|
||||||
|
'confidential' => kolabformat::ClassConfidential,
|
||||||
|
);
|
||||||
|
|
||||||
|
protected $role_map = array(
|
||||||
|
'REQ-PARTICIPANT' => kolabformat::Required,
|
||||||
|
'OPT-PARTICIPANT' => kolabformat::Optional,
|
||||||
|
'NON-PARTICIPANT' => kolabformat::NonParticipant,
|
||||||
|
'CHAIR' => kolabformat::Chair,
|
||||||
|
);
|
||||||
|
|
||||||
|
protected $rrule_type_map = array(
|
||||||
|
'MINUTELY' => RecurrenceRule::Minutely,
|
||||||
|
'HOURLY' => RecurrenceRule::Hourly,
|
||||||
|
'DAILY' => RecurrenceRule::Daily,
|
||||||
|
'WEEKLY' => RecurrenceRule::Weekly,
|
||||||
|
'MONTHLY' => RecurrenceRule::Monthly,
|
||||||
|
'YEARLY' => RecurrenceRule::Yearly,
|
||||||
|
);
|
||||||
|
|
||||||
|
protected $weekday_map = array(
|
||||||
|
'MO' => kolabformat::Monday,
|
||||||
|
'TU' => kolabformat::Tuesday,
|
||||||
|
'WE' => kolabformat::Wednesday,
|
||||||
|
'TH' => kolabformat::Thursday,
|
||||||
|
'FR' => kolabformat::Friday,
|
||||||
|
'SA' => kolabformat::Saturday,
|
||||||
|
'SU' => kolabformat::Sunday,
|
||||||
|
);
|
||||||
|
|
||||||
|
protected $alarm_type_map = array(
|
||||||
|
'DISPLAY' => Alarm::DisplayAlarm,
|
||||||
|
'EMAIL' => Alarm::EMailAlarm,
|
||||||
|
'AUDIO' => Alarm::AudioAlarm,
|
||||||
|
);
|
||||||
|
|
||||||
|
private $status_map = array(
|
||||||
|
'NEEDS-ACTION' => kolabformat::StatusNeedsAction,
|
||||||
|
'IN-PROCESS' => kolabformat::StatusInProcess,
|
||||||
|
'COMPLETED' => kolabformat::StatusCompleted,
|
||||||
|
'CANCELLED' => kolabformat::StatusCancelled,
|
||||||
|
);
|
||||||
|
|
||||||
|
protected $part_status_map = array(
|
||||||
|
'UNKNOWN' => kolabformat::PartNeedsAction,
|
||||||
|
'NEEDS-ACTION' => kolabformat::PartNeedsAction,
|
||||||
|
'TENTATIVE' => kolabformat::PartTentative,
|
||||||
|
'ACCEPTED' => kolabformat::PartAccepted,
|
||||||
|
'DECLINED' => kolabformat::PartDeclined,
|
||||||
|
'DELEGATED' => kolabformat::PartDelegated,
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Convert common xcard properties into a hash array data structure
|
||||||
|
*
|
||||||
|
* @return array Object data as hash array
|
||||||
|
*/
|
||||||
|
public function to_array()
|
||||||
|
{
|
||||||
|
$status_map = array_flip($this->status_map);
|
||||||
|
$sensitivity_map = array_flip($this->sensitivity_map);
|
||||||
|
|
||||||
|
$object = array(
|
||||||
|
'uid' => $this->obj->uid(),
|
||||||
|
'changed' => self::php_datetime($this->obj->lastModified()),
|
||||||
|
'title' => $this->obj->summary(),
|
||||||
|
'location' => $this->obj->location(),
|
||||||
|
'description' => $this->obj->description(),
|
||||||
|
'status' => $this->status_map[$this->obj->status()],
|
||||||
|
'sensitivity' => $sensitivity_map[$this->obj->classification()],
|
||||||
|
'priority' => $this->obj->priority(),
|
||||||
|
'categories' => self::vector2array($this->obj->categories()),
|
||||||
|
);
|
||||||
|
|
||||||
|
// read organizer and attendees
|
||||||
|
if ($organizer = $this->obj->organizer()) {
|
||||||
|
$object['organizer'] = array(
|
||||||
|
'email' => $organizer->email(),
|
||||||
|
'name' => $organizer->name(),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
$role_map = array_flip($this->role_map);
|
||||||
|
$part_status_map = array_flip($this->part_status_map);
|
||||||
|
$attvec = $this->obj->attendees();
|
||||||
|
for ($i=0; $i < $attvec->size(); $i++) {
|
||||||
|
$attendee = $attvec->get($i);
|
||||||
|
$cr = $attendee->contact();
|
||||||
|
$object['attendees'][] = array(
|
||||||
|
'role' => $role_map[$attendee->role()],
|
||||||
|
'status' => $part_status_map[$attendee->partStat()],
|
||||||
|
'rsvp' => $attendee->rsvp(),
|
||||||
|
'email' => $cr->email(),
|
||||||
|
'name' => $cr->name(),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// read recurrence rule
|
||||||
|
if (($rr = $this->obj->recurrenceRule()) && $rr->isValid()) {
|
||||||
|
$rrule_type_map = array_flip($this->rrule_type_map);
|
||||||
|
$object['recurrence'] = array('FREQ' => $rrule_type_map[$rr->frequency()]);
|
||||||
|
|
||||||
|
if ($intvl = $rr->interval())
|
||||||
|
$object['recurrence']['INTERVAL'] = $intvl;
|
||||||
|
|
||||||
|
if (($count = $rr->count()) && $count > 0) {
|
||||||
|
$object['recurrence']['COUNT'] = $count;
|
||||||
|
}
|
||||||
|
else if ($until = self::php_datetime($rr->end())) {
|
||||||
|
$until->setTime($object['start']->format('G'), $object['start']->format('i'), 0);
|
||||||
|
$object['recurrence']['UNTIL'] = $until->format('U');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (($byday = $rr->byday()) && $byday->size()) {
|
||||||
|
$weekday_map = array_flip($this->weekday_map);
|
||||||
|
$weekdays = array();
|
||||||
|
for ($i=0; $i < $byday->size(); $i++) {
|
||||||
|
$daypos = $byday->get($i);
|
||||||
|
$prefix = $daypos->occurence();
|
||||||
|
$weekdays[] = ($prefix ? $prefix : '') . $weekday_map[$daypos->weekday()];
|
||||||
|
}
|
||||||
|
$object['recurrence']['BYDAY'] = join(',', $weekdays);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (($bymday = $rr->bymonthday()) && $bymday->size()) {
|
||||||
|
$object['recurrence']['BYMONTHDAY'] = join(',', self::vector2array($bymday));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (($bymonth = $rr->bymonth()) && $bymonth->size()) {
|
||||||
|
$object['recurrence']['BYMONTH'] = join(',', self::vector2array($bymonth));
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($exceptions = $this->obj->exceptionDates()) {
|
||||||
|
for ($i=0; $i < $exceptions->size(); $i++) {
|
||||||
|
if ($exdate = self::php_datetime($exceptions->get($i)))
|
||||||
|
$object['recurrence']['EXDATE'][] = $exdate->format('U');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// read alarm
|
||||||
|
$valarms = $this->obj->alarms();
|
||||||
|
$alarm_types = array_flip($this->alarm_type_map);
|
||||||
|
for ($i=0; $i < $valarms->size(); $i++) {
|
||||||
|
$alarm = $valarms->get($i);
|
||||||
|
$type = $alarm_types[$alarm->type()];
|
||||||
|
|
||||||
|
if ($type == 'DISPLAY' || $type == 'EMAIL') { // only DISPLAY and EMAIL alarms are supported
|
||||||
|
if ($start = self::php_datetime($alarm->start())) {
|
||||||
|
$object['alarms'] = '@' . $start->format('U');
|
||||||
|
}
|
||||||
|
else if ($offset = $alarm->relativeStart()) {
|
||||||
|
$value = $alarm->relativeTo() == kolabformat::End ? '+' : '-';
|
||||||
|
if ($w = $offset->weeks()) $value .= $w . 'W';
|
||||||
|
else if ($d = $offset->days()) $value .= $d . 'D';
|
||||||
|
else if ($h = $offset->hours()) $value .= $h . 'H';
|
||||||
|
else if ($m = $offset->minutes()) $value .= $m . 'M';
|
||||||
|
else if ($s = $offset->seconds()) $value .= $s . 'S';
|
||||||
|
else continue;
|
||||||
|
|
||||||
|
$object['alarms'] = $value;
|
||||||
|
}
|
||||||
|
$object['alarms'] .= ':' . $type;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $object;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set common xcal properties to the kolabformat object
|
||||||
|
*
|
||||||
|
* @param array Event data as hash array
|
||||||
|
*/
|
||||||
|
public function set(&$object)
|
||||||
|
{
|
||||||
|
// set some automatic values if missing
|
||||||
|
if (!$this->obj->created()) {
|
||||||
|
if (!empty($object['created']))
|
||||||
|
$object['created'] = new DateTime('now', self::$timezone);
|
||||||
|
$this->obj->setCreated(self::get_datetime($object['created']));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!empty($object['uid']))
|
||||||
|
$this->obj->setUid($object['uid']);
|
||||||
|
|
||||||
|
// increment sequence
|
||||||
|
$this->obj->setSequence($this->obj->sequence()+1);
|
||||||
|
|
||||||
|
$this->obj->setSummary($object['title']);
|
||||||
|
$this->obj->setLocation($object['location']);
|
||||||
|
$this->obj->setDescription($object['description']);
|
||||||
|
$this->obj->setPriority($object['priority']);
|
||||||
|
$this->obj->setClassification($this->sensitivity_map[$object['sensitivity']]);
|
||||||
|
$this->obj->setCategories(self::array2vector($object['categories']));
|
||||||
|
|
||||||
|
// process event attendees
|
||||||
|
$attendees = new vectorattendee;
|
||||||
|
foreach ((array)$object['attendees'] as $attendee) {
|
||||||
|
if ($attendee['role'] == 'ORGANIZER') {
|
||||||
|
$object['organizer'] = $attendee;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
$cr = new ContactReference(ContactReference::EmailReference, $attendee['email']);
|
||||||
|
$cr->setName($attendee['name']);
|
||||||
|
|
||||||
|
$att = new Attendee;
|
||||||
|
$att->setContact($cr);
|
||||||
|
$att->setPartStat($this->status_map[$attendee['status']]);
|
||||||
|
$att->setRole($this->role_map[$attendee['role']] ? $this->role_map[$attendee['role']] : kolabformat::Required);
|
||||||
|
$att->setRSVP((bool)$attendee['rsvp']);
|
||||||
|
|
||||||
|
if ($att->isValid()) {
|
||||||
|
$attendees->push($att);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
raise_error(array(
|
||||||
|
'code' => 600, 'type' => 'php',
|
||||||
|
'file' => __FILE__, 'line' => __LINE__,
|
||||||
|
'message' => "Invalid event attendee: " . json_encode($attendee),
|
||||||
|
), true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$this->obj->setAttendees($attendees);
|
||||||
|
|
||||||
|
if ($object['organizer']) {
|
||||||
|
$organizer = new ContactReference(ContactReference::EmailReference, $object['organizer']['email']);
|
||||||
|
$organizer->setName($object['organizer']['name']);
|
||||||
|
$this->obj->setOrganizer($organizer);
|
||||||
|
}
|
||||||
|
|
||||||
|
// save recurrence rule
|
||||||
|
if ($object['recurrence']) {
|
||||||
|
$rr = new RecurrenceRule;
|
||||||
|
$rr->setFrequency($this->rrule_type_map[$object['recurrence']['FREQ']]);
|
||||||
|
|
||||||
|
if ($object['recurrence']['INTERVAL'])
|
||||||
|
$rr->setInterval(intval($object['recurrence']['INTERVAL']));
|
||||||
|
|
||||||
|
if ($object['recurrence']['BYDAY']) {
|
||||||
|
$byday = new vectordaypos;
|
||||||
|
foreach (explode(',', $object['recurrence']['BYDAY']) as $day) {
|
||||||
|
$occurrence = 0;
|
||||||
|
if (preg_match('/^([\d-]+)([A-Z]+)$/', $day, $m)) {
|
||||||
|
$occurrence = intval($m[1]);
|
||||||
|
$day = $m[2];
|
||||||
|
}
|
||||||
|
if (isset($this->weekday_map[$day]))
|
||||||
|
$byday->push(new DayPos($occurrence, $this->weekday_map[$day]));
|
||||||
|
}
|
||||||
|
$rr->setByday($byday);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($object['recurrence']['BYMONTHDAY']) {
|
||||||
|
$bymday = new vectori;
|
||||||
|
foreach (explode(',', $object['recurrence']['BYMONTHDAY']) as $day)
|
||||||
|
$bymday->push(intval($day));
|
||||||
|
$rr->setBymonthday($bymday);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($object['recurrence']['BYMONTH']) {
|
||||||
|
$bymonth = new vectori;
|
||||||
|
foreach (explode(',', $object['recurrence']['BYMONTH']) as $month)
|
||||||
|
$bymonth->push(intval($month));
|
||||||
|
$rr->setBymonth($bymonth);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($object['recurrence']['COUNT'])
|
||||||
|
$rr->setCount(intval($object['recurrence']['COUNT']));
|
||||||
|
else if ($object['recurrence']['UNTIL'])
|
||||||
|
$rr->setEnd(self::get_datetime($object['recurrence']['UNTIL'], null, true));
|
||||||
|
|
||||||
|
if ($rr->isValid()) {
|
||||||
|
$this->obj->setRecurrenceRule($rr);
|
||||||
|
|
||||||
|
// add exception dates (only if recurrence rule is valid)
|
||||||
|
$exdates = new vectordatetime;
|
||||||
|
foreach ((array)$object['recurrence']['EXDATE'] as $exdate)
|
||||||
|
$exdates->push(self::get_datetime($exdate, null, true));
|
||||||
|
$this->obj->setExceptionDates($exdates);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
raise_error(array(
|
||||||
|
'code' => 600, 'type' => 'php',
|
||||||
|
'file' => __FILE__, 'line' => __LINE__,
|
||||||
|
'message' => "Invalid event recurrence rule: " . json_encode($object['recurrence']),
|
||||||
|
), true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// save alarm
|
||||||
|
$valarms = new vectoralarm;
|
||||||
|
if ($object['alarms']) {
|
||||||
|
list($offset, $type) = explode(":", $object['alarms']);
|
||||||
|
|
||||||
|
if ($type == 'EMAIL') { // email alarms implicitly go to event owner
|
||||||
|
$recipients = new vectorcontactref;
|
||||||
|
$recipients->push(new ContactReference(ContactReference::EmailReference, $object['_owner']));
|
||||||
|
$alarm = new Alarm($object['title'], strval($object['description']), $recipients);
|
||||||
|
}
|
||||||
|
else { // default: display alarm
|
||||||
|
$alarm = new Alarm($object['title']);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (preg_match('/^@(\d+)/', $offset, $d)) {
|
||||||
|
$alarm->setStart(self::get_datetime($d[1], new DateTimeZone('UTC')));
|
||||||
|
}
|
||||||
|
else if (preg_match('/^([-+]?)(\d+)([SMHDW])/', $offset, $d)) {
|
||||||
|
$days = $hours = $minutes = $seconds = 0;
|
||||||
|
switch ($d[3]) {
|
||||||
|
case 'W': $days = 7*intval($d[2]); break;
|
||||||
|
case 'D': $days = intval($d[2]); break;
|
||||||
|
case 'H': $hours = intval($d[2]); break;
|
||||||
|
case 'M': $minutes = intval($d[2]); break;
|
||||||
|
case 'S': $seconds = intval($d[2]); break;
|
||||||
|
}
|
||||||
|
$alarm->setRelativeStart(new Duration($days, $hours, $minutes, $seconds, $d[1] == '-'), $d[1] == '-' ? kolabformat::Start : kolabformat::End);
|
||||||
|
}
|
||||||
|
|
||||||
|
$valarms->push($alarm);
|
||||||
|
}
|
||||||
|
$this->obj->setAlarms($valarms);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
Loading…
Add table
Reference in a new issue