2005-11-04 00:47:52 +01:00
< ? php
2006-06-13 06:30:16 +02:00
/**
2011-04-07 09:28:46 +02:00
* EGroupware - Addressbook - user interface
2006-06-13 06:30:16 +02:00
*
* @ link www . egroupware . org
* @ author Cornelius Weiss < egw @ von - und - zu - weiss . de >
* @ author Ralf Becker < RalfBecker - AT - outdoor - training . de >
2019-02-13 14:52:57 +01:00
* @ copyright ( c ) 2005 - 19 by Ralf Becker < RalfBecker - AT - outdoor - training . de >
2008-04-04 10:14:30 +02:00
* @ copyright ( c ) 2005 / 6 by Cornelius Weiss < egw @ von - und - zu - weiss . de >
2006-06-13 06:30:16 +02:00
* @ package addressbook
* @ license http :// opensource . org / licenses / gpl - license . php GPL - GNU General Public License
*/
2005-11-04 00:47:52 +01:00
2016-04-06 11:49:50 +02:00
use EGroupware\Api ;
2016-04-29 12:41:53 +02:00
use EGroupware\Api\Link ;
use EGroupware\Api\Framework ;
use EGroupware\Api\Egw ;
use EGroupware\Api\Acl ;
use EGroupware\Api\Vfs ;
use EGroupware\Api\Etemplate ;
2020-11-09 23:56:24 +01:00
use EGroupware\Kanban\Hooks ;
2016-04-06 11:49:50 +02:00
2005-11-04 00:47:52 +01:00
/**
* General user interface object of the adressbook
*/
2008-05-10 14:02:49 +02:00
class addressbook_ui extends addressbook_bo
2005-11-04 00:47:52 +01:00
{
2009-05-11 08:47:38 +02:00
public $public_functions = array (
2021-03-28 20:48:55 +02:00
'extSearch' => True ,
2005-11-04 00:47:52 +01:00
'edit' => True ,
2005-11-11 21:50:12 +01:00
'view' => True ,
2006-04-23 16:40:31 +02:00
'index' => True ,
'photo' => True ,
2006-06-16 06:44:58 +02:00
'emailpopup' => True ,
2006-07-08 02:36:23 +02:00
'migrate2ldap' => True ,
2009-05-09 09:58:16 +02:00
'admin_set_fileas' => True ,
2009-11-11 09:44:51 +01:00
'admin_set_all_cleanup' => True ,
2008-03-10 17:33:17 +01:00
'cat_add' => True ,
2005-11-04 00:47:52 +01:00
);
2009-05-11 08:47:38 +02:00
protected $org_views ;
2005-11-04 00:47:52 +01:00
2007-05-22 10:02:06 +02:00
/**
* Addressbook configuration ( stored as phpgwapi = general server config )
*
* @ var array
*/
2009-05-11 08:47:38 +02:00
protected $config ;
2010-08-30 12:21:23 +02:00
/**
* Fields to copy , default if nothing specified in config
2010-11-04 21:40:33 +01:00
*
2010-08-30 12:21:23 +02:00
* @ var array
*/
static public $copy_fields = array (
'org_name' ,
'org_unit' ,
'adr_one_street' ,
'adr_one_street2' ,
'adr_one_locality' ,
'adr_one_region' ,
'adr_one_postalcode' ,
'adr_one_countryname' ,
2011-03-07 18:25:54 +01:00
'adr_one_countrycode' ,
2010-08-30 12:21:23 +02:00
'email' ,
'url' ,
'tel_work' ,
'cat_id'
);
2014-03-06 19:39:52 +01:00
/**
* Instance of eTemplate class
*
2016-04-29 12:41:53 +02:00
* @ var Etemplate
2014-03-06 19:39:52 +01:00
*/
protected $tmpl ;
2020-10-16 21:34:26 +02:00
/**
* @ var array
*/
public $grouped_views ;
2006-12-16 13:02:14 +01:00
/**
2009-05-11 08:47:38 +02:00
* Constructor
2006-12-16 13:02:14 +01:00
*
2009-05-11 08:47:38 +02:00
* @ param string $contact_app
2006-12-16 13:02:14 +01:00
*/
2008-05-10 14:02:49 +02:00
function __construct ( $contact_app = 'addressbook' )
2005-11-04 00:47:52 +01:00
{
2008-05-10 14:02:49 +02:00
parent :: __construct ( $contact_app );
2006-04-23 16:40:31 +02:00
2016-04-29 12:41:53 +02:00
$this -> tmpl = new Etemplate ();
2005-11-04 00:47:52 +01:00
2017-03-13 19:11:37 +01:00
$this -> grouped_views = array (
2006-04-30 11:34:24 +02:00
'org_name' => lang ( 'Organisations' ),
'org_name,adr_one_locality' => lang ( 'Organisations by location' ),
'org_name,org_unit' => lang ( 'Organisations by departments' ),
2020-10-16 21:34:26 +02:00
'duplicates' => lang ( 'Duplicates' ),
'shared_by_me' => lang ( 'Shared by me' ),
2006-04-30 11:34:24 +02:00
);
2006-04-23 16:40:31 +02:00
2011-09-15 16:46:56 +02:00
// make sure the hook for export_limit is registered
2016-04-29 12:41:53 +02:00
if ( ! Api\Hooks :: exists ( 'export_limit' , 'addressbook' )) Api\Hooks :: read ( true );
2011-09-15 16:46:56 +02:00
2006-06-17 20:50:07 +02:00
$this -> config =& $GLOBALS [ 'egw_info' ][ 'server' ];
2008-10-16 13:17:49 +02:00
// check if a contact specific export limit is set, if yes use it also for etemplate's csv export
2016-04-29 12:41:53 +02:00
$this -> config [ 'export_limit' ] = $this -> config [ 'contact_export_limit' ] = Api\Storage\Merge :: getExportLimit ( $app = 'addressbook' );
2011-09-15 16:46:56 +02:00
2011-08-26 15:50:20 +02:00
if ( $this -> config [ 'copy_fields' ] && ( $fields = is_array ( $this -> config [ 'copy_fields' ]) ?
$this -> config [ 'copy_fields' ] : unserialize ( $this -> config [ 'copy_fields' ])))
2010-08-30 12:21:23 +02:00
{
2011-03-07 19:32:20 +01:00
// Set country code if country name is selected
$supported_fields = $this -> get_fields ( 'supported' , null , 0 );
if ( in_array ( 'adr_one_countrycode' , $supported_fields ) && in_array ( 'adr_one_countryname' , $fields ))
{
$fields [] = 'adr_one_countrycode' ;
}
if ( in_array ( 'adr_two_countrycode' , $supported_fields ) && in_array ( 'adr_two_countryname' , $fields ))
{
$fields [] = 'adr_two_countrycode' ;
}
2010-08-30 12:21:23 +02:00
self :: $copy_fields = $fields ;
}
2006-04-23 16:40:31 +02:00
}
2008-04-18 08:10:31 +02:00
2006-04-23 16:40:31 +02:00
/**
* List contacts of an addressbook
*
2016-04-29 12:41:53 +02:00
* @ param array $_content = null submitted content
* @ param string $msg = null message to show
2006-04-23 16:40:31 +02:00
*/
2018-11-20 18:27:43 +01:00
function index ( $_content = null , $msg = null )
2006-04-23 16:40:31 +02:00
{
2016-04-29 12:41:53 +02:00
//echo "<p>uicontacts::index(".print_r($_content,true).",'$msg')</p>\n";
if (( $re_submit = is_array ( $_content )))
2006-04-23 16:40:31 +02:00
{
2005-11-04 00:47:52 +01:00
2016-04-29 12:41:53 +02:00
if ( isset ( $_content [ 'nm' ][ 'rows' ][ 'delete' ])) // handle a single delete like delete with the checkboxes
2006-04-23 16:40:31 +02:00
{
2018-12-18 18:20:23 +01:00
$id = @ key ( $_content [ 'nm' ][ 'rows' ][ 'delete' ]);
2016-04-29 12:41:53 +02:00
$_content [ 'nm' ][ 'action' ] = 'delete' ;
$_content [ 'nm' ][ 'selected' ] = array ( $id );
2006-04-23 16:40:31 +02:00
}
2016-04-29 12:41:53 +02:00
if ( isset ( $_content [ 'nm' ][ 'rows' ][ 'document' ])) // handle insert in default document button like an action
2007-06-17 15:55:43 +02:00
{
2018-12-18 18:20:23 +01:00
$id = @ key ( $_content [ 'nm' ][ 'rows' ][ 'document' ]);
2016-04-29 12:41:53 +02:00
$_content [ 'nm' ][ 'action' ] = 'document' ;
$_content [ 'nm' ][ 'selected' ] = array ( $id );
2007-06-17 15:55:43 +02:00
}
2016-04-29 12:41:53 +02:00
if ( $_content [ 'nm' ][ 'action' ] !== '' && $_content [ 'nm' ][ 'action' ] !== null )
2006-04-23 16:40:31 +02:00
{
2016-04-29 12:41:53 +02:00
if ( ! count ( $_content [ 'nm' ][ 'selected' ]) && ! $_content [ 'nm' ][ 'select_all' ] && $_content [ 'nm' ][ 'action' ] != 'delete_list' )
2006-04-23 16:40:31 +02:00
{
$msg = lang ( 'You need to select some contacts first' );
}
2017-03-13 19:11:37 +01:00
elseif ( $_content [ 'nm' ][ 'action' ] == 'view_org' || $_content [ 'nm' ][ 'action' ] == 'view_duplicates' )
2011-04-25 13:30:37 +02:00
{
2017-03-13 19:11:37 +01:00
// grouped view via context menu
$_content [ 'nm' ][ 'grouped_view' ] = array_shift ( $_content [ 'nm' ][ 'selected' ]);
2011-04-25 13:30:37 +02:00
}
2006-04-23 16:40:31 +02:00
else
{
2016-04-29 12:41:53 +02:00
$success = $failed = $action_msg = null ;
if ( $this -> action ( $_content [ 'nm' ][ 'action' ], $_content [ 'nm' ][ 'selected' ], $_content [ 'nm' ][ 'select_all' ],
2020-10-26 10:44:40 +01:00
$success , $failed , $action_msg , 'index' , $msg , $_content [ 'nm' ][ 'checkboxes' ], $error_msg ))
2006-04-23 16:40:31 +02:00
{
$msg .= lang ( '%1 contact(s) %2' , $success , $action_msg );
2016-04-29 12:41:53 +02:00
Framework :: message ( $msg );
2006-04-23 16:40:31 +02:00
}
2007-03-13 14:38:15 +01:00
elseif ( is_null ( $msg ))
2006-04-23 16:40:31 +02:00
{
2020-10-26 10:44:40 +01:00
if ( empty ( $error_msg ))
{
$msg .= lang ( '%1 contact(s) %2, %3 failed because of insufficent rights !!!' , $success , $action_msg , $failed );
}
else
{
$msg .= lang ( '%1 contact(s) %2, %3 failed because of %4 !!!' , $success , $action_msg , $failed , $error_msg );
}
2016-04-29 12:41:53 +02:00
Framework :: message ( $msg , 'error' );
2006-04-23 16:40:31 +02:00
}
2014-02-06 00:36:01 +01:00
$msg = '' ;
2006-04-23 16:40:31 +02:00
}
}
2021-10-06 16:07:47 +02:00
if ( ! empty ( $_content [ 'nm' ][ 'rows' ][ 'infolog' ]))
2006-10-23 13:48:56 +02:00
{
2018-12-18 18:20:23 +01:00
$org = key ( $_content [ 'nm' ][ 'rows' ][ 'infolog' ]);
2006-10-23 13:48:56 +02:00
return $this -> infolog_org_view ( $org );
}
2021-10-06 16:07:47 +02:00
if ( ! empty ( $_content [ 'nm' ][ 'rows' ][ 'view' ])) // show all contacts of an organisation
2006-04-30 11:34:24 +02:00
{
2018-12-18 18:20:23 +01:00
$grouped_view = key ( $_content [ 'nm' ][ 'rows' ][ 'view' ]);
2006-04-30 11:34:24 +02:00
}
else
{
2017-03-13 19:11:37 +01:00
$grouped_view = $_content [ 'nm' ][ 'grouped_view' ];
2006-04-30 11:34:24 +02:00
}
2016-04-29 12:41:53 +02:00
$typeselection = $_content [ 'nm' ][ 'col_filter' ][ 'tid' ];
2006-04-23 16:40:31 +02:00
}
2007-03-13 14:38:15 +01:00
elseif ( $_GET [ 'add_list' ])
{
2007-05-25 20:20:57 +02:00
$list = $this -> add_list ( $_GET [ 'add_list' ], $_GET [ 'owner' ] ? $_GET [ 'owner' ] : $this -> user );
if ( $list === true )
{
$msg = lang ( 'List already exists!' );
}
elseif ( $list )
2007-03-13 14:38:15 +01:00
{
$msg = lang ( 'List created' );
}
else
{
$msg = lang ( 'List creation failed, no rights!' );
}
}
2018-11-20 18:27:43 +01:00
$preserv = array ();
2014-02-06 00:36:01 +01:00
$content = array ();
if ( $msg || $_GET [ 'msg' ])
{
2016-04-29 12:41:53 +02:00
Framework :: message ( $msg ? $msg : $_GET [ 'msg' ]);
2014-02-06 00:36:01 +01:00
}
2007-11-23 09:32:08 +01:00
2018-11-20 18:27:43 +01:00
$content [ 'nm' ] = Api\Cache :: getSession ( 'addressbook' , 'index' );
2006-04-24 13:15:10 +02:00
if ( ! is_array ( $content [ 'nm' ]))
2006-04-23 16:40:31 +02:00
{
$content [ 'nm' ] = array (
2008-05-10 14:02:49 +02:00
'get_rows' => 'addressbook.addressbook_ui.get_rows' , // I method/callback to request the data for the rows eg. 'notes.bo.get_rows'
2006-04-23 16:40:31 +02:00
'bottom_too' => false , // I show the nextmatch-line (arrows, filters, search, ...) again after the rows
'never_hide' => True , // I never hide the nextmatch-line if less then maxmatch entrie
'start' => 0 , // IO position in list
2006-10-07 11:17:30 +02:00
'cat_id' => '' , // IO category, if not 'no_cat' => True
2006-04-23 16:40:31 +02:00
'search' => '' , // IO search pattern
'order' => 'n_family' , // IO name of the column to sort after (optional for the sortheaders)
'sort' => 'ASC' , // IO direction of the sort: 'ASC' or 'DESC'
'col_filter' => array (), // IO array of column-name value pairs (optional for the filterheaders)
2016-02-17 14:23:27 +01:00
//'cat_id_label' => lang('Categories'),
//'filter_label' => lang('Addressbook'), // I label for filter (optional)
2006-06-24 08:09:02 +02:00
'filter' => '' , // =All // IO filter, if not 'no_filter' => True
2006-04-23 16:40:31 +02:00
'filter_no_lang' => True , // I set no_lang for filter (=dont translate the options)
'no_filter2' => True , // I disable the 2. filter (params are the same as for filter)
2016-02-17 14:23:27 +01:00
//'filter2_label'=> lang('Distribution lists'), // IO filter2, if not 'no_filter2' => True
2006-04-23 16:40:31 +02:00
'filter2' => '' , // IO filter2, if not 'no_filter2' => True
'filter2_no_lang' => True , // I set no_lang for filter2 (=dont translate the options)
'lettersearch' => true ,
2014-09-24 10:26:19 +02:00
// using a positiv list now, as we constantly adding new columns in addressbook, but not removing them from default
'default_cols' => 'type,n_fileas_n_given_n_family_n_family_n_given_org_name_n_family_n_given_n_fileas,' .
2015-09-08 18:48:42 +02:00
'number,org_name,org_unit,' .
2014-09-24 10:26:19 +02:00
'business_adr_one_countrycode_adr_one_postalcode,tel_work_tel_cell_tel_home,url_email_email_home' ,
/* old negative list
'default_cols' => '!cat_id,contact_created_contact_modified,distribution_list,contact_id,owner,room' , */
2017-01-24 16:43:57 +01:00
'filter2_onchange' => " return app.addressbook.filter2_onchange(); " ,
2017-09-26 16:57:45 +02:00
'filter2_tags' => true ,
2011-04-17 16:10:05 +02:00
//'actions' => $this->get_actions(), // set on each request, as it depends on some filters
'row_id' => 'id' ,
2014-03-18 23:55:48 +01:00
'row_modified' => 'modified' ,
2021-02-25 22:01:16 +01:00
'add_on_top_sort_field' => 'modified' ,
2017-03-13 19:11:37 +01:00
'is_parent' => 'group_count' ,
2015-03-02 22:50:25 +01:00
'parent_id' => 'parent_id' ,
2013-03-21 00:11:54 +01:00
'favorites' => true ,
2006-04-23 16:40:31 +02:00
);
2008-06-05 14:04:00 +02:00
2006-04-23 16:40:31 +02:00
// use the state of the last session stored in the user prefs
2018-11-20 18:27:43 +01:00
if (( $state = @ unserialize ( $this -> prefs [ 'index_state' ])))
2006-04-23 16:40:31 +02:00
{
$content [ 'nm' ] = array_merge ( $content [ 'nm' ], $state );
}
}
2016-02-17 14:23:27 +01:00
$sel_options [ 'cat_id' ] = array ( '' => lang ( 'All categories' ), '0' => lang ( 'None' ));
2014-02-27 21:20:15 +01:00
2018-06-21 18:21:31 +02:00
$content [ 'nm' ][ 'placeholder_actions' ] = array ( 'add' );
2014-10-27 19:43:03 +01:00
// Edit and delete list actions depends on permissions
2016-04-29 12:41:53 +02:00
if ( $this -> get_lists ( Acl :: EDIT ))
2013-04-15 17:14:36 +02:00
{
2014-10-28 20:11:10 +01:00
$content [ 'nm' ][ 'placeholder_actions' ][] = 'rename_list' ;
$content [ 'nm' ][ 'placeholder_actions' ][] = 'delete_list' ;
2013-04-15 17:14:36 +02:00
}
2009-12-08 22:27:56 +01:00
// Search parameter passed in
if ( $_GET [ 'search' ]) {
$content [ 'nm' ][ 'search' ] = $_GET [ 'search' ];
}
2008-10-20 21:35:18 +02:00
if ( isset ( $typeselection )) $content [ 'nm' ][ 'col_filter' ][ 'tid' ] = $typeselection ;
2011-11-09 10:06:27 +01:00
// save the tid for use in creating new addressbook entrys via UI. Current tid is to be used as type of new entrys
//error_log(__METHOD__.__LINE__.' '.$content['nm']['col_filter']['tid']);
2016-04-29 12:41:53 +02:00
Api\Cache :: setSession ( 'addressbook' , 'active_tid' , $content [ 'nm' ][ 'col_filter' ][ 'tid' ]);
2007-05-03 07:07:30 +02:00
if ( $this -> lists_available ())
2007-03-13 14:38:15 +01:00
{
2016-04-29 12:41:53 +02:00
$sel_options [ 'filter2' ] = $this -> get_lists ( Acl :: READ , array ( '' => lang ( 'No distribution list' )));
2007-05-03 07:07:30 +02:00
$sel_options [ 'filter2' ][ 'add' ] = lang ( 'Add a new list' ) . '...' ; // put it at the end
2007-03-13 14:38:15 +01:00
}
2018-11-20 18:27:43 +01:00
2006-06-17 20:50:07 +02:00
// Organisation stuff is not (yet) availible with ldap
2018-11-20 18:27:43 +01:00
if ( $GLOBALS [ 'egw_info' ][ 'server' ][ 'contact_repository' ] != 'ldap' )
2006-06-17 20:50:07 +02:00
{
$content [ 'nm' ][ 'header_left' ] = 'addressbook.index.left' ;
2006-06-16 06:44:58 +02:00
}
2016-04-29 12:41:53 +02:00
$sel_options [ 'filter' ] = $sel_options [ 'owner' ] = $this -> get_addressbooks ( Acl :: READ , lang ( 'All addressbooks' ));
2007-03-13 14:38:15 +01:00
$sel_options [ 'to' ] = array (
'to' => 'To' ,
'cc' => 'Cc' ,
'bcc' => 'Bcc' ,
2006-04-23 16:40:31 +02:00
);
2016-05-09 20:42:27 +02:00
$sel_options [ 'adr_one_countrycode' ][ '-custom-' ] = lang ( 'No country selected' );
2011-04-17 16:10:05 +02:00
// if there is any export limit set, pass it on to the nextmatch, to be evaluated by the export
if ( isset ( $this -> config [ 'contact_export_limit' ]) && ( int ) $this -> config [ 'contact_export_limit' ]) $content [ 'nm' ][ 'export_limit' ] = $this -> config [ 'contact_export_limit' ];
2017-01-20 16:37:08 +01:00
// Merge to email dialog needs the infolog types
$infolog = new infolog_bo ();
$sel_options [ 'info_type' ] = $infolog -> enums [ 'type' ];
2017-04-04 16:52:25 +02:00
2011-04-17 16:10:05 +02:00
// dont show tid-selection if we have only one content_type
2011-04-25 13:30:37 +02:00
// be a bit more sophisticated about it
2011-04-17 16:10:05 +02:00
$availabletypes = array_keys ( $this -> content_types );
if ( $content [ 'nm' ][ 'col_filter' ][ 'tid' ] && ! in_array ( $content [ 'nm' ][ 'col_filter' ][ 'tid' ], $availabletypes ))
{
//_debug_array(array('Typefilter:'=> $content['nm']['col_filter']['tid'],'Available Types:'=>$availabletypes,'action:'=>'remove invalid filter'));
unset ( $content [ 'nm' ][ 'col_filter' ][ 'tid' ]);
}
if ( ! isset ( $content [ 'nm' ][ 'col_filter' ][ 'tid' ])) $content [ 'nm' ][ 'col_filter' ][ 'tid' ] = $availabletypes [ 0 ];
if ( count ( $this -> content_types ) > 1 )
{
foreach ( $this -> content_types as $tid => $data )
{
2013-06-04 00:43:03 +02:00
$sel_options [ 'tid' ][ $tid ] = $data [ 'name' ];
2011-04-17 16:10:05 +02:00
}
}
2015-02-04 11:30:59 +01:00
else
{
2016-03-29 17:37:50 +02:00
$this -> tmpl -> disableElement ( 'nm[col_filter][tid]' );
2015-02-04 11:30:59 +01:00
}
2017-03-13 19:11:37 +01:00
// get the availible grouped-views plus the label of the contacts view of one group
$sel_options [ 'grouped_view' ] = $this -> grouped_views ;
if ( isset ( $grouped_view ))
2015-03-03 23:23:19 +01:00
{
2017-03-13 19:11:37 +01:00
$content [ 'nm' ][ 'grouped_view' ] = $grouped_view ;
2015-03-03 23:23:19 +01:00
}
2011-04-25 13:30:37 +02:00
2017-03-13 19:11:37 +01:00
$content [ 'nm' ][ 'actions' ] = $this -> get_actions ( $content [ 'nm' ][ 'col_filter' ][ 'tid' ]);
2011-04-25 13:30:37 +02:00
2017-03-13 19:11:37 +01:00
if ( ! isset ( $sel_options [ 'grouped_view' ][( string ) $content [ 'nm' ][ 'grouped_view' ]]))
2011-04-17 16:10:05 +02:00
{
2017-03-13 19:11:37 +01:00
$sel_options [ 'grouped_view' ] += $this -> _get_grouped_name (( string ) $content [ 'nm' ][ 'grouped_view' ]);
2011-04-17 16:10:05 +02:00
}
2017-03-13 19:11:37 +01:00
// unset the filters regarding grouped views, when there is no group selected
if ( empty ( $sel_options [ 'grouped_view' ][( string ) $content [ 'nm' ][ 'grouped_view' ]]) || stripos ( $grouped_view , " : " ) === false )
2011-04-17 16:10:05 +02:00
{
2017-03-13 19:11:37 +01:00
$this -> unset_grouped_filters ( $content [ 'nm' ]);
2011-04-17 16:10:05 +02:00
}
2017-03-13 19:11:37 +01:00
$content [ 'nm' ][ 'grouped_view_label' ] = $sel_options [ 'grouped_view' ][( string ) $content [ 'nm' ][ 'grouped_view' ]];
2011-04-17 16:10:05 +02:00
2020-11-04 16:05:41 +01:00
// allow to also filter by (not) shared contacts
$sel_options [ 'shared_with' ] = [
'not' => lang ( 'not shared' ),
'shared' => lang ( 'shared' ),
];
2018-11-20 18:27:43 +01:00
$this -> tmpl -> read ( 'addressbook.index' );
return $this -> tmpl -> exec ( 'addressbook.addressbook_ui.index' ,
$content , $sel_options , array (), $preserv );
2011-04-17 16:10:05 +02:00
}
/**
* Get actions / context menu items
*
2020-11-02 12:55:38 +01:00
* @ param ? string $tid_filter = null
2016-04-29 12:41:53 +02:00
* @ return array see Etemplate\Widget\Nextmatch :: get_actions ()
2011-04-17 16:10:05 +02:00
*/
2016-04-29 12:41:53 +02:00
public function get_actions ( $tid_filter = null )
2011-04-17 16:10:05 +02:00
{
2015-03-10 16:41:53 +01:00
// Contact view
$actions = array (
'view' => array (
'caption' => 'CRM-View' ,
'default' => $GLOBALS [ 'egw_info' ][ 'user' ][ 'preferences' ][ 'addressbook' ][ 'crm_list' ] != '~edit~' ,
'allowOnMultiple' => false ,
'group' => $group = 1 ,
'onExecute' => 'javaScript:app.addressbook.view' ,
2017-03-13 19:11:37 +01:00
'enableClass' => 'contact_contact' ,
2015-03-10 16:41:53 +01:00
'hideOnDisabled' => true ,
// Children added below
2016-03-09 13:31:55 +01:00
'children' => array (),
'hideOnMobile' => true
2015-03-10 16:41:53 +01:00
),
'open' => array (
'caption' => 'Open' ,
'default' => $GLOBALS [ 'egw_info' ][ 'user' ][ 'preferences' ][ 'addressbook' ][ 'crm_list' ] == '~edit~' ,
'allowOnMultiple' => false ,
2017-03-13 19:11:37 +01:00
'enableClass' => 'contact_contact' ,
2015-03-10 16:41:53 +01:00
'hideOnDisabled' => true ,
'url' => 'menuaction=addressbook.addressbook_ui.edit&contact_id=$id' ,
2016-04-29 12:41:53 +02:00
'popup' => Link :: get_registry ( 'addressbook' , 'edit_popup' ),
2015-03-10 16:41:53 +01:00
'group' => $group ,
),
'add' => array (
'caption' => 'Add' ,
'group' => $group ,
'hideOnDisabled' => true ,
'children' => array (
'new' => array (
'caption' => 'New' ,
'url' => 'menuaction=addressbook.addressbook_ui.edit' ,
2016-04-29 12:41:53 +02:00
'popup' => Link :: get_registry ( 'addressbook' , 'add_popup' ),
2015-03-10 16:41:53 +01:00
'icon' => 'new' ,
),
'copy' => array (
'caption' => 'Copy' ,
'url' => 'menuaction=addressbook.addressbook_ui.edit&makecp=1&contact_id=$id' ,
2016-04-29 12:41:53 +02:00
'popup' => Link :: get_registry ( 'addressbook' , 'add_popup' ),
2018-04-04 00:22:34 +02:00
'enableClass' => 'contact_contact' ,
2015-03-10 16:41:53 +01:00
'allowOnMultiple' => false ,
'icon' => 'copy' ,
2011-04-25 13:30:37 +02:00
),
),
2016-03-09 13:31:55 +01:00
'hideOnMobile' => true
2015-03-10 16:41:53 +01:00
),
);
// CRM view options
$crm_apps = array ( 'infolog' , 'tracker' );
2021-03-08 22:59:21 +01:00
foreach ( $crm_apps as $crm_index => $app )
2015-03-10 16:41:53 +01:00
{
2021-03-08 22:59:21 +01:00
if ( ! $GLOBALS [ 'egw_info' ][ 'user' ][ 'apps' ][ $app ])
{
unset ( $crm_apps [ $crm_index ]);
}
2015-03-10 16:41:53 +01:00
}
2019-10-22 18:57:00 +02:00
if ( $GLOBALS [ 'egw_info' ][ 'user' ][ 'apps' ][ 'infolog' ])
{
array_splice ( $crm_apps , 1 , 0 , 'infolog-organisation' );
}
2021-03-08 22:59:21 +01:00
if ( count ( $crm_apps ) > 1 )
2015-03-10 16:41:53 +01:00
{
2014-03-25 17:53:36 +01:00
foreach ( $crm_apps as $app )
{
2015-03-10 16:41:53 +01:00
$actions [ 'view' ][ 'children' ][ " view- $app " ] = array (
'caption' => $app ,
'icon' => " $app /navbar "
);
2014-03-25 17:53:36 +01:00
}
2011-04-25 13:30:37 +02:00
}
2015-04-24 17:13:45 +02:00
2015-03-10 16:41:53 +01:00
// org view
$actions += array (
'view_org' => array (
'caption' => 'View' ,
'default' => true ,
'allowOnMultiple' => false ,
'group' => $group = 1 ,
2017-03-13 19:11:37 +01:00
'enableClass' => 'contact_organisation' ,
2015-03-10 16:41:53 +01:00
'hideOnDisabled' => true
),
'add_org' => array (
'caption' => 'Add' ,
'group' => $group ,
'allowOnMultiple' => false ,
2017-03-13 19:11:37 +01:00
'enableClass' => 'contact_organisation' ,
2015-03-10 16:41:53 +01:00
'hideOnDisabled' => true ,
'url' => 'menuaction=addressbook.addressbook_ui.edit&org=$id' ,
2016-04-29 12:41:53 +02:00
'popup' => Link :: get_registry ( 'addressbook' , 'add_popup' ),
2015-03-10 16:41:53 +01:00
),
);
2011-04-17 16:10:05 +02:00
2017-03-13 19:11:37 +01:00
// Duplicates view
$actions += array (
'view_duplicates' => array (
'caption' => 'View' ,
'default' => true ,
'allowOnMultiple' => false ,
'group' => $group = 1 ,
'enableClass' => 'contact_duplicate' ,
'hideOnDisabled' => true
)
);
2011-04-17 16:10:05 +02:00
++ $group ; // other AB related stuff group: lists, AB's, categories
// categories submenu
$actions [ 'cat' ] = array (
'caption' => 'Categories' ,
'group' => $group ,
'children' => array (
2016-04-29 12:41:53 +02:00
'cat_add' => Etemplate\Widget\Nextmatch :: category_action (
2012-10-15 19:57:58 +02:00
'addressbook' , $group , 'Add category' , 'cat_add_' ,
2016-04-29 12:41:53 +02:00
true , 0 , Etemplate\Widget\Nextmatch :: DEFAULT_MAX_MENU_LENGTH , false
2011-04-25 16:13:40 +02:00
) + array (
'icon' => 'foldertree_nolines_plus' ,
'disableClass' => 'rowNoEdit' ,
),
2016-04-29 12:41:53 +02:00
'cat_del' => Etemplate\Widget\Nextmatch :: category_action (
2012-10-15 19:57:58 +02:00
'addressbook' , $group , 'Delete category' , 'cat_del_' ,
2016-04-29 12:41:53 +02:00
true , 0 , Etemplate\Widget\Nextmatch :: DEFAULT_MAX_MENU_LENGTH , false
2011-04-25 16:13:40 +02:00
) + array (
'icon' => 'foldertree_nolines_minus' ,
'disableClass' => 'rowNoEdit' ,
2014-02-12 12:07:33 +01:00
),
2011-04-17 16:10:05 +02:00
),
);
if ( ! $GLOBALS [ 'egw_info' ][ 'user' ][ 'apps' ][ 'preferences' ]) unset ( $actions [ 'cats' ][ 'children' ][ 'cat_edit' ]);
// Submenu for all distributionlist stuff
$actions [ 'lists' ] = array (
'caption' => 'Distribution lists' ,
'children' => array (
'list_add' => array (
'caption' => 'Add a new list' ,
'icon' => 'new' ,
2013-09-20 12:50:48 +02:00
'onExecute' => 'javaScript:app.addressbook.add_new_list' ,
2011-04-17 16:10:05 +02:00
),
),
'group' => $group ,
);
2016-04-29 12:41:53 +02:00
if (( $add_lists = $this -> get_lists ( Acl :: EDIT ))) // do we have distribution lists?, and are we allowed to edit them
2011-04-17 16:10:05 +02:00
{
$actions [ 'lists' ][ 'children' ] += array (
'to_list' => array (
'caption' => 'Add to distribution list' ,
'children' => $add_lists ,
'prefix' => 'to_list_' ,
'icon' => 'foldertree_nolines_plus' ,
2012-01-05 05:10:54 +01:00
'enabled' => ( $add_lists ? true : false ), // if there are editable lists, allow to add a contact to one of them,
2011-12-28 11:55:24 +01:00
//'disableClass' => 'rowNoEdit', // wether you are allowed to edit the contact or not, as you alter a list, not the contact
2011-04-17 16:10:05 +02:00
),
'remove_from_list' => array (
'caption' => 'Remove from distribution list' ,
'confirm' => 'Remove selected contacts from distribution list' ,
'icon' => 'foldertree_nolines_minus' ,
2013-09-20 12:50:48 +02:00
'enabled' => 'javaScript:app.addressbook.nm_compare_field' ,
2011-04-25 16:13:40 +02:00
'fieldId' => 'exec[nm][filter2]' ,
'fieldValue' => '!' , // enable if list != ''
2011-04-17 16:10:05 +02:00
),
2014-10-27 19:43:03 +01:00
'rename_list' => array (
'caption' => 'Rename selected distribution list' ,
'icon' => 'edit' ,
'enabled' => 'javaScript:app.addressbook.nm_compare_field' ,
'fieldId' => 'exec[nm][filter2]' ,
'fieldValue' => '!' , // enable if list != ''
'onExecute' => 'javaScript:app.addressbook.rename_list'
),
2011-04-17 16:10:05 +02:00
'delete_list' => array (
'caption' => 'Delete selected distribution list!' ,
'confirm' => 'Delete selected distribution list!' ,
'icon' => 'delete' ,
2013-09-20 12:50:48 +02:00
'enabled' => 'javaScript:app.addressbook.nm_compare_field' ,
2011-04-25 16:13:40 +02:00
'fieldId' => 'exec[nm][filter2]' ,
'fieldValue' => '!' , // enable if list != ''
2011-04-17 16:10:05 +02:00
),
);
2013-06-10 21:47:09 +02:00
if ( is_subclass_of ( 'etemplate' , 'etemplate_new' ))
{
$actions [ 'lists' ][ 'children' ][ 'remove_from_list' ][ 'fieldId' ] = 'filter2' ;
2014-10-28 20:11:10 +01:00
$actions [ 'lists' ][ 'children' ][ 'rename_list' ][ 'fieldId' ] = 'filter2' ;
2013-06-10 21:47:09 +02:00
$actions [ 'lists' ][ 'children' ][ 'delete_list' ][ 'fieldId' ] = 'filter2' ;
}
2011-04-17 16:10:05 +02:00
}
// move to AB
2016-04-29 12:41:53 +02:00
if (( $move2addressbooks = $this -> get_addressbooks ( Acl :: ADD ))) // do we have addressbooks, we should
2011-04-17 16:10:05 +02:00
{
2014-08-19 16:12:40 +02:00
unset ( $move2addressbooks [ 0 ]); // do not offer action to move contact to an account, as we dont support that currrently
2011-04-25 13:30:37 +02:00
foreach ( $move2addressbooks as $owner => $label )
{
2016-04-29 12:41:53 +02:00
$icon = $type_label = null ;
2011-04-25 13:30:37 +02:00
$this -> type_icon (( int ) $owner , substr ( $owner , - 1 ) == 'p' , 'n' , $icon , $type_label );
$move2addressbooks [ $owner ] = array (
'icon' => $icon ,
'caption' => $label ,
);
}
2013-11-08 19:51:37 +01:00
// copy checkbox
$move2addressbooks = array (
'copy' => array (
'id' => 'move_to_copy' ,
'caption' => 'Copy instead of move' ,
'checkbox' => true ,
)) + $move2addressbooks ;
2011-04-17 16:10:05 +02:00
$actions [ 'move_to' ] = array (
'caption' => 'Move to addressbook' ,
'children' => $move2addressbooks ,
'prefix' => 'move_to_' ,
'group' => $group ,
2011-04-25 16:13:40 +02:00
'disableClass' => 'rowNoDelete' ,
2016-03-09 13:31:55 +01:00
'hideOnMobile' => true
2011-04-17 16:10:05 +02:00
);
}
2020-10-16 21:34:26 +02:00
if (( $share2addressbooks = $this -> get_addressbooks ( Acl :: EDIT | self :: ACL_SHARED , null , null , false )))
{
unset ( $share2addressbooks [ 0 ]); // do not offer action to share contact into accounts AB
foreach ( $share2addressbooks as $owner => $label )
{
if ( substr ( $owner , - 1 ) === 'p' ) // share with private AB makes no sense
{
unset ( $share2addressbooks [ $owner ]);
continue ;
}
$icon = $type_label = null ;
$this -> type_icon (( int ) $owner , substr ( $owner , - 1 ) == 'p' , 'n' , $icon , $type_label );
$share2addressbooks [ $owner ] = array (
'icon' => $icon ,
'caption' => $label ,
);
}
$actions [ 'shared_with' ] = [
'caption' => 'Share into addressbook' ,
'children' => [
'writable' => [
'id' => 'writable' ,
'caption' => 'Share writable' ,
'checkbox' => true ,
2020-10-19 18:34:11 +02:00
]] + $share2addressbooks + [
'unshare' => [
'icon' => 'delete' ,
'caption' => 'Unshare' ,
'group' => $group ,
'enableClass' => 'unshare_contact' ,
'hideOnDisabled' => true ,
'hideOnMobile' => true
]
],
2020-10-16 21:34:26 +02:00
'prefix' => 'shared_with_' ,
'group' => $group ,
'hideOnMobile' => true
];
}
2020-05-20 21:05:56 +02:00
$actions [ 'change_type' ] = $this -> change_type_actions ( $group );
2011-04-17 16:10:05 +02:00
$actions [ 'merge' ] = array (
'caption' => 'Merge contacts' ,
'confirm' => 'Merge into first or account, deletes all other!' ,
'hint' => 'Merge into first or account, deletes all other!' ,
2011-04-17 23:25:01 +02:00
'allowOnMultiple' => 'only' ,
2011-04-17 16:10:05 +02:00
'group' => $group ,
2018-06-12 21:49:59 +02:00
'hideOnMobile' => true ,
'enabled' => 'javaScript:app.addressbook.can_merge'
2011-04-17 16:10:05 +02:00
);
2017-03-22 21:27:05 +01:00
// Duplicates view
$actions [ 'merge_duplicates' ] = array (
'caption' => 'Merge duplicates' ,
'group' => $group ,
'allowOnMultiple' => true ,
'enableClass' => 'contact_duplicate' ,
'hideOnDisabled' => true
);
2011-04-17 16:10:05 +02:00
2018-08-08 16:06:17 +02:00
++ $group ; // integration with other apps: infolog, calendar, filemanager, messenger
2020-04-02 17:48:07 +02:00
// Integrate Status Videoconference actions
if ( $GLOBALS [ 'egw_info' ][ 'user' ][ 'apps' ][ 'status' ])
2018-08-08 16:06:17 +02:00
{
2020-04-02 17:48:07 +02:00
$actions [ 'videoconference' ] = [
'caption' => 'Video Conference' ,
2020-04-08 19:56:11 +02:00
'icon' => 'status/videoconference' ,
2018-08-08 16:06:17 +02:00
'group' => $group ,
2020-04-02 17:48:07 +02:00
'children' => [
'call' => [
2020-04-09 10:50:54 +02:00
'caption' => lang ( 'Video Call' ),
2020-04-08 19:56:11 +02:00
'icon' => 'status/videoconference_call' ,
2018-08-08 16:06:17 +02:00
'allowOnMultiple' => true ,
2020-04-02 17:48:07 +02:00
'onExecute' => 'javaScript:app.addressbook.videoconference_actionCall' ,
'enabled' => 'javaScript:app.addressbook.videoconference_isUserOnline'
],
2020-04-29 17:39:04 +02:00
'audiocall' => [
'caption' => lang ( 'Audio Call' ),
'icon' => 'accept_call' ,
'allowOnMultiple' => true ,
'onExecute' => 'javaScript:app.addressbook.videoconference_actionCall' ,
'enabled' => 'javaScript:app.addressbook.videoconference_isUserOnline'
],
2020-04-28 18:35:25 +02:00
'invite' => [
2020-04-29 10:34:18 +02:00
'caption' => lang ( 'Invite to current call' ),
2020-04-28 18:35:25 +02:00
'icon' => 'status/videoconference_join' ,
'allowOnMultiple' => true ,
'onExecute' => 'javaScript:app.addressbook.videoconference_actionCall' ,
'enabled' => 'javaScript:app.addressbook.videoconference_isThereAnyCall'
],
2020-04-02 17:48:07 +02:00
'schedule_call' => [
2020-04-09 10:50:54 +02:00
'caption' => lang ( 'Schedule a video conference' ),
2020-06-08 11:48:42 +02:00
'icon' => 'calendar/navbar' ,
2020-04-02 17:48:07 +02:00
'allowOnMultiple' => true ,
2020-04-03 13:01:00 +02:00
'onExecute' => 'javaScript:app.addressbook.add_cal' ,
2020-04-02 17:48:07 +02:00
]
]
];
2018-08-08 16:06:17 +02:00
}
2011-04-17 16:10:05 +02:00
if ( $GLOBALS [ 'egw_info' ][ 'user' ][ 'apps' ][ 'infolog' ])
{
$actions [ 'infolog_app' ] = array (
'caption' => 'InfoLog' ,
'icon' => 'infolog/navbar' ,
'group' => $group ,
'children' => array (
'infolog' => array (
'caption' => lang ( 'View linked InfoLog entries' ),
'icon' => 'infolog/navbar' ,
2014-03-18 20:20:29 +01:00
'onExecute' => 'javaScript:app.addressbook.view_infolog' ,
2017-12-19 18:13:33 +01:00
'disableClass' => 'contact_duplicate' ,
2014-03-18 20:20:29 +01:00
'allowOnMultiple' => true ,
2015-03-12 00:15:50 +01:00
'hideOnDisabled' => true ,
2011-04-17 16:10:05 +02:00
),
'infolog_add' => array (
'caption' => 'Add a new Infolog' ,
'icon' => 'new' ,
2011-04-26 18:22:10 +02:00
'url' => 'menuaction=infolog.infolog_ui.edit&type=task&action=addressbook&action_id=$id' ,
2016-04-29 12:41:53 +02:00
'popup' => Link :: get_registry ( 'infolog' , 'add_popup' ),
2013-09-20 12:50:48 +02:00
'onExecute' => 'javaScript:app.addressbook.add_task' , // call server for org-view only
2011-04-17 16:10:05 +02:00
),
2016-03-09 13:31:55 +01:00
),
'hideOnMobile' => true
2011-04-17 16:10:05 +02:00
);
}
if ( $GLOBALS [ 'egw_info' ][ 'user' ][ 'apps' ][ 'calendar' ])
{
$actions [ 'calendar' ] = array (
'icon' => 'calendar/navbar' ,
2012-01-05 05:10:54 +01:00
'caption' => 'Calendar' ,
2011-04-17 16:10:05 +02:00
'group' => $group ,
2017-03-13 19:11:37 +01:00
'enableClass' => 'contact_contact' ,
2012-01-05 05:10:54 +01:00
'children' => array (
'calendar_view' => array (
'caption' => 'Show' ,
'icon' => 'view' ,
2015-03-17 20:14:00 +01:00
'onExecute' => 'javaScript:app.addressbook.view_calendar' ,
2015-03-12 00:15:50 +01:00
'targetapp' => 'calendar' , // open in calendar tab,
'hideOnDisabled' => true ,
2012-01-05 05:10:54 +01:00
),
'calendar_add' => array (
'caption' => 'Add appointment' ,
'icon' => 'new' ,
2016-04-29 12:41:53 +02:00
'popup' => Link :: get_registry ( 'calendar' , 'add_popup' ),
2015-03-17 20:14:00 +01:00
'onExecute' => 'javaScript:app.addressbook.add_cal' ,
2012-01-05 05:10:54 +01:00
),
),
2016-03-09 13:31:55 +01:00
'hideOnMobile' => true
2011-04-17 16:10:05 +02:00
);
}
2013-12-19 15:14:50 +01:00
//Send to email
$actions [ 'email' ] = array (
'caption' => 'Email' ,
'icon' => 'mail/navbar' ,
2017-03-13 19:11:37 +01:00
'enableClass' => 'contact_contact' ,
2015-03-12 00:15:50 +01:00
'hideOnDisabled' => true ,
2013-12-19 15:14:50 +01:00
'group' => $group ,
'children' => array (
2014-01-13 18:40:36 +01:00
'add_to_to' => array (
2014-01-15 14:01:31 +01:00
'caption' => lang ( 'Add to To' ),
2014-01-13 18:40:36 +01:00
'no_lang' => true ,
'onExecute' => 'javaScript:app.addressbook.addEmail' ,
),
2014-01-06 11:12:51 +01:00
'add_to_cc' => array (
2014-01-15 14:01:31 +01:00
'caption' => lang ( 'Add to Cc' ),
2014-01-06 11:12:51 +01:00
'no_lang' => true ,
2014-01-13 18:40:36 +01:00
'onExecute' => 'javaScript:app.addressbook.addEmail' ,
2014-01-06 11:12:51 +01:00
),
'add_to_bcc' => array (
2014-01-15 14:01:31 +01:00
'caption' => lang ( 'Add to BCc' ),
2014-01-06 11:12:51 +01:00
'no_lang' => true ,
2014-01-13 18:40:36 +01:00
'onExecute' => 'javaScript:app.addressbook.addEmail' ,
2014-01-06 11:12:51 +01:00
),
2013-12-19 15:14:50 +01:00
'email_business' => array (
2014-01-15 14:01:31 +01:00
'caption' => lang ( 'Business email' ),
2013-12-19 15:14:50 +01:00
'no_lang' => true ,
2014-01-13 18:40:36 +01:00
'checkbox' => true ,
'group' => $group ,
2014-01-15 12:22:37 +01:00
'onExecute' => 'javaScript:app.addressbook.mailCheckbox' ,
'checked' => $this -> prefs [ 'preferredMail' ][ 'business' ],
2013-12-19 15:14:50 +01:00
),
'email_home' => array (
2014-01-15 14:01:31 +01:00
'caption' => lang ( 'Home email' ),
2013-12-19 15:14:50 +01:00
'no_lang' => true ,
2014-01-13 18:40:36 +01:00
'checkbox' => true ,
'group' => $group ,
2014-01-15 12:22:37 +01:00
'onExecute' => 'javaScript:app.addressbook.mailCheckbox' ,
'checked' => $this -> prefs [ 'preferredMail' ][ 'private' ],
2013-12-19 15:14:50 +01:00
),
),
2011-04-17 16:10:05 +02:00
2013-12-19 15:14:50 +01:00
);
2014-01-15 12:22:37 +01:00
if ( ! $this -> prefs [ 'preferredMail' ])
$actions [ 'email' ][ 'children' ][ 'email_business' ][ 'checked' ] = true ;
2013-12-19 16:53:26 +01:00
if ( $GLOBALS [ 'egw_info' ][ 'user' ][ 'apps' ][ 'filemanager' ])
{
$actions [ 'filemanager' ] = array (
'icon' => 'filemanager/navbar' ,
'caption' => 'Filemanager' ,
2014-01-16 18:23:39 +01:00
'url' => 'menuaction=filemanager.filemanager_ui.index&path=/apps/addressbook/$id&ajax=true' ,
2013-12-19 16:53:26 +01:00
'allowOnMultiple' => false ,
'group' => $group ,
2017-03-13 19:11:37 +01:00
// disable for for group-views, as it needs contact-ids
'enableClass' => 'contact_contact' ,
2016-03-09 13:31:55 +01:00
'hideOnMobile' => true
2013-12-19 16:53:26 +01:00
);
}
2020-11-09 23:56:24 +01:00
if ( $GLOBALS [ 'egw_info' ][ 'user' ][ 'apps' ][ 'kanban' ])
{
$actions [ 'kanban' ] = EGroupware\Kanban\Hooks :: get_actions ( 'addressbook' , $group );
}
2016-05-20 15:50:26 +02:00
$actions [ 'geolocation' ] = array (
'caption' => 'GeoLocation' ,
'icon' => 'map' ,
'group' => ++ $group ,
2017-03-13 19:11:37 +01:00
'enableClass' => 'contact_contact' ,
2016-05-20 15:50:26 +02:00
'children' => array (
'private' => array (
'caption' => 'Private Address' ,
'enabled' => 'javaScript:app.addressbook.geoLocation_enabled' ,
2016-05-25 12:50:18 +02:00
'onExecute' => 'javaScript:app.addressbook.geoLocationExec' ,
2016-05-20 15:50:26 +02:00
),
'business' => array (
2016-05-25 14:26:15 +02:00
'caption' => 'Business Address' ,
2016-05-20 15:50:26 +02:00
'enabled' => 'javaScript:app.addressbook.geoLocation_enabled' ,
2016-05-25 12:50:18 +02:00
'onExecute' => 'javaScript:app.addressbook.geoLocationExec' ,
2016-05-20 15:50:26 +02:00
)
)
);
2018-05-30 17:37:16 +02:00
$actions += EGroupware\Api\Link\Sharing :: get_actions ( 'addressbook' , $group );
2011-04-17 16:10:05 +02:00
// check if user is an admin or the export is not generally turned off (contact_export_limit is non-numerical, eg. no)
2016-04-29 12:41:53 +02:00
$exception = Api\Storage\Merge :: is_export_limit_excepted ();
2011-08-17 17:38:56 +02:00
if (( isset ( $GLOBALS [ 'egw_info' ][ 'user' ][ 'apps' ][ 'admin' ]) || $exception ) || ! $this -> config [ 'contact_export_limit' ] || ( int ) $this -> config [ 'contact_export_limit' ])
2011-04-17 16:10:05 +02:00
{
$actions [ 'export' ] = array (
'caption' => 'Export' ,
'icon' => 'filesave' ,
2017-03-13 19:11:37 +01:00
'enableClass' => 'contact_contact' ,
2011-04-17 16:10:05 +02:00
'group' => ++ $group ,
'children' => array (
2012-02-27 17:06:10 +01:00
'csv' => array (
'caption' => 'Export as CSV' ,
'allowOnMultiple' => true ,
2014-07-07 18:47:08 +02:00
'url' => 'menuaction=importexport.importexport_export_ui.export_dialog&appname=addressbook&plugin=addressbook_export_contacts_csv&selection=$id&select_all=$select_all' ,
2013-05-29 22:51:28 +02:00
'popup' => '850x440'
2012-02-27 17:06:10 +01:00
),
2013-10-04 14:48:11 +02:00
'vcard' => array (
'caption' => 'Export as VCard' ,
'postSubmit' => true , // download needs post submit (not Ajax) to work
2016-04-29 12:41:53 +02:00
'icon' => Vfs :: mime_icon ( 'text/vcard' ),
2013-10-04 14:48:11 +02:00
),
2011-04-17 16:10:05 +02:00
),
2016-03-09 13:31:55 +01:00
'hideOnMobile' => true
2011-04-17 16:10:05 +02:00
);
}
2016-04-06 11:49:50 +02:00
$actions [ 'documents' ] = Api\Contacts\Merge :: document_action (
2011-04-25 13:30:37 +02:00
$this -> prefs [ 'document_dir' ], $group , 'Insert in document' , 'document_' ,
2011-06-16 13:36:15 +02:00
$this -> prefs [ 'default_document' ], $this -> config [ 'contact_export_limit' ]
2011-04-25 13:30:37 +02:00
);
2018-11-27 15:22:50 +01:00
if ( $GLOBALS [ 'egw_info' ][ 'user' ][ 'apps' ][ 'felamimail' ] || $GLOBALS [ 'egw_info' ][ 'user' ][ 'apps' ][ 'mail' ])
2011-11-29 13:07:11 +01:00
{
$actions [ 'mail' ] = array (
'caption' => lang ( 'Mail VCard' ),
'icon' => 'filemanager/mail_post_to' ,
'group' => $group ,
2013-09-20 12:50:48 +02:00
'onExecute' => 'javaScript:app.addressbook.adb_mail_vcard' ,
2017-03-13 19:11:37 +01:00
'enableClass' => 'contact_contact' ,
2015-03-12 00:15:50 +01:00
'hideOnDisabled' => true ,
2018-11-27 15:22:50 +01:00
'hideOnMobile' => true ,
'disableIfNoEPL' => true
2011-11-29 13:07:11 +01:00
);
}
2011-04-17 16:10:05 +02:00
++ $group ;
if ( ! ( $tid_filter == 'D' && ! $GLOBALS [ 'egw_info' ][ 'user' ][ 'apps' ][ 'admin' ] && $this -> config [ 'history' ] != 'userpurge' ))
{
$actions [ 'delete' ] = array (
'caption' => 'Delete' ,
'confirm' => 'Delete this contact' ,
2011-04-17 23:25:01 +02:00
'confirm_multiple' => 'Delete these entries' ,
2011-04-17 16:10:05 +02:00
'group' => $group ,
2011-04-17 23:25:01 +02:00
'disableClass' => 'rowNoDelete' ,
2020-09-28 18:51:30 +02:00
'onExecute' => 'javaScript:app.addressbook.action' ,
2011-04-17 16:10:05 +02:00
);
}
2016-04-29 12:41:53 +02:00
if ( $this -> grants [ 0 ] & Acl :: DELETE )
2014-03-19 14:20:46 +01:00
{
$actions [ 'delete_account' ] = array (
'caption' => 'Delete' ,
'icon' => 'delete' ,
'group' => $group ,
'enableClass' => 'rowAccount' ,
'hideOnDisabled' => true ,
'popup' => '400x200' ,
'url' => 'menuaction=admin.admin_account.delete&contact_id=$id' ,
);
$actions [ 'delete' ][ 'hideOnDisabled' ] = true ;
}
2011-04-17 16:10:05 +02:00
if ( $tid_filter == 'D' )
{
$actions [ 'undelete' ] = array (
'caption' => 'Un-delete' ,
2012-12-31 23:05:14 +01:00
'icon' => 'revert' ,
2011-04-17 16:10:05 +02:00
'group' => $group ,
2011-04-25 16:13:40 +02:00
'disableClass' => 'rowNoEdit' ,
2011-04-17 16:10:05 +02:00
);
}
2016-05-04 21:07:54 +02:00
if ( isset ( $actions [ 'export' ][ 'children' ][ 'csv' ]) &&
( ! isset ( $GLOBALS [ 'egw_info' ][ 'user' ][ 'apps' ][ 'importexport' ]) ||
! importexport_helper_functions :: has_definitions ( 'addressbook' , 'export' )))
{
unset ( $actions [ 'export' ][ 'children' ][ 'csv' ]);
}
2016-02-02 11:26:13 +01:00
// Intercept open action in order to open entry into view mode instead of edit
2016-04-29 12:41:53 +02:00
if ( Api\Header\UserAgent :: mobile ())
2016-02-04 18:25:52 +01:00
{
$actions [ 'open' ][ 'onExecute' ] = 'javaScript:app.addressbook.viewEntry' ;
2016-05-25 16:44:23 +02:00
$actions [ 'open' ][ 'mobileViewTemplate' ] = 'view?' . filemtime ( Api\Etemplate\Widget\Template :: rel2path ( '/addressbook/templates/mobile/view.xet' ));
2016-02-05 10:38:21 +01:00
$actions [ 'view' ][ 'default' ] = false ;
$actions [ 'open' ][ 'default' ] = true ;
2016-02-04 18:25:52 +01:00
}
2013-06-04 01:10:23 +02:00
// Allow contacts to be dragged
/*
$actions [ 'drag' ] = array (
'type' => 'drag' ,
'dragType' => 'addressbook'
);
*/
2011-04-17 16:10:05 +02:00
return $actions ;
}
2013-11-08 19:51:37 +01:00
2020-05-20 21:05:56 +02:00
protected function change_type_actions ( $group )
{
$types = array ();
foreach ( $this -> content_types as $key => $type )
{
// Skip deleted
if ( $key == self :: DELETED_TYPE ) continue ;
$types [ $key ] = array (
'caption' => $type [ 'name' ],
);
}
return array (
'caption' => 'Type' ,
'children' => $types ,
'prefix' => 'to_type_' ,
'group' => $group ,
'disableClass' => 'rowNoEdit' ,
'hideOnDisabled' => true ,
'disabled' => ( count ( $types ) <= 1 ),
'hideOnMobile' => true
);
}
2013-10-22 00:18:41 +02:00
/**
2017-03-13 19:11:37 +01:00
* Get a nice name for the given grouped view ID
2013-10-22 00:18:41 +02:00
*
2017-03-13 19:11:37 +01:00
* @ param String $view_id Some kind of indicator for a specific group , either
* organisation or duplicate . It looks like key : value pairs seperated by |||.
*
* @ return Array ( ID => name ), where ID is the $view_id passed in
2013-10-22 00:18:41 +02:00
*/
2017-03-13 19:11:37 +01:00
protected function _get_grouped_name ( $view_id )
2013-10-22 00:18:41 +02:00
{
2017-03-13 19:11:37 +01:00
$group_name = array ();
if ( strpos ( $view_id , '*AND*' ) !== false ) $view_id = str_replace ( '*AND*' , '&' , $view_id );
foreach ( explode ( '|||' , $view_id ) as $part )
2013-10-22 00:18:41 +02:00
{
list (, $name ) = explode ( ':' , $part , 2 );
2017-03-13 19:11:37 +01:00
if ( $name ) $group_name [] = $name ;
2013-10-22 00:18:41 +02:00
}
2017-03-13 19:11:37 +01:00
$name = implode ( ': ' , $group_name );
return $name ? array ( $view_id => $name ) : array ();
}
/**
* Unset the relevant column filters to clear a grouped view
2017-04-04 16:52:25 +02:00
*
2017-03-13 19:11:37 +01:00
* @ param Array $query
*/
protected function unset_grouped_filters ( & $query )
{
unset ( $query [ 'col_filter' ][ 'org_name' ]);
unset ( $query [ 'col_filter' ][ 'org_unit' ]);
unset ( $query [ 'col_filter' ][ 'adr_one_locality' ]);
2017-09-19 11:38:02 +02:00
foreach ( array_keys ( static :: $duplicate_fields ) as $field )
2017-03-13 19:11:37 +01:00
{
unset ( $query [ 'col_filter' ][ $field ]);
}
}
/**
* Adjust the query as needed and get the rows for the grouped views ( organisation
* or duplicate contacts )
*
* @ param Array $query Nextmatch query
* @ return array rows found
*/
protected function get_grouped_rows ( & $query )
{
// Query doesn't like empties
unset ( $query [ 'col_filter' ][ 'parent_id' ]);
if ( $query [ 'actions' ] && $query [ 'actions' ][ 'open' ])
{
// Just switched from contact view, update actions
$query [ 'actions' ] = $this -> get_actions ( $query [ 'col_filter' ][ 'tid' ]);
}
2020-08-07 21:18:41 +02:00
$template = $query [ 'grouped_view' ] == 'duplicates' ? 'addressbook.index.duplicate_rows' : 'addressbook.index.org_rows' ;
2017-03-13 19:11:37 +01:00
if ( $query [ 'advanced_search' ])
{
$query [ 'op' ] = $query [ 'advanced_search' ][ 'operator' ];
unset ( $query [ 'advanced_search' ][ 'operator' ]);
$query [ 'wildcard' ] = $query [ 'advanced_search' ][ 'meth_select' ];
unset ( $query [ 'advanced_search' ][ 'meth_select' ]);
$original_search = $query [ 'search' ];
$query [ 'search' ] = $query [ 'advanced_search' ];
}
2020-08-07 21:18:41 +02:00
switch ( $template )
2017-03-13 19:11:37 +01:00
{
case 'addressbook.index.org_rows' :
if ( $query [ 'order' ] != 'org_name' )
{
$query [ 'sort' ] = 'ASC' ;
$query [ 'order' ] = 'org_name' ;
}
$query [ 'org_view' ] = $query [ 'grouped_view' ];
2018-07-19 22:54:05 +02:00
// switch the distribution list selection off for ldap
if ( $this -> contact_repository != 'sql' )
{
$query [ 'no_filter2' ] = true ;
unset ( $query [ 'col_filter' ][ 'list' ]); // does not work here
}
else
{
$rows = parent :: organisations ( $query );
}
2017-03-13 19:11:37 +01:00
break ;
case 'addressbook.index.duplicate_rows' :
2018-07-19 22:54:05 +02:00
$query [ 'no_filter2' ] = true ; // switch the distribution list selection off
unset ( $query [ 'col_filter' ][ 'list' ]); // does not work for duplicates
2017-03-13 19:11:37 +01:00
$rows = parent :: duplicates ( $query );
break ;
}
if ( $query [ 'advanced_search' ])
{
$query [ 'search' ] = $original_search ;
unset ( $query [ 'wildcard' ]);
unset ( $query [ 'op' ]);
}
$GLOBALS [ 'egw_info' ][ 'flags' ][ 'params' ][ 'manual' ] = array ( 'page' => 'ManualAddressbookIndexOrga' );
return $rows ;
2013-10-22 00:18:41 +02:00
}
2013-11-08 19:51:37 +01:00
2014-03-18 20:20:29 +01:00
/**
* Return the contacts in an organisation via AJAX
*
* @ param string | string [] $org Organisation ID
2016-04-29 12:41:53 +02:00
* @ param mixed $_query Query filters ( category , etc ) to use , or null to use session
2014-03-18 20:20:29 +01:00
* @ return array
*/
2016-04-29 12:41:53 +02:00
public function ajax_organisation_contacts ( $org , $_query = null )
2014-03-18 20:20:29 +01:00
{
$org_contacts = array ();
2016-04-29 12:41:53 +02:00
$query = ! $_query ? Api\Cache :: getSession ( 'addressbook' , 'index' ) : $_query ;
2014-03-18 20:20:29 +01:00
$query [ 'num_rows' ] = - 1 ; // all
if ( ! is_array ( $query [ 'col_filter' ])) $query [ 'col_filter' ] = array ();
2014-03-19 14:20:46 +01:00
2014-03-18 20:20:29 +01:00
if ( ! is_array ( $org )) $org = array ( $org );
foreach ( $org as $org_name )
{
2017-03-13 19:11:37 +01:00
$query [ 'grouped_view' ] = $org_name ;
2014-03-18 20:20:29 +01:00
$checked = array ();
2016-04-29 12:41:53 +02:00
$readonlys = null ;
$this -> get_rows ( $query , $checked , $readonlys , true ); // true = only return the id's
2014-03-18 20:20:29 +01:00
if ( $checked [ 0 ])
{
$org_contacts = array_merge ( $org_contacts , $checked );
}
}
2016-04-29 12:41:53 +02:00
Api\Json\Response :: get () -> data ( array_unique ( $org_contacts ));
2014-03-18 20:20:29 +01:00
}
2006-10-23 13:48:56 +02:00
/**
* Show the infologs of an whole organisation
*
* @ param string $org
*/
function infolog_org_view ( $org )
{
2016-04-29 12:41:53 +02:00
$query = Api\Cache :: getSession ( 'addressbook' , 'index' );
2006-10-23 13:48:56 +02:00
$query [ 'num_rows' ] = - 1 ; // all
2017-03-13 19:11:37 +01:00
$query [ 'grouped_view' ] = $org ;
2007-05-22 20:06:38 +02:00
$query [ 'searchletter' ] = '' ;
2016-04-29 12:41:53 +02:00
$checked = $readonlys = null ;
2006-10-23 13:48:56 +02:00
$this -> get_rows ( $query , $checked , $readonlys , true ); // true = only return the id's
if ( count ( $checked ) > 1 ) // use a nicely formatted org-name as title in infolog
{
$parts = array ();
2009-07-20 14:11:05 +02:00
if ( strpos ( $org , '*AND*' ) !== false ) $org = str_replace ( '*AND*' , '&' , $org );
2006-10-23 13:48:56 +02:00
foreach ( explode ( '|||' , $org ) as $part )
{
list (, $part ) = explode ( ':' , $part , 2 );
if ( $part ) $parts [] = $part ;
}
$org = implode ( ', ' , $parts );
}
else
{
$org = '' ; // use infolog default of link-title
}
2016-04-29 12:41:53 +02:00
Egw :: redirect_link ( '/index.php' , array (
2008-10-07 15:04:49 +02:00
'menuaction' => 'infolog.infolog_ui.index' ,
2006-10-23 13:48:56 +02:00
'action' => 'addressbook' ,
'action_id' => implode ( ',' , $checked ),
'action_title' => $org ,
2014-03-13 20:04:47 +01:00
), 'infolog' );
2006-10-23 13:48:56 +02:00
}
2008-04-18 08:10:31 +02:00
2014-10-27 19:43:03 +01:00
/**
2014-10-28 20:50:19 +01:00
* Create or rename an existing email list
2014-10-27 19:43:03 +01:00
*
2014-10-28 20:50:19 +01:00
* @ param int $list_id ID of existing list , or 0 for a new one
* @ param string $new_name List name
2016-04-29 12:41:53 +02:00
* @ param int $_owner List owner , or empty for current user
2016-12-20 16:47:33 +01:00
* @ param string [] [ $contacts ] List of contacts to add to the array
2014-10-27 19:43:03 +01:00
* @ return boolean | string
*/
2016-12-20 16:47:33 +01:00
function ajax_set_list ( $list_id , $new_name , $_owner = false , $contacts = array ())
2014-10-27 19:43:03 +01:00
{
2014-10-28 20:50:19 +01:00
// Set owner to current user, if not set
2016-04-29 12:41:53 +02:00
$owner = $_owner ? $_owner : $GLOBALS [ 'egw_info' ][ 'user' ][ 'account_id' ];
2016-09-15 17:37:04 +02:00
// if admin forced or set default for add_default pref
// consider default_addressbook as owner which already
// covered all cases in contacts class.
if ( $owner == ( int ) $GLOBALS [ 'egw' ] -> preferences -> default [ 'addressbook' ][ 'add_default' ] ||
$owner == ( int ) $GLOBALS [ 'egw' ] -> preferences -> forced [ 'addressbook' ][ 'add_default' ])
{
$owner = $this -> default_addressbook ;
}
2014-10-27 19:43:03 +01:00
// Check for valid list & permissions
2014-10-28 20:50:19 +01:00
if ( ! ( int ) $list_id && ! $this -> check_list ( null , EGW_ACL_ADD | EGW_ACL_EDIT , $owner ))
2014-10-27 19:43:03 +01:00
{
2016-04-29 12:41:53 +02:00
Api\Json\Response :: get () -> apply ( 'egw.message' , array ( lang ( 'List creation failed, no rights!' ), 'error' ));
2014-10-27 19:43:03 +01:00
return ;
}
2016-04-29 12:41:53 +02:00
if (( int ) $list_id && ! $this -> check_list (( int ) $list_id , Acl :: EDIT , $owner ))
2014-10-27 19:43:03 +01:00
{
2016-04-29 12:41:53 +02:00
Api\Json\Response :: get () -> apply ( 'egw.message' , array ( lang ( 'Insufficent rights to edit this list!' ), 'error' ));
2014-10-27 19:43:03 +01:00
return ;
}
2014-10-28 20:50:19 +01:00
$list = array ( 'list_owner' => $owner );
2014-10-27 19:43:03 +01:00
// Rename
2014-10-28 20:50:19 +01:00
if ( $list_id )
{
$list = $this -> read_list (( int ) $list_id );
}
2014-10-27 19:43:03 +01:00
$list [ 'list_name' ] = $new_name ;
2014-10-28 20:50:19 +01:00
$new_id = $this -> add_list ( array ( 'list_id' => ( int ) $list_id ), $list [ 'list_owner' ], array (), $list );
2015-02-04 11:30:59 +01:00
2016-12-20 16:47:33 +01:00
if ( $contacts )
{
$this -> add2list ( $contacts , $new_id );
}
2016-04-29 12:41:53 +02:00
Api\Json\Response :: get () -> apply ( 'egw.message' , array (
2014-10-28 20:50:19 +01:00
$new_id == $list_id ? lang ( 'Distribution list renamed' ) : lang ( 'List created' ),
'success'
));
2014-10-27 19:43:03 +01:00
// Success, just update selectbox to new value
2016-04-29 12:41:53 +02:00
Api\Json\Response :: get () -> data ( $new_id == $list_id ? " true " : $new_id );
2014-10-27 19:43:03 +01:00
}
2016-05-25 12:50:18 +02:00
/**
* Ajax function to get contact data out of provided account_id
*
2016-06-01 09:55:57 +02:00
* @ param string $account_id
2016-05-25 12:50:18 +02:00
*/
function ajax_get_contact ( $account_id )
{
$bo = new Api\Contacts ();
2016-06-01 09:55:57 +02:00
$contact = $bo -> read ( 'account:' . $account_id );
2016-05-25 12:50:18 +02:00
Api\Json\Response :: get () -> data ( $contact );
}
2016-06-09 23:05:25 +02:00
/**
* Disable / clear advanced search
*
* Advanced search is stored server side in session no matter what the nextmatch
* sends , so we have to clear it here .
*/
public static function ajax_clear_advanced_search ()
{
$query = Api\Cache :: getSession ( 'addressbook' , 'index' );
unset ( $query [ 'advanced_search' ]);
Api\Cache :: setSession ( 'addressbook' , 'index' , $query );
Api\Cache :: setSession ( 'addressbook' , 'advanced_search' , false );
}
2016-06-15 12:09:24 +02:00
2020-09-28 18:51:30 +02:00
/**
* Apply an action to multiple events , but called via AJAX instead of submit
*
* @ param string $action
* @ param string [] $selected
* @ param bool $all_selected All entries are selected , not just what ' s in $selected
* @ param bool $skip_notification
*/
public function ajax_action ( $action , $selected , $all_selected , $skip_notification = false )
{
$success = 0 ;
$failed = 0 ;
$action_msg = '' ;
$session_name = 'index' ;
if ( $this -> action ( $action , $selected , $all_selected , $success , $failed , $action_msg , $session_name , $msg , $skip_notification ))
{
$msg = lang ( '%1 event(s) %2' , $success , $action_msg );
}
elseif ( is_null ( $msg ))
{
$msg .= lang ( '%1 event(s) %2, %3 failed because of insufficient rights !!!' , $success , $action_msg , $failed );
}
Api\Json\Response :: get () -> message ( $msg );
}
2006-04-23 16:40:31 +02:00
/**
* apply an action to multiple contacts
*
* @ param string / int $action 'delete' , 'vcard' , 'csv' or nummerical account_id to move contacts to that addessbook
* @ param array $checked contact id ' s to use if ! $use_all
* @ param boolean $use_all if true use all contacts of the current selection ( in the session )
* @ param int & $success number of succeded actions
* @ param int & $failed number of failed actions ( not enought permissions )
* @ param string & $action_msg translated verb for the actions , to be used in a message like % 1 contacts 'deleted'
2018-11-20 18:27:43 +01:00
* @ param string / array $session_name 'index' or array with session - data depending if we are in the main list or the popup
2020-10-26 10:44:40 +01:00
* @ param ? string & $error_msg on return optional error - message
2006-04-23 16:40:31 +02:00
* @ return boolean true if all actions succeded , false otherwise
*/
2020-10-26 10:44:40 +01:00
function action ( $action , $checked , $use_all , & $success , & $failed , & $action_msg , $session_name , & $msg , $checkboxes = NULL , & $error_msg = null )
2006-04-23 16:40:31 +02:00
{
2008-04-18 08:10:31 +02:00
//echo "<p>uicontacts::action('$action',".print_r($checked,true).','.(int)$use_all.",...)</p>\n";
2006-04-23 16:40:31 +02:00
$success = $failed = 0 ;
2020-10-26 10:44:40 +01:00
$error_msg = null ;
2020-10-19 18:34:11 +02:00
if ( $use_all || in_array ( $action , array ( 'remove_from_list' , 'delete_list' , 'unshare' )))
2006-04-23 16:40:31 +02:00
{
// get the whole selection
2016-04-29 12:41:53 +02:00
$query = is_array ( $session_name ) ? $session_name : Api\Cache :: getSession ( 'addressbook' , $session_name );
2008-04-18 08:10:31 +02:00
2007-03-13 14:38:15 +01:00
if ( $use_all )
{
2007-05-22 10:02:06 +02:00
@ set_time_limit ( 0 ); // switch off the execution time limit, as it's for big selections to small
2007-03-13 14:38:15 +01:00
$query [ 'num_rows' ] = - 1 ; // all
2016-04-29 12:41:53 +02:00
$readonlys = null ;
2007-03-13 14:38:15 +01:00
$this -> get_rows ( $query , $checked , $readonlys , true ); // true = only return the id's
}
2006-04-23 16:40:31 +02:00
}
2006-04-30 11:34:24 +02:00
// replace org_name:* id's with all id's of that org
2017-06-12 17:59:11 +02:00
$grouped_contacts = $this -> find_grouped_ids ( $action , $checked , $use_all , $success , $failed , $action_msg , $session_name , $msg );
2017-03-13 19:11:37 +01:00
if ( $grouped_contacts ) $checked = array_unique ( $checked ? array_merge ( $checked , $grouped_contacts ) : $grouped_contacts );
2006-12-13 14:39:00 +01:00
//_debug_array($checked); exit;
2008-04-18 08:10:31 +02:00
2008-02-21 12:54:22 +01:00
if ( substr ( $action , 0 , 8 ) == 'move_to_' )
{
2008-08-13 08:18:03 +02:00
$action = ( int ) substr ( $action , 8 ) . ( substr ( $action , - 1 ) == 'p' ? 'p' : '' );
2008-02-21 12:54:22 +01:00
}
2011-04-25 16:13:40 +02:00
elseif ( substr ( $action , 0 , 8 ) == 'to_list_' )
2007-03-13 14:38:15 +01:00
{
$to_list = ( int ) substr ( $action , 8 );
$action = 'to_list' ;
}
2020-05-20 21:05:56 +02:00
elseif ( substr ( $action , 0 , 8 ) == 'to_type_' )
{
$to_type = substr ( $action , 8 );
$action = 'to_type' ;
}
2011-04-25 16:13:40 +02:00
elseif ( substr ( $action , 0 , 9 ) == 'document_' )
2007-06-17 15:55:43 +02:00
{
2007-06-19 19:06:32 +02:00
$document = substr ( $action , 9 );
2007-06-17 15:55:43 +02:00
$action = 'document' ;
}
2011-04-25 16:13:40 +02:00
elseif ( substr ( $action , 0 , 4 ) == 'cat_' ) // cat_add_123 or cat_del_456
{
$cat_id = ( int ) substr ( $action , 8 );
$action = substr ( $action , 0 , 7 );
}
2020-10-16 21:34:26 +02:00
elseif ( substr ( $action , 0 , 12 ) === 'shared_with_' )
{
$shared_with = substr ( $action , 12 );
$action = 'shared_with' ;
}
2007-05-22 10:02:06 +02:00
// Security: stop non-admins to export more then the configured number of contacts
2016-04-29 12:41:53 +02:00
if ( in_array ( $action , array ( 'csv' , 'vcard' )) && $this -> config [ 'contact_export_limit' ] && ! Api\Storage\Merge :: is_export_limit_excepted () &&
2008-10-16 13:17:49 +02:00
( ! is_numeric ( $this -> config [ 'contact_export_limit' ]) || count ( $checked ) > $this -> config [ 'contact_export_limit' ]))
2007-05-22 10:02:06 +02:00
{
$action_msg = lang ( 'exported' );
$failed = count ( $checked );
return false ;
}
2006-04-26 23:23:38 +02:00
switch ( $action )
{
2006-07-09 01:02:30 +02:00
case 'vcard' :
$action_msg = lang ( 'exported' );
2012-02-10 21:32:45 +01:00
$vcard = new addressbook_vcal ( 'addressbook' , 'text/vcard' );
$vcard -> export ( $checked );
2006-07-09 01:02:30 +02:00
// does not return!
$Ok = false ;
2008-04-18 08:10:31 +02:00
break ;
2006-12-19 12:25:44 +01:00
case 'merge' :
2016-04-29 12:41:53 +02:00
$error_msg = null ;
2006-12-19 12:25:44 +01:00
$success = $this -> merge ( $checked , $error_msg );
$failed = count ( $checked ) - ( int ) $success ;
$action_msg = lang ( 'merged' );
$checked = array (); // to not start the single actions
break ;
2007-03-13 14:38:15 +01:00
case 'delete_list' :
if ( ! $query [ 'filter2' ])
{
$msg = lang ( 'You need to select a distribution list' );
}
elseif ( $this -> delete_list ( $query [ 'filter2' ]) === false )
{
$msg = lang ( 'Insufficent rights to delete this list!' );
}
else
{
$msg = lang ( 'Distribution list deleted' );
unset ( $query [ 'filter2' ]);
2016-04-29 12:41:53 +02:00
Api\Cache :: setSession ( 'addressbook' , $session_name , $query );
2007-03-13 14:38:15 +01:00
}
2007-06-17 15:55:43 +02:00
return false ;
2015-02-04 11:30:59 +01:00
2007-06-17 15:55:43 +02:00
case 'document' :
2011-06-14 12:48:15 +02:00
if ( ! $document ) $document = $this -> prefs [ 'default_document' ];
2016-04-06 11:49:50 +02:00
$document_merge = new Api\Contacts\Merge ();
2011-06-14 12:48:15 +02:00
$msg = $document_merge -> download ( $document , $checked , '' , $this -> prefs [ 'document_dir' ]);
2011-06-16 13:36:15 +02:00
$failed = count ( $checked );
2007-06-17 15:55:43 +02:00
return false ;
2008-04-26 10:47:26 +02:00
2008-04-23 10:22:22 +02:00
case 'infolog_add' :
2016-04-29 12:41:53 +02:00
Framework :: popup ( Egw :: link ( '/index.php' , array (
2011-04-26 18:22:10 +02:00
'menuaction' => 'infolog.infolog_ui.edit' ,
'type' => 'task' ,
'action' => 'addressbook' ,
'action_id' => implode ( ',' , $checked ),
2016-04-29 12:41:53 +02:00
)), '_blank' , Link :: get_registry ( 'infolog' , 'add_popup' ));
2011-04-26 18:22:10 +02:00
$msg = '' ; // no message, as we send none in javascript too and users sees opening popup
return false ;
2012-01-05 05:10:54 +01:00
case 'calendar_add' : // add appointment for org-views, other views are handled directly in javascript
2016-04-29 12:41:53 +02:00
Framework :: popup ( Egw :: link ( '/index.php' , array (
2011-04-26 18:22:10 +02:00
'menuaction' => 'calendar.calendar_uiforms.edit' ,
'participants' => 'c' . implode ( ',c' , $checked ),
2016-04-29 12:41:53 +02:00
)), '_blank' , Link :: get_registry ( 'calendar' , 'add_popup' ));
2011-04-26 18:22:10 +02:00
$msg = '' ; // no message, as we send none in javascript too and users sees opening popup
2008-04-26 10:47:26 +02:00
return false ;
2012-01-05 05:10:54 +01:00
2015-03-17 20:14:00 +01:00
case 'calendar_view' : // show calendar for org-views, although all views are handled directly in javascript
2016-04-29 12:41:53 +02:00
Egw :: redirect_link ( '/index.php' , array (
2012-01-05 05:10:54 +01:00
'menuaction' => 'calendar.calendar_uiviews.index' ,
'owner' => 'c' . implode ( ',c' , $checked ),
));
2011-04-25 16:13:40 +02:00
}
2011-08-29 14:20:16 +02:00
foreach ( $checked as $id )
2011-04-25 16:13:40 +02:00
{
switch ( $action )
{
case 'cat_add' :
case 'cat_del' :
2016-04-29 12:41:53 +02:00
if (( $Ok = !! ( $contact = $this -> read ( $id )) && $this -> check_perms ( Acl :: EDIT , $contact )))
2008-03-10 17:33:17 +01:00
{
2011-04-25 16:13:40 +02:00
$action_msg = $action == 'cat_add' ? lang ( 'categorie added' ) : lang ( 'categorie delete' );
2016-04-29 12:41:53 +02:00
$cat_ids = $contact [ 'cat_id' ] ? explode ( ',' , $contact [ 'cat_id' ]) : array (); //existing Api\Categories
2011-04-25 16:13:40 +02:00
if ( $action == 'cat_add' )
2008-03-10 17:33:17 +01:00
{
2011-04-25 16:13:40 +02:00
$cat_ids [] = $cat_id ;
$cat_ids = array_unique ( $cat_ids );
2008-03-10 17:33:17 +01:00
}
2011-04-25 16:13:40 +02:00
elseif ((( $key = array_search ( $cat_id , $cat_ids ))) !== false )
2008-03-10 17:33:17 +01:00
{
2011-04-25 16:13:40 +02:00
unset ( $cat_ids [ $key ]);
2008-03-10 17:33:17 +01:00
}
2016-04-29 12:41:53 +02:00
$ids = $cat_ids ? implode ( ',' , $cat_ids ) : null ;
if ( $ids !== $contact [ 'cat_id' ])
2008-03-10 17:33:17 +01:00
{
2016-04-29 12:41:53 +02:00
$contact [ 'cat_id' ] = $ids ;
2011-04-25 16:13:40 +02:00
$Ok = $this -> save ( $contact );
2008-03-10 17:33:17 +01:00
}
}
2011-04-25 16:13:40 +02:00
break ;
2006-04-23 16:40:31 +02:00
case 'delete' :
$action_msg = lang ( 'deleted' );
2016-04-29 12:41:53 +02:00
if (( $Ok = !! ( $contact = $this -> read ( $id )) && $this -> check_perms ( Acl :: DELETE , $contact )))
2006-04-23 16:40:31 +02:00
{
2012-03-07 13:05:02 +01:00
if ( $contact [ 'owner' ] || // regular contact or
2015-07-23 19:40:48 +02:00
empty ( $contact [ 'account_id' ]) || // accounts without account_id
2012-03-07 13:05:02 +01:00
// already deleted account (should no longer happen, but needed to allow for cleanup)
2016-03-06 14:45:15 +01:00
$contact [ 'tid' ] == self :: DELETED_TYPE )
2006-04-23 16:40:31 +02:00
{
2016-03-06 14:45:15 +01:00
$Ok = $this -> delete ( $id , $contact [ 'tid' ] != self :: DELETED_TYPE && $contact [ 'account_id' ]);
2006-04-23 16:40:31 +02:00
}
2006-06-14 18:53:14 +02:00
// delete single account --> redirect to admin
2008-04-18 08:10:31 +02:00
elseif ( count ( $checked ) == 1 && $contact [ 'account_id' ])
2006-04-23 16:40:31 +02:00
{
2016-04-29 12:41:53 +02:00
Egw :: redirect_link ( '/index.php' , array (
2014-03-19 14:20:46 +01:00
'menuaction' => 'admin.admin_account.delete' ,
2006-04-23 16:40:31 +02:00
'account_id' => $contact [ 'account_id' ],
));
// this does NOT return!
}
2020-11-20 15:48:22 +01:00
else // no mass delete of accounts
2006-04-23 16:40:31 +02:00
{
$Ok = false ;
}
}
break ;
2011-04-25 16:13:40 +02:00
2010-09-23 23:55:06 +02:00
case 'undelete' :
$action_msg = lang ( 'recovered' );
2016-04-29 12:41:53 +02:00
if (( $contact = $this -> read ( $id )))
2010-09-23 23:55:06 +02:00
{
$contact [ 'tid' ] = 'n' ;
$Ok = $this -> save ( $contact );
}
break ;
2008-04-18 08:10:31 +02:00
2006-10-22 13:40:43 +02:00
case 'email' :
case 'email_home' :
2016-04-29 12:41:53 +02:00
/* this cant work anymore , as Framework :: set_onload does not longer exist
$action_fallback = $action == 'email' ? 'email_home' : 'email' ;
2007-11-06 16:45:40 +01:00
$action_msg = lang ( 'added' );
2016-04-29 12:41:53 +02:00
if (( $contact = $this -> read ( $id )))
2006-10-22 13:40:43 +02:00
{
2007-11-06 16:45:40 +01:00
if ( strpos ( $contact [ $action ], '@' ) !== false )
{
$email = $contact [ $action ];
}
elseif ( strpos ( $contact [ $action_fallback ], '@' ) !== false )
{
$email = $contact [ $action_fallback ];
}
else
{
$Ok = $email = false ;
}
if ( $email )
{
2010-12-06 16:02:56 +01:00
$contact [ 'n_fn' ] = str_replace ( array ( ',' , '@' ), ' ' , $contact [ 'n_fn' ]);
2016-04-29 12:41:53 +02:00
Framework :: set_onload ( " addEmail(' " . addslashes (
2010-11-25 14:38:38 +01:00
$contact [ 'n_fn' ] ? $contact [ 'n_fn' ] . ' <' . trim ( $email ) . '>' : trim ( $email )) . " '); " );
//error_log(__METHOD__.__LINE__."addEmail('".addslashes(
// $contact['n_fn'] ? $contact['n_fn'].' <'.trim($email).'>' : trim($email))."');");
2007-11-06 16:45:40 +01:00
$Ok = true ;
}
2016-04-29 12:41:53 +02:00
} */
2006-10-22 13:40:43 +02:00
break ;
2008-04-18 08:10:31 +02:00
2007-03-13 14:38:15 +01:00
case 'remove_from_list' :
$action_msg = lang ( 'removed from distribution list' );
if ( ! $query [ 'filter2' ])
{
$msg = lang ( 'You need to select a distribution list' );
return false ;
}
else
{
$Ok = $this -> remove_from_list ( $id , $query [ 'filter2' ]) !== false ;
}
break ;
2008-04-18 08:10:31 +02:00
2007-03-13 14:38:15 +01:00
case 'to_list' :
$action_msg = lang ( 'added to distribution list' );
if ( ! $to_list )
{
$msg = lang ( 'You need to select a distribution list' );
return false ;
}
else
{
$Ok = $this -> add2list ( $id , $to_list ) !== false ;
}
break ;
2020-05-20 21:05:56 +02:00
case 'to_type' :
$action_msg = lang ( 'changed type to %1' , lang ( $this -> content_types [ $to_type ][ 'name' ]));
if (( $Ok = !! ( $contact = $this -> read ( $id )) && $this -> check_perms ( Acl :: EDIT , $contact )))
{
2020-11-20 15:48:22 +01:00
if ( ! $contact [ 'owner' ]) // no change of accounts
2020-05-20 21:05:56 +02:00
{
$Ok = false ;
}
else
{
$contact [ 'tid' ] = $to_type ;
$Ok = $this -> save ( $contact );
}
}
break ;
2020-10-16 21:34:26 +02:00
case 'shared_with' :
2020-10-19 18:34:11 +02:00
// as "unshare" is in "shared_with" submenu/children it uses "shared_with_unshare"
if ( $shared_with === 'unshare' )
{
$action_msg = lang ( 'unshared' );
if (( $Ok = !! ( $contact = $this -> read ( $id ))))
{
$need_save = false ;
foreach ( $contact [ 'shared' ] as $key => $shared )
{
// only unshare contacts shared by current user
2020-11-02 12:55:38 +01:00
if (( $shared [ 'shared_by' ] == $this -> user ||
$this -> check_perms ( ACL :: EDIT , $contact )) &&
2020-10-19 18:34:11 +02:00
// only unshare from given addressbook, or all
( empty ( $query [ 'filter' ]) || $shared [ 'shared_with' ] == ( int ) $query [ 'filter' ]))
{
$need_save = true ;
unset ( $contact [ 'shared' ][ $key ]);
}
}
// we might need to ignore acl, as we are allowed to share with just read-rights
// setting user and update-time is explicitly desired for sync(-collection)!
$Ok = ! $need_save || $this -> save ( $contact , true );
}
break ;
}
2020-11-20 15:48:22 +01:00
$action_msg = lang ( 'shared into addressbook %1' , Api\Accounts :: username ( $shared_with ));
2020-10-16 21:34:26 +02:00
if (( $Ok = !! ( $contact = $this -> read ( $id ))))
{
$new_shared_with = [[
'shared_with' => $shared_with ,
'shared_by' => $this -> user ,
'shared_at' => new Api\DateTime ( 'now' ),
// only allow to share writable, if user has edit-rights!
'shared_writable' => ( int )( $checkboxes [ 'writable' ] && $this -> check_perms ( Acl :: EDIT , $contact )),
2020-10-26 10:44:40 +01:00
'contact_id' => $id ,
'contact' => $contact ,
2020-10-16 21:34:26 +02:00
]];
2020-10-26 10:44:40 +01:00
if ( $this -> check_shared_with ( $new_shared_with , $error_msg )) // returns [] if OK
2020-10-16 21:34:26 +02:00
{
$Ok = false ;
}
else
{
$contact [ 'shared' ][] = $new_shared_with [ 0 ];
// we might need to ignore acl, as we are allowed to share with just read-rights
// setting user and update-time is explicitly desired for sync(-collection)!
$Ok = $this -> save ( $contact , true );
}
}
break ;
2006-04-23 16:40:31 +02:00
default : // move to an other addressbook
2016-04-29 12:41:53 +02:00
if ( ! ( int ) $action || ! ( $this -> grants [( string ) ( int ) $action ] & Acl :: EDIT )) // might be ADD in the future
2006-04-23 16:40:31 +02:00
{
return false ;
}
2013-11-08 19:51:37 +01:00
if ( ! $checkboxes [ 'move_to_copy' ])
2006-04-23 16:40:31 +02:00
{
2013-11-08 19:51:37 +01:00
$action_msg = lang ( 'moved' );
2016-04-29 12:41:53 +02:00
if (( $Ok = !! ( $contact = $this -> read ( $id )) && $this -> check_perms ( Acl :: DELETE , $contact )))
2006-04-23 16:40:31 +02:00
{
2016-04-29 12:41:53 +02:00
if ( ! $contact [ 'owner' ]) // no (mass-)move of Api\Accounts
2013-11-08 19:51:37 +01:00
{
$Ok = false ;
}
elseif ( $contact [ 'owner' ] != ( int ) $action || $contact [ 'private' ] != ( int )( substr ( $action , - 1 ) == 'p' ))
{
$contact [ 'owner' ] = ( int ) $action ;
$contact [ 'private' ] = ( int )( substr ( $action , - 1 ) == 'p' );
$Ok = $this -> save ( $contact );
}
2006-04-23 16:40:31 +02:00
}
2013-11-08 19:51:37 +01:00
}
else
{
$action_msg = lang ( 'copied' );
2016-04-29 12:41:53 +02:00
if (( $Ok = !! ( $contact = $this -> read ( $id )) && $this -> check_perms ( Acl :: READ , $contact )))
2006-04-23 16:40:31 +02:00
{
2015-12-15 23:38:22 +01:00
if ( $contact [ 'owner' ] != ( int ) $action || $contact [ 'private' ] != ( int )( substr ( $action , - 1 ) == 'p' ))
2013-11-08 19:51:37 +01:00
{
2015-12-15 23:38:22 +01:00
$this -> copy_contact ( $contact , false ); // do NOT use self::$copy_fields, copy everything but uid etc.
$links = $contact [ 'link_to' ][ 'to_id' ];
2013-11-08 19:51:37 +01:00
$contact [ 'owner' ] = ( int ) $action ;
$contact [ 'private' ] = ( int )( substr ( $action , - 1 ) == 'p' );
$Ok = $this -> save ( $contact );
2015-12-15 23:38:22 +01:00
if ( $Ok && is_array ( $links ))
{
2016-04-29 12:41:53 +02:00
Link :: link ( 'addressbook' , $contact [ 'id' ], $links );
2015-12-15 23:38:22 +01:00
}
2013-11-08 19:51:37 +01:00
}
2006-04-23 16:40:31 +02:00
}
}
break ;
}
if ( $Ok )
{
++ $success ;
}
2006-10-22 13:40:43 +02:00
elseif ( $action != 'email' && $action != 'email_home' )
2006-04-23 16:40:31 +02:00
{
++ $failed ;
}
}
return ! $failed ;
}
2017-03-13 19:11:37 +01:00
/**
* Find the individual contact IDs for a list of grouped contacts
*
* Successful lookups are removed from the checked array .
*
* Used for action on organisation and duplicate views
* @ param string / int $action 'delete' , 'vcard' , 'csv' or nummerical account_id to move contacts to that addessbook
* @ param array $checked contact id ' s to use if ! $use_all
2017-09-19 11:38:02 +02:00
* @ param boolean $use_all if true use all contacts of the current selection in the session ( NOT used ! )
2017-03-13 19:11:37 +01:00
* @ param int & $success number of succeded actions
* @ param int & $failed number of failed actions ( not enought permissions )
* @ param string & $action_msg translated verb for the actions , to be used in a message like % 1 contacts 'deleted'
* @ param string / array $session_name 'index' or 'email' , or array with session - data depending if we are in the main list or the popup
*
* @ return array List of contact IDs in the provided groups
*/
protected function find_grouped_ids ( $action , & $checked , $use_all , & $success , & $failed , & $action_msg , $session_name , & $msg )
{
2017-09-19 11:38:02 +02:00
unset ( $use_all );
2017-03-13 19:11:37 +01:00
$grouped_contacts = array ();
foreach (( array ) $checked as $n => $id )
{
if ( substr ( $id , 0 , 9 ) == 'org_name:' || substr ( $id , 0 , 10 ) == 'duplicate:' )
{
if ( count ( $checked ) == 1 && ! count ( $grouped_contacts ) && $action == 'infolog' )
{
return $this -> infolog_org_view ( $id ); // uses the org-name, instead of 'selected contacts'
}
unset ( $checked [ $n ]);
$query = Api\Cache :: getSession ( 'addressbook' , $session_name );
$query [ 'num_rows' ] = - 1 ; // all
$query [ 'grouped_view' ] = $id ;
unset ( $query [ 'filter2' ]);
$extra = $readonlys = null ;
$this -> get_rows ( $query , $extra , $readonlys , true ); // true = only return the id's
// Merge them here, so we only merge the ones that are duplicates,
// not merge all selected together
if ( $action == 'merge_duplicates' )
{
$loop_success = $loop_fail = 0 ;
$this -> action ( 'merge' , $extra , false , $loop_success , $loop_fail , $action_msg , $session_name , $msg );
$success += $loop_success ;
$failed += $loop_fail ;
}
2017-04-04 16:52:25 +02:00
if ( $extra [ 0 ])
2017-03-13 19:11:37 +01:00
{
$grouped_contacts = array_merge ( $grouped_contacts , $extra );
}
}
}
return $grouped_contacts ;
}
2015-12-15 23:38:22 +01:00
/**
* Copy a given contact ( not storing it ! )
*
* Taken care only configured fields get copied and certain fields never to copy ( uid etc . ) .
*
* @ param array & $content
* @ param boolean $only_copy_fields = true true : only copy fields configured for copying ( eg . no name ),
* false : copy everything , but never to copy fields
*/
function copy_contact ( array & $content , $only_copy_fields = true )
{
$content [ 'link_to' ][ 'to_id' ] = 0 ;
2016-04-29 12:41:53 +02:00
Link :: link ( 'addressbook' , $content [ 'link_to' ][ 'to_id' ], 'addressbook' , $content [ 'id' ],
lang ( 'Copied by %1, from record #%2.' , Api\Accounts :: format_username ( '' ,
2015-12-15 23:38:22 +01:00
$GLOBALS [ 'egw_info' ][ 'user' ][ 'account_firstname' ], $GLOBALS [ 'egw_info' ][ 'user' ][ 'account_lastname' ]),
$content [ 'id' ]));
// create a new contact with the content of the old
foreach ( array_keys ( $content ) as $key )
{
if ( $only_copy_fields && ! in_array ( $key , self :: $copy_fields ) || in_array ( $key , array ( 'id' , 'etag' , 'carddav_name' , 'uid' )))
{
unset ( $content [ $key ]);
}
}
if ( ! isset ( $content [ 'owner' ]))
{
$content [ 'owner' ] = $this -> default_private ? $this -> user . 'p' : $this -> default_addressbook ;
}
$content [ 'creator' ] = $this -> user ;
$content [ 'created' ] = $this -> now_su ;
}
2006-04-23 16:40:31 +02:00
/**
* rows callback for index nextmatch
*
2008-04-18 08:10:31 +02:00
* @ internal
2006-04-23 16:40:31 +02:00
* @ param array & $query
* @ param array & $rows returned rows / cups
2016-04-29 12:41:53 +02:00
* @ param array & $readonlys eg . to disable buttons based on Acl
* @ param boolean $id_only = false if true only return ( via $rows ) an array of contact - ids , dont save state to session
2006-04-23 16:40:31 +02:00
* @ return int total number of contacts matching the selection
*/
function get_rows ( & $query , & $rows , & $readonlys , $id_only = false )
{
2018-11-20 18:27:43 +01:00
$what = $query [ 'sitemgr_display' ] ? $query [ 'sitemgr_display' ] : 'index' ;
2008-10-20 21:35:18 +02:00
2009-10-30 12:18:47 +01:00
if ( ! $id_only && ! $query [ 'csv_export' ]) // do NOT store state for csv_export or querying id's (no regular view)
2009-07-18 17:17:41 +02:00
{
2014-02-27 21:20:15 +01:00
$store_query = $query ;
// Do not store these
2017-04-04 16:52:25 +02:00
foreach ( array ( 'options-cat_id' , 'actions' , 'action_links' , 'placeholder_actions' ) as $key )
2014-02-27 21:20:15 +01:00
{
unset ( $store_query [ $key ]);
}
2016-06-09 23:05:25 +02:00
$old_state = $store_query ;
Api\Cache :: setSession ( 'addressbook' , $what , $store_query );
2009-07-18 17:17:41 +02:00
}
else
{
2016-04-29 12:41:53 +02:00
$old_state = Api\Cache :: getSession ( 'addressbook' , $what );
2009-07-18 17:17:41 +02:00
}
2018-12-20 18:45:11 +01:00
$GLOBALS [ 'egw' ] -> session -> commit_session ();
2020-10-16 21:34:26 +02:00
if ( $query [ 'grouped_view' ] === 'shared_by_me' )
{
$query [ 'col_filter' ][ 'shared_by' ] = $this -> user ;
$query [ 'grouped_view' ] = '' ;
}
2017-04-04 16:52:25 +02:00
if ( ! isset ( $this -> grouped_views [( string ) $query [ 'grouped_view' ]]) || strpos ( $query [ 'grouped_view' ], ':' ) === false )
2008-03-10 13:15:47 +01:00
{
2017-03-13 19:11:37 +01:00
// we don't have a grouped view, unset the according col_filters
$this -> unset_grouped_filters ( $query );
2008-03-10 13:15:47 +01:00
}
2008-02-21 12:54:22 +01:00
2017-03-13 19:11:37 +01:00
if ( isset ( $this -> grouped_views [( string ) $query [ 'grouped_view' ]]))
2006-10-31 08:56:34 +01:00
{
2017-03-13 19:11:37 +01:00
// we have a grouped view, reset the advanced search
2021-10-05 16:35:27 +02:00
if ( empty ( $query [ 'search' ]) && ! empty ( $old_state [ 'advanced_search' ]))
{
$query [ 'advanced_search' ] = $old_state [ 'advanced_search' ];
}
2006-10-31 08:56:34 +01:00
}
2021-10-05 16:35:27 +02:00
// eg. paging in an advanced search
elseif ( empty ( $query [ 'search' ]) && is_array ( $old_state ) && array_key_exists ( 'advanced_search' , $old_state ))
2006-10-31 08:56:34 +01:00
{
$query [ 'advanced_search' ] = $old_state [ 'advanced_search' ];
}
2012-02-01 21:34:32 +01:00
// Make sure old lettersearch filter doesn't stay - current letter filter will be added later
foreach ( $query [ 'col_filter' ] as $key => $col_filter )
{
if ( ! is_numeric ( $key )) continue ;
if ( preg_match ( '/' . $GLOBALS [ 'egw' ] -> db -> capabilities [ 'case_insensitive_like' ] .
2018-07-18 21:43:32 +02:00
' ' . $GLOBALS [ 'egw' ] -> db -> quote ( '[a-z]%' ) . '$/i' , $col_filter ) == 1
2012-02-01 21:34:32 +01:00
)
{
unset ( $query [ 'col_filter' ][ $key ]);
}
}
2006-04-23 16:40:31 +02:00
//echo "<p>uicontacts::get_rows(".print_r($query,true).")</p>\n";
if ( ! $id_only )
{
2006-06-13 23:53:00 +02:00
// check if accounts are stored in ldap, which does NOT yet support the org-views
2017-03-13 19:11:37 +01:00
if ( $this -> so_accounts && $query [ 'filter' ] === '0' && $query [ 'grouped_view' ])
2006-06-13 23:53:00 +02:00
{
if ( $old_state [ 'filter' ] === '0' ) // user changed to org_view
{
$query [ 'filter' ] = '' ; // --> change filter to all contacts
}
else // user changed to accounts
{
2017-03-13 19:11:37 +01:00
$query [ 'grouped_view' ] = '' ; // --> change to regular contacts view
2006-06-13 23:53:00 +02:00
}
}
2017-03-13 19:11:37 +01:00
if ( $query [ 'grouped_view' ] && isset ( $this -> grouped_views [ $old_state [ 'grouped_view' ]]) && ! isset ( $this -> grouped_views [ $query [ 'grouped_view' ]]))
2006-10-07 12:18:35 +02:00
{
2017-03-13 19:11:37 +01:00
$query [ 'searchletter' ] = '' ; // reset lettersearch if viewing the contacts of one group (org or duplicates)
2006-10-07 12:18:35 +02:00
}
2006-04-23 16:40:31 +02:00
// save the state of the index in the user prefs
$state = serialize ( array (
2017-03-13 19:11:37 +01:00
'filter' => $query [ 'filter' ],
'cat_id' => $query [ 'cat_id' ],
'order' => $query [ 'order' ],
'sort' => $query [ 'sort' ],
'col_filter' => array ( 'tid' => $query [ 'col_filter' ][ 'tid' ]),
'grouped_view' => $query [ 'grouped_view' ],
2006-04-23 16:40:31 +02:00
));
2012-03-29 14:59:22 +02:00
if ( $state != $this -> prefs [ $what . '_state' ] && ! $query [ 'csv_export' ])
2008-02-21 12:54:22 +01:00
{
2008-10-20 21:35:18 +02:00
$GLOBALS [ 'egw' ] -> preferences -> add ( 'addressbook' , $what . '_state' , $state );
2006-06-13 23:53:00 +02:00
// save prefs, but do NOT invalid the cache (unnecessary)
$GLOBALS [ 'egw' ] -> preferences -> save_repository ( false , 'user' , false );
2006-04-23 16:40:31 +02:00
}
}
2006-10-31 08:56:34 +01:00
unset ( $old_state );
2006-10-02 09:49:00 +02:00
if (( string ) $query [ 'cat_id' ] != '' )
2006-04-23 16:40:31 +02:00
{
2006-10-02 09:49:00 +02:00
$query [ 'col_filter' ][ 'cat_id' ] = $query [ 'cat_id' ] ? $query [ 'cat_id' ] : null ;
}
else
{
unset ( $query [ 'col_filter' ][ 'cat_id' ]);
2006-04-23 16:40:31 +02:00
}
if ( $query [ 'filter' ] !== '' ) // not all addressbooks
{
$query [ 'col_filter' ][ 'owner' ] = ( string ) ( int ) $query [ 'filter' ];
if ( $this -> private_addressbook )
{
$query [ 'col_filter' ][ 'private' ] = substr ( $query [ 'filter' ], - 1 ) == 'p' ? 1 : 0 ;
}
}
2013-02-05 12:47:32 +01:00
else
{
unset ( $query [ 'col_filter' ][ 'owner' ]);
unset ( $query [ 'col_filter' ][ 'private' ]);
}
2007-03-13 14:38:15 +01:00
if (( int ) $query [ 'filter2' ]) // not no distribution list
{
$query [ 'col_filter' ][ 'list' ] = ( string ) ( int ) $query [ 'filter2' ];
}
else
{
unset ( $query [ 'col_filter' ][ 'list' ]);
}
2017-11-15 19:29:10 +01:00
if ( $GLOBALS [ 'egw_info' ][ 'user' ][ 'preferences' ][ 'addressbook' ][ 'hide_accounts' ] === '1' )
2007-04-30 17:18:29 +02:00
{
$query [ 'col_filter' ][ 'account_id' ] = null ;
}
2017-11-15 19:29:10 +01:00
else
{
unset ( $query [ 'col_filter' ][ 'account_id' ]);
}
2017-01-23 11:16:24 +01:00
// all backends allow now at least to use groups as distribution lists
$query [ 'no_filter2' ] = false ;
2008-04-18 08:10:31 +02:00
2017-03-13 19:11:37 +01:00
// Grouped view
if ( isset ( $this -> grouped_views [( string ) $query [ 'grouped_view' ]]) && ! $query [ 'col_filter' ][ 'parent_id' ])
2006-04-23 16:40:31 +02:00
{
2017-03-13 19:11:37 +01:00
$query [ 'grouped_view_label' ] = '' ;
$rows = $this -> get_grouped_rows ( $query );
2006-04-23 16:40:31 +02:00
}
2006-04-30 11:34:24 +02:00
else // contacts view
2006-04-23 16:40:31 +02:00
{
2015-03-02 22:50:25 +01:00
if ( $query [ 'col_filter' ][ 'parent_id' ])
{
2017-03-13 19:11:37 +01:00
$query [ 'grouped_view' ] = $query [ 'col_filter' ][ 'parent_id' ];
2015-03-02 22:50:25 +01:00
}
// Query doesn't like parent_id
unset ( $query [ 'col_filter' ][ 'parent_id' ]);
2017-03-13 19:11:37 +01:00
if ( $query [ 'grouped_view' ]) // view the contacts of one organisation only
2013-11-08 19:51:37 +01:00
{
2017-03-13 19:11:37 +01:00
if ( strpos ( $query [ 'grouped_view' ], '*AND*' ) !== false ) $query [ 'grouped_view' ] = str_replace ( '*AND*' , '&' , $query [ 'grouped_view' ]);
2021-11-10 11:38:06 +01:00
if ( ! is_array ( $fields = $GLOBALS [ 'egw_info' ][ 'user' ][ 'preferences' ][ 'addressbook' ][ 'duplicate_fields' ] ? ? []))
{
$fields = explode ( ',' , $fields );
}
2017-03-13 19:11:37 +01:00
foreach ( explode ( '|||' , $query [ 'grouped_view' ]) as $part )
2006-04-30 11:34:24 +02:00
{
list ( $name , $value ) = explode ( ':' , $part , 2 );
2014-06-03 11:54:53 +02:00
// do NOT set invalid column, as this gives an SQL error ("AND AND" in sql)
2017-05-31 18:18:34 +02:00
if ( static :: $duplicate_fields [ $name ] && $value && (
strpos ( $query [ 'grouped_view' ], 'duplicate:' ) === 0 && in_array ( $name , $fields ) ||
strpos ( $query [ 'grouped_view' ], 'duplicate:' ) !== 0
))
2014-06-03 11:54:53 +02:00
{
$query [ 'col_filter' ][ $name ] = $value ;
}
2006-04-30 11:34:24 +02:00
}
}
2014-02-03 21:13:52 +01:00
else if ( $query [ 'actions' ] && ! $query [ 'actions' ][ 'edit' ])
{
2017-03-13 19:11:37 +01:00
// Just switched from grouped view, update actions
$query [ 'actions' ] = $this -> get_actions ( $query [ 'col_filter' ][ 'tid' ]);
2014-02-03 21:13:52 +01:00
}
2006-09-25 12:18:05 +02:00
// translate the select order to the really used over all 3 columns
2006-04-30 11:34:24 +02:00
$sort = $query [ 'sort' ];
2007-06-03 10:42:59 +02:00
switch ( $query [ 'order' ]) // "xxx<>'' DESC" sorts contacts with empty order-criteria always at the end
2006-09-25 12:18:05 +02:00
{ // we don't exclude them, as the total would otherwise depend on the order-criteria
2006-04-30 11:34:24 +02:00
case 'org_name' :
2010-05-12 16:37:36 +02:00
$order = " egw_addressbook.org_name<>''DESC,egw_addressbook.org_name $sort ,n_family $sort ,n_given $sort " ;
2006-04-30 11:34:24 +02:00
break ;
default :
2008-01-19 06:41:04 +01:00
if ( $query [ 'order' ][ 0 ] == '#' ) // we order by a custom field
{
2010-04-09 00:42:25 +02:00
$order = " { $query [ 'order' ] } $sort ,org_name $sort ,n_family $sort ,n_given $sort " ;
2008-01-19 06:41:04 +01:00
break ;
}
2006-04-30 11:34:24 +02:00
$query [ 'order' ] = 'n_family' ;
case 'n_family' :
2007-06-03 10:42:59 +02:00
$order = " n_family<>'' DESC,n_family $sort ,n_given $sort ,org_name $sort " ;
2006-04-30 11:34:24 +02:00
break ;
case 'n_given' :
2007-06-03 10:42:59 +02:00
$order = " n_given<>'' DESC,n_given $sort ,n_family $sort ,org_name $sort " ;
2006-04-30 11:34:24 +02:00
break ;
case 'n_fileas' :
2007-06-03 10:42:59 +02:00
$order = " n_fileas<>'' DESC,n_fileas $sort " ;
2006-04-30 11:34:24 +02:00
break ;
2006-12-11 08:35:49 +01:00
case 'adr_one_postalcode' :
2011-11-11 17:56:08 +01:00
case 'adr_two_postalcode' :
$order = $query [ 'order' ] . " <>'' DESC, " . $query [ 'order' ] . " $sort ,org_name $sort ,n_family $sort ,n_given $sort " ;
2006-12-11 08:35:49 +01:00
break ;
2007-03-07 13:31:48 +01:00
case 'contact_modified' :
case 'contact_created' :
$order = " $query[order] IS NULL, $query[order] $sort ,org_name $sort ,n_family $sort ,n_given $sort " ;
break ;
2010-09-29 12:38:44 +02:00
case 'contact_id' :
2012-05-14 20:00:19 +02:00
$order = " egw_addressbook. $query[order] $sort " ;
2006-04-30 11:34:24 +02:00
}
2006-09-25 12:18:05 +02:00
if ( $query [ 'searchletter' ]) // only show contacts if the order-criteria starts with the given letter
2006-04-30 11:34:24 +02:00
{
2011-06-06 18:41:17 +02:00
$no_letter_search = array ( 'adr_one_postalcode' , 'adr_two_postalcode' , 'contact_id' , 'contact_created' , 'contact_modified' );
$query [ 'col_filter' ][] = ( in_array ( $query [ 'order' ], $no_letter_search ) ? 'org_name' : ( substr ( $query [ 'order' ], 0 , 1 ) == '#' ? '' : 'egw_addressbook.' ) . $query [ 'order' ]) . ' ' .
2018-01-24 10:08:55 +01:00
$GLOBALS [ 'egw' ] -> db -> capabilities [ 'case_insensitive_like' ] . ' ' . $GLOBALS [ 'egw' ] -> db -> quote ( $query [ 'searchletter' ] . '%' );
2006-04-30 11:34:24 +02:00
}
2006-10-24 21:20:37 +02:00
$wildcard = '%' ;
$op = 'OR' ;
2006-10-31 08:56:34 +01:00
if ( $query [ 'advanced_search' ])
2006-10-24 21:20:37 +02:00
{
2014-09-08 20:47:40 +02:00
// Make sure op & wildcard are only valid options
$op = $query [ 'advanced_search' ][ 'operator' ] == $op ? $op : 'AND' ;
2006-10-31 08:56:34 +01:00
unset ( $query [ 'advanced_search' ][ 'operator' ]);
2016-06-26 18:52:45 +02:00
$wildcard = $query [ 'advanced_search' ][ 'meth_select' ] == $wildcard ? $wildcard : '' ;
2006-10-31 08:56:34 +01:00
unset ( $query [ 'advanced_search' ][ 'meth_select' ]);
2006-10-24 21:20:37 +02:00
}
2018-11-20 18:27:43 +01:00
2020-11-02 11:43:55 +01:00
$columsel = $this -> prefs [ 'nextmatch-addressbook.index.rows' ];
$columselection = $columsel ? explode ( ',' , $columsel ) : array ();
$extracols = [];
if ( in_array ( 'owner_shared_with' , $columselection ))
{
$extracols [] = 'shared_with' ;
}
2007-05-22 10:02:06 +02:00
$rows = parent :: search ( $query [ 'advanced_search' ] ? $query [ 'advanced_search' ] : $query [ 'search' ], $id_only ,
2020-11-02 11:43:55 +01:00
$order , $extracols , $wildcard , false , $op ,[( int ) $query [ 'start' ], ( int ) $query [ 'num_rows' ]], $query [ 'col_filter' ]);
2007-05-26 09:58:37 +02:00
2018-11-20 18:27:43 +01:00
// do we need to read the custom fields, depends on the column is enabled and customfields
2021-02-08 17:56:49 +01:00
$available_distib_lists = $this -> get_lists ( Acl :: READ );
2017-03-08 17:53:52 +01:00
$ids = $calendar_participants = array ();
2007-09-14 12:31:08 +02:00
if ( ! $id_only && $rows )
2006-04-30 11:34:24 +02:00
{
2019-10-07 22:16:04 +02:00
$show_custom_fields = ( in_array ( 'customfields' , $columselection ) || $this -> config [ 'index_load_cfs' ]) && $this -> customfields ;
2018-12-17 18:04:06 +01:00
$show_calendar = $this -> config [ 'disable_event_column' ] != 'True' && in_array ( 'calendar_calendar' , $columselection );
2021-02-08 17:56:49 +01:00
$show_distributionlist = in_array ( 'distribution_list' , $columselection ) ||
2020-11-02 11:43:55 +01:00
is_array ( $available_distib_lists ) && count ( $available_distib_lists );
2008-01-31 13:52:43 +01:00
if ( $show_calendar || $show_custom_fields || $show_distributionlist )
2006-04-30 11:34:24 +02:00
{
2007-09-14 12:31:08 +02:00
foreach ( $rows as $val )
{
$ids [] = $val [ 'id' ];
2017-03-08 17:53:52 +01:00
$calendar_participants [ $val [ 'id' ]] = $val [ 'account_id' ] ? $val [ 'account_id' ] : 'c' . $val [ 'id' ];
2007-09-14 12:31:08 +02:00
}
2008-04-02 10:24:52 +02:00
if ( $show_custom_fields )
{
2019-10-07 22:16:04 +02:00
$selected_cfs = array ();
if ( in_array ( 'customfields' , $columselection ))
2008-04-02 10:24:52 +02:00
{
2019-10-07 22:16:04 +02:00
foreach ( $columselection as $col )
{
if ( $col [ 0 ] == '#' ) $selected_cfs [] = substr ( $col , 1 );
}
2008-04-02 10:24:52 +02:00
}
2019-10-07 22:16:04 +02:00
$selected_cfs = array_unique ( array_merge ( $selected_cfs , ( array ) $this -> config [ 'index_load_cfs' ]));
2008-04-02 10:24:52 +02:00
$customfields = $this -> read_customfields ( $ids , $selected_cfs );
}
2018-11-20 18:27:43 +01:00
if ( $show_calendar && ! empty ( $ids )) $calendar = $this -> read_calendar ( $calendar_participants );
2008-04-18 08:10:31 +02:00
// distributionlist memership for the entrys
2016-04-29 12:41:53 +02:00
//_debug_array($this->get_lists(Acl::EDIT));
2008-03-31 07:40:53 +02:00
if ( $show_distributionlist && $available_distib_lists )
{
$distributionlist = $this -> read_distributionlist ( $ids , array_keys ( $available_distib_lists ));
}
2006-04-30 11:34:24 +02:00
}
}
2006-04-23 16:40:31 +02:00
}
2006-04-30 11:34:24 +02:00
if ( ! $rows ) $rows = array ();
2006-04-23 16:40:31 +02:00
2006-04-26 23:23:38 +02:00
if ( $id_only )
{
foreach ( $rows as $n => $row )
{
$rows [ $n ] = $row [ 'id' ];
}
return $this -> total ; // no need to set other fields or $readonlys
}
2006-04-23 16:40:31 +02:00
$order = $query [ 'order' ];
2008-04-18 08:10:31 +02:00
2020-11-02 12:55:38 +01:00
$unshare_grants = [];
foreach ( $this -> grants as $grantee => $rights )
{
if ( $rights & ( ACL :: EDIT | self :: ACL_SHARED )) $unshare_grants [] = $grantee ;
}
2006-04-23 16:40:31 +02:00
$readonlys = array ();
2011-04-17 16:10:05 +02:00
foreach ( $rows as $n => & $row )
2006-04-23 16:40:31 +02:00
{
$given = $row [ 'n_given' ] ? $row [ 'n_given' ] : ( $row [ 'n_prefix' ] ? $row [ 'n_prefix' ] : '' );
switch ( $order )
{
2007-03-07 13:31:48 +01:00
default : // postalcode, created, modified, ...
2006-04-23 16:40:31 +02:00
case 'org_name' :
2006-04-24 13:15:10 +02:00
$row [ 'line1' ] = $row [ 'org_name' ];
$row [ 'line2' ] = $row [ 'n_family' ] . ( $given ? ', ' . $given : '' );
2006-04-23 16:40:31 +02:00
break ;
case 'n_family' :
2006-04-24 13:15:10 +02:00
$row [ 'line1' ] = $row [ 'n_family' ] . ( $given ? ', ' . $given : '' );
$row [ 'line2' ] = $row [ 'org_name' ];
2006-04-23 16:40:31 +02:00
break ;
case 'n_given' :
2006-04-24 13:15:10 +02:00
$row [ 'line1' ] = $given . ' ' . $row [ 'n_family' ];
$row [ 'line2' ] = $row [ 'org_name' ];
break ;
case 'n_fileas' :
2006-09-25 12:18:05 +02:00
if ( ! $row [ 'n_fileas' ]) $row [ 'n_fileas' ] = $this -> fileas ( $row );
2006-04-24 13:15:10 +02:00
list ( $row [ 'line1' ], $row [ 'line2' ]) = explode ( ': ' , $row [ 'n_fileas' ]);
2006-04-23 16:40:31 +02:00
break ;
}
2017-03-13 19:11:37 +01:00
if ( isset ( $this -> grouped_views [( string ) $query [ 'grouped_view' ]]))
2006-04-23 16:40:31 +02:00
{
2006-04-30 11:34:24 +02:00
$row [ 'type' ] = 'home' ;
2017-03-13 19:11:37 +01:00
$row [ 'type_label' ] = $query [ 'grouped_view' ] == 'duplicate' ? lang ( 'Duplicates' ) : lang ( 'Organisation' );
2008-04-18 08:10:31 +02:00
2016-04-29 12:41:53 +02:00
if ( $query [ 'filter' ] && ! ( $this -> grants [( int ) $query [ 'filter' ]] & Acl :: DELETE ))
2011-04-17 23:25:01 +02:00
{
2011-04-28 11:12:30 +02:00
$row [ 'class' ] .= 'rowNoDelete ' ;
2011-04-17 23:25:01 +02:00
}
2011-04-28 11:12:30 +02:00
$row [ 'class' ] .= 'rowNoEdit ' ; // no edit in OrgView
2017-03-13 19:11:37 +01:00
$row [ 'class' ] .= $query [ 'grouped_view' ] == 'duplicates' ? 'contact_duplicate' : 'contact_organisation ' ;
2006-04-23 16:40:31 +02:00
}
2006-04-30 11:34:24 +02:00
else
2006-04-23 16:40:31 +02:00
{
2006-04-30 11:34:24 +02:00
$this -> type_icon ( $row [ 'owner' ], $row [ 'private' ], $row [ 'tid' ], $row [ 'type' ], $row [ 'type_label' ]);
2008-04-18 08:10:31 +02:00
2008-06-11 09:17:30 +02:00
static $tel2show = array ( 'tel_work' , 'tel_cell' , 'tel_home' , 'tel_fax' );
2016-04-29 12:41:53 +02:00
static $prefer_marker = null ;
2013-02-05 12:24:02 +01:00
if ( is_null ( $prefer_marker ))
{
// as et2 adds options with .text(), it can't be entities, but php knows no string literals with utf-8
2016-05-19 16:59:08 +02:00
$prefer_marker = html_entity_decode ( ' ☆' , ENT_NOQUOTES , 'utf-8' );
2013-02-05 12:24:02 +01:00
}
2006-04-30 11:34:24 +02:00
foreach ( $tel2show as $name )
{
2013-02-05 12:24:02 +01:00
$row [ $name ] .= ' ' . ( $row [ 'tel_prefer' ] == $name ? $prefer_marker : '' ); // .' ' to NOT remove the field
2006-04-30 11:34:24 +02:00
}
// allways show the prefered phone, if not already shown
if ( ! in_array ( $row [ 'tel_prefer' ], $tel2show ) && $row [ $row [ 'tel_prefer' ]])
{
2013-02-05 12:24:02 +01:00
$row [ 'tel_prefered' ] = $row [ $row [ 'tel_prefer' ]] . $prefer_marker ;
2006-04-30 11:34:24 +02:00
}
2017-08-14 19:22:46 +02:00
// Show nice name as status text
if ( $row [ 'tel_prefer' ])
{
$row [ 'tel_prefer_label' ] = $this -> contact_fields [ $row [ 'tel_prefer' ]];
}
2015-07-23 19:40:48 +02:00
if ( ! $row [ 'owner' ] && $row [ 'account_id' ] > 0 )
2014-03-19 14:20:46 +01:00
{
2015-04-24 17:13:45 +02:00
$row [ 'class' ] .= 'rowAccount rowNoDelete ' ;
2014-03-19 14:20:46 +01:00
}
2016-04-29 12:41:53 +02:00
elseif ( ! $this -> check_perms ( Acl :: DELETE , $row ) || ( ! $GLOBALS [ 'egw_info' ][ 'user' ][ 'apps' ][ 'admin' ] && $this -> config [ 'history' ] != 'userpurge' && $query [ 'col_filter' ][ 'tid' ] == self :: DELETED_TYPE ))
2011-04-17 23:25:01 +02:00
{
2011-04-28 11:12:30 +02:00
$row [ 'class' ] .= 'rowNoDelete ' ;
2011-04-17 23:25:01 +02:00
}
2016-04-29 12:41:53 +02:00
if ( ! $this -> check_perms ( Acl :: EDIT , $row ))
2011-04-17 23:25:01 +02:00
{
2011-04-28 11:12:30 +02:00
$row [ 'class' ] .= 'rowNoEdit ' ;
2011-04-17 23:25:01 +02:00
}
2015-03-10 16:41:53 +01:00
$row [ 'class' ] .= 'contact_contact ' ;
2008-04-18 08:10:31 +02:00
2013-02-05 09:07:02 +01:00
unset ( $row [ 'jpegphoto' ]); // unused and messes up json encoding (not utf-8)
2006-04-30 11:34:24 +02:00
if ( isset ( $customfields [ $row [ 'id' ]]))
2006-04-23 16:40:31 +02:00
{
2006-04-30 11:34:24 +02:00
foreach ( $this -> customfields as $name => $data )
{
2010-04-09 00:42:25 +02:00
$row [ '#' . $name ] = $customfields [ $row [ 'id' ]][ '#' . $name ];
2006-04-30 11:34:24 +02:00
}
2006-04-23 16:40:31 +02:00
}
2008-01-31 13:52:43 +01:00
if ( isset ( $distributionlist [ $row [ 'id' ]]))
{
$row [ 'distrib_lists' ] = implode ( " \n " , array_values ( $distributionlist [ $row [ 'id' ]]));
//if ($show_distributionlist) $readonlys['distrib_lists'] =true;
}
2017-03-08 17:53:52 +01:00
if ( isset ( $calendar [ $calendar_participants [ $row [ 'id' ]]]))
2007-09-14 12:03:18 +02:00
{
2017-03-08 17:53:52 +01:00
foreach ( $calendar [ $calendar_participants [ $row [ 'id' ]]] as $name => $data )
2007-09-14 12:03:18 +02:00
{
$row [ $name ] = $data ;
}
}
2006-06-17 20:50:07 +02:00
}
2007-06-17 15:55:43 +02:00
2007-05-03 10:17:31 +02:00
// hide region for address format 'postcode_city'
if (( $row [ 'addr_format' ] = $this -> addr_format_by_country ( $row [ 'adr_one_countryname' ])) == 'postcode_city' ) unset ( $row [ 'adr_one_region' ]);
if (( $row [ 'addr_format2' ] = $this -> addr_format_by_country ( $row [ 'adr_two_countryname' ])) == 'postcode_city' ) unset ( $row [ 'adr_two_region' ]);
2010-03-05 09:28:25 +01:00
2009-11-26 09:32:18 +01:00
// respect category permissions
if ( ! empty ( $row [ 'cat_id' ]))
{
2016-04-29 12:41:53 +02:00
$row [ 'cat_id' ] = $this -> categories -> check_list ( Acl :: READ , $row [ 'cat_id' ]);
2009-11-26 09:32:18 +01:00
}
2020-10-19 18:34:11 +02:00
2020-11-02 12:55:38 +01:00
if ( $query [ 'col_filter' ][ 'shared_by' ] == $this -> user || ! empty ( $row [ 'shared_with' ]) &&
array_intersect ( $unshare_grants , explode ( ',' , $row [ 'shared_with' ])))
2020-10-19 18:34:11 +02:00
{
$row [ 'class' ] .= 'unshare_contact ' ;
}
2006-04-23 16:40:31 +02:00
}
2016-03-14 18:22:09 +01:00
$rows [ 'no_distribution_list' ] = ( bool ) $query [ 'filter2' ];
2009-05-30 09:39:58 +02:00
2006-04-23 16:40:31 +02:00
// disable customfields column, if we have no customefield(s)
2018-12-10 17:50:34 +01:00
if ( ! $this -> customfields )
{
$rows [ 'no_customfields' ] = true ;
}
// Disable next/last date if so configured
2018-12-17 18:04:06 +01:00
if ( $this -> config [ 'disable_event_column' ] == 'True' )
2018-12-10 17:50:34 +01:00
{
$rows [ 'no_event_column' ] = true ;
}
2014-02-28 11:13:26 +01:00
2020-12-29 17:39:14 +01:00
// If we've changed the sort order on them, update the display
if ( $order !== $query [ 'order' ] )
{
$rows [ 'order' ] = $order ;
}
2006-04-30 20:03:06 +02:00
$rows [ 'call_popup' ] = $this -> config [ 'call_popup' ];
2006-04-23 16:40:31 +02:00
$rows [ 'customfields' ] = array_values ( $this -> customfields );
2008-04-18 08:10:31 +02:00
2006-04-30 11:34:24 +02:00
// full app-header with all search criteria specially for the print
2016-02-17 20:56:54 +01:00
$header = array ();
2017-03-13 19:11:37 +01:00
if ( $query [ 'filter' ] !== '' && ! isset ( $this -> grouped_views [ $query [ 'grouped_view' ]]))
2008-04-18 08:10:31 +02:00
{
2016-02-17 20:56:54 +01:00
$header [] = ( $query [ 'filter' ] == '0' ? lang ( 'accounts' ) :
2008-04-18 08:10:31 +02:00
( $GLOBALS [ 'egw' ] -> accounts -> get_type ( $query [ 'filter' ]) == 'g' ?
2006-04-23 16:40:31 +02:00
lang ( 'Group %1' , $GLOBALS [ 'egw' ] -> accounts -> id2name ( $query [ 'filter' ])) :
2016-04-29 12:41:53 +02:00
Api\Accounts :: username (( int ) $query [ 'filter' ]) .
2006-04-23 16:40:31 +02:00
( substr ( $query [ 'filter' ], - 1 ) == 'p' ? ' (' . lang ( 'private' ) . ')' : '' )));
}
2017-03-13 19:11:37 +01:00
if ( $query [ 'grouped_view' ])
2006-04-30 11:34:24 +02:00
{
2017-03-13 19:11:37 +01:00
$header [] = $query [ 'grouped_view_label' ];
2013-10-22 00:18:41 +02:00
// Make sure option is there
2017-03-13 19:11:37 +01:00
if ( ! array_key_exists ( $query [ 'grouped_view' ], $this -> grouped_views ))
2013-10-22 00:18:41 +02:00
{
2017-03-13 19:11:37 +01:00
$this -> grouped_views += $this -> _get_grouped_name ( $query [ 'grouped_view' ]);
$rows [ 'sel_options' ][ 'grouped_view' ] = $this -> grouped_views ;
2013-10-22 00:18:41 +02:00
}
2006-04-30 11:34:24 +02:00
}
2008-04-18 08:10:31 +02:00
if ( $query [ 'advanced_search' ])
2006-10-31 08:56:34 +01:00
{
2016-02-17 20:56:54 +01:00
$header [] = lang ( 'Advanced search' );
2006-10-31 08:56:34 +01:00
}
2006-04-23 16:40:31 +02:00
if ( $query [ 'cat_id' ])
{
2016-02-17 20:56:54 +01:00
$header [] = lang ( 'Category' ) . ' ' . $GLOBALS [ 'egw' ] -> categories -> id2name ( $query [ 'cat_id' ]);
2006-04-23 16:40:31 +02:00
}
2006-10-31 08:56:34 +01:00
if ( $query [ 'searchletter' ])
2006-04-23 16:40:31 +02:00
{
2006-12-11 08:35:49 +01:00
$order = $order == 'n_given' ? lang ( 'first name' ) : ( $order == 'n_family' ? lang ( 'last name' ) : lang ( 'Organisation' ));
2016-02-17 20:56:54 +01:00
$header [] = lang ( " %1 starts with '%2' " , $order , $query [ 'searchletter' ]);
2006-04-23 16:40:31 +02:00
}
2011-03-30 15:31:09 +02:00
if ( $query [ 'search' ] && ! $query [ 'advanced_search' ]) // do not add that, if we have advanced search active
2006-04-23 16:40:31 +02:00
{
2016-02-17 20:56:54 +01:00
$header [] = lang ( " Search for '%1' " , $query [ 'search' ]);
2006-04-23 16:40:31 +02:00
}
2016-02-17 20:56:54 +01:00
$GLOBALS [ 'egw_info' ][ 'flags' ][ 'app_header' ] = implode ( ': ' , $header );
2020-10-16 21:34:26 +02:00
if ( $query [ 'grouped_view' ] === '' && $query [ 'col_filter' ][ 'shared_by' ] == $this -> user )
{
$query [ 'grouped_view' ] = 'shared_by_me' ;
unset ( $query [ 'col_filter' ][ 'shared_by' ]);
}
2006-10-31 08:56:34 +01:00
return $this -> total ;
2006-04-23 16:40:31 +02:00
}
/**
* Get addressbook type icon from owner , private and tid
*
2016-04-29 12:41:53 +02:00
* @ param int $owner user - or group - id or 0 for Api\Accounts
2008-04-18 08:10:31 +02:00
* @ param boolean $private
2006-04-23 16:40:31 +02:00
* @ param string $tid 'n' for regular addressbook
* @ param string & $icon icon - name
* @ param string & $label translated label
*/
function type_icon ( $owner , $private , $tid , & $icon , & $label )
{
if ( ! $owner )
{
$icon = 'accounts' ;
$label = lang ( 'accounts' );
}
2007-06-03 13:42:39 +02:00
elseif ( $private )
2006-04-23 16:40:31 +02:00
{
$icon = 'private' ;
$label = lang ( 'private' );
}
elseif ( $GLOBALS [ 'egw' ] -> accounts -> get_type ( $owner ) == 'g' )
{
$icon = 'group' ;
$label = lang ( 'group %1' , $GLOBALS [ 'egw' ] -> accounts -> id2name ( $owner ));
}
else
{
$icon = 'personal' ;
2016-04-29 12:41:53 +02:00
$label = $owner == $this -> user ? lang ( 'personal' ) : Api\Accounts :: username ( $owner );
2008-04-18 08:10:31 +02:00
}
2008-10-20 21:35:18 +02:00
// show tid icon for tid!='n' AND only if one is defined
2016-04-29 12:41:53 +02:00
if ( $tid != 'n' && Api\Image :: find ( 'addressbook' , $this -> content_types [ $tid ][ 'name' ]))
2014-11-19 23:06:30 +01:00
{
2016-04-29 12:41:53 +02:00
$icon = Api\Image :: find ( 'addressbook' , $this -> content_types [ $tid ][ 'name' ]);
2014-11-19 23:06:30 +01:00
}
2015-02-04 11:30:59 +01:00
2014-11-19 23:06:30 +01:00
// Legacy - from when icons could be anywhere
2008-10-20 21:35:18 +02:00
if ( $tid != 'n' && $this -> content_types [ $tid ][ 'options' ][ 'icon' ])
{
$icon = $this -> content_types [ $tid ][ 'options' ][ 'icon' ];
$label = $this -> content_types [ $tid ][ 'name' ] . ' (' . $label . ')' ;
}
2006-04-23 16:40:31 +02:00
}
2005-11-11 21:50:12 +01:00
/**
2008-04-18 08:10:31 +02:00
* Edit a contact
2005-11-11 21:50:12 +01:00
*
2005-11-13 18:51:41 +01:00
* @ param array $content = null submitted content
2009-11-13 09:01:28 +01:00
* @ param int $_GET [ 'contact_id' ] contact_id mainly for popup use
* @ param bool $_GET [ 'makecp' ] true if you want to copy the contact given by $_GET [ 'contact_id' ]
2005-11-11 21:50:12 +01:00
*/
2005-11-13 18:51:41 +01:00
function edit ( $content = null )
2005-11-04 00:47:52 +01:00
{
if ( is_array ( $content ))
{
2020-10-13 16:54:35 +02:00
// sync $content['shared'] with $content['shared_values']
2021-04-05 19:25:57 +02:00
foreach (( array ) $content [ 'shared' ] as $key => $shared )
2020-10-13 16:54:35 +02:00
{
$shared_value = $shared [ 'shared_id' ] . ':' . $shared [ 'shared_with' ] . ':' . $shared [ 'shared_by' ] . ':' . $shared [ 'shared_writable' ];
2020-11-04 14:37:29 +01:00
if (( $k = array_search ( $shared_value , ( array ) $content [ 'shared_values' ])) === false )
2020-10-13 16:54:35 +02:00
{
unset ( $content [ 'shared' ][ $key ]);
}
else
{
unset ( $content [ 'shared_values' ][ $k ]);
}
}
2020-11-04 14:37:29 +01:00
foreach (( array ) $content [ 'shared_values' ] as $account_id )
2020-10-13 16:54:35 +02:00
{
$content [ 'shared' ][] = [
2020-11-04 14:37:29 +01:00
'contact_id' => $content [ 'id' ],
'contact' => $content ,
2020-10-13 16:54:35 +02:00
'shared_with' => $account_id ,
'shared_by' => $this -> user ,
'shared_at' => new Api\DateTime (),
'shared_writable' => ( int )( bool ) $content [ 'shared_writable' ],
];
}
unset ( $content [ 'shared_values' ]);
2020-10-15 13:03:14 +02:00
// remove invalid shared-with entries (should not happen, as we validate already on client-side)
$this -> check_shared_with ( $content [ 'shared' ]);
2020-10-13 16:54:35 +02:00
2021-10-06 16:07:47 +02:00
$button = @ key ( $content [ 'button' ] ? ? []);
2006-04-23 16:40:31 +02:00
unset ( $content [ 'button' ]);
$content [ 'private' ] = ( int ) ( $content [ 'owner' ] && substr ( $content [ 'owner' ], - 1 ) == 'p' );
$content [ 'owner' ] = ( string ) ( int ) $content [ 'owner' ];
2013-07-31 10:13:20 +02:00
$content [ 'cat_id' ] = $this -> config [ 'cat_tab' ] === 'Tree' ? $content [ 'cat_id_tree' ] : $content [ 'cat_id' ];
2014-06-02 15:35:59 +02:00
if ( $this -> config [ 'private_cf_tab' ]) $content = ( array ) $content [ 'private_cfs' ] + $content ;
2013-06-04 01:10:23 +02:00
unset ( $content [ 'private_cfs' ]);
2006-04-23 16:40:31 +02:00
2005-11-13 18:51:41 +01:00
switch ( $button )
2005-11-04 00:47:52 +01:00
{
2005-11-13 18:51:41 +01:00
case 'save' :
case 'apply' :
2014-10-13 15:33:10 +02:00
if ( $content [ 'presets_fields' ])
{
// unset the duplicate_filed after submit because we don't need to warn user for second time about contact duplication
unset ( $content [ 'presets_fields' ]);
}
2017-11-29 09:25:08 +01:00
// photo might be changed by ajax_upload_photo
if ( ! array_key_exists ( 'jpegphoto' , $content ))
2014-03-21 18:12:32 +01:00
{
2017-11-29 09:25:08 +01:00
$content [ 'photo_unchanged' ] = true ; // hint no need to store photo
2014-03-21 18:12:32 +01:00
}
2005-11-13 19:22:43 +01:00
$links = false ;
if ( ! $content [ 'id' ] && is_array ( $content [ 'link_to' ][ 'to_id' ]))
{
$links = $content [ 'link_to' ][ 'to_id' ];
}
2010-03-08 12:14:49 +01:00
$fullname = $old_fullname = parent :: fullname ( $content );
2006-04-30 11:34:24 +02:00
if ( $content [ 'id' ] && $content [ 'org_name' ] && $content [ 'change_org' ])
{
$old_org_entry = $this -> read ( $content [ 'id' ]);
2010-03-08 12:14:49 +01:00
$old_fullname = ( $old_org_entry [ 'n_fn' ] ? $old_org_entry [ 'n_fn' ] : parent :: fullname ( $old_org_entry ));
2006-04-30 11:34:24 +02:00
}
2010-11-04 21:40:33 +01:00
if ( $content [ 'n_fn' ] != $fullname || $fullname != $old_fullname )
2010-03-05 09:28:25 +01:00
{
unset ( $content [ 'n_fn' ]);
}
2010-09-28 01:02:32 +02:00
// Country codes
foreach ( array ( 'adr_one' , 'adr_two' ) as $c_prefix )
{
if ( $content [ $c_prefix . '_countrycode' ] == '-custom-' )
{
$content [ $c_prefix . '_countrycode' ] = null ;
}
}
2014-03-18 16:10:57 +01:00
$content [ 'msg' ] = '' ;
$this -> error = false ;
foreach (( array ) $content [ 'pre_save_callbacks' ] as $callback )
2006-04-30 11:34:24 +02:00
{
2014-03-18 16:10:57 +01:00
try {
if (( $success_msg = call_user_func_array ( $callback , array ( & $content ))))
{
$content [ 'msg' ] .= ( $content [ 'msg' ] ? ', ' : '' ) . $success_msg ;
}
}
catch ( Exception $ex ) {
$content [ 'msg' ] .= ( $content [ 'msg' ] ? ', ' : '' ) . $ex -> getMessage ();
$button = 'apply' ; // do not close dialog
$this -> error = true ;
break ;
}
}
if ( $this -> error )
{
// error in pre_save_callbacks
}
elseif ( $this -> save ( $content ))
{
$content [ 'msg' ] .= ( $content [ 'msg' ] ? ', ' : '' ) . lang ( 'Contact saved' );
2017-11-29 09:25:08 +01:00
unset ( $content [ 'jpegphoto' ], $content [ 'photo_unchanged' ]);
2014-03-18 16:10:57 +01:00
foreach (( array ) $content [ 'post_save_callbacks' ] as $callback )
{
try {
if (( $success_msg = call_user_func_array ( $callback , array ( & $content ))))
{
$content [ 'msg' ] .= ', ' . $success_msg ;
}
}
2016-04-29 12:41:53 +02:00
catch ( Api\Exception\Redirect $r )
2014-10-15 16:55:08 +02:00
{
// catch it to continue execution and rethrow it later
}
2014-03-18 16:10:57 +01:00
catch ( Exception $ex ) {
$content [ 'msg' ] .= ', ' . $ex -> getMessage ();
$button = 'apply' ; // do not close dialog
$this -> error = true ;
break ;
}
}
2006-04-30 11:34:24 +02:00
if ( $content [ 'change_org' ] && $old_org_entry && ( $changed = $this -> changed_fields ( $old_org_entry , $content , true )) &&
( $members = $this -> org_similar ( $old_org_entry [ 'org_name' ], $changed )))
{
//foreach($changed as $name => $old_value) echo "<p>$name: '$old_value' --> '{$content[$name]}'</p>\n";
list ( $changed_members , $changed_fields , $failed_members ) = $this -> change_org ( $old_org_entry [ 'org_name' ], $changed , $content , $members );
if ( $changed_members )
{
$content [ 'msg' ] .= ', ' . lang ( '%1 fields in %2 other organisation member(s) changed' , $changed_fields , $changed_members );
}
if ( $failed_members )
{
$content [ 'msg' ] .= ', ' . lang ( 'failed to change %1 organisation member(s) (insufficent rights) !!!' , $failed_members );
}
}
}
2008-04-25 21:06:15 +02:00
elseif ( $this -> error === true )
{
$content [ 'msg' ] = lang ( 'Error: the entry has been updated since you opened it for editing!' ) . '<br />' .
lang ( 'Copy your changes to the clipboard, %1reload the entry%2 and merge them.' , '<a href="' .
2016-04-29 12:41:53 +02:00
htmlspecialchars ( Egw :: link ( '/index.php' , array (
2008-05-10 14:02:49 +02:00
'menuaction' => 'addressbook.addressbook_ui.edit' ,
2008-04-25 21:06:15 +02:00
'contact_id' => $content [ 'id' ],
))) . '">' , '</a>' );
break ; // dont refresh the list
}
2006-04-30 11:34:24 +02:00
else
{
2006-06-13 23:53:00 +02:00
$content [ 'msg' ] = lang ( 'Error saving the contact !!!' ) .
( $this -> error ? ' ' . $this -> error : '' );
2006-04-30 11:34:24 +02:00
$button = 'apply' ; // to not leave the dialog
}
2005-11-13 19:22:43 +01:00
// writing links for new entry, existing ones are handled by the widget itself
2008-04-18 08:10:31 +02:00
if ( $links && $content [ 'id' ])
2005-11-13 19:22:43 +01:00
{
2016-04-29 12:41:53 +02:00
Link :: link ( 'addressbook' , $content [ 'id' ], $links );
2005-11-13 19:22:43 +01:00
}
2016-04-11 22:38:12 +02:00
// Update client side global datastore
2016-04-29 12:41:53 +02:00
$response = Api\Json\Response :: get ();
2016-04-11 22:38:12 +02:00
$response -> generic ( 'data' , array ( 'uid' => 'addressbook::' . $content [ 'id' ], 'data' => $content ));
2016-04-29 12:41:53 +02:00
Framework :: refresh_opener ( $content [ 'msg' ], 'addressbook' , $content [ 'id' ], $content [ 'id' ] ? 'edit' : 'add' ,
2014-03-18 16:10:57 +01:00
null , null , null , $this -> error ? 'error' : 'success' );
2014-10-15 16:55:08 +02:00
// re-throw redirect exception, if there's no error
if ( ! $this -> error && isset ( $r ))
{
throw $r ;
}
2005-11-13 19:22:43 +01:00
if ( $button == 'save' )
{
2016-04-29 12:41:53 +02:00
Framework :: window_close ();
2005-11-13 19:22:43 +01:00
}
2014-03-18 16:10:57 +01:00
else
{
2016-04-29 12:41:53 +02:00
Framework :: message ( $content [ 'msg' ], $this -> error ? 'error' : 'success' );
2014-03-18 16:10:57 +01:00
unset ( $content [ 'msg' ]);
}
2005-11-23 18:07:33 +01:00
$content [ 'link_to' ][ 'to_id' ] = $content [ 'id' ];
2005-11-13 18:51:41 +01:00
break ;
2008-04-18 08:10:31 +02:00
2005-11-13 18:51:41 +01:00
case 'delete' :
2016-04-29 12:41:53 +02:00
$success = $failed = $action_msg = null ;
2008-04-26 10:47:26 +02:00
if ( $this -> action ( 'delete' , array ( $content [ 'id' ]), false , $success , $failed , $action_msg , '' , $content [ 'msg' ]))
2005-11-13 18:51:41 +01:00
{
2013-09-20 12:50:48 +02:00
if ( $GLOBALS [ 'egw' ] -> currentapp == 'addressbook' )
{
2016-04-29 12:41:53 +02:00
Framework :: refresh_opener ( lang ( 'Contact deleted' ), 'addressbook' , $content [ 'id' ], 'delete' );
Framework :: window_close ();
2013-09-20 12:50:48 +02:00
}
else
{
2016-04-29 12:41:53 +02:00
Framework :: refresh_opener ( lang ( 'Contact deleted' ), 'addressbook' , $content [ 'id' ], null , 'addressbook' );
Framework :: window_close ();
2013-09-20 12:50:48 +02:00
}
2005-11-13 18:51:41 +01:00
}
2006-04-30 11:34:24 +02:00
else
{
$content [ 'msg' ] = lang ( 'Error deleting the contact !!!' );
}
2005-11-13 18:51:41 +01:00
break ;
2005-11-04 00:47:52 +01:00
}
2016-04-29 12:41:53 +02:00
$view = ! $this -> check_perms ( Acl :: EDIT , $content );
2005-11-04 00:47:52 +01:00
}
else
{
$content = array ();
2006-04-23 16:40:31 +02:00
$contact_id = $_GET [ 'contact_id' ] ? $_GET [ 'contact_id' ] : (( int ) $_GET [ 'account_id' ] ? 'account:' . ( int ) $_GET [ 'account_id' ] : 0 );
2015-05-27 07:31:16 +02:00
$view = ( boolean ) $_GET [ 'view' ];
2006-04-23 16:40:31 +02:00
// new contact --> set some defaults
if ( $contact_id && is_array ( $content = $this -> read ( $contact_id )))
2005-11-04 00:47:52 +01:00
{
2006-04-23 16:40:31 +02:00
$contact_id = $content [ 'id' ]; // it could have been: "account:$account_id"
2016-04-29 12:41:53 +02:00
if ( ! $this -> check_perms ( Acl :: EDIT , $content ))
2014-03-12 14:29:52 +01:00
{
$view = true ;
}
2005-11-04 00:47:52 +01:00
}
2006-04-23 16:40:31 +02:00
else // not found
2005-12-01 18:21:38 +01:00
{
2016-04-29 12:41:53 +02:00
$state = Api\Cache :: getSession ( 'addressbook' , 'index' );
2006-04-30 11:34:24 +02:00
// check if we create the new contact in an existing org
2012-07-17 14:15:10 +02:00
if (( $org = $_GET [ 'org' ]))
2006-04-30 11:34:24 +02:00
{
2012-07-17 14:15:10 +02:00
// arguments containing a comma get quoted by etemplate/js/nextmatch_action.js
2016-04-29 12:41:53 +02:00
// leading to error in Api\Db::column_data_implode, if not unquoted
2012-07-17 14:15:10 +02:00
if ( $org [ 0 ] == '"' ) $org = substr ( $org , 1 , - 1 );
$content = $this -> read_org ( $org );
2006-04-30 11:34:24 +02:00
}
2017-03-13 19:11:37 +01:00
elseif ( $state [ 'grouped_view' ] && ! isset ( $this -> grouped_views [ $state [ 'grouped_view' ]]))
2006-04-30 11:34:24 +02:00
{
2017-03-13 19:11:37 +01:00
$content = $this -> read_org ( $state [ 'grouped_view' ]);
2006-04-30 11:34:24 +02:00
}
2008-10-10 13:25:35 +02:00
else
2006-12-04 13:41:03 +01:00
{
2008-10-10 13:25:35 +02:00
if ( $GLOBALS [ 'egw_info' ][ 'user' ][ 'preferences' ][ 'common' ][ 'country' ])
{
2011-03-07 18:25:54 +01:00
$content [ 'adr_one_countrycode' ] =
$GLOBALS [ 'egw_info' ][ 'user' ][ 'preferences' ][ 'common' ][ 'country' ];
2011-03-07 18:27:53 +01:00
$content [ 'adr_one_countryname' ] =
$GLOBALS [ 'egw' ] -> country -> get_full_name ( $GLOBALS [ 'egw_info' ][ 'user' ][ 'preferences' ][ 'common' ][ 'country' ]);
2013-08-16 16:49:08 +02:00
$content [ 'adr_two_countrycode' ] =
$GLOBALS [ 'egw_info' ][ 'user' ][ 'preferences' ][ 'common' ][ 'country' ];
$content [ 'adr_two_countryname' ] =
$GLOBALS [ 'egw' ] -> country -> get_full_name ( $GLOBALS [ 'egw_info' ][ 'user' ][ 'preferences' ][ 'common' ][ 'country' ]);
2008-10-10 13:25:35 +02:00
}
if ( $this -> prefs [ 'fileas_default' ]) $content [ 'fileas_type' ] = $this -> prefs [ 'fileas_default' ];
2006-12-04 13:41:03 +01:00
}
2006-04-23 16:40:31 +02:00
if ( isset ( $_GET [ 'owner' ]) && $_GET [ 'owner' ] !== '' )
{
$content [ 'owner' ] = $_GET [ 'owner' ];
}
else
{
2017-12-20 15:50:24 +01:00
$content [ 'owner' ] = ( string )( $state [ 'filter' ] == 0 ? '' : $state [ 'filter' ]);
2006-04-23 16:40:31 +02:00
}
$content [ 'private' ] = ( int ) ( $content [ 'owner' ] && substr ( $content [ 'owner' ], - 1 ) == 'p' );
2017-12-20 15:20:48 +01:00
if ( $content [ 'owner' ] === '' || ! ( $this -> grants [ $content [ 'owner' ] = ( string ) ( int ) $content [ 'owner' ]] & Acl :: ADD ))
2006-04-23 16:40:31 +02:00
{
2007-12-15 00:20:18 +01:00
$content [ 'owner' ] = $this -> default_addressbook ;
$content [ 'private' ] = ( int ) $this -> default_private ;
2006-10-07 11:17:30 +02:00
2016-04-29 12:41:53 +02:00
if ( ! ( $this -> grants [ $content [ 'owner' ] = ( string ) ( int ) $content [ 'owner' ]] & Acl :: ADD ))
2006-10-07 11:17:30 +02:00
{
$content [ 'owner' ] = ( string ) $this -> user ;
$content [ 'private' ] = 0 ;
}
2006-04-23 16:40:31 +02:00
}
2006-03-14 15:26:55 +01:00
$new_type = array_keys ( $this -> content_types );
2011-11-09 10:06:27 +01:00
// fetch active type to preset the type, if param typeid is not passed
2016-04-29 12:41:53 +02:00
$active_tid = Api\Cache :: getSession ( 'addressbook' , 'active_tid' );
2011-11-09 10:06:27 +01:00
if ( $active_tid && strtoupper ( $active_tid ) === 'D' ) unset ( $active_tid );
$content [ 'tid' ] = $_GET [ 'typeid' ] ? $_GET [ 'typeid' ] : ( $active_tid ? $active_tid : $new_type [ 0 ]);
2006-08-24 18:06:45 +02:00
foreach ( $this -> get_contact_columns () as $field )
2005-12-01 18:21:38 +01:00
{
2014-04-17 10:55:21 +02:00
if ( $_GET [ 'presets' ][ $field ])
{
if ( $field == 'email' || $field == 'email_home' )
{
$singleAddress = imap_rfc822_parse_adrlist ( $_GET [ 'presets' ][ $field ], '' );
//error_log(__METHOD__.__LINE__.' Address:'.$singleAddress[0]->mailbox."@".$singleAddress[0]->host.", ".$singleAddress[0]->personal);
if ( ! ( ! is_array ( $singleAddress ) || count ( $singleAddress ) < 1 ))
{
$content [ $field ] = $singleAddress [ 0 ] -> mailbox . " @ " . $singleAddress [ 0 ] -> host ;
if ( ! empty ( $singleAddress [ 0 ] -> personal ))
{
if ( strpos ( $singleAddress [ 0 ] -> personal , ',' ) === false )
{
list ( $P_n_given , $P_n_family , $P_org_name ) = explode ( ' ' , $singleAddress [ 0 ] -> personal , 3 );
if ( strlen ( trim ( $P_n_given )) > 0 ) $content [ 'n_given' ] = trim ( $P_n_given );
if ( strlen ( trim ( $P_n_family )) > 0 ) $content [ 'n_family' ] = trim ( $P_n_family );
if ( strlen ( trim ( $P_org_name )) > 0 ) $content [ 'org_name' ] = trim ( $P_org_name );
}
else
{
list ( $P_n_family , $P_other ) = explode ( ',' , $singleAddress [ 0 ] -> personal , 2 );
if ( strlen ( trim ( $P_n_family )) > 0 ) $content [ 'n_family' ] = trim ( $P_n_family );
if ( strlen ( trim ( $P_other )) > 0 )
{
list ( $P_n_given , $P_org_name ) = explode ( ',' , $P_other , 2 );
if ( strlen ( trim ( $P_n_given )) > 0 ) $content [ 'n_given' ] = trim ( $P_n_given );
if ( strlen ( trim ( $P_org_name )) > 0 ) $content [ 'org_name' ] = trim ( $P_org_name );
}
}
}
}
else
{
$content [ $field ] = $_GET [ 'presets' ][ $field ];
}
}
else
{
$content [ $field ] = $_GET [ 'presets' ][ $field ];
}
}
2012-10-24 16:22:24 +02:00
}
if ( isset ( $_GET [ 'presets' ]))
{
foreach ( array ( 'email' , 'email_home' , 'n_family' , 'n_given' , 'org_name' ) as $field )
2012-10-24 12:14:09 +02:00
{
2012-10-24 16:22:24 +02:00
if ( ! empty ( $content [ $field ]))
2012-10-24 12:14:09 +02:00
{
2014-10-13 15:33:10 +02:00
//Set the presets fields in content in order to be able to use them later in client side for checking duplication only on first time load
// after save/apply we unset them
$content [ 'presets_fields' ][] = $field ;
2012-10-24 16:22:24 +02:00
break ;
2012-10-24 12:14:09 +02:00
}
}
2014-04-17 10:55:21 +02:00
if ( empty ( $content [ 'n_fn' ])) $content [ 'n_fn' ] = $this -> fullname ( $content );
2005-12-01 18:21:38 +01:00
}
2006-04-23 16:40:31 +02:00
$content [ 'creator' ] = $this -> user ;
$content [ 'created' ] = $this -> now_su ;
2006-04-30 11:34:24 +02:00
unset ( $state );
2014-04-17 10:55:21 +02:00
//_debug_array($content);
2005-12-01 18:21:38 +01:00
}
2011-01-13 13:09:06 +01:00
2010-02-05 04:34:17 +01:00
if ( $_GET [ 'msg' ]) $content [ 'msg' ] = strip_tags ( $_GET [ 'msg' ]); // dont allow HTML!
2005-11-23 18:07:33 +01:00
if ( $content && $_GET [ 'makecp' ]) // copy the contact
{
2015-12-15 23:38:22 +01:00
$this -> copy_contact ( $content );
2016-11-24 18:30:36 +01:00
$content [ 'msg' ] = lang ( '%1 copied - the copy can now be edited' , lang ( Link :: get_registry ( 'addressbook' , 'entry' )));
2015-08-20 15:05:00 +02:00
$view = false ;
2005-11-23 18:07:33 +01:00
}
else
{
2019-11-04 19:48:40 +01:00
if ( $contact_id && is_numeric ( $contact_id )) $content [ 'link_to' ][ 'to_id' ] = $contact_id ;
2005-11-23 18:07:33 +01:00
}
2006-12-11 08:35:49 +01:00
// automatic link new entries to entries specified in the url
if ( ! $contact_id && isset ( $_REQUEST [ 'link_app' ]) && isset ( $_REQUEST [ 'link_id' ]) && ! is_array ( $content [ 'link_to' ][ 'to_id' ]))
{
$link_ids = is_array ( $_REQUEST [ 'link_id' ]) ? $_REQUEST [ 'link_id' ] : array ( $_REQUEST [ 'link_id' ]);
foreach ( is_array ( $_REQUEST [ 'link_app' ]) ? $_REQUEST [ 'link_app' ] : array ( $_REQUEST [ 'link_app' ]) as $n => $link_app )
{
$link_id = $link_ids [ $n ];
if ( preg_match ( '/^[a-z_0-9-]+:[:a-z_0-9-]+$/i' , $link_app . ':' . $link_id )) // gard against XSS
{
2016-04-29 12:41:53 +02:00
Link :: link ( 'addressbook' , $content [ 'link_to' ][ 'to_id' ], $link_app , $link_id );
2006-12-11 08:35:49 +01:00
}
}
}
2005-11-04 00:47:52 +01:00
}
2020-10-13 16:54:35 +02:00
// set $content[shared_options/_values] from $content[shared]
$content [ 'shared_options' ] = [];
foreach (( array ) $content [ 'shared' ] as $shared )
{
$content [ 'shared_options' ][ $shared [ 'shared_id' ] . ':' . $shared [ 'shared_with' ] . ':' . $shared [ 'shared_by' ] . ':' . $shared [ 'shared_writable' ]] = [
2020-11-20 15:48:22 +01:00
'label' => Api\Accounts :: username ( $shared [ 'shared_with' ]),
2020-10-13 16:54:35 +02:00
'title' => lang ( '%1 shared this contact on %2 with %3 %4' ,
2020-11-20 15:48:22 +01:00
Api\Accounts :: username ( $shared [ 'shared_by' ]), Api\DateTime :: to ( $shared [ 'shared_at' ]),
Api\Accounts :: username ( $shared [ 'shared_with' ]), $shared [ 'shared_writable' ] ? lang ( 'writable' ) : lang ( 'readonly' )),
2020-10-13 16:54:35 +02:00
'icon' => $shared [ 'shared_writable' ] ? 'edit' : 'view' ,
];
}
$content [ 'shared_values' ] = array_keys ( $content [ 'shared_options' ]);
2020-10-15 13:03:14 +02:00
// disable shared with UI for non-SQL backends
$content [ 'shared_disabled' ] = ! is_a ( $this -> get_backend ( $content [ 'id' ], $content [ 'owner' ]), Api\Contacts\Sql :: class );
2020-10-13 16:54:35 +02:00
2007-10-19 10:34:47 +02:00
if ( $content [ 'id' ])
{
// last and next calendar date
2018-12-18 18:20:23 +01:00
$dates = current ( $this -> read_calendar ( array ( $content [ 'account_id' ] ? $content [ 'account_id' ] : 'c' . $content [ 'id' ]), false ));
2007-10-19 10:34:47 +02:00
if ( is_array ( $dates )) $content += $dates ;
}
2017-04-10 18:39:04 +02:00
// Registry has view_id as contact_id, so set it (custom fields uses it)
$content [ 'contact_id' ] = $content [ 'id' ];
2017-09-19 11:38:02 +02:00
2013-02-07 11:51:00 +01:00
// Avoid ID conflict with tree & selectboxes
$content [ 'cat_id_tree' ] = $content [ 'cat_id' ];
2013-06-04 01:10:23 +02:00
// Avoid setting conflicts with private custom fields
2017-04-13 17:25:47 +02:00
$content [ 'private_cfs' ] = array ();
foreach ( Api\Storage\Customfields :: get ( 'addressbook' , true ) as $name => $cf )
2014-06-02 15:35:59 +02:00
{
2017-04-13 17:25:47 +02:00
if ( $this -> config [ 'private_cf_tab' ] && $cf [ 'private' ] && isset ( $content [ '#' . $name ]))
2014-06-02 15:35:59 +02:00
{
2017-04-13 17:25:47 +02:00
$content [ 'private_cfs' ][ '#' . $name ] = $content [ '#' . $name ];
}
2014-06-02 15:35:59 +02:00
}
2017-09-19 11:38:02 +02:00
2007-05-03 10:17:31 +02:00
// how to display addresses
$content [ 'addr_format' ] = $this -> addr_format_by_country ( $content [ 'adr_one_countryname' ]);
$content [ 'addr_format2' ] = $this -> addr_format_by_country ( $content [ 'adr_two_countryname' ]);
2008-04-18 08:10:31 +02:00
2005-11-04 00:47:52 +01:00
//_debug_array($content);
2016-04-29 12:41:53 +02:00
$readonlys [ 'button[delete]' ] = ! $content [ 'owner' ] || ! $this -> check_perms ( Acl :: DELETE , $content );
2005-11-13 18:51:41 +01:00
$readonlys [ 'button[copy]' ] = $readonlys [ 'button[edit]' ] = $readonlys [ 'button[vcard]' ] = true ;
2014-03-12 14:29:52 +01:00
$readonlys [ 'button[save]' ] = $readonlys [ 'button[apply]' ] = $view ;
2015-05-27 07:31:16 +02:00
if ( $view )
{
$readonlys [ '__ALL__' ] = true ;
$readonlys [ 'button[cancel]' ] = false ;
}
2005-11-11 21:50:12 +01:00
2006-04-23 16:40:31 +02:00
$sel_options [ 'fileas_type' ] = $this -> fileas_options ( $content );
2015-04-15 17:57:19 +02:00
$sel_options [ 'adr_one_countrycode' ][ '-custom-' ] = lang ( 'Custom' );
2016-04-29 12:41:53 +02:00
$sel_options [ 'owner' ] = $this -> get_addressbooks ( Acl :: ADD );
2014-08-19 16:12:40 +02:00
if ( $content [ 'owner' ]) unset ( $sel_options [ 'owner' ][ 0 ]); // do not offer to switch to accounts, as we do not support moving contacts to accounts
2006-04-23 16:40:31 +02:00
if (( string ) $content [ 'owner' ] !== '' )
{
if ( ! isset ( $sel_options [ 'owner' ][( int ) $content [ 'owner' ]]))
{
2006-04-25 14:43:41 +02:00
$sel_options [ 'owner' ][( int ) $content [ 'owner' ]] = ! $content [ 'owner' ] ? lang ( 'Accounts' ) :
2016-04-29 12:41:53 +02:00
Api\Accounts :: username ( $content [ 'owner' ]);
2006-04-23 16:40:31 +02:00
}
$readonlys [ 'owner' ] = ! $content [ 'owner' ] || // dont allow to move accounts, as this mean deleting the user incl. all content he owns
2016-04-29 12:41:53 +02:00
$content [ 'id' ] && ! $this -> check_perms ( Acl :: DELETE , $content ); // you need delete rights to move an existing contact into an other addressbook
2006-04-23 16:40:31 +02:00
}
2006-06-13 06:30:16 +02:00
// set the unsupported fields from the backend to readonly
foreach ( $this -> get_fields ( 'unsupported' , $content [ 'id' ], $content [ 'owner' ]) as $field )
{
$readonlys [ $field ] = true ;
}
2015-05-27 07:31:16 +02:00
// for editing own account, make all fields not allowed by own_account_acl readonly
if ( ! $this -> is_admin () && ! $content [ 'owner' ] && $content [ 'account_id' ] == $this -> user && $this -> own_account_acl && ! $view )
{
$readonlys [ '__ALL__' ] = true ;
$readonlys [ 'button[cancel]' ] = false ;
foreach ( $this -> own_account_acl as $field )
{
$readonlys [ $field ] = false ;
}
2016-09-29 16:17:45 +02:00
if ( ! $readonlys [ 'jpegphoto' ])
{
$readonlys = array_merge ( $readonlys , array (
'upload_photo' => false ,
'delete_photo' => false ,
'addressbook.edit.upload' => false
));
}
2018-03-28 18:22:07 +02:00
if ( ! $readonlys [ 'pubkey' ])
{
$readonlys [ 'addressbook:' . $content [ 'id' ] . ':.files/pgp-pubkey.asc' ] =
$readonlys [ 'addressbook:' . $content [ 'id' ] . ':.files/smime-pubkey.crt' ] = false ;
}
2015-05-27 07:31:16 +02:00
}
2018-03-28 18:22:07 +02:00
2015-05-27 07:31:16 +02:00
if ( isset ( $readonlys [ 'n_fileas' ])) $readonlys [ 'fileas_type' ] = $readonlys [ 'n_fileas' ];
2006-12-07 20:11:39 +01:00
// disable not needed tabs
2009-05-11 08:47:38 +02:00
$readonlys [ 'tabs' ][ 'cats' ] = ! ( $content [ 'cat_tab' ] = $this -> config [ 'cat_tab' ]);
2012-02-17 16:00:51 +01:00
$readonlys [ 'tabs' ][ 'custom' ] = ! $this -> customfields || $this -> get_backend ( $content [ 'id' ], $content [ 'owner' ]) == $this -> so_accounts ;
2017-04-19 18:44:13 +02:00
$readonlys [ 'tabs' ][ 'custom_private' ] = $readonlys [ 'tabs' ][ 'custom' ] || ! $this -> config [ 'private_cf_tab' ];
2009-05-11 08:47:38 +02:00
$readonlys [ 'tabs' ][ 'distribution_list' ] = ! $content [ 'distrib_lists' ]; #false;
2013-07-11 17:33:59 +02:00
$readonlys [ 'tabs' ][ 'history' ] = $this -> contact_repository != 'sql' || ! $content [ 'id' ] ||
$this -> account_repository != 'sql' && $content [ 'account_id' ];
2014-02-13 15:07:42 +01:00
if ( ! $content [ 'id' ]) $readonlys [ 'button[delete]' ] = ! $content [ 'id' ];
2008-01-19 06:41:04 +01:00
if ( $this -> config [ 'private_cf_tab' ]) $content [ 'no_private_cfs' ] = 0 ;
2012-05-15 18:52:25 +02:00
$readonlys [ 'change_org' ] = empty ( $content [ 'org_name' ]) || $view ;
2008-04-18 08:10:31 +02:00
2006-12-07 20:11:39 +01:00
// for editing the own account (by a non-admin), enable only the fields allowed via the "own_account_acl"
2016-04-29 12:41:53 +02:00
if ( ! $content [ 'owner' ] && ! $this -> check_perms ( Acl :: EDIT , $content ))
{
$this -> _set_readonlys_for_own_account_acl ( $readonlys , $content [ 'id' ]);
}
for ( $i = - 23 ; $i <= 23 ; $i ++ )
2006-09-15 09:16:07 +02:00
{
2016-04-29 12:41:53 +02:00
$tz [ $i ] = ( $i > 0 ? '+' : '' ) . $i ;
2006-09-15 09:16:07 +02:00
}
2005-11-04 00:47:52 +01:00
$sel_options [ 'tz' ] = $tz ;
2014-01-23 16:49:07 +01:00
$content [ 'tz' ] = $content [ 'tz' ] ? $content [ 'tz' ] : '0' ;
2006-04-30 11:34:24 +02:00
if ( count ( $this -> content_types ) > 1 )
{
foreach ( $this -> content_types as $type => $data )
{
$sel_options [ 'tid' ][ $type ] = $data [ 'name' ];
}
2016-04-29 12:41:53 +02:00
$content [ 'typegfx' ] = Api\Html :: image ( 'addressbook' , $this -> content_types [ $content [ 'tid' ]][ 'options' ][ 'icon' ], '' , ' width="16px" height="16px"' );
2006-04-30 11:34:24 +02:00
}
else
{
$content [ 'no_tid' ] = true ;
}
2006-10-21 22:14:31 +02:00
2013-08-26 09:35:42 +02:00
$content [ 'view' ] = false ;
2005-11-23 18:07:33 +01:00
$content [ 'link_to' ] = array (
2005-11-13 19:22:43 +01:00
'to_app' => 'addressbook' ,
2005-11-23 18:07:33 +01:00
'to_id' => $content [ 'link_to' ][ 'to_id' ],
2005-11-13 19:22:43 +01:00
);
2010-02-08 18:53:47 +01:00
2010-09-27 18:39:54 +02:00
// Links for deleted entries
2016-03-06 14:45:15 +01:00
if ( $content [ 'tid' ] == self :: DELETED_TYPE )
2010-09-27 18:39:54 +02:00
{
$content [ 'link_to' ][ 'show_deleted' ] = true ;
2010-11-22 18:10:11 +01:00
if ( ! $GLOBALS [ 'egw_info' ][ 'user' ][ 'apps' ][ 'admin' ] && $this -> config [ 'history' ] != 'userpurge' )
{
$readonlys [ 'button[delete]' ] = true ;
}
2010-09-27 18:39:54 +02:00
}
2010-02-08 18:53:47 +01:00
// Enable history
$this -> setup_history ( $content , $sel_options );
2018-08-13 11:56:05 +02:00
$content [ 'photo' ] = $this -> photo_src ( $content [ 'id' ], $content [ 'jpegphoto' ], '' , $content [ 'etag' ]);
2006-04-23 16:40:31 +02:00
if ( $content [ 'private' ]) $content [ 'owner' ] .= 'p' ;
2014-10-09 14:03:14 +02:00
// for custom types, check if we have a custom edit template named "addressbook.edit.$type", $type is the name
if ( in_array ( $content [ 'tid' ], array ( 'n' , self :: DELETED_TYPE )) || ! $this -> tmpl -> read ( 'addressbook.edit.' . $this -> content_types [ $content [ 'tid' ]][ 'name' ]))
2007-06-17 15:15:13 +02:00
{
$this -> tmpl -> read ( 'addressbook.edit' );
}
2014-03-17 16:28:20 +01:00
// allow other apps to add tabs to addressbook edit
$preserve = $content ;
2019-04-04 23:20:13 +02:00
$preserve [ 'old_owner' ] = $content [ 'owner' ];
2019-02-20 17:07:28 +01:00
unset ( $preserve [ 'jpegphoto' ], $content [ 'jpegphoto' ]); // unused and messes up json encoding (not utf-8)
2014-03-17 16:28:20 +01:00
$this -> tmpl -> setElementAttribute ( 'tabs' , 'add_tabs' , true );
$tabs =& $this -> tmpl -> getElementAttribute ( 'tabs' , 'tabs' );
2014-09-06 12:00:42 +02:00
if (( $first_call = ! isset ( $tabs )))
{
$tabs = array ();
}
//error_log(__LINE__.': '.__METHOD__."() first_call=$first_call");
2016-04-29 12:41:53 +02:00
$hook_data = Api\Hooks :: process ( array ( 'location' => 'addressbook_edit' ) + $content );
2014-03-17 16:28:20 +01:00
//error_log(__METHOD__."() hook_data=".array2string($hook_data));
foreach ( $hook_data as $extra_tabs )
{
if ( ! $extra_tabs ) continue ;
foreach ( isset ( $extra_tabs [ 0 ]) ? $extra_tabs : array ( $extra_tabs ) as $extra_tab )
{
if ( $extra_tab [ 'data' ] && is_array ( $extra_tab [ 'data' ]))
{
$content = array_merge ( $content , $extra_tab [ 'data' ]);
}
if ( $extra_tab [ 'preserve' ] && is_array ( $extra_tab [ 'preserve' ]))
{
$preserve = array_merge ( $preserve , $extra_tab [ 'preserve' ]);
}
if ( $extra_tab [ 'readonlys' ] && is_array ( $extra_tab [ 'readonlys' ]))
{
$readonlys = array_merge ( $readonlys , $extra_tab [ 'readonlys' ]);
}
2014-09-06 12:00:42 +02:00
// we must NOT add tabs and callbacks more then once!
if ( ! $first_call ) continue ;
2014-03-18 16:10:57 +01:00
if ( ! empty ( $extra_tab [ 'pre_save_callback' ]))
{
$preserve [ 'pre_save_callbacks' ][] = $extra_tab [ 'pre_save_callback' ];
}
if ( ! empty ( $extra_tab [ 'post_save_callback' ]))
{
$preserve [ 'post_save_callbacks' ][] = $extra_tab [ 'post_save_callback' ];
}
2014-09-06 12:00:42 +02:00
if ( ! empty ( $extra_tab [ 'label' ]) && ! empty ( $extra_tab [ 'name' ]))
{
$tabs [] = array (
'label' => $extra_tab [ 'label' ],
'template' => $extra_tab [ 'name' ],
'prepend' => $extra_tab [ 'prepend' ],
);
}
//error_log(__METHOD__."() changed tabs=".array2string($tabs));
2014-03-17 16:28:20 +01:00
}
}
return $this -> tmpl -> exec ( 'addressbook.addressbook_ui.edit' , $content , $sel_options , $readonlys , $preserve , 2 );
2005-11-11 21:50:12 +01:00
}
2008-04-18 08:10:31 +02:00
2020-10-15 13:03:14 +02:00
/**
* Check if user has right to share with / into given AB
*
2020-10-26 10:44:40 +01:00
* @ param array $_data values for keys " shared_writable " , " shared_values " and " contact "
2020-10-15 13:03:14 +02:00
* @ return array of entries removed from $shared_with because current user is not allowed to share into
*/
public function ajax_check_shared ( array $_data )
{
$response = Api\Json\Response :: get ();
try {
$shared = [];
foreach ( $_data [ 'shared_values' ] as $value )
{
if ( is_numeric ( $value ))
{
$shared [ $value ] = [
'shared_with' => $value ,
'shared_by' => $this -> user ,
'shared_writable' => ( int ) $_data [ 'shared_writable' ],
];
}
else
{
$shared [ $value ] = array_combine ([ 'shared_id' , 'shared_with' , 'shared_by' , 'shared_writable' ], explode ( ':' , $value ));
}
2020-10-26 10:44:40 +01:00
$shared [ $value ][ 'contact' ] = $_data [ 'contact' ];
2020-10-15 13:03:14 +02:00
}
2020-10-26 10:44:40 +01:00
if (( $failed = $this -> check_shared_with ( $shared , $error )))
2020-10-15 13:03:14 +02:00
{
$response -> data ( array_keys ( $failed ));
2020-10-26 10:44:40 +01:00
$response -> message ( $error ? : lang ( 'You are not allowed to share into the addressbook of %1' ,
2020-10-15 13:03:14 +02:00
implode ( ', ' , array_map ( function ( $data ) {
return Api\Accounts :: username ( $data [ 'shared_with' ]);
}, $failed ))), 'error' );
}
}
catch ( \Exception $e ) {
$response -> message ( $e -> getMessage (), 'error' );
}
}
2007-06-03 14:24:49 +02:00
/**
* Set the readonlys for non - admins editing their own account
*
* @ param array & $readonlys
* @ param int $id
*/
function _set_readonlys_for_own_account_acl ( & $readonlys , $id )
{
// regular fields depending on the backend
foreach ( $this -> get_fields ( 'supported' , $id , 0 ) as $field )
{
if ( ! $this -> own_account_acl || ! in_array ( $field , $this -> own_account_acl ))
{
$readonlys [ $field ] = true ;
switch ( $field )
{
2008-04-18 08:10:31 +02:00
case 'tel_work' :
case 'tel_cell' :
case 'tel_home' :
2007-06-03 14:24:49 +02:00
$readonlys [ $field . '2' ] = true ;
break ;
case 'n_fileas' :
$readonlys [ 'fileas_type' ] = true ;
break ;
}
}
}
// custom fields
if ( $this -> customfields )
{
2016-04-29 12:41:53 +02:00
foreach ( array_keys ( $this -> customfields ) as $name )
2007-06-03 14:24:49 +02:00
{
if ( ! $this -> own_account_acl || ! in_array ( '#' . $name , $this -> own_account_acl ))
{
$readonlys [ '#' . $name ] = true ;
}
}
}
// links
if ( ! $this -> own_account_acl || ! in_array ( 'link_to' , $this -> own_account_acl ))
{
$readonlys [ 'link_to' ] = true ;
}
}
2008-04-18 08:10:31 +02:00
2012-09-06 14:26:11 +02:00
/**
* Doublicate check : returns similar contacts : same email or 2 of name , firstname , org
*
* Also update / return fileas options , if necessary .
*
* @ param array $values contact values from form
* @ param string $name name of changed value , eg . " email "
2016-04-29 12:41:53 +02:00
* @ param int $own_id = 0 own contact id , to not check against it
2012-09-06 14:26:11 +02:00
* @ return array with keys 'msg' => " EMail address exists, do you want to open contact? " ( or null if not existing )
* 'data' => array of id => " full name (addressbook) " pairs
* 'fileas_options'
*/
public function ajax_check_values ( $values , $name , $own_id = 0 )
2006-04-23 16:40:31 +02:00
{
2021-11-10 11:38:06 +01:00
if ( ! is_array ( $fields = $GLOBALS [ 'egw_info' ][ 'user' ][ 'preferences' ][ 'addressbook' ][ 'duplicate_fields' ] ? ? []))
{
$fields = explode ( ',' , $fields );
}
2018-02-07 18:17:27 +01:00
$threshold = ( int ) $GLOBALS [ 'egw_info' ][ 'user' ][ 'preferences' ][ 'addressbook' ][ 'duplicate_threshold' ];
2017-03-13 19:11:37 +01:00
2012-09-06 14:26:11 +02:00
$ret = array ( 'doublicates' => array (), 'msg' => null );
2022-03-29 09:16:24 +02:00
// set not returned n_fileas value, to keep custom fileas value
$values [ 'n_fileas' ] = $this -> fileas ( $values , $values [ 'fileas_type' ]);
2012-09-06 14:26:11 +02:00
// if email changed, check for doublicates
2018-02-12 17:05:37 +01:00
if ( in_array ( $name , array ( 'email' , 'email_home' )) && in_array ( 'contact_' . $name , $fields ))
2012-09-06 14:26:11 +02:00
{
2016-06-20 10:03:03 +02:00
if ( preg_match ( Etemplate\Widget\Url :: EMAIL_PREG , $values [ $name ])) // only search for real email addresses, to not return to many contacts
2012-09-06 14:26:11 +02:00
{
$contacts = parent :: search ( array (
'email' => $values [ $name ],
'email_home' => $values [ $name ],
2016-04-29 12:41:53 +02:00
), false , '' , '' , '' , false , 'OR' );
2012-09-06 14:26:11 +02:00
}
}
else
{
// only set fileas-options if other then email changed
$ret [ 'fileas_options' ] = array_values ( $this -> fileas_options ( $values ));
2013-06-19 21:02:41 +02:00
// Full options for et2
$ret [ 'fileas_sel_options' ] = $this -> fileas_options ( $values );
2012-09-06 14:26:11 +02:00
2017-03-13 19:11:37 +01:00
// if name, firstname or org changed and enough are specified, check for doublicates
$specified_count = 0 ;
foreach ( $fields as $field )
{
2018-01-24 17:10:45 +01:00
if ( $values [ trim ( $field )])
2017-03-13 19:11:37 +01:00
{
$specified_count ++ ;
}
}
2018-02-07 18:17:27 +01:00
if ( in_array ( $name , $fields ) && $specified_count >= $threshold )
2012-09-06 14:26:11 +02:00
{
$filter = array ();
2017-03-13 19:11:37 +01:00
foreach ( $fields as $n ) // use email too, to exclude obvious false positives
2012-09-06 14:26:11 +02:00
{
if ( ! empty ( $values [ $n ])) $filter [ $n ] = $values [ $n ];
}
2016-04-29 12:41:53 +02:00
$contacts = parent :: search ( '' , false , '' , '' , '' , false , 'AND' , false , $filter );
2012-09-06 14:26:11 +02:00
}
}
if ( $contacts )
{
foreach ( $contacts as $contact )
{
if ( $own_id && $contact [ 'id' ] == $own_id ) continue ;
$ret [ 'doublicates' ][ $contact [ 'id' ]] = $this -> fileas ( $contact ) . ' (' .
( ! $contact [ 'owner' ] ? lang ( 'Accounts' ) : ( $contact [ 'owner' ] == $this -> user ?
2016-04-29 12:41:53 +02:00
( $contact [ 'private' ] ? lang ( 'Private' ) : lang ( 'Personal' )) : Api\Accounts :: username ( $contact [ 'owner' ]))) . ')' ;
2012-09-06 14:26:11 +02:00
}
if ( $ret [ 'doublicates' ])
{
$ret [ 'msg' ] = lang ( 'Similar contacts found:' ) .
" \n \n " . implode ( " \n " , $ret [ 'doublicates' ]) . " \n \n " .
lang ( 'Open for editing?' );
}
}
2012-10-24 12:18:13 +02:00
//error_log(__METHOD__.'('.array2string($values).", '$name', $own_id) doublicates found ".array2string($ret['doublicates']));
2016-04-29 12:41:53 +02:00
Api\Json\Response :: get () -> data ( $ret );
2006-04-23 16:40:31 +02:00
}
2008-04-18 08:10:31 +02:00
2014-03-10 22:15:23 +01:00
/**
* CRM view
*
* @ param array $content
*/
function view ( array $content = null )
2005-11-11 21:50:12 +01:00
{
2014-03-25 17:53:36 +01:00
// CRM list comes from content, request, or preference
$crm_list = $content [ 'crm_list' ] ? $content [ 'crm_list' ] :
( $_GET [ 'crm_list' ] ? $_GET [ 'crm_list' ] : $GLOBALS [ 'egw_info' ][ 'user' ][ 'preferences' ][ 'addressbook' ][ 'crm_list' ]);
2014-04-08 16:20:22 +02:00
if ( ! $crm_list || $crm_list == '~edit~' ) $crm_list = 'infolog' ;
2014-03-25 17:53:36 +01:00
2005-11-11 21:50:12 +01:00
if ( is_array ( $content ))
{
2021-10-06 16:07:47 +02:00
$button = key ( $content [ 'button' ] ? ? []);
2020-09-30 13:19:36 +02:00
switch ( $button )
2005-11-11 21:50:12 +01:00
{
2005-11-13 18:51:41 +01:00
case 'vcard' :
2016-04-29 12:41:53 +02:00
Egw :: redirect_link ( '/index.php' , 'menuaction=addressbook.uivcard.out&ab_id=' . $content [ 'id' ]);
2005-11-13 18:51:41 +01:00
case 'cancel' :
2016-04-29 12:41:53 +02:00
Egw :: redirect_link ( '/index.php' , 'menuaction=addressbook.addressbook_ui.index&ajax=true' );
2005-11-13 18:51:41 +01:00
case 'delete' :
2016-04-29 12:41:53 +02:00
Egw :: redirect_link ( '/index.php' , array (
2008-05-10 14:02:49 +02:00
'menuaction' => 'addressbook.addressbook_ui.index' ,
2008-04-22 08:08:01 +02:00
'msg' => $this -> delete ( $content ) ? lang ( 'Contact deleted' ) : lang ( 'Error deleting the contact !!!' ),
2006-03-28 13:41:48 +02:00
));
2014-03-12 14:29:52 +01:00
case 'next' :
$inc = 1 ;
// fall through
case 'back' :
if ( ! isset ( $inc )) $inc = - 1 ;
// get next/previous contact in selection
2016-04-29 12:41:53 +02:00
$query = Api\Cache :: getSession ( 'addressbook' , 'index' );
2014-03-12 14:29:52 +01:00
$query [ 'start' ] = $content [ 'index' ] + $inc ;
$query [ 'num_rows' ] = 1 ;
$rows = $readonlys = array ();
$num_rows = $this -> get_rows ( $query , $rows , $readonlys , true );
//error_log(__METHOD__."() get_rows()=$num_rows rows=".array2string($rows));
$contact_id = $rows [ 0 ];
if ( ! $contact_id || ! is_array ( $content = $this -> read ( $contact_id )))
{
2016-04-29 12:41:53 +02:00
Egw :: redirect_link ( '/index.php' , array (
2014-03-12 14:29:52 +01:00
'menuaction' => 'addressbook.addressbook_ui.index' ,
'msg' => $content ,
'ajax' => 'true'
));
}
$content [ 'index' ] = $query [ 'start' ];
2014-03-12 16:21:01 +01:00
2014-03-12 23:42:06 +01:00
// List nextmatch is already there, just update the filter
2016-04-29 12:41:53 +02:00
if ( $contact_id && Api\Json\Request :: isJSONRequest ())
2014-03-12 16:21:01 +01:00
{
2014-03-25 17:53:36 +01:00
switch ( $crm_list )
2014-03-12 23:42:06 +01:00
{
2019-10-22 18:57:00 +02:00
case 'infolog-organisation' :
$contact_id = $this -> get_all_org_contacts ( $contact_id );
// Fall through
2014-03-12 23:42:06 +01:00
case 'infolog' :
2014-03-19 21:21:05 +01:00
case 'tracker' :
2014-03-13 09:15:41 +01:00
default :
2016-04-29 12:41:53 +02:00
Api\Json\Response :: get () -> apply ( 'app.addressbook.view_set_list' , Array ( Array ( 'action' => 'addressbook' , 'action_id' => $contact_id )));
2014-03-12 23:42:06 +01:00
break ;
}
2014-03-12 16:21:01 +01:00
2014-03-12 23:42:06 +01:00
// Clear contact_id, it's used as a flag to send the list
2014-03-12 16:21:01 +01:00
unset ( $contact_id );
}
2014-03-12 14:29:52 +01:00
break ;
2021-03-04 21:53:52 +01:00
default :
// No button, probably a refresh
$content = $this -> read ( $content [ 'id' ]);
break ;
2005-11-11 21:50:12 +01:00
}
}
else
{
2015-10-07 11:31:10 +02:00
// allow to search eg. for a phone number
if ( isset ( $_GET [ 'search' ]))
{
2016-04-29 12:41:53 +02:00
$query = Api\Cache :: getSession ( 'addressbook' , 'index' );
2015-10-07 11:31:10 +02:00
$query [ 'search' ] = $_GET [ 'search' ];
unset ( $_GET [ 'search' ]);
// reset all filters
unset ( $query [ 'advanced_search' ]);
$query [ 'col_filter' ] = array ();
$query [ 'filter' ] = $query [ 'filter2' ] = $query [ 'cat_id' ] = '' ;
2016-04-29 12:41:53 +02:00
Api\Cache :: setSession ( 'addressbook' , 'index' , $query );
2015-10-07 11:31:10 +02:00
$query [ 'start' ] = 0 ;
$query [ 'num_rows' ] = 1 ;
$rows = $readonlys = array ();
$num_rows = $this -> get_rows ( $query , $rows , $readonlys , true );
$_GET [ 'contact_id' ] = array_shift ( $rows );
$_GET [ 'index' ] = 0 ;
}
2021-10-06 16:07:47 +02:00
$contact_id = $_GET [ 'contact_id' ] ? ? (( int ) $_GET [ 'account_id' ] ? 'account:' . ( int ) $_GET [ 'account_id' ] : 0 );
2012-05-03 17:23:30 +02:00
if ( ! $contact_id || ! is_array ( $content = $this -> read ( $contact_id )))
2006-03-28 13:41:48 +02:00
{
2016-04-29 12:41:53 +02:00
Egw :: redirect_link ( '/index.php' , array (
2008-05-10 14:02:49 +02:00
'menuaction' => 'addressbook.addressbook_ui.index' ,
2006-03-28 13:41:48 +02:00
'msg' => $content ,
2013-11-27 01:12:11 +01:00
'ajax' => 'true'
2015-10-07 11:31:10 +02:00
) + ( isset ( $_GET [ 'search' ]) ? array ( 'search' => $_GET [ 'search' ]) : array ()));
2006-03-28 13:41:48 +02:00
}
2014-03-12 14:29:52 +01:00
if ( isset ( $_GET [ 'index' ]))
{
$content [ 'index' ] = ( int ) $_GET [ 'index' ];
// get number of rows to determine if we can have a next button
2016-04-29 12:41:53 +02:00
$query = Api\Cache :: getSession ( 'addressbook' , 'index' );
2014-03-12 14:29:52 +01:00
$query [ 'start' ] = $content [ 'index' ];
$query [ 'num_rows' ] = 1 ;
$rows = $readonlys = array ();
$num_rows = $this -> get_rows ( $query , $rows , $readonlys , true );
}
2005-11-11 21:50:12 +01:00
}
2014-08-06 01:27:06 +02:00
$content [ 'jpegphoto' ] = ! empty ( $content [ 'jpegphoto' ]); // unused and messes up json encoding (not utf-8)
2011-04-19 17:03:58 +02:00
// make everything not explicit mentioned readonly
$readonlys [ '__ALL__' ] = true ;
2020-09-30 13:19:36 +02:00
$readonlys [ 'photo' ] = $readonlys [ 'button[copy]' ] = false ;
2011-04-19 17:03:58 +02:00
2006-04-30 11:34:24 +02:00
foreach ( array_keys ( $this -> contact_fields ) as $key )
2005-11-11 21:50:12 +01:00
{
2008-08-25 15:49:32 +02:00
if ( in_array ( $key , array ( 'tel_home' , 'tel_work' , 'tel_cell' , 'tel_fax' )))
2005-11-13 18:51:41 +01:00
{
$content [ $key . '2' ] = $content [ $key ];
2008-04-18 08:10:31 +02:00
}
2005-11-11 21:50:12 +01:00
}
2010-03-05 09:28:25 +01:00
2009-11-20 09:49:39 +01:00
// respect category permissions
if ( ! empty ( $content [ 'cat_id' ]))
{
2016-04-29 12:41:53 +02:00
$content [ 'cat_id' ] = $this -> categories -> check_list ( Acl :: READ , $content [ 'cat_id' ]);
2009-11-20 09:49:39 +01:00
}
2013-12-05 21:38:16 +01:00
$content [ 'cat_id_tree' ] = $content [ 'cat_id' ];
2009-11-26 09:32:18 +01:00
2005-11-13 18:51:41 +01:00
$content [ 'view' ] = true ;
2005-11-23 18:07:33 +01:00
$content [ 'link_to' ] = array (
2005-11-14 18:46:23 +01:00
'to_app' => 'addressbook' ,
'to_id' => $content [ 'id' ],
);
2010-09-27 18:39:54 +02:00
// Links for deleted entries
2016-03-06 14:45:15 +01:00
if ( $content [ 'tid' ] == self :: DELETED_TYPE )
2010-09-27 18:39:54 +02:00
{
$content [ 'link_to' ][ 'show_deleted' ] = true ;
}
2016-04-29 12:41:53 +02:00
$readonlys [ 'button[delete]' ] = ! $content [ 'owner' ] || ! $this -> check_perms ( Acl :: DELETE , $content );
$readonlys [ 'button[edit]' ] = ! $this -> check_perms ( Acl :: EDIT , $content );
2006-04-30 11:34:24 +02:00
2007-06-23 09:09:52 +02:00
// how to display addresses
$content [ 'addr_format' ] = $this -> addr_format_by_country ( $content [ 'adr_one_countryname' ]);
$content [ 'addr_format2' ] = $this -> addr_format_by_country ( $content [ 'adr_two_countryname' ]);
2008-04-18 08:10:31 +02:00
2006-04-23 16:40:31 +02:00
$sel_options [ 'fileas_type' ][ $content [ 'fileas_type' ]] = $this -> fileas ( $content );
$sel_options [ 'owner' ] = $this -> get_addressbooks ();
2016-04-29 12:41:53 +02:00
for ( $i = - 23 ; $i <= 23 ; $i ++ )
{
$tz [ $i ] = ( $i > 0 ? '+' : '' ) . $i ;
}
2006-03-14 15:26:55 +01:00
$sel_options [ 'tz' ] = $tz ;
$content [ 'tz' ] = $content [ 'tz' ] ? $content [ 'tz' ] : 0 ;
2006-04-30 11:34:24 +02:00
if ( count ( $this -> content_types ) > 1 )
{
foreach ( $this -> content_types as $type => $data )
{
$sel_options [ 'tid' ][ $type ] = $data [ 'name' ];
}
2016-04-29 12:41:53 +02:00
$content [ 'typegfx' ] = Api\Html :: image ( 'addressbook' , $this -> content_types [ $content [ 'tid' ]][ 'options' ][ 'icon' ], '' , ' width="16px" height="16px"' );
2006-04-30 11:34:24 +02:00
}
else
{
$content [ 'no_tid' ] = true ;
}
2014-03-06 19:39:52 +01:00
$this -> tmpl -> read ( 'addressbook.view' );
/* if ( ! $this -> tmpl -> read ( $this -> content_types [ $content [ 'tid' ]][ 'options' ][ 'template' ] ? $this -> content_types [ $content [ 'tid' ]][ 'options' ][ 'template' ] : 'addressbook.edit' ))
2006-03-14 15:26:55 +01:00
{
2007-06-17 15:15:13 +02:00
$content [ 'msg' ] = lang ( 'WARNING: Template "%1" not found, using default template instead.' , $this -> content_types [ $content [ 'tid' ]][ 'options' ][ 'template' ]) . " \n " ;
$content [ 'msg' ] .= lang ( 'Please update the templatename in your customfields section!' );
$this -> tmpl -> read ( 'addressbook.edit' );
2014-03-06 19:39:52 +01:00
} */
2007-06-03 13:42:39 +02:00
if ( $this -> private_addressbook && $content [ 'private' ] && $content [ 'owner' ] == $this -> user )
{
$content [ 'owner' ] .= 'p' ;
}
2012-05-15 17:52:11 +02:00
$this -> tmpl -> set_cell_attribute ( 'change_org' , 'disabled' , true );
2010-02-08 18:53:47 +01:00
2011-02-17 21:00:54 +01:00
// Prevent double countries - invalid code blanks it, disabling doesn't work
$content [ 'adr_one_countrycode' ] = '-' ;
$content [ 'adr_two_countrycode' ] = '-' ;
2010-02-08 18:53:47 +01:00
// Enable history
$this -> setup_history ( $content , $sel_options );
2007-10-19 10:34:47 +02:00
// disable not needed tabs
2009-05-11 08:47:38 +02:00
$readonlys [ 'tabs' ][ 'cats' ] = ! ( $content [ 'cat_tab' ] = $this -> config [ 'cat_tab' ]);
$readonlys [ 'tabs' ][ 'custom' ] = ! $this -> customfields ;
$readonlys [ 'tabs' ][ 'custom_private' ] = ! $this -> customfields || ! $this -> config [ 'private_cf_tab' ];
$readonlys [ 'tabs' ][ 'distribution_list' ] = ! $content [ 'distrib_lists' ]; #false;
2013-07-11 17:33:59 +02:00
$readonlys [ 'tabs' ][ 'history' ] = $this -> contact_repository != 'sql' || ! $content [ 'id' ] ||
$this -> account_repository != 'sql' && $content [ 'account_id' ];
2008-01-19 06:41:04 +01:00
if ( $this -> config [ 'private_cf_tab' ]) $content [ 'no_private_cfs' ] = 0 ;
2008-04-18 08:10:31 +02:00
2007-10-19 10:34:47 +02:00
// last and next calendar date
2018-12-18 18:20:23 +01:00
if ( ! empty ( $content [ 'id' ])) $dates = current ( $this -> read_calendar ( array ( $content [ 'account_id' ] ? $content [ 'account_id' ] : 'c' . $content [ 'id' ]), false ));
2007-10-19 10:34:47 +02:00
if ( is_array ( $dates )) $content += $dates ;
2011-06-22 20:14:52 +02:00
// Disable importexport
$GLOBALS [ 'egw_info' ][ 'flags' ][ 'disable_importexport' ][ 'export' ] = true ;
$GLOBALS [ 'egw_info' ][ 'flags' ][ 'disable_importexport' ][ 'merge' ] = true ;
2006-12-11 08:35:49 +01:00
// set id for automatic linking via quick add
$GLOBALS [ 'egw_info' ][ 'flags' ][ 'currentid' ] = $content [ 'id' ];
2014-02-12 12:07:33 +01:00
// load app.css for addressbook explicit, as addressbook_view hooks changes currentapp!
2016-04-29 12:41:53 +02:00
Framework :: includeCSS ( 'addressbook' , 'app' );
2011-05-02 15:34:59 +02:00
2014-03-10 22:15:23 +01:00
// dont show an app-header
$GLOBALS [ 'egw_info' ][ 'flags' ][ 'app_header' ] = '' ;
2014-03-10 13:32:19 +01:00
// always show sidebox, as it contains contact-data
unset ( $GLOBALS [ 'egw_info' ][ 'user' ][ 'preferences' ][ 'common' ][ 'auto_hide_sidebox' ]);
2014-03-19 21:21:05 +01:00
// need to load list's app.js now, as exec calls header before other app can include it
2020-09-03 17:58:12 +02:00
// Framework::includeJS('/'.$crm_list.'/js/app.js');
// Load CRM code
Framework :: includeJS ( '.' , 'CRM' , 'addressbook' );
2021-03-04 21:53:52 +01:00
$content [ 'view_sidebox' ] = addressbook_hooks :: getViewDOMID ( $content [ 'id' ], $crm_list );
2014-03-12 14:29:52 +01:00
$this -> tmpl -> exec ( 'addressbook.addressbook_ui.view' , $content , $sel_options , $readonlys , array (
'id' => $content [ 'id' ],
'index' => $content [ 'index' ],
2014-03-25 17:53:36 +01:00
'crm_list' => $crm_list
2014-03-12 14:29:52 +01:00
));
2007-06-03 15:21:13 +02:00
2014-03-11 16:26:09 +01:00
// Only load this on first time - we're using AJAX, so it stays there through submits.
// Sending it again (via ajax) will break the addressbook.view etemplate2
if ( $contact_id )
{
2019-10-22 18:57:00 +02:00
// Show for whole organisation, not just selected contact
2019-10-25 18:18:46 +02:00
if ( $crm_list == 'infolog-organisation' )
2019-10-22 18:57:00 +02:00
{
$crm_list = str_replace ( '-organisation' , '' , $crm_list );
$_query = Api\Cache :: getSession ( 'addressbook' , 'index' );
$content [ 'id' ] = $this -> get_all_org_contacts ( $content [ 'id' ]);
}
2016-04-29 12:41:53 +02:00
Api\Hooks :: single ( array (
2014-03-11 16:26:09 +01:00
'location' => 'addressbook_view' ,
'ab_id' => $content [ 'id' ]
2014-03-25 17:53:36 +01:00
), $crm_list );
2014-03-11 16:26:09 +01:00
}
2005-11-04 00:47:52 +01:00
}
2008-04-18 08:10:31 +02:00
2019-10-22 18:57:00 +02:00
/**
* Get all the contact IDs in the given contact ' s organisation
*
* @ param int $contact_id
* @ param Array $query Optional base query
*
* @ return array of contact IDs in the organisation
*/
function get_all_org_contacts ( $contact_id , $query = array ())
{
$contact = $this -> read ( $contact_id );
2019-10-25 18:18:46 +02:00
// No org name, early return with just the contact
if ( ! $contact [ 'org_name' ])
{
return array ( $contact_id );
}
2019-11-04 19:48:40 +01:00
2019-10-22 18:57:00 +02:00
$query [ 'num_rows' ] = - 1 ;
$query [ 'start' ] = 0 ;
if ( ! array_key_exists ( 'filter' , $query ))
{
$query [ 'filter' ] = '' ;
}
if ( ! is_array ( $query [ 'col_filter' ]))
{
$query [ 'col_filter' ] = array ();
}
$query [ 'grouped_view' ] = 'org_name:' . $contact [ 'org_name' ];
$org_contacts = array ();
$readonlys = null ;
$this -> get_rows ( $query , $org_contacts , $readonlys , true ); // true = only return the id's
return $org_contacts ? $org_contacts : array ( $contact_id );
}
2005-11-18 18:03:23 +01:00
/**
* convert email - address in compose link
*
* @ param string $email email - addresse
* @ return array / string array with get - params or mailto : $email , or '' or no mail addresse
*/
function email2link ( $email )
{
2007-04-29 16:28:47 +02:00
if ( strpos ( $email , '@' ) == false ) return '' ;
2005-11-18 18:03:23 +01:00
2014-03-21 12:54:38 +01:00
if ( $GLOBALS [ 'egw_info' ][ 'user' ][ 'apps' ][ 'mail' ])
{
return array (
'menuaction' => 'mail.mail_compose.compose' ,
'send_to' => base64_encode ( $email )
);
}
2005-11-18 18:03:23 +01:00
if ( $GLOBALS [ 'egw_info' ][ 'user' ][ 'apps' ][ 'felamimail' ])
{
return array (
'menuaction' => 'felamimail.uicompose.compose' ,
'send_to' => base64_encode ( $email )
);
}
if ( $GLOBALS [ 'egw_info' ][ 'user' ][ 'apps' ][ 'email' ])
{
return array (
'menuaction' => 'email.uicompose.compose' ,
'to' => $email ,
);
}
return 'mailto:' . $email ;
}
2006-12-19 12:25:44 +01:00
/**
* Extended search
*
* @ param array $_content
* @ return string
*/
2021-03-28 20:48:55 +02:00
function extSearch ( $_content = array ())
2005-11-04 00:47:52 +01:00
{
2010-10-12 16:01:36 +02:00
if ( ! empty ( $_content ))
{
2014-02-12 12:07:33 +01:00
2014-09-09 23:55:00 +02:00
$_content [ 'cat_id' ] = $this -> config [ 'cat_tab' ] === 'Tree' ? $_content [ 'cat_id_tree' ] : $_content [ 'cat_id' ];
2016-04-29 12:41:53 +02:00
$response = Api\Json\Response :: get ();
2008-04-18 08:10:31 +02:00
2016-04-29 12:41:53 +02:00
$query = Api\Cache :: getSession ( 'addressbook' , 'index' );
2008-04-18 08:10:31 +02:00
2014-01-31 17:04:05 +01:00
if ( $_content [ 'button' ][ 'cancelsearch' ])
2010-10-12 16:01:36 +02:00
{
unset ( $query [ 'advanced_search' ]);
}
else
2007-07-12 15:02:19 +02:00
{
2010-10-12 16:01:36 +02:00
$query [ 'advanced_search' ] = array_intersect_key ( $_content , array_flip ( array_merge ( $this -> get_contact_columns (), array ( 'operator' , 'meth_select' ))));
foreach ( $query [ 'advanced_search' ] as $key => $value )
{
if ( ! $value ) unset ( $query [ 'advanced_search' ][ $key ]);
}
2014-09-08 20:47:40 +02:00
// Skip n_fn, it causes problems in sql
unset ( $query [ 'advanced_search' ][ 'n_fn' ]);
2007-07-12 15:02:19 +02:00
}
$query [ 'search' ] = '' ;
// store the index state in the session
2016-04-29 12:41:53 +02:00
Api\Cache :: setSession ( 'addressbook' , 'index' , $query );
2007-07-12 15:02:19 +02:00
// store the advanced search in the session to call it again
2016-04-29 12:41:53 +02:00
Api\Cache :: setSession ( 'addressbook' , 'advanced_search' , $query [ 'advanced_search' ]);
2014-09-08 20:47:40 +02:00
// Update client / nextmatch with filters, or clear
$response -> call ( " app.addressbook.adv_search " , array ( 'advanced_search' => $_content [ 'button' ][ 'search' ] ? $query [ 'advanced_search' ] : '' ));
if ( $_content [ 'button' ][ 'cancelsearch' ])
{
2016-04-29 12:41:53 +02:00
Framework :: window_close ();
2014-09-08 20:47:40 +02:00
// No need to reload popup
return ;
}
2006-10-24 21:20:37 +02:00
}
2014-02-12 12:07:33 +01:00
2006-10-24 21:20:37 +02:00
$GLOBALS [ 'egw_info' ][ 'etemplate' ][ 'advanced_search' ] = true ;
2008-04-18 08:10:31 +02:00
2006-10-21 22:14:31 +02:00
// initialize etemplate arrays
2010-10-12 16:01:36 +02:00
$sel_options = $readonlys = array ();
2016-11-07 17:23:22 +01:00
$this -> tmpl -> read ( 'addressbook.edit' );
2016-04-29 12:41:53 +02:00
$content = Api\Cache :: getSession ( 'addressbook' , 'advanced_search' );
2010-10-12 16:01:36 +02:00
$content [ 'n_fn' ] = $this -> fullname ( $content );
2014-09-09 23:55:00 +02:00
// Avoid ID conflict with tree & selectboxes
$content [ 'cat_id_tree' ] = $content [ 'cat_id' ];
2008-04-18 08:10:31 +02:00
2016-04-29 12:41:53 +02:00
for ( $i = - 23 ; $i <= 23 ; $i ++ )
{
$tz [ $i ] = ( $i > 0 ? '+' : '' ) . $i ;
}
2005-11-04 00:47:52 +01:00
$sel_options [ 'tz' ] = $tz + array ( '' => lang ( 'doesn\'t matter' ));
2006-03-14 15:26:55 +01:00
$sel_options [ 'tid' ][] = lang ( 'all' );
//foreach($this->content_types as $type => $data) $sel_options['tid'][$type] = $data['name'];
2008-04-18 08:10:31 +02:00
2006-10-24 21:20:37 +02:00
// configure search options
2016-04-29 12:41:53 +02:00
$sel_options [ 'owner' ] = $this -> get_addressbooks ( Acl :: READ , lang ( 'all' ));
2006-10-24 21:20:37 +02:00
$sel_options [ 'operator' ] = array (
2020-04-16 18:23:22 +02:00
'AND' => lang ( 'AND' ),
'OR' => lang ( 'OR' ),
2006-10-24 21:20:37 +02:00
);
$sel_options [ 'meth_select' ] = array (
'%' => lang ( 'contains' ),
false => lang ( 'exact' ),
);
2007-05-15 16:23:28 +02:00
if ( $this -> customfields )
{
foreach ( $this -> customfields as $name => $data )
{
2014-09-09 10:36:34 +02:00
if ( substr ( $data [ 'type' ], 0 , 6 ) == 'select' && ! ( $data [ 'rows' ] > 1 ))
2007-05-15 16:23:28 +02:00
{
if ( ! isset ( $content [ '#' . $name ])) $content [ '#' . $name ] = '' ;
if ( ! isset ( $data [ 'values' ][ '' ])) $sel_options [ '#' . $name ][ '' ] = lang ( 'Select one' );
}
2016-11-07 17:23:22 +01:00
// Make them not required, otherwise you can't search
$this -> tmpl -> setElementAttribute ( '#' . $name , 'needed' , FALSE );
2007-05-15 16:23:28 +02:00
}
}
2006-10-24 21:20:37 +02:00
// configure edit template as search dialog
2006-04-24 22:52:14 +02:00
$readonlys [ 'change_photo' ] = true ;
2006-10-21 22:14:31 +02:00
$readonlys [ 'fileas_type' ] = true ;
$readonlys [ 'creator' ] = true ;
2008-08-26 12:40:20 +02:00
// this setting will enable (and show) the search and cancel buttons, setting this to true will hide the before mentioned buttons completely
$readonlys [ 'button' ] = false ;
2006-12-16 13:02:14 +01:00
// disable not needed tabs
2009-05-11 08:47:38 +02:00
$readonlys [ 'tabs' ][ 'cats' ] = ! ( $content [ 'cat_tab' ] = $this -> config [ 'cat_tab' ]);
$readonlys [ 'tabs' ][ 'custom' ] = ! $this -> customfields ;
$readonlys [ 'tabs' ][ 'custom_private' ] = ! $this -> customfields || ! $this -> config [ 'private_cf_tab' ];
$readonlys [ 'tabs' ][ 'links' ] = true ;
$readonlys [ 'tabs' ][ 'distribution_list' ] = true ;
2014-02-03 14:32:34 +01:00
$readonlys [ 'tabs' ][ 'history' ] = true ;
2008-08-26 12:40:20 +02:00
// setting hidebuttons for content will hide the 'normal' addressbook edit dialog buttons
2006-10-21 22:14:31 +02:00
$content [ 'hidebuttons' ] = true ;
2006-10-24 21:20:37 +02:00
$content [ 'no_tid' ] = true ;
2014-01-31 17:04:05 +01:00
$content [ 'showsearchbuttons' ] = true ; // enable search operation and search buttons| they're disabled by default
2014-02-03 17:19:49 +01:00
if ( $this -> config [ 'private_cf_tab' ]) $content [ 'no_private_cfs' ] = 0 ;
2014-02-12 12:07:33 +01:00
2012-05-15 18:52:25 +02:00
$this -> tmpl -> set_cell_attribute ( 'change_org' , 'disabled' , true );
2021-04-06 10:54:48 +02:00
return $this -> tmpl -> exec ( 'addressbook.addressbook_ui.extSearch' , $content , $sel_options , $readonlys , array (), 2 );
2005-11-04 00:47:52 +01:00
}
2006-04-30 20:03:06 +02:00
2017-11-13 12:15:54 +01:00
/**
* Check if there ' s a photo for given contact id . This is used for avatar widget
* to set or unset delete button . If there ' s no uploaded photo it responses true .
*
* @ param type $contact_id
*/
function ajax_noPhotoExists ( $contact_id )
{
$response = Api\Json\Response :: get ();
$response -> data (( ! ( $contact = $this -> read ( $contact_id )) ||
2019-10-02 12:53:02 +02:00
empty ( $contact [ 'photo' ]) && ! (( $contact [ 'files' ] & Api\Contacts :: FILES_BIT_PHOTO ) &&
2017-11-13 12:15:54 +01:00
( $size = filesize ( $url = Api\Link :: vfs_path ( 'addressbook' , $contact_id , Api\Contacts :: FILES_PHOTO ))))));
}
2016-09-13 17:30:39 +02:00
/**
2017-09-19 11:38:02 +02:00
* Ajax method to update edited avatar photo via avatar widget
2016-09-13 17:30:39 +02:00
*
2017-11-29 02:58:36 +01:00
* @ param string $etemplate_exec_id to update id , files , etag , ...
2017-11-29 09:25:08 +01:00
* @ param file string $file null means to delete
2016-09-13 17:30:39 +02:00
*/
2017-11-29 09:25:08 +01:00
function ajax_update_photo ( $etemplate_exec_id , $file )
2016-09-13 17:30:39 +02:00
{
2017-11-29 02:58:36 +01:00
$et_request = Api\Etemplate\Request :: read ( $etemplate_exec_id );
2016-09-13 17:30:39 +02:00
$response = Api\Json\Response :: get ();
if ( $file )
{
2017-09-19 11:38:02 +02:00
$filteredFile = substr ( $file , strpos ( $file , " , " ) + 1 );
// resize photo if wider then default width of 240pixel (keeping aspect ratio)
$decoded = $this -> resize_photo ( base64_decode ( $filteredFile ));
2016-09-13 17:30:39 +02:00
}
2017-11-29 09:25:08 +01:00
$response -> data ( true );
// add photo into current eT2 request
$et_request -> preserv = array_merge ( $et_request -> preserv , array (
'jpegphoto' => is_null ( $file ) ? $file : $decoded ,
'photo_unchanged' => false , // hint photo is changed
));
2016-09-13 17:30:39 +02:00
}
2017-09-21 11:32:55 +02:00
/**
* Callback for vfs - upload widgets for PGP and S / Mime pubkey
*
* @ param array $file
* @ param string $widget_id
* @ param Api\Etemplate\Request $request eT2 request eg . to access attribute $content
* @ param Api\Json\Response $response
*/
public function pubkey_uploaded ( array $file , $widget_id , Api\Etemplate\Request $request , Api\Json\Response $response )
{
//error_log(__METHOD__."(".array2string($file).", ...) widget_id=$widget_id, id=".$request->content['id'].", files=".$request->content['files']);
unset ( $file , $response ); // not used, but required by function signature
list (,, $path ) = explode ( ':' , $widget_id );
$bit = $path === Api\Contacts :: FILES_PGP_PUBKEY ? Api\Contacts :: FILES_BIT_PGP_PUBKEY : Api\Contacts :: FILES_BIT_SMIME_PUBKEY ;
if ( ! ( $request -> content [ 'files' ] & $bit ) && $this -> check_perms ( Acl :: EDIT , $request -> content ))
{
$content = $request -> content ;
$content [ 'files' ] |= $bit ;
$content [ 'photo_unchanged' ] = true ; // hint no need to store photo
if ( $this -> save ( $content ))
{
$changed = array_diff_assoc ( $content , $request -> content );
//error_log(__METHOD__."() changed=".array2string($changed));
$request -> content = $content ;
// need to update preserv, as edit stores content there too and we would get eg. an contact modified error when trying to store
$request -> preserv = array_merge ( $request -> preserv , $changed );
}
}
}
2009-05-09 09:58:16 +02:00
/**
* Migrate contacts to or from LDAP ( called by Admin >> Addressbook >> Site configuration ( Admin only )
*
*/
2021-03-28 20:48:55 +02:00
function migrate2ldap ( $type = null )
2006-07-08 02:36:23 +02:00
{
$GLOBALS [ 'egw_info' ][ 'flags' ][ 'app_header' ] = lang ( 'Addressbook' ) . ' - ' . lang ( 'Migration to LDAP' );
2016-05-14 21:26:36 +02:00
echo $GLOBALS [ 'egw' ] -> framework -> header ();
echo $GLOBALS [ 'egw' ] -> framework -> navbar ();
2008-04-18 08:10:31 +02:00
2006-09-15 09:16:07 +02:00
if ( ! $this -> is_admin ())
2006-07-08 02:36:23 +02:00
{
echo '<h1>' . lang ( 'Permission denied !!!' ) . " </h1> \n " ;
}
else
{
2021-03-28 20:48:55 +02:00
parent :: migrate2ldap ( $type ? ? $_GET [ 'type' ]);
2006-07-08 02:36:23 +02:00
echo '<p style="margin-top: 20px;"><b>' . lang ( 'Migration finished' ) . " </b></p> \n " ;
}
2016-05-14 21:26:36 +02:00
echo $GLOBALS [ 'egw' ] -> framework -> footer ();
2006-07-08 02:36:23 +02:00
}
2008-04-18 08:10:31 +02:00
2009-05-09 09:58:16 +02:00
/**
* Set n_fileas ( and n_fn ) in contacts of all users ( called by Admin >> Addressbook >> Site configuration ( Admin only )
*
* If $_GET [ all ] all fileas fields will be set , if ! $_GET [ all ] only empty ones
*
*/
function admin_set_fileas ()
{
2016-04-29 12:41:53 +02:00
Api\Translation :: add_app ( 'admin' );
2009-05-09 09:58:16 +02:00
$GLOBALS [ 'egw_info' ][ 'flags' ][ 'app_header' ] = lang ( 'Addressbook' ) . ' - ' . lang ( 'Contact maintenance' );
2016-05-14 21:26:36 +02:00
echo $GLOBALS [ 'egw' ] -> framework -> header ();
echo $GLOBALS [ 'egw' ] -> framework -> navbar ();
2009-05-09 09:58:16 +02:00
// check if user has admin rights AND if a valid fileas type is given (Security)
if ( ! $this -> is_admin () || $_GET [ 'type' ] != '' && ! in_array ( $_GET [ 'type' ], $this -> fileas_types ))
{
echo '<h1>' . lang ( 'Permission denied !!!' ) . " </h1> \n " ;
}
else
{
2016-04-29 12:41:53 +02:00
$errors = null ;
$updated = parent :: set_all_fileas ( $_GET [ 'type' ],( boolean ) $_GET [ 'all' ], $errors , true ); // true = ignore Acl
2009-05-09 09:58:16 +02:00
echo '<p style="margin-top: 20px;"><b>' . lang ( '%1 contacts updated (%2 errors).' , $updated , $errors ) . " </b></p> \n " ;
}
2016-05-14 21:26:36 +02:00
echo $GLOBALS [ 'egw' ] -> framework -> footer ();
2009-05-09 09:58:16 +02:00
}
2010-03-05 09:28:25 +01:00
2009-11-11 09:44:51 +01:00
/**
* Cleanup all contacts of all users ( called by Admin >> Addressbook >> Site configuration ( Admin only )
*
*/
function admin_set_all_cleanup ()
{
2016-04-29 12:41:53 +02:00
Api\Translation :: add_app ( 'admin' );
2009-11-11 09:44:51 +01:00
$GLOBALS [ 'egw_info' ][ 'flags' ][ 'app_header' ] = lang ( 'Addressbook' ) . ' - ' . lang ( 'Contact maintenance' );
2016-05-14 21:26:36 +02:00
echo $GLOBALS [ 'egw' ] -> framework -> header ();
echo $GLOBALS [ 'egw' ] -> framework -> navbar ();
2009-11-11 09:44:51 +01:00
// check if user has admin rights (Security)
if ( ! $this -> is_admin ())
{
echo '<h1>' . lang ( 'Permission denied !!!' ) . " </h1> \n " ;
}
else
{
2016-04-29 12:41:53 +02:00
$errors = null ;
$updated = parent :: set_all_cleanup ( $errors , true ); // true = ignore Acl
2009-11-11 09:44:51 +01:00
echo '<p style="margin-top: 20px;"><b>' . lang ( '%1 contacts updated (%2 errors).' , $updated , $errors ) . " </b></p> \n " ;
}
2016-05-14 21:26:36 +02:00
echo $GLOBALS [ 'egw' ] -> framework -> footer ();
2009-11-11 09:44:51 +01:00
}
2009-05-09 09:58:16 +02:00
2010-02-08 18:53:47 +01:00
/**
* Set up history log widget
*/
2010-11-13 10:10:11 +01:00
protected function setup_history ( & $content , & $sel_options )
{
if ( $this -> contact_repository == 'ldap' || ! $content [ 'id' ] ||
$this -> account_repository == 'ldap' && $content [ 'account_id' ])
{
return ; // no history for ldap as history table only allows integer id's
}
2010-02-08 18:53:47 +01:00
$content [ 'history' ] = array (
'id' => $content [ 'id' ],
'app' => 'addressbook' ,
'status-widgets' => array (
'owner' => 'select-account' ,
2011-02-18 19:28:11 +01:00
'creator' => 'select-account' ,
'created' => 'date-time' ,
2010-02-08 18:53:47 +01:00
'cat_id' => 'select-cat' ,
2010-11-15 17:29:31 +01:00
'adr_one_countrycode' => 'select-country' ,
'adr_two_countrycode' => 'select-country' ,
2010-02-08 18:53:47 +01:00
),
);
2010-11-13 10:10:11 +01:00
foreach ( $this -> content_types as $id => $settings )
{
2010-02-08 18:53:47 +01:00
$content [ 'history' ][ 'status-widgets' ][ 'tid' ][ $id ] = $settings [ 'name' ];
}
$sel_options [ 'status' ] = $this -> contact_fields ;
2010-02-12 17:47:15 +01:00
2021-04-23 18:20:20 +02:00
// Addressbook also has an 'owner' field, which has different options.
// If we don't put something here (just empty won't work), history log will use
// those options instead of the select-account options.
$sel_options [ 'history' ][ 'owner' ] = [ 'ignore' => 'me' ];
2010-02-08 18:53:47 +01:00
}
2022-03-29 09:16:24 +02:00
}