* API/Calendar: allow to link to accounts and allow to select accounts as participants by searching them like contacts

This commit is contained in:
Ralf Becker 2011-09-07 16:54:55 +00:00
parent 1f1e800503
commit 714d13e8b6
8 changed files with 130 additions and 29 deletions

View File

@ -237,6 +237,10 @@ class calendar_bo
'info' => __CLASS__.'::email_info',
'app' => 'email',
);
$this->resources[''] = array(
'type' => '',
'app' => 'home-accounts',
);
$GLOBALS['egw']->session->appsession('resources','calendar',$this->resources);
}
//echo "registered resources="; _debug_array($this->resources);

View File

@ -235,7 +235,8 @@ class calendar_hooks
'resources_conflict' => lang('resources with conflict detection'),
'resources_without_conflict' => lang('resources except conflicting ones'),
'resources' => lang('resources'),
'addressbook' => lang('addressbook')
'addressbook' => lang('addressbook'),
'home-accounts' => lang('Accounts'),
);
$reset_stati_on_shifts = array(
'no' => lang('Never'),

View File

@ -319,8 +319,12 @@ class calendar_uiforms extends calendar_ui
}
foreach($this->bo->resources as $type => $data) if ($data['app'] == $app) break;
$uid = $this->bo->resources[$type]['app'] == $app ? $type.$id : false;
if ($app == 'home-accounts')
{
$data = $id;
}
// check if new entry is no account (or contact entry of an account)
if ($app != 'addressbook' || !($data = $GLOBALS['egw']->accounts->name2id($id,'person_id')) || !$this->bo->check_acl_invite($data))
elseif ($app != 'addressbook' || !($data = $GLOBALS['egw']->accounts->name2id($id,'person_id')) || !$this->bo->check_acl_invite($data))
{
if ($uid && $id)
{

View File

@ -318,7 +318,7 @@ class link_widget
}
else
{
$value[$row]['icon'] = 'egw/'.$value[$row]['app'];
$value[$row]['icon'] = egw_link::get_registry($value[$row]['app'], 'icon');
$value[$row]['label'] = 'Unlink';
$value[$row]['help'] = lang('Remove this link (not the entry itself)');
}

View File

@ -309,10 +309,10 @@ class vfs_widget
$cell['label'] = mime_magic::mime2label($mime);
list($mime_main,$mime_sub) = explode('/',$mime);
if ($mime_main == 'egw')
if ($mime_main == 'egw' || isset($GLOBALS['egw_info']['apps'][$mime_main]))
{
$value = $mime_sub.'/navbar'; // egw-applications for link-widget
$cell['label'] = lang($mime_sub);
$value = $mime_main == 'egw' ? $mime_sub.'/navbar' : $mime; // egw-applications for link-widget
$cell['label'] = lang($mime_main == 'egw' ? $mime_sub : $mime_main);
list($span,$class) = explode(',',$cell['span'],2);
$class .= ($class ? ' ' : '') . 'vfsMimeIcon';
$cell['span'] = $span.','.$class;

View File

@ -231,7 +231,8 @@ class accounts
* Searches / lists accounts: users and/or groups
*
* @param array with the following keys:
* @param $param['type'] string/int 'accounts', 'groups', 'owngroups' (groups the user is a member of), 'both'
* @param $param['type'] string/int 'accounts', 'groups', 'owngroups' (groups the user is a member of), 'both',
* 'groupmembers' (members of groups the user is a member of), 'groupmembers+memberships' (incl. memberships too)
* or integer group-id for a list of members of that group
* @param $param['start'] int first account to return (returns offset or max_matches entries) or all if not set
* @param $param['order'] string column to sort after, default account_lid if unset
@ -249,7 +250,7 @@ class accounts
*/
function search($param)
{
//echo "<p>accounts::search(".print_r($param,True).") start: ".microtime()."</p>\n";
//error_log(__METHOD__.'('.array2string($param).')');
self::setup_cache();
$account_search = &self::$cache['account_search'];
$serial = serialize($param);
@ -261,7 +262,7 @@ class accounts
// no backend understands $param['app'] and sql does not understand group-parameters
// --> do an full search first and then filter and limit that search
elseif($param['app'] || $this->config['account_repository'] != 'ldap' &&
(is_numeric($param['type']) || $param['type'] == 'owngroups'))
(is_numeric($param['type']) || in_array($param['type'],array('owngroups','groupmembers','groupmembers+memberships'))))
{
$app = $param['app'];
unset($param['app']);
@ -270,14 +271,24 @@ class accounts
if ($this->config['account_repository'] != 'ldap' && is_numeric($param['type']))
{
$group = (int) $param['type'];
$members = $this->members($group,true);
$param['type'] = 'accounts';
}
elseif ($param['type'] == 'owngroups')
{
$group = true;
$members = $this->memberships($GLOBALS['egw_info']['user']['account_id'],true);
$param['type'] = 'groups';
}
elseif(in_array($param['type'],array('groupmembers','groupmembers+memberships')))
{
$members = array();
foreach($this->memberships($GLOBALS['egw_info']['user']['account_id'],true) as $grp)
{
$members = array_unique(array_merge($members,$this->members($grp,true)));
if ($param['type'] == 'groupmembers+memberships') $members[] = $grp;
}
$param['type'] = $param['type'] == 'groupmembers+memberships' ? 'both' : 'accounts';
}
// call ourself recursive to get (evtl. cached) full search
$full_search = $this->search($param);
@ -288,9 +299,9 @@ class accounts
// we want the result merged, whatever it takes, as we only care for the ids
$valid = $this->split_accounts($app,!in_array($param['type'],array('accounts','groups')) ? 'merge' : $param['type']);
}
if ($group)
if (isset($members))
{
$members = is_int($group) ? $this->members($group,true) : $this->memberships($GLOBALS['egw_info']['user']['account_id'],true);
//error_log(__METHOD__.'() members='.array2string($members));
if (!$members) $members = array();
$valid = !$app ? $members : array_intersect($valid,$members); // use the intersection
}
@ -339,6 +350,48 @@ class accounts
return $account_search[$serial]['data'];
}
/**
* Query for accounts
*
* @param string|array $pattern
* @param array $options
* @return array with id - title pairs of the matching entries
*/
public static function link_query($pattern, array &$options = array())
{
if (isset($options['filter']) && !is_array($options['filter']))
{
$options['filter'] = (array)$options['filter'];
}
switch($GLOBALS['egw_info']['user']['preferences']['common']['account_display'])
{
case 'firstname':
case 'firstall':
$order = 'account_firstname,account_lastname';
break;
case 'lastname':
case 'lastall':
$order = 'account_lastname,account_firstname';
break;
default:
$order = 'account_lid';
break;
}
$accounts = array();
foreach(self::getInstance()->search(array(
'type' => $GLOBALS['egw_info']['user']['preferences']['common']['account_selection'] == 'groupmembers' &&
!isset($GLOBALS['egw_info']['user']['apps']['admin']) ? 'groupmembers+memberships' : 'both',
'query' => $pattern,
'query_type' => 'all',
'order' => $order,
)) as $account)
{
$accounts[$account['account_id']] = common::display_fullname($account['account_lid'],
$account['account_firstname'],$account['account_lastname'],$account['account_id']);
}
return $accounts;
}
/**
* Reads the data of one account
*

View File

@ -8,7 +8,7 @@
*
* @link http://www.egroupware.org
* @author Ralf Becker <RalfBecker-AT-outdoor-training.de>
* @copyright 2001-2008 by RalfBecker@outdoor-training.de
* @copyright 2001-2011 by RalfBecker@outdoor-training.de
* @license http://opensource.org/licenses/gpl-license.php GPL - GNU General Public License
* @package api
* @subpackage link
@ -61,6 +61,8 @@
* ),
* 'edit_id' => 'app_id',
* 'edit_popup' => '400x300',
* 'name' => 'Some name', // Name to use instead of app-name
* 'icon' => 'app/icon', // Optional icon to use instead of app-icon
* 'additional' => array( // allow one app to register sub-types,
* 'app-sub' => array( // different from 'types' approach above
* // every value defined above
@ -106,6 +108,12 @@ class egw_link extends solink
),
'add_popup' => '700x750',
),
'home-accounts' => array( // user need run-rights for home
'name' => 'Accounts',
'icon' => 'addressbook/accounts',
'query' => 'accounts::link_query',
'title' => 'common::grab_owner_name',
),
);
/**
* Caches link titles for a better performance
@ -162,6 +170,12 @@ class egw_link extends solink
}
}
}
// disable ability to link to accounts for non-admins, if account-selection is disabled
if ($GLOBALS['egw_info']['user']['preferences']['common']['account_selection'] == 'none' &&
!isset($GLOBALS['egw_info']['user']['apps']['admin']))
{
unset(self::$app_register['home-accounts']);
}
if (!(self::$title_cache = $GLOBALS['egw']->session->appsession('link_title_cache','phpgwapi')))
{
self::$title_cache = array();
@ -547,13 +561,14 @@ class egw_link extends solink
static function app_list($must_support='')
{
$apps = array();
foreach(self::$app_register as $app => $reg)
foreach(self::$app_register as $type => $reg)
{
if ($must_support && !isset($reg[$must_support])) continue;
list($app) = explode('-', $type);
if ($GLOBALS['egw_info']['user']['apps'][$app])
{
$apps[$app] = $GLOBALS['egw_info']['apps'][$app]['title'];
$apps[$type] = lang(self::get_registry($type, 'name'));
}
}
return $apps;
@ -849,6 +864,29 @@ class egw_link extends solink
{
$reg = self::$app_register[$app];
if (!isset($reg)) return false;
if (!isset($reg[$name])) // some defaults
{
switch($name)
{
case 'name':
$reg[$name] = $app;
break;
case 'icon':
if (isset($GLOBALS['egw_info']['apps'][$app]['icon']))
{
$reg[$name] = ($GLOBALS['egw_info']['apps'][$app]['icon_app'] ? $GLOBALS['egw_info']['apps'][$app]['icon_app'] : $app).
'/'.$GLOBALS['egw_info']['apps'][$app]['icon'];
}
else
{
$reg[$name] = $app.'/navbar';
}
break;
}
}
return isset($reg) ? $reg[$name] : false;
}

View File

@ -19,7 +19,7 @@
* generalized linking between entries of eGroupware apps - SO layer
*
* All vars passed to this class get correct escaped to prevent query insertion.
*
*
* All methods are now static!
*/
class solink
@ -89,7 +89,7 @@ class solink
'link_owner' => $owner,
),False,__LINE__,__FILE__) ? self::$db->get_last_insert_id(self::TABLE,'link_id') : false;
}
/**
* update the remark of a link
*
@ -110,7 +110,7 @@ class solink
/**
* returns array of links to $app,$id
*
* @param string $app appname
* @param string $app appname
* @param string/array $id id(s) in $app
* @param string $only_app if set return only links from $only_app (eg. only addressbook-entries) or NOT from if $only_app[0]=='!'
* @param string $order defaults to newest links first
@ -156,7 +156,8 @@ class solink
$linked_app = $left ? $row['link_app2'] : $row['link_app1'];
$linked_id = $left ? $row['link_id2'] : $row['link_id1'];
$app_id = $left ? $row['link_id1'] : $row['link_id2'];
if ($only_app && $not_only == ($linked_app == $only_app) || !$GLOBALS['egw_info']['user']['apps'][$linked_app])
list($app) = explode('-',$linked_app);
if ($only_app && $not_only == ($linked_app == $only_app) || !$GLOBALS['egw_info']['user']['apps'][$app])
{
#echo "$linked_app == $only_app, ";var_dump($linked_app == $only_app);echo " ->dont return a link<br>";
return;
@ -171,7 +172,7 @@ class solink
'link_id' => $row['link_id'],
);
}
/**
* returns data of a link
*
@ -308,21 +309,21 @@ class solink
return self::$db->affected_rows();
}
/**
* Get all links from a given app's entries to an other app's entries, which both link to the same 3. app and id
*
* Example:
* I search all timesheet's linked to a given project and id(s), who are also linked to other entries,
* which link to the same project:
*
*
* ($app='timesheet'/some id) <--a--> (other app/other id) <--b--> ($t_app='projectmanager'/$t_id=$pm_id)
* ^ ^
* ^ ^
* +---------------------------c-----------------------------------------+
*
* bolink::get_3links('timesheet','projectmanager',$pm_id) returns the links (c) between the timesheet and the project,
*
* bolink::get_3links('timesheet','projectmanager',$pm_id) returns the links (c) between the timesheet and the project,
* plus the other app/id in the keys 'app3' and 'id3'
*
*
* @param string $app app the returned links are linked on one side (atm. this must be link_app1!)
* @param string $target_app app the returned links other side link also to
* @param string/array $target_id=null id(s) the returned links other side link also to
@ -347,7 +348,7 @@ class solink
'cols'=>'b.link_id, b.link_app2 as app1, b.link_id2 as id1, b.link_app1 as app2, b.link_id1 as id2, b.link_remark,b.link_lastmod,b.link_owner,c.link_app1 AS app3,c.link_id1 AS id3,c.link_id AS link3',
'where'=>'a.link_app1='.self::$db->quote($app).' AND b.link_app1='.self::$db->quote($target_app).
(!$target_id ? '' : self::$db->expression(self::TABLE,' AND b.',array('link_id1' => $target_id))),
'join'=>" a
'join'=>" a
JOIN $table b ON a.link_id1=b.link_id2 AND a.link_app1=b.link_app2
JOIN $table c ON a.link_id2=c.link_id1 AND a.link_app2=c.link_app1 AND a.link_id!=c.link_id AND c.link_app2=b.link_app1 AND c.link_id2=b.link_id1",
),
@ -356,7 +357,7 @@ class solink
'cols'=>'a.*,c.link_app1 AS app3,c.link_id1 AS id3,c.link_id AS link3',
'where'=>'a.link_app1='.self::$db->quote($app).' AND a.link_app2='.self::$db->quote($target_app).
(!$target_id ? '' : self::$db->expression(self::TABLE,' AND a.',array('link_id2' => $target_id))),
'join'=>" a
'join'=>" a
JOIN $table b ON a.link_id1=b.link_id2 AND a.link_app1=b.link_app2
JOIN $table c ON a.link_id2=c.link_id2 AND a.link_app2=c.link_app2 AND a.link_id!=c.link_id AND c.link_app1=b.link_app1 AND c.link_id1=b.link_id1",
),