remove addressbook, calendar and infolog classes for xmlrpc, as we droped xmlrpc support

This commit is contained in:
Ralf Becker 2014-01-28 08:28:20 +00:00
parent d3e9f43b94
commit ad57c7ee86
3 changed files with 0 additions and 1139 deletions

View File

@ -1,481 +0,0 @@
<?php
/**
* Addressbook - xmlrpc access
*
* The original addressbook xmlrpc interface was written by Joseph Engo <jengo@phpgroupware.org>
* and Miles Lott <milos@groupwhere.org>
*
* Please note: dont use addressbook_... naming convention, as it would break the existing xmlrpc clients
*
* @link http://www.egroupware.org
* @author Ralf Becker <RalfBecker-AT-outdoor-training.de>
* @package addressbook
* @copyright (c) 2007/8 by Ralf Becker <RalfBecker-AT-outdoor-training.de>
* @license http://opensource.org/licenses/gpl-license.php GPL - GNU General Public License
* @version $Id$
*/
/**
* Class to access AND manipulate addressbook data via XMLRPC or SOAP
*
* eGW's xmlrpc interface is documented at http://egroupware.org/wiki/xmlrpc
*
* @link http://egroupware.org/wiki/xmlrpc
*/
class boaddressbook
{
/**
* Instance of the contacts class
*
* @var contacts
*/
var $contacts;
/**
* Field-mapping for certain user-agents
*
* @var array
*/
var $mapping=array();
/**
* User agent: 'KDE-AddressBook', 'eGWOSync', ...
*
* @var string
*/
var $user_agent;
/**
* Contstructor
*
* @return boaddressbook
*/
function __construct()
{
$this->contacts = $GLOBALS['egw']->contacts;
// are we called via xmlrpc?
if (!is_object($GLOBALS['server']) || !$GLOBALS['server']->last_method)
{
die('not called via xmlrpc');
}
$this->set_mapping_for_user_agent();
}
/**
* This handles introspection or discovery by the logged in client,
* in which case the input might be an array. The server always calls
* this function to fill the server dispatch map using a string.
*
* @param string/array $_type='xmlrpc' xmlrpc or soap
* @return array
*/
function list_methods($_type='xmlrpc')
{
if(is_array($_type))
{
$_type = $_type['type'] ? $_type['type'] : $_type[0];
}
switch($_type)
{
case 'xmlrpc':
return array(
'read' => array(
'function' => 'read',
'signature' => array(array(xmlrpcStruct,xmlrpcStruct)),
'docstring' => lang('Read a single entry by passing the id and fieldlist.')
),
'save' => array(
'function' => 'save',
'signature' => array(array(xmlrpcStruct,xmlrpcStruct)),
'docstring' => lang('Write (update or add) a single entry by passing the fields.')
),
'write' => array( // old 1.2 name
'function' => 'save',
'signature' => array(array(xmlrpcStruct,xmlrpcStruct)),
'docstring' => lang('Write (update or add) a single entry by passing the fields.')
),
'delete' => array(
'function' => 'delete',
'signature' => array(array(xmlrpcString,xmlrpcString)),
'docstring' => lang('Delete a single entry by passing the id.')
),
'search' => array(
'function' => 'search',
'signature' => array(array(xmlrpcStruct,xmlrpcStruct)),
'docstring' => lang('Read a list / search for entries.')
),
'categories' => array(
'function' => 'categories',
'signature' => array(array(xmlrpcBoolean,xmlrpcBoolean)),
'docstring' => lang('List all categories')
),
'customfields' => array(
'function' => 'customfields',
'signature' => array(array(xmlrpcArray,xmlrpcArray)),
'docstring' => lang('List all customfields')
),
'list_methods' => array(
'function' => 'list_methods',
'signature' => array(array(xmlrpcStruct,xmlrpcString)),
'docstring' => lang('Read this list of methods.')
)
);
case 'soap':
return array(
'read' => array(
'in' => array('int','struct'),
'out' => array('array')
),
'write' => array(
'in' => array('int','struct'),
'out' => array()
),
'categories' => array(
'in' => array('bool'),
'out' => array('struct')
),
'customfields' => array(
'in' => array('array'),
'out'=> array('struct')
)
);
default:
return array();
}
}
/**
* Get field-mapping for user agents expecting old / other field-names
*
* @internal
*/
function set_mapping_for_user_agent()
{
//error_log("set_mapping_for_user_agent(): HTTP_USER_AGENT='$_SERVER[HTTP_USER_AGENT]'");
switch($this->user_agent = $_SERVER['HTTP_USER_AGENT'])
{
case 'KDE-AddressBook':
$this->mapping = array(
'n_fn' => 'fn',
'modified' => 'last_mod',
'tel_other' => 'ophone',
'adr_one_street2' => 'address2',
'adr_two_street2' => 'address3',
'freebusy_uri' => 'freebusy_url',
'grants[owner]' => 'rights',
'jpegphoto' => false, // gives errors in KAddressbook, maybe the encoding is wrong
'photo' => false, // is uncomplete anyway
'private' => 'access', // special handling necessary
'adr_one_type' => "'Work'", // defines how KAddresbook labels the address
'adr_two_type' => "'Home'",
);
break;
case 'eGWOSync': // no idea what is necessary
break;
}
}
/**
* translate array of internal datas to xmlrpc, eg. format bday as iso8601
*
* @internal
* @param array $datas array of contact arrays
* @param boolean $read_customfields=false should the customfields be read, default no (contacts::read() does it already)
* @return array
*/
function data2xmlrpc($datas,$read_customfields=false)
{
if(is_array($datas))
{
if ($read_customfields)
{
$ids = array();
foreach($datas as $data)
{
$ids[] = $data['id'];
}
$customfields = $this->contacts->read_customfields($ids);
}
foreach($datas as $n => $nul)
{
$data =& $datas[$n]; // $n => &$data is php5 ;-)
if ($customfields && isset($customfields[$data['id']]))
{
foreach($customfields[$data['id']] as $name => $value)
{
$data['#'.$name] = $value;
}
}
// remove empty or null elements, they dont need to be transfered
$data = array_diff($data,array('',null));
// translate birthday to a iso8601 date
if(isset($data['bday']) && $data['bday'])
{
$y = $m = $d = null;
list($y,$m,$d) = explode('-',$data['bday']);
if (is_null($d)) list($m,$d,$y) = explode('/',$data['bday']);
$data['bday'] = $GLOBALS['server']->date2iso8601(array('year'=>$y,'month'=>$m,'mday'=>$d));
}
// translate timestamps
foreach($this->contacts->timestamps as $name)
{
if(isset($data[$name]))
{
$data[$name] = $GLOBALS['server']->date2iso8601($data[$name]);
}
}
// translate categories-id-list to array with id-name pairs
if(isset($data['cat_id']))
{
$data['cat_id'] = $GLOBALS['server']->cats2xmlrpc(explode(',',$data['cat_id']));
}
// replacing the fieldname in tel_prefer with the actual number, if it exists and is non-empty
if (substr($data['tel_prefer'],0,4) === 'tel_' && $data[$data['tel_prefer']])
{
$data['tel_prefer'] = $data[$data['tel_prefer']];
}
// translate fieldnames if required
foreach($this->mapping as $from => $to)
{
switch($from)
{
case 'grants[owner]':
$data[$to] = $this->contacts->grants[$data['owner']];
break;
case 'private':
$data[$to] = $data['private'] ? 'private' : 'public';
break;
default:
if ($to{0} == "'") // constant value enclosed in single quotes
{
$data[$from] = substr($to,1,-1);
}
elseif(isset($data[$from]))
{
if ($to) $data[$to] =& $data[$from];
unset($data[$from]);
}
break;
}
}
}
}
return $datas;
}
/**
* retranslate from xmlrpc / iso8601 to internal format
*
* @internal
* @param array $data
* @return array
*/
function xmlrpc2data($data)
{
// translate fieldnames if required
foreach($this->mapping as $to => $from)
{
if ($from && isset($data[$from]))
{
switch($to)
{
case 'private':
$data[$to] = $data['access'] == 'private';
break;
default:
$data[$to] =& $data[$from]; unset($data[$from]);
break;
}
}
}
// translate birthday
if(isset($data['bday']))
{
$arr = $GLOBALS['server']->iso86012date($data['bday']);
$data['bday'] = $arr['year'] && $arr['month'] && $arr['mday'] ? sprintf('%04d-%02d-%02d',$arr['year'],$arr['month'],$arr['mday']) : null;
}
// translate timestamps
foreach($this->contacts->timestamps as $name)
{
if(isset($data[$name]))
{
$data[$name] = $GLOBALS['server']->date2iso8601($data[$name]);
}
}
// translate cats
if(isset($data['cat_id']))
{
$cats = $GLOBALS['server']->xmlrpc2cats($data['cat_id']);
$data['cat_id'] = count($cats) > 1 ? ','.implode(',',$cats).',' : (int)$cats[0];
}
// replacing the number in tel_prefer with the fieldname, if it matches a phone-number, otherwise keep it's content as is
if ($data['tel_prefer'])
{
$prefer = $data['tel_prefer'];
unset($data['tel_prefer']);
if (($key = array_search($prefer,$data)) !== false && substr($key,0,4) === 'tel_')
{
$data['tel_prefer'] = $key;
}
else
{
$data['tel_prefer'] = $prefer;
}
}
return $data;
}
/**
* Search the addressbook
*
* Todo: use contacts::search and all it's possebilities instead of the depricated contacts::old_read()
*
* @param array $param
* @param int $param['start']=0 starting number of the range, if $param['limit'] != 0
* @param int $param['limit']=0 max. number of entries to return, 0=all
* @param array $param['fields']=null fields to return or null for all stock fields, fields are in the values (!)
* @param string $param['query']='' search pattern or '' for none
* @param string $param['filter']='' filters with syntax like <name>=<value>,<name2>=<value2>,<name3>=!'' for not empty
* @param string $param['sort']='' sorting: ASC or DESC
* @param string $param['order']='' column to order, default ('') n_family,n_given,email ASC
* @param int $param['lastmod']=-1 return only values modified after given timestamp, default (-1) return all
* @param string $param['cquery']='' return only entries starting with given character, default ('') all
* @param string $param['customfields']=true return the customfields too, default yes
* @return array of contacts
*/
function search($param)
{
$read_customfields = !isset($param['customfields']) || $param['customfields'];
$extra_accounts = array();
if ($this->user_agent == 'KDE-AddressBook' && strpos($this->contacts->contact_repository,$this->contacts->account_repository) === false)
{
$extra_accounts = $this->contacts->search(array(),false,'','','',false,'AND',false,array(
'contact_owner' => 0,
));
}
$searchResults = $this->contacts->old_read(
(int) $param['start'],
(int) $param['limit'],
$param['fields'],
$param['query'],
$param['filter'],
$param['sort'],
$param['order'],
$param['lastmod'] ? $param['lastmod'] : -1,
$param['cquery']
);
if (!is_array($searchResults)) $searchResults = array();
return $this->data2xmlrpc(array_merge($searchResults,$extra_accounts),$read_customfields);
}
/**
* Read one contact
*
* @param mixed $id $id, $id[0] or $id['id'] contains the id of the contact
* @return array contact
*/
function read($id)
{
if(is_array($id)) $id = isset($id[0]) ? $id[0] : $id['id'];
$data = $this->contacts->read($id);
if($data !== false) // permission denied
{
$data = $this->data2xmlrpc(array($data));
return $data[0];
}
$GLOBALS['server']->xmlrpc_error($GLOBALS['xmlrpcerr']['no_access'],$GLOBALS['xmlrpcstr']['no_access']);
}
/**
* Save a contact
*
* @param array $data
* @return int new contact_id
*/
function save($data)
{
$data = $this->xmlrpc2data($data);
$id = $this->contacts->save($data);
if($id) return $id;
$GLOBALS['server']->xmlrpc_error($GLOBALS['xmlrpcerr']['no_access'],$GLOBALS['xmlrpcstr']['no_access']);
}
/**
* Delete a contact
*
* @param mixed $id $id, $id[0] or $id['id'] contains the id of the contact
* @param boolean true
*/
function delete($id)
{
if(is_array($id)) $id = isset($id[0]) ? $id[0] : $id['id'];
if ($this->contacts->delete($id))
{
return true;
}
$GLOBALS['server']->xmlrpc_error($GLOBALS['xmlrpcerr']['no_access'],$GLOBALS['xmlrpcstr']['no_access']);
}
/**
* return all addressbook categories
*
* @param boolean $complete complete cat-array or just the name
* @param array with cat_id => name or cat_id => cat-array pairs
*/
function categories($complete = False)
{
return $GLOBALS['server']->categories($complete);
}
/**
* get or set addressbook customfields
*
* @param array $new_fields=null
* @return array
*/
function customfields($new_fields=null)
{
if(is_array($new_fields) && count($new_fields))
{
if(!$GLOBALS['egw_info']['user']['apps']['admin'])
{
$GLOBALS['server']->xmlrpc_error($GLOBALS['xmlrpcerr']['no_access'],$GLOBALS['xmlrpcstr']['no_access']);
}
require_once(EGW_INCLUDE_ROOT.'/admin/inc/class.customfields.inc.php');
$fields = new customfields('addressbook');
foreach($new_fields as $new)
{
if (!is_array($new))
{
$new = array('name' => $new);
}
$fields->create_field(array('fields' => $new));
}
}
$customfields = array();
foreach($this->contacts->customfields as $name => $data)
{
$customfields[$name] = $data['label'];
}
return $customfields;
}
}

