2016-02-18 20:45:37 +01:00
|
|
|
<?php
|
|
|
|
/**
|
|
|
|
* EGroupware - eTemplate serverside of owner list widget
|
|
|
|
*
|
|
|
|
* @license http://opensource.org/licenses/gpl-license.php GPL - GNU General Public License
|
|
|
|
* @package etemplate
|
|
|
|
* @subpackage api
|
|
|
|
* @link http://www.egroupware.org
|
|
|
|
* @author Nathan Gray
|
|
|
|
* @copyright 2016 Nathan Gray
|
|
|
|
* @version $Id$
|
|
|
|
*/
|
|
|
|
|
2016-05-01 19:47:59 +02:00
|
|
|
use EGroupware\Api;
|
|
|
|
use EGroupware\Api\Link;
|
|
|
|
use EGroupware\Api\Framework;
|
|
|
|
use EGroupware\Api\Etemplate;
|
|
|
|
|
2016-02-18 20:45:37 +01:00
|
|
|
/**
|
|
|
|
* eTemplate tag list widget
|
|
|
|
*
|
|
|
|
* The naming convention is <appname>_<subtype>_etemplate_widget
|
|
|
|
*/
|
2016-05-01 19:47:59 +02:00
|
|
|
class calendar_owner_etemplate_widget extends Etemplate\Widget\Taglist
|
2016-02-18 20:45:37 +01:00
|
|
|
{
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Make sure all the needed select options are there
|
|
|
|
*
|
|
|
|
* @param string $cname
|
|
|
|
* @param array $expand values for keys 'c', 'row', 'c_', 'row_', 'cont'
|
|
|
|
*/
|
|
|
|
public function beforeSendToClient($cname, array $expand=null)
|
|
|
|
{
|
|
|
|
|
2016-05-24 23:08:48 +02:00
|
|
|
Framework::includeCSS('calendar','calendar');
|
2016-05-01 11:57:48 +02:00
|
|
|
|
2016-02-18 20:45:37 +01:00
|
|
|
$bo = new calendar_bo();
|
|
|
|
|
|
|
|
$form_name = self::form_name($cname, $this->id, $expand);
|
|
|
|
|
|
|
|
$value =& self::get_array(self::$request->content, $form_name);
|
2017-06-26 12:52:12 +02:00
|
|
|
|
2016-02-18 20:45:37 +01:00
|
|
|
if (!is_array(self::$request->sel_options[$form_name]))
|
|
|
|
{
|
|
|
|
self::$request->sel_options[$form_name] = array();
|
|
|
|
}
|
|
|
|
$sel_options =& self::$request->sel_options[$form_name];
|
|
|
|
|
2020-04-22 21:08:50 +02:00
|
|
|
if($value && !is_array($value))
|
2017-06-26 12:52:12 +02:00
|
|
|
{
|
|
|
|
// set value with an empty string only if sel options are not
|
|
|
|
// loaded, for example: setting calendar owner via URL when
|
|
|
|
// calendar app is not yet loaded.
|
|
|
|
$value = !empty($sel_options) ? array(): explode(',', $value);
|
|
|
|
}
|
2018-06-29 10:12:59 +02:00
|
|
|
|
2016-02-18 20:45:37 +01:00
|
|
|
// Add external owners that a select account widget will not find
|
2020-09-25 14:35:40 +02:00
|
|
|
foreach((array)$value as $owner)
|
2016-02-18 20:45:37 +01:00
|
|
|
{
|
2016-05-02 21:22:52 +02:00
|
|
|
$label = self::get_owner_label($owner);
|
2016-07-19 22:09:58 +02:00
|
|
|
$info = array();
|
2016-02-18 20:45:37 +01:00
|
|
|
if(!is_numeric($owner))
|
|
|
|
{
|
|
|
|
$resource = $bo->resources[substr($owner, 0,1)];
|
2016-08-24 12:34:55 +02:00
|
|
|
if($resource['info'] && !($info = $bo->resource_info($owner)))
|
2016-07-19 22:09:58 +02:00
|
|
|
{
|
2016-08-24 12:34:55 +02:00
|
|
|
continue; // ignore that resource, we would get a PHP Fatal: Unsupported operand types
|
2016-07-19 22:09:58 +02:00
|
|
|
}
|
2016-02-18 20:45:37 +01:00
|
|
|
}
|
2020-04-23 00:37:43 +02:00
|
|
|
else
|
2016-02-18 20:45:37 +01:00
|
|
|
{
|
2016-05-01 11:57:48 +02:00
|
|
|
$resource = array('app'=> 'api-accounts');
|
2016-02-18 20:45:37 +01:00
|
|
|
}
|
2019-09-03 23:50:14 +02:00
|
|
|
if ($resource && is_numeric ($owner) && (int)$owner < 0)
|
2018-12-19 23:31:17 +01:00
|
|
|
{
|
|
|
|
// Add in group memberships as strings
|
|
|
|
$info['resources'] = array_map(function($a) { return ''.$a;},$GLOBALS['egw']->accounts->members($owner, true));
|
|
|
|
}
|
2019-09-03 23:50:14 +02:00
|
|
|
|
2018-12-19 23:31:17 +01:00
|
|
|
$option = array('value' => $owner, 'label' => $label, 'app' => lang($resource['app'])) + $info;
|
|
|
|
$sel_option_index = $this->get_index($sel_options, 'value', $owner);
|
|
|
|
if($sel_option_index === false)
|
|
|
|
{
|
|
|
|
$sel_options[] = $option;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
$sel_options[$sel_option_index] = array_merge($sel_options[$sel_option_index], $option);
|
|
|
|
}
|
2016-02-18 20:45:37 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-12-19 23:31:17 +01:00
|
|
|
/**
|
|
|
|
* Get the index of an array (sel_options) containing the given value
|
|
|
|
*
|
|
|
|
* @param Array $array
|
|
|
|
* @param string $key key we're checking to match value
|
|
|
|
* @param string $value Value we're looking for
|
|
|
|
* @return boolean|int Returns index
|
|
|
|
*/
|
|
|
|
private function get_index(&$array, $key, $value)
|
|
|
|
{
|
|
|
|
foreach($array as $_key => $_value)
|
|
|
|
{
|
|
|
|
if($_value[$key] === $value) return $_key;
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
2016-02-18 21:54:26 +01:00
|
|
|
/**
|
|
|
|
* Validate input
|
|
|
|
*
|
|
|
|
* @param string $cname current namespace
|
|
|
|
* @param array $expand values for keys 'c', 'row', 'c_', 'row_', 'cont'
|
|
|
|
* @param array $content
|
|
|
|
* @param array &$validated=array() validated content
|
|
|
|
*/
|
|
|
|
public function validate($cname, array $expand, array $content, &$validated=array())
|
|
|
|
{
|
|
|
|
$form_name = self::form_name($cname, $this->id, $expand);
|
|
|
|
|
|
|
|
if (!$this->is_readonly($cname, $form_name))
|
|
|
|
{
|
|
|
|
$value = $value_in =& self::get_array($content, $form_name);
|
|
|
|
if(!is_array($value))
|
|
|
|
{
|
|
|
|
$value = Array($value);
|
|
|
|
}
|
2016-05-01 11:57:48 +02:00
|
|
|
|
2016-02-18 21:54:26 +01:00
|
|
|
$valid =& self::get_array($validated, $form_name, true);
|
2016-05-01 19:47:59 +02:00
|
|
|
if (true) $valid = $value;
|
2016-02-18 21:54:26 +01:00
|
|
|
}
|
|
|
|
}
|
2016-02-18 20:45:37 +01:00
|
|
|
/**
|
|
|
|
* Handle ajax searches for owner across all supported resources
|
|
|
|
*
|
|
|
|
* @return Array List of matching results
|
|
|
|
*/
|
2016-05-02 21:22:52 +02:00
|
|
|
public static function ajax_owner($id = null)
|
2016-02-18 20:45:37 +01:00
|
|
|
{
|
2021-10-20 13:53:19 +02:00
|
|
|
// close session now, to not block other user actions
|
|
|
|
$GLOBALS['egw']->session->commit_session();
|
|
|
|
|
2016-05-02 21:22:52 +02:00
|
|
|
// Handle a request for a single ID
|
2020-06-26 21:11:46 +02:00
|
|
|
if($id && !is_array($id))
|
2016-05-02 21:22:52 +02:00
|
|
|
{
|
|
|
|
$label = self::get_owner_label($id);
|
|
|
|
Api\Json\Response::get()->data($label);
|
|
|
|
return $label;
|
|
|
|
}
|
2020-06-26 21:11:46 +02:00
|
|
|
else if($id && is_array($id))
|
|
|
|
{
|
|
|
|
$labels = Array();
|
|
|
|
foreach($id as $index => $_id)
|
|
|
|
{
|
2020-08-04 00:42:31 +02:00
|
|
|
$labels[$_id] = self::format_owner($_id, self::get_owner_label($_id));
|
2020-06-26 21:11:46 +02:00
|
|
|
}
|
|
|
|
Api\Json\Response::get()->data($labels);
|
|
|
|
return $labels;
|
|
|
|
}
|
2016-02-18 20:45:37 +01:00
|
|
|
|
2016-05-03 23:03:51 +02:00
|
|
|
$bo = new calendar_bo();
|
2016-02-18 20:45:37 +01:00
|
|
|
$query = $_REQUEST['query'];
|
2016-08-24 12:34:55 +02:00
|
|
|
|
2016-02-18 20:45:37 +01:00
|
|
|
// Arbitrarily limited to 50 / resource
|
2017-03-17 15:43:46 +01:00
|
|
|
$options = array('start' => 0, 'num_rows' => 50,
|
|
|
|
// Filter accounts out of addressbook
|
|
|
|
'filter' => array('account_id' => null)) +
|
2016-04-29 20:01:17 +02:00
|
|
|
array_diff_key($_REQUEST, array_flip(array('menuaction','query')));
|
2016-03-04 16:57:13 +01:00
|
|
|
$results = array();
|
2016-02-18 20:45:37 +01:00
|
|
|
|
2017-03-07 19:08:26 +01:00
|
|
|
// Contacts matching accounts the user does not have permission for cause
|
|
|
|
// confusion as user selects the contact and there's nothing there, so
|
|
|
|
// we remove those contacts
|
|
|
|
$remove_contacts = array();
|
|
|
|
|
2016-02-18 20:45:37 +01:00
|
|
|
$resources = array_merge(array('' => $bo->resources['']),$bo->resources);
|
2018-06-29 10:12:59 +02:00
|
|
|
$contacts_obj = new Api\Contacts();
|
2016-02-18 20:45:37 +01:00
|
|
|
foreach($resources as $type => $data)
|
|
|
|
{
|
|
|
|
$mapped = array();
|
|
|
|
$_results = array();
|
|
|
|
|
2016-05-01 19:47:59 +02:00
|
|
|
// Handle Api\Accounts seperately
|
2016-02-18 20:45:37 +01:00
|
|
|
if($type == '')
|
|
|
|
{
|
2020-04-22 21:08:50 +02:00
|
|
|
$owngroup_options = $options+array('account_type'=>'owngroups');
|
|
|
|
$own_groups = Api\Accounts::link_query('',$owngroup_options);
|
2016-06-27 11:39:25 +02:00
|
|
|
$account_options = $options + array('account_type' => 'both');
|
2017-03-09 21:16:57 +01:00
|
|
|
$_results += $remove_contacts = Api\Accounts::link_query($query, $account_options);
|
2016-07-06 21:18:36 +02:00
|
|
|
if (!empty($_REQUEST['checkgrants']))
|
|
|
|
{
|
2020-04-22 21:08:50 +02:00
|
|
|
$grants = (array)$GLOBALS['egw']->acl->get_grants('calendar') + $own_groups;
|
2017-03-07 19:08:26 +01:00
|
|
|
$_results = array_intersect_key($_results, $grants);
|
2016-07-06 21:18:36 +02:00
|
|
|
}
|
2016-02-18 20:45:37 +01:00
|
|
|
}
|
2017-03-07 19:08:26 +01:00
|
|
|
// App provides a custom search function
|
2016-07-19 22:09:58 +02:00
|
|
|
else if ($data['app'] && $data['search'])
|
|
|
|
{
|
|
|
|
$_results = call_user_func_array($data['search'], array($query, $options));
|
|
|
|
}
|
2017-03-07 19:08:26 +01:00
|
|
|
// Use standard link registry
|
2016-05-01 19:47:59 +02:00
|
|
|
else if ($data['app'] && Link::get_registry($data['app'], 'query'))
|
2016-02-18 20:45:37 +01:00
|
|
|
{
|
2016-05-01 19:47:59 +02:00
|
|
|
$_results = Link::query($data['app'], $query,$options);
|
2016-02-18 20:45:37 +01:00
|
|
|
}
|
2017-03-07 19:08:26 +01:00
|
|
|
|
|
|
|
// There are always special cases
|
|
|
|
switch ($type)
|
2016-07-06 21:18:36 +02:00
|
|
|
{
|
2017-03-07 19:08:26 +01:00
|
|
|
case 'l':
|
2020-09-03 21:26:41 +02:00
|
|
|
// Include mailing lists, but not account groups
|
2017-03-07 19:08:26 +01:00
|
|
|
$lists = array_filter(
|
|
|
|
$contacts_obj->get_lists(Api\Acl::READ),
|
2020-09-03 21:26:41 +02:00
|
|
|
function($element, $index) use($query) {
|
|
|
|
return $index > 0 && (stripos($element, $query) !== false);
|
|
|
|
},
|
|
|
|
ARRAY_FILTER_USE_BOTH
|
2016-07-20 20:39:06 +02:00
|
|
|
);
|
2017-03-07 19:08:26 +01:00
|
|
|
foreach($lists as $list_id => $list)
|
|
|
|
{
|
2021-03-28 20:48:55 +02:00
|
|
|
$_results[(string)$list_id] = array(
|
2017-03-07 19:08:26 +01:00
|
|
|
'label' => $list,
|
|
|
|
'resources' => $bo->enum_mailing_list($type.$list_id)
|
|
|
|
);
|
|
|
|
}
|
|
|
|
break;
|
2016-07-06 21:18:36 +02:00
|
|
|
}
|
|
|
|
if(!$_results)
|
|
|
|
{
|
|
|
|
continue;
|
|
|
|
}
|
2016-02-18 20:45:37 +01:00
|
|
|
|
2017-01-20 16:55:57 +01:00
|
|
|
foreach(array_unique($_results, SORT_REGULAR) as $id => $title)
|
2016-02-18 20:45:37 +01:00
|
|
|
{
|
|
|
|
if($id && $title)
|
|
|
|
{
|
2020-08-04 00:42:31 +02:00
|
|
|
$mapped[] = static::format_owner($id, $title, $data);
|
2016-02-18 20:45:37 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
if(count($mapped))
|
|
|
|
{
|
|
|
|
$results = array_merge($results, $mapped);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// switch regular JSON response handling off
|
2016-05-01 19:47:59 +02:00
|
|
|
Api\Json\Request::isJSONRequest(false);
|
2016-02-18 20:45:37 +01:00
|
|
|
|
|
|
|
header('Content-Type: application/json; charset=utf-8');
|
|
|
|
echo json_encode($results);
|
2016-05-01 19:47:59 +02:00
|
|
|
exit();
|
2016-02-18 20:45:37 +01:00
|
|
|
}
|
2016-05-02 21:22:52 +02:00
|
|
|
|
2020-08-04 00:42:31 +02:00
|
|
|
/**
|
|
|
|
* Given an ID & title, format the result into data the client side wants
|
|
|
|
*
|
|
|
|
* @param $id
|
|
|
|
* @param $title
|
|
|
|
* @param $type
|
|
|
|
*/
|
|
|
|
protected static function format_owner($id, $title, $data = array())
|
|
|
|
{
|
|
|
|
static $contacts_obj = null;
|
|
|
|
if(is_null($contacts_obj))
|
|
|
|
{
|
|
|
|
$contacts_obj = new Api\Contacts();
|
|
|
|
}
|
|
|
|
if(!$data)
|
|
|
|
{
|
|
|
|
$bo = new calendar_bo();
|
|
|
|
if(!is_numeric($id))
|
|
|
|
{
|
|
|
|
$data = $bo->resources[substr($id, 0, 1)];
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
$data = $bo->resources[''];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
$type = $data['type'];
|
|
|
|
|
|
|
|
// Magicsuggest uses id, not value.
|
|
|
|
$value = array(
|
|
|
|
'id' => $type.$id,
|
|
|
|
'value'=> $type.$id,
|
|
|
|
'label' => $title,
|
|
|
|
'app' => lang($data['app'])
|
|
|
|
);
|
|
|
|
if(is_array($value['label']))
|
|
|
|
{
|
|
|
|
$value = array_merge($value, $value['label']);
|
|
|
|
}
|
|
|
|
switch($type)
|
|
|
|
{
|
|
|
|
case 'r':
|
|
|
|
// TODO: fetch resources photo
|
|
|
|
break;
|
|
|
|
case 'c':
|
|
|
|
case '':
|
|
|
|
$contact = $contacts_obj->read($type === '' ? 'account:'.$id : $id, true);
|
|
|
|
if (is_array($contact)) $value['icon'] = Api\Framework::link('/api/avatar.php', array(
|
|
|
|
'contact_id' => $contact['id'],
|
|
|
|
'etag' => $contact['etag'] ? $contact['etag'] : 1
|
|
|
|
));
|
|
|
|
if($id < 0)
|
|
|
|
{
|
|
|
|
$value['resources'] = array_map('strval',$GLOBALS['egw']->accounts->members($id, true));
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
default :
|
|
|
|
// do nothing
|
|
|
|
}
|
|
|
|
return $value;
|
|
|
|
}
|
|
|
|
|
2016-05-02 21:22:52 +02:00
|
|
|
/**
|
|
|
|
* Get just the label for a single owner
|
|
|
|
* @param string $id
|
|
|
|
*/
|
2016-05-16 22:32:03 +02:00
|
|
|
public static function get_owner_label($id)
|
2016-05-02 21:22:52 +02:00
|
|
|
{
|
2019-03-09 12:38:15 +01:00
|
|
|
static $bo=null;
|
2016-05-02 21:22:52 +02:00
|
|
|
if(!$bo) $bo = new calendar_bo();
|
|
|
|
|
|
|
|
$id = ''.$id;
|
|
|
|
if(!is_numeric($id))
|
|
|
|
{
|
|
|
|
$resource = $bo->resources[substr($id, 0,1)];
|
|
|
|
$label = Link::title($resource['app'], substr($id,1));
|
2016-06-23 15:49:44 +02:00
|
|
|
|
2016-05-02 21:22:52 +02:00
|
|
|
// Could not get via link, try via resources info
|
|
|
|
if($label === false)
|
|
|
|
{
|
|
|
|
$info = ExecMethod($resource['info'], substr($id,1));
|
|
|
|
$label = $info[0]['name'];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2019-01-11 19:50:55 +01:00
|
|
|
$label = Link::title('api-accounts',$id) ?: Api\Accounts::username($id);
|
2016-05-02 21:22:52 +02:00
|
|
|
}
|
|
|
|
return $label;
|
|
|
|
}
|
2016-02-18 20:45:37 +01:00
|
|
|
}
|