restructured accounts::search() code, to handle $param[app] for ldap too, fixed ldap backend to also index array by account_id

This commit is contained in:
Ralf Becker 2010-03-20 13:25:03 +00:00
parent fbe4b39c9b
commit 8025caf852
2 changed files with 115 additions and 76 deletions

View File

@ -244,7 +244,7 @@ class accounts
* 'lid','firstname','lastname','email' - query only the given field for containing $param[query]
* @param $param['app'] string with an app-name, to limit result on accounts with run-right for that app
* @param $param['offset'] int - number of matches to return if start given, default use the value in the prefs
* @return array with uid / data pairs, data is an array with account_id, account_lid, account_firstname,
* @return array with account_id => data pairs, data is an array with account_id, account_lid, account_firstname,
* account_lastname, person_id (id of the linked addressbook entry), account_status, account_expires, account_primary_group
*/
function search($param)
@ -259,19 +259,18 @@ class accounts
{
$this->total = $account_search[$serial]['total'];
}
elseif ($this->config['account_repository'] == 'ldap')
//not correct for php<5.1 elseif ((method_exists($this,'search')) // implements its on search function ==> use it
// 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'))
{
$account_search[$serial]['data'] = $this->backend->search($param);
$account_search[$serial]['total'] = $this->total = $this->backend->total;
}
else
{
$serial2 = $serial;
if (is_numeric($param['type']) || $param['app'] || $param['type'] == 'owngroups') // do we need to limit the search on a group or app?
$app = $param['app'];
unset($param['app']);
$start = $param['start'];
unset($param['start']);
if ($this->config['account_repository'] != 'ldap')
{
$app = $param['app'];
unset($param['app']);
if (is_numeric($param['type']))
{
$group = (int) $param['type'];
@ -282,62 +281,63 @@ class accounts
$group = true;
$param['type'] = 'groups';
}
$start = $param['start'];
unset($param['start']);
$serial2 = serialize($param);
}
if (!isset($account_search[$serial2])) // check if we already did this general search
// call ourself recursive to get (evtl. cached) full search
$full_search = $this->search($param);
// filter search now on accounts with run-rights for app or a group
$valid = array();
if ($app)
{
$account_search[$serial2]['data'] = array();
$accounts = $this->backend->get_list($param['type'],$param['start'],$param['sort'],$param['order'],$param['query'],$param['offset'],$param['query_type']);
if (!$accounts) $accounts = array();
foreach($accounts as $data)
{
$account_search[$serial2]['data'][$data['account_id']] = $data;
}
$account_search[$serial2]['total'] = $this->total = $this->backend->total;
$valid = $this->split_accounts($app,$param['type'] == 'both' ? 'merge' : $param['type']);
}
else
if ($group)
{
$this->total = $account_search[$serial2]['total'];
$members = is_int($group) ? $this->members($group,true) : $this->memberships($GLOBALS['egw_info']['user']['account_id'],true);
if (!$members) $members = array();
$valid = !$app ? $members : array_intersect($valid,$members); // use the intersection
}
//echo "$this->backend->get_list($param[type],$param[start],$param[sort],$param[order],$param[query],$param[offset],$param[query_type]) returned<pre>".print_r($account_search[$serial2],True)."</pre>\n";
if ($app || $group) // limit the search on accounts with run-rights for app or a group
//echo "<p>limiting result to app='app' and/or group=$group valid-ids=".print_r($valid,true)."</p>\n";
$offset = $param['offset'] ? $param['offset'] : $GLOBALS['egw_info']['user']['preferences']['common']['maxmatchs'];
$stop = $start + $offset;
$n = 0;
$account_search[$serial]['data'] = array();
foreach ($full_search as $id => $data)
{
$valid = array();
if ($app)
if (!in_array($id,$valid))
{
$valid = $this->split_accounts($app,$param['type'] == 'both' ? 'merge' : $param['type']);
$this->total--;
continue;
}
if ($group)
// now we have a valid entry
if (!is_int($start) || $start <= $n && $n < $stop)
{
$members = is_int($group) ? $this->members($group,true) : $this->memberships($GLOBALS['egw_info']['user']['account_id'],true);
if (!$members) $members = array();
$valid = !$app ? $members : array_intersect($valid,$members); // use the intersection
$account_search[$serial]['data'][$id] = $data;
}
//echo "<p>limiting result to app='app' and/or group=$group valid-ids=".print_r($valid,true)."</p>\n";
$offset = $param['offset'] ? $param['offset'] : $GLOBALS['egw_info']['user']['preferences']['common']['maxmatchs'];
$stop = $start + $offset;
$n = 0;
$account_search[$serial]['data'] = array();
foreach ($account_search[$serial2]['data'] as $id => $data)
{
if (!in_array($id,$valid))
{
$this->total--;
continue;
}
// now we have a valid entry
if (!is_int($start) || $start <= $n && $n < $stop)
{
$account_search[$serial]['data'][$id] = $data;
}
$n++;
}
$account_search[$serial]['total'] = $this->total;
$n++;
}
$account_search[$serial]['total'] = $this->total;
}
//echo "<p>accounts::search('$serial')=<pre>".print_r($account_search[$serial]['data'],True).")</pre>\n";
// search via ldap backend
elseif ($this->config['account_repository'] == 'ldap')
//not correct for php<5.1 elseif ((method_exists($this,'search')) // implements its on search function ==> use it
{
$account_search[$serial]['data'] = $this->backend->search($param);
$account_search[$serial]['total'] = $this->total = $this->backend->total;
}
// search by old accounts_sql backend
else
{
$account_search[$serial]['data'] = array();
$accounts = $this->backend->get_list($param['type'],$param['start'],$param['sort'],$param['order'],$param['query'],$param['offset'],$param['query_type']);
if (!$accounts) $accounts = array();
foreach($accounts as $data)
{
$account_search[$serial]['data'][$data['account_id']] = $data;
}
$account_search[$serial]['total'] = $this->total = $this->backend->total;
}
//echo "<p>accounts::search(".array2string(unserialize($serial)).")= returning ".count($account_search[$serial]['data'])." of $this->total entries<pre>".print_r($account_search[$serial]['data'],True)."</pre>\n";
//echo "<p>accounts::search() end: ".microtime()."</p>\n";
return $account_search[$serial]['data'];
}

