mirror of
https://github.com/EGroupware/egroupware.git
synced 2024-12-27 00:58:56 +01:00
* Calendar: adding default alarm for regular or whole-day events, preference is shared with CalDAV clients
This commit is contained in:
parent
bb5b1163cb
commit
f0e391220f
@ -146,6 +146,23 @@ class calendar_bo
|
||||
'OPT-PARTICIPANT' => 'Optional',
|
||||
'NON-PARTICIPANT' => 'None',
|
||||
);
|
||||
/**
|
||||
* Alarm times
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
var $alarms = array(
|
||||
300 => '5 Minutes',
|
||||
600 => '10 Minutes',
|
||||
900 => '15 Minutes',
|
||||
1800 => '30 Minutes',
|
||||
3600 => '1 Hour',
|
||||
7200 => '2 Hours',
|
||||
43200 => '12 Hours',
|
||||
86400 => '1 Day',
|
||||
172800 => '2 Days',
|
||||
604800 => '1 Week',
|
||||
);
|
||||
/**
|
||||
* @var array $resources registered scheduling resources of the calendar (gets cached in the session for performance reasons)
|
||||
*/
|
||||
@ -253,6 +270,34 @@ class calendar_bo
|
||||
$this->categories = new categories($this->user,'calendar');
|
||||
|
||||
$this->customfields = config::get_customfields('calendar');
|
||||
|
||||
foreach($this->alarms as $secs => &$label)
|
||||
{
|
||||
$label = self::secs2label($secs);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate translated label for a given number of seconds
|
||||
*
|
||||
* @param int $secs
|
||||
* @return string
|
||||
*/
|
||||
static public function secs2label($secs)
|
||||
{
|
||||
if ($secs <= 3600)
|
||||
{
|
||||
$label = lang('%1 minutes', $secs/60);
|
||||
}
|
||||
elseif($secs <= 86400)
|
||||
{
|
||||
$label = lang('%1 hours', $secs/3600);
|
||||
}
|
||||
else
|
||||
{
|
||||
$label = lang('%1 days', $secs/86400);
|
||||
}
|
||||
return $label;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -154,7 +154,8 @@ class calendar_hooks
|
||||
{
|
||||
if (!$hook_data['setup']) // does not work on setup time
|
||||
{
|
||||
ExecMethod('calendar.calendar_bo.check_set_default_prefs');
|
||||
$bo = new calendar_bo();
|
||||
$bo->check_set_default_prefs();
|
||||
}
|
||||
$mainscreen = array(
|
||||
'0' => lang('None'),
|
||||
@ -276,7 +277,7 @@ class calendar_hooks
|
||||
}
|
||||
|
||||
$settings = array(
|
||||
array(
|
||||
'1.section' => array(
|
||||
'type' => 'section',
|
||||
'title' => lang('General settings'),
|
||||
'no_lang'=> true,
|
||||
@ -411,7 +412,7 @@ class calendar_hooks
|
||||
'admin' => False,
|
||||
'forced' => 'all',
|
||||
),
|
||||
array(
|
||||
'2.section' => array(
|
||||
'type' => 'section',
|
||||
'title' => lang('appointment settings'),
|
||||
'no_lang'=> true,
|
||||
@ -429,6 +430,47 @@ class calendar_hooks
|
||||
'admin' => False,
|
||||
'default'=> 60,
|
||||
),
|
||||
'default-alarm' => array(
|
||||
'type' => 'select',
|
||||
'label' => 'Default alarm for regular events',
|
||||
'name' => 'default-alarm',
|
||||
'values' => isset($bo) ? array(0 => lang('None'))+$bo->alarms : array(),
|
||||
'help' => 'Alarm added automatic to new events before event start-time',
|
||||
'xmlrpc' => True,
|
||||
'admin' => False,
|
||||
'default' => 0,
|
||||
),
|
||||
'default-alarm-wholeday' => array(
|
||||
'type' => 'select',
|
||||
'label' => 'Default alarm for whole-day events',
|
||||
'name' => 'default-alarm-wholeday',
|
||||
'values' => isset($bo) ? array(0 => lang('None'))+$bo->alarms : array(),
|
||||
'help' => lang('Alarm added automatic to new events before event start-time').' ('.lang('Midnight').')',
|
||||
'xmlrpc' => True,
|
||||
'admin' => False,
|
||||
'default' => 0,
|
||||
)
|
||||
);
|
||||
if (isset($bo)) // add custom time-spans set by CalDAV clients, not in our prefs
|
||||
{
|
||||
$prefs = $GLOBALS['egw_info']['user']['preferences']['calendar'];
|
||||
$data = array(
|
||||
'prefs' => &$prefs, // use reference to get preference value back
|
||||
'preprocess' => true,
|
||||
'type' => 'user',
|
||||
);
|
||||
self::verify_settings($data);
|
||||
foreach(array('default-alarm', 'default-alarm-wholeday') as $name)
|
||||
{
|
||||
$value = $prefs[$name];
|
||||
if ($value > 0 && !isset($bo->alarms[$value]))
|
||||
{
|
||||
$settings[$name]['values'][$value] = calendar_bo::secs2label($value);
|
||||
ksort($settings[$name]['values']);
|
||||
}
|
||||
}
|
||||
}
|
||||
$settings += array(
|
||||
'defaultresource_sel' => array(
|
||||
'type' => 'select',
|
||||
'label' => 'default type of resources selection',
|
||||
@ -458,7 +500,7 @@ class calendar_hooks
|
||||
'xmlrpc' => True,
|
||||
'admin' => False,
|
||||
),
|
||||
array(
|
||||
'3.section' => array(
|
||||
'type' => 'section',
|
||||
'title' => lang('notification settings'),
|
||||
'no_lang'=> true,
|
||||
@ -579,7 +621,7 @@ class calendar_hooks
|
||||
'xmlrpc' => True,
|
||||
'admin' => False,
|
||||
),
|
||||
array(
|
||||
'4.section' => array(
|
||||
'type' => 'section',
|
||||
'title' => lang('Data exchange settings'),
|
||||
'no_lang'=> true,
|
||||
@ -696,6 +738,87 @@ class calendar_hooks
|
||||
return $settings;
|
||||
}
|
||||
|
||||
/**
|
||||
* Verify settings hook called to generate errors about settings used here to store default alarms in CalDAV prefs
|
||||
*
|
||||
* @param array $data
|
||||
* array $data['prefs']
|
||||
* string $data['type'] 'user', 'default' or 'forced'
|
||||
* boolean $data['preprocess'] true data just shown to user, false: data stored by user
|
||||
*/
|
||||
public static function verify_settings(array $data)
|
||||
{
|
||||
//error_log(__METHOD__."(".array2string($data).")");
|
||||
// caldav perfs are always user specific and cant by switched off
|
||||
if ($data['type'] == 'user')
|
||||
{
|
||||
$account_lid = $GLOBALS['egw_info']['user']['account_lid'];
|
||||
foreach(array(
|
||||
'default-alarm' => 'default-alarm-vevent-datetime:/'.$account_lid.'/:urn:ietf:params:xml:ns:caldav',
|
||||
'default-alarm-wholeday' => 'default-alarm-vevent-date:/'.$account_lid.'/:urn:ietf:params:xml:ns:caldav',
|
||||
) as $name => $dav)
|
||||
{
|
||||
$pref =& $GLOBALS['egw_info']['user']['preferences']['groupdav'][$dav];
|
||||
if (true) $pref = str_replace("\r", '', $pref); // remove CR messing up multiline preg_match
|
||||
$val = $data['prefs'][$name];
|
||||
//error_log(__METHOD__."() groupdav[$dav]=$pref, calendar[$name]=$val");
|
||||
|
||||
if ($data['preprocess']) // showing preferences
|
||||
{
|
||||
if ((string)$data['prefs'][$name] === '') // no calendar pref --> read value from caldav
|
||||
{
|
||||
$matches = null;
|
||||
if (preg_match('/^ACTION:NONE$/i', $pref))
|
||||
{
|
||||
$data['prefs'][$name] = '0';
|
||||
}
|
||||
elseif (preg_match('/^TRIGGER:-PT(\d+(M|H|D))$/mi', $pref, $matches))
|
||||
{
|
||||
static $factors = array(
|
||||
'M' => 60,
|
||||
'H' => 3600,
|
||||
'D' => 86400,
|
||||
);
|
||||
$factor = $factors[strtoupper($matches[2])];
|
||||
$data['prefs'][$name] = $factor*(int)$matches[1];
|
||||
}
|
||||
else
|
||||
{
|
||||
$data['prefs'][$name] = '0';
|
||||
}
|
||||
error_log(__METHOD__."() setting $name={$data['prefs'][$name]} from $dav='$pref'");
|
||||
}
|
||||
}
|
||||
else // storing preferences
|
||||
{
|
||||
if (empty($pref) || !preg_match('/^TRIGGER:/m', $pref))
|
||||
{
|
||||
$pref = 'BEGIN:VALARM
|
||||
TRIGGER:-PT1H
|
||||
ATTACH;VALUE=URI:Basso
|
||||
ACTION:AUDIO
|
||||
END:VALARM';
|
||||
}
|
||||
if (!$val)
|
||||
{
|
||||
$pref = preg_replace('/^ACTION:.*$/m', 'ACTION:NONE', $pref);
|
||||
}
|
||||
elseif ($val < 3600)
|
||||
{
|
||||
$pref = preg_replace('/^TRIGGER:.*$/m', 'TRIGGER:-PT'.number_format($val/60, 0).'M', $pref);
|
||||
}
|
||||
else
|
||||
{
|
||||
$pref = preg_replace('/^TRIGGER:.*$/m', 'TRIGGER:-PT'.number_format($val/3600, 0).'H', $pref);
|
||||
}
|
||||
$GLOBALS['egw']->preferences->add('groupdav', $dav, $pref, 'user');
|
||||
error_log(__METHOD__."() storing $name=$val --> $dav='$pref'");
|
||||
}
|
||||
}
|
||||
$GLOBALS['egw']->preferences->save_repository();
|
||||
}
|
||||
}
|
||||
|
||||
public static function config_validate()
|
||||
{
|
||||
$GLOBALS['egw_info']['server']['found_validation_hook'] = array('calendar_purge_old');
|
||||
|
@ -326,7 +326,7 @@ class calendar_uiforms extends calendar_ui
|
||||
foreach($this->bo->resources as $type => $data)
|
||||
{
|
||||
if ($data['app'] == $app) break;
|
||||
}
|
||||
}
|
||||
$uid = $this->bo->resources[$type]['app'] == $app ? $type.$id : false;
|
||||
if ($app == 'home-accounts')
|
||||
{
|
||||
@ -891,7 +891,7 @@ class calendar_uiforms extends calendar_ui
|
||||
case 'add_alarm':
|
||||
$time = ($content['actual_date'] ? $content['actual_date'] : $content['start']);
|
||||
$offset = $time - $content['new_alarm']['date'];
|
||||
|
||||
|
||||
if ($event['recur_type'] != MCAL_RECUR_NONE &&
|
||||
($next_occurrence = $this->bo->read($event['id'], $this->bo->now_su + $offset, true)) &&
|
||||
$time < $next_occurrence['start'])
|
||||
@ -1125,8 +1125,7 @@ class calendar_uiforms extends calendar_ui
|
||||
'status' => $this->bo->verbose_status,
|
||||
'duration' => $this->durations,
|
||||
'role' => $this->bo->roles,
|
||||
'new_alarm[options]' =>array(300 => lang('5 Minutes'), 600 => lang('10 Minutes'), 900 => lang('15 Minutes'), 1800 => lang('30 Minutes'), 3600 => lang('1 Hour'), 7200 => lang('2 Hours'),
|
||||
43200 => lang('12 Hours'), 86400 => lang('1 Day'), 172800 => lang('2 Days'), 604800 => lang('1 Week'), 0 => lang('Custom')),
|
||||
'new_alarm[options]' => $this->bo->alarms+array(0 => lang('Custom')),
|
||||
'before_after'=>array(0 => lang('Before'), 1 => lang('After')),
|
||||
'action' => array(
|
||||
'copy' => array('label' => 'Copy', 'title' => 'Copy this event'),
|
||||
|
@ -1,6 +1,9 @@
|
||||
%1 %2 in %3 calendar de %1 %2 im %3
|
||||
%1 days calendar de %1 Tage
|
||||
%1 event(s) %2 calendar de %1 Termin(e) %2
|
||||
%1 event(s) %2, %3 failed because of insufficent rights !!! calendar de %1 Termin(e) %2, %3 wegen fehlender Rechte !!!
|
||||
%1 hours calendar de %1 Stunden
|
||||
%1 minutes calendar de %1 Minuten
|
||||
%1 participants removed because of missing invite grants calendar de %1 Teilnehmer entfernt wegen fehlender Einladungsrechte
|
||||
%1 records imported calendar de %1 Datensätze importiert
|
||||
%1 records read (not yet imported, you may go back and uncheck test import) calendar de %1 Datensätze gelesen (noch nicht importiert, Sie können zurück gehen und Test Import ausschalten)
|
||||
@ -33,6 +36,7 @@ after current date calendar de Nach dem aktuellen Datum
|
||||
age: calendar de Alter:
|
||||
alarm calendar de Alarm
|
||||
alarm added calendar de Alarm zugefügt
|
||||
alarm added automatic to new events before event start-time calendar de Der Alarm wird automatisch bei neuen Termin vor dem Startdatum eingefügt
|
||||
alarm deleted calendar de Alarm gelöscht
|
||||
alarm for %1 at %2 in %3 calendar de Alarm für %1 am %2 in %3
|
||||
alarm management calendar de Alarm Management
|
||||
@ -113,6 +117,7 @@ creator calendar de Ersteller
|
||||
csv calendar de CSV
|
||||
csv-fieldname calendar de CSV-Feldname
|
||||
csv-filename calendar de CSV-Dateiname
|
||||
custom calendar de Benutzerdefiniert
|
||||
custom fields common de Benutzerdefinierte Felder
|
||||
custom_2 common de frei / besetzt
|
||||
daily calendar de Täglich
|
||||
@ -125,6 +130,8 @@ days calendar de Tage
|
||||
days of the week for a weekly repeated event calendar de Wochentage für wöchentlich wiederholten Termin
|
||||
days repeated calendar de wiederholte Tage
|
||||
dayview calendar de Tagesansicht
|
||||
default alarm for regular events calendar de Default-Alarm für normale Termine
|
||||
default alarm for whole-day events calendar de Default-Alarm für ganztägige Termine
|
||||
default appointment length (in minutes) calendar de Standardlänge eines neuen Kalendereintrags (in Minuten)
|
||||
default calendar filter calendar de Standard-Filter des Kalenders
|
||||
default calendar view calendar de Standard-Ansicht des Kalenders
|
||||
@ -314,6 +321,7 @@ maximum available quantity of %1 exceeded! calendar de Maximale Anzahl von %1 er
|
||||
meeting request calendar de Terminanfrage
|
||||
meetingrequest to all participants calendar de Terminanforderung an alle Teilnehmer
|
||||
merge document... calendar de Dokument einfügen...
|
||||
midnight calendar de Mitternacht
|
||||
minutes calendar de Minuten
|
||||
modified calendar de Geändert
|
||||
modifier calendar de Geändert von
|
||||
|
@ -1,6 +1,9 @@
|
||||
%1 %2 in %3 calendar en %1 %2 in %3
|
||||
%1 days calendar en %1 days
|
||||
%1 event(s) %2 calendar en %1 event(s) %2
|
||||
%1 event(s) %2, %3 failed because of insufficent rights !!! calendar en %1 event(s) %2, %3 failed because of insufficient rights!
|
||||
%1 hours calendar en %1 hours
|
||||
%1 minutes calendar en %1 minutes
|
||||
%1 participants removed because of missing invite grants calendar en %1 participants removed because of missing invite grants.
|
||||
%1 records imported calendar en %1 records imported.
|
||||
%1 records read (not yet imported, you may go back and uncheck test import) calendar en %1 records read. Not yet imported, go back and uncheck Test import.
|
||||
@ -33,6 +36,7 @@ after current date calendar en After current date
|
||||
age: calendar en Age:
|
||||
alarm calendar en Alarm
|
||||
alarm added calendar en Alarm added.
|
||||
alarm added automatic to new events before event start-time calendar en Alarm added automatic to new events before event start-time
|
||||
alarm deleted calendar en Alarm deleted.
|
||||
alarm for %1 at %2 in %3 calendar en Alarm for %1 at %2 in %3
|
||||
alarm management calendar en Alarm management
|
||||
@ -113,6 +117,7 @@ creator calendar en Creator
|
||||
csv calendar en CSV
|
||||
csv-fieldname calendar en CSV field name
|
||||
csv-filename calendar en CSV file name
|
||||
custom calendar en Custom
|
||||
custom fields common en Custom fields
|
||||
custom_2 common en Free/Busy
|
||||
daily calendar en Daily
|
||||
@ -125,6 +130,8 @@ days calendar en Days
|
||||
days of the week for a weekly repeated event calendar en Days of the week for a weekly repeated event
|
||||
days repeated calendar en Days repeated
|
||||
dayview calendar en Day view
|
||||
default alarm for regular events calendar en Default alarm for regular events
|
||||
default alarm for whole-day events calendar en Default alarm for whole-day events
|
||||
default appointment length (in minutes) calendar en Default appointment length in minutes
|
||||
default calendar filter calendar en Default calendar filter
|
||||
default calendar view calendar en Default calendar view
|
||||
@ -314,6 +321,7 @@ maximum available quantity of %1 exceeded! calendar en Maximum available quantit
|
||||
meeting request calendar en Meeting request
|
||||
meetingrequest to all participants calendar en Meetingrequest to all participants
|
||||
merge document... calendar en Merge document...
|
||||
midnight calendar en Midnight
|
||||
minutes calendar en Minutes
|
||||
modified calendar en Modified
|
||||
modifier calendar en Modifier
|
||||
|
@ -38,6 +38,7 @@ $setup_info['calendar']['hooks']['admin'] = 'calendar_hooks::admin';
|
||||
$setup_info['calendar']['hooks']['deleteaccount'] = 'calendar.calendar_so.deleteaccount';
|
||||
$setup_info['calendar']['hooks']['home'] = 'calendar_hooks::home';
|
||||
$setup_info['calendar']['hooks']['settings'] = 'calendar_hooks::settings';
|
||||
$setup_info['calendar']['hooks']['verify_settings'] = 'calendar_hooks::verify_settings';
|
||||
$setup_info['calendar']['hooks']['sidebox_menu'] = 'calendar.calendar_ui.sidebox_menu';
|
||||
$setup_info['calendar']['hooks']['search_link'] = 'calendar_hooks::search_link';
|
||||
$setup_info['calendar']['hooks']['config_validate'] = 'calendar_hooks::config_validate';
|
||||
|
@ -140,12 +140,6 @@ class preferences_settings
|
||||
'preferences' : $content['current_app'];
|
||||
egw_framework::includeCSS('preferences','app');
|
||||
|
||||
$sel_options = $readonlys = null;
|
||||
$content = $this->get_content($appname, $type, $sel_options, $readonlys, $preserve['types'], $tpl);
|
||||
$preserve['appname'] = $preserve['old_appname'] = $content['appname'];
|
||||
$preserve['type'] = $preserve['old_type'] = $content['type'];
|
||||
if (isset($old_tab)) $content['tabs'] = $old_tab;
|
||||
|
||||
// if not just saved, call validation before, to be able to show failed validation of current prefs
|
||||
if (!isset($button))
|
||||
{
|
||||
@ -153,6 +147,13 @@ class preferences_settings
|
||||
$msg = $this->process_array($GLOBALS['egw']->preferences->$attribute,
|
||||
(array)$GLOBALS['egw']->preferences->{$attribute}[$appname], $preserve['types'], $appname, $attribute, true);
|
||||
}
|
||||
|
||||
$sel_options = $readonlys = null;
|
||||
$content = $this->get_content($appname, $type, $sel_options, $readonlys, $preserve['types'], $tpl);
|
||||
$preserve['appname'] = $preserve['old_appname'] = $content['appname'];
|
||||
$preserve['type'] = $preserve['old_type'] = $content['type'];
|
||||
if (isset($old_tab)) $content['tabs'] = $old_tab;
|
||||
|
||||
if ($msg) egw_framework::message($msg, $msg_type ? $msg_type : 'error');
|
||||
|
||||
$tpl->exec('preferences.preferences_settings.index', $content, $sel_options, $readonlys, $preserve, 2);
|
||||
@ -250,8 +251,9 @@ class preferences_settings
|
||||
//
|
||||
if(($error .= $GLOBALS['egw']->hooks->single(array(
|
||||
'location' => 'verify_settings',
|
||||
'prefs' => $repository[$appname],
|
||||
'type' => $type
|
||||
'prefs' => &$repository[$appname],
|
||||
'type' => $type,
|
||||
'preprocess' => $only_verify,
|
||||
),
|
||||
$appname
|
||||
)))
|
||||
|
Loading…
Reference in New Issue
Block a user