View File

@ -1,341 +0,0 @@
<?php
/**
* eGroupWare - Calendar's XMLRPC or SOAP access
*
* Please note: dont use addressbook_... naming convention, as it would break the existing xmlrpc clients
*
* @link http://www.egroupware.org
* @package calendar
* @author Ralf Becker <RalfBecker-AT-outdoor-training.de>
* @copyright (c) 2005-8 by RalfBecker-At-outdoor-training.de
* @license http://opensource.org/licenses/gpl-license.php GPL - GNU General Public License
* @version $Id$
*/
/**
* Class to access AND manipulate calendar data via XMLRPC or SOAP
*
* eGW's xmlrpc interface is documented at http://egroupware.org/wiki/xmlrpc
*
* @link http://egroupware.org/wiki/xmlrpc
*/
class bocalendar
{
var $xmlrpc_date_format = 'Y-m-d\\TH:i:s';
var $debug = false; // log function call to the apache error_log
var $cal;
var $public_functions = Array(
'read' => True,
'delete' => True,
'write' => True,
'search' => True,
'categories'=> True,
'list_methods' => True,
);
function __construct()
{
$this->cal = new calendar_boupdate();
if (is_object($GLOBALS['server']) && $GLOBALS['server']->simpledate)
{
$this->xmlrpc_date_format = 'Ymd\\TH:i:s';
}
}
/**
* This handles introspection or discovery by the logged in client,
* in which case the input might be an array. The server always calls
* this function to fill the server dispatch map using a string.
*
* @param string/array $_type string or array with key 'type' for type of interface: xmlrpc or soap
* @return array
*/
function list_methods($_type='xmlrpc')
{
switch(is_array($_type) ? ($_type['type'] ? $_type['type'] : $_type[0]) : $_type)
{
case 'xmlrpc':
return array(
'list_methods' => array(
'function' => 'list_methods',
'signature' => array(array(xmlrpcStruct,xmlrpcString)),
'docstring' => 'Read this list of methods.'
),
'read' => array(
'function' => 'read',
'signature' => array(array(xmlrpcStruct,xmlrpcInt)),
'docstring' => 'Read a single entry by passing the id or uid.'
),
'write' => array(
'function' => 'write',
'signature' => array(array(xmlrpcStruct,xmlrpcStruct)),
'docstring' => 'Add or update a single entry by passing the fields.'
),
'delete' => array(
'function' => 'delete',
'signature' => array(array(xmlrpcInt,xmlrpcInt)),
'docstring' => 'Delete a single entry by passing the id.'
),
'search' => array(
'function' => 'search',
'signature' => array(array(xmlrpcStruct,xmlrpcStruct)),
'docstring' => 'Read a list of entries.'
),
'categories' => array(
'function' => 'categories',
'signature' => array(array(xmlrpcStruct,xmlrpcStruct)),
'docstring' => 'List all categories.'
),
);
case 'soap':
return Array(
'read' => Array(
'in' => Array('int'),
'out' => Array('SOAPStruct')
),
'delete' => Array(
'in' => Array('int'),
'out' => Array('int')
),
'write' => Array(
'in' => Array('array'),
'out' => Array('array')
),
'search' => Array(
'in' => Array('struct'),
'out' => Array('SOAPStruct')
),
'categories' => array(
'in' => array('bool'),
'out' => array('array')
),
);
}
return array();
}
/**
* Read a single entry
*
* @param int/array $id
* @return array with event(s) or XMLRPC error not_existent or no_access
*/
function read($id)
{
if ($this->debug) error_log('bocalendar::read('.print_r($id,true).')');
$events =& $this->cal->read($id,null,true,$this->xmlrpc_date_format); // true = ignore acl!!!
if (!$events) // only id not found, as ignore_acl=true
{
// xmlrpc_error does NOT return
$GLOBALS['server']->xmlrpc_error($GLOBALS['xmlrpcerr']['not_existent'],$GLOBALS['xmlrpcstr']['not_existent']);
}
if (is_array($id) && count($id) > 1)
{
foreach($events as $key => $event)
{
if (!$this->cal->check_perms(EGW_ACL_READ,$event,0,$this->xmlrpc_date_format))
{
// xmlrpc_error does NOT return
$GLOBALS['server']->xmlrpc_error($GLOBALS['xmlrpcerr']['no_access'],$GLOBALS['xmlrpcstr']['no_access']);
}
$events[$key] = $this->xmlrpc_prepare($event);
}
}
else
{
// for a single id the event is returned and not an array with the event
if (is_array($id)) $events = array_shift($events);
if (!$this->cal->check_perms(EGW_ACL_READ,$events,0,$this->xmlrpc_date_format))
{
// xmlrpc_error does NOT return
$GLOBALS['server']->xmlrpc_error($GLOBALS['xmlrpcerr']['no_access'],$GLOBALS['xmlrpcstr']['no_access']);
}
$events = $this->xmlrpc_prepare($events);
}
return $events;
}
/**
* Delete an event
*
* @param array $ids event-id(s)
* @return boolean true or XMLRPC error not_existent or no_access
*/
function delete($ids)
{
if ($this->debug) error_log('bocalendar::delete('.print_r($ids,true).')');
foreach((array) $ids as $id)
{
if (!$event = $this->cal->read($id,null,true)) // id not found, as ignore_acl=true
{
// xmlrpc_error does NOT return
$GLOBALS['server']->xmlrpc_error($GLOBALS['xmlrpcerr']['not_existent'],$GLOBALS['xmlrpcstr']['not_existent']);
}
if (!$this->cal->check_perms(EGW_ACL_DELETE,$event))
{
// xmlrpc_error does NOT return
$GLOBALS['server']->xmlrpc_error($GLOBALS['xmlrpcerr']['no_access'],$GLOBALS['xmlrpcstr']['no_access']);
}
if (!$this->cal->delete($id))
{
return false; // other db-problem
}
}
return true;
}
/**
* Add/update an event
*
* @param array $event event-data
* @return int cal-id
*/
function write($event)
{
if ($this->debug) error_log('bocalendar::write('.print_r($event,true).')');
// convert xmlrpc specific values back
$event['category'] = $event['category'] ? $GLOBALS['server']->xmlrpc2cats($event['category']) : null;
// using access={public|private} in all modules via xmlrpc
$event['public'] = $event['access'] != 'private';
unset($event['access']);
if (is_array($event['participants']))
{
foreach($event['participants'] as $user => $data)
{
if (!is_numeric($user))
{
unset($event['participants'][$user]);
$user = $GLOBALS['egw']->accounts->name2id($data['email'],'account_email');
}
if (!$user) continue;
$event['participants'][$user] = in_array($data['status'],array('U','A','R','T')) ? $data['status'] : 'U';
}
}
if (!is_array($event['participants']) || !count($event['participants']))
{
$event['participants'] = array($GLOBALS['egw_info']['user']['account_id'] => 'A');
}
if (!($id = $this->cal->update($event,true))) // true=no conflict check for now
{
$GLOBALS['server']->xmlrpc_error($GLOBALS['xmlrpcerr']['no_access'],$GLOBALS['xmlrpcstr']['no_access']);
}
return (int) $id;
}
/**
* search calendar for events
*
* If daywise is not set or false, an XMLRPC array of events is returned, otherwise an
* XMLRCP struct with date as string (eg. '20060101') and an array of events is returned.
*
* @param array $params following keys are allowed: start, end, user (more see bocal::search)
* @return array with events
*/
function search($params)
{
if ($this->debug) error_log('bocalendar::search('.print_r($params,true).')');
// some defaults for xmlrpc
if (!isset($params['date_format'])) $params['date_format'] = $this->xmlrpc_date_format;
if (!isset($params['enum_recuring'])) $params['enum_recuring'] = false;
// security precausion
unset($params['ignore_acl']);
$events =& $this->cal->search($params);
foreach($events as $key => $event)
{
$events[$key] = $this->xmlrpc_prepare($event);
}
return !$params['daywise'] ? array_values($events) : $events;
}
/**
* prepare regular event-array (already with iso8601 dates) to be send by xmlrpc
* - participants are send as struct/array with keys: name, email, status
* - categories are send as array with cat_id - title pairs
* - public is transformed to access={public|private}
* - new (1.2) values get unset (eg. participant_types)
*
* @param array &$event
* @return array
*/
function xmlrpc_prepare(&$event)
{
$event['rights'] = $this->cal->grants[$event['owner']];
static $user_cache = array();
foreach((array) $event['participants'] as $uid => $status)
{
if (!is_numeric($uid)) continue; // resources
if (!isset($user_cache[$uid]))
{
$user_cache[$uid] = array(
'name' => $GLOBALS['egw']->common->grab_owner_name($uid),
'email' => $GLOBALS['egw']->accounts->id2name($uid,'account_email')
);
}
$event['participants'][$uid] = $user_cache[$uid] + array(
'status' => $status,
);
}
if (is_array($event['alarm']))
{
foreach($event['alarm'] as $id => $alarm)
{
if ($alarm['owner'] != $GLOBALS['egw_info']['user']['account_id'])
{
unset($event['alarm'][$id]);
}
}
}
if ($event['category'])
{
$event['category'] = $GLOBALS['server']->cats2xmlrpc(explode(',',$event['category']));
}
else
{
unset($event['category']);
}
// using access={public|private} in all modules via xmlrpc
$event['access'] = $event['public'] ? 'public' : 'private';
// unset everything not known in version 1.0
foreach(array('public','participant_types') as $key)
{
unset($event[$key]);
}
// unsetting everything which could result in an typeless <value />
foreach($event as $key => $value)
{
if (is_null($value) || is_array($value) && !$value)
{
unset($event[$key]);
}
}
return $event;
}
/**
* return array with all categories
*
* @param boolean $complete=false false: return id => title pairs, true array with full data instead of title
* @return array
*/
function categories($complete = False)
{
return $GLOBALS['server']->categories($complete);
}
}

