diff --git a/egwical/doc/EgwIcal-BUGS-and-TODOS.txt b/egwical/doc/EgwIcal-BUGS-and-TODOS.txt deleted file mode 100644 index 1cd51ba64d..0000000000 --- a/egwical/doc/EgwIcal-BUGS-and-TODOS.txt +++ /dev/null @@ -1,95 +0,0 @@ -/*! \page pageegwicalbugandtodo BUGS and TODOS - -
-Know BUGS and things todo ---------------------------- -TODO means: should be done/would be nice in a newer release -BUG means: known problem needs to be fixed -FAIl means: known failure to provide (not easily to be done/fixed - -(note: this list is probably not quite up todate) - - -release: VERSION 0.9.0 NEED TO UPDATE THIS!! - -new in V0.7.78 versus v0.7.70: - - bovevents: - -+ whole day events import/export seems to work nice -+ continue on erroneous overwrites (errors only visible in errorlog) -+ no error messages for forbidden overwrite events of non owned events -+ errormessages (when activated) only shows problematic events -++ basic (multiple) VALARM import and export, working! (without action select) -+ allow for vevents with either DTEND or DURATION -+ provided (horde iCalendar) patch to prevent segfaults on some bad iCal inputs - -1) EgwIcal package general (V0.9) ----------------- - - -[ ]1.2 TODO get it nicely into egw cvs -[+/-]1.7 TODO/WISH allow for import of ATTENDEEs not in Egw yet (create new addressbook entry?) - [+](ad hoc solution: add CN and mailto to description) -[+/-]1.4 TODO check and generate source code documentation(phpdoc or doxygen) - -[ ]1.5 TODO test these routines in use for syncml import/export - -1.6 TODO/WISH: nothing done yet for vfreebusy, vjournal, notes, components - only vevents and vtodos are supported. - - -3) egwical.egwical (V0.9.01) --------------------- - -[+?]3.1 TODO check/implement correct timezone handling (seems ok) -[ ]3.9 TEST with syncml -[ ]3.2 TODO/WISH handle location (GEO), link(?), url, delegation, ()CONTACT? -[ ]3.3 TODO write more documentation (continue mainpage) -[ ]3.4 TODO add accumulting buffer system to egwical - -4) egwical.bocalupdate_vevents (V0.9.02) ------------------------------- - -[+?]4.1 TODO check/implement correct timezone handling (related 3.1) -[ ]4.2a TODO/WISH handle URL, GEO etc. fields. (needs extra fields handling in bocalupdate!) -[ ]4.2b FAIL rrule-COUNT import not implemented in egw? -[+]4.2 BUG!!!! rrule-BYDAY import goes wrong. FIXED (v0.7.76) -[+]4.3 TODO check and improve ORGANIZER,ATTENDEE<-> participants mapping - ATTENDEE s import and export (appears to work oke >= V0.7.71) -[+]4.4 TODO handle import and export of ALARMS -[ ]4.7 TODO (ad hoc) add non egw known attendees to description on import -[ ]4.8 TODO move compatibility code to compat classes. - - -4.9 see 3.2 - - -5) egwical.boinfolog_vtodos (V0.9.02) ----------------------------- -5.1 TODO check/implement correct timezone handling (related 3.1) -5.3 FAIL import/export more than 1 category per task (egw doesnot allow) -5.3 TODO check and improve ORGANIZER,ATTENDEE<-> info_responsible etc mapping -5.4 TODO handle import and export of ALARMS -5.5 TODO rewrite code into supportedFields structure (for next version) -[ ]5.9 TODO rewrite into skeleton structure analog to egwical.bocalupdate_vevents - - - -10.) in used routines from others: - -10.1 BUG Horde_iCalendar(1.2rc6): EXDATE bug - -[+]fixed by patch 'exdate ....' -10.2 BUG Horde_iCalendar(1.2rc6): standard.php Warning - -[+]fixed by patch '...??..' - -10.3 BUG infolog(1.2rc6): datetime is 1 hour wrong for untimed due field in tasks - -11) detected errors/flaws in other programs - -11.1 Korganizer 3.5: recurrence endondate display is interpreted different from egw and -mozilla (and probable also rfc 2445) - - --*/ \ No newline at end of file diff --git a/egwical/doc/EgwIcal-Timezone-handling.txt b/egwical/doc/EgwIcal-Timezone-handling.txt deleted file mode 100644 index d75b3c49b3..0000000000 --- a/egwical/doc/EgwIcal-Timezone-handling.txt +++ /dev/null @@ -1,183 +0,0 @@ -/*! \page pageegwicaltzh EgwIcal Timezone Handling - -Short description on the timezone handling in EgwIcal - -@date 20060216 -@version 0.9.04 -@author JVL -@note Document needs further editing and annotations!! - - - -In EgwIcal the timed data of Egroupware like events and tasks get -converted to elements for an iCalendar. In the Egroupware server we -are dealing with socalled "egw server" time, in applications that a -user of egw runs, the user can set a "locale" and thereby defining a -"local timezone". And finally when events and task get exported to an -iCalendar that is sent to a client or uploaded from it, they may also -have their timesettings defined according to some "timezone". - -How is this all handled in EgwIcal? - - - -@section secegwicalgentzh EgwIcal general Timezone handling - -In general EgwIcal distinguishes between two different types of time -descriptions for an event. An event can either be a: -
- mon 12 june 2006 at 12:33 GMT+001
Examples are: the
- opening of the Olympic games.
-
- DT events are thus absolute (in global world time) anchored in time:
- everyone watching live TV, anywhere in the world can see it happen
- at that same moment described by DT.
-
- Result is that a DT described event will occur at different hours or
- even days in different timezones. (Some people have to watch the
- Olympic game openings at night..)
-
-
- ......
-
-
-@section secusageeicnv Converting Egw elements to iCalendar elements.
-
-To convert a egw component of e.g. "calendar event" into a
-corresponding iCalendar datacomponent of e.g. type "VEVENT"you can use the
-following in your code:
-
- ......
-
-
-@section secusageimport Importing iCalendar elements into Egw
-applications storage.
-
-To import a iCalendar datacomponentof e.g. type "VEVENT" as a
-corresponding egw component of type "calendar event" into your
-calendar application (its database) you can use the
-following in your code:
-
- ......
-
-
-@section secusageexport Exporting Egw application elements as iCalendar elements.
-
-To export as a egw datacomponent of e.g. type "calendar event" from your
-calendar application (its database) as a iCalendar datacomponentof e.g. type "VEVENT",
-you can use the following in your code:
-
- ......
-
-
-@section secusageexpimpbuffer Exporting (mixed) collections of iCalendar elements.
-
-Beside directly exporting single elements or sets of
-iCalendar data generated generated from a egw application like
-calendar, you can also use the "buffer" system of EgwIcal, to collect
-various sets of such dataelements, even from different Egw
-applications (like calendar and infolog), and then later on export
-these all together as one big iCalendar.
-
-To do collection followed by export you can use code like below:
- ......
-
-
-
-@section secimplementation How is EgwIcal implemented?
-
-To use or extend EgwIcal best, as a developer, it may be good know a bit about
-its implementation.
-EgwIcal is built according to the Workers Union Representatives
-Hierarchy (WURH) pattern. Quite a mouthfull, and probably there are
-somewhere better names for this pattern (see ...). In @ref pageegwicalwurh
-you can read more on this.
-
-Basically it means that there is one super "worker" class
-@ref egwical that uses for specific work like e.g. conversion
-between VEVENTS and calendar tasks, a specific subclass
-like e.g. bocalupdate_vevents that is connected to the
-egwical object via a socalled "representative" member in the registry $reg_rscs
-(attribute).
-
-Currently EgwIcal has the following subclasses:
-
-- bocalupdate_vevents
for manipulating calendar events as
- VEVENTS.
-
-- boinfolog_vtodos
for manipulating infolog tasks as VTODOS.
-
-Future subclasses might be:
-
-- ???_vjournals
for manipulating .... as VJOURNALS.
-
-- bocal_vfreebusies
for manipulating calendar data as
- VFREEBUSY elements.
-
-- addressbook_vcard
for manipulating addressdata data as
- VCARDS.
-
-- ???_vnotes
for manipulating .... as VNOTES.
-
-
-
-@section secdeletioncheatcode Cheatcode for Deleting Calendars, events or todos
-
-Egwical provides a special "hackish" feature specifically meant for
-use with the crippeld ical-over-http (aka webcal) implementation that
-the package IcalSrv provides for Egroupware.
-
-This IcalSrv implementation does not support deletion of egw calendar
-or infolog elements directly (see the IcalSrv package). As a help out
-the "cheat" is implemented that: you can though delete an item by
-simply giving the VEVENT or VTODO 'SUMMARY' field a value
-X-DELETE
or _DELETED_
and then importing it
-through the Egwical system. I you do so the the corresponding egw
-element from calendar or infolog will get deleted.
-
-
-@section secpatches Patches
-
-
-You may need to apply some of the patches found in PATCHES.
-Currently there a two patches to fix a warning and a bug (related to EXDATE
-fields handling) in the horde routines.
-Note these may be already committed in the CVS version.
-
-
-
-@section sectest Extra testing
-
-The package contains two "compatibility" classes (@ref boical and @ref vcalinfolog) with
-which you can replace
-the current infolog/inc/class.vcalinfolog.inc.php
resp.
-calendar/inc/class.boical.inc.php
-files.
-
-When done so, the egw syncml, ical import/export and infolog import/export in egw
-will all use the new code. This way you can discover more bugs and failure in the code :)
-
-But, when not renamed, these programs will use the old code (and thus are not broken or
-improved by the new one..)
-
-
-@section secdocumentation Documentation
-
-There is (somewhere) complete doxygen generated documentation for the
-EgwIcal package. Otherwise you can generate it yourself by using
-doxygen on the source filetree. Maybe phpdocumenter can give you also
-something usefull. And maybe you are just reading it now this very moment...
-
-
-
-@section secbugandtodo BuG and todo list
-
- @todo notably timezone handling in EgwIcal should be documented and
-possible features to allow import/export and use of iCalendar
-VTIMEZONE components should be provided.
-
- -see BUGs and TODOs in @ref pageegwicalbugandtodo
-
-
-
-
-have fun
-
-
-JVL
-
-
-*/
\ No newline at end of file
diff --git a/egwical/doc/egwical-doxydoc.tgz b/egwical/doc/egwical-doxydoc.tgz
deleted file mode 100644
index a3c46fdf8b..0000000000
Binary files a/egwical/doc/egwical-doxydoc.tgz and /dev/null differ
diff --git a/egwical/doc/egwical-wurh-pattern.txt b/egwical/doc/egwical-wurh-pattern.txt
deleted file mode 100644
index b33329a01c..0000000000
--- a/egwical/doc/egwical-wurh-pattern.txt
+++ /dev/null
@@ -1,205 +0,0 @@
-/*!
-\page pageegwicalwurh EgwIcal Workers Union Representatives Hierarchy Pattern
-implementation.
-
-@author JVL
-@date 20060214
-@version v0.9.02
-
-The current Egw Ical package provides routines for exporting iCalendar
-data like vevents, vtodos, vcards etc. from the various corresponding
-Egroupware packages (the "backends"). And vice versa importing these to the datastores
-of these packages. On the other hand there can also be a variety of
-interface components that transport e.g these exported vevents to
-further applications (the "clients"). Think e.g on the "icalsrv"
-service to transport whole sets of vevents in one go over http to a
-client, or the "syncml" service that transports them to syncml
-speaking device, or simple routine that let you save or upload a
-calendar file from within the webgui.
-
-An iCalendar data object can hold a set of these various kinds of
-data-elements as parts of itself. And these data-elements itself can
-also be composed of sub-elements (like e.g. VALARM and VTIMEZONE
-components).
-
-
-So in this situation we have Wholes (like an iCalendar object) with
-Parts (like groups of Vevents and groups of Vtodos) on the one hand.
-And on the other hand we have dedicated subappliations that may handle
-these groups of Part data. To implement this we can make use of a
-smart combination of two implementation primitives "compounds" and
-"classes and subclasses".
-
-In the WURH pattern the combination of these two is very rather
-outspoken and quite entangled and even a bit tricky: each specific
-type of Part is "represented" by specific subclass of the class of
-Whole compound. The data in the parts can now be manipulated in two
-ways:
-
-1) all together as whole, via methods of the compound, or
-2) all in the group of a part, by the methods of the (associated)
-subclass its representative.
-
-@note I forgot the official (GOF) name of the pattern (if there is
-any..)
-
-
-
-\section secwurhexample Example WURH pattern implementation: Meal preparation
-
-As simple example should explain this: Meal preparation URH pattern
-implementation
-
-think of the preparation of meal, that consist of soup and meat.
-To "cook" the meal, the soup has to be boiled and the meat has to be
-baked.
-
-in OO notation: <>-
or .
. means member of,
-<-
means subclass of
-
-Classes:
--MealCooker <- SoupCooker; MealCooker <- MeatCooker; -MealCooker <>- SoupCooker; MealCooker <>- MeatCooker; --Methods: -
-MealCooker->cook(); SoupCooker->boil(); MeatCooker->bake(); --and possibly the cook() method may even, for easy of use in the Soup and -Meat classes by implemented (overridden) by the boil() resp. bake() method. - -Now the code to prepare to have $mymealck prepare a meail with $mysoupck and $mymeatck (without -subclass overrriding): -
-$mymealck = New MealCooker; -$mymeatck = New MeatCooker; -$mysoupck = New SoupCooker; - -$meat_in_mealck = $mymealck->addMeatHandler($mymeatck); -$soup_in mealck = $mymealck->addSoupHandler($mysoupck); - -// these are in class MealCooker implemented as -// $this.m = meatcooker_config($mymeatck); resp. $this.s = soupcooker_config($mysoupck); -- -Now cooking the meal is done by, cooking the soup in its appropiate -way (namely "boiling()" )via its union representative ($soup_in_mealck). Note that it is -called "union" representative because multiple SoupCookers parts may have been -added already to use. And also cooking the meat in its appropiate way -("baking()") likewise. Thus -
-$mymealck->cook([$apiec_of_meat,$avolum_of_soup]) can be done by calling: - - $meat_in_mealck->bake($apiece_of_meat); - $soup_in_mealck->boil($avolume_of_soup); --and then you can serve boths parts in one go with: -
-$mymealck->serve(); -- -If we implemented the specific ways of cooking as overriding subclass -methods for Meal->cook() then in simple cases we dont even need to use -the representatives to call the preparation as we implement to main -cook() method to call all itself on all its parts: -
-$mymealck = New MealCooker; -$mymeatck = New MeatCooker; -$mysoupck = New SoupCooker; - - $mymealck->addMeatHandler($mymeatck); - $mymealck->addSoupHandler($mysoupck); -- -And
$mymealck->cook([$apiec_of_meat,$avolum_of_soup])
can then done by
-just calling:
-
-- $meat_in_mealck->bake($apiece_of_meat); - $soup_in_mealck->boil($avolume_of_soup); - - // which effects in $mymealck.m->cook($apiece_o_fmeat); - // and $mymealck.s ->cook($avolume_of_soup); - // that effects again in $mymealck.m->bake($apiece_o_fmeat); - // and $mymealck.s->boil($avolume_of_soup); - -- -So this allows for using of manipulation methods of the whole (in case -of simple generic actions reimplemented in the subclasses of the -parts) together with using more specific methods for specific -parts. (e.g. $soup_in_mealck->set_boil_time(10) etc.) - - - -\section securhinei WURH pattern usage in Egwical. - -The Egwical class manages an complete iCalendar component with -VEVENTS, VTODOS etc. as parts. The handling of these part(unions)s is -done by specific subclasses of Egwical, like e.g. infolog_bovtodo and -calendar_bovevents. -The system can be used in two different modes of operation: - -- 1) for conversion of egw tasks, events, etc. to their iCal - counterparts. (the cnv_ methods). - -- 2) for filling the (internal) egwical object with al lot of vtodos and - vevents, either coming from import or from conversion of egw - counterparts. When the compound is filled it can (as a whole) be - exported or imported. - - -add 1) So e.g. exporting a group of events refered to by $event_ids as -VEVENTS goes as follows: -
-$cal = New Bocal; // build calendar -$event_ids = $cal->search("filt_def'); // get group of egw event ids to export. - -$ei = New Egwical; // build Compound iCalendar processor -$bve = $ei->addRsc($cal); // add calendar part and get representive -$vcalstr = $bve->cnv2VEVENTS($event_ids); // export some events - -- -if we also want to export some VTODOs this goes as follows: - -
-$binf = New Infolog // build infolog app. object -$task_ids = $binf->search("filt_def'); // get group of egw task ids to export. - -$bvt = $ei->addRsc($binf); // add infolog part and get representive -$vcalstr = $bvt->cnv2VTODOS($task_ids); - --add 2) the same egw elements from 1) are now first collected in -egwical and then as a whole exported. - -
-$cal = New Bocal; // build calendar -$event_ids = $cal->search("filt_def'); // get group of egw event ids to export. - -$ei = New Egwical; // build Compound iCalendar processor -$bve = $ei->addRsc($cal); // add calendar sys part and get representive - $bve->clear(); // empty the list of Vevents in bve - $bve->addEventsOntoVEVENTS($event_ids); // add the converted events to vevents in $ei - --if we also want to add some VTODOs this goes as follows: -
-$binf = New Infolog // build infolog app. object -$task_ids = $binf->search("filt_def'); // get group of egw task ids to export. - - $bvt = $ei->addRsc($binf); // add infolog sys part and get representive - $bvt->clear(); // empty the list of Vtodos in bvt - $bvt>addTasksOntoVTODOS($task_ids); // add the converted tasks to vtodos in $ei - --and finally export the whole iCalendar -
-$ei->export() -- - ---------- - -*/ \ No newline at end of file diff --git a/egwical/inc/class.bocalupdate_vevents.inc.php b/egwical/inc/class.bocalupdate_vevents.inc.php deleted file mode 100644 index f263e65ee5..0000000000 --- a/egwical/inc/class.bocalupdate_vevents.inc.php +++ /dev/null @@ -1,1075 +0,0 @@ - (This version. new api rewrite, - * refactoring, and extension). - * @author Lars Kneschke
isset($this->supportedFields['ORGANIZER'])
.
- * To detect if a certain egw field (eg status
) is supported in the current
- * data import/export do a
- * in_array(array_flatten(array_values($this->supportedFields)),'status')
- * or something like that (not tested, implemented, or needed yet..) Maybe should
- * implement a method for this..
- * @note This table should probably better be in class @ref egwical
- */
- var $supportedFields;
-
-
-
-
- /**
- * @var boolean
- * Switch that determines if uid matching is tried.
- *
- * For a more on uidmatching @see \secimpumatch
- *
- * If $uid_matching is true then:
- * - on import of a vevent the update routines will first try to
- * find an existing egw event with the same uid value as present
- * in the UID field of the newly to be imported vevent. If this
- * succeeds this egw event will get updated with the info from
- * the vevent. If this fails a new event will be generated and
- * the uid taken from the vevent will be stored in its uid
- * field.
- *
- * if $uid_matching is false then:
- * - On import the VEVENT UID field will be checked, if it
- * appears to be a previously exported uid value then the
- * encoded egw id of the old egw event is retrieved and used for
- * update. If it doesnot have a uid value with a valid egw id
- * encoding, then the its is handled as being a new VEVENT to be
- * imported, and a new egw id will be generated. The old vevent
- * uid will though be saved for possible later use, (just as
- * with uid_matching on).
- */
- var $uid_matching = false;
-
- /**
- * @var boolean
- * Switch that determines if events not anymore in egw are allowed to be reimported
- *
- * Default this is on
- */
- var $reimport_missing_events = true;
-
-
-
- /**
- * Export Egw events and add them to a Horde_iCalendar.
- *
- * The eGW events in $events are exported to iCalendar VEVENTS and then these are added to
- * the Horde_iCalendar object &$hIcal.
- * Note that only supported Fields are exported as VEVENTS to the iCalendar.
- *
- * @section secexpeuid Egw uid export switch
- * If $euid_export is set, then for each exported event, the current value of the event uid
- * as stored in Egw, will be used to produce a value for the vevent its UID field. When off
- * a new UID value will generated with the egw event id encoded.
- *
- * @param Horde_iCalendar &$hIcal
- * object to wich the produced VEvents are added.
- * @param array $events the array with eGW events (or event id's) that will be exported
- * @param boolean $euid_export switch to enable export of the egw uid fields, when off
- * default) the vevents uid fields get a value generated with the egw id encoded.
- * @return boolean|int $ok/$vcnt on error: false / on success: nof vevents exported
- * @ref $supportedFields determines which fields of VEVENT will be exported
- */
- function exportEventsOntoIcal(&$hIcal, $events, $euid_export=false,
- $reimport_missing_events=false)
- {
- $vexpcnt =0; // number of vevents exported
-
- $veExportFields =& $this->supportedFields;
-
- if (!is_array($events)) $events = array($events);
-
- foreach($events as $event) {
- // event was passed as an event id
- if (!is_array($event)){
- $eid = $event;
- if( !$event = $this->mycal->read($eid,null,false,'server')){
- // server = timestamp in server-time(!)
- return false; // no permission to read $cal_id
- }
- // event was passed as an array of fields
- } else {
- $eid = $event['id'];
- // now read it again to get all fields (including our alarms)
- $event = $this->mycal->read($eid);
- }
-
- // error_log('>>>>>>>>>>>' .'event to export=' . print_r($event,true));
-
- // now create a UID value
- if ($euid_export) {
- // put egw uid into VEVENT, to allow client to sync with his uids
- $eventGUID = $event['uid'];
- } else {
- $eventGUID = $this->mki_v_guid($eid,'calendar');
- }
-
- $vevent = Horde_iCalendar::newComponent('VEVENT',$hIcal);
- $parameters = $attributes = array();
- // to important to let supportedFields decide on this
- $attributes['UID'] = $eventGUID;
-
- foreach($veExportFields as $veFieldName) {
-
- switch($veFieldName) {
- case 'UID':
- // already set
- break;
-
- case 'ATTENDEE':
- foreach((array)$event['participants'] as $pid => $partstat) {
- if (!is_numeric($pid)) continue;
-
- list($propval,$propparams) =
- $this->mki_vp_4ATTENDEE($pid,$partstat,$event['owner']);
- // NOTE: we need to add it already: multiple ATTENDEE fields may be occur
- $this->addAttributeOntoVevent($vevent,'ATTENDEE',$propval,$propparams);
- }
- break;
-
- case 'CLASS':
- $attributes['CLASS'] = $event['public'] ? 'PUBLIC' : 'PRIVATE';
- break;
-
- // according to rfc, ORGANIZER not used for events in the own calendar
- case 'ORGANIZER':
- if (!isset($event['participants'][$event['owner']])
- || count($event['participants']) > 1) {
- $attributes['ORGANIZER'] = $this->mki_v_CAL_ADDRESS($event['owner']);
- $parameters['ORGANIZER'] = $this->mki_p_CN($event['owner']);
- }
- break;
-
- // Note; wholeday detection may change the DTEND value later!
- case 'DTEND':
- // if(date('H:i:s',$event['end']) == '23:59:59')
- // $event['end']++;
- $attributes[$veFieldName] = $event['end'];
- break;
-
- case 'RRULE':
- if ($event['recur_type'] == MCAL_RECUR_NONE)
- break; // no recuring event
- $attributes['RRULE'] = $this->mki_v_RECUR($event['recur_type'],
- $event['recur_data'],
- $event['recur_interval'],
- $event['start'],
- $event['recur_enddate']);
- break;
-
- case 'EXDATE':
- if ($event['recur_exception']) {
- list( $attributes['EXDATE'], $parameters['EXDATE'])=
- $this->mki_vp_4EXDATE($event['recur_exception'],false);
- }
- break;
-
- case 'PRIORITY':
- if (is_numeric($eprio = $event['priority']) && ($eprio >0) )
- $attributes['PRIORITY'] = $this->mki_v_prio($eprio);
- break;
-
- case 'TRANSP':
- $attributes['TRANSP'] = $event['non_blocking'] ? 'TRANSPARENT' : 'OPAQUE';
- break;
-
- case 'CATEGORIES':
- if ($catids = $event['category']){
- $catnamescstr = $this->cats_ids2idnamescstr(explode(',',$catids));
- $attributes['CATEGORIES'] = $catnamescstr;
- }
- break;
-
- // @todo find out about AALARM, DALARM, Is this in the RFC !?
- case 'AALARM':
- foreach($event['alarm'] as $alarmID => $alarmData) {
- $attributes['AALARM'] = $hIcal->_exportDateTime($alarmData['time']);
- // lets take only the first alarm
- break;
- }
- break;
-
- case 'DALARM':
- foreach($event['alarm'] as $alarmID => $alarmData) {
- $attributes['DALARM'] = $hIcal->_exportDateTime($alarmData['time']);
- // lets take only the first alarm
- break;
- }
- break;
-
- case 'VALARM':
- foreach($event['alarm'] as $alarmID => $alarmData) {
- $this->mki_c_VALARM($alarmData, $vevent,
- $event['start'], $veExportFields);
- }
- break;
-
- case 'STATUS': // note: custom field in event
- if (! $evstat = strtoupper($event['status']))
- $evstat = 'CONFIRMED'; //default..
- $attributes['STATUS'] = $evstat;
- break;
-
- default:
- // only use default for level1 VEVENT fields
- if(strpos($veFieldName, '/') !== false)
- break;
- // use first related field only for the simple conversion
- $efield = $this->ical2egwFields[$veFieldName][0];
- if ($event[$efield]) { // dont write empty fields
- $attributes[$veFieldName] = $event[$efield];
- }
- break;
- }
-
- } //end foreach
-
- // wholeday detector (DTEND =23:59:59 && DTSTART = 00:00)
- // if detected the times will be exported in VALUE=DATE format
- if(((date('H:i:s',$event['end']) == '23:59:59') ||
- (date('H:i:s',$event['end']) == '00:00:00'))
- && (date('H:i',$event['start'] == '00:00'))){
- $attributes['DTSTART'] =
- $this->hi->_parseDate(date('Ymd',$event['start']));
- $attributes['DTEND'] =
- $this->hi->_parseDate(date('Ymd',$event['end']+1));
- $parameters['DTEND']['VALUE'] = 'DATE';
- $parameters['DTSTART']['VALUE'] = 'DATE';
- // error_log('WHOLE DAY DETECTED');
- }
-
- // handle created and modified field setting
- $created = $this->get_TSdbAdd($event['id'],'calendar');
- if (!$created && !$modified)
- $created = $event['modified'];
- if ($created)
- $attributes['CREATED'] = $created;
- if (!$modified)
- $modified = $event['modified'];
- if ($modified)
- $attributes['LAST-MODIFIED'] = $modified;
-
- // add all collected attributes (not yet added) to the vevent
- foreach($attributes as $aname => $avalue) {
- $this->addAttributeOntoVevent($vevent,
- $aname,
- $avalue,
- $parameters[$aname]);
- }
- $hIcal->addComponent($vevent);
- $vexpcnt += 1;
- }
-
- return $vexpcnt; //return nof vevents exported
- }
-
-
-
-
- /**
- * Import all VEVENTS from a Horde_iCalendar into Egw
- *
- * The ical VEVENTS components that are contained in de $hIcal Horde_iCalendar
- * are converted to eGW events and imported into the eGW calendar.
- * Depending on the value of $importMode, the conversion will generate either eGW
- * events with completely new id s (DUPLICATE mode) or generate ids created after
- * the VEVENT;UID field so that VEVENTS that refer to already existing eGW events
- * will be used to update these (OVERWRITE mode).
- *
- * @section secimpumatch Uidmatching
- * When $uid_matching is not set, the default situation, the uid field of each vevent
- * to be imported will examined to check if it has a valid egw id encoded. If so the import
- * will try to update the egw event indicated by this id with the contents of the vevent.
- * When this doesnot succeed an appropiate error or skip (if you had not enough write rights)
- * will be the result. If there can be no valid egw id be decoded, the vevent will be considered
- * as a new one and an hence a new egw id will automatically be produced.
- *
- * When $uid_matching is enabled, the value of the uid field of the vevent will matched against
- * all the uid fields of existing egw events. If a matching egw event with id is found,
- * the import
- * routine will try to update this event. If no success an appropiate error will be generated.
- * If no match is found, the import proceeds, just as without uidmatching, by generating a
- * new egw event with a new id. The events uid field will be filled with the vevents uid,
- * for possible later re-use.
- *
- * @note Mostly it is best to disable uidmatching. It prevents that multiple duplicates
- * of a event will be created in Egw, that may not be accessible anymore via the Ical-Service
- * interface. Only use it when you really need to reimport an already once imported calendar
- * because you accidentally deleted parts of it in Egw. Better still would be copy these lost
- * events into a downloaded version of your original calendar and then update this one without
- * the uid_matching enabled. (It has namely no effect for new events and the old (i.e.
- * already downloaded to the client) events will be recognized without uidmatching.
- *
- * @param Horde_iCalendar &$hIcal object with ical VEVENT objects
- * @param string $importMode toggle for duplicate (ICAL_IMODE_DUPLICATE)
- * or overwrite (ICAL_IMODE_OVERWRITE) import mode
- * @param int $cal_id strange parameter, at least for -1 create new events
- * and if 0 then always add user to participants
- * JVL: THIS NEEDS TO BE CLARIFIED!
- * @param boolean $reimport_missing_events enable the import of previously exported events
- * that are now gone in egw (probably deleted by someone else) Default false.
- * @return boolean| int $false|$evcnt on error: false | on success: nof imported elms
- * @ref $supportedFields determins the VEVENTS that will be used for import
- */
- function importVEventsFromIcal(&$hIcal, $importMode='OVERWRITE', $cal_id=0,
- $reimport_missing_events=false)
- {
- $overwritemode = stristr($importMode,'overwrite') ? true : false;
- $evokcnt = 0; // nof events imported ok
- $everrcnt = 0; // nof events imported erroneous
- $evskipcnt = 0; // nof events imported skipped (user !== owner)
- $evdelcnt = 0; // nof events deleted ok
- $evmisskipcnt =0; // nof missing event updates skipped
-
- $veImportFields =& $this->supportedFields;
-
-// error_log('veImportFields::'. print_r($veImportFields,true));
-
- $eidOk = false; // returning false, if file contains no components
- $user_id = $GLOBALS['egw_info']['user']['account_id'];
-
- foreach($hIcal->getComponents() as $vevent) {
- // HANDLE ONLY VEVENTS HERE
- if(!is_a($vevent, 'Horde_iCalendar_vevent'))
- continue;
-
-// $event = array('participants' => array());
- $event = array('title' => 'Untitled');
- $alarms = array();
- unset($owner_id);
- $evduration = false;
- $nonegw_participants = array();
-
- // handle UID field always first according to uid_matching algorithm
- $cur_eid = false; // current egw event id
- $cur_owner_id = false; // current egw event owner id
- $cur_event = false; // and the whole array of possibly correspond egw event
- // import action description (just for fun and debug) :
- // NEW|NEW-NONUID|NEW-FOR-MISSING
- // DEL-MISSING|DEL-READ|DEL-READ-UID|
- // UPD-MISSING|UPD-READ|UPD-READ-UID
- $imp_action = 'NEW-NONUID';
-
- if($uidval = $vevent->getAttribute('UID')){
- // ad hoc hack: egw hates slashes in a uid so we replace these anyhow with -
- $vuid = strtr($uidval,'/','-');
- $event['uid'] = $vuid;
-
- if(!$this->uid_matching){
-
- // UID_MATCHING DISABLED, try to decode cur_eid from uid
- if ($cur_eid = $this->mke_guid2id($vuid,'calendar')){
- // yes a request to import a previously exported event!
- if ($cur_event = $this->mycal->read($cur_eid)){
- // oke we can read the old event
- $cur_owner_id = $cur_event['owner'];
- $imp_action = 'UPD-READ';
- $event['id'] = $cur_eid;
- } elseif($reimport_missing_events){
- // else: a pity couldnot read the corresponding cur_event,
- // maybe it was deleted in egw already..
- $imp_action = 'UPD-MISSING';
- unset($event['id']); // import as a new one
- } else{
- // go on with next vevent
- $evmisskipcnt += 1;
- continue;
- }
- }else{
- // no decodable egw id there, so per definition no corresponding egw event
- // so will just import the vevent as a new event
- $imp_action = 'NEW';
- }
-
- //UID_MATCHING ENABLED
- } elseif($overwritemode && $cal_id <= 0 && !empty($vuid)){
- // go do uidmatching, search for a egw event with the vuid as uid field
- if ($cur_event = $this->mycal->read($vuid)) {
- $cur_eid = $uidmatch_event['id'];
- $cur_owner_id = $uidmatch_event['owner'];
- $imp_action = 'UPD-READ-UID';
- $event['id'] = $cur_eid;
- }else{
- // uidmatch failed, insert as new
- $imp_action = 'NEW';
- }
- }
-
- }
-
- // lets see what other supported veImportFields we can get from the vevent
- foreach($vevent->_attributes as $attr) {
- $attrval = $GLOBALS['egw']->translation->convert($attr['value'],'UTF-8');
-
-
- // SKIP UNSUPPORTED VEVENT FIELDS
- if(!in_array($attr['name'],$veImportFields))
- continue;
-
-// error_log('cnv field:' . $attr['name'] . ' val:' . $attrval);
-
- switch($attr['name']) {
- // oke again these strange ALARM properties...
- case 'AALARM':
- case 'DALARM':
- if (preg_match('/.*Z$/',$attrval,$matches)) {
- $alarmTime = $hIcal->_parseDateTime($attrval);
- $alarms[$alarmTime] = array('time' => $alarmTime);
- }
- break;
-
- case 'CLASS':
- $event['public'] = (int)(strtolower($attrval) == 'public');
- break;
-
- case 'DESCRIPTION':
- $event['description'] = $attrval;
- break;
-
- case 'DTEND':
- // will be reviewed after all fields are collected
- $event['end'] = $attrval;
- break;
-
- // note: DURATION and DTEND are mutually exclusive
- case 'DURATION':
- // duration after eventstart in secs
- $evduration = $attrval;
- break;
-
- case 'DTSTART':
- // will be reviewed after all fields are collected
- $event['start'] = $attrval;
- break;
-
- case 'LOCATION':
- $event['location'] = $attrval;
- break;
-
- case 'RRULE':
- // we may need to find a startdate first so delegate to later
- // by putting it in event['RECUR']
- $event['RECUR'] = $attrval;
- break;
- case 'EXDATE':
- if (($exdays = $this->mke_EXDATEpv2udays($attr['params'], $attrval))
- !== false ){
- foreach ($exdays as $day){
- $event['recur_exception'][] = $day;
- }
- }
- break;
-
- case 'SUMMARY':
- $event['title'] = $attrval;
- break;
-
- case 'TRANSP':
- $event['non_blocking'] = $attrval == 'TRANSPARENT';
- break;
- // JVL: rewrite!
- case 'PRIORITY':
- $event['priority'] = $this->mke_prio($attrval);
- break;
-
- case 'CATEGORIES':
- $catnames = explode(',',$attrval);
- $catidcstr = $this->cats_names2idscstr($catnames,$user_id,'calendar');
- $event['category'] .= (!empty($event['category']))
- ? ',' . $catidcstr : $catidcstr;
- break;
-
- // when we encounter an new valid cal_address but not yet in egw db
- // should we import it?
- case 'ATTENDEE':
- if ($pid = $this->mke_CAL_ADDRESS2pid($attrval)){
- if( $epartstat = $this->mke_params2partstat($attr['params'])){
- $event['participants'][$pid] = $epartstat;
- } elseif ($pid == $event['owner']){
- $event['participants'][$pid] = 'A';
- } else {
- $event['participants'][$pid] = 'U';
- }
- // egw unknown participant, add to nonegw_participants list
- } else {
- $nonegw_participants[] =
- $this->mke_ATTENDEE2cneml($attrval,$attr['params']);
- }
- break;
-
- // make organizer into a accepting participant
- case 'ORGANIZER': // make him
- if ($pid = $this->mke_CAL_ADDRESS2pid($attrval))
- $event['participants'][$pid] = 'A';
- //$event['owner'] = $pid;
- break;
-
- case 'CREATED': // will be written direct to the event
- if ($event['modified']) break;
- // fall through
-
- case 'LAST-MODIFIED': // will be written direct to the event
- $event['modified'] = $attrval;
- break;
-
- case 'STATUS': // note: custom field in event
- $event['status'] = strtoupper($attrval);
- break;
-
- default:
- error_log('VEVENT field:' .$attr['name'] .':'
- . $attrval . 'HAS NO CONVERSION YET');
- }
- } // end of fields loop
-
- // now all fields are gathered do some checking and combinations
-
- // we may have a RECUR value set? Then convert to egw recur def
- if ($recurval = $event['RECUR']){
-//error_log('recurval=' . $recurval . '=');
- if(!($recur = $this->mke_RECUR2rar($recurval,$event['start'])) == false){
- foreach($recur as $rf => $rfval){
- $event[$rf] = $rfval;
- }
- }
- unset($event['RECUR']);
- }
-
- // build endtime from duration if dtend was not set
- if (!isset($event['end']) && ($evduration !== false)){
- $event['end'] = $this->mke_DDT2utime($event['start']) + $evduration;
- }
-
- // a trick for whole day handling or ...??
- if(date('H:i:s',$event['end']) == '00:00:00')
- $event['end']--;
-
- // check vevent for subcomponents (VALARM only at the moment)
- // maybe some day do it recursively... (would be better..)
- foreach($vevent->getComponents() as $valarm) {
- // SKIP anything but a VALARM
- if(!is_a($valarm, 'Horde_iCalendar_valarm'))
- continue;
- $this->upde_c_VALARM2alarms($alarms,$valarm,$user_id,$veImportFields);
- }
-
- // AD HOC solution: add nonegw participants to the description
- // should be controlable by class member switch
- if (count($nonegw_participants) > 0)
- $this->upde_nonegwParticipants2description($event['description'],
- $nonegw_participants);
-
- // handle fixed id call (for boical compatibility)
- // @todo test boical compatibility (esp. with $cal_id>0 case)
- if($cal_id > 0) {
- $event['id'] = $cal_id;
- }
-
- // SORRY THE PARTICPANTS HANDLING OF EGW IS NOT YET CLEAR TO ME (JVL)
- // so I do the bold solution to add ourself to participants list if we are not on yet
- if(!isset($event['participants'][$user_id]))
- $event['participants'][$user_id] = 'A';
-
- // error_log('<< ok <<<<' . 'event read for import=' . print_r($event,true));
-
-
- // -- finally we come to the import into egw ---
-
- if (($event['title'] == 'X-DELETE') || ($event['title'] == '_DELETED_')){
-
-
- // -------- DELETION --------------------
- // error_log('delete event=' . print_r($event,true));
- $imp_action = 'DEL-' . $imp_action;
- if(! $cur_eid) {
- $this->_errorlog_evupd('ERROR: ' . $imp_action,
- $user_id, $event, false);
- $everrcnt += 1;
- continue;
- } else {
- // event to delete is found readable
- if($eidOk = $this->mycal->delete($cur_eid)){
- // DELETE OK
- $evdelcnt += 1;
-
- // ASSUME Alarms are deleted by egw on delete of the event...
- // otherwise we should use this code:
- // delete the old alarms
- //foreach($cur_event['alarm'] as $alarmID => $alarmData) {
- // $this->delete_alarm($alarmID);
- //}
- continue;
- } elseif ($user_id != $cur_owner_id){
- // DELETE BAD but it wasnt ours anyway so skip it
- if ($this->evdebug)
- $this->_errorlog_evupd('SKIPPED: ' . $imp_action . ' (INSUFFICIENT RIGHTS)',
- $user_id, $event, $cur_event);
- $evskipcnt += 1;
- continue;
- } else {
- // DELETE BAD and it was ours
- $this->_errorlog_evupd('ERROR: ' . $imp_action . '(** INTERNAL ERROR ? **)',
- $user_id, $event, $cur_event);
- $everrcnt += 1;
- continue;
- }
-
- }
-
- // -------- UPDATE --------------------
- } elseif ($eidOk = $this->mycal->update($event, TRUE)){
- // UPDATE OKE ,now update alarms
- $evokcnt += 1; // nof imported ok vevents
- // handle the found alarms
- if(in_array('VALARM',$veImportFields)){
- // delete the old alarms for the event, note: we could also have used $cur_event
- // but jus to be sure
- if(!$updatedEvent = $this->mycal->read($eidOk)){
- error_log('ERROR reading event for Alarm update, will skip update..');
- continue;
- }
-
- // ******** for serious debugging only.. **************
- // if ($this->evdebug){
- // $this->_errorlog_evupd('OK: ' . $imp_action,
- // $user_id, $event, $cur_event);
- //error_log('event readback dump:' . print_r($updatedEvent,true));
- // }
- // ******** eof serious debugging only.. **************
-
- foreach($updatedEvent['alarm'] as $alarmID => $alarmData) {
- $this->delete_alarm($alarmID);
- }
- // set new alarms
- foreach($alarms as $alarm) {
- if(!isset($alarm['offset'])){
- $alarm['offset'] = $event['start'] - $alarm['time'];
- } elseif (!isset($alarm['time'])){
- $alarm['time'] = $event['start'] - $alarm['offset'];
- }
- $alarm['owner'] = $user_id;
-// error_log('setting egw alarm as:' . print_r($alarm,true));
- $this->save_alarm($eidOk, $alarm);
- }
- }
- continue;
-
- // ---UPDATE BAD --------
- } elseif ($user_id != $cur_owner_id){
- // UPDATE BAD, but other ones event, so skip
- if ($this->evdebug)
- $this->_errorlog_evupd('SKIPPED: ' . $imp_action . ' (INSUFFICIENT RIGHTS)',
- $user_id, $event, $cur_event);
- $evskipcnt += 1;
- continue;
- } else {
- // UPDATE BAD and we own it or it was a new one
- $this->_errorlog_evupd('ERROR: ' . $imp_action . '(** INTERNAL ERROR ? **)',
- $user_id, $event, $cur_event);
- $everrcnt += 1;
- continue;
- }
- error_log('CODING ERROR: SHOULDNOT GET HERE');
- } // for each
-
- if (($everrcnt > 0) || $this->evdebug)
- error_log('** user[' . $user_id . '] vevents imports: ' . $everrcnt . ' BAD,' .
- $evskipcnt . ' skip-(insufficient rights), ' . $evmisskipcnt .
- ' skip-(ignore reimport missings), ' .
- $evokcnt . ' upd-ok, ' . $evdelcnt . ' del-ok');
- return ($everrcnt > 0) ? false : $evokcnt+ $evdelcnt;
- }
-
-
- /**
- * @private
- * Log event update problems to http errorlog
- * @param string $fault description of the fault type
- * @param ind $user_id the id of the logged in user
- * @param array $new_event the info converted from the vevent to be imported
- * @param array|false $cur_event_ids settings of owner, id and uid field of a possibly found
- * corresponding egw event. When no such event found: false.
- */
- function _errorlog_evupd($fault='ERROR', $user_id, &$new_event, $cur_event)
- {
- // ex output:
- // ** bovevents import for user(12 [pietje]): ERROR
- // current egw event: id=24, owner=34, uid='adaafa'\n
- // vevent info event: id=24, owner=--, uid='dfafasdf'\n
-
- $uname =(is_numeric($user_id))
- ? $user_id . '[' . $GLOBALS['egw']->accounts->id2name($user_id) . ']'
- : '--';
- if ($cur_event === false){
- $cid = $cown = $cuid = '--';
- }else{
- $cid = $cur_event['id'];
- $cown = $cur_event['owner'];
- $cuid = $cur_event['uid'];
- }
- $nid = ($vi = $new_event['id']) ? $vi : '--';
- $nown = ($vi = $new_event['owner']) ? $vi : '--';
- $nuid = ($vi = $new_event['uid']) ? $vi : '--';
-
- error_log('** bovevents import for user (' . $cur_eid .
- '['. $uname . ']):' . $fault . '\n' .
- 'current egw event: id=' . $cid . ',owner=' . $cown . ',uid=' . $cuid .'\n' .
- 'vevent info event: id=' . $nid . ',owner=' . $nown . ',uid=' . $nuid .'\n' );
-// error_log('vevent info event dump:' . print_r($new_event,true) . '\n <<-----------<<\n');
- }
-
-
- /**
- * @private
- *
- * Fill member var that holds the iCalendar property to Egw fields mapping.
- *
- * Copy keys from this var to the supportedFields member var to allow import/export
- * of the field refered to by the key.
- * @todo Maybe someday rethink the ical2egwFields trafo system by rewriting it in paths
- * starting from iCalendar/Component=>Field or iCalendar/Comp/SubComp etc.
- * @see $ical2egwFields member var that holds the mapping
- */
- function _set_ical2egwFields()
- {
- $this->ical2egwFields =
- array(
- 'UID' => array('uid'),
- 'CLASS' => array('public'),
- 'SUMMARY' => array('title'),
- 'DESCRIPTION' => array('description'),
- 'LOCATION' => array('location'),
- 'DTSTART' => array('start'),
- 'DTEND' => array('end'),
- 'DURATION' => array('end-duration'),
- 'ORGANIZER' => array('owner'),
- 'ATTENDEE' => array('participants'),
- 'RRULE' => array('recur_type','recur_interval','recur_data','recur_enddate'),
- 'EXDATE' => array('recur_exception'),
- 'PRIORITY' => array('priority'),
- 'TRANSP' => array('non_blocking'),
- 'CATEGORIES'=> array('category'),
- 'URL' => array(''),
- 'CONTACT' => array(''),
- 'GEO' => array(''),
- 'CREATED' => array(''),
- 'AALARM' => array('alarms'), // NON RFC2445!!
- 'DALARM' => array('alarms'), // NON RFC2445!!
- 'VALARM' => array('alarms'),
- 'VALARM/TRIGGER' => array('alarms/time')
- );
- return true;
- }
-
-
- /**
- * Set the list of ical fields that are supported during the next imports and exports.
- *
- * The list of iCal fields that should be converted during the following imports and exports
- * of VEVENTS is set. This is done by providing a productmanufacturer name and
- * (optionally) a prductname. In a small lookup table the set of currently supported
- * fields for this is searched and then set thus in the class member @ref $supportedFields.
- *
- * @note JVL: I can only see sense in defining supported fields in iCal fields as
- * these are the fields (terminology) that the devices have in common.
- * in addressbook this approach is also --correctly-- taken. Why not here?
- * @param string $_productManufacturer a string indicating the device manufacturer
- * @param string $_productName a further specification of the current device that is used
- * for import or export.
- */
- function setSupportedFields($_productManufacturer='file', $_productName='')
- {
- $defaultFields = array('CLASS','SUMMARY','DESCRIPTION','LOCATION','DTSTART',
- 'DTEND','RRULE','EXDATE','PRIORITY');
- // not: 'TRANSP','ATTENDEE','ORGANIZER','CATEGORIES','URL','CONTACT'
-
- switch(strtolower($_productManufacturer)) {
- case 'nexthaus corporation':
- switch(strtolower($_productName)){
- default:
- // participants disabled until working correctly
- // $this->supportedFields = array_merge($defaultFields,array('ATTENDEE'));
- $this->supportedFields = $defaultFields;
- break;
- }
- break;
-
- // multisync does not provide anymore information then the manufacturer
- // we suppose multisync with evolution
- case 'the multisync project':
- switch(strtolower($_productName)) {
- case 'd750i':
- default:
- $this->supportedFields = $defaultFields;
- break;
- }
- break;
- case 'sonyericsson':
- switch(strtolower($_productName)){
- default:
- $this->supportedFields = $defaultFields;
- break;
- }
- break;
-
- case 'synthesis ag':
- switch(strtolower($_productName)){
- default:
- $this->supportedFields = $defaultFields;
- break;
- }
- break;
- // used outside of SyncML, eg. by the calendar itself ==> all possible fields
- case 'file':
- case 'all':
- $this->supportedFields =
- array_merge($defaultFields,
- array('ATTENDEE','ORGANIZER','TRANSP','CATEGORIES',
- 'DURATION','VALARM','VALARM/TRIGGER'));
-// error_log('OKE setsupportedFields (all)to:'. print_r($this->supportedFields,true));
- break;
-
- // the fallback for SyncML
- default:
- error_log("Client not found: $_productManufacturer $_productName");
- $this->supportedFields = $defaultFields;
- break;
- }
- }
-
-
- /**
- *
- * Exports calendar events as an iCalendar string
- *
- * @note -- PART OF calendar.boical API COMPATIBILITY INTERFACE -----------
- * @param int/array $events (array of) cal_id or array of the events
- * @param string $method='PUBLISH'
- * @return string|boolean string with vCal or false on error
- * (eg. no permission to read the event)
- *
- * @see _hiCal class member to hold a temporary Horde_iCalendar object
- */
- function &exportVCal($events,$version='1.0',$method='PUBLISH')
- {
- $hIcal = &new Horde_iCalendar;
- $euid_export = false;
-
- // set some header values of the Horde_iCalendar object
- $hIcal->setAttribute('PRODID', '-//eGroupWare//NONSGML eGroupWare Calendar '
- . $GLOBALS['egw_info']['apps']['calendar']['version'].'//'
- . strtoupper($GLOBALS['egw_info']['user']['preferences']['common']['lang']));
- $hIcal->setAttribute('VERSION',$version);
- $hIcal->setAttribute('METHOD',$method);
-
- // convert the eGW events to VEVENTS and add them to hIcal
- if(!$this->exportEventsOntoIcal($hIcal, $events,$euid_export))
- return false;
-
- // conversion oke, now let Horde stringify it and deliver as result
- $vcal = $hIcal->exportvCalendar();
- // JVL: destroy the object by hand or does automagic this in php ?
- $hIcal = null;
-
- return $vcal;
-
- }
-
-
-
- /**
- * Convert VEVENT components from an iCalendar string into eGW calendar events
- * and write these to the eGW calendar as new events or changes of existing events
- *
- * @note -- PART OF calendar.boical API COMPATIBILITY INTERFACE -----------
- * @param string $_vcalData ical data string to be imported
- * @param int $cal_id id of the eGW event to fill with the VEvent data
- * when -1 import the VEvent content to new EGW events
- * (JVL HACK when 0 allow change but no deletion user is added to participants
- * if needed)
- * @return boolean $ok false on failure | true on success
- */
- function importVCal($_vcalData, $cal_id=-1)
- {
-
- $hIcal = &new Horde_iCalendar;
- // our (patched) horde classes, do NOT unfold folded lines,
- // which causes a lot trouble in the import, so we do it here
- $_vcalData = preg_replace("/[\r\n]+ /",'',$_vcalData);
-
- // let the Horde_iCalendar object parse the Vcal string into its components
- if(!$hIcal->parsevCalendar($_vcalData)){
- return FALSE;
- }
- $importMode = 'OVERWRITE';
-
- // now import the found VEVENTS into eGW calendar
- if(!$this->importVEventsFromIcal($hIcal, $importMode, $cal_id))
- {
- //error_log('importVCal(): errors in importVEventsFromIcal');
- $hIcal = null;
- return false;
- }
-
- $hIcal = null;
- return true;
- }
-
-
- }
-
-
-?>
diff --git a/egwical/inc/class.boical.inc.compat.php b/egwical/inc/class.boical.inc.compat.php
deleted file mode 100644
index 71d1681c3c..0000000000
--- a/egwical/inc/class.boical.inc.compat.php
+++ /dev/null
@@ -1,69 +0,0 @@
-ei =& CreateObject('egwical.egwical');
- $this->wkobj =& $this->ei->addRsc($this);
- // alternatively the fast, shortcut, road for knowingly experts only:
- //$this->wkobj =& CreateObject('egwical.bocalupdate_vevents');
- //$this->wkobj->setRsc($this);
-
- if ($this->wkobj == false){
- error_log('boical constructor: couldnot add boical resource to egwical: FATAL');
- return false;
- }
- }
-
-
- // now implement the compatibility methods, that are all moved to egwical!
-
- function &exportVCal($events,$version='1.0',$method='PUBLISH')
- {
- return $this->wkobj->exportVCal($events,$version,$method);
- }
-
- function importVCal($_vcalData, $cal_id=-1)
- {
- return $this->wkobj->importVCal($_vcalData, $cal_id);
- }
-
-
- function setSupportedFields($_productManufacturer='file', $_productName='')
- {
- return $this->wkobj->setSupportedFields($_productManufacturer, $_productName);
- }
-
- }
-?>
diff --git a/egwical/inc/class.boinfolog_vtodos.inc.php b/egwical/inc/class.boinfolog_vtodos.inc.php
deleted file mode 100644
index d3ad5a9a98..0000000000
--- a/egwical/inc/class.boinfolog_vtodos.inc.php
+++ /dev/null
@@ -1,561 +0,0 @@
- *
- * -------------------------------------------- *
- * This program is free software; you can redistribute it and/or modify it *
- * under the terms of the GNU General Public License as published by the *
- * Free Software Foundation; either version 2 of the License. *
- **************************************************************************/
-
- /* JVL Todo V0.7:
- * - add structure and API terminology from class.bovevents.inc.php:DONE
- * - rewrite all vevent to vtodo strings: DONE..
- * - Maybe add a supportFields system as done in calendar.bovevents, to allow for
- * handling vtodos for various devices
- * - if done document the supportFields method and show how it can be used
- * - find out how to do deletion based on imported VTODOS ? Can that be done?
- * - check the usage and conversions of user time and server times
- * - add compatibility API for the class infolog.vcalinfolog: DONE but UNTESTED
- * - add ORGANIZER export: DONE (V0.51) removed (dont know map field)
- * - add ORGANIZER import: ... maybe map t info_responsible
- * - add CATEGORIES export: DONE (V0.52)
- * - add CATEGORIE import: DONE (V0.7.01)
- * - add "subtask" export: DONE (v0.52)
- * - add "subtask" import: PARTLY
- * - rewrite PRIORITY export: DONE (V0.52)
- * - rewrite PRIORITY import:DONE (V0.7.01)
- * - repair datecreated: DONT know map field
- * - repair date modified export: PARTLY done
- * - repair startdate or enddate without time details: DONE (V0.7.02)
- */
-
-
- // require_once EGW_SERVER_ROOT.'/infolog/inc/class.boinfolog.inc.php';
- require_once EGW_SERVER_ROOT.'/phpgwapi/inc/horde/Horde/iCalendar.php';
-// require_once EGW_SERVER_ROOT.'/icalsrv/inc/class.egwical.inc.php';
-
- /**
- *
- * iCal vtodos import and export via Horde iCalendar classes
- * @note the routines in this package should be used OO only so that de constructor
- * can initialize the data common to the import and export routines
- * @note this package provides compatibilty routines for class infolog.vcalinfolog
- * this can e.g. be used by making infolog.vcalinfolog a simple extension of
- * infolog.bovtodos
- *
- * @todo move the compatibility functions for vcalinfolog completely to the compat class.
- * There is no need to have them here anymore.
- * @todo rewrite bovtodos to use a ical2egw and supportedFields system
- * @todo IMPORTANT rewrite bovtodos to handle uid_matching analogous to bovevents
- *
- * @package egwical
- * @author Jan van Lieshout mki_
- * This is for methods that MaKe a Ical thing like a component, field, fieldvalue or
- * fieldparameter. Thus these are subdived in:mki_c
to make ical Components like VEVENTS or VALARMS mki_v
to make ical field Values like e.g. a ATTENDEE field valuemki_vp
to make both ical field Values and Parameters mke_
- * This is for methods that MaKe a Egw things like a field of egw event or task.updi_
- * This is for methods that UPDate an Ical component or field. Note that the Ical component
- * to be updated will be passed by reference to these routinesupde_
- * This is for methods that UPDate an Egw entity like an event or task or.... Note again
- * that the Egw entity will be passed by reference to these routines.bocalupdate_vevents
to convert between egw calendar events and VEVENTS
- * and allow import and export of these. When added as a resource to an Egwical object,
- * the representative member for this subclass is set in the attribute $this->buverpr
- *
- * - boinfolog_vtodos
to convert between egw infolog tasks events and VTODOS
- * and allow import and export of these. When added as a resource to an Egwical object,
- * the representative member for this subclass is set in the attribute $this->ivtrpr
- *
- * @note At this moment (V 0.9.01) there is still a little unpleasant piece of extra
- * coding needed to get
- * it working: when you develop a new workerssubclass you must enter it manually in
- * the egwical constructor,
- * so that it can later on automatically be found and matched to the appropiat egw resource.
- * (I couldnot find an easy way to search for existing subclasses so therefore it is needed)
- *
- * @note in future this package may become a full wrapper around the Horde_iCalendar
- * libraries. This way we can keep the relevant egw and ical objects alive between
- * calls so that code could be made faster and less memory consuming..
- *
- * @since 0.9.0 api is incompatible with lower versions
- * @author Jan van Lieshout - * $reg_rscworkers = array($rsclass_name => - * array('workerclass' =>$workerclass_name, - * 'workerobj' => $worker_obj, - * 'vcsup' =>array($velmc1,$velmc2,..)), - * ..) - *- * example of an entry: - *
- * $reg_rscworkers['boinfolog'] = array('workerclass' =>'boinfolog_vtodos', - * 'workerobj' => null, - * 'icalsup' =>array('VTODO')) - *- */ - var $reg_rscworkers = array(); - - - /** Registry for Resources - * - * @var array - * - * The resources registry is an array that holds an entry for - * types of icalendar component class ('VEVENT, VTODO etc.) - * with: - *- 1) an appropiate egw resource object for storing and - * retrieving the info for these components (thus a calendar- or - * infolog- or .. etc. object) and - *- 2) an (instantiated) worker object to handle transport from - * and to the resource. - * The entries of this registry get filled when the - * resources are added to the egwical object by calls to the - * addRsc() method. - * @note multiple entries for the same icalendar component are allowed. - * This can occur when multiple resources can provide e.g. VEVENT data. - * - * Structure of the registry: - *
- * reg_rscs = array($icalcompclass_name => array($rsc_obj, $worker_obj),..) - *- * example of an entry: - *
- * reg_rscs['VTODO'] = array(null, null) - *- */ - var $reg_rscs = array(); - - - - /** - * Constructor, init the auxiliary object @ref $hi and @ref $TASKMAGIC - * and instantiate the @ref $reg_rscworkers workers registry and the - * @ref $reg_rscs resources - * registry. - * @note At this moment (V 0.9.01): when you develop a new workerssubclass you must - * manually add its characteristics via a class call to its provides_work() function - * from within the constructor code. - * (It is needed because I couldnot find an easy way to search for existing subclasses - * yet) - * - */ - function egwical() - { - // actually this would only be needed by the abstract superclass? - $this->hi = &new Horde_iCalendar; - - $this->TASKMAGIC = $GLOBALS['egw_info']['server']['install_id'] - ? $GLOBALS['egw_info']['server']['install_id'] - : 'local'; - // update following list when a new worker subclasses becomes available - // (i.e. copy the info from its $iprovide_work var) - $this->reg_rscworkers = - array_merge( - $this->reg_rscworkers, - bocalupdate_vevents::provides_work(), - boinfolog_vtodos::provides_work() - ); - // error_log('**now reg_workers=' . print_r($this->reg_rscworkers,true)); - $this->reg_rscs = array(); - } - - - /** - * Add a egw resource. - * - * The egw resource (calendar, infolog, ..) in $egw_rsc is added - * to egwical. This will be used for storing and retrieving - * types of iCalendar components (VEVENT, VTODO,..) for which it has corresponding - * egw data elements (like egw events or egw tasks. - * - * Following the WURH pattern, adding the egw resource $rsc will result in - * the creation of a dedicated representative "worker" subclass object to handle the - * transport to and from the resource. The appropiate worker class is looked up in the - * $reg_workers registry. When the worker is created, the resource and its worker will - * be entered as a resource worker pair in the egwical $reg_rscs registry. - * This representative worker object will also be - * returned by reference to the caller. Using this reference the caller can later on do - * specific settings for the worker, (like setSupportedFields()). - * - * @param object $egw_rsc egw resource (like calendar or infolog,..) object that will be - * used by the egwical representative worker class to transport converted - * ical components to and from. - * @return egwical|false $rpr_worker the representative worker class for handling the - * added egw resource. On error false is returned. - */ - function addRsc($egw_rsc) - { - //step 1: detect the egw_rsc class - if (!$rsc_classname = get_class($egw_rsc)) - // bad value for $egw_rsc - return false; - - //step 1a check that the egwrsc is not already registered - foreach($this->reg_rscs as $vc => $rscwkpair){ - if($rscwkpair[0] === $egw_rcs){ - error_log('Warning: egwical.addRsc(): trying add resource multiple times,' . - ' for class: ' . $rsc_classname . ' : ignored'); - return $rscwkpair[1]; - } - } - - //step 1: detect the egw_rsc class - if (!$rsc_classname = get_class($egw_rsc)) - // bad value for $egw_rsc - return false; - - // step 2a: look in reg_rscworkers for appropiate worker class - if (!$wkprov = $this->reg_rscworkers[$rsc_classname]){ - error_log('Error: egwical.addRsc(): no workerclass available yet for resourcetype:' . - $class_name . ' sorry'); - return false; - } - - // step 2b create a workerobject of the correct type - // note that we dont reuse an already available workerobj of the right type because - // probably the workerclasses are not reentrantly coded yet... - if(! $wkobj =& CreateObject('egwical.' . $wkprov['workerclass'])){ - // workerclass object creation problem - return false; - } - // step 2c give the workerobj the egw_rsc to handle - $wkobj->setRsc($egw_rsc); - - // step3: use the found worker info to register the egw_rsc and workerobj for - // each of the supported type of ical elements - foreach ($wkprov['icalsup'] as $icomptype ){ - //error_log('adding reg_rscs['. $icomptype . '] entry'); - $this->reg_rscs = array_merge($this->reg_rscs, - array($icomptype => array($egw_rsc, $wkobj))); - } - // step 4: return the workerclass (representative obj) - - return $wkobj; - } - - - - // ------------- second: below only generic conversion stuff -------------- - - - // --- generic conversion auxilliary routines ------------- - // --- note: this could be left out in the abstract baseclass instantiation - // but is not that much, so leave it get duplicated... - - /** - * @private - * @var string - * Magic unique number used for de/encoding our uids. - * - * This string that contains global unique magic number that is - * unique for our current database installed etc. It is used to recognize - * earlier exported VTODO or VEVENT UID fields as referring to their eGW counterparts. - */ - var $TASKMAGIC='dummy'; - - - /** - * @var array $status_ical2egw - * Conversion of the egw used priority values(0..3) to corresponding ical values(0..9). - * @private - */ - var $priority_egw2ical = - array( - 0 => 0, // undefined - 1 => 9, // low - 2 => 5, // normal - 3 => 1, // high - ); - /** - * @var array $status_ical2egw conversation of the priority ical => egw - * Conversion of the icalendar used priority values(0..9) to corresponding egw values (0..3). - * @private - */ - var $priority_ical2egw = - array( - 0 => 0, // undefined - 9 => 1, 8 => 1, 7 => 1, // low - 6 => 2, 5 => 2, 4 => 2, // normal - 3 => 3, 2 => 3, 1 => 3, // high - ); - - - /** - * @var array $partstatus_egw2ical - * Conversion of the egw used participant status values to the corresponding icalendar - * attendee status terminology. - * @private - */ - var $partstatus_egw2ical = - array( - 'U' => 'NEEDS-ACTION', - 'A' => 'ACCEPTED', - 'R' => 'DECLINED', - 'T' => 'TENTATIVE', - ); - /** - * @var array - * Conversion of the icalendar used attendee status values to the corresponding icalendar - * participants status terminology. - * @private - */ - var $partstatus_ical2egw = - array( - 'NEEDS-ACTION' => 'U', - 'ACCEPTED' => 'A', - 'DECLINED' => 'R', - 'TENTATIVE' => 'T', - ); - - - /** - * @var array $recur_egw2ical - * Conversion of egw recur-type to ical FREQ values for RRULE fields - * @private - */ - var $recur_egw2ical = - array( - MCAL_RECUR_DAILY => 'DAILY', - MCAL_RECUR_WEEKLY => 'WEEKLY', - MCAL_RECUR_MONTHLY_MDAY => 'MONTHLY', - MCAL_RECUR_MONTHLY_WDAY => 'MONTHLY', - MCAL_RECUR_YEARLY => 'YEARLY', - ); - // BYMONHTDAY={1..31}, BYDAY={1..5}{MO..SO} - - /** - * @var array - * recur_days translates MCAL recur-days to verbose labels - * (copied from class.bocal.inc.php file - * @private - */ - var $recur_days = - array( - MCAL_M_MONDAY => 'Monday', - MCAL_M_TUESDAY => 'Tuesday', - MCAL_M_WEDNESDAY => 'Wednesday', - MCAL_M_THURSDAY => 'Thursday', - MCAL_M_FRIDAY => 'Friday', - MCAL_M_SATURDAY => 'Saturday', - MCAL_M_SUNDAY => 'Sunday', - ); - - /** - * @var array - * Get sequential indexes for the daynames in a week. Used for recurrence count - * calculations. - */ - var $dowseqid = - array('SU' => 1, 'MO' => 2, 'TU' => 3, 'WE' => 4, 'TH' => 5, 'FR' => 6, 'SA' => 7); - - - // --- generic conversion auxilliary routines ------------- - - /** - * Parse a vCalendar string into an Horde_iCalendar object. - * - * To actually parse the string, the Horde_iCalendar in member @ref $hi is used. - * @param string $vcalstr the icalendar input string - * @return boolean|Horde_iCalendar the resulting parsed elements collected in a - * horde ical object. On error: false - */ - function parsevCalendar($vcalstr) - { - // unfoldlines as this was removed from our horde stuff - $vcalstr = preg_replace("/[\r\n]+ /",'',$vcalstr); - - // $this->hi->clear(); - if(!$this->hi->parsevCalendar($vcalstr)){ - error_log('egwical parsevCalendar: ERROR- couldnot parse..'); - return false; - } - - return $this->hi; - } - - - - - /** - * Generate ical UID from egw id. - * - * generate a unique id, with the egw id encoded into it, which can be - * used for later synchronisation. - * @param string|int $egw_id eGW id of the egw entity (event, task,..) - * @param string $app_prefix prefix to use in ecnoding the name - * - * @return string|false on success the global unique id. On error: false. - * - * Uses @ref $TASKMAGIC string that holds our unique ID - */ - function mki_v_guid($egw_id,$app_prefix='egw') - { - if (empty($egw_id)) - return false; - return $app_prefix .'-' . $egw_id. '-' . $this->TASKMAGIC; - } - - - - /** - * Try to decode an egw id from a ical UID - * - * @param string $guid the global Icalendar UID value - * @param string $app_prefix prefix to be found in the encoding - * @return false|int On error: false. - * On success: local egw todo id. - */ - function mke_guid2id($guid,$app_prefix='egw') - { - // error_log('mke_guid2id: trying to recover id from' . $guid); - if (!preg_match('/^' . $app_prefix . '-(\d+)-' . - $this->TASKMAGIC . '$/',$guid,$matches)) - return false; - - // error_log("mke_guid2id: found (" . $matches[1] . ")"); - return $matches[1]; - } - - - - /** - * Get database add date of event or todo - * @private - * @param int $id id of event or todo - * @param string $appname name of the application (='calendar' or 'infolog') - * @return int $createdate of db insert or false on error - */ - function get_TSdbAdd($id,$appname='calendar') - { - if (!(($appname == 'calendar') || ($appname == 'infolog'))) - return false; - if (! $auid = $GLOBALS['egw']->common->generate_uid($appname,$id)) - return false; - - return $GLOBALS['egw']->contenthistory->getTSforAction($auid,'add'); - } - - - /** - * Convert a egw prio into a value for the ical property PRIORITY - * @param int $eprio priority in egw (0..3) - * @return int $iprio conversion of $eprio as value (0..9) for the ical PRIORITY prop - */ - function mki_v_prio($eprio = 0) - { - return $this->priority_egw2ical[$eprio]; - } - - /** - * Convert a ical prio into a value for egw - * @param int $iprio priority in ical (0..9) - * @return int $eprio conversion of $iprio as value (0..3) for egw - */ - function mke_prio($iprio = 0) - { - return $this->priority_ical2egw[$iprio]; - } - - - - /** - * Translate cat-ids to array with id-name pairs - * - * JVLNOTE: boldly copied from class.xmlrpc_server.inc.php because I donot know how - * to instantiate $GLOBALS['server'] (that provides this method) atm. - * @note THIS CODE SHOULD BE SOMEWHERE ELSE: IT HAS NOTHING TO DO WITH ICAL!! - * @param array $cids the list with category ids - * @return string|false $idnamescstr commasep string with names for the category ids or - * on error false - */ - function cats_ids2idnamescstr($cids) - { - if(empty($cids)) - return false; - - if (!is_object($GLOBALS['egw']->categories)) - $GLOBALS['egw']->categories = CreateObject('phpgwapi.categories'); - - $idnames = array(); - foreach($cids as $cid) { - if ($cid) - $idnames[$cid] = stripslashes($GLOBALS['egw']->categories->id2name($cid)); - } - return implode(',',$idnames); - } - - - // ************ JVL CHECK THE CODE BENEATH ***************** - // oke: seems to work for a single categorie (tested form bovtodos calls) - - /** - * Translate catnames back to cat-ids creating/modifying cats on the fly - * - * JVLNOTE boldly copied from class.xmlrpc_server.inc.php because I donot know how - * to instantiate $GLOBALS['server'] (that provides this method) atm. - * - * @note THIS CODE SHOULD BE SOMEWHERE ELSE: IT HAS NOTHING TO DO WITH ICAL!! - * @param array $cnames list with category names - * @return string $cidscstr commasep string with ids generated or found for - * the category names. - */ - function cats_names2idscstr($cnames,$owner_id,$app_name='infolog') - { - if (empty($cnames)) - return false; - - if (!is_object($catsys =& $GLOBALS['egw']->categories)) { - $GLOBALS['egw']->categories =& CreateObject('phpgwapi.categories', - $owner_id,$app_name); - $catsys =& $GLOBALS['egw']->categories; - } - $cids = array(); - foreach($cnames as $name) { - if (!($cid = $catsys->name2id($name))) { - // existing cat-name use the id - // new cat - $cid = $catsys->add(array('name' => $name,'descr' => $name)); - } - $cids[] = (int)$cid; - } - return implode(',',$cids); - } - - - /** - * Convert and egw account id into a iCalendar CAL-ADDRESS type value string - * @param int $aid egw account(person) id - * @return string $cls cal_address format string (mailto:
year
four digit year field
- * - month
integer month number
- * - mday
integer day of month number
- * - hour
integer hour
- * - minute
integer minutes
- * - second
integer seconds
- *
- * @param int $utime a unixtimestamp assumed in utc timezone
- * @return array The date in a6date in local timezone format.
- */
- function utimetoa6($utime)
- {
- $t=getdate($utime);
- return array('hour' => $t['hours'], 'minute' => $t['minutes'],
- 'second' => $t['seconds'],'month' => $t['mon'],
- 'mday' => $t['mday'],'year' => $t['year']);
- }
-
-
- /**
- * Convert a 6 field hash array in the current active timezone to a unix timestamp.
- *
- * This is basically the inverseof php getdate() function.
- *
- * The a6date array has fields as in the php getdate() function:
- * - year
four digit year field
- * - month
integer month number note: mon, not month!!
- * - mday
integer day of month number
- * - hour
integer hour
- * - minute
integer minutes
- * - second
integer seconds
- *
- * @param array $a6 The date in a6date in local timezone format.
- * @return int a unixtimestamp assumed in utc timezone
- */
- function a6toutime ($a6)
- {
- return mktime($a6['hour'],$a6['minute'],$a6['second'],
- $a6['month'],$a6['mday'],$a6['year']);
- }
-
-
- /**
- * Convert the egw person id and its participant status into
- * an ATTENDEE value and parameterslist
- *
- * The resulting value of the ATTENDEE field will be in CAL_ADDRESS type format.
- * The resulting parameterlist may contain fields of the following:
- * - ROLE={CHAIR|REQ-PARTICIPANT|OPT-PARTICIPANT|NON-PARTICIPANT}
- * this parameter is NOT used by eGW atm.
- * - RSVP={TRUE|FALSE}
- * resonse is expected, not set in eGW then status will have value U
.
- * - PARTSTAT={NEEDS-ACTION|ACCEPTED|DECLINED|TENTATIVE|DELEGATED|
- * COMPLETED|IN-PROGRESS}
everything from delegated is NOT used by eGW atm.
- * - CUTYPE={INDIVIDUAL|GROUP|RESOURCE|ROOM|UNKNOWN}
only GROUP or INDIVIDUAL
- * are produced atm.
- *
- * @param int $pid egw id of a participant
- * @param array $partstat egw particpant status of person with $uid
- * @param int $owner_id id of the owner of the todo or event (needed to set the CHAIR)
- * @return array ($val,$params) list with value and parameter-array for ATTENDEE property
- * @note no error handling atm
- */
- function mki_vp_4ATTENDEE($pid,$partstat,$owner_id)
- {
- $atdval = $this->mki_v_CAL_ADDRESS($pid);
- // first parameter
- $atdpars = $this->mki_p_CN($pid);
- $atdpars['ROLE'] = ($pid == $owner_id) ? 'CHAIR' : 'REQ-PARTICIPANT';
- $atdpars['RSVP'] = $partstat == 'U' ? 'TRUE' : 'FALSE';
- $atdpars['CUTYPE'] = $GLOBALS['egw']->accounts->get_type($uid) == 'g'
- ? 'GROUP' : 'INDIVIDUAL';
- $atdpars['PARTSTAT'] = $this->partstatus_egw2ical[$partstat];
-
- return array($atdval,$atdpars);
- }
-
-
- /**
- * Make a value of type RECUR for a ical RRULE property
- *
- * A simple example:
- * ( RRULE) : (FREQ=MONTHLY;COUNT=10;INTERVAL=2)
- * here the first part between parenthesis is property and the
- * second is a value of type RECUR
- *
- * @param string $recur_type the type of recurrence frequence we have
- * @param mixed $recur_data Todo describe this parameter...
- * @param int $recur_interval Todo describe this parameter...
- * @param utime $recur_enddate the final date that the recurrence ends
- * @return string ($recurval) a value format as RECUR for the RRULE property
- * (if a time is set)
- */
- function mki_v_RECUR($recur_type,$recur_data,$recur_interval,$recur_start,$recur_enddate)
- {
- $recur = array();
- $recurval ='FREQ=' . $this->recur_egw2ical[$recur_type];
-
- switch ($recur_type) {
- case MCAL_RECUR_WEEKLY:
- $days = array();
- foreach($this->recur_days as $did => $day) {
- if ($recur_data & $did)
- $days[] = strtoupper(substr($day,0,2));
- }
- $recur['BYDAY'] = implode(',',$days);
- break;
- case MCAL_RECUR_MONTHLY_MDAY: // date of the month: BYMONTDAY={1..31}
- $recur['BYMONTHDAY'] = (int) date('d',$recur_start);
- break;
- case MCAL_RECUR_MONTHLY_WDAY: // weekday of the month: BDAY={1..5}{MO..SO}
- $recur['BYDAY'] = (1 + (int) ((date('d',$recur_start)-1) / 7))
- . strtoupper(substr(date('l',$recur_start),0,2));
- break;
- }
-
- if ($recur_interval > 1)
- $recur['INTERVAL'] = $recur_interval;
-
- if ($recur_enddate){
-
-// $expdt= $this->hi->_exportDateTime($recur_enddate);
-// error_log('EXPORT UNTIL=' . $recur_enddate . ' expdDT:' . $expdt);
-
- $recur['UNTIL'] = $this->hi->_exportDateTime($recur_enddate);
- }
- foreach($recur as $parnam => $parval){
- $recurval .= ';' . $parnam . '=' . $parval;
- }
- return $recurval;
- }
-
- /**
- * Make a value (commasep string of dates) for the EXDATE property
- *
- * In the conversion you can chose between a commastring of DATES or DATE-TIMES
- * @param array $recur_exceptions list with utime exception dates
- * @param boolean $dtmode if true generate DATE-TIME dates else DATES
- * @return array ($exdval, $exdparams) a list with the value and parameters generated
- */
- function mki_vp_4EXDATE($recur_exceptions,$dtmode=false)
- {
- $days = array();
- foreach($recur_exceptions as $day) {
- $days[] = date('Ymd',$day);
- }
-
- $exdparams = array();
- if(!$dtmode)
- $exdparams['VALUE'] = 'DATE';
- return array( implode(',',$days), $exdparams);
- }
-
- /**
- * Convert DDT possible DATE|DATE-TIME params and a value commalist
- * into an array of utime dates.
- *
- * Some examples
- * - * ex1: ...;VALUE=DATE:20060123,20060124 - * ex2: ...:20060118T101500Z,20060119T1000Z - * ex3: ...:VALUE=DATE-TIME:20060118T101500Z,20060119T1000Z - *- * @note unfortunately horde_icalendar will parse ex1 into an array of - * array(month => .. , mday => .. , year=> ) - * @param array $dvals list of dates - * @return array $udays list with the days from the input list in utime format - */ - function mke_EXDATEpv2udays($params, $dvals) - { - //$exdays = (!is_array($dvals)) ? $dvals : array($dvals); - $exdays = $dvals; - - if (count($exdays) < 1) - return false; -//error_log('EXDAYS params=' . print_r($params,true)); -//error_log('EXDAYS exploded=' . print_r($exdays,true)); - if($params['VALUE'] == 'DATE'){ - // list is in awful horde DATE mode - // convert the date somehow to udays - $udays = array(); - foreach ($exdays as $day){ - $udays[] = $this->mke_DDT2utime($day); - } - } else { - // assume list is in DT mode - $udays = &$exdays; - } - - return $udays; - } - - - - /** - * Convert a RECUR value into the corresponding egw recur fields. - * - * A value of type RECUR (for a ical RRULE property) is parsed - * into the 4 related egw fields. Fields unfilled stay false A - * simple example:
( RRULE) :
- * (FREQ=MONTHLY;COUNT=10;INTERVAL=2)
here the first
- * part between parenthesis is property and the second is a
- * value of type RECUR
- *
- * @bug RECUR: MONTHLY;BYMONTHDAY, only ok if startdate is also on this MONTHDAY
- * egw problem.
- *
- * @todo RECUR: COUNT=xx;WEEKLY;BYDAY, may miss the last occurence, if not started
- * on a BYDAY day: to be fixed! prio=low
- *
- * @todo RECUR: YEARLY seems only to support the most basic variant?? To be checked!
- *
- * @author JVL (required some thinking..)
- * @param string $recur RECUR type value of RRULE
- * @param mixed $rstart start date in UTC format
- * @return array $rar a assoc array with keys: 'recur_type', 'recur_data', 'recur_interval'
- * and 'recur_enddate'. On error: false
- * @note the class var @ref $hi is used as auxiliary Horde_iCalendar object
- */
- function mke_RECUR2rar($recur,$rstart)
- {
- $ustart = $this->mke_DDT2utime($rstart);
-
- // a6sd is in Icalsrv usertime
- $a6sd = $this->utimetoa6($ustart);
-
-// error_log('IMPORT RECURVAL=' . $recur . 'ustart=' .$ustart);
-
-
- $r_data = 0;
- $dow =array(); // for weekly count calc
- $r_type = $r_interval = $r_end = $r_count = false;
-
- $type = preg_match('/FREQ=([^;: ]+)/i',$recur,$matches)
- ? $matches[1] : $recur[0];
- if ($type == false)
- return false;
-
- // vCard 2.0 values for all types
- if (preg_match('/UNTIL=([0-9TZ]+)/',$recur,$matches))
- $r_end = $this->hi->_parseDateTime($matches[1]);
-
- if (preg_match('/INTERVAL=([0-9]+)/',$recur,$matches))
- $r_interval = (int) $matches[1];
-
- // with count given we must calculate r_end
- if (preg_match('/COUNT=([0-9]+)/',$recur,$matches)){
- $r_count = (int) $matches[1];
- // count calculation auxvars
- $c_interval = ($r_interval) ? $r_interval : 1; //interval
- $c_count = ($r_count - 1)*$c_interval;
- }
-
- switch($type) {
-
- case 'W':
- case 'WEEKLY':
- $days = array();
- if(preg_match('/W(\d+) (.*) (.*)/',$recur, $recurMatches)) { // 1.0
- $r_interval = $recurMatches[1];
- $c_interval = $r_interval;
- $days = explode(' ',trim($recurMatches[2]));
- } elseif (preg_match('/BYDAY=([^;: ]+)/',$recur,$recurMatches)) { // 2.0
- $days = explode(',',$recurMatches[1]);
- }
- if ($days) {
- foreach($this->recur_days as $mid => $day) {
- if (in_array(strtoupper(substr($day,0,2)), $days)){ //WAS ERROR IN BOICAL!!
- $r_data |= $mid;
- }
- }
- $r_type = MCAL_RECUR_WEEKLY;
- }
- // --------- r_end calculation from COUNT and BYDAYs ---
- if ($r_count) {
- $c_count = ($r_count - 1)*$c_interval;
- foreach($days as $wdd){
- $dow[] = $this->dowseqid[$wdd];
- }
- sort($dow);
- $ustart_seqid = $this->dowseqid[strtoupper(substr(date('D',$ustart),0,2))];
- // find index of start day 0..
- $sdi = 0; //in case start is not on a byday
- foreach($dow as $i) {
- if ($dow[$i] == $ustart_seqid){ // hope start is on byday
- $sdi = $i; break;
- } elseif($dow[$i] >= $ustart_seqid){ // else next byday
- $sdi = $i; break;
- }
- }
- $edi = $sdi + $c_count; // end day index
- $dur = 0; // duration until end in days
- $wic = count($dow); // week indexes count
- $dur = 7 * floor($edi / $wic) + $dow[($edi % $wic)];
- $dur -= $dow[$sdi];
- $a6sd['mday'] += intval($dur);
- $r_end = $this->a6toutime($a6sd);
- // destroy $a6sd here..
-
-//error_log('count=' . $c_count .'sdi=' . $sdi . ' edi=' . $edi .
-// ' wic=' .$wic . ' dur=' .$dur . ' r_end=' . $r_end);
- }
- break;
-
- case 'D': // 1.0
- if(!preg_match('/D(\d+) (.*)/',$recur, $recurMatches))
- break;
- $c_interval = $r_interval = $recurMatches[1];
- $r_end = $this->hi->_parseDateTime($recurMatches[2]);
- // fall-through
-
- case 'DAILY': // 2.0
- $r_type = MCAL_RECUR_DAILY;
- if ($r_count) { // count calc is still experimental!
- $c_count = ($r_count - 1)*$c_interval;
- $a6sd['mday'] += $c_count;
- $r_end = $this->a6toutime($a6sd);
- }
- break;
-
- case 'MONTHLY':
- $r_type = strstr($recur,'BYDAY') ?
- MCAL_RECUR_MONTHLY_WDAY : MCAL_RECUR_MONTHLY_MDAY;
- // break;
- //fall through
-
- case 'M':
- if(preg_match('/MD(\d+) (.*)/',$recur, $recurMatches)) {
- $r_type = MCAL_RECUR_MONTHLY_MDAY;
- $c_interval = $r_interval = $recurMatches[1];
- } elseif(preg_match('/MP(\d+) (.*) (.*) (.*)/',$recur, $recurMatches)) {
- $r_type = MCAL_RECUR_MONTHLY_WDAY;
- $c_interval = $r_interval = $recurMatches[1];
- }
- //
- if ($r_count) { // count calc is still experimental!
- switch ($r_type) {
- case MCAL_RECUR_MONTHLY_MDAY:
- // error_log('DOING MOTNHLY MDAY'); Egw doesnot handle this special, see todo
- $c_count = ($r_count - 1)*$c_interval; // maybe changed because 1.0 found
- $a6sd['month'] += $c_count;
- $r_end = $this->a6toutime($a6sd);
- break;
-
- case MCAL_RECUR_MONTHLY_WDAY:
- $c_count = ($r_count - 1)*$c_interval; // maybe changed because 1.0 found
- // startday
- $dowsd = date('w',$this->a6toutime($a6sd)); // day of week for sd
- //end day, first try
- $a6ed = array_diff($a6sd,array()); $a6ed['month'] += $c_count;
- //day1 of startmonth
- $a6smd1 = array_diff($a6sd,array()); $a6smd1['mday'] = 1;
- $dowsmd1 = date('w',$this->a6toutime($a6smd1)); // day of week for smd1
-
- //startdate as day of 5week segment, anchored on and afer smd1
- $do5wsegsd = $dowsmd1 + $a6sd['mday'];
- if($dowsmd1 > $dowsd)
- $do5wsegsd -= 7;
-
- $a6ed['mday'] =1;
- $dowemd1 = date('w',$this->a6toutime($a6ed)); // endmonthday1 as day of week
- $a6ed['mday'] = $do5wsegsd - $dowemd1;
- if($dowemd1 > $dowsd)
- $a6ed['mday'] += 7;
-
-// error_log('dowsd='. $dowsd . ' dowsmd1='. $dowsmd1 . ' do5wsegsd=' . $do5wsegsd .
-// ' dowemd1='. $dowemd1 . ' edmday=' . $a6ed['mday'] );
- $r_end = $this->a6toutime($a6ed);
- break;
- }
- }
- break;
-
-
- case 'Y': // 1.0
- if(!preg_match('/YM(\d+) (.*)/',$recur, $recurMatches))
- break;
- $c_interval = $r_interval = $recurMatches[1];
- // fall-through
-
- case 'YEARLY': // 2.0
- $r_type = MCAL_RECUR_YEARLY;
- if ($r_count) { // count calc is still experimental!
- // is there only this BYMONTHDAY support?
- $c_count = ($r_count - 1)*$c_interval; // maybe changed because 1.0 found
- $a6sd['year'] += $c_count;
- $r_end = $this->a6toutime($a6sd);
- }
- break;
- }
-
- return array('recur_type' => $r_type,
- 'recur_data' => $r_data,
- 'recur_interval' => $r_interval,
- 'recur_enddate' => $r_end );
- }
-
-
- /**
- * Parse a CAL_ADDRESS and try to find the associated egw person_id
- * @param string $attrval CAL_ADDRESS type value string
- * @return int|false $pid associated (by email) egw pid. On error: false.
- */
- function mke_CAL_ADDRESS2pid($attrval)
- {
- if (preg_match('/MAILTO:([@.a-z0-9_-]+)/i',$attrval,$matches) &&
- ($pid = $GLOBALS['egw']->accounts->name2id(strtolower($matches[1]),'account_email'))){
- return $pid;
- } else {
- return false;
- }
- }
-
- /**
- * Parse a CAL_ADDRESS and PARAMS to find the CN name and email
- * @param string $aval CAL_ADDRESS type value string
- * @param array $aparams parameters for a ATTENDEE
- * @return array $cneml assoc array with 'cn' and 'mailto' field
- */
- function mke_ATTENDEE2cneml($aval,$aparams)
- {
- $cneml = array('cn' => '', 'mailto' => '');
-
- // if (preg_match('/MAILTO:([@.a-z0-9_-]+)/i',$aval,$matches))
- // lets be a bit more relaxed here (rfc1378)..
- // try for "Fnam Lnam " first
- if (preg_match('/MAILTO:([^<]+)<([@.a-z0-9_-]+)>/i',$aval,$matches)){
- $cneml['cn'] = $matches[1];
- $cneml['mailto'] = $matches[2];
- // try for second
- }elseif (preg_match('/MAILTO:([@.a-z0-9_-]+)/i',$aval,$matches)){
- $cneml['mailto'] = $matches[1];
- }
- // a CN from the params overrules one from the mailto
- if(isset($aparams['CN']))
- $cneml['cn'] = $aparams['CN'];
-
- return $cneml;
- }
-
- /**
- * Update an egw event description with a list of nonegw participants.
- *
- * note: this is a adhoc solution, preferably the nonegw participants
- * should be added automatically to the addressbook
- * @param string &$edescription the participants are append to this string as
- * a string formatted ([cn: name:mailto: eml] [] ... )
- * @param array &$ne_participants array of the non egw participants as
- * ('cn' =>, 'mailto' =>) pairs
- * @return true
- */
- function upde_nonegwParticipants2description(&$edescription,&$ne_participants)
- {
- $edescription.= "\n - non egw participants:\n(";
- $neplist = array();
- foreach ($ne_participants as $nep){
-// $li = '[cn:' . $nep['cn'];
-// $li .= ($nep['mailto']) ? ';mailto:' . $nep['mailto'] .']' : ']';
- $li = '[' . $nep['cn'];
- $li .= ($nep['mailto']) ? '<' . $nep['mailto'] .'>]' : ']';
-
- $neplist[]= $li;
- }
- $edescription .= implode("\n",$neplist) . ')';
-
- return true;
- }
-
-
- /**
- * Search a ical parameterlist for possible setting for a egw participant status.
- *
- * Parse the params array to find a PARTSTAT param, convert this to
- * a egw partstatus (may occur e.g. in ATTENDEE params)
- * @param array $params params of e.g. an ical ATTENDEE field
- * @return array|false $epartstatus egw term for particpant status if detected else false
- */
- function mke_params2partstat($params)
- {
- if (!isset($params['PARTSTAT']))
- return false;
-
- return $this->partstatus_ical2egw[strtoupper($params['PARTSTAT'])];
- }
-
- /**
- * Add (append) an new attribute (aka field) to the vevent.
- *
- * @param horde_iCalendar_vevent $vevent obj to which the attribute is added
- * @param string $aname name for the new attribute
- * @param mixed $avalue value for the new attribute
- * @param array $aparams parameters for the new attribute
- * @return true
- */
- function addAttributeOntoVevent(&$vevent,$aname,&$avalue,&$aparams)
- {
-
- // it appears that translation->convert() can translate an array
- // (that is: the values!, not the keys though)
- // so lets apply it to the avalue and aparams, that should be enough!
-// error_log('n:' . $aname . 'v:' . $avalue);
- $valueData =
- $GLOBALS['egw']->translation->convert($avalue,
- $GLOBALS['egw']->translation->charset(),
- 'UTF-8');
- $paramData =
- $GLOBALS['egw']->translation->convert( $aparams,
- $GLOBALS['egw']->translation->charset(),
- 'UTF-8');
-// error_log('n:' . $aname . 'v:' . $valueData);
- $vevent->setAttribute($aname, $valueData, $paramData);
- $options = array();
- // JVL:is this really needed?
- if (is_string($valueData)){
-
-// // JVL: TEMPORARY SWITCHED OFF... TURN ON AGAIN!!!
-// if(!(in_array($aname, array('RRULE')))
-// && preg_match('/([\000-\012\015\016\020-\037\075])/',$valueData)) {
-// $options['ENCODING'] = 'QUOTED-PRINTABLE';
-// }
-
- if( (preg_match('/([\177-\377])/',$valueData))) {
- $options['CHARSET'] = 'UTF-8';
- }
- }
- $vevent->setParameter($aname, $options);
-
- return true;
- }
-
-
- /**
- * Convert egw alarm info to a ical VALARM object.
- *
- * Make a VALARM object form data in $alarms and $utstart (in utc)
- * and with $vevent as container
- * @param array &$alarm a single egw alarm array to be used
- * @param horde_object &$vcomp that will be the container for the valarm
- * mostly vevent or vtodo.
- * @param array &$veExportFields list with fields that may get imported
- * @return horde_iCalendar_valarm|false valarm object or, on error, false.
- */
- function mki_c_VALARM(&$alarm, &$vcomp, $utstart,&$veExportFields){
-
-// error_log('export comp-alarm-field:' . print_r($alarm,true));
-
- $valarm = Horde_iCalendar::newComponent('VALARM',$vevent);
-
- //try first an offset
- if($durtime = -$alarm['offset']){
- $valarm->setAttribute('TRIGGER',
- $durtime,
- array('VALUE' => 'DURATION',
- 'RELATED' => 'START'));
- // no success then try a date-time
- } elseif($dtime = $alarm['time']){
- $valarm->setAttribute('TRIGGER',
- $ddtime,
- array('VALUE' => 'DATE-TIME'));
- } else{
- $valarm = null;
- return false;
- }
- $vcomp->addComponent($valarm);
-
- return $valarm;
- }
-
-
- /**
- * Update the egw alarms array with info from a VALARM
- * @param array &$alarms the the egw alarms array to be updated
- * @param horde_iCalendar_valarm $valarm ref to the valarm component to be updated
- * @param int $user_id the user that will own the alarms found
- * @param array &$veImportFields with fields that may get imported
- * @return true
- */
- function upde_c_VALARM2alarms(&$alarms,&$valarm,$user_id,&$veImportFields){
-
- // lets see what supported veImportFields we can get from the valarm
- foreach($valarm->_attributes as $vattr) {
- // $vattrval = $GLOBALS['egw']->translation->convert($vattr['value'],'UTF-8');
- // handle only supported fields
- if(!in_array('VALARM/' . $vattr['name'], $veImportFields))
- continue;
-
- switch($vattr['name']) {
- case 'TRIGGER':
- $vtype = (isset($vattr['params']['VALUE']))
- ? $vattr['params']['VALUE'] : 'DURATION'; //default type
- switch ($vtype) {
- case 'DURATION':
- $alarms[] = array('offset' => -$vattr['value']);
- break;
- case 'DATE-TIME':
- $alarms[] = array('time' => $vattr['value']);
- break;
- default:
- // we should also do ;RELATED=START|END
- error_log('VALARM/TRIGGER: unsupported value type:' . $vtype);
- }
- break;
-// case 'ACTION':
-// break;
-// case 'DISPLAY':
-// break;
-
- default:
- error_log('VALARM field:' .$vattr['name'] .':'
- . print_r($vattrval,true) . ' HAS NO CONVERSION YET');
- }
- }
-// error_log('updated alarms to:' . print_r($alarms,true));
- return true;
- }
-
-
-
-
-
-
- }
-
-?>
\ No newline at end of file
diff --git a/egwical/inc/class.vcalinfolog.inc.compat.php b/egwical/inc/class.vcalinfolog.inc.compat.php
deleted file mode 100644
index 19d81d5694..0000000000
--- a/egwical/inc/class.vcalinfolog.inc.compat.php
+++ /dev/null
@@ -1,72 +0,0 @@
-ei =& CreateObject('egwical.egwical');
- // $this->wkobj =& $this->ei->addRsc($this);
- // or the fast, shortcut, road for knowingly experts only:
- $this->wkobj =& CreateObject('egwical.boinfolog_vtodos');
- $this->wkobj->setRsc($this);
-
- if ($this->wkobj == false){
- error_log('boical constructor: couldnot add bocal resource to egwical: FATAL');
- return false;
- }
- }
-
-
- // now implement the compatibility methods, that are all moved to egwical!
-
- function exportVTODO($_taskID, $_version)
- {
- return $this->wkobj->exportVTODO($_taskID, $_version);
- }
-
- function importVTODO(&$_vcalData, $_taskID=-1)
- {
- return $this->wkobj->importVTODO($_vcalData, $_taskID);
- }
-
-
-// function setSupportedFields($_productManufacturer='file', $_productName='')
-// {
-// return $this->wkobj->setSupportedFields($_productManufacturer, $_productName);
-// }
-
- }
-?>