From fb89b061ba410fd766f042c28cecd065eb86e4de Mon Sep 17 00:00:00 2001 From: Laurent Destailleur <eldy@destailleur.fr> Date: Sun, 22 Jan 2012 02:12:11 +0100 Subject: [PATCH] New: [ task #187 ] Gerer les evenement recurrents dans les imports ical --- ChangeLog | 1 + htdocs/comm/action/class/ical.class.php | 8 +- htdocs/comm/action/index.php | 168 ++++++++++++++++++------ htdocs/core/lib/date.lib.php | 91 ++++++++----- htdocs/core/lib/functions.lib.php | 32 +++-- 5 files changed, 211 insertions(+), 89 deletions(-) diff --git a/ChangeLog b/ChangeLog index b0bb143cd02..06aac38c66e 100644 --- a/ChangeLog +++ b/ChangeLog @@ -24,6 +24,7 @@ For users: - New: task #10606 : more comprehensive message error. - New: task #11278 : Option into point of sale module to add services in list. - New: task #11261 : Add an entry into menu called "New shipment". +- New: [ task #187 ] Gerer les evenement recurrents dans les imports ical - New: Make option MAIN_GENERATE_DOCUMENTS_WITHOUT_VAT available by default. - New: Can build PDF in USLetter format or canada format (change paper size). - New: Can export into Excel 2007 format. diff --git a/htdocs/comm/action/class/ical.class.php b/htdocs/comm/action/class/ical.class.php index bddd4802bc5..e821c4ce84d 100644 --- a/htdocs/comm/action/class/ical.class.php +++ b/htdocs/comm/action/class/ical.class.php @@ -155,11 +155,11 @@ class ical } /** - * Add to $this->ical array one value and key. Type is VTODO, VEVENT, VFREEBUSY, VCALENDAR ... . + * Add to $this->ical array one value and key. * - * @param string $type Type - * @param string $key Key - * @param string $value Value + * @param string $type Type ('VTODO', 'VEVENT', 'VFREEBUSY', 'VCALENDAR'...) + * @param string $key Key ('DTSTART', ...). Note: Field is never 'DTSTART;TZID=...' because ';...' was before removed and added as another property + * @param string $value Value * @return void */ function add_to_array($type, $key, $value) diff --git a/htdocs/comm/action/index.php b/htdocs/comm/action/index.php index 3a316110223..d875269f4ef 100644 --- a/htdocs/comm/action/index.php +++ b/htdocs/comm/action/index.php @@ -42,9 +42,9 @@ $showbirthday = GETPOST("showbirthday","int"); $sortfield = GETPOST("sortfield"); $sortorder = GETPOST("sortorder"); $page = GETPOST("page","int"); -if ($page == -1) { $page = 0 ; } +if ($page == -1) { $page = 0; } $limit = $conf->liste_limit; -$offset = $limit * $page ; +$offset = $limit * $page; if (! $sortorder) $sortorder="ASC"; if (! $sortfield) $sortfield="a.datec"; @@ -73,9 +73,15 @@ $actioncode=GETPOST("actioncode"); $pid=GETPOST("projectid","int")?GETPOST("projectid","int"):0; $status=GETPOST("status"); $maxprint=GETPOST("maxprint"); -if (GETPOST('viewcal')) { $action='show_month'; $day=''; } // View by month -if (GETPOST('viewweek')) { $action='show_week'; $week=($week?$week:date("W")); $day=($day?$day:date("d")); } // View by week -if (GETPOST('viewday')) { $action='show_day'; $day=($day?$day:date("d")); } // View by day +if (GETPOST('viewcal')) { + $action='show_month'; $day=''; +} // View by month +if (GETPOST('viewweek')) { + $action='show_week'; $week=($week?$week:date("W")); $day=($day?$day:date("d")); +} // View by week +if (GETPOST('viewday')) { + $action='show_day'; $day=($day?$day:date("d")); +} // View by day $langs->load("other"); $langs->load("commercial"); @@ -491,18 +497,18 @@ $listofextcals=array(); if (empty($conf->global->AGENDA_DISABLE_EXT) && $conf->global->AGENDA_EXT_NB > 0) { - $i=0; - while($i < $conf->global->AGENDA_EXT_NB) - { - $i++; - $paramkey='AGENDA_EXT_SRC'.$i; - $url=$conf->global->$paramkey; - $paramkey='AGENDA_EXT_NAME'.$i; - $namecal = $conf->global->$paramkey; - $paramkey='AGENDA_EXT_COLOR'.$i; - $colorcal = $conf->global->$paramkey; - if ($url && $namecal) $listofextcals[]=array('src'=>$url,'name'=>$namecal,'color'=>$colorcal); - } + $i=0; + while($i < $conf->global->AGENDA_EXT_NB) + { + $i++; + $paramkey='AGENDA_EXT_SRC'.$i; + $url=$conf->global->$paramkey; + $paramkey='AGENDA_EXT_NAME'.$i; + $namecal = $conf->global->$paramkey; + $paramkey='AGENDA_EXT_COLOR'.$i; + $colorcal = $conf->global->$paramkey; + if ($url && $namecal) $listofextcals[]=array('src'=>$url,'name'=>$namecal,'color'=>$colorcal); + } } if (count($listofextcals)) @@ -516,38 +522,126 @@ if (count($listofextcals)) //print "url=".$url." namecal=".$namecal." colorcal=".$colorcal; $ical=new ical(); $ical->parse($url); + // After this $ical->cal['VEVENT'] contains array of events, $ical->cal['DAYLIGHT'] contains daylight info, $ical->cal['STANDARD'] contains non daylight info, ... + //var_dump($ical->cal); exit; $icalevents=array(); - if (is_array($ical->get_event_list())) $icalevents=array_merge($icalevents,$ical->get_event_list()); - if (is_array($ical->get_freebusy_list())) $icalevents=array_merge($icalevents,$ical->get_freebusy_list()); + if (is_array($ical->get_event_list())) $icalevents=array_merge($icalevents,$ical->get_event_list()); // Add $ical->cal['VEVENT'] + if (is_array($ical->get_freebusy_list())) $icalevents=array_merge($icalevents,$ical->get_freebusy_list()); // Add $ical->cal['VFREEBUSY'] if (count($icalevents)>0) { // Duplicate all repeatable events into new entries + $moreicalevents=array(); foreach($icalevents as $icalevent) { if (is_array($icalevent['RRULE'])) //repeatable event { //if ($event->date_start_in_calendar < $firstdaytoshow) $event->date_start_in_calendar=$firstdaytoshow; //if ($event->date_end_in_calendar > $lastdaytoshow) $event->date_end_in_calendar=$lastdaytoshow; - $datecur=$icalevent['DTSTART']['unixtime']; - if ($icalevent['RRULE']['FREQ']=='WEEKLY') + if ($icalevent['DTSTART;VALUE=DATE']) //fullday event { - $until=dol_stringtotime($icalevent['RRULE']['UNTIL'],1); - + $datecurstart=dol_stringtotime($icalevent['DTSTART;VALUE=DATE'],1); + $datecurend=dol_stringtotime($icalevent['DTEND;VALUE=DATE'],1)-1; // We remove one second to get last second of day } + else if (is_array($icalevent['DTSTART']) && ! empty($icalevent['DTSTART']['unixtime'])) + { + $datecurstart=$icalevent['DTSTART']['unixtime']; + $datecurend=$icalevent['DTEND']['unixtime']; + if (! empty($ical->cal['DAYLIGHT']['DTSTART']) && $datecurstart) + { + //var_dump($ical->cal); + $tmpcurstart=$datecurstart; + $tmpcurend=$datecurend; + $tmpdaylightstart=dol_mktime(0,0,0,1,1,1970,1) + (int) $ical->cal['DAYLIGHT']['DTSTART']; + $tmpdaylightend=dol_mktime(0,0,0,1,1,1970,1) + (int) $ical->cal['STANDARD']['DTSTART']; + //var_dump($tmpcurstart);var_dump($tmpcurend); var_dump($ical->cal['DAYLIGHT']['DTSTART']);var_dump($ical->cal['STANDARD']['DTSTART']); + // Edit datecurstart and datecurend + if ($tmpcurstart >= $tmpdaylightstart && $tmpcurstart < $tmpdaylightend) $datecurstart-=((int) $ical->cal['DAYLIGHT']['TZOFFSETTO'])*36; + else $datecurstart-=((int) $ical->cal['STANDARD']['TZOFFSETTO'])*36; + if ($tmpcurend >= $tmpdaylightstart && $tmpcurstart < $tmpdaylightend) $datecurend-=((int) $ical->cal['DAYLIGHT']['TZOFFSETTO'])*36; + else $datecurend-=((int) $ical->cal['STANDARD']['TZOFFSETTO'])*36; + } + // datecurstart and datecurend are now GMT date + //var_dump($datecurstart); var_dump($datecurend); exit; + } + else + { + // Not a recongized record + dol_syslog("Found a not recognized repeatable record with unknown date start", LOG_ERR); + continue; + } + //print 'xx'.$datecurstart;exit; + + $interval=(empty($icalevent['RRULE']['INTERVAL'])?1:$icalevent['RRULE']['INTERVAL']); + $until=empty($icalevent['RRULE']['UNTIL'])?0:dol_stringtotime($icalevent['RRULE']['UNTIL'],1); + $maxrepeat=empty($icalevent['RRULE']['COUNT'])?0:$icalevent['RRULE']['COUNT']; + if ($until && ($until+($datecurend-$datecurstart)) < $firstdaytoshow) continue; // We discard repeatable event that end before start date to show + if ($datecurstart > $lastdaytoshow) continue; // We discard repeatable event that start after end date to show + $numofevent=0; + while (($datecurstart <= $lastdaytoshow) && (empty($maxrepeat) || ($numofevent < $maxrepeat))) + { + if ($datecurend >= $firstdaytoshow) // We add event + { + $newevent=$icalevent; + unset($newevent['RRULE']); + if ($icalevent['DTSTART;VALUE=DATE']) + { + $newevent['DTSTART;VALUE=DATE']=dol_print_date($datecurstart,'%Y%m%d'); + $newevent['DTEND;VALUE=DATE']=dol_print_date($datecurend+1,'%Y%m%d'); + } + else + { + $newevent['DTSTART']=$datecurstart; + $newevent['DTEND']=$datecurend; + } + $moreicalevents[]=$newevent; + } + // Jump on next occurence + $numofevent++; + $savdatecurstart=$datecurstart; + if ($icalevent['RRULE']['FREQ']=='DAILY') + { + $datecurstart=dol_time_plus_duree($datecurstart, $interval, 'd'); + $datecurend=dol_time_plus_duree($datecurend, $interval, 'd'); + } + if ($icalevent['RRULE']['FREQ']=='WEEKLY') + { + $datecurstart=dol_time_plus_duree($datecurstart, $interval, 'w'); + $datecurend=dol_time_plus_duree($datecurend, $interval, 'w'); + } + elseif ($icalevent['RRULE']['FREQ']=='MONTHLY') + { + $datecurstart=dol_time_plus_duree($datecurstart, $interval, 'm'); + $datecurend=dol_time_plus_duree($datecurend, $interval, 'm'); + } + elseif ($icalevent['RRULE']['FREQ']=='YEARLY') + { + $datecurstart=dol_time_plus_duree($datecurstart, $interval, 'y'); + $datecurend=dol_time_plus_duree($datecurend, $interval, 'y'); + } + // Test to avoid infinite loop ($datecurstart must increase) + if ($savdatecurstart >= $datecurstart) + { + dol_syslog("Found a rule freq ".$icalevent['RRULE']['FREQ']." not managed by dolibarr code. Assume 1 week frequency.", LOG_ERR); + $datecurstart+=3600*24*7; + $datecurend+=3600*24*7; + } + } } } + $icalevents=array_merge($icalevents,$moreicalevents); // Loop on each entry into cal file to know if entry is qualified and add an ActionComm into $eventarray foreach($icalevents as $icalevent) { //print $icalevent['SUMMARY'].'->'.var_dump($icalevent).'<br>';exit; + if (! empty($icalevent['RRULE'])) continue; // We found a repeatable event. It was already split into unitary events, so we discard general rule. // Create a new object action $event=new ActionComm($db); $addevent = false; - if ($icalevent['DTSTART;VALUE=DATE']) //fullday event + if ($icalevent['DTSTART;VALUE=DATE']) // fullday event { // For full day events, date are also GMT but they wont but converted using tz during output $datestart=dol_stringtotime($icalevent['DTSTART;VALUE=DATE'],1); @@ -557,19 +651,12 @@ if (count($listofextcals)) $event->fulldayevent=true; $addevent=true; } - elseif (!is_array($icalevent['DTSTART'])) //non-repeatable and not fullday event DTSTART;TZID=Europe/Paris:20120102T100000 + elseif (!is_array($icalevent['DTSTART'])) // not fullday event (DTSTART is not array) { $datestart=$icalevent['DTSTART']; $dateend=$icalevent['DTEND']; $addevent=true; } - //elseif (is_array($icalevent['DTSTART']) && ! empty($icalevent['DTSTART']['unixtime']) && ! is_array($icalevent['RRULE'])) - elseif (is_array($icalevent['DTSTART']) && ! empty($icalevent['DTSTART']['unixtime'])) - { - $datestart=$icalevent['DTSTART']['unixtime']; - $dateend=$icalevent['DTEND']['unixtime']; - $addevent=true; - } if ($addevent) { @@ -583,9 +670,9 @@ if (count($listofextcals)) if($icalevent['SUMMARY']) $event->libelle=$icalevent['SUMMARY']; elseif($icalevent['DESCRIPTION']) $event->libelle=dol_nl2br($icalevent['DESCRIPTION'],1); - else $event->libelle = $langs->trans("ExtSiteNoLabel"); + else $event->libelle = $langs->trans("ExtSiteNoLabel"); - $event->date_start_in_calendar=$event->datep; + $event->date_start_in_calendar=$event->datep; if ($event->datef != '' && $event->datef >= $event->datep) $event->date_end_in_calendar=$event->datef; else $event->date_end_in_calendar=$event->datep; @@ -594,11 +681,15 @@ if (count($listofextcals)) if ($event->date_start_in_calendar == $event->date_end_in_calendar) { $event->ponctuel=1; + //print 'x'.$datestart.'-'.$dateend;exit; } // Add event into $eventarray if date range are ok. if ($event->date_end_in_calendar < $firstdaytoshow || $event->date_start_in_calendar > $lastdaytoshow) { + //print 'x'.$datestart.'-'.$dateend;exit; + //print 'x'.$datestart.'-'.$dateend;exit; + //print 'x'.$datestart.'-'.$dateend;exit; // This record is out of visible range } else @@ -618,6 +709,7 @@ if (count($listofextcals)) $daykey=dol_mktime(0,0,0,$mois,$jour,$annee); $daykeygmt=dol_mktime(0,0,0,$mois,$jour,$annee,true,0,false); do + //print 'x'.$datestart.'-'.$dateend;exit; { //if ($event->fulldayevent) print dol_print_date($daykeygmt,'dayhour','gmt').'-'.dol_print_date($daykey,'dayhour','gmt').'-'.dol_print_date($event->date_end_in_calendar,'dayhour','gmt').' '; $eventarray[$daykey][]=$event; @@ -796,7 +888,7 @@ else // View by day $db->close(); /* TODO Export -print ' + print ' <a href="" id="actionagenda_ical_link"><img src="'.DOL_URL_ROOT.'/theme/common/ical.gif" border="0"/></a> <a href="" id="actionagenda_vcal_link"><img src="'.DOL_URL_ROOT.'/theme/common/vcal.gif" border="0"/></a> <a href="" id="actionagenda_rss_link"><img src="'.DOL_URL_ROOT.'/theme/common/rss.gif" border="0"/></a> @@ -955,10 +1047,10 @@ function show_day_events($db, $day, $month, $year, $monthshown, $style, &$eventa } else { - if ($showinfo) - { + if ($showinfo) + { print $langs->trans("EventOnFullDay")."<br>\n"; - } + } } // Show title diff --git a/htdocs/core/lib/date.lib.php b/htdocs/core/lib/date.lib.php index b11026f70b2..44ddacb3047 100644 --- a/htdocs/core/lib/date.lib.php +++ b/htdocs/core/lib/date.lib.php @@ -31,32 +31,33 @@ */ function get_tz_array() { - $tzarray=array( -11=>"Pacific/Midway", - -10=>"Pacific/Fakaofo", - -9=>"America/Anchorage", - -8=>"America/Los_Angeles", - -7=>"America/Dawson_Creek", - -6=>"America/Chicago", - -5=>"America/Bogota", - -4=>"America/Anguilla", - -3=>"America/Araguaina", - -2=>"America/Noronha", - -1=>"Atlantic/Azores", - 0=>"Africa/Abidjan", - 1=>"Europe/Paris", - 2=>"Europe/Helsinki", - 3=>"Europe/Moscow", - 4=>"Asia/Dubai", - 5=>"Asia/Karachi", - 6=>"Indian/Chagos", - 7=>"Asia/Jakarta", - 8=>"Asia/Hong_Kong", - 9=>"Asia/Tokyo", - 10=>"Australia/Sydney", - 11=>"Pacific/Noumea", - 12=>"Pacific/Auckland", - 13=>"Pacific/Enderbury" - ); + $tzarray=array( + -11=>"Pacific/Midway", + -10=>"Pacific/Fakaofo", + -9=>"America/Anchorage", + -8=>"America/Los_Angeles", + -7=>"America/Dawson_Creek", + -6=>"America/Chicago", + -5=>"America/Bogota", + -4=>"America/Anguilla", + -3=>"America/Araguaina", + -2=>"America/Noronha", + -1=>"Atlantic/Azores", + 0=>"Africa/Abidjan", + 1=>"Europe/Paris", + 2=>"Europe/Helsinki", + 3=>"Europe/Moscow", + 4=>"Asia/Dubai", + 5=>"Asia/Karachi", + 6=>"Indian/Chagos", + 7=>"Asia/Jakarta", + 8=>"Asia/Hong_Kong", + 9=>"Asia/Tokyo", + 10=>"Australia/Sydney", + 11=>"Pacific/Noumea", + 12=>"Pacific/Auckland", + 13=>"Pacific/Enderbury" + ); return $tzarray; } @@ -78,17 +79,33 @@ function getCurrentTimeZone() } +/** + * Add a delay of a timezone to a date + * + * @param timestamp $time Date timestamp + * @param string $timezone Timezone + * @return timestamp New timestamp + */ +function dol_time_plus_timezone($time,$timezone) +{ + // TODO Finish function + + return $time; +} + + /** * Add a delay to a date * * @param timestamp $time Date timestamp (or string with format YYYY-MM-DD) * @param int $duration_value Value of delay to add - * @param int $duration_unit Unit of added delay (d, m, y) + * @param int $duration_unit Unit of added delay (d, m, y, w) * @return timestamp New timestamp */ function dol_time_plus_duree($time,$duration_value,$duration_unit) { - if ($duration_value == 0) return $time; + if ($duration_value == 0) return $time; + if ($duration_unit == 'w') return $time + (3600*24*7*$duration_value); if ($duration_value > 0) $deltastring="+".abs($duration_value); if ($duration_value < 0) $deltastring="-".abs($duration_value); if ($duration_unit == 'd') { $deltastring.=" day"; } @@ -98,7 +115,7 @@ function dol_time_plus_duree($time,$duration_value,$duration_unit) } -/** Converti les heures et minutes en secondes +/** Convert hours and minutes into seconds * * @param int $iHours Heures * @param int $iMinutes Minutes @@ -208,13 +225,16 @@ function ConvertSecondToTime($iSecond,$format='all',$lengthOfDay=86400,$lengthOf * YYYY-MM-DDTHH:MM:SSZ (RFC3339) * DD/MM/YY or DD/MM/YYYY (this format should not be used anymore) * DD/MM/YY HH:MM:SS or DD/MM/YYYY HH:MM:SS (this format should not be used anymore) - * @param int $gm 1=Input date is GM date, 0=Input date is local date - * 19700101020000 -> 7200 with gm=1 + * @param int $gm 1 =Input date is GM date, + * 0 =Input date is local date using PHP server timezone + * -1=Input date is local date using timezone provided as third parameter + * @param string $tz Timezone to use of $gm=-1 * @return date Date + * 19700101020000 -> 7200 with gm=1 * * @see dol_print_date, dol_mktime, dol_getdate */ -function dol_stringtotime($string, $gm=1) +function dol_stringtotime($string, $gm=1, $tz='') { // Convert date with format DD/MM/YYY HH:MM:SS. This part of code should not be used. if (preg_match('/^([0-9]+)\/([0-9]+)\/([0-9]+)\s?([0-9]+)?:?([0-9]+)?:?([0-9]+)?/i',$string,$reg)) @@ -257,7 +277,12 @@ function dol_stringtotime($string, $gm=1) $string=preg_replace('/([^0-9])/i','',$string); $tmp=$string.'000000'; - $date=dol_mktime(substr($tmp,8,2),substr($tmp,10,2),substr($tmp,12,2),substr($tmp,4,2),substr($tmp,6,2),substr($tmp,0,4),$gm); + $date=dol_mktime(substr($tmp,8,2),substr($tmp,10,2),substr($tmp,12,2),substr($tmp,4,2),substr($tmp,6,2),substr($tmp,0,4),($gm?1:0)); + if ($gm == -1) + { + // TODO Define offset according to TZ + $date+=0; + } return $date; } diff --git a/htdocs/core/lib/functions.lib.php b/htdocs/core/lib/functions.lib.php index 834f00e8d7d..1b0fcd09ddf 100644 --- a/htdocs/core/lib/functions.lib.php +++ b/htdocs/core/lib/functions.lib.php @@ -825,9 +825,9 @@ function dol_format_address($object) /** * Output date in a string format according to outputlangs (or langs if not defined). - * Return charset is always UTF-8, except if encodetoouput is defined. In this cas charset is output charset + * Return charset is always UTF-8, except if encodetoouput is defined. In this case charset is output charset * - * @param timestamp $time GM Timestamps date (or deprecated strings 'YYYY-MM-DD' or 'YYYY-MM-DD HH:MM:SS') + * @param timestamp $time GM Timestamps date * @param string $format Output date format * "%d %b %Y", * "%d/%m/%Y %H:%M", @@ -973,9 +973,12 @@ function dol_print_date($time,$format='',$tzoutput='tzserver',$outputlangs='',$e /** - * Return an array with date info + * Return an array with locale date info. * PHP getdate is restricted to the years 1901-2038 on Unix and 1970-2038 on Windows * + * WARNING: This function always use PHP server timezone to return locale informations. + * Usage must be avoid. + * * @param timestamp $timestamp Timestamp * @param boolean $fast Fast mode * @return array Array of informations @@ -1000,6 +1003,7 @@ function dol_print_date($time,$format='',$tzoutput='tzserver',$outputlangs='',$e * 'yday' => floor($secsInYear/$_day_power), * 'leap' => $leaf, * 'ndays' => $ndays + * @see dol_print_date, dol_stringtotime, dol_mktime */ function dol_getdate($timestamp,$fast=false) { @@ -1030,17 +1034,17 @@ function dolibarr_mktime($hour,$minute,$second,$month,$day,$year,$gm=false,$chec * Replace function mktime not available under Windows if year < 1970 * PHP mktime is restricted to the years 1901-2038 on Unix and 1970-2038 on Windows * - * @param int $hour Hour (can be -1 for undefined) - * @param int $minute Minute (can be -1 for undefined) - * @param int $second Second (can be -1 for undefined) - * @param int $month Month (1 to 12) - * @param int $day Day (1 to 31) - * @param int $year Year - * @param int $gm 1=Input informations are GMT values, otherwise local to server TZ - * @param int $check 0=No check on parameters (Can use day 32, etc...) - * @param int $isdst Dayling saving time - * @return timestamp Date as a timestamp, '' if error - * @see dol_print_date, dol_stringtotime + * @param int $hour Hour (can be -1 for undefined) + * @param int $minute Minute (can be -1 for undefined) + * @param int $second Second (can be -1 for undefined) + * @param int $month Month (1 to 12) + * @param int $day Day (1 to 31) + * @param int $year Year + * @param int $gm 1=Input informations are GMT values, otherwise local to server TZ + * @param int $check 0=No check on parameters (Can use day 32, etc...) + * @param int $isdst Dayling saving time + * @return timestamp Date as a timestamp, '' if error + * @see dol_print_date, dol_stringtotime, dol_getdate */ function dol_mktime($hour,$minute,$second,$month,$day,$year,$gm=false,$check=1,$isdst=true) { -- GitLab