View File

@ -1,317 +0,0 @@
<?php
/**
* InfoLog - xmlrpc access
*
* Please note: dont use infolog_... naming convention, as it would break the existing xmlrpc clients
*
* @link http://www.egroupware.org
* @author Ralf Becker <RalfBecker-AT-outdoor-training.de>
* @package infolog
* @copyright (c) 2003-8 by Ralf Becker <RalfBecker-AT-outdoor-training.de>
* @license http://opensource.org/licenses/gpl-license.php GPL - GNU General Public License
* @version $Id$
*/
/**
* Class to access AND manipulate InfoLog data via XMLRPC or SOAP
*
* eGW's xmlrpc interface is documented at http://egroupware.org/wiki/xmlrpc
*
* @link http://egroupware.org/wiki/xmlrpc
*/
class boinfolog extends infolog_bo
{
var $xmlrpc_methods = array();
var $soap_functions = array(
'read' => array(
'in' => array('int'),
'out' => array('array')
),
'search' => array(
'in' => array('array'),
'out' => array('array')
),
'write' => array(
'in' => array('array'),
'out' => array()
),
'delete' => array(
'in' => array('int'),
'out' => array()
),
'categories' => array(
'in' => array('bool'),
'out' => array('array')
),
);
/**
* handles introspection or discovery by the logged in client,
* in which case the input might be an array. The server always calls
* this function to fill the server dispatch map using a string.
*
* @param string $_type='xmlrpc' xmlrpc or soap
* @return array
*/
function list_methods($_type='xmlrpc')
{
if (is_array($_type))
{
$_type = $_type['type'] ? $_type['type'] : $_type[0];
}
switch($_type)
{
case 'xmlrpc':
$xml_functions = array(
'read' => array(
'function' => 'read',
'signature' => array(array(xmlrpcInt,xmlrpcInt)),
'docstring' => lang('Read one record by passing its id.')
),
'search' => array(
'function' => 'search',
'signature' => array(array(xmlrpcStruct,xmlrpcStruct)),
'docstring' => lang('Returns a list / search for records.')
),
'write' => array(
'function' => 'write',
'signature' => array(array(xmlrpcStruct,xmlrpcStruct)),
'docstring' => lang('Write (add or update) a record by passing its fields.')
),
'delete' => array(
'function' => 'delete',
'signature' => array(array(xmlrpcInt,xmlrpcInt)),
'docstring' => lang('Delete one record by passing its id.')
),
'categories' => array(
'function' => 'categories',
'signature' => array(array(xmlrpcBoolean,xmlrpcBoolean)),
'docstring' => lang('List all categories')
),
'list_methods' => array(
'function' => 'list_methods',
'signature' => array(array(xmlrpcStruct,xmlrpcString)),
'docstring' => lang('Read this list of methods.')
)
);
return $xml_functions;
break;
case 'soap':
return $this->soap_functions;
break;
default:
return array();
break;
}
}
/**
* Read an infolog entry specified by $info_id
*
* @param int/array $info_id integer id or array with key 'info_id' of the entry to read
* @return array/boolean infolog entry, null if not found or false if no permission to read it
*/
function &read($info_id)
{
$data = parent::read($info_id);
if (is_null($data))
{
$GLOBALS['server']->xmlrpc_error($GLOBALS['xmlrpcerr']['not_exist'],$GLOBALS['xmlrpcstr']['not_exist']);
}
elseif($data === false)
{
$GLOBALS['server']->xmlrpc_error($GLOBALS['xmlrpcerr']['no_access'],$GLOBALS['xmlrpcstr']['no_access']);
}
else
{
$data = $this->data2xmlrpc($data);
}
return $data;
}
/**
* Delete an infolog entry, evtl. incl. it's children / subs
*
* @param array $data array with keys 'info_id', 'delete_children' and 'new_parent'
* @return boolean True if delete was successful, False otherwise ($info_id does not exist or no rights)
*/
function delete($data)
{
if (is_array($data))
{
$delete_children = $data['delete_children'];
$new_parent = $data['new_parent'];
$info_id = (int)(isset($data[0]) ? $data[0] : $data['info_id']);
$status = parent::delete($info_id,$delete_children,$new_parent);
}
else
{
$status = parent::delete($data);
}
if ($status === false)
{
$GLOBALS['server']->xmlrpc_error($GLOBALS['xmlrpcerr']['no_access'],$GLOBALS['xmlrpcstr']['no_access']);
}
return $status;
}
/**
* writes the given $values to InfoLog, a new entry gets created if info_id is not set or 0
*
* checks and asures ACL
*
* @param array $values values to write, if contains values for check_defaults and touch_modified,
* they have precedens over the parameters. The
* @param boolean $check_defaults=true check and set certain defaults
* @param boolean $touch_modified=true touch the modification data and sets the modiefier's user-id
* @return int/boolean info_id on a successfull write or false
*/
function write($values,$check_defaults=True,$touch_modified=True)
{
//echo "boinfolog::write()values="; _debug_array($values);
// allow to (un)set check_defaults and touch_modified via values, eg. via xmlrpc
foreach(array('check_defaults','touch_modified') as $var)
{
if(isset($values[$var]))
{
$$var = $values[$var];
unset($values[$var]);
}
}
$values = $this->xmlrpc2data($values);
$status = parent::write($values,$check_defaults,$touch_modified);
if ($status == false)
{
$GLOBALS['server']->xmlrpc_error($GLOBALS['xmlrpcerr']['no_access'],$GLOBALS['xmlrpcstr']['no_access']);
}
return $status;
}
/**
* searches InfoLog for a certain pattern in $query
*
* @param $query[order] column-name to sort after
* @param $query[sort] sort-order DESC or ASC
* @param $query[filter] string with combination of acl-, date- and status-filters, eg. 'own-open-today' or ''
* @param $query[cat_id] category to use or 0 or unset
* @param $query[search] pattern to search, search is done in info_from, info_subject and info_des
* @param $query[action] / $query[action_id] if only entries linked to a specified app/entry show be used
* @param &$query[start], &$query[total] nextmatch-parameters will be used and set if query returns less entries
* @param $query[col_filter] array with column-name - data pairs, data == '' means no filter (!)
* @return array with id's as key of the matching log-entries
*/
function &search(&$query)
{
//echo "<p>boinfolog::search(".print_r($query,True).")</p>\n";
$ret = parent::search($query);
if (is_array($ret))
{
$infos =& $ret;
unset($ret);
$ret = array();
foreach($infos as $id => $data)
{
$ret[] = $this->data2xmlrpc($data);
}
}
//echo "<p>boinfolog::search(".print_r($query,True).")=<pre>".print_r($ret,True)."</pre>\n";
return $ret;
}
/**
* Convert an InfoLog entry into its xmlrpc representation, eg. convert timestamps to datetime.iso8601
*
* @param array $data infolog entry in db format
*
* @return array xmlrpc infolog entry
*/
function data2xmlrpc($data)
{
$data['rights'] = $this->so->grants[$data['info_owner']];
// translate timestamps
if($data['info_enddate'] == 0) unset($data['info_enddate']);
foreach($this->timestamps as $name)
{
if (isset($data[$name]))
{
$data[$name] = $GLOBALS['server']->date2iso8601($data[$name]);
}
}
$ret[$id]['info_percent'] = (int)$data['info_percent'].'%';
// translate cat_id
if (isset($data['info_cat']))
{
$data['info_cat'] = $GLOBALS['server']->cats2xmlrpc(array($data['info_cat']));
}
foreach($data as $name => $val)
{
if (substr($name,0,5) == 'info_')
{
unset($data[$name]);
$data[substr($name,5)] = $val;
}
}
// unsetting everything which could result in an typeless <value />
foreach($data as $key => $value)
{
if (is_null($value) || is_array($value) && !$value)
{
unset($data[$key]);
}
}
return $data;
}
/**
* Convert an InfoLog xmlrpc representation into the internal one, eg. convert datetime.iso8601 to timestamps
*
* @param array $data infolog entry in xmlrpc representation
*
* @return array infolog entry in db format
*/
function xmlrpc2data($data)
{
foreach($data as $name => $val)
{
if (substr($name,0,5) != 'info_')
{
unset($data[$name]);
$data['info_'.$name] = $val;
}
}
// translate timestamps
foreach($this->timestamps as $name)
{
if (isset($data[$name]))
{
$data[$name] = $GLOBALS['server']->iso86012date($data[$name],True);
}
}
// translate cat_id
if (isset($data['info_cat']))
{
$cats = $GLOBALS['server']->xmlrpc2cats($data['info_cat']);
$data['info_cat'] = (int)$cats[0];
}
return $data;
}
/**
* return array with all infolog categories (for xmlrpc)
*
* @param boolean $complete true returns array with all data for each cat, else only the title is returned
* @return array with cat_id / title or data pairs (see above)
*/
function categories($complete = False)
{
return $GLOBALS['server']->categories($complete);
}
}