Implement event creation and editing.
authorJan Schneider <jan@horde.org>
Mon, 23 Mar 2009 23:54:46 +0000 (00:54 +0100)
committerJan Schneider <jan@horde.org>
Mon, 23 Mar 2009 23:54:46 +0000 (00:54 +0100)
kronolith/ajax.php
kronolith/js/src/kronolith.js
kronolith/lib/Driver/Kolab.php
kronolith/lib/Driver/Sql.php
kronolith/lib/Event.php
kronolith/lib/Kronolith.php
kronolith/templates/index/index.inc

index e529791..2e8d496 100644 (file)
@@ -33,6 +33,9 @@ function getDriver($cal)
     case 'holiday':
         $driver = 'Holidays';
         break;
+    default:
+        $GLOBALS['notification']->push('No calendar driver specified', 'horde.error');
+        break;
     }
 
     $kronolith_driver = Kronolith::getDriver($driver, $calendar);
@@ -133,6 +136,45 @@ case 'GetEvent':
     $result->event = $event->toJSON(true, $prefs->getValue('twentyFour') ? 'H:i' : 'h:i A');
     break;
 
+case 'SaveEvent':
+    $cal = Util::getFormData('cal');
+    if (!($kronolith_driver = getDriver($cal))) {
+        $result = true;
+        break;
+    }
+    $event = $kronolith_driver->getEvent(Util::getFormData('id'));
+    if (is_a($event, 'PEAR_Error')) {
+        $notification->push($event, 'horde.error');
+        $result = true;
+        break;
+    }
+    if (!$event) {
+        $notification->push(_("The requested event was not found."), 'horde.error');
+        $result = true;
+        break;
+    }
+    if (!$event->hasPermission(PERMS_EDIT)) {
+        $notification->push(_("You do not have permission to edit this event."), 'horde.warning');
+        $result = true;
+        break;
+    }
+    $event->readForm();
+    $result = $event->save();
+    if (is_a($result, 'PEAR_Error')) {
+        $notification->push($result, 'horde.error');
+    }
+    $start = new Horde_Date(Util::getFormData('view_start'));
+    $end   = new Horde_Date(Util::getFormData('view_end'));
+    Kronolith::addEvents($events, $event, $start, $end, true, true);
+    $result = new stdClass;
+    $result->cal = $cal;
+    $result->view = Util::getFormData('view');
+    $result->sig = $start->dateString() . $end->dateString();
+    if (count($events)) {
+        $result->events = $events;
+    }
+    break;
+
 case 'UpdateEvent':
     if (!($kronolith_driver = getDriver($cal = Util::getFormData('cal')))) {
         break;
@@ -150,6 +192,11 @@ case 'UpdateEvent':
         $notification->push(_("The requested event was not found."), 'horde.error');
         break;
     }