View File

@ -505,8 +505,8 @@ class accounts_ldap
// 'account_lastlogin' => $data['phpgwaccountlastlogin'][0],
// 'account_lastloginfrom' => $data['phpgwaccountlastloginfrom'][0],
'person_id' => $data['uid'][0], // id of associated contact
'account_created' => isset($data['createtimestamp'][0]) ? $this->accounts_ldap2ts($data['createtimestamp'][0]) : null,
'account_modified' => isset($data['modifytimestamp'][0]) ? $this->accounts_ldap2ts($data['modifytimestamp'][0]) : null,
'account_created' => isset($data['createtimestamp'][0]) ? self::accounts_ldap2ts($data['createtimestamp'][0]) : null,
'account_modified' => isset($data['modifytimestamp'][0]) ? self::accounts_ldap2ts($data['modifytimestamp'][0]) : null,
);
//echo "<p align=right>accounts_ldap::_read_user($account_id): shadowexpire={$data['shadowexpire'][0]} --> account_expires=$user[account_expires]=".date('Y-m-d H:i',$user['account_expires'])."</p>\n";
if ($this->frontend->config['ldap_extra_attributes'])
@ -621,7 +621,7 @@ class accounts_ldap
* 'exact' - query all fields for exact $param[query]
* 'lid','firstname','lastname','email' - query only the given field for containing $param[query]
* @param $param['offset'] int - number of matches to return if start given, default use the value in the prefs
* @return array with uid / data pairs, data is an array with account_id, account_lid, account_firstname,
* @return array with account_id => data pairs, data is an array with account_id, account_lid, account_firstname,
* account_lastname, person_id (id of the linked addressbook entry), account_status, account_expires, account_primary_group
*/
function search($param)
@ -751,16 +751,16 @@ class accounts_ldap
$test = @$allVals['uid'][0];
if (!$this->frontend->config['global_denied_users'][$test] && $allVals['uid'][0])
{
$accounts[] = Array(
$accounts[$allVals['uidnumber'][0]] = Array(
'account_id' => $allVals['uidnumber'][0],
'account_lid' => $GLOBALS['egw']->translation->convert($allVals['uid'][0],'utf-8'),
'account_lid' => translation::convert($allVals['uid'][0],'utf-8'),
'account_type' => 'u',
'account_firstname' => $GLOBALS['egw']->translation->convert($allVals['givenname'][0],'utf-8'),
'account_lastname' => $GLOBALS['egw']->translation->convert($allVals['sn'][0],'utf-8'),
'account_firstname' => translation::convert($allVals['givenname'][0],'utf-8'),
'account_lastname' => translation::convert($allVals['sn'][0],'utf-8'),
'account_status' => isset($allVals['shadowexpire'][0]) && $allVals['shadowexpire'][0]*24*3600-$utc_diff < time() ? false : 'A',
'account_email' => $allVals['mail'][0],
'account_created' => isset($allVals['createtimestamp'][0]) ? $this->accounts_ldap2ts($allVals['createtimestamp'][0]) : null,
'account_modified' => isset($allVals['modifytimestamp'][0]) ? $this->accounts_ldap2ts($allVals['modifytimestamp'][0]) : null,
'account_created' => isset($allVals['createtimestamp'][0]) ? self::accounts_ldap2ts($allVals['createtimestamp'][0]) : null,
'account_modified' => isset($allVals['modifytimestamp'][0]) ? self::accounts_ldap2ts($allVals['modifytimestamp'][0]) : null,
);
}
@ -796,11 +796,11 @@ class accounts_ldap
$test = $allVals['cn'][0];
if (!$this->frontend->config['global_denied_groups'][$test] && $allVals['cn'][0])
{
$accounts[] = Array(
$accounts[(string)-$allVals['gidnumber'][0]] = Array(
'account_id' => -$allVals['gidnumber'][0],
'account_lid' => $GLOBALS['egw']->translation->convert($allVals['cn'][0],'utf-8'),
'account_lid' => translation::convert($allVals['cn'][0],'utf-8'),
'account_type' => 'g',
'account_firstname' => $GLOBALS['egw']->translation->convert($allVals['cn'][0],'utf-8'),
'account_firstname' => translation::convert($allVals['cn'][0],'utf-8'),
'account_lastname' => lang('Group'),
'account_status' => 'A',
);
@ -808,12 +808,11 @@ class accounts_ldap
}
}
// sort the array
$arrayFunctions =& CreateObject('phpgwapi.arrayfunctions');
if(empty($param['order']))
{
$param['order'] = 'account_lid';
}
$account_search[$unl_serial]['data'] = $sortedAccounts = $arrayFunctions->arfsort($accounts,explode(',',$param['order']),$param['sort']);
$this->_callback_sort = strtoupper($param['sort']);
$this->_callback_order = empty($param['order']) ? array('account_lid') : explode(',',$param['order']);
uasort($sortedAccounts=$accounts,array($this,'_sort_callback'));
$account_search[$unl_serial]['data'] = $sortedAccounts;
$account_search[$unl_serial]['total'] = $this->total = isset($totalcount) ? $totalcount : count($accounts);
}
//echo "<p>accounts_ldap::search() found $this->total: ".microtime()."</p>\n";
@ -827,6 +826,46 @@ class accounts_ldap
return $sortedAccounts;
}
/**
* DESC or ASC
*
* @var string
*/
private $_callback_sort = 'DESC';
/**
* column_names to sort by
*
* @var array
*/
private $_callback_order = array('account_lid');
/**
* Sort callback for uasort
*
* @param array $a
* @param array $b
* @return int
*/
function _sort_callback($a,$b)
{
foreach($this->_callback_order as $col )
{
if($this->_callback_sort == 'ASC')
{
$cmp = strcasecmp( $a[$col], $b[$col] );
}
else
{
$cmp = strcasecmp( $b[$col], $a[$col] );
}
if ( $cmp != 0 )
{
return $cmp;
}
}
return 0;
}
/**
* Creates a timestamp from the date returned by the ldap server
*
@ -834,9 +873,9 @@ class accounts_ldap
* @param string $date YYYYmmddHHiiss
* @return int
*/
protected function accounts_ldap2ts($date)
protected static function accounts_ldap2ts($date)
{
if (isset($date) && strlen($date)>0)
if (!empty($date))
{
return gmmktime(substr($date,8,2),substr($date,10,2),substr($date,12,2),
substr($date,4,2),substr($date,6,2),substr($date,0,4));