mirror of
https://github.com/EGroupware/egroupware.git
synced 2024-12-28 17:48:56 +01:00
Merge remote-tracking branch 'origin/master' into upstream_master
This commit is contained in:
commit
44af749074
@ -95,6 +95,7 @@ add new application admin de Neue Anwendung hinzufügen
|
||||
add new email address: admin de Neue E-Mail-Adresse hinzufügen:
|
||||
add peer server admin de Server zu Serververbund hinzufügen
|
||||
add profile admin de Profil hinzufügen
|
||||
add to group admin de Zu Gruppe hinzufügen
|
||||
add sub-category admin de Unterkategorie hinzufügen
|
||||
add user admin de Neuen Benutzer erstellen
|
||||
add user or group admin de Benutzer oder Gruppen eingeben
|
||||
@ -186,6 +187,7 @@ bi-dir passthrough admin de Weiterleitung in beide Richtungen
|
||||
bi-directional admin de beide Richtungen
|
||||
blocking after wrong password admin de Blockierung nach falschem Passwort
|
||||
bottom admin de Unten
|
||||
bulk changes admin de Massenänderungen
|
||||
bulk password reset admin de Rücksetzen Passwörter
|
||||
by admin de Von
|
||||
by selecting a user or group you effectively delete the mail account for all other users!\n\nare you really sure you want to do that? admin de Durch die Auswahl eines Benutzer oder Gruppe löschen Sie das Mailkonto für alle anderen Benutzer!<br>Sind Sie wirklich sicher, dass Sie das wollen?
|
||||
|
@ -95,6 +95,7 @@ add new email address: admin en Add new email address:
|
||||
add peer server admin en Add Peer Server
|
||||
add profile admin en Add profile
|
||||
add sub-category admin en Add sub category
|
||||
add to group admin en Add to group
|
||||
add user admin en Add user
|
||||
add user or group admin en Add user or group
|
||||
added admin en added
|
||||
|
@ -925,7 +925,7 @@ class JsCalendar extends JsBase
|
||||
protected static function Recurrence(array $event, array $data, array $exceptions=[], ?array $rrule=null)
|
||||
{
|
||||
$overrides = [];
|
||||
if (!empty($event['recur_type']) || isset($rrule))
|
||||
if ((!empty($event['recur_type']) || isset($rrule)) && $event['recur_type'] != \calendar_rrule::RDATE)
|
||||
{
|
||||
if (!isset($rrule))
|
||||
{
|
||||
@ -956,24 +956,36 @@ class JsCalendar extends JsBase
|
||||
{
|
||||
$rule['byMonthDay'] = [$rrule['BYMONTHDAY']]; // EGroupware supports only a single day!
|
||||
}
|
||||
|
||||
// adding excludes to the overrides
|
||||
if (!empty($event['recur_exception']))
|
||||
}
|
||||
elseif (!empty($event['recur_rdates']) && $event['recur_type'] == \calendar_rrule::RDATE)
|
||||
{
|
||||
foreach($event['recur_rdates'] as $rdate)
|
||||
{
|
||||
foreach ($event['recur_exception'] as $timestamp)
|
||||
if ($rdate != $event['start'])
|
||||
{
|
||||
$ex_date = new Api\DateTime($timestamp, Api\DateTime::$server_timezone);
|
||||
if (!empty($event['whole_day']))
|
||||
{
|
||||
$ex_date->setTime(0, 0, 0);
|
||||
}
|
||||
$overrides[self::DateTime($ex_date, $event['tzid'])] = [
|
||||
'excluded' => true,
|
||||
$overrides[self::DateTime($rdate, $event['tzid'])] = [
|
||||
'start' => self::DateTime($rdate, $event['tzid']),
|
||||
];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// adding excludes to the overrides
|
||||
if (!empty($event['recur_type']) && !empty($event['recur_exception']))
|
||||
{
|
||||
foreach ($event['recur_exception'] as $timestamp)
|
||||
{
|
||||
$ex_date = new Api\DateTime($timestamp, Api\DateTime::$server_timezone);
|
||||
if (!empty($event['whole_day']))
|
||||
{
|
||||
$ex_date->setTime(0, 0, 0);
|
||||
}
|
||||
$overrides[self::DateTime($ex_date, $event['tzid'])] = [
|
||||
'excluded' => true,
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
// adding exceptions to the overrides
|
||||
foreach($exceptions as $exception)
|
||||
{
|
||||
|
@ -129,7 +129,7 @@ class calendar_bo
|
||||
MCAL_RECUR_MONTHLY_WDAY => 'Monthly (by day)',
|
||||
MCAL_RECUR_MONTHLY_MDAY => 'Monthly (by date)',
|
||||
MCAL_RECUR_YEARLY => 'Yearly',
|
||||
MCAL_RECUR_RDATE/*calendar_rrule::PERIOD*/ => 'Explicit recurrences',
|
||||
MCAL_RECUR_RDATE => 'Explicit recurrences',
|
||||
);
|
||||
/**
|
||||
* @var array recur_days translates MCAL recur-days to verbose labels
|
||||
|
@ -302,7 +302,7 @@ class calendar_boupdate extends calendar_bo
|
||||
$this->log2file($event2save,$event,$old_event);
|
||||
}
|
||||
// send notifications if the event is in the future
|
||||
if(!$skip_notification && $event['end'] > $this->now_su)
|
||||
if(!$skip_notification && $this->eventInFuture($event))
|
||||
{
|
||||
if ($new_event)
|
||||
{
|
||||
@ -857,13 +857,30 @@ class calendar_boupdate extends calendar_bo
|
||||
* @param array $new_event =null Event after the change
|
||||
* @param int|string $user =0 User/participant who started the notify, default current user
|
||||
* @param array $alarm =null values for "offset", "start", etc.
|
||||
* @parqm boolean $ignore_prefs Ignore the user's preferences about when they want to be notified and send it
|
||||
* @return bool true/false
|
||||
*/
|
||||
function send_update($msg_type, $to_notify, $old_event, $new_event=null, $user=0, array $alarm=null)
|
||||
function send_update($msg_type, $to_notify, $old_event, $new_event=null, $user=0, ?array $alarm=null, $ignore_prefs=false)
|
||||
{
|
||||
Api\Egw::on_shutdown([$this, '_send_update'], func_get_args());
|
||||
}
|
||||
|
||||
/**
|
||||
* Check event is (ending) in the future
|
||||
*
|
||||
* @param array $event
|
||||
* @param int $grace_time
|
||||
* @return bool
|
||||
*/
|
||||
public function eventInFuture(array $event, int $grace_time=10) : bool
|
||||
{
|
||||
if ($event['recur_type'] != MCAL_RECUR_NONE)
|
||||
{
|
||||
return empty($event['recur_enddate']) || $event['recur_enddate'] > $this->now_su - $grace_time;
|
||||
}
|
||||
return $event['end'] > $this->now_su - $grace_time;
|
||||
}
|
||||
|
||||
/**
|
||||
* sends update-messages to certain participants of an event
|
||||
*
|
||||
@ -876,7 +893,7 @@ class calendar_boupdate extends calendar_bo
|
||||
* @parqm boolean $ignore_prefs Ignore the user's preferences about when they want to be notified and send it
|
||||
* @return bool true/false
|
||||
*/
|
||||
function _send_update($msg_type, $to_notify, $old_event, $new_event=null, $user=0, array $alarm=null, $ignore_prefs = false)
|
||||
function _send_update($msg_type, $to_notify, $old_event, $new_event=null, $user=0, ?array $alarm=null, $ignore_prefs = false)
|
||||
{
|
||||
//error_log(__METHOD__."($msg_type, ".json_encode($to_notify).", ..., ".json_encode($new_event).", ...)");
|
||||
if (!is_array($to_notify))
|
||||
@ -893,9 +910,7 @@ class calendar_boupdate extends calendar_bo
|
||||
}
|
||||
|
||||
// ignore events in the past (give a tolerance of 10 seconds for the script)
|
||||
if($new_event && $this->date2ts($new_event['start']) < ($this->now_su - 10) ||
|
||||
!$new_event && $old_event && $this->date2ts($old_event['start']) < ($this->now_su - 10)
|
||||
)
|
||||
if($new_event && !$this->eventInFuture($new_event) || !$new_event && $old_event && !$this->eventInFuture($old_event))
|
||||
{
|
||||
error_log(__METHOD__."($msg_type, ".json_encode($to_notify).", ..., ".json_encode($new_event).", ...) --> ignoring event in the past: start=".
|
||||
date('Y-m-d H:i:s', ($new_event ?: $old_event)['start'])." < ".date('Y-m-d H:i:s', $this->now_su-10));
|
||||
@ -982,6 +997,10 @@ class calendar_boupdate extends calendar_bo
|
||||
$enddate = new Api\DateTime($event['end'], new DateTimeZone($user_prefs['common']['tz']));
|
||||
$modified = new Api\DateTime($event['modified'], new DateTimeZone($user_prefs['common']['tz']));
|
||||
if ($old_event) $olddate = new Api\DateTime($old_event['start'], new DateTimeZone($user_prefs['common']['tz']));
|
||||
$rdates = array_map(static function($rdate) use ($user_prefs)
|
||||
{
|
||||
return new Api\DateTime($rdate, new DateTimeZone($user_prefs['common']['tz']));
|
||||
}, $event['recur_rdates']);
|
||||
|
||||
//error_log(__METHOD__."() date_default_timezone_get()=".date_default_timezone_get().", user-timezone=".Api\DateTime::$user_timezone->getName().", startdate=".$startdate->format().", enddate=".$enddate->format().", updated=".$modified->format().", olddate=".($olddate ? $olddate->format() : ''));
|
||||
$owner_prefs = $ics = null;
|
||||
@ -1114,17 +1133,20 @@ class calendar_boupdate extends calendar_bo
|
||||
// Set dates:
|
||||
// $details in "preference" format, $cleared_event as DateTime so calendar_ical->exportVCal() gets
|
||||
// the times right, since it assumes a timestamp is in server time
|
||||
$startdate->setTimezone($timezone);
|
||||
$cleared_event['start'] = $startdate->setTimezone($timezone);
|
||||
$details['startdate'] = $startdate->format($timeformat);
|
||||
$cleared_event['start'] = $startdate;
|
||||
|
||||
$enddate->setTimezone($timezone);
|
||||
$cleared_event['end'] = $enddate->setTimezone($timezone);
|
||||
$details['enddate'] = $enddate->format($timeformat);
|
||||
$cleared_event['end'] = $enddate;
|
||||
|
||||
$modified->setTimezone($timezone);
|
||||
$cleared_event['updated'] = $modified->setTimezone($timezone);
|
||||
$details['updated'] = $modified->format($timeformat) . ', ' . Api\Accounts::username($event['modifier']);
|
||||
$cleared_event['updated'] = $modified;
|
||||
|
||||
// we also need to "fix" timezone for rdates, to not get wrong times!
|
||||
$cleared_event['recur_rdates'] = array_map(static function ($rdate) use ($timezone)
|
||||
{
|
||||
return $rdate->setTimezone($timezone);
|
||||
}, $rdates);
|
||||
|
||||
// Current date doesn't need to go into the cleared event, just for details
|
||||
$date->setTimezone($timezone);
|
||||
@ -1404,7 +1426,7 @@ class calendar_boupdate extends calendar_bo
|
||||
$this->check_reset_statuses($event, $old_event);
|
||||
|
||||
// set recur-enddate/range-end to real end-date of last recurrence
|
||||
if (!empty($event['recur_type']) && (!empty($event['recur_enddate']) || $event['recur_type'] == calendar_rrule::PERIOD) && $event['start'])
|
||||
if (!empty($event['recur_type']) && (!empty($event['recur_enddate']) || $event['recur_type'] == calendar_rrule::RDATE) && $event['start'])
|
||||
{
|
||||
$event['recur_enddate'] = new Api\DateTime($event['recur_enddate'], calendar_timezones::DateTimeZone($event['tzid']));
|
||||
$event['recur_enddate']->setTime(23,59,59);
|
||||
@ -2064,7 +2086,7 @@ class calendar_boupdate extends calendar_bo
|
||||
$event_arr = $this->event2array($event);
|
||||
foreach($event_arr as $key => $val)
|
||||
{
|
||||
if ($key == 'recur_type') $key = 'repetition';
|
||||
if ($key == 'recur_type') $details['repetition'] = $val['data'];
|
||||
$details[$key] = $val['data'];
|
||||
}
|
||||
$details['participants'] = $details['participants'] ? implode("\n",$details['participants']) : '';
|
||||
|
@ -222,6 +222,7 @@ class calendar_ical extends calendar_boupdate
|
||||
'ORGANIZER' => 'owner',
|
||||
'RRULE' => 'recur_type',
|
||||
'EXDATE' => 'recur_exception',
|
||||
'RDATE' => 'recur_rdates',
|
||||
'PRIORITY' => 'priority',
|
||||
'TRANSP' => 'non_blocking',
|
||||
'CATEGORIES' => 'category',
|
||||
@ -630,8 +631,8 @@ class calendar_ical extends calendar_boupdate
|
||||
case 'RRULE':
|
||||
if ($event['recur_type'] == MCAL_RECUR_NONE) break; // no recuring event
|
||||
$rriter = calendar_rrule::event2rrule($event, false, $tzid);
|
||||
$rrule = $rriter->generate_rrule($version);
|
||||
if ($event['recur_enddate'])
|
||||
if (!($rrule = $rriter->generate_rrule($version))) break; // no recurring event (with rrule)
|
||||
if (isset($rrule['UNTIL']))
|
||||
{
|
||||
if (!$tzid || $version != '1.0')
|
||||
{
|
||||
@ -653,7 +654,7 @@ class calendar_ical extends calendar_boupdate
|
||||
}
|
||||
if ($version == '1.0')
|
||||
{
|
||||
if ($event['recur_enddate'] && $tzid)
|
||||
if (isset($rrule['UNTIL']) && $tzid)
|
||||
{
|
||||
$rrule['UNTIL'] = self::getDateTime($rrule['UNTIL'],$tzid);
|
||||
}
|
||||
@ -670,24 +671,25 @@ class calendar_ical extends calendar_boupdate
|
||||
break;
|
||||
|
||||
case 'EXDATE':
|
||||
case 'RDATE':
|
||||
if ($event['recur_type'] == MCAL_RECUR_NONE) break;
|
||||
if (!empty($event['recur_exception']))
|
||||
if (!empty($event[$egwFieldName]))
|
||||
{
|
||||
if (empty($event['whole_day']))
|
||||
{
|
||||
foreach ($event['recur_exception'] as $key => $timestamp)
|
||||
foreach ($event[$egwFieldName] as $key => $timestamp)
|
||||
{
|
||||
// current Horde_Icalendar 2.1.4 exports EXDATE always in UTC, postfixed with a Z :(
|
||||
// so if we set a timezone here, we have to remove the Z, see the hack at the end of this method
|
||||
// Apple calendar on OS X 10.11.4 uses a timezone, so does Horde eg. for Recurrence-ID
|
||||
$ex_date = new Api\DateTime($timestamp, Api\DateTime::$server_timezone);
|
||||
$event['recur_exception'][$key] = self::getDateTime($ex_date->format('ts') + $ex_date->getOffset(), $tzid, $parameters['EXDATE']);
|
||||
$event[$egwFieldName][$key] = self::getDateTime($ex_date->format('ts') + $ex_date->getOffset(), $tzid, $parameters[$icalFieldName]);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// use 'DATE' instead of 'DATE-TIME' on whole day events
|
||||
foreach ($event['recur_exception'] as $id => $timestamp)
|
||||
foreach ($event[$egwFieldName] as $id => $timestamp)
|
||||
{
|
||||
$time = new Api\DateTime($timestamp,Api\DateTime::$server_timezone);
|
||||
$time->setTimezone(self::$tz_cache[$event['tzid']]);
|
||||
@ -698,10 +700,10 @@ class calendar_ical extends calendar_boupdate
|
||||
'mday' => $arr['day'],
|
||||
);
|
||||
}
|
||||
$event['recur_exception'] = $days;
|
||||
if ($version != '1.0') $parameters['EXDATE']['VALUE'] = 'DATE';
|
||||
$event[$egwFieldName] = $days;
|
||||
if ($version != '1.0') $parameters[$icalFieldName]['VALUE'] = 'DATE';
|
||||
}
|
||||
$vevent->setAttribute('EXDATE', $event['recur_exception'], $parameters['EXDATE']);
|
||||
$vevent->setAttribute($icalFieldName, $event[$egwFieldName], $parameters[$icalFieldName]);
|
||||
}
|
||||
break;
|
||||
|
||||
@ -1105,9 +1107,9 @@ class calendar_ical extends calendar_boupdate
|
||||
"()\n".array2string($retval)."\n",3,$this->logfile);
|
||||
}
|
||||
|
||||
// hack to fix iCalendar exporting EXDATE always postfixed with a Z
|
||||
// hack to fix iCalendar exporting EXDATE|RDATE always postfixed with a Z
|
||||
// EXDATE can have multiple values and therefore be folded into multiple lines
|
||||
return preg_replace_callback("/\nEXDATE;TZID=[^:]+:[0-9TZ \r\n,]+/", function($matches)
|
||||
return preg_replace_callback("/\n(EXDATE|RDATE);TZID=[^:]+:[0-9TZ \r\n,]+/", static function($matches)
|
||||
{
|
||||
return preg_replace('/([0-9 ])Z/', '$1', $matches[0]);
|
||||
}, $retval);
|
||||
@ -2179,6 +2181,7 @@ class calendar_ical extends calendar_boupdate
|
||||
'recur_data' => 'recur_data',
|
||||
'recur_enddate' => 'recur_enddate',
|
||||
'recur_exception' => 'recur_exception',
|
||||
'recur_rdates' => 'recur_rdates',
|
||||
'title' => 'title',
|
||||
'alarm' => 'alarm',
|
||||
'whole_day' => 'whole_day',
|
||||
@ -2764,21 +2767,19 @@ class calendar_ical extends calendar_boupdate
|
||||
$hour = date('H', $vcardData['start']);
|
||||
$minutes = date('i', $vcardData['start']);
|
||||
$seconds = date('s', $vcardData['start']);
|
||||
if($attributes['params']['VALUE'] == 'PERIOD')
|
||||
$vcardData['recur_type'] = calendar_rrule::RDATE;
|
||||
$vcardData['recur_rdates'] = [];
|
||||
foreach($attributes['values'] as $date)
|
||||
{
|
||||
$vcardData['recur_type'] = calendar_rrule::PERIOD;
|
||||
$vcardData['recur_rdates'] = [];
|
||||
foreach($attributes['values'] as $date)
|
||||
{
|
||||
$vcardData['recur_rdates'][] = mktime(
|
||||
$hour,
|
||||
$minutes,
|
||||
$seconds,
|
||||
$date['month'],
|
||||
$date['mday'],
|
||||
$date['year']
|
||||
);
|
||||
}
|
||||
// ToDo: use $date['period'], if set, to allow a different duration than end- - start-time
|
||||
$vcardData['recur_rdates'][] = mktime(
|
||||
$date['hour'] ?? $hour,
|
||||
$date['minute'] ?? $minutes,
|
||||
$date['second'] ?? $seconds,
|
||||
$date['month'],
|
||||
$date['mday'],
|
||||
$date['year']
|
||||
);
|
||||
}
|
||||
break;
|
||||
case 'EXDATE': // current Horde_Icalendar returns dates, no timestamps
|
||||
|
@ -68,10 +68,10 @@ class calendar_rrule implements Iterator
|
||||
/**
|
||||
* RDATE: date or period (a list of dates, instead of a RRULE)
|
||||
*/
|
||||
const PERIOD = 9;
|
||||
const RDATE = 9;
|
||||
|
||||
/**
|
||||
* Translate recure types to labels
|
||||
* Translate recurrence types to labels
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
@ -82,11 +82,11 @@ class calendar_rrule implements Iterator
|
||||
self::MONTHLY_WDAY => 'Monthly (by day)',
|
||||
self::MONTHLY_MDAY => 'Monthly (by date)',
|
||||
self::YEARLY => 'Yearly',
|
||||
self::PERIOD => 'By date or period'
|
||||
self::RDATE => 'Explicit recurrences',
|
||||
);
|
||||
|
||||
/**
|
||||
* @var array $recur_egw2ical_2_0 converstaion of egw recur-type => ical FREQ
|
||||
* @var array $recur_egw2ical_2_0 conversation of egw recur-type => ical RULE;FREQ
|
||||
*/
|
||||
static private $recur_egw2ical_2_0 = array(
|
||||
self::DAILY => 'DAILY',
|
||||
@ -96,11 +96,11 @@ class calendar_rrule implements Iterator
|
||||
self::YEARLY => 'YEARLY',
|
||||
self::HOURLY => 'HOURLY',
|
||||
self::MINUTELY => 'MINUTELY',
|
||||
self::PERIOD => 'PERIOD'
|
||||
self::RDATE => 'RDATE',
|
||||
);
|
||||
|
||||
/**
|
||||
* @var array $recur_egw2ical_1_0 converstaion of egw recur-type => ical FREQ
|
||||
* @var array $recur_egw2ical_1_0 conversation of egw recur-type => ical FREQ
|
||||
*/
|
||||
static private $recur_egw2ical_1_0 = array(
|
||||
self::DAILY => 'D',
|
||||
@ -143,10 +143,10 @@ class calendar_rrule implements Iterator
|
||||
public $monthly_bymonthday;
|
||||
|
||||
/**
|
||||
* Period list
|
||||
* @var
|
||||
* Recurrence dates
|
||||
* @var \DateTime[]
|
||||
*/
|
||||
public $period = [];
|
||||
public $rdates = [];
|
||||
|
||||
/**
|
||||
* Enddate of recurring event or null, if not ending
|
||||
@ -276,7 +276,7 @@ class calendar_rrule implements Iterator
|
||||
$this->time = $time instanceof Api\DateTime ? $time : new Api\DateTime($time);
|
||||
|
||||
if(!in_array($type, array(self::NONE, self::DAILY, self::WEEKLY, self::MONTHLY_MDAY, self::MONTHLY_WDAY,
|
||||
self::YEARLY, self::HOURLY, self::MINUTELY, self::PERIOD)))
|
||||
self::YEARLY, self::HOURLY, self::MINUTELY, self::RDATE)))
|
||||
{
|
||||
throw new Api\Exception\WrongParameter(__METHOD__."($time,$type,$interval,$enddate,$weekdays,...) type $type is NOT valid!");
|
||||
}
|
||||
@ -326,22 +326,22 @@ class calendar_rrule implements Iterator
|
||||
$this->exceptions_objs = $exceptions;
|
||||
}
|
||||
$this->enddate = $enddate;
|
||||
if($type == self::PERIOD)
|
||||
if($type == self::RDATE)
|
||||
{
|
||||
foreach($rdates as $rdate)
|
||||
{
|
||||
$rdate->setTimezone($this->time->getTimezone());
|
||||
$this->period[] = $rdate;
|
||||
$this->rdates[] = $rdate;
|
||||
}
|
||||
// if startdate is neither in the rdates, nor the exceptions --> prepend it to rdates
|
||||
if (!in_array($this->time, $this->period) && !in_array($this->time, $this->exceptions_objs))
|
||||
if (!in_array($this->time, $this->rdates) && !in_array($this->time, $this->exceptions_objs))
|
||||
{
|
||||
array_unshift($this->period, clone($this->time));
|
||||
array_unshift($this->rdates, clone($this->time));
|
||||
}
|
||||
$enddate = clone(count($this->period) ? end($this->period) : $this->time);
|
||||
$enddate = clone(count($this->rdates) ? end($this->rdates) : $this->time);
|
||||
// Make sure to include the last date as valid
|
||||
$enddate->modify('+1 second');
|
||||
reset($this->period);
|
||||
reset($this->rdates);
|
||||
}
|
||||
// no recurrence --> current date is enddate
|
||||
if ($type == self::NONE)
|
||||
@ -502,8 +502,8 @@ class calendar_rrule implements Iterator
|
||||
case self::MINUTELY:
|
||||
$this->current->modify($this->interval.' minute');
|
||||
break;
|
||||
case self::PERIOD:
|
||||
if (($next = next($this->period)))
|
||||
case self::RDATE:
|
||||
if (($next = next($this->rdates)))
|
||||
{
|
||||
$this->current->setDate($next->format('Y'), $next->format('m'), $next->format('d'));
|
||||
$this->current->setTime($next->format('H'), $next->format('i'), $next->format('s'), 0);
|
||||
@ -601,9 +601,9 @@ class calendar_rrule implements Iterator
|
||||
*/
|
||||
public function rewind(): void
|
||||
{
|
||||
if ($this->type == self::PERIOD)
|
||||
if ($this->type == self::RDATE)
|
||||
{
|
||||
$this->current = $this->period ? clone reset($this->period) : null;
|
||||
$this->current = $this->rdates ? clone reset($this->rdates) : null;
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -696,13 +696,18 @@ class calendar_rrule implements Iterator
|
||||
$str_extra[] = ($this->monthly_byday_num == -1 ? lang('last') : $this->monthly_byday_num.'.').' '.implode(', ',$repeat_days);
|
||||
}
|
||||
break;
|
||||
|
||||
case self::RDATE:
|
||||
$str_extra = array_map(static function (DateTime $rdate)
|
||||
{
|
||||
return Api\DateTime::server2user($rdate, '');
|
||||
}, $this->rdates);
|
||||
break;
|
||||
}
|
||||
if($this->interval > 1)
|
||||
if($this->interval > 1 && $this->type != self::RDATE)
|
||||
{
|
||||
$str_extra[] = lang('Interval').': '.$this->interval;
|
||||
}
|
||||
if ($this->enddate)
|
||||
if ($this->enddate && $this->type != self::RDATE)
|
||||
{
|
||||
if ($this->enddate->getTimezone()->getName() != Api\DateTime::$user_timezone->getName())
|
||||
{
|
||||
@ -733,7 +738,7 @@ class calendar_rrule implements Iterator
|
||||
$repeat_days = array();
|
||||
$rrule = array();
|
||||
|
||||
if ($this->type == self::NONE) return false; // no recuring event
|
||||
if ($this->type == self::NONE || $this->type == self::RDATE) return false; // no recurring event (with RRULE)
|
||||
|
||||
if ($version == '1.0')
|
||||
{
|
||||
@ -792,13 +797,6 @@ class calendar_rrule implements Iterator
|
||||
$rrule['BYDAY'] = $this->monthly_byday_num .
|
||||
strtoupper(substr($this->time->format('l'),0,2));
|
||||
break;
|
||||
case self::PERIOD:
|
||||
$period = [];
|
||||
foreach($this->period as $date)
|
||||
{
|
||||
$period[] = $date->format("Ymd\THms\Z");
|
||||
}
|
||||
$rrule['PERIOD'] = implode(',', $period);
|
||||
}
|
||||
if ($this->interval > 1)
|
||||
{
|
||||
@ -979,7 +977,7 @@ class calendar_rrule implements Iterator
|
||||
'recur_enddate' => $this->enddate ? $this->enddate->format('ts') : null,
|
||||
'recur_data' => $this->weekdays,
|
||||
'recur_exception' => $this->exceptions,
|
||||
'recur_rdates' => $this->period,
|
||||
'recur_rdates' => $this->rdates,
|
||||
);
|
||||
}
|
||||
|
||||
@ -987,7 +985,7 @@ class calendar_rrule implements Iterator
|
||||
* Shift a recurrence rule to a new timezone
|
||||
*
|
||||
* @param array $event recurring event
|
||||
* @param DateTime/string starttime of the event (in servertime)
|
||||
* @param DateTime|string $starttime of the event (in servertime)
|
||||
* @param string $to_tz new timezone
|
||||
*/
|
||||
public static function rrule2tz(array &$event,$starttime,$to_tz)
|
||||
|
@ -425,7 +425,7 @@ class calendar_so
|
||||
$this->db->update($this->cal_table, array('cal_uid' => $event['uid']),
|
||||
array('cal_id' => $event['id']),__LINE__,__FILE__,'calendar');
|
||||
}
|
||||
if (!(int)$recur_date && !empty($event['recur_type']))
|
||||
if (!(int)$recur_date && !empty($event['recur_type']) || $event['recur_type'] == MCAL_RECUR_RDATE)
|
||||
{
|
||||
foreach($this->db->select($this->dates_table, 'cal_id,cal_start,recur_exception', [
|
||||
'cal_id' => $ids,
|
||||
|
@ -3698,7 +3698,8 @@ class calendar_uiforms extends calendar_ui
|
||||
$this->setup_participants($event, $content, $sel_options, $readonlys,$preserve,true);
|
||||
$content = array_merge($event, $content);
|
||||
|
||||
$readonlys = [];
|
||||
// disable notifying yourself, as it is ignored anyway and user is only confused, why no notification is send
|
||||
$readonlys = ['participants[notify]['.$GLOBALS['egw_info']['user']['account_id'].']' => true];
|
||||
|
||||
$etpl = new Etemplate('calendar.notify_dialog');
|
||||
$preserve = $content;
|
||||
|
@ -1422,6 +1422,7 @@ export class CalendarApp extends EgwApp
|
||||
addRdate.set_disabled(recurType.value != 9);
|
||||
recurRdate.set_disabled(recurType.value != 9);
|
||||
this.et2.getWidgetById('recur_enddate')?.set_disabled(recurType.value == 9);
|
||||
this.et2.getWidgetById('recur_interval')?.set_disabled(recurType.value == 9);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -712,6 +712,7 @@ you are not allowed to book the resource selected: calendar de Sie sind nicht be
|
||||
you are not invited to that event! calendar de Sie sind zu diesem Termin nicht eingeladen!
|
||||
you attempt to mail a meetingrequest to the recipients above. depending on the client this mail is opened with, the recipient may or may not see the mailbody below, but only see the meeting request attached. calendar de Sie sind im Begriff eine Terminanfrage an die oben eingetragenen Empfänger zu versenden.
|
||||
you can either set a year or a occurrence, not both !!! calendar de Sie können nur entweder das Jahr oder die Wiederholung angeben, nicht beides!
|
||||
you can only notify other users, not yourself! calendar de Sie können nur andere Benutzer benachrichtigen, nicht sich selbst!
|
||||
you can only set a year or a occurrence !!! calendar de Sie können nur ein Jahr oder eine Wiederholung angeben!
|
||||
you do not have permission to read this record! calendar de Sie haben keine Berechtigung diesen Eintrag zu lesen!
|
||||
you have a meeting scheduled for %1 calendar de Sie haben einen Termin am %1
|
||||
|
@ -712,6 +712,7 @@ you are not allowed to book the resource selected: calendar en You are not allow
|
||||
you are not invited to that event! calendar en You are not invited to that event!
|
||||
you attempt to mail a meetingrequest to the recipients above. depending on the client this mail is opened with, the recipient may or may not see the mailbody below, but only see the meeting request attached. calendar en You attempt to mail a meetingrequest to the recipients above. Depending on the client this mail is opened with, the recipient may or may not see the message below, but only see the meeting request attached.
|
||||
you can either set a year or a occurrence, not both !!! calendar en You can either set a year or occurrence, not both!
|
||||
you can only notify other users, not yourself! calendar en You can only notify other users, not yourself!
|
||||
you can only set a year or a occurrence !!! calendar en You can only set a year or occurrence!
|
||||
you do not have permission to read this record! calendar en You do not have permission to read this record!
|
||||
you have a meeting scheduled for %1 calendar en You have a meeting scheduled for %1
|
||||
|
@ -50,7 +50,7 @@
|
||||
<et2-description id="${row}[title]" noLang="1"></et2-description>
|
||||
<et2-description id="${row}[role_label]"></et2-description>
|
||||
<et2-select id="${row}[status]" readonly="true"></et2-select>
|
||||
<et2-checkbox align="center" label="Notify" id="notify[$row_cont[delete_id]]"></et2-checkbox>
|
||||
<et2-checkbox align="right" label="Notify" id="notify[$row_cont[delete_id]]" statustext="You can only notify other users, not yourself!"></et2-checkbox>
|
||||
</row>
|
||||
</rows>
|
||||
</grid>
|
||||
|
@ -1404,7 +1404,7 @@ class mail_compose
|
||||
$attachment_block = '<fieldset class="attachments mceNonEditable"><legend>Download attachments</legend>' . lang('Attachments') . '</fieldset>';
|
||||
if($content['is_html'] && strpos($content['mail_htmltext'], $attachment_block) == false)
|
||||
{
|
||||
$content['mail_htmltext'] .= $attachment_block;
|
||||
//$content['mail_htmltext'] .= $attachment_block;
|
||||
}
|
||||
foreach($content['attachments'] as &$attach)
|
||||
{
|
||||
|
@ -3977,6 +3977,7 @@ app.classes.mail = AppJS.extend(
|
||||
}
|
||||
if (_file_count && !jQuery.isEmptyObject(_event.data.getValue()))
|
||||
{
|
||||
this.addAttachmentPlaceholder();
|
||||
var widget = _event.data;
|
||||
this.et2_obj.submit();
|
||||
}
|
||||
@ -4023,6 +4024,7 @@ app.classes.mail = AppJS.extend(
|
||||
if (jQuery.isEmptyObject(_widget)) return;
|
||||
if (!jQuery.isEmptyObject(_widget.getValue()))
|
||||
{
|
||||
this.addAttachmentPlaceholder();
|
||||
this.et2_obj.submit();
|
||||
}
|
||||
},
|
||||
@ -5087,6 +5089,7 @@ app.classes.mail = AppJS.extend(
|
||||
(mode == 'share_rw' || mode == 'share_ro') ? 'link' : mode;
|
||||
}
|
||||
this.et2.setArrayMgr('content', content);
|
||||
this.addAttachmentPlaceholder();
|
||||
attachments.set_value({content:content.data.attachments});
|
||||
}
|
||||
},
|
||||
@ -6275,5 +6278,20 @@ app.classes.mail = AppJS.extend(
|
||||
{
|
||||
window.open("mailto:" + _address.value);
|
||||
}
|
||||
},
|
||||
|
||||
addAttachmentPlaceholder: function ()
|
||||
{
|
||||
if (this.et2.getArrayMgr("content").getEntry("is_html"))
|
||||
{
|
||||
// Add link placeholder box
|
||||
const email = this.et2.getWidgetById("mail_htmltext");
|
||||
const placeholder = '<fieldset class="attachments mceNonEditable"><legend>Download attachments</legend>' + this.egw.lang('Attachments') + '</fieldset>';
|
||||
|
||||
if (email && !email.getValue().includes(placeholder))
|
||||
{
|
||||
email.editor.execCommand('mceInsertContent', false, placeholder);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
Loading…
Reference in New Issue
Block a user