+    if (!$event->hasPermission(PERMS_EDIT)) {
+        $notification->push(_("You do not have permission to edit this event."), 'horde.warning');
+        $result = true;
+        break;
+    }
     $attributes = Horde_Serialize::unserialize(Util::getFormData('att'), Horde_Serialize::JSON);
     foreach ($attributes as $attribute => $value) {
         switch ($attribute) {
@@ -188,8 +235,7 @@ case 'DeleteEvent':
         $result = true;
         break;
     }
-    $share = &$kronolith_shares->getShare($event->getCalendar());
-    if (!$share->hasPermission(Auth::getAuth(), PERMS_DELETE, $event->getCreatorID())) {
+    if (!$event->hasPermission(PERMS_DELETE)) {
         $notification->push(_("You do not have permission to delete this event."), 'horde.warning');
         $result = true;
         break;
index 50c43ae..e6ba6f3 100644 (file)
@@ -420,7 +420,7 @@ KronolithCore = {
     },
 
     /**
-     * Rebuilds the mini calendar
+     * Rebuilds the mini calendar.
      *
      * @param Date date    The date to show in the calendar.
      * @param string view  The view that's displayed, determines which days in
@@ -579,14 +579,16 @@ KronolithCore = {
             $('kronolithLoading').hide();
         }
 
-        // Check if this is the still the result of the most current request.
-        if (r.response.view != this.view ||
-            r.response.sig != this.eventsLoading[r.response.cal]) {
-            return;
-        }
-
         if (r.response.events) {
             this._storeCache(r.response.events, r.response.cal);
+
+            // Check if this is the still the result of the most current
+            // request.
+            if (r.response.view != this.view ||
+                r.response.sig != this.eventsLoading[r.response.cal]) {
+                return;
+            }
+
             $H(r.response.events).each(function(date) {
                 $H(date.value).each(function(event) {
                     switch (this.view) {
@@ -621,6 +623,12 @@ KronolithCore = {
         }
     },
 
+    _removeEvent: function(event, calendar)
+    {
+        this._deleteCache(event, calendar);
+        $('kronolithViewMonth').select('div[calendar=' + calendar + '][eventid=' + event + ']').invoke('remove');
+    },
+
     /**
      * Parses a date attribute string into a Date object.
      *
@@ -677,6 +685,22 @@ KronolithCore = {
         this.ecache[calendar[0]][calendar[1]] = this.ecache[calendar[0]][calendar[1]].merge(events);
     },
 
+    _deleteCache: function(event, calendar)
+    {
+        if (Object.isString(calendar)) {
+            calendar = calendar.split('|');
+        }
+        if (!this.ecache[calendar[0]] ||
+            !this.ecache[calendar[0]][calendar[1]]) {
+            return;
+        }
+        this.ecache[calendar[0]][calendar[1]].each(function(day) {
+            if (day.value[event]) {
+                delete day.value[event];
+            }
+        });
+    },
+
     _addHistory: function(loc, data)
     {
         if (Horde.dhtmlHistory.getCurrentLocation() != loc) {
@@ -766,13 +790,46 @@ KronolithCore = {
                 e.stop();
                 return;
 
+            case 'kronolithEventSave':
+                var cal = $F('kronolithEventCalendar'),
+                    eventid = $F('kronolithEventId'),
+                    viewDates = this.viewDates(this.date, this.view),
+                    start = viewDates[0].dateString(),
+                    end = viewDates[1].dateString();
+                this.eventsLoading[cal] = start + end;
+                this.loading++;
+                this.doAction('SaveEvent',
+                              $H($('kronolithEventForm').serialize({ 'hash': true }))
+                                  .merge({
+                                      'view': this.view,
+                                      'view_start': start,
+                                      'view_end': end
+                                  }),
+                              function(r) {
+                                  if (r.response.events) {
+                                      if (eventid) {
+                                          this._removeEvent(eventid, cal);
+                                      }
+                                      this._loadEventsCallback(r);
+                                  }
+                                  this._closeRedBox();
+                              }.bind(this));
+                e.stop();
+                return;
+
             case 'kronolithEventDelete':
                 var cal = $F('kronolithEventCalendar'),
                     eventid = $F('kronolithEventId'),
                     elm = $('kronolithEvent' + this.view + cal + eventid);
                 this.doAction('DeleteEvent',
                               { 'cal': cal, 'id': eventid },
-                              function(r) { if (r.response.deleted) elm.remove(); else elm.toggle() });
+                              function(r) {
+                                  if (r.response.deleted) {
+                                      this._removeEvent(eventid, cal);
+                                  } else {
+                                      elm.toggle();
+                                  }
+                              }.bind(this));
                 elm.hide();
                 this._closeRedBox();
                 e.stop();
@@ -905,7 +962,10 @@ KronolithCore = {
             this.doAction('GetEvent', { 'cal': calendar, 'id': id }, this._editEvent.bind(this));
         } else {
             var d = new Date();
-            $('kronolithEventForm').enable().reset();
+            $('kronolithEventForm').enable();
+            $('kronolithEventForm').reset();
+            $('kronolithEventId').value = '';
+            $('kronolithEventCalendar').value = Kronolith.conf.default_calendar;
             $('kronolithEventDelete').hide();
             $('kronolithEventStartDate').value = d.toString(Kronolith.conf.date_format);
             $('kronolithEventStartTime').value = d.toString(Kronolith.conf.time_format);
index 4f931b6..1d4db7d 100644 (file)
@@ -256,7 +256,7 @@ class Kronolith_Driver_Kolab extends Kronolith_Driver
 
     public function getEvent($eventId = null)
     {
-        if (is_null($eventId)) {
+        if (!strlen($eventId)) {
             return new Kronolith_Event_Kolab($this);
         }
 
index 44f7ec3..752d073 100644 (file)
@@ -387,7 +387,7 @@ class Kronolith_Driver_Sql extends Kronolith_Driver
 
     public function getEvent($eventId = null)
     {
-        if (is_null($eventId)) {
+        if (!strlen($eventId)) {
             return new Kronolith_Event_Sql($this);
         }
 
index d7effe7..c323190 100644 (file)
@@ -1551,46 +1551,90 @@ abstract class Kronolith_Event
             $this->setAttendees($_SESSION['kronolith']['attendees']);
         }
 
+        // strptime() is locale dependent, i.e. %p is not always matching
+        // AM/PM. Set the locale to C to workaround this, but grab the
+        // locale's D_FMT before that.
+        $date_format = NLS::getLangInfo(D_FMT);
+        $old_locale = setlocale(LC_TIME, 0);
+        setlocale(LC_TIME, 'C');
+
         // Event start.
-        $start = Util::getFormData('start');
-        $start_year = $start['year'];
-        $start_month = $start['month'];
-        $start_day = $start['day'];
-        $start_hour = Util::getFormData('start_hour');
-        $start_min = Util::getFormData('start_min');
-        $am_pm = Util::getFormData('am_pm');
-
-        if (!$prefs->getValue('twentyFour')) {
-            if ($am_pm == 'PM') {
-                if ($start_hour != 12) {
-                    $start_hour += 12;
+        if ($start_date = Util::getFormData('start_date')) {
+            $start_time = Util::getFormData('start_time');
+            $start = $start_date . ' ' . $start_time;
+            $format = $date_format . ' '
+                . ($prefs->getValue('twentyFour') ? '%H:%M' : '%I:%M %p');
+            // Try exact format match first.
+            if ($date_arr = strptime($start, $format)) {
+                $this->start = new Horde_Date(
+                    array('year'  => $date_arr['tm_year'] + 1900,
+                          'month' => $date_arr['tm_mon'] + 1,
+                          'mday'  => $date_arr['tm_mday'],
+                          'hour'  => $date_arr['tm_hour'],
+                          'min'   => $date_arr['tm_min'],
+                          'sec'   => $date_arr['tm_sec']));
+            } else {
+                $this->start = new Horde_Date($start);
+            }
+        } else {
+            $start = Util::getFormData('start');
+            $start_year = $start['year'];
+            $start_month = $start['month'];
+            $start_day = $start['day'];
+            $start_hour = Util::getFormData('start_hour');
+            $start_min = Util::getFormData('start_min');
+            $am_pm = Util::getFormData('am_pm');
+
+            if (!$prefs->getValue('twentyFour')) {
+                if ($am_pm == 'PM') {
+                    if ($start_hour != 12) {
+                        $start_hour += 12;
+                    }
+                } elseif ($start_hour == 12) {
+                    $start_hour = 0;
                 }
-            } elseif ($start_hour == 12) {
-                $start_hour = 0;
             }
-        }
 
-        if (Util::getFormData('end_or_dur') == 1) {
-            if (Util::getFormData('whole_day') == 1) {
-                $start_hour = 0;
-                $start_min = 0;
-                $dur_day = 0;
-                $dur_hour = 24;
-                $dur_min = 0;
-            } else {
-                $dur_day = (int)Util::getFormData('dur_day');
-                $dur_hour = (int)Util::getFormData('dur_hour');
-                $dur_min = (int)Util::getFormData('dur_min');
+            if (Util::getFormData('end_or_dur') == 1) {
+                if (Util::getFormData('whole_day') == 1) {
+                    $start_hour = 0;
+                    $start_min = 0;
+                    $dur_day = 0;
+                    $dur_hour = 24;
+                    $dur_min = 0;
+                } else {
+                    $dur_day = (int)Util::getFormData('dur_day');
+                    $dur_hour = (int)Util::getFormData('dur_hour');
+                    $dur_min = (int)Util::getFormData('dur_min');
+                }
             }
-        }
 
-        $this->start = new Horde_Date(array('hour' => $start_hour,
-                                            'min' => $start_min,
-                                            'month' => $start_month,
-                                            'mday' => $start_day,
-                                            'year' => $start_year));
+            $this->start = new Horde_Date(array('hour' => $start_hour,
+                                                'min' => $start_min,
+                                                'month' => $start_month,
+                                                'mday' => $start_day,
+                                                'year' => $start_year));
+        }
 
-        if (Util::getFormData('end_or_dur') == 1) {
+        if ($end_date = Util::getFormData('end_date')) {
+            // Event end.
+            $end_time = Util::getFormData('end_time');
+            $end = $end_date . ' ' . $end_time;
+            $format = $date_format . ' '
+                . ($prefs->getValue('twentyFour') ? '%H:%M' : '%I:%M %p');
+            // Try exact format match first.
+            if ($date_arr = strptime($end, $format)) {
+                $this->end = new Horde_Date(
+                    array('year'  => $date_arr['tm_year'] + 1900,
+                          'month' => $date_arr['tm_mon'] + 1,
+                          'mday'  => $date_arr['tm_mday'],
+                          'hour'  => $date_arr['tm_hour'],
+                          'min'   => $date_arr['tm_min'],
+                          'sec'   => $date_arr['tm_sec']));
+            } else {
+                $this->end = new Horde_Date($end);
+            }
+        } elseif (Util::getFormData('end_or_dur') == 1) {
             // Event duration.
             $this->end = new Horde_Date(array('hour' => $start_hour + $dur_hour,
                                               'min' => $start_min + $dur_min,
@@ -1627,35 +1671,39 @@ abstract class Kronolith_Event
             }
         }
 
+        setlocale(LC_TIME, $old_locale);
+
         // Alarm.
-        if (Util::getFormData('alarm') == 1) {
-            $this->setAlarm(Util::getFormData('alarm_value') * Util::getFormData('alarm_unit'));
-            // Notification.
-            if (Util::getFormData('alarm_change_method')) {
-                $types = Util::getFormData('event_alarms');
-                if (!empty($types)) {
-                    $methods = array();
-                    foreach ($types as $type) {
-                        $methods[$type] = array();
-                        switch ($type){
-                        case 'notify':
-                            $methods[$type]['sound'] = Util::getFormData('event_alarms_sound');
-                            break;
-                        case 'mail':
-                            $methods[$type]['email'] = Util::getFormData('event_alarms_email');
-                            break;
-                        case 'popup':
-                            break;
+        if (!is_null($alarm = Util::getFormData('alarm'))) {
+            if ($alarm) {
+                $this->setAlarm(Util::getFormData('alarm_value') * Util::getFormData('alarm_unit'));
+                // Notification.
+                if (Util::getFormData('alarm_change_method')) {
+                    $types = Util::getFormData('event_alarms');
+                    if (!empty($types)) {
+                        $methods = array();
+                        foreach ($types as $type) {
+                            $methods[$type] = array();
+                            switch ($type){
+                            case 'notify':
+                                $methods[$type]['sound'] = Util::getFormData('event_alarms_sound');
+                                break;
+                            case 'mail':
+                                $methods[$type]['email'] = Util::getFormData('event_alarms_email');
+                                break;
+                            case 'popup':
+                                break;
+                            }
                         }
+                        $this->methods = $methods;
                     }
-                    $this->methods = $methods;
+                } else {
+                    $this->methods = array();
                 }
             } else {
+                $this->setAlarm(0);
                 $this->methods = array();
             }
-        } else {
-            $this->setAlarm(0);
-            $this->methods = array();
         }
 
         // Recurrence.
@@ -1743,7 +1791,7 @@ abstract class Kronolith_Event
         }
 
         // Tags.
-        $this->tags = Util::getFormData('tags');
+        $this->tags = Util::getFormData('tags', $this->tags);
 
         $this->initialized = true;
     }
index 842b321..ab98776 100644 (file)
@@ -144,6 +144,7 @@ class Kronolith
             'name' => $registry->get('name'),
             'is_ie6' => ($browser->isBrowser('msie') && ($browser->getMajor() < 7)),
             'login_view' => $prefs->getValue('defaultview'),
+            'default_calendar' => 'internal|' . Kronolith::getDefaultCalendar(PERMS_EDIT),
             'week_start' => (int)$prefs->getValue('week_start_monday'),
             'date_format' => str_replace(array('%e', '%d', '%a', '%A', '%m', '%h', '%b', '%B', '%y', '%Y'),
                                          array('d', 'dd', 'ddd', 'dddd', 'MM', 'MMM', 'MMM', 'MMMM', 'yy', 'yyyy'),
index bfc85ab..423c56a 100644 (file)
 <!-- ini edit -->
 <div id="kronolithEventDialog" style="display:none">
 <form id="kronolithEventForm">
-<input id="kronolithEventCalendar" type="hidden" name="calendar" />
-<input id="kronolithEventId" type="hidden" name="eventid" />
+<input id="kronolithEventCalendar" type="hidden" name="cal" />
+<input id="kronolithEventId" type="hidden" name="id" />
 <div>
   <label for="kronolithEventTitle"><?php echo _("Title") ?></label><br />
   <input type="text" name="title" id="kronolithEventTitle" class="kronolithLongField" />