1<?php
2	/**
3	* View and manipulate contact records using SQL
4	* @author Jonathan Alberto Rivera Gomez <jarg@co.com.mx>
5	* @copyright Copyright (C) 2003,2004 Free Software Foundation, Inc. http://www.fsf.org/
6	* @license http://www.gnu.org/licenses/gpl.html GNU General Public License
7	* @package phpgwapi
8	* @subpackage contacts
9	* @version $Id: class.contacts_sql.inc.php 19092 2009-02-22 00:12:18Z skwashd $
10	* @internal Development of this application was funded by http://www.sogrp.com
11	*/
12
13	/**
14	* Include SQL Builder
15	*/
16	include_once(PHPGW_API_INC . '/class.sql_builder.inc.php');
17	/**
18	* Include SQL criteria
19	*/
20	include_once(PHPGW_API_INC . '/class.sql_criteria.inc.php');
21	/**
22	* Include SQL entity
23	*/
24	include_once(PHPGW_API_INC . '/class.sql_entity.inc.php');
25
26	define(PHPGW_CONTACTS_CATEGORIES_ALL, -3);
27	define(PHPGW_CONTACTS_ALL, 1);
28	define(PHPGW_CONTACTS_MINE, 2);
29	define(PHPGW_CONTACTS_PRIVATE, 3);
30
31	/**
32	* Contact Management System
33	*
34	* This class provides a contact database scheme.
35	* It attempts to be based on the vcard 2.1 standard,
36	* with mods as needed to make for more reasonable sql storage.
37	* Note that changes here must also work in the LDAP version.
38	* @package phpgwapi
39	* @subpackage contacts
40	* @internal example: $contacts = CreateObject('phpgwapi.contacts');
41	*/
42	class contacts_ extends sql_builder
43	{
44		var $db = '';
45		var $account_id = 0;
46		var $total_records = 0;
47		var $grants;
48		/**
49		* All exporteds fields
50		*
51		* We used to have a simple array that told us what the false fields were.
52		* this used to be its name.
53		* Now, what this holds is a reference to the $contact_fields['showable'] array that
54		* tells us what false fields can we show and their translation to english
55		* @deprecated New Apps must use new api
56		*/
57		var $stock_contact_fields;
58
59		/**
60		* This is an array of three elements that are arrays themselves.
61		*
62		* The purpose of the whole thing is to give us all the fields we can manage.
63		* This includes old false fields (deprecated), and all of the new data we can manage.
64		* Most importantly, this tree categorizes the said elements this way:
65		* 1. contact_fields['showable'] are fields we can show in the index page, selectable
66		* from the preferences page...etc.
67		* 2. contact_fields['retreivable'] the rest of the fields that we generaly dont show in
68		* the addressbook ui.
69		* 3. contact_fields['catalogs'] fields that belong to catalogs and, as such, we never
70		* show in raw form as they correspond to the database but we need to query for them.
71		*
72		* All of the array data points to the english translation of the field that should then
73		* be langed to get a label for the field
74		* @access private
75		*/
76		var $contact_fields = array('showable' =>
77						array(
78							'per_full_name'		=> 'full name',
79							'per_first_name'	=> 'first name',
80							'per_last_name'		=> 'last name',
81							'per_middle_name'	=> 'middle name',
82							'per_initials'		=> 'initials',
83							'per_prefix'		=> 'prefix',
84							'per_suffix'		=> 'suffix',
85							'per_birthday'		=> 'birthday',
86							'per_pubkey'		=> 'public key',
87							'per_title'		=> 'title',
88							'per_department'	=> 'department',
89							'per_sound'		=> 'sound',
90							'per_active'		=> 'active',
91					//		'per_name'		=> 'full name',
92					//		'sel_cat_id'		=> 'categories',
93							'org_name'		=> 'company name',
94							'org_active'		=> 'active company',
95							'org_parent'		=> 'parent organization',
96							'addr_type'		=> 'address type',
97							'addr_add1'		=> 'street first',
98							'addr_add2'		=> 'street second',
99							'addr_city'		=> 'city',
100							'addr_state'		=> 'state',
101							'addr_postal_code'	=> 'postal code',
102							'addr_country'		=> 'country'
103							),
104					//		'addr_address'		=> 'street address',
105					'retrievable' =>
106					array(
107					//deprecated start
108							'adr_one_street'      => 'business street',
109							'adr_one_locality'    => 'business city',
110							'adr_one_region'      => 'business state',
111							'adr_one_postalcode'  => 'business zip code',
112							'adr_one_countryname' => 'business country',
113							'adr_one_type'        => 'business address type',
114							'adr_two_street'      => 'home street',
115							'adr_two_locality'    => 'home city',
116							'adr_two_region'      => 'home state',
117							'adr_two_postalcode'  => 'home zip code',
118							'adr_two_countryname' => 'home country',
119							'adr_two_type'        => 'home address type',
120							'tz'                  => 'time zone',
121							'geo'                 => 'geo',
122							'fn'                  => 'full name',
123							'sound'               => 'Sound',
124							'org_name'            => 'company name',
125							'org_unit'            => 'department',
126							'title'               => 'title',
127							'n_prefix'            => 'prefix',
128							'n_given'             => 'first name',
129							'n_middle'            => 'middle name',
130							'n_family'            => 'last name',
131							'n_suffix'            => 'suffix',
132							'label'               => 'label',
133							'note'                => 'notes',
134							'email'               => 'business email',
135							'email_type'          => 'business email type',
136							'email_home'          => 'home email',
137							'email_home_type'     => 'home email type',
138							'address2'            => 'address line 2',
139							'address3'            => 'address line 3',
140							'tel_home'            => 'home phone',
141							'tel_voice'           => 'voice phone',
142							'tel_msg'             => 'message phone',
143							'tel_fax'             => 'fax',
144							'tel_pager'           => 'pager',
145							'tel_cell'            => 'mobile phone',
146							'tel_bbs'             => 'bbs phone',
147							'tel_modem'           => 'modem phone',
148							'tel_isdn'            => 'isdn phone',
149							'tel_car'             => 'car phone',
150							'tel_video'           => 'video phone',
151							'tel_prefer'          => 'preferred phone',
152							'ophone'              => 'Other Phone',
153							'bday'                => 'birthday',
154							'url'                 => 'url',
155							'pubkey'              => 'public key',
156							'tel_work'            => 'business phone',
157
158							//deprecated end
159
160							'addr_preferred'	=> 'preffered address',
161							'owner'			=> 'owner',
162							'access'		=> 'access',
163							'addr_pref_val'		=> 'preferred address value',
164							'other_name'		=> 'custom name',
165							'other_value'		=> 'custom value',
166							'other_owner'		=> 'custom owner',
167							'other_count_row'	=> 'custom number',
168							'org_creaton'		=> 'created on',
169							'org_creatby'		=> 'created by',
170							'org_modon'		=> 'modified on',
171							'org_modby'		=> 'modified by',
172							'count_orgs'		=> 'number of organizations',
173							//'account_id'		=> 'account id',
174							'count_persons'		=> 'number of persons',
175
176
177
178							'contact_id'		=> 'contact id',
179							'cat_id'		=> 'category id',
180							'count_contacts'	=> 'number of contacts',
181							'org_id'		=> 'organization id',
182							'person_id'		=> 'person id',
183							'my_org_id'		=> 'private organization id',
184							'my_person_id'		=> 'private person id',
185							'my_addr_id'		=> 'private address id',
186							'my_preferred'		=> 'private preferred address',
187							'my_creaton'		=> 'private created on',
188							'my_creatby'		=> 'private created by',
189							'key_addr_id'		=> 'address id',
190							'addr_creaton'		=> 'created on',
191							'addr_creatby'		=> 'created by',
192							'addr_modon'		=> 'modified on',
193							'addr_modby'		=> 'modified by',
194							'addr_contact_id'	=> 'address contact id',
195							'key_other_id'		=> 'custom id',
196							'other_contact_id'	=> 'custom contact id',
197							'addr_type_id'		=> 'address type id',
198// 							'account_id'		=> 'account id',
199// 							'account_person_id'	=> 'account person id',
200							'person_only'		=> 'only persons',
201							'per_active'		=> 'active person',
202							'per_creaton'		=> 'created on',
203							'per_creatby'		=> 'created by',
204							'per_modon'		=> 'modified on',
205							'per_modby'		=> 'modified by',
206
207							'key_cat_id'		=> 'category id'
208
209
210
211
212						),
213					'catalogs' =>
214					array(
215							'comm_descr'		=> 'communication type description',
216							'comm_preferred'	=> 'communication type preferred',
217							'comm_data'		=> 'communication type data',
218
219
220							'contact_type_descr'	=> 'contact type description',
221							'contact_type_table'	=> 'contact type table',
222
223							'comm_description'	=> 'communication media description',
224							'comm_type'		=> 'communication media type',
225							'comm_find_descr'	=> 'find communication media description',
226
227							'comm_type_description'=> 'communication media type description',
228							'comm_active'		=> 'active communication media type',
229							'comm_class'		=> 'communication media class',
230
231							'addr_description'	=> 'address type description',
232							'comm_creaton'		=> 'created on',
233							'comm_creatby'		=> 'created by',
234							'comm_modon'		=> 'modified on',
235							'comm_modby'		=> 'modified by',
236							'contact_type_id'	=> 'contact type id',
237							'comm_descr_id'	=> 'communication media description id',
238
239							'comm_contact_id'	=> 'communication type contact id',
240							'comm_type_id'		=> 'communication media type id',
241							'key_comm_id'		=> 'communication type id',
242
243							'note_type_id'		=> 'note type id',
244							'note_type'		=> 'note type',
245							'note_text'		=> 'note text',
246
247							'note_description'	=> 'note type description',
248							'key_note_id'		=> 'note id',
249							'note_contact_id'	=> 'note contact id',
250							'note_creaton'		=> 'created on',
251							'note_creatby'		=> 'created by',
252							'note_modon'		=> 'modified on',
253							'note_modby'		=> 'modified by',
254							'contact_type'		=> 'contact type'
255
256
257
258							)
259				);
260
261		/**
262		* Maps database columns to contact classes
263		* @access private
264		*/
265		var $map = array('contact_id'		=> array('phpgwapi.contact_central', '0'),
266				 'owner'		=> array('phpgwapi.contact_central', '0'),
267				 'access'		=> array('phpgwapi.contact_central', '0'),
268				 'cat_id'		=> array('phpgwapi.contact_central', '0'),
269				 'contact_type'		=> array('phpgwapi.contact_central', '0'),
270				 'count_contacts'	=> array('phpgwapi.contact_central', '0'),
271				 'max_contacts'		=> array('phpgwapi.contact_central', '0'),
272				 'sel_cat_id'		=> array('phpgwapi.contact_central', '0'),
273				 'organizations_contact'=> array('phpgwapi.contact_central', '0'),
274				 'people_contact'	=> array('phpgwapi.contact_central', '0'),
275
276				 'org_id'		=> array('phpgwapi.contact_org', '1'),
277				 'org_name'		=> array('phpgwapi.contact_org', '1'),
278				 'org_active'		=> array('phpgwapi.contact_org', '1'),
279				 'org_parent'		=> array('phpgwapi.contact_org', '1'),
280				 'org_creaton'		=> array('phpgwapi.contact_org', '1'),
281				 'org_creatby'		=> array('phpgwapi.contact_org', '1'),
282				 'org_modon'		=> array('phpgwapi.contact_org', '1'),
283				 'org_modby'		=> array('phpgwapi.contact_org', '1'),
284				 'name'			=> array('phpgwapi.contact_org', '1'),
285				 'count_orgs'		=> array('phpgwapi.contact_org', '1'),
286				 'organizations'	=> array('phpgwapi.contact_org', '1', array('organizations_person', 'organizations_org_person', 'organizations_contact')),
287				 'orgs_local'		=> array('phpgwapi.contact_org', '1'),
288				 'people_org'		=> array('phpgwapi.contact_org', '1', '', 3),
289
290				 'person_id'		=> array('phpgwapi.contact_person', '1'),
291				 'per_full_name'	=> array('phpgwapi.contact_person', '1'),
292				 'per_first_name'	=> array('phpgwapi.contact_person', '1'),
293				 'per_last_name'	=> array('phpgwapi.contact_person', '1'),
294				 'per_middle_name'	=> array('phpgwapi.contact_person', '1'),
295				 'per_prefix'		=> array('phpgwapi.contact_person', '1'),
296				 'per_suffix'		=> array('phpgwapi.contact_person', '1'),
297				 'per_birthday'		=> array('phpgwapi.contact_person', '1'),
298				 'per_pubkey'		=> array('phpgwapi.contact_person', '1'),
299				 'per_title'		=> array('phpgwapi.contact_person', '1'),
300				 'per_department'	=> array('phpgwapi.contact_person', '1'),
301				 'per_initials'		=> array('phpgwapi.contact_person', '1'),
302				 'per_sound'		=> array('phpgwapi.contact_person', '1'),
303				 'per_active'		=> array('phpgwapi.contact_person', '1'),
304				 'per_creaton'		=> array('phpgwapi.contact_person', '1'),
305				 'per_creatby'		=> array('phpgwapi.contact_person', '1'),
306				 'per_modon'		=> array('phpgwapi.contact_person', '1'),
307				 'per_modby'		=> array('phpgwapi.contact_person', '1'),
308				 'per_name'		=> array('phpgwapi.contact_person', '1'),
309				 //'account_id'		=> array('phpgwapi.contact_person', '1'),
310				 'count_persons'	=> array('phpgwapi.contact_person', '1'),
311				 'people'		=> array('phpgwapi.contact_person', '1', array('people_org', 'people_org_person', 'people_contact')),
312				 'people_local'		=> array('phpgwapi.contact_person', '1'),
313				 'organizations_person'	=> array('phpgwapi.contact_person', '1', '', 3),
314
315				 //deprecated start
316				 'fn'                  	=> array('phpgwapi.contact_person', '1'),
317				 'n_given'             	=> array('phpgwapi.contact_person', '1'),
318				 'n_family'            	=> array('phpgwapi.contact_person', '1'),
319				 'n_middle'            	=> array('phpgwapi.contact_person', '1'),
320				 'n_prefix'            	=> array('phpgwapi.contact_person', '1'),
321				 'n_suffix'            	=> array('phpgwapi.contact_person', '1'),
322				 'sound'               	=> array('phpgwapi.contact_person', '1'),
323				 'bday'                	=> array('phpgwapi.contact_person', '1'),
324				 'note'                	=> array('phpgwapi.contact_person', '1'),
325				 'tz'                  	=> array('phpgwapi.contact_person', '1'),
326				 'geo'                 	=> array('phpgwapi.contact_person', '1'),
327				 'url'                 	=> array('phpgwapi.contact_person', '1'),
328				 'pubkey'              	=> array('phpgwapi.contact_person', '1'),
329				 'org_unit'            	=> array('phpgwapi.contact_person', '1'),
330				 'title'               	=> array('phpgwapi.contact_person', '1'),
331				 //deprecated end
332
333				 'my_org_id'		=> array('phpgwapi.contact_org_person', '2'),
334				 'my_person_id'		=> array('phpgwapi.contact_org_person', '2'),
335				 'my_addr_id'		=> array('phpgwapi.contact_org_person', '2'),
336				 'my_preferred'		=> array('phpgwapi.contact_org_person', '2'),
337				 'my_creaton'		=> array('phpgwapi.contact_org_person', '2'),
338				 'my_creatby'		=> array('phpgwapi.contact_org_person', '2'),
339				 'people_org_person'	=> array('phpgwapi.contact_org_person', '2'),
340			'organizations_org_person'	=> array('phpgwapi.contact_org_person', '2'),
341
342				 'key_addr_id'		=> array('phpgwapi.contact_addr', '3'),
343				 'addr_contact_id'	=> array('phpgwapi.contact_addr', '3'),
344				 'addr_type'		=> array('phpgwapi.contact_addr', '3'),
345				 'addr_add1'		=> array('phpgwapi.contact_addr', '3'),
346				 'addr_add2'		=> array('phpgwapi.contact_addr', '3'),
347				 'addr_add3'		=> array('phpgwapi.contact_addr', '3'),
348				 'addr_city'		=> array('phpgwapi.contact_addr', '3'),
349				 'addr_state'		=> array('phpgwapi.contact_addr', '3'),
350				 'addr_postal_code'	=> array('phpgwapi.contact_addr', '3'),
351				 'addr_country'		=> array('phpgwapi.contact_addr', '3'),
352				 'addr_preferred'	=> array('phpgwapi.contact_addr', '3'),
353				 'addr_creaton'		=> array('phpgwapi.contact_addr', '3'),
354				 'addr_creatby'		=> array('phpgwapi.contact_addr', '3'),
355				 'addr_modon'		=> array('phpgwapi.contact_addr', '3'),
356				 'addr_modby'		=> array('phpgwapi.contact_addr', '3'),
357				 'addr_address'		=> array('phpgwapi.contact_addr', '3'),
358				 //deprecated start
359				 'adr_one_street'      	=> array('phpgwapi.contact_addr', '3'),
360				 'adr_one_locality'    	=> array('phpgwapi.contact_addr', '3'),
361				 'adr_one_region'      	=> array('phpgwapi.contact_addr', '3'),
362				 'adr_one_postalcode'  	=> array('phpgwapi.contact_addr', '3'),
363				 'adr_one_countryname' 	=> array('phpgwapi.contact_addr', '3'),
364				 'adr_one_type'        	=> array('phpgwapi.contact_addr', '3'),
365				 'adr_two_street'      	=> array('phpgwapi.contact_addr', '3'),
366				 'adr_two_locality'    	=> array('phpgwapi.contact_addr', '3'),
367				 'adr_two_region'      	=> array('phpgwapi.contact_addr', '3'),
368				 'adr_two_postalcode'  	=> array('phpgwapi.contact_addr', '3'),
369				 'adr_two_countryname' 	=> array('phpgwapi.contact_addr', '3'),
370				 'adr_two_type'        	=> array('phpgwapi.contact_addr', '3'),
371				 //deprecated end
372				 'addr_pref_val'	=> array('phpgwapi.contact_addr', '3'),
373
374				 'key_note_id'		=> array('phpgwapi.contact_note', '4'),
375				 'note_contact_id'	=> array('phpgwapi.contact_note', '4'),
376				 'note_type'		=> array('phpgwapi.contact_note', '4'),
377				 'note_text'		=> array('phpgwapi.contact_note', '4'),
378				 'note_creaton'		=> array('phpgwapi.contact_note', '4'),
379				 'note_creatby'		=> array('phpgwapi.contact_note', '4'),
380				 'note_modon'		=> array('phpgwapi.contact_note', '4'),
381				 'note_modby'		=> array('phpgwapi.contact_note', '4'),
382				 //deprecated start
383				 'note'			=> array('phpgwapi.contact_note', '4'),
384				 //deprecated end
385
386				 'key_other_id'		=> array('phpgwapi.contact_others', '5'),
387				 'other_contact_id'	=> array('phpgwapi.contact_others', '5'),
388				 'other_name'		=> array('phpgwapi.contact_others', '5'),
389				 'other_value'		=> array('phpgwapi.contact_others', '5'),
390				 'other_owner'		=> array('phpgwapi.contact_others', '5'),
391				 'other_count_row'	=> array('phpgwapi.contact_others', '5'),
392				 //deprecated start
393				 'label'               => array('phpgwapi.contact_others', '5'),
394				 'email_type'          => array('phpgwapi.contact_others', '5'),
395				 'email_home_type'     => array('phpgwapi.contact_others', '5'),
396				 'adr_one_type'        => array('phpgwapi.contact_others', '5'),
397				 'adr_two_type'        => array('phpgwapi.contact_others', '5'),
398				 //deprecated end
399
400				 'key_comm_id'		=> array('phpgwapi.contact_comm', '6'),
401				 'comm_contact_id'	=> array('phpgwapi.contact_comm', '6'),
402				 'comm_descr'		=> array('phpgwapi.contact_comm', '6'),
403				 'comm_preferred'	=> array('phpgwapi.contact_comm', '6'),
404				 'comm_data'		=> array('phpgwapi.contact_comm', '6'),
405				 'comm_creaton'		=> array('phpgwapi.contact_comm', '6'),
406				 'comm_creatby'		=> array('phpgwapi.contact_comm', '6'),
407				 'comm_modon'		=> array('phpgwapi.contact_comm', '6'),
408				 'comm_modby'		=> array('phpgwapi.contact_comm', '6'),
409				 //deprecated start
410				 'tel_work'            	=> array('phpgwapi.contact_comm', '6'),
411				 'tel_home'            	=> array('phpgwapi.contact_comm', '6'),
412				 'tel_voice'           	=> array('phpgwapi.contact_comm', '6'),
413				 'tel_fax'             	=> array('phpgwapi.contact_comm', '6'),
414				 'tel_msg'             	=> array('phpgwapi.contact_comm', '6'),
415				 'tel_cell'            	=> array('phpgwapi.contact_comm', '6'),
416				 'tel_pager'           	=> array('phpgwapi.contact_comm', '6'),
417				 'tel_bbs'             	=> array('phpgwapi.contact_comm', '6'),
418				 'tel_modem'           	=> array('phpgwapi.contact_comm', '6'),
419				 'tel_car'             	=> array('phpgwapi.contact_comm', '6'),
420				 'tel_isdn'            	=> array('phpgwapi.contact_comm', '6'),
421				 'tel_video'           	=> array('phpgwapi.contact_comm', '6'),
422				 'tel_prefer'          	=> array('phpgwapi.contact_comm', '6'),
423				 'email'               	=> array('phpgwapi.contact_comm', '6'),
424				 'email_type'          	=> array('phpgwapi.contact_comm', '6'),
425				 'email_home'          	=> array('phpgwapi.contact_comm', '6'),
426				 'email_home_type'     	=> array('phpgwapi.contact_comm', '6'),
427				 'url'			=> array('phpgwapi.contact_comm', '6'),
428				 //deprecated end
429
430				 'contact_type_id'	=> array('phpgwapi.contact_types', '9'),
431				 'contact_type_descr'	=> array('phpgwapi.contact_types', '9'),
432				 'contact_type_table'	=> array('phpgwapi.contact_types', '9'),
433
434				 'comm_descr_id'	=> array('phpgwapi.contact_comm_descr', '7'),
435				 'comm_description'	=> array('phpgwapi.contact_comm_descr', '7'),
436				 'comm_type'		=> array('phpgwapi.contact_comm_descr', '7'),
437				 'comm_find_descr'	=> array('phpgwapi.contact_comm_descr', '7'),
438
439				 'comm_type_id'		=> array('phpgwapi.contact_comm_type', '8'),
440				 'comm_type_description'=> array('phpgwapi.contact_comm_type', '8'),
441				 'comm_active'		=> array('phpgwapi.contact_comm_type', '8'),
442				 'comm_class'		=> array('phpgwapi.contact_comm_type', '8'),
443
444				 'addr_type_id'		=> array('phpgwapi.contact_addr_type', '10'),
445				 'addr_description'	=> array('phpgwapi.contact_addr_type', '10'),
446
447				 'note_type_id'		=> array('phpgwapi.contact_note_type', '11'),
448				 'note_description'	=> array('phpgwapi.contact_note_type', '11'),
449
450				 'account_id'		=> array('phpgwapi.contact_accounts', '12'),
451				 'account_person_id'	=> array('phpgwapi.contact_accounts', '12'),
452				 'person_only'		=> array('phpgwapi.contact_accounts', '12'),
453
454				 'key_cat_id'		=> array('phpgwapi.contact_categories', '13'));
455		/**
456		* Database columns for import/export
457		* @access private
458		*/
459		var $import_export_fields = array('contact_id',
460						'access',
461						'owner',
462						'per_full_name',
463						'per_first_name',
464						'per_middle_name',
465						'org_name',
466						'people',
467						'per_last_name',
468						'per_suffix',
469						'per_prefix',
470						'per_birthday',
471						'per_pubkey',
472						'per_title',
473						'per_department',
474						'per_initials',
475						'per_sound',
476						'per_active',
477						'per_creaton',
478						'per_creatby',
479						'per_modby',
480						'per_modon',
481						'key_addr_id',
482						'addr_description',
483						'addr_add1',
484						'addr_add2',
485						'addr_add3',
486						'addr_address',
487						'addr_postal_code',
488						'addr_city',
489						'addr_state',
490						'addr_country',
491						'addr_preferred',
492						'comm_description',
493						'comm_type_description',
494						'comm_data',
495						'key_note_id',
496						'note_text',
497						'note_description',
498						'other_value',
499						'other_name');
500
501		/**
502		* Database columns for import
503		* @access private
504		*/
505		var $import_fields = array('contact_id'	=> 'contact id',
506					   'first_name' => 'first name',
507					   'last_name' 	=> 'last name',
508					   'middle_name'=> 'middle name',
509					   'sufix' 	=> 'sufix',
510					   'prefix' 	=> 'prefix',
511					   'birthday' 	=> 'birthday',
512					   'pubkey' 	=> 'public key',
513					   'title' 	=> 'title',
514					   'department' => 'department',
515					   'initials' 	=> 'initials',
516					   'sound' 	=> 'sound',
517					   'active' 	=> 'active',
518					   'organizations' => 'organizations',
519					   'categories' => 'Categories',
520					   'locations'	=> array('add1'	=> 'Address 1',
521								 'add2' => 'Address 2',
522								 'add3' => 'Address 3',
523								 'city' => 'City',
524								 'state'=> 'State',
525								 'postal_code' => 'Postal code',
526								 'country' 	=> 'Country',
527								 'preferred' => 'Preferred'));
528
529
530		//'parent_id'		=> array('categories_parent', '14'));
531
532		/**
533		* Adresses fields array for mantain backward compatibility.
534		*
535		* As soon as csv and vcard import/export, had been fixed, this could be removed.
536		* @access private
537		* @deprecated Just for old add function.
538		*/
539		var $adr_old = array(array('adr_one_street',
540				       'adr_one_locality',
541				       'adr_one_region',
542				       'adr_one_postalcode',
543				       'adr_one_countryname'),
544				 array('adr_two_street',
545				       'adr_two_locality',
546				       'adr_two_region',
547				       'adr_two_postalcode',
548				       'adr_two_countryname'));
549		/**
550		* Phone/Emails fields array for mantain backward compatibility.
551		*
552		* As soon as csv and vcard import/export, had been fixed, this could be removed.
553		* @access private
554		* @deprecated Just for old add function.
555		*/
556		var $comm_old = array('tel_work'=> array('Bussiness Phone', 'phone'),
557				  'tel_home'	=> array('Home Phone', 'phone'),
558				  'tel_voice'	=> array('Voice', 'phone'),
559				  'tel_fax'	=> array('Fax', 'fax'),
560				  'tel_msg'	=> array('Message Service', 'phone'),
561				  'tel_cell'	=> array('Mobille Phone', 'mobil'),
562				  'tel_pager'	=> array('Pager', 'phone'),
563				  'tel_bbs'	=> array('BBS', 'phone'),
564				  'tel_modem'	=> array('Modem', 'phone'),
565				  'tel_car'	=> array('Car', 'phone'),
566				  'tel_isdn'	=> array('ISDN', 'phone'),
567				  'tel_video'	=> array('Video', 'phone'),
568				  'email'	=> array('Bussiness', 'email'),
569				  'email_home'	=> array('Home', 'email'));
570		/**
571		* Describe the type of contact, this var know the type of contact.
572		* @access private
573		*/
574		var $_contact_person;
575		var $_contact_org;
576
577		function contacts_($session=True)
578		{
579			$this->db = &$GLOBALS['phpgw']->db;
580			if(!is_object($GLOBALS['phpgw']->session))
581			{
582				$GLOBALS['phpgw']->session = CreateObject('phpgwapi.sessions');
583			}
584
585			$this->stock_contact_fields=&$this->contact_fields['showable'];
586			$this->account_id = $GLOBALS['phpgw_info']['user']['account_id'];
587			if($session)
588			{
589				$this->read_sessiondata();
590				$this->save_sessiondata();
591			}
592
593			if ($GLOBALS['phpgw_info']['server']['contact_repository'] == 'ldap')
594			{
595				$this->LDAPSyncEnabled = true;
596				$this->LDAPResource = $GLOBALS['phpgw']->common->ldapConnect($GLOBALS['phpgw_info']['server']['ldap_contact_host'], $GLOBALS['phpgw_info']['server']['ldap_contact_dn'], $GLOBALS['phpgw_info']['server']['ldap_contact_pw']);
597			}
598		}
599
600		/**
601		* Read data from session into this object
602		*
603		* @access private
604		*/
605		function read_sessiondata()
606		{
607			$data = $GLOBALS['phpgw']->session->appsession('session_data','phpgwapi');
608
609			if ($data['comm_descr_flag']=='cache')
610			{
611				$this->comm_descr = $data['comm_descr'];
612				$this->comm_descr_flag = 'cache';
613			}
614			else
615			{
616				$this->comm_descr = $this->get_contact_comm_descr();
617				$this->comm_descr_flag = 'cache';
618			}
619
620			if ($data['comm_type_flag']=='cache')
621			{
622				$this->comm_type = $data['comm_type'];
623				$this->comm_type_flag = 'cache';
624			}
625			else
626			{
627				$this->comm_type = $this->get_contact_comm_type();
628				$this->comm_type_flag = 'cache';
629			}
630
631			if ($data['addr_type_flag']=='cache')
632			{
633				$this->addr_type = $data['addr_type'];
634				$this->addr_type_flag = 'cache';
635			}
636			else
637			{
638				$this->addr_type = $this->get_contact_addr_type();
639				$this->addr_type_flag = 'cache';
640			}
641
642			if ($data['note_type_flag']=='cache')
643			{
644				$this->note_type = $data['note_type'];
645				$this->note_type_flag = 'cache';
646			}
647			else
648			{
649				$this->note_type = $this->get_contact_note_type();
650				$this->note_type_flag = 'cache';
651			}
652
653			if ($data['contact_type_flag']=='cache')
654			{
655				$this->contact_type = $data['contact_type'];
656				$this->contact_type_flag = 'cache';
657			}
658			else
659			{
660				$this->contact_type = $this->get_contact_types();
661				$this->contact_type_flag = 'cache';
662			}
663			$this->_contact_person = 'Persons';
664			$this->_contact_org = 'Organizations';
665		}
666
667		/**
668		* Save this object into session
669		*
670		* @access private
671		*/
672		function save_sessiondata()
673		{
674			$data = array(
675				'comm_descr'=> $this->comm_descr,
676				'comm_type' => $this->comm_type,
677				'addr_type' => $this->addr_type,
678				'note_type' => $this->note_type,
679				'contact_type' => $this->contact_type,
680				'comm_descr_flag'=> $this->comm_descr_flag,
681				'comm_type_flag' => $this->comm_type_flag,
682				'addr_type_flag' => $this->addr_type_flag,
683				'note_type_flag' => $this->note_type_flag,
684				'contact_type_flag' => $this->contact_type_flag
685			);
686			$GLOBALS['phpgw']->session->appsession('session_data','phpgwapi',$data);
687		}
688
689		function delete_sessiondata($var='')
690		{
691			$data = $GLOBALS['phpgw']->session->appsession('session_data','phpgwapi');
692			if($var!='')
693			{
694				unset($data[$var]);
695			}
696			else
697			{
698				$data = '';
699			}
700			$GLOBALS['phpgw']->session->appsession('session_data','phpgwapi',$data);
701		}
702
703		/**
704		* Get the information about contact of type 'person'
705		*
706		* @return string Contact person name
707		*/
708		function get_person_name()
709		{
710			return $this->_contact_person;
711		}
712
713		/**
714		* Get the information about contact of type `Organization'
715		*
716		* @return string Organization name
717		*/
718		function get_org_name()
719		{
720			return $this->_contact_org;
721		}
722
723
724		/**
725		* Read one contact entry and return the wanted fields
726		*
727		* @param integer $id ID for contact entry to read
728		* @param array $fields Wanted fields filter
729		* @return array Array with ine contact entry
730		* @deprecated
731		* @access private
732		* @internal send this the id and whatever fields you want to see
733		*/
734		function read_single_entry($id,$fields='')
735		{
736			$person_data = $this->person_complete_data($id);
737			$entry['fn']                  	= $person_data['full_name'];
738			$entry['sound']              	= $person_data['sound'];
739			$entry['org_name']            	= '';
740			$entry['org_unit']            	= $person_data['department'];
741			$entry['title']               	= $person_data['title'];
742			$entry['n_prefix']            	= $person_data['prefix'];
743			$entry['n_given']             	= $person_data['first_name'];
744			$entry['n_middle']            	= $person_data['middle_name'];
745			$entry['n_family']            	= $person_data['last_name'];
746			$entry['n_suffix']            	= $person_data['suffix'];
747			$entry['label']               	= '';
748			$entry['adr_one_street']      	= $person_data['locations'][1]['add1'];
749			$entry['adr_one_locality']    	= $person_data['locations'][1]['city'];
750			$entry['adr_one_region']      	= $person_data['locations'][1]['state'];
751			$entry['adr_one_postalcode']	= $person_data['locations'][1]['postal_code'];
752			$entry['adr_one_countryname']	= $person_data['locations'][1]['country'];
753			$entry['adr_one_type'] 		= $person_data['locations'][1]['type'];
754			$entry['adr_two_street'] 	= $person_data['locations'][2]['add1'];
755			$entry['adr_two_locality'] 	= $person_data['locations'][2]['city'];
756			$entry['adr_two_region'] 	= $person_data['locations'][2]['state'];
757			$entry['adr_two_postalcode'] 	= $person_data['locations'][2]['postal_code'];
758			$entry['adr_two_countryname'] 	= $person_data['locations'][2]['country'];
759			$entry['adr_two_type'] 		= $person_data['locations'][2]['type'];
760			$entry['tz'] 			= $person_data['locations'][1]['tz'];;
761			$entry['geo'] 			= '';
762			$entry['tel_work'] 		= $person_data['work phone'];
763			$entry['tel_home'] 		= $person_data['home phone'];
764			$entry['tel_voice'] 		= $person_data['voice phone'];
765			$entry['tel_msg'] 		= $person_data['msg phone'];
766			$entry['tel_fax'] 		= $person_data['work fax'];
767			$entry['tel_pager'] 		= $person_data['pager'];
768			$entry['tel_cell'] 		= $person_data['mobile (cell) phone'];
769			$entry['tel_bbs'] 		= $person_data['bbs'];
770			$entry['tel_modem'] 		= $person_data['modem'];
771			$entry['tel_isdn'] 		= $person_data['isdn'];
772			$entry['tel_car'] 		= $person_data['car phone'];
773			$entry['tel_video'] 		= $person_data['video'];
774			$entry['tel_prefer'] 		= '';
775			$entry['email'] 		= $person_data['work email'];
776			$entry['email_type'] 		= $person_data['comm_type']['work email'];
777			$entry['email_home'] 		= $person_data['home email'];
778			$entry['email_home_type'] 	= $person_data['comm_type']['home email'];
779			$entry['address2'] 		= $person_data['locations'][1]['add2'];
780			$entry['address3'] 		= $person_data['locations'][1]['add3'];
781			$entry['ophone'] 		= '';
782			$entry['bday'] 			= $person_data['birthday'];
783			$entry['url'] 			= $person_data['website'];
784			$entry['pubkey'] 		= $person_data['per_pubkey'];
785			$entry['note'] 			= $person_data['notes'][1]['text'];
786			if(is_array($fields))
787			{
788				foreach($fields as $field)
789				{
790					$entry_data[0][$field] = $entry[$field];
791				}
792			}
793			else
794			{
795				$entry_data[0] = $entry;
796			}
797			return $entry_data;
798		}
799
800		/**
801		* Read last contact entry and return wanted fields
802		*
803		* @param array $fields Wanted fields
804		* @return array Array with contact fields
805		* @deprecated
806		* @access private
807		*/
808		function read_last_entry($fields='')
809		{
810			$last_contact = $this->get_max_contact();
811			$person_data = $this->read_single_entry($last_contact, $fields);
812			return $person_data;
813		}
814
815		/**
816		* Read fields from database
817		*
818		* @param integer $start Start position in database result
819		* @param integer $limit Number of values wanted
820		* @param array $fields Fields to read from database
821		* @param string $query Unused
822		* @param string $filter Unused
823		* @param string $sort Unused
824		* @param string $order Unused
825		* @param integer $lastmod Unused
826		* @return array Array with database fields
827		* @deprecated
828		* @access private
829		*/
830		function read($start=0,$limit=0,$fields='',$query='',$filter='',$sort='',$order='', $lastmod=-1)
831		{
832			foreach($fields as $field)
833			{
834				// we need search for a this communication media
835				if(@array_key_exists($field, $comm_old))
836				{
837					$comms[] = array($field, 'comm_descr');
838					unset($fields[$field]);
839				}
840			}
841			$first_adr = array();
842			foreach($fields as $field)
843			{
844				// We'll get first address
845				if(@in_array($field, $adr_old[0]))
846				{
847					$adr[0] = $adr[0] + $field;
848					unset($fields[$field]);
849				}
850
851				if(@in_array($field, $adr_old[1]))
852				{
853					$adr[1] = $adr[1] + $field;
854					unset($fields[$field]);
855				}
856			}
857
858			$this->request($fields);
859			//$this->limit($limit, $start);
860			$sql = $this->get_sql();
861			$this->db->limit_query($sql,$start,__LINE__,__FILE__,$limit);
862			while ($this->db->next_record())
863			{
864				$return_fields[] = $this->db->Record;
865			}
866			return $return_fields;
867		}
868
869		/**
870		* Add contact by importing it and adding a new organization when required
871		*
872		* @param string $owner Unused
873		* @param array $fields Fields to import
874		* @param mixed $access Access rights
875		* @param integer $cat_id Category ID
876		* @param integer $tid Unused
877		* @deprecated This method is for old import only, I ask help to code a new one
878		* @access private
879		*/
880		function add($owner,$fields,$access='',$cat_id='',$tid='n')
881		{
882			foreach($fields as $field => $value)
883			{
884				$this->explode_field_name($field, $value, $fields);
885			}
886
887			if(in_array($fields['note'], $fields))
888			{
889				$note['type'] = 'general';
890				$note['note'] = $fields['note'];
891				unset($fields['note']);
892			}
893
894			if($fields['organization'])
895			{
896				$criteria = $this->criteria_for_index($GLOBALS['phpgw_info']['user']['account_id'], PHPGW_CONTACTS_CATEGORIES_ALL, array('org_name'), $fields['organization']);
897				$records = $this->get_orgs(array('contact_id'));
898				if(is_array($records))
899				{
900					foreach($record as $org)
901					{
902						$orgs[] = $org['contact_id'];
903					}
904				}
905				else
906				{
907					$this->add_org(array('org_name' => $fields['organization']));
908					$orgs = array($this->last_id('contact', 'contact_id'));
909				}
910			}
911
912			$fields['notes'] 		= $note;
913			$fields['organizations']	= $orgs;
914			$fields['categories']	= $cat_id;
915			$fields['access']		= $access;
916			$this->contact_import($fields);
917		}
918
919		/**
920		* Test existence of a field in a contact
921		*
922		* @param integer $id Contact ID
923		* @param string $field_name Field name which should be tested
924		* @return integer Number of existing rows
925		* @deprecated
926		* @access private
927		*/
928		function field_exists($id,$field_name)
929		{
930			$this->request('other_count_row');
931			$this->criteria(array('other_contact_id' => $id));
932			$this->criteria(array('other_name' => $field_name));
933			$sql_select = $this->map['other_count_row']->select();
934			$this->db->query($sql_select,__LINE__,__FILE__);
935			$this->db->next_record();
936			return $this->db->f(0);
937		}
938
939		/**
940		* Add one extra field to a contact
941		*
942		* @param integer $id Contact ID
943		* @param integer $owner Unused
944		* @param string $field_name Field name
945		* @param string $field_value Field value
946		* @deprecated
947		* @access private
948		*/
949		function add_single_extra_field($id,$owner,$field_name,$field_value)
950		{
951			$this->other_fields = CreateObject('phpgwapi.contact_others');
952			$this->other_fields->insert(array('other_contact_id' => $id, 'other_name' => $field_name, 'other_value' => $field_value));
953		}
954
955		/**
956		* Delete one extra field from a contact
957		*
958		* @param $id Contact ID
959		* @param $field_name Field name to delete
960		* @return array Empty array
961		* @deprecated
962		* @access private
963		*/
964		function delete_single_extra_field($id,$field_name)
965		{
966			$this->delete_others($cid, PHPGW_SQL_RUN_SQL);
967			return array();
968		}
969
970		/**
971		* Update contact entry
972		*
973		* @param integer $id Contact ID
974		* @param integer $owner Owner of contact
975		* @param array $fields Fields to update
976		* @param mixed $access Unused
977		* @param integer $cat_id Unused
978		* @param integer $tid Unused
979		* @deprecated
980		* @access private
981		*/
982		function update($id,$owner,$fields,$access='',$cat_id='',$tid='n')
983		{
984			$this->update($fields);
985			$this->criteria('contact_id', $id);
986			$sql_update = $this->run_update();
987
988			foreach($sql_update as $update)
989			{
990				$this->db->query($update, __LINE__, __FILE__);
991			}
992
993			foreach($extra_fields as $name => $value)
994			{
995				if ($this->field_exists($id,$x_name))
996				{
997					if (!$value)
998					{
999						$this->delete_single_extra_field($id,$name);
1000					}
1001					else
1002					{
1003						$this->update_single_extra_field($id,$name);
1004					}
1005				}
1006				else
1007				{
1008					$this->add_single_extra_field($id,$owner,$name,$value);
1009				}
1010			}
1011		}
1012
1013		/**
1014		* Echoes "don't use this"
1015		*
1016		* @param integer $id Unused
1017		* @deprecated
1018		* @access private
1019		*/
1020		function read_extra_fields($id)
1021		{
1022			echo "don't use this";
1023		}
1024
1025		/**
1026		* Update one extra field of a contact
1027		*
1028		* @param integer $id Contact ID
1029		* @param string $name Field name
1030		* @param string $value Field value
1031		* @deprecated
1032		* @access private
1033		*/
1034		function update_single_extra_field($id, $name, $value)
1035		{
1036			$other = CreateObject('phpgwapi.contact_others');
1037			$criteria = sql_criteria::token_and(sql_criteria::_equal('other_name', $name), sql_criteria::_equal('contact_id', $id));
1038			$other->update($id, array('other_value' => $value), $criteria);
1039		}
1040
1041
1042		/**
1043		* Retrieve all persons data which you specify, this can use limit and order.
1044		*
1045		* @param array $fields The fields that you can see from person
1046		* @param integer $limit Limit of records that you want
1047		* @param integer $ofset Ofset of record that you want start
1048		* @param string $orderby The field which you want order
1049		* @param string $sort ASC | DESC depending what you want
1050		* @param mixed $criteria All criterias what you want
1051		* @param mixed $criteria_token same like $criteria but builded<br />with sql_criteria class, more powerfull
1052		* @return array Array person with records
1053		*/
1054		function get_persons($fields, $limit='', $ofset='', $orderby='', $sort='', $criteria='', $criteria_token='')
1055		{
1056			$this->request($fields);
1057			if(in_array('org_name', $fields))
1058			{
1059				$this->request(array('people'));
1060			}
1061
1062			if ($criteria != '')
1063			{
1064				$this->criteria($criteria);
1065				$this->criteria(array('contact_type' => $this->search_contact_type($this->_contact_person)));
1066			}
1067			else
1068			{
1069				if($criteria_token=='')
1070				{
1071					$this->criteria(array('contact_type' => $this->search_contact_type($this->_contact_person)));
1072				}
1073				else
1074				{
1075					$criteria_token = sql_criteria::token_and(sql_criteria::_equal('contact_type', $this->search_contact_type($this->_contact_person)), $criteria_token);
1076					$this->criteria_token($criteria_token);
1077				}
1078			}
1079
1080			if($orderby)
1081			{
1082				$this->order(array($orderby), $sort);
1083			}
1084			$sql = $this->get_sql();
1085			if ($limit)
1086			{
1087				$this->db->limit_query($sql, $ofset, __LINE__, __FILE__, $limit);
1088			}
1089			else
1090			{
1091				$this->db->query($sql, __LINE__, __FILE__);
1092			}
1093
1094			$this->total_records = $this->db->num_rows();
1095			while ($this->db->next_record())
1096			{
1097				$persons[] = $this->db->Record;
1098			}
1099			return $persons;
1100		}
1101
1102		/**
1103		* Get all the `principal' information related for organization
1104		*
1105		* @param integer|array $contact_id id of the contact or array of the same
1106		* @param integer $action PHPGW_SQL_RETURN_SQL | PHPGW_SQL_RUN_SQL depending what we want
1107		* @param boolean $get_org True: Also get the organization; False: get only the person data
1108		* @return array|string Array with records or string with sql query
1109		*/
1110		function get_principal_persons_data($contact_id, $action=PHPGW_SQL_RUN_SQL, $get_org=True)
1111		{
1112			$data = array('contact_id',
1113				      'owner',
1114				      'access',
1115				      'cat_id',
1116				      'per_full_name',
1117				      'per_first_name',
1118				      'per_last_name',
1119				      'per_middle_name',
1120				      'per_prefix',
1121				      'per_suffix',
1122				      'per_birthday',
1123				      'per_pubkey',
1124				      'per_title',
1125				      'per_department',
1126				      'per_initials',
1127				      'per_active',
1128				      'per_sound');
1129			$this->request($data);
1130			$this->criteria(array('contact_id' => $contact_id));
1131			if($get_org==True)
1132			{
1133				$this->request(array('org_name', 'org_id', 'people'));
1134				$this->criteria(array('my_preferred' => 'Y'));
1135			}
1136			return $this->get_query($action, __LINE__, __FILE__);
1137		}
1138
1139		/**
1140		* Retrieve Data for Id, taking care that are person.
1141		*
1142		* @param mixed $person_id Organizations Id which want information.
1143		* @param string $criteria
1144		* @param integer $action PHPGW_SQL_RETURN_SQL | PHPGW_SQL_RUN_SQL depending what we want
1145		* @return array Asociative array with id and all data that you requested
1146		*/
1147		function get_organizations_by_person($person_id, $criteria ='', $action=PHPGW_SQL_RUN_SQL)
1148		{
1149			$data = array('my_org_id',
1150				      'my_addr_id',
1151				      'my_preferred',
1152				      'org_name',
1153				      'people');
1154
1155			$this->request($data);
1156			$this->criteria(array('my_person_id' => $person_id));
1157			if (!empty($criteria))
1158			{
1159				$this->criteria($criteria);
1160			}
1161			return $this->get_query($action, __LINE__, __FILE__);
1162		}
1163
1164		/**
1165		* Retrieve all organizations data which you specify, this can use limit and order.
1166		*
1167		* @param array $fields The fields that you can see from person
1168		* @param integer $limit Limit of records that you want
1169		* @param integer $ofset Ofset of record that you want start
1170		* @param string $orderby The field which you want order
1171		* @param string $sort ASC | DESC depending what you want
1172		* @param array $criteria All criterias what you want
1173		* @param mixed $criteria_token same like $criteria but builded<br />with sql_criteria class, more powerfull
1174		* @return array Array with organization with records
1175		*/
1176		function get_orgs($fields, $limit='', $ofset='', $orderby='', $sort='', $criteria='', $criteria_token='')
1177		{
1178			$this->request($fields);
1179			$person_fields = array('per_full_name', 'per_first_name', 'per_last_name');
1180			if(count(array_intersect($person_fields, $fields)) > 0)
1181			{
1182				$this->request(array('organizations'));
1183			}
1184
1185			if ($criteria != '')
1186			{
1187				$this->criteria($criteria);
1188				$this->criteria(array('contact_type' => $this->search_contact_type($this->_contact_org)));
1189			}
1190			else
1191			{
1192				if($criteria_token=='')
1193				{
1194					$this->criteria(array('contact_type' => $this->search_contact_type($this->_contact_org)));
1195				}
1196				else
1197				{
1198					$criteria_token = sql_criteria::token_and(sql_criteria::_equal('contact_type', $this->search_contact_type($this->_contact_org)), $criteria_token);
1199					$this->criteria_token($criteria_token);
1200				}
1201			}
1202
1203			if($orderby)
1204			{
1205				$this->order(array($orderby), $sort);
1206			}
1207
1208			$sql = $this->get_sql();
1209
1210			if ($limit)
1211			{
1212				$this->db->limit_query($sql, $ofset, __LINE__, __FILE__, $limit);
1213			}
1214			else
1215			{
1216				$this->db->query($sql, __LINE__, __FILE__);
1217			}
1218
1219			$this->total_records = $this->db->num_rows();
1220			while ($this->db->next_record())
1221			{
1222				$orgs[] = $this->db->Record;
1223			}
1224
1225			return $orgs;
1226		}
1227
1228		/**
1229		* Get all the `principal' information related for contacts (when is/are person)
1230		*
1231		* @param integer|array $contact_id id of the contact or array of the same
1232		* @param integer $action PHPGW_SQL_RETURN_SQL | PHPGW_SQL_RUN_SQL depending what we want
1233		* @return array|string Array with records or string with sql query
1234		*/
1235		function get_principal_organizations_data($contact_id, $action=PHPGW_SQL_RUN_SQL)
1236		{
1237			$data = array('contact_id',
1238				      'owner',
1239				      'access',
1240				      'cat_id',
1241				      'org_active',
1242				      'org_name');
1243			$this->request($data);
1244			$this->criteria(array('contact_id' => $contact_id));
1245			return $this->get_query($action, __LINE__, __FILE__);
1246		}
1247
1248		/**
1249		* Retrieve Data for Id, taking care that are organizations.
1250		*
1251		* @param mixed $organizations_id Organizations Id which want information.
1252		* @param string $criteria
1253		* @param integer $action PHPGW_SQL_RETURN_SQL | PHPGW_SQL_RUN_SQL depending what we want
1254		* @return array Asociative array with id and all data that we requested
1255		*/
1256		function get_people_by_organizations($organizations_id, $criteria='', $action=PHPGW_SQL_RUN_SQL)
1257		{
1258			$data = array('my_person_id',
1259				      'my_addr_id',
1260				      'my_preferred');
1261			$this->request($data);
1262
1263			$this->criteria(array('my_org_id' => $organizations_id));
1264			$this->criteria($criteria);
1265			return $this->get_query($action, __LINE__, __FILE__);
1266		}
1267
1268		/**
1269		* Retrieve communications data for contact id.
1270		*
1271		* @param integer $contact_id  Id which want information.
1272		* @param array $fields_to_search Description what you want to find.
1273		* This parameter is an array and you can use it when you want get
1274		* information of especific comm_description (based in descriptions
1275		* from comm_description catalog).
1276		* @return array Asociative with id and all data that you requested
1277		*/
1278		function get_comm_contact_data($contact_id, $fields_to_search='')
1279		{
1280			$comms = array();
1281			$data = array('comm_contact_id',
1282				      'key_comm_id',
1283				      'comm_preferred',
1284				      'comm_data',
1285				      'comm_descr',
1286				      'comm_description');
1287			$this->request($data);
1288			$this->criteria(array('comm_contact_id' => $contact_id));
1289			if(!empty($fields_to_search))
1290			{
1291				$this->criteria(array('comm_find_descr' => $fields_to_search));
1292			}
1293
1294			$entry =  $this->get_records(__LINE__, __FILE__);
1295			if($entry)
1296			{
1297				foreach($entry as $k => $v)
1298				{
1299					$comms[] = $entry[$k];
1300				}
1301			}
1302			return $comms;
1303		}
1304
1305
1306
1307		/**
1308		* Retrieve locations data for contact id.
1309		*
1310		* @param integer $contact_id  Id which want information.
1311		* @param array $criteria Others criterias what you want.
1312		* @return array Asociative with id and all data that you requested
1313		*/
1314		function get_addr_contact_data($contact_id, $criteria='')
1315		{
1316			$locations = array();
1317			$data = array('addr_contact_id',
1318				      'key_addr_id',
1319				      'addr_type',
1320				      'addr_add1',
1321				      'addr_add2',
1322				      'addr_city',
1323				      'addr_state',
1324				      'addr_postal_code',
1325				      'addr_country',
1326				      'addr_preferred',
1327				      'addr_description');
1328			$this->request($data);
1329			$this->criteria(array('addr_contact_id' => $contact_id));
1330			if($criteria!='')
1331			{
1332				$this->criteria($criteria);
1333			}
1334			$entry =  $this->get_records(__LINE__, __FILE__);
1335			if($entry)
1336			{
1337				foreach($entry as $k => $v)
1338				{
1339					$locations[] = $entry[$k];
1340				}
1341			}
1342			return $locations;
1343		}
1344
1345		/**
1346		* Retrieve others data for contact id.
1347		*
1348		* @param integer $contact_id  Id which want information.
1349		* @param string $criteria
1350		* @return array Asociative with id and all data that you requested
1351		*/
1352		function get_others_contact_data($contact_id, $criteria='')
1353		{
1354			$others = array();
1355			$data = array('other_contact_id',
1356				      'key_other_id',
1357				      'other_owner',
1358				      'other_name',
1359				      'other_value');
1360			$this->request($data);
1361			$this->criteria(array('other_contact_id' => $contact_id));
1362			if($criteria!='')
1363			{
1364				$this->criteria($criteria);
1365			}
1366			$entry =  $this->get_records(__LINE__, __FILE__);
1367			if($entry)
1368			{
1369				foreach($entry as $k => $v)
1370				{
1371					$others[] = $entry[$k];
1372				}
1373			}
1374			return $others;
1375		}
1376
1377		/**
1378		* Get the records from contact type catalog
1379		*
1380		* @param integer $action PHPGW_SQL_RETURN_SQL | PHPGW_SQL_RUN_SQL depending what we want
1381		* @return array|string Array with records or string with sql query
1382		*/
1383		function get_contact_types($action=PHPGW_SQL_RUN_SQL)
1384		{
1385			$fields = array('contact_type_id', 'contact_type_descr', 'contact_type_table');
1386			$this->request($fields);
1387			return $this->get_query($action, __LINE__, __FILE__);
1388		}
1389
1390		/**
1391		* Get the records from addr type catalog
1392		*
1393		* @param integer $action PHPGW_SQL_RETURN_SQL | RUN_SQL depending what we want
1394		* @return array|string Array with records or string with sql query
1395		*/
1396		function get_contact_addr_type($action=PHPGW_SQL_RUN_SQL)
1397		{
1398			$fields = array('addr_type_id', 'addr_description');
1399			$this->request($fields);
1400			return $this->get_query($action, __LINE__, __FILE__);
1401		}
1402
1403		/**
1404		* Get the records from comm type catalog
1405		*
1406		* @param integer $action PHPGW_SQL_RETURN_SQL | PHPGW_SQL_RUN_SQL depending what we want
1407		* @return array|string Array with records or string with sql query
1408		*/
1409		function get_contact_comm_type($action=PHPGW_SQL_RUN_SQL)
1410		{
1411			$fields = array('comm_type_id', 'comm_type_description', 'comm_active', 'comm_class');
1412			$this->request($fields);
1413			return $this->get_query($action, __LINE__, __FILE__);
1414		}
1415
1416		/**
1417		* Get the records from comm descr catalog
1418		*
1419		* @param integer $action PHPGW_SQL_RETURN_SQL | PHPGW_SQL_RUN_SQL depending what we want
1420		* @return array|string Array with records or string with sql query
1421		*/
1422		function get_contact_comm_descr($action=PHPGW_SQL_RUN_SQL)
1423		{
1424			$fields = array('comm_descr_id', 'comm_description', 'comm_type');
1425			$this->request($fields);
1426			return $this->get_query($action, __LINE__, __FILE__);
1427		}
1428
1429		/**
1430		* Get the records from note descr catalog
1431		*
1432		* @param integer $action PHPGW_SQL_RETURN_SQL | PHPGW_SQL_RUN_SQL depending what we want
1433		* @return mixed SQL string or records with note_type_id and not_description
1434		*/
1435		function get_contact_note_type($action=PHPGW_SQL_RUN_SQL)
1436		{
1437			$fields = array('note_type_id', 'note_description');
1438			$this->request($fields);
1439			return $this->get_query($action, __LINE__, __FILE__);
1440		}
1441
1442		/**
1443		* Count the persons and return the number
1444		*
1445		* @param string $criteria  The criterias
1446		* @param integer $action PHPGW_SQL_RETURN_SQL | PHPGW_SQL_RUN_SQL depending what we want
1447		* @return integer The record count number
1448		*/
1449		function get_count_persons($criteria='', $action=PHPGW_SQL_RUN_SQL)
1450		{
1451			$this->request('count_persons');
1452			if($criteria!='')
1453			{
1454				$this->criteria_token($criteria);
1455			}
1456			$count =  $this->get_query($action, __LINE__, __FILE__);
1457			return $count[0]['count_persons'];
1458		}
1459
1460		/**
1461		* Count the organizations and return the number
1462		*
1463		* @param string $criteria  The criterias
1464		* @param integer $action PHPGW_SQL_RETURN_SQL | PHPGW_SQL_RUN_SQL depending what we want
1465		* @return integer The record count number
1466		*/
1467		function get_count_orgs($criteria='', $action=PHPGW_SQL_RUN_SQL)
1468		{
1469			$this->request('count_orgs');
1470			if($criteria!='')
1471			{
1472				$this->criteria_token($criteria);
1473			}
1474			$count =  $this->get_query($action, __LINE__, __FILE__);
1475			return $count[0]['count_orgs'];
1476		}
1477
1478		/**
1479		* Count the contacts and return the number
1480		*
1481		* @param string $criteria  The criterias
1482		* @param integer $action PHPGW_SQL_RETURN_SQL | PHPGW_SQL_RUN_SQL depending what we want
1483		* @return integer The record count number
1484		*/
1485		function get_count_contacts($criteria='', $action=PHPGW_SQL_RUN_SQL)
1486		{
1487			$this->request('count_contacts');
1488			if($criteria!='')
1489			{
1490				$this->criteria($criteria);
1491			}
1492			$count =  $this->get_query($action, __LINE__, __FILE__);
1493			return $count[0]['count_contacts'];
1494		}
1495
1496		/**
1497		* Get the max contact_id
1498		*
1499		* @param string $criteria  The criterias
1500		* @param integer $action PHPGW_SQL_RETURN_SQL | PHPGW_SQL_RUN_SQL depending what we want
1501		* @return integer The record count number
1502		*/
1503		function get_max_contact($criteria='', $action=PHPGW_SQL_RUN_SQL)
1504		{
1505			$this->request('max_contacts');
1506			if($criteria!='')
1507			{
1508				$this->criteria($criteria);
1509			}
1510			$max =  $this->get_query($action, __LINE__, __FILE__);
1511			return $max[0]['max_contacts'];
1512		}
1513
1514		/**
1515		* Retrieve all the people that is owned by $owner (but I have read access).
1516		*
1517		* @param integer $owner The account_id of the owner.
1518		* @param array $data This is the information that want to retrieve.
1519		* @param integer $action PHPGW_SQL_RETURN_SQL | PHPGW_SQL_RUN_SQL depending what we want
1520		* @return array Asociative with id and all data that we requested
1521		*/
1522		function get_people_by_owner($owner, $data, $action=PHPGW_SQL_RUN_SQL)
1523		{
1524			$this->request('contact_id');
1525			$this->request($data);
1526			$this->criteria(array('owner' => $owner));
1527			return $this->get_query($action, __LINE__, __FILE__);
1528		}
1529
1530		/**
1531		* Retrieve all the people that is part from specified category.
1532		*
1533		* @param integer $cat_id The cat_id of the owner.
1534		* @param boolean $sub_cat
1535		* @return array Asociative with id and all data that we requested
1536		*/
1537		function get_persons_by_cat($cat_id, $sub_cat=True)
1538		{
1539			if($sub_cat && $cat_id)
1540			{
1541				$cat_id = array_merge(array($cat_id), (array)$this->get_sub_cats($cat_id));
1542			}
1543
1544			$this->request('person_id');
1545			if(is_array($cat_id))
1546			{
1547				$this->criteria(array('sel_cat_id' => $cat_id));
1548			}
1549			else
1550			{
1551				$this->criteria(array('cat_id' => $cat_id));
1552			}
1553
1554			$sql = $this->get_sql();
1555
1556			$this->db->query($sql, __LINE__, __FILE__);
1557			while ($this->db->next_record())
1558			{
1559				$persons[] = $this->db->f('person_id');
1560			}
1561			return $persons;
1562		}
1563
1564		/**
1565		* Get all the contacts id, and data if it is dessired, from the contacts that are users of phpGroupWare
1566		*
1567		* @param array $data Data that we want for each contact that we retrieve.
1568		* @param integer $action PHPGW_SQL_RETURN_SQL | PHPGW_SQL_RUN_SQL depending what we want
1569		* @return array Contacts that are users and his data.
1570		*/
1571		function get_system_contacts($data, $action=PHPGW_SQL_RUN_SQL)
1572		{
1573
1574			$accounts = $GLOBALS['phpgw']->accounts->get_list();
1575			foreach($accounts as $account_data)
1576			{
1577				if($account_data['person_id'])
1578				{
1579					$people[] = $account_data['person_id'];
1580				}
1581			}
1582
1583			if(is_array($data))
1584			{
1585				$this->request($data);
1586			}
1587
1588			$this->request('person_id');
1589			// sql::in() is better than make a select by each account
1590			$this->criteria(array('person_id' => $people));
1591			return $this->get_query($action, __LINE__, __FILE__);
1592		}
1593
1594		/**
1595		* Retrieve all contacts of user that are marked as private.
1596		*
1597		* @param mixed $data List of fields what we want retrieve
1598		* @param integer $action PHPGW_SQL_RETURN_SQL | PHPGW_SQL_RUN_SQL depending what we want
1599		* @return array Asociative with id and all data that we requested
1600		*/
1601		function get_private_contacts($data, $action=PHPGW_SQL_RUN_SQL)
1602		{
1603			$this->request('contact_id');
1604			$this->request($data);
1605			$this->criteria(array('access' => 'private'));
1606			return $this->get_query($action, __LINE__, __FILE__);
1607
1608		}
1609
1610		/**
1611		* Retrieve the bussines email by contact
1612		*
1613		* @param integer $contacts_id The contact id that will be used for search his email.
1614		* @param integer $action PHPGW_SQL_RETURN_SQL | PHPGW_SQL_RUN_SQL depending what we want
1615		* @return array Asociative with id and email
1616		*/
1617		function get_email($contacts_id, $action=PHPGW_SQL_RUN_SQL)
1618		{
1619			$this->request(array('comm_data'));
1620			$this->criteria(array('comm_descr' => $this->search_comm_descr('work email'), 'comm_contact_id' => $contacts_id));
1621			$email = $this->get_records_by_field('comm_data', __LINE__, __FILE__);
1622			return $email[0];
1623		}
1624
1625		/**
1626		* Retrieve the bussines phone by contact
1627		*
1628		* @param integer $contacts_id The contact id that will be used for search his phone.
1629		* @param integer $action PHPGW_SQL_RETURN_SQL | PHPGW_SQL_RUN_SQL depending what we want
1630		* @return array Asociative with id and phone
1631		*/
1632		function get_phone($contacts_id, $action=PHPGW_SQL_RUN_SQL)
1633		{
1634			$this->request(array('comm_data'));
1635			$this->criteria(array('comm_descr' => $this->search_comm_descr('work phone'), 'comm_contact_id' => $contacts_id));
1636			$phone = $this->get_records_by_field('comm_data', __LINE__, __FILE__);
1637			return $phone[0];
1638		}
1639
1640		/**
1641		* Get all sub categories from cat_id
1642		*
1643		* @param integer $cat_id  The category id to find
1644		* @return array All sub categories
1645		* @access private
1646		*/
1647		function get_sub_cats($cat_id)
1648		{
1649			$sql = 'SELECT cat2.cat_id FROM phpgw_categories as cat '
1650				.'INNER JOIN phpgw_categories as cat2 ON cat.cat_id=cat2.cat_parent '
1651				.'WHERE '.sql::in('cat.cat_id', $cat_id);
1652
1653			$this->db->query($sql, __LINE__, __FILE__);
1654			while ($this->db->next_record())
1655			{
1656				$cats[] = $this->db->f('cat_id');
1657			}
1658
1659			if(is_array($cats))
1660			{
1661				return array_merge($cats, (array)$this->get_sub_cats($cats));
1662			}
1663		}
1664
1665		/**
1666		* This function get all the Communication media from one contact.
1667		*
1668		* Or the first if there is no one marked as preferred.
1669		* @param integer $contact_id id to locate the contact
1670		* @return array Form: description => value, ...
1671		*/
1672		function get_all_comms($contact_id)
1673		{
1674			if (intval($contact_id) != 0)
1675			{
1676				// get all comm_descriptions from api function
1677				$this->request(array('comm_data', 'comm_descr'));
1678				$this->criteria(array('comm_contact_id' => $contact_id));
1679				// get all comms from db
1680				$records = $this->get_query(PHPGW_SQL_RUN_SQL, __LINE__, __FILE__);
1681				if(count($records) == 0)
1682				{
1683					return;
1684				}
1685				foreach ($records as $comm)
1686				{
1687					$descr = $this->search_comm_descr_id($comm['comm_descr']);
1688					$comms[$descr] = $comm['comm_data'];
1689				}
1690			}
1691			return $comms;
1692		}
1693
1694		/**
1695		* This function get the contact name.
1696		*
1697		* @param integer $contact_id id The contact what you want
1698		* @return string The name of the contact
1699		*/
1700		function get_contact_name($contact_id)
1701		{
1702			$type = $this->search_contact_type_id($this->get_type_contact($contact_id));
1703			if($type == $this->_contact_person)
1704			{
1705				$field_name = 'per_full_name';
1706			}
1707			elseif($type == $this->_contact_org)
1708			{
1709				$field_name = 'org_name';
1710			}
1711
1712			$this->request(array($field_name));
1713			$this->criteria(array('contact_id' => $contact_id));
1714			$contact_name = $this->get_records_by_field($field_name, __LINE__, __FILE__);
1715			return $contact_name[0];
1716		}
1717
1718		function get_name_of_person_id($person_id)
1719		{
1720			$this->request(array('per_full_name'));
1721			$this->criteria(array('person_id' => $person_id));
1722			$person_name = $this->get_records_by_field('per_full_name', __LINE__, __FILE__);
1723			return $person_name[0];
1724		}
1725
1726		/**
1727		* Get communication description string.
1728		*
1729		* When there are no communication types available create them.
1730		* @param string $comm_type Communication Type
1731		* @param string $comm_description Communication location
1732		* @return string Communication description
1733		* @access private
1734		*/
1735		function comms_fixed($comm_type, $comm_description)
1736		{
1737			// In this array add all the label that you have on an import method, an make the
1738			// association with the corresponding description on database
1739			if(!$this->hash_comms_import)
1740			{
1741				$this->hash_comms_import =
1742					array('email'  => array('home'		=> 'home email',
1743											'work'		=> 'work email',
1744											'other'		=> 'other email'),
1745					      'phone'  => array('home'		=> 'home phone',
1746											'work'		=> 'work phone',
1747											'other'		=> 'other phone',
1748											'msg'		=> 'msg phone',
1749											'home_two'	=> 'second home phone',
1750											'work_two'	=> 'second work phone',
1751											'isdn'		=> 'isdn',
1752											'other_two'	=> 'second other phone',
1753											'pager'		=> 'pager'),
1754					      'fax'    => array('work'		=> 'work fax',
1755											'home'		=> 'home fax',
1756											'other'		=> 'other fax'),
1757					      'mobile' => array('car'		=> 'car phone',
1758											'cell'		=> 'mobile (cell) phone'));
1759			}
1760			return $this->hash_comms_import[$comm_type][$comm_description];
1761		}
1762
1763		/**
1764		* Explode a field name by `_' so parts of the field name have a meaning, not only the whole name
1765		*
1766		* @param string $field meta-field name, with form: {kind}_{key_{real_field_name}
1767		* @param mixed $value to assing to field
1768		* @param mixed &$field_list reference to the list that contain $field
1769		* @access private
1770		*/
1771		function explode_field_name($field, $value, &$fields_list)
1772		{
1773			// ugly hack
1774			$addr_keys = array('work', 'home', 'other', 'other', 'other', 'other');
1775
1776			list($kind, $key, $name) = explode('_', $field, 3);
1777			//echo "$kind : $key : $name<br />\n";
1778			switch ($kind)
1779			{
1780			case 'addr':
1781				// Code for locations
1782				$fields_list['location'][$key][$name] = $value;
1783				unset($fields_list[$field]);
1784				$fields_list['location'][$key]['type'] = $addr_keys[$key];
1785				break;
1786			case 'comm':
1787				// Code for comms
1788				$fields_list['comm_media'][$this->comms_fixed($key, $name)] = $value;
1789				unset($fields_list[$field]);
1790				break;
1791			case 'org':
1792				list($org_key, $name) = explode('_', $name, 2);
1793				switch($key)
1794				{
1795				case 'addr':
1796					// Code for locations
1797					$fields_list['org_data']['location'][$org_key][$name] = $value;
1798					unset($fields_list[$field]);
1799					$fields_list['org_data']['location'][$org_key]['type'] = $addr_keys[$org_key];
1800					break;
1801				case 'comm':
1802					// Code for comms
1803					$fields_list['org_data']['comm_media'][$this->comms_fixed($org_key, $name)] = $value;
1804					unset($fields_list[$field]);
1805					break;
1806				default:
1807					// code for default (principal/others)
1808					$fields_list['org_data'][$field] = $value;
1809					unset($fields_list[$field]);
1810				}
1811			}
1812		}
1813
1814		/**
1815		* Get all the data for any contact or contacts that are part of $optional_criteria.
1816		*
1817		* This function try to be a comprensive way to get data from contacts
1818		* convert the contacts database output on a multidimensional array
1819		* @param integer|array $contact_id
1820		* @param mixed $optional_criteria criteria built with sql_criteria
1821		* @param integer $line where this function is called, usefull for debug
1822		* @param integer $file where this function is called, usefull for debug
1823		* @return array All the data of contact (contacts).
1824		*/
1825		function person_complete_data($contact_id, $optional_criteria = '', $line=__LINE__, $file=__FILE__)
1826		{
1827			$this->request($this->import_export_fields);
1828			if (empty($optional_criteria))
1829			{
1830				if (intval($contact_id) == 0)
1831				{
1832					// this is an error
1833					return ;
1834				}
1835				$this->criteria_token(sql_criteria::_equal('contact_id', $contact_id));
1836			}
1837			else
1838			{
1839				$this->criteria_token($optional_criteria);
1840			}
1841
1842			$sql = $this->get_sql();
1843
1844			$this->execute_query($sql, $line, $file);
1845
1846			while ($this->db->next_record())
1847			{
1848				$record = $this->db->Record;
1849				$contact['contact_id']		= $record['contact_id'];
1850				$contact['access']		= $record['access'];
1851				$contact['owner']		= $record['owner'];
1852				$contact['full_name']		= $record['per_full_name'];
1853				$contact['first_name']		= $record['per_first_name'];
1854				$contact['last_name']		= $record['per_last_name'];
1855				$contact['middle_name']		= $record['per_middle_name'];
1856				$contact['suffix']		= $record['per_suffix'];
1857				$contact['prefix']		= $record['per_prefix'];
1858				$contact['birthday']		= $record['per_birthday'];
1859				$contact['pubkey']		= $record['per_pubkey'];
1860				$contact['title']		= $record['per_title'];
1861				$contact['department']		= $record['per_department'];
1862				$contact['initials']		= $record['per_initials'];
1863				$contact['sound']		= $record['per_sound'];
1864				$contact['active']		= $record['per_active'];
1865				$contact['createon']		= $record['per_creaton'];
1866				$contact['createby']		= $record['per_creatby'];
1867				$contact['modby']		= $record['per_modby'];
1868				$contact['modon']		= $record['per_modon'];
1869				$contact['account_id']		= $record['account_id'];
1870				$contact['org_name']		= $record['org_name'];
1871				// Locations info
1872				$loc_id				= $record['key_addr_id'];
1873				if($loc_id)
1874				{
1875					$contact['locations'][$loc_id]['type']		= $record['addr_description'];
1876					$contact['locations'][$loc_id]['add1']		= $record['addr_add1'];
1877					$contact['locations'][$loc_id]['add2']		= $record['addr_add2'];
1878					$contact['locations'][$loc_id]['add3']		= $record['addr_add3'];
1879					$contact['locations'][$loc_id]['address']	= $record['addr_address'];
1880					$contact['locations'][$loc_id]['city']		= $record['addr_city'];
1881					$contact['locations'][$loc_id]['state']		= $record['addr_state'];
1882					$contact['locations'][$loc_id]['postal_code']	= $record['addr_postal_code'];
1883					$contact['locations'][$loc_id]['country']	= $record['addr_country'];
1884					$contact['locations'][$loc_id]['preferred']	= $record['addr_preferred'];
1885				}
1886				// Notes
1887				$note_id 					= $record['key_note_id'];
1888				if($note_id)
1889				{
1890					$contact['notes'][$note_id]['text']		= $record['note_text'];
1891					$contact['notes'][$note_id]['type']		= $record['note_description'];
1892				}
1893				// Communcation media fields
1894				if($record['comm_data'])
1895				{
1896					$comm_descr 				= $record['comm_description'];
1897					//$contact[$comm_descr]			= $record['comm_data'];
1898					$contact['comm_media'][$comm_descr]	= $record['comm_data'];
1899				}
1900				// Other fields
1901				if($record['other_value'])
1902				{
1903					$contact[$record['other_name']]		= $record['other_value'];
1904				}
1905			}
1906			return $contact;
1907		}
1908
1909
1910		/**
1911		* Search location id in location catalog
1912		*
1913		* @param integer $id The location id to find
1914		* @return string The description of id
1915		*/
1916		function search_location_type_id($id)
1917		{
1918			return $this->search_catalog('addr_type_id', $id, 'addr_description', 'addr_type');
1919		}
1920
1921		/**
1922		* Search location type in location catalog
1923		*
1924		* @param string $description The location description to find
1925		* @return integer The id of description
1926		*/
1927		function search_location_type($description)
1928		{
1929			return $this->search_catalog('addr_description', $description, 'addr_type_id', 'addr_type');
1930		}
1931
1932		/**
1933		* Search location id in location catalog
1934		*
1935		* @param integer $id The location id to find
1936		* @return string The description of id
1937		*/
1938		function search_note_type_id($id)
1939		{
1940			return $this->search_catalog('note_type_id', $id, 'note_description', 'note_type');
1941		}
1942
1943		/**
1944		* Search location type in location catalog
1945		*
1946		* @param string $description The location description to find
1947		* @return integer The id of description
1948		*/
1949		function search_note_type($description)
1950		{
1951			return $this->search_catalog('note_description', $description, 'note_type_id', 'note_type');
1952		}
1953
1954		/**
1955		* Search communication type id in communications catalog
1956		*
1957		* @param integer $id The communication id to find
1958		* @return string The description type of id
1959		*/
1960		function search_comm_type_id($id)
1961		{
1962			return $this->search_catalog('comm_type_id', $id, 'comm_type_description', 'comm_type');
1963		}
1964
1965		/**
1966		* Search communication type in location catalog
1967		*
1968		* @param string $description The communication type to find
1969		* @return integer The id of description
1970		*/
1971		function search_comm_type($description)
1972		{
1973			return $this->search_catalog('comm_type_description', $description, 'comm_type_id', 'comm_type');
1974		}
1975
1976		/**
1977		* Search communication id in communications description catalog
1978		*
1979		* @param integer $id The communication description id to find
1980		* @return string The description text of id
1981		*/
1982		function search_comm_descr_id($id)
1983		{
1984			return $this->search_catalog('comm_descr_id', $id, 'comm_description', 'comm_descr');
1985		}
1986
1987		/**
1988		* Search communication description in communications description catalog
1989		*
1990		* @param string $description The communication type to find
1991		* @return integer The id of description
1992		*/
1993		function search_comm_descr($description)
1994		{
1995			return $this->search_catalog('comm_description', $description, 'comm_descr_id', 'comm_descr');
1996		}
1997
1998		/**
1999		* Search contact type id in contact type catalog
2000		*
2001		* @param integer $id The contact type id to find
2002		* @return string The description text of id
2003		*/
2004		function search_contact_type_id($id)
2005		{
2006			return $this->search_catalog('contact_type_id', $id, 'contact_type_descr', 'contact_type');
2007		}
2008
2009
2010		/**
2011		* Search contact type description in contact type catalog
2012		*
2013		* @param string $description The contact type description to find
2014		* @return integer The id of description
2015		*/
2016		function search_contact_type($description)
2017		{
2018			return $this->search_catalog('contact_type_descr', $description, 'contact_type_id', 'contact_type');
2019		}
2020
2021
2022		/**
2023		* Allow edit information of an existent contact
2024		*
2025		* Allow edit many communications media, locations, categories and others fields, that already exist for a given contact.
2026		* @param integer $cid Contact Id that want to be edited.
2027		* @param array $principal Principal information for contact, its depends on $type, but is according which each definition
2028		* @param integer $action PHPGW_SQL_RETURN_SQL | PHPGW_SQL_RUN_SQL depending what we want
2029		* @return string SQL update string
2030		*/
2031		function edit_contact($cid, $principal, $action=PHPGW_SQL_RETURN_SQL)
2032		{
2033			$contact = CreateObject('phpgwapi.contact_central');
2034			if (isset($principal['cat_id']))
2035			{
2036				$principal['cat_id'] = $this->get_categories($principal['cat_id']);
2037			}
2038			if(!isset($principal['owner']))
2039			{
2040				$principal['owner'] = $GLOBALS['phpgw_info']['user']['account_id'];
2041			}
2042			return $contact->update($principal, sql_criteria::_equal('contact_id',sql::integer($cid)), $action);
2043		}
2044
2045		/**
2046		* Allow edit information of an person
2047		*
2048		* @param integer $id Person Id that want to be edited.
2049		* @param array $data Principal information for person
2050		* @param integer $action PHPGW_SQL_RETURN_SQL | PHPGW_SQL_RUN_SQL depending what we want
2051		* @return string SQL update string
2052		*/
2053		function edit_person($id, $data, $action=PHPGW_SQL_RUN_SQL)
2054		{
2055			$person = CreateObject('phpgwapi.contact_person');
2056			if(!isset($data['per_modon']))
2057			{
2058				$data['per_modon'] = $this->get_mkdate();
2059			}
2060			if(!isset($data['per_modby']))
2061			{
2062				$data['per_modby'] = $this->get_user_id();
2063			}
2064			return $person->update($data, sql_criteria::_equal('person_id',sql::integer($id)), $action);
2065		}
2066
2067		/**
2068		* Allow edit information of an org
2069		*
2070		* @param integer $id Org Id that want to be edited.
2071		* @param array $data Information for contact
2072		* @param integer $action PHPGW_SQL_RETURN_SQL | PHPGW_SQL_RUN_SQL depending what we want
2073		* @return string SQL update string
2074		*/
2075		function edit_org($id, $data, $action=PHPGW_SQL_RETURN_SQL)
2076		{
2077			$org = CreateObject('phpgwapi.contact_org');
2078			if(!isset($data['org_modon']))
2079			{
2080				$data['org_modon'] = $this->get_mkdate();
2081			}
2082			if(!isset($data['org_modby']))
2083			{
2084				$data['org_modby'] = $this->get_user_id();
2085			}
2086			return $org->update($data, sql_criteria::_equal('org_id',sql::integer($id)), $action);
2087		}
2088
2089
2090		/**
2091		* Allow edit location information of an contact
2092		*
2093		* @param integer $id Contact location Id that want to be edited.
2094		* @param array $data Information for contact
2095		* @param integer $action PHPGW_SQL_RETURN_SQL | PHPGW_SQL_RUN_SQL depending what we want
2096		* @return string SQL update string
2097		*/
2098		function edit_location($id, $data, $action=PHPGW_SQL_RETURN_SQL)
2099		{
2100			$loc = CreateObject('phpgwapi.contact_addr');
2101			if(!isset($data['addr_modon']))
2102			{
2103				$data['addr_modon'] = $this->get_mkdate();
2104			}
2105			if(!isset($data['addr_modby']))
2106			{
2107				$data['addr_modby'] = $this->get_user_id();
2108			}
2109			return $loc->update($data, sql_criteria::_equal('contact_addr_id',sql::integer($id)), $action);
2110		}
2111
2112		/**
2113		* Allow edit all location information of an contact
2114		*
2115		* @param integer $contact_id Contact Id that want to be edited.
2116		* @param array $data Information for contact
2117		* @param integer $action PHPGW_SQL_RETURN_SQL | PHPGW_SQL_RUN_SQL depending what we want
2118		* @return string SQL update string
2119		*/
2120		function edit_location_by_contact($contact_id, $data, $action=PHPGW_SQL_RETURN_SQL)
2121		{
2122			$loc = CreateObject('phpgwapi.contact_addr');
2123			if(!isset($data['addr_modon']))
2124			{
2125				$data['addr_modon'] = $this->get_mkdate();
2126			}
2127			if(!isset($data['addr_modby']))
2128			{
2129				$data['addr_modby'] = $this->get_user_id();
2130			}
2131			return $loc->update($data, sql_criteria::_equal('contact_id',sql::integer($contact_id)), $action);
2132		}
2133
2134		/**
2135		* Allow edit communication information of an contact
2136		*
2137		* @param integer $id Contact comm Id that want to be edited.
2138		* @param array $data Information for contact
2139		* @param integer $action PHPGW_SQL_RETURN_SQL | PHPGW_SQL_RUN_SQL depending what we want
2140		* @return string SQL update string
2141		*/
2142		function edit_comms($id, $data, $action=PHPGW_SQL_RETURN_SQL)
2143		{
2144			$comm = CreateObject('phpgwapi.contact_comm');
2145			if(!isset($data['comm_modon']))
2146			{
2147				$data['comm_modon'] = $this->get_mkdate();
2148			}
2149			if(!isset($data['comm_modby']))
2150			{
2151				$data['comm_modby'] = $this->get_user_id();
2152			}
2153			return $comm->update($data, sql_criteria::_equal('comm_id',sql::integer($id)), $action);
2154		}
2155
2156		/**
2157		* Allow edit other information of an contact
2158		*
2159		* @param integer $id Contact other Id that want to be edited.
2160		* @param array $data Information for contact
2161		* @param integer $action PHPGW_SQL_RETURN_SQL | PHPGW_SQL_RUN_SQL depending what we want
2162		* @return string SQL update string
2163		*/
2164		function edit_other($id, $data, $action=PHPGW_SQL_RETURN_SQL)
2165		{
2166			$other = CreateObject('phpgwapi.contact_others');
2167			if(!isset($data['other_modon']))
2168			{
2169				$data['other_modon'] = $this->get_mkdate();
2170			}
2171			if(!isset($data['other_modby']))
2172			{
2173				$data['other_modby'] = $this->get_user_id();
2174			}
2175			return $other->update($data, sql_criteria::_equal('other_id',sql::integer($id)), $action);
2176		}
2177
2178		/**
2179		* Allow edit communication information of an contact
2180		*
2181		* @param integer $id Contact Id that want to be edited.
2182		* @param array $data Information for contact
2183		* @param integer $action PHPGW_SQL_RETURN_SQL | PHPGW_SQL_RUN_SQL depending what we want
2184		* @return string SQL update string
2185		*/
2186		function edit_comms_by_contact($id, $data, $action=PHPGW_SQL_RETURN_SQL)
2187		{
2188			$comm = CreateObject('phpgwapi.contact_comm');
2189			if(!isset($data['comm_modon']))
2190			{
2191				$data['comm_modon'] = $this->get_mkdate();
2192			}
2193			if(!isset($data['comm_modby']))
2194			{
2195				$data['comm_modby'] = $this->get_user_id();
2196			}
2197			return $comm->update($data, sql_criteria::_equal('contact_id',sql::integer($id)), $action);
2198		}
2199
2200		/**
2201		* Allow edit org-person relation of an contact
2202		*
2203		* @param integer $org_id Organization Id that want to be edited.
2204		* @param integer $person_id Person Id that want to be edited.
2205		* @param array $data Information for contact
2206		* @param integer $action PHPGW_SQL_RETURN_SQL | PHPGW_SQL_RUN_SQL depending what we want
2207		* @return string SQL update string
2208		*/
2209		function edit_org_person_relation($org_id='', $person_id='', $data=array(), $action=PHPGW_SQL_RETURN_SQL)
2210		{
2211			$relation = CreateObject('phpgwapi.contact_org_person');
2212			if($org_id && $person_id)
2213			{
2214				$criteria = sql_criteria::and_(sql_criteria::equal('org_id',sql::integer($org_id)),
2215							       sql_criteria::equal('person_id',sql::integer($person_id)));
2216			}
2217			elseif($org_id)
2218			{
2219				$criteria = sql_criteria::equal('org_id',sql::integer($org_id));
2220			}
2221			elseif($person_id)
2222			{
2223				$criteria = sql_criteria::equal('person_id',sql::integer($person_id));
2224			}
2225
2226			return $relation->update($data, $criteria, $action);
2227		}
2228
2229		/**
2230		* Allow to change the current owner for the new
2231		*
2232		* @param integer $old_owner Current owner
2233		* @param integer $new_owner New owner, wath you want to have now.
2234		* @return string SQL update string
2235		*/
2236		function change_owner($old_owner='',$new_owner='')
2237		{
2238			if (!($new_owner && $old_owner))
2239			{
2240				return False;
2241			}
2242			$contact = CreateObject('phpgwapi.contact_central');
2243			return $contact->update(array('owner' => $new_owner),
2244						sql_criteria::_equal('owner',sql::integer($old_owner)),
2245						PHPGW_SQL_RUN_SQL);
2246		}
2247
2248		/**
2249		* Allow to change the current owner for the new
2250		*
2251		* @param integer $old_owner Current owner
2252		* @param integer $new_owner New owner, wath you want to have now.
2253		* @return string SQL update string
2254		*/
2255		function change_owner_others($old_owner='',$new_owner='')
2256		{
2257			if (!($new_owner && $old_owner))
2258			{
2259				return False;
2260			}
2261			$contact = CreateObject('phpgwapi.contact_others');
2262			return $contact->update(array('contact_owner' => $new_owner),
2263						sql_criteria::_equal('contact_owner',sql::integer($old_owner)),
2264						PHPGW_SQL_RUN_SQL);
2265		}
2266
2267		/**
2268		* Allow to edit the current other data for the owner, you can modify other_name or other_value fields
2269		*
2270		* @param integer $id the owner id
2271		* @param string $new_data The new value which you want to update.
2272		* @param string $old_data The current value which you want to update.
2273		* @param string $field_data The field is can be other_name or other_value
2274		* @param integer $action PHPGW_SQL_RETURN_SQL | PHPGW_SQL_RUN_SQL depending what we want
2275		* @return string SQL update string
2276		*/
2277		function edit_other_by_owner($id, $new_data, $old_data, $field_data, $action=PHPGW_SQL_RUN_SQL)
2278		{
2279			$other = CreateObject('phpgwapi.contact_others');
2280			$criteria = sql_criteria::append_and(array(sql_criteria::equal('contact_owner', sql::integer($id)),
2281								   sql_criteria::equal($field_data, sql::string($old_data))));
2282			return $other->update(array($field_data => $new_data), $criteria, $action);
2283		}
2284
2285		/**
2286		* Allow to change the current cat_id by the new
2287		*
2288		* @param integer $cid The contact_id what you want to edit
2289		* @param array $categories The new categories
2290		* @param $action
2291		* @return string SQL update string
2292		*/
2293		function edit_category($cid, $categories=array(), $action=PHPGW_SQL_RETURN_SQL)
2294		{
2295			$contact = CreateObject('phpgwapi.contact_central');
2296			$principal['cat_id'] = $this->get_categories($categories);
2297			return $contact->update($principal, sql_criteria::_equal('contact_id',sql::integer($cid)), $action);
2298		}
2299
2300
2301		/**
2302		 * Add a contact and it's data
2303		 *
2304		 * If account_person_id will be null for each person that is not a user.
2305		 * @param mixed $type Type of contact, for either `organzation' or `person'
2306		 * @param array $principal Principal information for contact, its depends on $type, but is according which each definition
2307		 * @param array $comms Information relative to communication media
2308		 * @param array $location Information relative to locations.
2309		 * @param array $categeries Catagories in which contact must be added.
2310		 * @param array $others Others fields to be added.
2311		 * @param array $contact_relations the org_id or the person_id for this person or organzation
2312		 * @param array $notes Notes to be added.
2313		 * @return integer New contact ID
2314		 */
2315		function add_contact($type, $principal=array(), $comms=array(), $locations=array(), $categories=array(), $others=array(), $contact_relations=array(), $notes=array())
2316		{
2317			$this->contact = CreateObject('phpgwapi.contact_central');
2318			$owner = $principal['owner']?$principal['owner']:$GLOBALS['phpgw_info']['user']['account_id'];
2319			$this->lock_table($this->contact->table);
2320
2321			$this->contact->insert(array('owner' => $owner,
2322						     'access' => $principal['access'],
2323						     'cat_id' => $this->get_categories($categories),
2324						     'contact_type' => $type), PHPGW_SQL_RUN_SQL);
2325			$cid = $this->last_id('contact', 'contact_id');
2326			$this->unlock_table();
2327			$add_type = $this->search_contact_type_id($type);
2328			switch($add_type)
2329			{
2330			case $this->_contact_person:
2331				$this->add_person($principal, $cid, PHPGW_SQL_RUN_SQL);
2332				$this->add_orgs_for_person($contact_relations, $principal['preferred_org'], $principal['preferred_address'], $cid, PHPGW_SQL_RUN_SQL);
2333				break;
2334			case $this->_contact_org:
2335				$this->add_org($principal, $cid, PHPGW_SQL_RUN_SQL);
2336				$this->add_people_for_organzation($contact_relations, $cid, PHPGW_SQL_RUN_SQL);
2337				break;
2338			}
2339
2340			if(is_array($comms))
2341			{
2342				foreach($comms as $comm)
2343				{
2344					$this->add_communication_media($comm, $cid, PHPGW_SQL_RUN_SQL);
2345					$this->unlock_table();
2346				}
2347			}
2348			if(is_array($locations))
2349			{
2350				foreach($locations as $location)
2351				{
2352					$this->add_location($location, $cid, PHPGW_SQL_RUN_SQL);
2353					$this->unlock_table();
2354				}
2355			}
2356
2357			if(is_array($others))
2358			{
2359				foreach($others as $other)
2360				{
2361					$this->add_others($other, $cid, PHPGW_SQL_RUN_SQL);
2362					$this->unlock_table();
2363				}
2364			}
2365			if(is_array($notes))
2366			{
2367				foreach($notes as $note)
2368				{
2369					$this->add_note($note, $cid, PHPGW_SQL_RUN_SQL);
2370					$this->unlock_table();
2371				}
2372			}
2373
2374			if($add_type == $this->_contact_person)
2375			{
2376				$this->finalize_add($cid);
2377			}
2378			return $cid;
2379		}
2380
2381		/**
2382		* Add an organization and it's data
2383		*
2384		* @param array $principal Principal information for organization
2385		* @param integer $cid Organization id
2386		* @param integer $action PHPGW_SQL_RETURN_SQL | PHPGW_SQL_RUN_SQL depending what we want
2387		* @return SQL insert string or nothing
2388		*/
2389		function add_org($principal, $cid, $action=PHPGW_SQL_RETURN_SQL)
2390		{
2391			$this->org = CreateObject('phpgwapi.contact_org');
2392			if ($action == PHPGW_SQL_RUN_SQL)
2393			{
2394				$this->lock_table($this->org->table);
2395			}
2396			$this->lock_table($this->org->table);
2397			$principal['org_creaton'] = (isset($principal['org_creaton'])?$principal['org_creaton']:$this->get_mkdate());
2398			$principal['org_creatby'] = $this->get_user_id();
2399			$principal['org_modon'] = (isset($principal['org_modon'])?$principal['org_modon']:$this->get_mkdate());
2400			$principal['org_modby'] = $this->get_user_id();
2401
2402			$execute = $this->_add($principal,'org','org_id',$cid, $action);
2403			$this->unlock_table();
2404			return $execute;
2405		}
2406
2407		/**
2408		* Add a person and it's data
2409		*
2410		* @param array $principal Principal information for person
2411		* @param integer $cid  person id
2412		* @param integer $action PHPGW_SQL_RETURN_SQL | PHPGW_SQL_RUN_SQL depending what we want
2413		* @return SQL insert string or nothing
2414		*/
2415		function add_person($principal, $cid, $action=PHPGW_SQL_RETURN_SQL)
2416		{
2417			$this->person = CreateObject('phpgwapi.contact_person');
2418			if ($action == PHPGW_SQL_RUN_SQL)
2419			{
2420				$this->lock_table($this->person->table);
2421			}
2422			$this->lock_table($this->person->table);
2423			$principal['per_creaton'] = (isset($principal['per_creaton'])?$principal['per_creaton']:$this->get_mkdate());
2424			$principal['per_creatby'] = $this->get_user_id();
2425			$principal['per_modon'] = (isset($principal['per_modon'])?$principal['per_modon']:$this->get_mkdate());;
2426			$principal['per_modby'] = $this->get_user_id();
2427
2428			$execute = $this->_add($principal,'person','person_id',$cid, $action);
2429			$this->unlock_table();
2430			//$this->finalize_add($cid);
2431			return $execute;
2432		}
2433
2434		/**
2435		* Add a people for a organizations
2436		*
2437		* @param array $people People id which you want to insert
2438		* @param integer $cid Organization id
2439		* @param integer $action PHPGW_SQL_RETURN_SQL | PHPGW_SQL_RUN_SQL depending what we want
2440		* @return SQL insert string or nothing
2441		*/
2442		function add_people_for_organzation($people, $cid, $action=PHPGW_SQL_RETURN_SQL)
2443		{
2444			if(!is_array($people))
2445			{
2446// 				echo "There is no any person to add in your array";
2447// 				This must be a critical error to stop everything?
2448// 				$GLOBALS['phpgw']->exit();
2449				return;
2450			}
2451
2452			foreach($people as $person)
2453			{
2454				$orgs = $this->has_preferred_org($person);
2455				$this->relations = CreateObject('phpgwapi.contact_org_person');
2456				$data['my_person_id'] = $person;
2457				$data['my_creaton'] = $this->get_mkdate();
2458				$data['my_creatby'] = $this->get_user_id();
2459				if(count($orgs[0]) == 0)
2460				{
2461					$data['my_preferred'] = 'Y';
2462				}
2463				else
2464				{
2465					$data['my_preferred'] = 'N';
2466				}
2467
2468				if ($action == PHPGW_SQL_RUN_SQL)
2469				{
2470					$this->lock_table($this->relations->table);
2471				}
2472				$sql[] = $this->_add($data,'relations', 'my_org_id', $cid, $action);
2473				$this->unlock_table();
2474			}
2475			return $sql;
2476		}
2477
2478		/**
2479		* Add a organizations for a person
2480		*
2481		* @param array $oragnizations Organizations id which you want to insert
2482		* @param integer $preferred_org Organization id from preferred organization
2483		* @param integer $addr_id Address id from preferred organization
2484		* @param integer $cid Person id
2485		* @param integer $action PHPGW_SQL_RETURN_SQL | PHPGW_SQL_RUN_SQL depending what we want
2486		* @return SQL insert string or nothing
2487		*/
2488		function add_orgs_for_person($organizations, $preferred_org, $addr_id, $cid, $action=PHPGW_SQL_RETURN_SQL)
2489		{
2490			if(is_array($organizations))
2491			{
2492				foreach($organizations as $org)
2493				{
2494					$this->relations = CreateObject('phpgwapi.contact_org_person');
2495					$data['my_org_id'] = $org;
2496					$data['my_addr_id'] = $addr_id;
2497					if ($preferred_org == $org)
2498					{
2499						$data['my_preferred'] = 'Y';
2500					}
2501					else
2502					{
2503						$data['my_preferred'] = 'N';
2504					}
2505					$data['my_creaton'] = $this->get_mkdate();
2506					$data['my_creatby'] = $this->get_user_id();
2507					if ($action == PHPGW_SQL_RUN_SQL)
2508					{
2509						$this->lock_table($this->relations->table);
2510					}
2511					$sql[] = $this->_add($data,'relations', 'my_person_id', $cid, $action);
2512					$this->unlock_table();
2513				}
2514			}
2515			return $sql;
2516		}
2517
2518		/**
2519		* Add a locations for a contact
2520		*
2521		* @param array $location Locations information for contact
2522		* @param integer $cid contact id
2523		* @param integer $action PHPGW_SQL_RETURN_SQL | PHPGW_SQL_RUN_SQL depending what we want
2524		* @return SQL insert string or nothing
2525		*/
2526		function add_location($location, $cid, $action=PHPGW_SQL_RETURN_SQL)
2527		{
2528			$addr = $this->has_preferred_location($cid);
2529			$this->location = CreateObject('phpgwapi.contact_addr');
2530			if ($action == PHPGW_SQL_RUN_SQL)
2531			{
2532				$this->lock_table($this->location->table);
2533			}
2534			if(count($addr[0]) == 0)
2535			{
2536				$location['addr_preferred'] = 'Y';
2537			}
2538			else
2539			{
2540				$location['addr_preferred'] = 'N';
2541			}
2542
2543			$location['addr_creaton'] = (isset($location['addr_creaton'])?$location['addr_creaton']:$this->get_mkdate());
2544			$location['addr_creatby'] = $this->get_user_id();
2545			$location['addr_modon'] = (isset($location['addr_modon'])?$location['addr_modon']:$this->get_mkdate());;
2546			$location['addr_modby'] = $this->get_user_id();
2547
2548			unset($location['key_addr_id']);
2549
2550			return $this->_add($location,'location','addr_contact_id',$cid, $action);
2551		}
2552
2553		/**
2554		* Add a communications for a contact
2555		*
2556		* @param array $comm Communications information for contact
2557		* @param integer $cid  contact id
2558		* @param integer $action PHPGW_SQL_RETURN_SQL | PHPGW_SQL_RUN_SQL depending what we want
2559		* @return SQL insert string or nothing
2560		*/
2561		function add_communication_media($comm, $cid = '', $action=PHPGW_SQL_RETURN_SQL)
2562		{
2563			$this->comm = CreateObject('phpgwapi.contact_comm');
2564			if ($action == PHPGW_SQL_RUN_SQL)
2565			{
2566				$this->lock_table($this->comm->table);
2567			}
2568
2569			$comm['comm_creaton'] = (isset($comm['comm_creaton'])?$comm['comm_creaton']:$this->get_mkdate());
2570			$comm['comm_creatby'] = $this->get_user_id();
2571			$comm['comm_modon'] = (isset($comm['comm_modon'])?$comm['comm_modon']:$this->get_mkdate());;
2572			$comm['comm_modby'] = $this->get_user_id();
2573
2574			unset($comm['key_comm_id']);
2575
2576			return $this->_add($comm,'comm','comm_contact_id',$cid, $action);
2577		}
2578
2579		/**
2580		* Add a note for a contact
2581		*
2582		* @param array $note Note information for contact
2583		* @param integer $cid  contact id
2584		* @param integer $action PHPGW_SQL_RETURN_SQL | PHPGW_SQL_RUN_SQL depending what we want
2585		* @return SQL insert string or nothing
2586		*/
2587		function add_note($note, $cid = '', $action=PHPGW_SQL_RETURN_SQL)
2588		{
2589			$this->note = CreateObject('phpgwapi.contact_note');
2590			if ($action == PHPGW_SQL_RUN_SQL)
2591			{
2592				$this->lock_table($this->note->table);
2593			}
2594
2595			$note['note_creaton'] = (isset($note['note_creaton'])?$note['note_creaton']:$this->get_mkdate());
2596			$note['note_creatby'] = $this->get_user_id();
2597			$note['note_modon'] = (isset($note['note_modon'])?$note['note_modon']:$this->get_mkdate());;
2598			$note['note_modby'] = $this->get_user_id();
2599
2600			unset($comm['key_note_id']);
2601
2602			return $this->_add($note,'note','note_contact_id',$cid,$action);
2603		}
2604
2605		/**
2606		* Add a others for a contact
2607		*
2608		* @param array $others Others information for contact
2609		* @param integer $cid contact id
2610		* @param integer $action PHPGW_SQL_RETURN_SQL | PHPGW_SQL_RUN_SQL depending what we want
2611		* @return SQL insert string or nothing
2612		*/
2613		function add_others($others, $cid='', $action=PHPGW_SQL_RETURN_SQL)
2614		{
2615			$this->others = CreateObject('phpgwapi.contact_others');
2616			if ($action == PHPGW_SQL_RUN_SQL)
2617			{
2618				$this->lock_table($this->others->table);
2619			}
2620
2621			unset($others['key_other_id']);
2622
2623			return $this->_add($others,'others','other_contact_id',$cid, $action);
2624		}
2625
2626
2627		/**
2628		* Delete all data of this contact_id
2629		*
2630		* @param mixed $cid The contact_id or any list of contacts_id
2631		* @param string $contact_type Contact type
2632		* @param boolean $transaction Use transaction
2633		* @return boolean|array Error reason strings from different applications
2634		*/
2635		function delete($cid, $contact_type='', $transaction=True)
2636		{
2637			// check for hooks saying "do not delete"
2638			if(!is_object($GLOBALS['phpgw']->hooks) )
2639			{
2640				$GLOBALS['phpgw']->hooks = createObject('phpgwapi.hooks');
2641			}
2642			$hook_response= $GLOBALS['phpgw']->hooks->process(array(
2643								'location' => 'delete_addressbook',
2644								'contact_id' => $cid )
2645							);
2646
2647			$negative_apps=false;
2648			foreach($hook_response as $application => $response)
2649			{
2650				if(is_array($response))
2651				{
2652					if(!$response['can_delete'])
2653					{
2654						$negative_apps[$application]=$response['reason'];
2655					}
2656				}
2657			}
2658
2659			if( $negative_apps )
2660			{
2661				$return_value = $negative_apps;
2662			}
2663			else
2664			{
2665				$type = ($contact_type)? $contact_type : $this->search_contact_type_id($this->get_type_contact($cid));
2666				$type = ($type == $this->_contact_person) ? 'person' : 'org';
2667
2668
2669				if(empty($entity_keys))
2670				{
2671					$entity_keys = array('contact_id',
2672							// $type= org | person therefore: here goes person_id or org_id
2673							$type.'_id',
2674							// in addition: here goes my_person_id or my_org_id
2675							'my_'.$type.'_id',
2676							'addr_contact_id',
2677							'note_contact_id',
2678							'other_contact_id',
2679							'comm_contact_id');
2680				}
2681				if($transaction)
2682				{
2683					$this->transaction_begin();
2684				}
2685				foreach ($entity_keys as $key)
2686				{
2687					$return_value = $this->_delete(sql_criteria::_equal($key, $cid), PHPGW_SQL_RUN_SQL);
2688				}
2689				if($transaction)
2690				{
2691					$this->transaction_end();
2692				}
2693
2694				if ($contact_type == $this->_contact_person)
2695				{
2696					$this->finalize_delete($cid);
2697				}
2698			}
2699			return $return_value;
2700		}
2701
2702		/**
2703		* Delete principal data of this contact_id
2704		*
2705		* @param mixed $cid The contact_id or any list of contacts_id
2706		* @param mixed $contact_type Contact type
2707		* @param integer $action PHPGW_SQL_RETURN_SQL | PHPGW_SQL_RUN_SQL
2708		* @return boolean|array Error reason strings from different applications
2709		*/
2710		function delete_contact($cid, $contact_type='', $action=PHPGW_SQL_RUN_SQL)
2711		{
2712			// check for hooks saying "do not delete"
2713			$hook_response= $GLOBALS['phpgw']->hooks->process(array(
2714								'location' => 'delete_addressbook',
2715								'contact_id' => $cid )
2716							);
2717			$negative_apps=false;
2718			foreach($hook_response as $application => $response)
2719			{
2720				if(is_array($response))
2721				{
2722					if(!$response['can_delete'])
2723					{
2724						$negative_apps[$application]=$response['reason'];
2725					}
2726				}
2727			}
2728
2729			if( $negative_apps )
2730			{
2731				$return_value = $negative_apps;
2732			}
2733			else
2734			{
2735				$type = ($contact_type)? $contact_type : $this->search_contact_type_id($this->get_type_contact($cid));
2736				$type = ($type == $this->_contact_person) ? 'person' : 'org';
2737				if ($action == PHPGW_SQL_RUN_SQL)
2738				{
2739					$this->transaction_begin();
2740				}
2741				$return_value[] = $this->_delete(sql_criteria::_equal('contact_id', $cid), $action);
2742				$return_value[] = $this->_delete(sql_criteria::_equal($type.'_id', $cid), $action);
2743				if ($action == PHPGW_SQL_RUN_SQL)
2744				{
2745					$this->transaction_end();
2746				}
2747			}
2748			return $return_value;
2749		}
2750
2751		/**
2752		* Delete relations between a person and their related orgs
2753		*
2754		* @param mixed $cid The contact_id or any list of contacts_id
2755		* @param integer $action PHPGW_SQL_RETURN_SQL | PHPGW_SQL_RUN_SQL
2756		* @return string Delete SQL string
2757		*/
2758		function delete_orgs_by_person($cid, $action=PHPGW_SQL_RUN_SQL)
2759		{
2760			return $this->_delete(sql_criteria::_equal('my_person_id', $cid), $action);
2761		}
2762
2763		/**
2764		* Delete relations between an org and their related person
2765		*
2766		* @param mixed $cid The contact_id or any list of contacts_id
2767		* @param integer $action PHPGW_SQL_RETURN_SQL | PHPGW_SQL_RUN_SQL
2768		* @return string Delete SQL string
2769		*/
2770		function delete_people_by_org($cid, $action=PHPGW_SQL_RUN_SQL)
2771		{
2772			return $this->_delete(sql_criteria::_equal('my_org_id', $cid), $action);
2773		}
2774
2775		/**
2776		* Delete relations between an org and their related person
2777		*
2778		* @param mixed $org_id
2779		* @param mixed $person_id
2780		* @param integer $action PHPGW_SQL_RETURN_SQL | PHPGW_SQL_RUN_SQL
2781		* @return string Delete SQL string
2782		*/
2783		function delete_org_person_relation($org_id, $person_id, $action=PHPGW_SQL_RUN_SQL)
2784		{
2785			$relations = CreateObject('phpgwapi.contact_org_person');
2786			$this->lock_table($relations->table);
2787			$criteria = $relations->entity_criteria(sql_criteria::token_and(sql_criteria::_equal('my_org_id', $org_id),
2788											sql_criteria::_equal('my_person_id', $person_id)));
2789			$sql = $relations->delete($criteria, $action);
2790			$this->unlock_table();
2791			return $sql;
2792		}
2793
2794		/**
2795		* Delete the address information of contact.
2796		*
2797		* @param integer|array $cid contact_id or list of contact_ids
2798		* @param integer $action PHPGW_SQL_RETURN_SQL | PHPGW_SQL_RUN_SQL
2799		* @return string Delete SQL string
2800		*/
2801		function delete_locations($cid, $action=PHPGW_SQL_RETURN_SQL)
2802		{
2803			return $this->_delete(sql_criteria::_equal('addr_contact_id',$cid), $action);
2804		}
2805
2806		/**
2807		* Delete the communication media for this contact.
2808		*
2809		* @param integer|array $cid contact_id or list of contact_ids
2810		* @param integer $action PHPGW_SQL_RETURN_SQL | PHPGW_SQL_RUN_SQL
2811		* @return string Delete SQL string
2812		*/
2813		function delete_comms($cid, $action=PHPGW_SQL_RETURN_SQL)
2814		{
2815			return $this->_delete(sql_criteria::_equal('comm_contact_id',$cid), $action);
2816		}
2817
2818		/**
2819		* Delete the others fields for this contact.
2820		*
2821		* @param integer|array $cid contact_id or list of contact_ids
2822		* @param integer $action PHPGW_SQL_RETURN_SQL | PHPGW_SQL_RUN_SQL
2823		* @return string Delete SQL string
2824		*/
2825		function delete_others($cid, $action=PHPGW_SQL_RETURN_SQL)
2826		{
2827			return $this->_delete(sql_criteria::_equal('other_contact_id',$cid), $action);
2828		}
2829
2830		/**
2831		* Delete the notes for this contact.
2832		*
2833		* @param integer|array $cid Contact_id or list of contact_ids
2834		* @param integer $action PHPGW_SQL_RETURN_SQL | PHPGW_SQL_RUN_SQL
2835		* @return string Delete SQL string
2836		*/
2837		function delete_notes($cid, $action=PHPGW_SQL_RETURN_SQL)
2838		{
2839			return $this->_delete(sql_criteria::_equal('note_contact_id',$cid), $action);
2840		}
2841
2842		/**
2843		* Delete the specified communication media.
2844		*
2845		* @param integer|array $id Key of the comm media what you want
2846		* @param integer $action PHPGW_SQL_RETURN_SQL | PHPGW_SQL_RUN_SQL
2847		* @return string Delete SQL string
2848		*/
2849		function delete_specified_comm($id, $action=PHPGW_SQL_RETURN_SQL)
2850		{
2851			return $this->_delete(sql_criteria::_equal('key_comm_id',$id), $action);
2852		}
2853
2854		/**
2855		* Delete the specified address.
2856		*
2857		* @param integer|array $id Key of the address what you want
2858		* @param integer $action PHPGW_SQL_RETURN_SQL | PHPGW_SQL_RUN_SQL
2859		* @return string Delete SQL string
2860		*/
2861		function delete_specified_location($id, $action=PHPGW_SQL_RETURN_SQL)
2862		{
2863			return $this->_delete(sql_criteria::_equal('key_addr_id',$id), $action);
2864		}
2865
2866		/**
2867		* Delete the specified others field.
2868		*
2869		* @param integer|array $id Key of the other field what you want
2870		* @param integer $action PHPGW_SQL_RETURN_SQL | PHPGW_SQL_RUN_SQL
2871		* @return string Delete SQL string
2872		*/
2873		function delete_specified_other($id, $action=PHPGW_SQL_RETURN_SQL)
2874		{
2875			return $this->_delete(sql_criteria::_equal('key_other_id',$id), $action);
2876		}
2877
2878		/**
2879		* Delete the specified note.
2880		*
2881		* @param integer|array $id Key of the note what you want
2882		* @param integer $action PHPGW_SQL_RETURN_SQL | PHPGW_SQL_RUN_SQL
2883		* @return string Delete SQL string
2884		*/
2885		function delete_specified_note($id, $action=PHPGW_SQL_RETURN_SQL)
2886		{
2887			return $this->_delete(sql_criteria::_equal('key_note_id',$id), $action);
2888		}
2889
2890		/**
2891		* Delete all contacts of an owner
2892		*
2893		* @param integer $owner Ownder of contacts
2894		* @internal This is for the admin script deleteaccount.php
2895		*/
2896		function delete_all($owner=0)
2897		{
2898			$owner = intval($owner);
2899			if ($owner)
2900			{
2901				$contacts = $this->get_contacts_by_owner($owner);
2902				if(is_array($contacts))
2903				{
2904					foreach ($contacts as $row)
2905					{
2906						$this->delete($row['contact_id']);
2907					}
2908				}
2909			}
2910		}
2911
2912
2913		/**
2914		* This function is the wrapper for getting queries or the sql string
2915		*
2916		* @param integer $action PHPGW_SQL_RETURN_SQL | PHPGW_SQL_RUN_SQL depending what we want
2917		* @param integer $line where this function is called, usefull for debug
2918		* @param integer $file where this function is called, usefull for debug
2919		* @return array|string Array with records or string with sql query
2920		* @access private
2921		*/
2922		function get_query($action=PHPGW_SQL_RUN_SQL, $line=__LINE__, $file=__FILE__)
2923		{
2924			switch($action)
2925			{
2926			case PHPGW_SQL_RETURN_RECORDS:
2927			case PHPGW_SQL_RUN_SQL:
2928				return $this->get_records($line, $file);
2929			case PHPGW_SQL_RETURN_SQL:
2930				return $this->get_sql();
2931			}
2932		}
2933
2934		/**
2935		* This make a common task in many functions. Get the records resulted by get_sql method.
2936		*
2937		* @param integer $line where this function is called, usefull for debug
2938		* @param integer $file where this function is called, usefull for debug
2939		* @return array Recordset with all records in the database.
2940		* @access private
2941		*/
2942		function get_records($line, $file)
2943		{
2944			$this->execute_query($this->get_sql(),$line,$file);
2945			while ($this->db->next_record())
2946			{
2947				$record[] = $this->db->Record;
2948			}
2949			return $record;
2950		}
2951
2952		/**
2953		* Get records from database for one field
2954		*
2955		* @param string $field Database field name
2956		* @param integer $line Program line number that executes this method
2957		* @param string $file File name from which this method was called
2958		* @return array Database results for given field name
2959		* @access private
2960		*/
2961		function get_records_by_field($field, $line=__LINE__, $file=__FILE__)
2962		{
2963			$this->execute_query($this->get_sql(),$line,$file);
2964			while ($this->db->next_record())
2965			{
2966				$record[] = $this->db->f($field);
2967			}
2968			return $record;
2969		}
2970
2971		/**
2972		* Execute SQL query string
2973		*
2974		* @param string $query SQL query string
2975		* @param integer $line Program line number that executes this method
2976		* @param string $file File name from which this method was called
2977		* @access private
2978		*/
2979		function execute_query($query, $line=__LINE__, $file=__FILE__)
2980		{
2981			if (is_null($this->db))
2982			{
2983				$this->db = &$GLOBALS['phpgw']->db;
2984			}
2985			$this->db->query($query, $line, $file);
2986		}
2987
2988		/**
2989		* Execute a list of SQL queries
2990		*
2991		* @param array $queries List of SQL queries
2992		* @access private
2993		*/
2994		function execute_queries($queries=array())
2995		{
2996			if(is_array($queries))
2997			{
2998				foreach($queries as $query)
2999				{
3000					$this->db->query($query, -1, -1);
3001				}
3002			}
3003		}
3004
3005
3006		/**
3007		* Retrieve all the locations of $contacts_id
3008		*
3009		* @param integer|array $contact_id The contact id that will be used for search his data.
3010		* @param array $data This is the information that want to retrieve, according whith phpGroupware Address Specification.
3011		* @param integer $action PHPGW_SQL_RETURN_SQL | PHPGW_SQL_RUN_SQL depending what we want
3012		* @return array Asociative with id and all data that we requested
3013		*/
3014		function get_locations($contact_id, $data, $action=PHPGW_SQL_RUN_SQL)
3015		{
3016			$this->request('contact_id');
3017			$this->request($data);
3018			$this->criteria(array('addr_contact_id' => $contact_id));
3019			return $this->get_query($action,__LINE__, __FILE__);
3020		}
3021
3022		function get_orgs_by_cat($cat_id)
3023		{
3024			$this->request('org_id');
3025			$this->request('org_name');
3026			$this->criteria(array('cat_id' => $cat_id));
3027			$sql = $this->get_sql();
3028			$this->db->query($sql, __LINE__, __FILE__);
3029			while ($this->db->next_record())
3030			{
3031				$orgs = &$this->db->Record;
3032			}
3033			return $orgs;
3034		}
3035
3036		function get_cats_by_person($person_id)
3037		{
3038			$this->request('cat_id');
3039			$this->criteria(array('contact_id' => $person_id));
3040			$cats = $this->get_records_by_field('cat_id', __LINE__, __FILE__);
3041
3042			if($cats[0])
3043			{
3044				$cats_array = explode(',', $cats[0]);
3045			}
3046			else
3047			{
3048				$cats_array=array();
3049			}
3050
3051			return $cats_array;
3052		}
3053
3054		function get_cats_by_org($org_id)
3055		{
3056			$this->request('cat_id');
3057			$this->criteria(array('org_id' => $org_id));
3058			$cats = $this->get_records_by_field('cat_id', __LINE__, __FILE__);
3059			if($cats[0])
3060			{
3061				$cats_array = explode(',', $cats[0]);
3062			}
3063			else
3064			{
3065				$cats_array=array();
3066			}
3067			return $cats_array;
3068		}
3069
3070		function get_cats($fields)
3071		{
3072			$this->request($fields);
3073			$this->db->query($this->get_sql(), __LINE__, __FILE__);
3074			while ($this->db->next_record())
3075			{
3076				$cats[] = $this->db->Record;
3077			}
3078
3079			return $cats;
3080		}
3081
3082		function get_categories($categories)
3083		{
3084			if (is_array($categories))
3085			{
3086				return count($categories) > 1 ? ','.implode(',',$categories).',' : $categories[0];
3087			}
3088			else
3089			{
3090				return $categories;
3091			}
3092		}
3093
3094		function get_addr_by_contact($contact_id)
3095		{
3096			$this->request('addr_address');
3097			$this->criteria(array('addr_contact_id' => $contact_id));
3098			return $this->get_query(PHPGW_SQL_RUN_SQL, __LINE__, __FILE__);
3099		}
3100
3101
3102		/**
3103		* Read phone number for one contact
3104		*
3105		* @param $contacts_id Contact ID
3106		* @deprecated
3107		*/
3108		function get_phone_by_contact($contacts_id)
3109		{
3110			$this->get_phone($contacts_id);
3111		}
3112
3113
3114		/**
3115		* Create a criteria with or and like operators for all the fields
3116		*
3117		* @param array $fields Database field names
3118		* @return string Search result
3119		*/
3120		function search_by_any($fields)
3121		{
3122			foreach($fields as $field => $value)
3123			{
3124				if ($value == NULL)
3125				{
3126					continue;
3127				}
3128				if (is_array($value))
3129				{
3130					if(in_array('append_or', $value) || in_array('append_and', $value))
3131					{
3132						$elements[] = $value;
3133					}
3134					else
3135					{
3136						$elements[] = sql_criteria::in($field, $value);
3137					}
3138				}
3139				else
3140				{
3141					$elements[] = sql_criteria::token_has($field, $value);
3142				}
3143			}
3144			return sql_criteria::_append_or($elements);
3145		}
3146
3147		/**
3148		* Create a criteria with `and' and the corresponding operator of each field.
3149		*
3150		* @param array $fields Database field names
3151		* @return string Search result
3152		*/
3153		function search_by_all($fields)
3154		{
3155			foreach($fields as $field => $value)
3156			{
3157				if ($value == NULL)
3158				{
3159					continue;
3160				}
3161
3162				if (is_array($value))
3163				{
3164					if(in_array('append_or', $value) || in_array('append_and', $value))
3165					{
3166						$elements[] = $value;
3167					}
3168					else
3169					{
3170						if (count($value) == 1)
3171						{
3172							$elements[] = sql_criteria::_equal($field, current($value));
3173						}
3174						else
3175						{
3176							$elements[] = sql_criteria::_in($field, $value);
3177						}
3178					}
3179				}
3180				else
3181				{
3182					$elements[] = sql_criteria::_equal($field, $value);
3183				}
3184			}
3185			return sql_criteria::_append_and($elements);
3186		}
3187
3188		/**
3189		* Get the all contacts which are from specified owner
3190		*
3191		* @param integer $owner The owner what you can find
3192		* @param integer $action PHPGW_SQL_RETURN_SQL | PHPGW_SQL_RUN_SQL depending what we want
3193		* @return mixed SQL string or records with note_type_id and not_description
3194		*/
3195		function get_contacts_by_owner($owner,$action=PHPGW_SQL_RUN_SQL)
3196		{
3197			$this->request('contact_id');
3198			$this->criteria(array('owner' => $owner));
3199			return $this->get_query($action,__LINE__, __FILE__);
3200		}
3201
3202		/**
3203		* Retrieve Data for categories given, taking care that are person.
3204		*
3205		* @param mixed $categories_id
3206		* @param mixed $data
3207		* @param mixed $contact_type
3208		* @param integer $action PHPGW_SQL_RETURN_SQL | PHPGW_SQL_RUN_SQL depending what we want
3209		* @return array Asociative with id and all data that we requested
3210		*/
3211		function get_contact_by_categories($categories_id, $data, $contact_type, $action=PHPGW_SQL_RUN_SQL)
3212		{
3213			$this->request('contact_id');
3214			$this->request($data);
3215			if($contact_type)
3216			{
3217				$this->criteria(array('cat_cat_id' => $categories_id, 'contact_type' => $this->get_type($contact_type)));
3218			}
3219			else
3220			{
3221				$this->criteria(array('cat_cat_id' => $categories_id));
3222			}
3223			return $this->get_query($action, __LINE__, __FILE__);
3224		}
3225
3226		/**
3227		* Retrieve data from the categories that the contact_id belongs
3228		*
3229		* @param mixed $person_id Contacts Id which want his categories.
3230		* @param mixed $data list of fields that we want retrieve
3231		* @param integer $action PHPGW_SQL_RETURN_SQL | PHPGW_SQL_RUN_SQL depending what we want
3232		* @return array|string Array with records or string with SQL query
3233		* @access private
3234		*/
3235		function _get_categories($person_id, $data, $action=PHPGW_SQL_RUN_SQL)
3236		{
3237			$this->request('contact_id');
3238			$this->request($data);
3239			$this->criteria(array('my_person_id' => $person_id));
3240			return $this->get_query($aciton, __LINE__, __FILE__);
3241		}
3242
3243		/**
3244		* Decide if contact is a user or not
3245		*
3246		* @param integer $contact_id Contact id which want to check.
3247		* @return boolean|integer Account id or false
3248		*/
3249		function is_user($contact_id)
3250		{
3251			$account_id = $GLOBALS['phpgw']->accounts->search_person($contact_id);
3252
3253			if($account_id == 0)
3254			{
3255				return FALSE;
3256			}
3257			else
3258			{
3259				return $account_id;
3260			}
3261		}
3262
3263		function get_account_id($contact_id)
3264		{
3265			$accounts = $GLOBALS['phpgw']->accounts->get_list();
3266			foreach($accounts as $account_data)
3267			{
3268				if($account_data['person_id'] == $contact_id)
3269				{
3270					$account_id = $account_data['account_id'];
3271					break;
3272				}
3273			}
3274
3275			return $account_id;
3276		}
3277
3278
3279		/**
3280		* Decide if the person has preferred organization
3281		*
3282		* @param integer $person_id Person id which want to check.
3283		* @return array|boolean False if has't preferred org or array with all id which has preferred org.
3284		*/
3285		function has_preferred_org($person_id)
3286		{
3287			$this->request('my_person_id');
3288			$this->request('my_org_id');
3289			$this->criteria(array('my_person_id' => $person_id,
3290					      'my_preferred' => 'Y'));
3291			$persons = $this->get_records(__LINE__, __FILE__);
3292			return $persons;
3293		}
3294
3295		/**
3296		* Decide if the contact has preferred location
3297		*
3298		* @param integer $contact_id Contact id which want to check.
3299		* @return array|boolean False if has't preferred org or array with all id which has preferred org.
3300		*/
3301		function has_preferred_location($contact_id)
3302		{
3303			$this->request('addr_contact_id');
3304			$this->request('key_addr_id');
3305			$this->criteria(array('addr_contact_id' => $contact_id,
3306					      'addr_preferred' => 'Y'));
3307			$locations = $this->get_records(__LINE__, __FILE__);
3308			return $locations;
3309		}
3310
3311		/**
3312		* Decide if contact exist
3313		*
3314		* @param integer $contact_id Contact id which want to check.
3315		* @return boolean TRUE if contact exist false otherwise
3316		*/
3317		function exist_contact($contact_id)
3318		{
3319			$this->request('count_contacts');
3320			$this->criteria(array('contact_id' => $contact_id));
3321			$contact = $this->get_records(__LINE__, __FILE__);
3322			if($contact[0]['count_contacts']==0)
3323			{
3324				return FALSE;
3325			}
3326			else
3327			{
3328				return TRUE;
3329			}
3330		}
3331
3332		function exist_org_person_relation($org_id, $person_id)
3333		{
3334			$this->request('my_org_id');
3335			$this->request('my_person_id');
3336			$this->criteria(array('my_org_id' => $org_id,
3337					      'my_person_id' => $person_id));
3338
3339			$contact = $this->get_records(__LINE__, __FILE__);
3340			if($contact[0]['my_org_id']==0)
3341			{
3342				return FALSE;
3343			}
3344			else
3345			{
3346				return TRUE;
3347			}
3348		}
3349
3350
3351		/**
3352		* Decide if contacts are user or not, and retrieve its data.
3353		*
3354		* If account_person_id will be null for each person that is not a user.
3355		* @param mixed $person_id Person id which want to check.
3356		* @param array $data the info that you want of this contact
3357		* @return array With person_id, account_person_id and all data of contacts that we wanted.
3358		*/
3359		function are_users($person_id, $data='')
3360		{
3361			if($data!='')
3362			{
3363				$this->request($data);
3364			}
3365			$this->request(array('contact_id'));
3366			$this->criteria(array('contact_id' => $person_id));
3367			$query = $this->get_query(PHPGW_SQL_RETURN_SQL);
3368			$this->db->query($query,__LINE__, __FILE__);
3369			while($this->db->next_record())
3370			{
3371				$contact = $this->db->Record;
3372				$contact['account_id'] = $GLOBALS['phpgw']->accounts->search_person($contact['contact_id']);
3373				$contacts[] = $contact;
3374			}
3375			return $contacts;
3376		}
3377
3378		/**
3379		* Get the organizations from one person
3380		*
3381		* @param integer $person_id Id of the contact type person
3382		* @return array Asociative array with id and all data that you requested
3383		*/
3384		function get_orgs_by_person($person_id)
3385		{
3386			return $this->get_organizations_by_person($person_id);
3387		}
3388
3389		/**
3390		* Get the all contacts which are users of phpGroupWare
3391		*
3392		* @return mixed SQL string or records with note_type_id and not_description
3393		*/
3394		function get_contacts_which_are_users()
3395		{
3396			return $this->get_system_contacts();
3397		}
3398
3399		function get_person_properties()
3400		{
3401			$person = CreateObject('phpgwapi.contact_person');
3402			return $person->get_false_fields();
3403		}
3404
3405		function get_organization_properties()
3406		{
3407			$org = CreateObject('phpgwapi.contact_org');
3408			return $org->get_false_fields();
3409		}
3410
3411		/**
3412		* Get all persons of specified organization
3413		*
3414		* @param integer $org_id ID of the organization what you want
3415		* @return array Array with records
3416		*/
3417		function get_persons_by_org($org_id)
3418		{
3419			$this->request(array('organizations', 'person_id', 'per_full_name', 'per_first_name', 'per_middle_name', 'per_last_name'));
3420			$this->criteria(array('org_id' => $org_id));
3421			return $this->get_query(PHPGW_SQL_RETURN_SQL, __LINE__, __FILE__);
3422		}
3423
3424		/**
3425		* Search a value into an array
3426		*
3427		* @param string $field_to_search Field into what you want to find
3428		* @param string $value_to_search Value what you want
3429		* @param string $field Field what you want return
3430		* @param string $catalog Catalog name into you want to find
3431		* @return string The value which you requiere in $field
3432		*/
3433		function search_catalog($field_to_search, $value_to_search, $field, $catalog)
3434		{
3435			if(is_array($this->$catalog))
3436			{
3437				foreach ($this->$catalog as $key => $value)
3438				{
3439					if ($value[$field_to_search] == $value_to_search)
3440					{
3441						return $value[$field];
3442					}
3443				}
3444			}
3445		}
3446
3447		/**
3448		* Retrieve the criteria for index addressbook implementation.
3449		*
3450		* Could be used in others parts but thinks that it was created
3451		* with that propouse. This looks for the categories and for the acl perms.
3452		*
3453		* @param integer $owner This is the actual user of phpgroupware
3454		*
3455		* @param mixed $access This is limit the search for private only
3456		* (with PHPGW_CONTACTS_PRIVATE), all my contacts(PHPGW_CONTACTS_MINE)
3457		* or all the records I have access (PHPGW_CONTACTS_ALL).
3458		*
3459		* @param integer $categories if have any value then limit the result
3460		* to contacts that belongs to this categories (and childs)
3461		* PHPGW_CONTACTS_CATEGORIES_ALL if want not use categories criterias.
3462		*
3463		* @param array $search_fields This is used in search, is the<br />
3464		* list of fields to search. Also this list is used to know if we<br />
3465		* need to set the criteria for search the prefered addresses for contacts.
3466		*
3467		* @param string $pattern Is the string that will be used to search in
3468		* all fields of $search_fields, set value to this param without
3469		* setting $search_field is useless.
3470		*
3471		* @param array $show_fields Database fields to show
3472		* @return string SQL string
3473		*/
3474		function criteria_for_index($owner, $access=PHPGW_CONTACTS_ALL, $categories=PHPGW_CONTACTS_CATEGORIES_ALL, $search_fields=array(), $pattern='', $show_fields=array())
3475		{
3476			if(!is_numeric($owner) || intval($owner) == 0)
3477			{
3478				return ;
3479			}
3480			switch($access)
3481			{
3482			case PHPGW_CONTACTS_MINE:
3483				$criteria = sql_criteria::_equal('owner', $owner);
3484				break;
3485			case PHPGW_CONTACTS_PRIVATE:
3486				$criteria = sql_criteria::token_and(sql_criteria::_equal('access', 'private'),
3487								sql_criteria::_equal('owner', $owner));
3488				break;
3489			case PHPGW_CONTACTS_ALL:
3490			default:
3491				$criteria = sql_criteria::token_or(sql_criteria::token_and(sql_criteria::_equal('access', 'public'),
3492										sql_criteria::_in('owner', $this->get_contacts_shared($owner, PHPGW_ACL_READ))),
3493								   sql_criteria::_equal('owner', $owner));
3494			}
3495			if($categories != PHPGW_CONTACTS_CATEGORIES_ALL)
3496			{
3497				if(!is_array($categories))
3498				{
3499					$categories = array($categories);
3500				}
3501
3502				$categories_array = array_merge($categories, (array)$this->get_sub_cats($categories));
3503				if(count($categories_array) > 0)
3504				{
3505					foreach($categories_array as $cat_id)
3506					{
3507						$search_categories[] = sql_criteria::token_or(sql_criteria::_equal('sel_cat_id', $cat_id),
3508											sql_criteria::token_has('sel_cat_id', ','.$cat_id.','));
3509					}
3510					$categories_criteria = sql_criteria::_append_or($search_categories);
3511					$criteria = sql_criteria::token_and($criteria, $categories_criteria);
3512				}
3513			}
3514
3515			$location = CreateObject('phpgwapi.contact_addr');
3516			$search_fields = (empty($search_fields) || !is_array($search_fields)) ? array() : $search_fields;
3517			$show_fields = (empty($show_fields) || !is_array($show_fields)) ? array() : $show_fields;
3518			$search_count = count(array_intersect($location->get_false_fields(), $search_fields));
3519			$show_count = count(array_intersect($location->get_false_fields(), $show_fields));
3520
3521			if($search_count <= 0 && $show_count > 0)
3522			{
3523				$addr_preferred_criteria = sql_criteria::token_or(sql_criteria::_equal('addr_pref_val', 'Y'),
3524										sql_criteria::_is_null('key_addr_id'));
3525				$criteria = sql_criteria::token_and($criteria, $addr_preferred_criteria);
3526			}
3527
3528			if(count($search_fields['comm_media']) > 0)
3529			{
3530				$search_fields_comms = $search_fields['comm_media'];
3531			}
3532			unset($search_fields['comm_media']);
3533
3534			$index = array_search('per_full_name', $search_fields);
3535			if($index!==False &&  $index!==Null)
3536			{
3537				unset($search_fields[$index]);
3538				$search_fields[] = 'per_first_name';
3539				$search_fields[] = 'per_last_name';
3540				$search_fields[] = 'per_middle_name';
3541			}
3542
3543			if(count($search_fields) > 0 && $pattern)
3544			{
3545				foreach($search_fields as $field)
3546				{
3547					$search_array[] = sql_criteria::token_has($field, $pattern);
3548				}
3549
3550				$criteria = sql_criteria::token_and($criteria, sql_criteria::_append_or($search_array));
3551			}
3552
3553			if(count($search_fields_comms) > 0 && $pattern)
3554			{
3555				foreach($search_fields_comms as $field)
3556				{
3557					$search_array_comm[] = sql_criteria::token_and(sql_criteria::token_has('comm_data', $pattern),
3558										       sql_criteria::_equal('comm_descr', $this->search_comm_descr($field)));
3559				}
3560				$criteria = sql_criteria::token_and($criteria, sql_criteria::_append_or($search_array_comm));
3561			}
3562			return $criteria;
3563		}
3564
3565		function search($search_fields, $pattern, $data='contact_id')
3566		{
3567			if(count($search_fields) > 0 && $pattern)
3568			{
3569				$index = array_search('per_full_name', $search_fields);
3570				if($index!==False && $index!==Null)
3571				{
3572					unset($search_fields[$index]);
3573					$search_fields[] = 'per_first_name';
3574					$search_fields[] = 'per_last_name';
3575					$search_fields[] = 'per_middle_name';
3576				}
3577
3578				foreach($search_fields as $field)
3579				{
3580					$search_array[] = sql_criteria::token_has($field, $pattern);
3581				}
3582				$criteria = sql_criteria::_append_or($search_array);
3583			}
3584
3585			$this->request('contact_id');
3586			$this->criteria_token($criteria);
3587			$records = $this->get_records(__LINE__, __FILE__);
3588			if(is_array($records))
3589			{
3590				foreach($records as $key => $value)
3591				{
3592					$info[] = $value['contact_id'];
3593				}
3594			}
3595			return $info;
3596		}
3597
3598		function get_contacts_shared($owner_id, $acl_type=PHPGW_ACL_READ)
3599		{
3600			$this->grants = $GLOBALS['phpgw']->acl->get_grants('addressbook');
3601			if($GLOBALS['phpgw']->acl->check('addressmaster', 7, 'addressbook'))
3602			{
3603				$required_grants[] = $GLOBALS['phpgw_info']['server']['addressmaster'];
3604			}
3605			foreach($this->grants as $owner => $perm)
3606			{
3607				if($this->check_perms($perm, $acl_type))
3608				{
3609					$required_grants[] = $owner;
3610				}
3611			}
3612			return $required_grants;
3613		}
3614
3615		function check_perms($has, $needed)
3616		{
3617			return (!!($has & $needed) == True);
3618		}
3619
3620		/**
3621		* Check if the contact has a specified permission or if is addressmaster
3622		*
3623		* @param integer $contact_id The contact_id which you want to find
3624		* @param integer $needed The permission what you need
3625		* @param integer $owner_id The owner_id of the contact
3626		* @return boolean True when access is allowed otherwise false
3627		*/
3628		function check_acl($contact_id, $needed, $owner_id='')
3629		{
3630			$grants = $GLOBALS['phpgw']->acl->get_grants('addressbook');
3631			if($owner_id=='')
3632			{
3633				$owner_id = $this->get_contact_owner($contact_id);
3634			}
3635			return($this->check_perms($grants[$owner_id],$needed) || $GLOBALS['phpgw']->acl->check('addressmaster',7,'addressbook'));
3636		}
3637
3638		/**
3639		* Check if the contact has add permissions.
3640		*
3641		* @param integer $contact_id The contact_id which you want to check
3642		* @param integer $owner_id The owner_id of the contact which you want to check
3643		* @return boolean True when when adding to this contact is allowed otherwise false
3644		*/
3645		function check_add($contact_id, $owner_id='')
3646		{
3647			return $this->check_acl($contact_id, PHPGW_ACL_ADD, $owner_id);
3648		}
3649
3650		/**
3651		* Check if the contact has edit permissions.
3652		*
3653		* @param integer $contact_id The contact_id which you want to check
3654		* @param integer $owner_id The owner_id of the contact which you want to check
3655		* @return boolean True when editing this contact is allowed otherwise false
3656		*/
3657		function check_edit($contact_id, $owner_id='')
3658		{
3659			return $this->check_acl($contact_id, PHPGW_ACL_EDIT, $owner_id);
3660		}
3661
3662		/**
3663		* Check if the contact has read permissions.
3664		*
3665		* @param integer $contact_id The contact_id which you want to check
3666		* @param integer $owner_id The owner_id of the contact which you want to check
3667		* @return boolean TRue when reading this contact is allowed otherwise false
3668		*/
3669		function check_read($contact_id, $owner_id='')
3670		{
3671			return $this->check_acl($contact_id, PHPGW_ACL_READ, $owner_id);
3672		}
3673
3674		/**
3675		* Check if the contact has delete permissions.
3676		*
3677		* @param integer $contact_id The contact_id which you want to check
3678		* @param integer $owner_id The owner_id of the contact which you want to check
3679		* @return boolean True when deleting this contact is allowed otherwise false
3680		*/
3681		function check_delete($contact_id, $owner_id='')
3682		{
3683			return $this->check_acl($contact_id, PHPGW_ACL_DELETE, $owner_id);
3684		}
3685
3686		/**
3687		* Get the owner of the contact.
3688		*
3689		* @param integer $contact_id The contact_id which you want to find
3690		* @return integer Owner of the given contact
3691		*/
3692		function get_contact_owner($contact_id)
3693		{
3694			$this->request('owner');
3695			$this->criteria(array('contact_id' => $contact_id));
3696			$owner = $this->get_records(__LINE__, __FILE__);
3697			return $owner[0]['owner'];
3698		}
3699
3700		/**
3701		* Copy all contact data to new contact
3702		*
3703		* @param integer $contact_id Id of the contact what you want to copy
3704		* @param integer $type Type Id of the contact what you want to copy
3705		* @return integer Id of the new contact
3706		*/
3707		function copy_contact($contact_id, $type='')
3708		{
3709			$type = ($contact_type)? $contact_type : $this->get_type_contact($contact_id);
3710			$copy_type = ($this->search_contact_type_id($type) == $this->_contact_person) ? 'persons' : 'organizations';
3711
3712			$get_data_type= 'get_principal_' . $copy_type . '_data';
3713
3714			$principal = $this->$get_data_type($contact_id);
3715			unset($principal[0]['owner']);
3716			unset($principal[0]['per_full_name']);
3717
3718			$cats = explode(",", $principal[0]['cat_id']);
3719			foreach($cats as $cat)
3720			{
3721				if($cat)
3722				{
3723					$categories[] = $cat;
3724				}
3725			}
3726
3727			$comms = $this->get_comm_contact_data($contact_id);
3728			$locations = $this->get_addr_contact_data($contact_id);
3729			$others = $this->get_others_contact_data($contact_id);
3730
3731			$new_contact_id = $this->add_contact($type, $principal[0], $comms, $locations, $categories, $others);
3732
3733			switch($copy_type)
3734			{
3735			case $this->tab_main_persons:
3736				$this->copy_organizations_by_person($contact_id, $new_contact_id);
3737				break;
3738			case $this->tab_main_organizations:
3739				$this->copy_people_by_organizations($contact_id, $new_contact_id);
3740				break;
3741			}
3742
3743			return $new_contact_id;
3744		}
3745
3746		/**
3747		* Copy all organizatons from person_id to new person_id
3748		*
3749		* @param integer $person_id Id of the person what you want to copy
3750		* @param integer $new_person_id Id of the new person
3751		*/
3752		function copy_organizations_by_person($person_id, $new_person_id)
3753		{
3754			$records = $this->get_organizations_by_person($person_id);
3755			if(is_array($records))
3756			{
3757				foreach($records as $data)
3758				{
3759					$this->relations = CreateObject('phpgwapi.contact_org_person');
3760					$this->lock_table($this->relations->table);
3761					$data['my_creaton'] = $this->get_mkdate();
3762					$data['my_creatby'] = $this->get_user_id();
3763					$sql[] = $this->_add($data, 'relations', 'my_person_id', $new_person_id, PHPGW_SQL_RUN_SQL);
3764					$this->unlock_table();
3765				}
3766			}
3767		}
3768
3769		/**
3770		* Copy all persons from org_id to new org_id
3771		*
3772		* @param integer $organization_id Id of the organization what you want to copy
3773		* @param integer $new_organization_id Id of the new organization
3774		*/
3775		function copy_people_by_organizations($organization_id, $new_organization_id)
3776		{
3777			$records = $this->get_people_by_organizations($organization_id);
3778
3779			if(is_array($records))
3780			{
3781				foreach($records as $data)
3782				{
3783					if(!$this->exist_org_person_relation($new_organization_id, $data['my_person_id']))
3784					{
3785						$this->relations = CreateObject('phpgwapi.contact_org_person');
3786						$this->lock_table($this->relations->table);
3787						$data['my_creaton'] = $this->get_mkdate();
3788						$data['my_creatby'] = $this->get_user_id();
3789						$sql[] = $this->_add($data,'relations', 'my_org_id', $new_organization_id, PHPGW_SQL_RUN_SQL);
3790						$this->unlock_table();
3791					}
3792				}
3793			}
3794		}
3795
3796		/**
3797		* Create insert SQL statement to insert data from object
3798		*
3799		* @param mixed $data Data
3800		* @param mixed $object Object
3801		* @param string $key_field Key for associatove array
3802		* @param integer $cid Value for key
3803		* @param mixed $action Unknown
3804		* @return string Insert SQL string or nothing
3805		* @access private
3806		*/
3807		function _add($data, $object, $key_field, $cid = '', $action=PHPGW_SQL_RETURN_SQL)
3808		{
3809			// If dont get the $cid, then I hope is in $data array.
3810			$this->ldebug('_add', array('object' => $object, 'cid' => $cid, 'data' => $data ));
3811			$cid = ($cid)? $cid : $data[$key_field];
3812			// Do nothing without contact
3813			if (empty($cid))
3814			{
3815				$this->abort($this->$object->table);
3816			}
3817			else
3818			{
3819				$data[$key_field] = $cid;
3820				return $this->$object->insert($data, $action);
3821			}
3822		}
3823
3824		/**
3825		* Display the correct translation for the field
3826		*
3827		* @param string $field The field what you want
3828		* @return string Translated field name for display
3829		*/
3830		function display_name($field)
3831		{
3832			if($this->contact_fields['showable'][$field])
3833			{
3834				return $GLOBALS['phpgw']->lang($this->contact_fields['showable'][$field]);
3835			}
3836			if($this->contact_fields['retreivable'][$field])
3837			{
3838				return $GLOBALS['phpgw']->lang($this->contact_fields['retrievable'][$field]);
3839			}
3840			if($this->contact_fields['catalogs'][$field])
3841			{
3842				return $GLOBALS['phpgw']->lang($this->contact_fields['catalogs'][$field]);
3843			}
3844			else
3845			{
3846				return $field;
3847			}
3848		}
3849
3850		/**
3851		* Begin a Transaction to database.
3852		*
3853		* @internal Create database object if necesary
3854		* @access private
3855		*/
3856		function transaction_begin()
3857		{
3858			if (is_null($this->db))
3859			{
3860				$this->db = &$GLOBALS['phpgw']->db;
3861			}
3862			if (!$this->trans)
3863			{
3864				$this->db->transaction_begin();
3865				$this->trans = TRUE;
3866			}
3867		}
3868
3869		/**
3870		* End actual Transaction
3871		*
3872		* @access private
3873		*/
3874		function transaction_end()
3875		{
3876			if (!is_null($this->db))
3877			{
3878				$this->db->transaction_commit();
3879				$this->trans = FALSE;
3880			}
3881		}
3882
3883		function last_id($entity, $field)
3884		{
3885			return $this->db->get_last_insert_id($this->$entity->table, $this->$entity->real_field($field));
3886		}
3887
3888		function lock_table($table, $action=PHPGW_SQL_RUN_SQL)
3889		{
3890			if (!($this->locked[$table]) && $action == PHPGW_SQL_RUN_SQL)
3891			{
3892				$this->db->lock($table);
3893				$this->locked[$table] = TRUE;
3894			}
3895		}
3896
3897		/**
3898		* Unlock database table
3899		*
3900		* @access private
3901		*/
3902		function unlock_table()
3903		{
3904			$this->ldebug('unlock_table', array($this->locked), 'dump');
3905			if(count($this->locked))
3906			{
3907				$this->ldebug('unlock_table', array('count' => count($this->locked)));
3908				$this->db->unlock();
3909				$this->locked = NULL;
3910			}
3911		}
3912
3913		/**
3914		* Unknown
3915		*
3916		* @param array $fields Database field names
3917		* @param string $data_type Unknown
3918		* @return array Array with 'comms','locations' and 'others'
3919		* @access private
3920		*/
3921		function slice_old_fields($fields, $data_type)
3922		{
3923			foreach ($comm_old as $old_field => $value)
3924			{
3925				if($fields[$old_field])
3926				{
3927					if($fields['tel_pref'] == $old_field)
3928					{
3929						$comms[] = array($old_field	=> $value,
3930								'comm_descr'	=> $this->search_comm_id($this->comm_old[$old_field][0]),
3931								'comm_preferred'=> $old_field);
3932						unset($fields['tel_pref']);
3933					}
3934					else
3935					{
3936						$comms[] = array($old_field => $value, 'comm_descr' => $this->search_comm_id($this->comm_old[$old_field][0]));
3937					}
3938					unset($fields[$old_field]);
3939				}
3940			}
3941			foreach ($this->adr_old[0] as $old_field)
3942			{
3943				$location[0][$old_field] = $fields[$old_field];
3944				unset($fields[$old_field]);
3945			}
3946			foreach ($this->adr_old[1] as $old_field)
3947			{
3948				$location[1][$old_field] = $fields[$old_field];
3949				unset($fields[$old_field]);
3950			}
3951			$new_fields = $this->split_stock_and_extras($fields);
3952			if(count($new_fields[0]) > 0)
3953			{
3954				// This fields are send to /dev/null
3955				// There is no need of they?
3956				// _debug_array($new_fields[0]);
3957			}
3958			foreach ($new_fields[2] as $field => $value)
3959			{
3960				$others[] = array('other_name' => $field, 'other_value' => $value);
3961			}
3962			return array('comms' => $comms, 'locations' => $location, 'others' => $others);
3963		}
3964
3965		function is_contact($account_id)
3966		{
3967			$account = $GLOBALS['phpgw']->accounts->get_account_data($account_id);
3968			if(empty($account[$account_id]['person_id']))
3969			{
3970				return False;
3971			}
3972			return $account[$account_id]['person_id'];
3973		}
3974
3975		/**
3976		* Get the contact_type for contact_id.
3977		*
3978		* @param integer $contact_id  Contact id which want to check.
3979		* @param integer $action PHPGW_SQL_RETURN_SQL | PHPGW_SQL_RUN_SQL depending what we want
3980		* @return integer The contact_type_id.
3981		*/
3982		function get_type_contact($contact_id, $action=PHPGW_SQL_RUN_SQL)
3983		{
3984			$this->request(array('contact_type'));
3985			$this->criteria(array('contact_id' => $contact_id));
3986			$type =  $this->get_query($action, __LINE__, __FILE__);
3987			return $type[0]['contact_type'];
3988		}
3989
3990		/**
3991		* Get the preferred address of organization.
3992		*
3993		* @param integer $org_id  The organization id which want to check.
3994		* @param integer $action PHPGW_SQL_RETURN_SQL | PHPGW_SQL_RUN_SQL depending what we want
3995		* @return integer The addr_id.
3996		*/
3997		function get_location_pref_org($org_id, $action=PHPGW_SQL_RUN_SQL)
3998		{
3999			$this->request(array('key_addr_id'));
4000			$this->criteria(array('org_id' => $org_id,
4001					      'addr_pref_val'=>'Y'));
4002			$addr_id =  $this->get_query($action, __LINE__, __FILE__);
4003			return $addr_id[0]['key_addr_id'];
4004		}
4005
4006		function get_mkdate()
4007		{
4008			$date =  mktime();
4009			return $date;
4010		}
4011
4012		function get_user_id()
4013		{
4014			return $GLOBALS['phpgw_info']['user']['account_id'];
4015		}
4016
4017		function finalize_add($id)
4018		{
4019			$this->finalize_edit($id);
4020		}
4021
4022		function finalize_edit($id)
4023		{
4024			if ($this->LDAPSyncEnabled)
4025			{
4026				$this->LDAPSync($id);
4027			}
4028		}
4029
4030		function finalize_delete($id)
4031		{
4032			if ($this->LDAPSyncEnabled)
4033			{
4034				$this->LDAPSyncDelete($id);
4035			}
4036		}
4037
4038		function LDAPSyncDelete($id)
4039		{
4040			$result = ldap_search($this->LDAPResource, $GLOBALS['phpgw_info']['server']['ldap_contact_context'], 'employeeNumber='.$id, array('dn'));
4041			$count = ldap_get_entries($this->LDAPResource, $result);
4042			if ((int)$count['count'] > 0)
4043			{
4044				ldap_delete($this->LDAPResource,$count[0]['dn']);
4045			}
4046		}
4047
4048		function LDAPSync($id)
4049		{
4050			if ( !$this->LDAPResource ) //don't segfault on SUSE
4051			{
4052				return false;
4053			}
4054
4055			$this->LDAPSyncDelete($id);
4056
4057			$person = $this->get_principal_persons_data($id);
4058
4059			$time = gettimeofday();
4060			$uid = $person[0]['contact_id'].':'.$person[0]['per_full_name'];
4061			$dn = 'uid=' . utf8_encode($uid).',' . $GLOBALS['phpgw_info']['server']['ldap_contact_context'];
4062
4063			/* Requerid attributes */
4064 			$attributes['objectClass'][] = 'person';
4065 			$attributes['objectClass'][] = 'organizationalPerson';
4066			$attributes['objectClass'][] = 'inetOrgPerson';
4067			$attributes['cn'][]          = utf8_encode($person[0]['per_full_name']) ? utf8_encode($person[0]['per_full_name']) : ' ';
4068			$attributes['sn'][]          = utf8_encode($person[0]['per_last_name']) ? utf8_encode($person[0]['per_last_name']) : ' ';
4069
4070			/* Optional attributes */
4071 			$attributes['uid'][]         = utf8_encode($uid);
4072			if($person[0]['org_name'])
4073			{
4074				$attributes['o'][]         = utf8_encode($person[0]['org_name']);
4075			}
4076			if($person[0]['per_title'])
4077			{
4078				$attributes['title'][]     = utf8_encode($person[0]['per_title']);
4079			}
4080			if($person[0]['per_first_name'])
4081			{
4082				$attributes['givenName'][] = utf8_encode($person[0]['per_first_name']);
4083			}
4084			/*if($person[0]['per_last_name'])
4085			{
4086			}*/
4087			if($person[0]['per_initials'])
4088			{
4089				$attributes['initials'][]	= utf8_encode($person[0]['per_initials']);
4090			}
4091			if($person[0]['per_department'])
4092			{
4093				$attributes['ou'][]       = utf8_encode($person[0]['per_department']);
4094			}
4095			if($person[0]['contact_id'])
4096			{
4097				$attributes['employeeNumber'][] = utf8_encode($person[0]['contact_id']);
4098			}
4099			unset($person);
4100
4101			$address_pref = $this->get_addr_contact_data($id, array('addr_pref_val'=>'Y'));
4102
4103			if($address_pref[0]['addr_add1'] || $address_pref[0]['addr_add2'] || $address_pref[0]['addr_add3'])
4104			{
4105				$attributes['street'][] 			= utf8_encode($address_pref[0]['addr_add1'] .
4106											      $address_pref[0]['addr_add2'] .
4107											      $address_pref[0]['addr_add3']);
4108				$attributes['postalAddress'][] 			= utf8_encode($address_pref[0]['addr_add1'] .
4109											      $address_pref[0]['addr_add2'] .
4110											      $address_pref[0]['addr_add3']);
4111			}
4112
4113			if($address_pref[0]['addr_state'])
4114			{
4115				$attributes['st'][]         = utf8_encode($address_pref[0]['addr_state']);
4116			}
4117			if($address_pref[0]['addr_postal_code'])
4118			{
4119				$attributes['postalCode'][] = utf8_encode($address_pref[0]['addr_postal_code']);
4120			}
4121			if($address_pref[0]['addr_city'])
4122			{
4123				$attributes['l'][]          = utf8_encode($address_pref[0]['addr_city']);
4124			}
4125			//$attributes['homePostalAddress'][] 		= ''; //we can use the address with type home
4126			unset($address_pref);
4127
4128			$db2LDAP_map['home email']          = 'mail';
4129			$db2LDAP_map['work email']          = 'mail';
4130			$db2LDAP_map['home phone']          = 'homePhone';
4131			$db2LDAP_map['work phone']          = 'telephoneNumber';
4132			$db2LDAP_map['pager']               = 'pager';
4133			$db2LDAP_map['isdn']                = 'internationaliSDNNumber';
4134			$db2LDAP_map['home fax']            = 'facsimileTelephoneNumber';
4135			$db2LDAP_map['work fax']            = 'facsimileTelephoneNumber';
4136			$db2LDAP_map['mobile (cell) phone'] = 'mobile';
4137			$db2LDAP_map['car phone']           = 'telephoneNumber';
4138			$db2LDAP_map['website']             = 'labeledURI';
4139
4140			$comms = $this->get_comm_contact_data($id, '');
4141			$validator = CreateObject('phpgwapi.validator');
4142			for ($i=0; $i < count($comms); $i++)
4143			{
4144				$key = $db2LDAP_map[$comms[$i]['comm_description']];
4145				if ($comms[$i]['comm_data'] && $key)
4146				{
4147					$write = true;
4148					switch($key)
4149					{
4150						case 'mail':
4151						$write = $validator->is_email($comms[$i]['comm_data']);
4152						break;
4153					}
4154
4155					if($write)
4156					{
4157						if ($comms[$i]['comm_preferred'] == 'Y' && count($attributes[$key]) > 0)
4158						{
4159							array_unshift($attributes[$key], utf8_encode($comms[$i]['comm_data']));
4160						}
4161						else
4162						{
4163							$attributes[$key][] = utf8_encode($comms[$i]['comm_data']);
4164						}
4165					}
4166				}
4167			}
4168
4169			$success = @ldap_add($this->LDAPResource, $dn, $attributes);
4170			if (!$success)
4171			{
4172				echo 'ldap_add FAILED: [' . ldap_errno($this->LDAPResource) . '] ' . ldap_error($this->LDAPResource).'<br /><br />';
4173				echo "<strong>Adds: ".$dn."</strong><br />";
4174				echo "<pre>";
4175				print_r($attributes);
4176				echo "</pre>";
4177				echo "<br />";
4178			}
4179		}
4180
4181		/**
4182		* Method that could be used to import fields from an array with the specified form.
4183		*
4184		* This is the only one method that provide the fullfill fields for contact.
4185		* @param array $fields Field names to import
4186		* @param string $type Type of given communications
4187		* @param boolean $update True: update existing entry; False: overwrite
4188		* @return integer New contact ID or -1 on error
4189		*/
4190		function contact_import($fields, $type = '', $update=false)
4191		{
4192			$type = empty($type) ? $this->search_contact_type($this->_contact_person) : $type;
4193			if((isset($fields['first_name']) && !isset($fields['org_name'])) || $type)
4194			{
4195				$contact['contact_id']        = isset($fields['contact_id'])        ? $fields['contact_id']        : '';
4196				$contact['access']            = isset($fields['access'])            ? $fields['access']            : 'private';
4197				$contact['owner']             = isset($fields['owner'])             ? $fields['owner']             : $GLOBALS['phpgw_info']['user']['account_id'];
4198				$contact['per_first_name']    = isset($fields['first_name'])        ? $fields['first_name']        : '';
4199				$contact['per_last_name']     = isset($fields['last_name'])         ? $fields['last_name']         : '';
4200				$contact['per_middle_name']   = isset($fields['middle_name'])       ? $fields['middle_name']       : '';
4201				$contact['per_suffix']        = isset($fields['suffix'])            ? $fields['suffix']            : '';
4202				$contact['per_prefix']        = isset($fields['prefix'])            ? $fields['prefix']            : '';
4203				$contact['per_birthday']      = isset($fields['birthday'])          ? $fields['birthday']          : '';
4204				$contact['per_pubkey']        = isset($fields['pubkey'])            ? $fields['pubkey']            : '';
4205				$contact['per_title']         = isset($fields['title'])             ? $fields['title']             : '';
4206				$contact['per_department']    = isset($fields['department'])        ? $fields['department']        : '';
4207				$contact['per_initials']      = isset($fields['initials'])          ? $fields['initials']          : '';
4208				$contact['per_sound']         = isset($fields['sound'])             ? $fields['sound']             : '';
4209				$contact['per_active']        = isset($fields['active'])            ? $fields['active']            : '';
4210				$contact['preferred_org']     = isset($fields['preferred_org'])     ? $fields['preferred_org']     : '';
4211				$contact['preferred_address'] = isset($fields['preferred_address']) ? $fields['preferred_address'] : '';
4212				$contact['relations']         = isset($fields['organizations'])     ? $fields['organizations']     : array();
4213				$contact['per_creaton']       = isset($fields['createon'])          ? $fields['createon']          : null;
4214				$contact['per_modon']         = isset($fields['modon'])             ? $fields['modon']             : null;
4215
4216				unset(	$fields['contact_id'],
4217					$fields['first_name'],
4218					$fields['last_name'],
4219					$fields['middle_name'],
4220					$fields['suffix'],
4221					$fields['prefix'],
4222					$fields['birthday'],
4223					$fields['pubkey'],
4224					$fields['title'],
4225					$fields['department'],
4226					$fields['initials'],
4227					$fields['sound'],
4228					$fields['active'],
4229					$fields['preferred_org'],
4230					$fields['preferred_address'],
4231					$fields['organizations'],
4232					$fields['access'],
4233					$fields['full_name'],
4234					$fields['owner'],
4235					$fields['account_id'],
4236					$fields['org_name']);
4237			}
4238			else
4239			{
4240				$contact['access']     = isset($fields['access'])   ? $fields['access']   : 'private';
4241				$contact['owner']      = isset($fields['owner'])    ? $fields['owner']    : $GLOBALS['phpgw_info']['user']['account_id'];
4242				$contact['org_name']   = isset($fields['org_name']) ? $fields['org_name'] : '';
4243				$contact['org_active'] = isset($fields['active'])   ? $fields['active']   : '';
4244				$contact['org_parent'] = isset($fields['parent'])   ? $fields['parent']   : '';
4245				$contact['relations']  = isset($fields['people'])   ? $fields['people']   : '';
4246				$contact['org_creaton']= isset($fields['createon']) ? $fields['createon'] : null;
4247				$contact['org_creatby']= isset($fields['createby']) ? $fields['createby'] : null;
4248				$contact['org_modon']  = isset($fields['modon'])    ? $fields['modon']    : null;
4249				$contact['org_modby']  = isset($fields['modby'])    ? $fields['modby']    : null;
4250
4251				unset(	$fields['org_name'],
4252					$fields['active'],
4253					$fields['parent'],
4254					$fields['people']
4255				);
4256			}
4257
4258			$contact['cat_id'] = isset($fields['categories']) ? $fields['categories'] : '';
4259			unset($fields['categories'], $fields['access']);
4260
4261			// Locations info
4262			$locations = array();
4263			if(is_array($fields['locations']))
4264			{
4265				foreach($fields['locations'] as $location_input)
4266				{
4267					// Go for a _good_ address type
4268					$addr_type = $this->search_location_type($location_input['type']);
4269					if(!empty($addr_type))
4270					{
4271						$location['addr_type'] = $addr_type;
4272					}
4273					else
4274					{
4275						$addr_type = $this->search_location_type('work');
4276						if(!empty($addr_type))
4277						{
4278							$location['addr_type'] = $addr_type;
4279						}
4280						else
4281						{
4282							//return PHPGW_CONTACTS_ERROR_LOCATION_TYPE_MISSING;
4283							return -1;
4284						}
4285					}
4286					$location['addr_add1']        = isset($location_input['add1'])        ? $location_input['add1']        : '';
4287					$location['addr_add2']        = isset($location_input['add2'])        ? $location_input['add2']        : '';
4288					$location['addr_add3']        = isset($location_input['add3'])        ? $location_input['add3']        : '';
4289					$location['addr_city']        = isset($location_input['city'])        ? $location_input['city']        : '';
4290					$location['addr_state']       = isset($location_input['state'])       ? $location_input['state']       : '';
4291					$location['addr_postal_code'] = isset($location_input['postal_code']) ? $location_input['postal_code'] : '';
4292					$location['addr_country']     = isset($location_input['country'])     ? $location_input['country']     : '';
4293					$location['addr_preferred']   = isset($location_input['preferred'])   ? $location_input['preferred']   : '';
4294					$location['addr_createon']   = isset($fields['createon'])   ? $fields['createon']   : '';
4295					$location['addr_createby']   = isset($fields['createby'])   ? $fields['createby']   : '';
4296					$location['addr_modon']      = isset($fields['modon'])      ? $fields['modon']      : '';
4297					$location['addr_modby']      = isset($fields['modby'])      ? $fields['modby']      : '';
4298					$locations[] = $location;
4299				}
4300			}
4301			unset($fields['locations']);
4302
4303			// Notes
4304			$notes = array();
4305			if(is_array($fields['notes']))
4306			{
4307				if(isset($fields['notes']['type']) && isset($fields['notes']['note']))
4308				{
4309					$fields['notes'] = array($fields['notes']);
4310				}
4311
4312				foreach($fields['notes'] as $note_input)
4313				{
4314					$note_type = $this->search_note_type($note_input['type']);
4315					if(!empty($note_type))
4316					{
4317						$note['note_type'] = $note_type;
4318					}
4319					else
4320					{
4321						// FIXME: what is the default value for note_type?
4322						$note_type = $this->search_note_type('general');
4323						if(!empty($note_type))
4324						{
4325							$note['note_type'] = $note_type;
4326						}
4327						else
4328						{
4329							//return PHPGW_CONTACTS_ERROR_NOTE_TYPE_MISSING;
4330							return -1;
4331						}
4332					}
4333					$note['note_text'] = $note_input['note'];
4334					$note['note_createon'] = isset($fields['createon'])   ? $fields['createon']   : '';
4335					$note['note_createby'] = isset($fields['createby'])   ? $fields['createby']   : '';
4336					$note['note_modon']    = isset($fields['modon'])      ? $fields['modon']      : '';
4337					$note['note_modby']    = isset($fields['modby'])      ? $fields['modby']      : '';
4338
4339					$notes[] = $note;
4340				}
4341			}
4342			unset($fields['notes']);
4343
4344			// Communcation media fields
4345			$comm_media = array();
4346			if(is_array($fields['comm_media']))
4347			{
4348				foreach($fields['comm_media'] as $description_input => $comm_input)
4349				{
4350					$description_id = $this->search_comm_descr($description_input);
4351					if(!empty($description_id))
4352					{
4353						$comm['comm_descr']	= $description_id;
4354						$comm['comm_data']	= $comm_input;
4355						$comm['comm_createon'] = isset($fields['createon'])   ? $fields['createon']   : '';
4356						$comm['comm_createby'] = isset($fields['createby'])   ? $fields['createby']   : '';
4357						$comm['comm_modon']    = isset($fields['modon'])      ? $fields['modon']      : '';
4358						$comm['comm_modby']    = isset($fields['modby'])      ? $fields['modby']      : '';
4359						$comm_media[]		= $comm;
4360					}
4361					else
4362					{
4363						// Promote to others
4364						$fields[$description_input] = $comm_input;
4365					}
4366				}
4367			}
4368			unset($fields['comm_media']);
4369
4370			// Other fields
4371			$others=array();
4372			if(count($fields) > 0)
4373			{
4374				foreach($fields as $field_name => $field_value)
4375				{
4376					$other['other_name']	= $field_name;
4377					$other['other_value']	= $field_value;
4378					$other['other_owner']	= $GLOBALS['phpgw_info']['user']['account_id'];
4379					$other['other_createon'] = isset($fields['createon'])   ? $fields['createon']   : '';
4380					$other['other_createby'] = isset($fields['createby'])   ? $fields['createby']   : '';
4381					$other['other_modon']    = isset($fields['modon'])      ? $fields['modon']      : '';
4382					$other['other_modby']    = isset($fields['modby'])      ? $fields['modby']      : '';
4383					$others[]		= $other;
4384				}
4385			}
4386
4387
4388			if($contact['preferred_org'] != '')
4389			{
4390				$this->criteria(array('org_name' => $contact['preferred_org'],
4391				                      'owner' => $GLOBALS['phpgw_info']['user']['account_id']));
4392				$records = $this->get_orgs(array('contact_id'));
4393
4394				if(is_array($records))
4395				{
4396					foreach($records as $org)
4397					{
4398						$contact['relations'][] = $org['contact_id'];
4399					}
4400				}
4401				else
4402				{
4403					$principal['access']   = $contact['access'];
4404					$principal['owner']    = $contact['owner'];
4405					$principal['org_name'] = $contact['preferred_org'];
4406
4407					$principal['org_creaton'] = isset($fields['createon'])   ? $fields['createon']   : '';
4408					$principal['org_creatby'] = isset($fields['createby'])   ? $fields['createby']   : '';
4409					$principal['org_modon']   = isset($fields['modon'])      ? $fields['modon']      : '';
4410					$principal['org_modby']   = isset($fields['modby'])      ? $fields['modby']      : '';
4411				}
4412			}
4413
4414			unset(
4415				$fields['createon'],
4416				$fields['createby'],
4417				$fields['modon'],
4418				$fields['modby']
4419			);
4420
4421			if (($update == true) && (isset($contact['contact_id']) == true))
4422			{
4423				$cid = $contact['contact_id'];
4424				$ret = array();
4425				$ret['contact_id'] = $cid;
4426
4427				$this->edit_contact($cid, $contact, PHPGW_SQL_RUN_SQL);
4428				if ($GLOBALS['phpgw']->db->Error)
4429					$ret['edit_contact'] = false;
4430				else
4431					$ret['edit_contact'] = true;
4432
4433				$this->edit_person($cid, $contact, PHPGW_SQL_RUN_SQL);
4434				if ($GLOBALS['phpgw']->db->Error)
4435					$ret['edit_person'] = false;
4436				else
4437					$ret['edit_person'] = true;
4438
4439
4440				// update comm media data
4441				if(is_array($comm_media) && (count($comm_media) > 0))
4442				{
4443					$ret_comm = array();
4444					$ret['comm'] =& $ret_comm;
4445
4446					$old_comms_media = $this->get_comm_contact_data($cid);
4447					if(is_array($old_comms_media) && (count($old_comms_media) > 0))
4448					{
4449						foreach($old_comms_media as $old_comm)
4450						{
4451							$key_comm_id = $old_comm['key_comm_id'];
4452							$ret_comm['key_comm_id'][] = $key_comm_id;
4453							$is_edited = false;
4454
4455							reset($comm_media);
4456							while(list($key,$comm) = each($comm_media))
4457							{
4458								if($comm['comm_descr'] == $old_comm['comm_descr'])
4459								{
4460									// replace old comm data
4461									$this->edit_comms($key_comm_id, $comm, PHPGW_SQL_RUN_SQL);
4462									if ($GLOBALS['phpgw']->db->Error)
4463										$ret_comm['edit_comms'][$key_comm_id] = false;
4464									else
4465										$ret_comm['edit_comms'][$key_comm_id] = true;
4466									// unset comm array
4467									unset($comm_media[$key]);
4468									$is_edited = true;
4469									break;
4470								}
4471							}
4472
4473							// if old entry was not set by new data (edited), delete them
4474							if($is_edited == false)
4475							{
4476								// delete old comm data
4477								$this->delete_specified_comm($key_comm_id, PHPGW_SQL_RUN_SQL);
4478								if ($GLOBALS['phpgw']->db->Error)
4479									$ret_comm[$key_comm_id]['delete_specified_comm'] = false;
4480								else
4481									$ret_comm[$key_comm_id]['delete_specified_comm'] = true;
4482							}
4483						}
4484					}
4485					// add new comms (rest of the comms array)
4486					foreach($comm_media as $comm)
4487					{
4488						$this->add_communication_media($comm, $cid, PHPGW_SQL_RUN_SQL);
4489						$this->unlock_table();
4490						if ($GLOBALS['phpgw']->db->Error)
4491							$ret_comm['add_communication_media'][] = false;
4492						else
4493							$ret_comm['add_communication_media'][] = true;
4494					}
4495				}
4496
4497				// update location data (delete old and add new locs)
4498				$ret_loc = array();
4499				$ret['loc'] =& $ret_loc;
4500				$old_locations = $this->get_addr_contact_data($cid);
4501				if(is_array($old_locations) && (count($old_locations) > 0))
4502				{
4503					// 1. delete old locs
4504					$this->delete_locations($cid, PHPGW_SQL_RUN_SQL);
4505					if ($GLOBALS['phpgw']->db->Error)
4506						$ret_loc['delete_locations'] = false;
4507					else
4508						$ret_loc['delete_locations'] = true;
4509				}
4510				// 2. add new locs
4511				if(is_array($locations) && (count($locations) > 0))
4512				{
4513					foreach($locations as $loc)
4514					{
4515						$this->add_location($loc, $cid, PHPGW_SQL_RUN_SQL);
4516						$this->unlock_table();
4517						if ($GLOBALS['phpgw']->db->Error)
4518							$ret_loc['add_location'][] = false;
4519						else
4520							$ret_loc['add_location'][] = true;
4521					}
4522				}
4523
4524				// update organizations data (delete old and add new org)
4525				$this->delete_orgs_by_person($cid, PHPGW_SQL_RUN_SQL);
4526				if($contact['preferred_org'])
4527				{
4528					if(isset($principal))
4529					{ // new org
4530						$type_org = $this->search_contact_type($this->_contact_org);
4531						$contact_relations[] = $cid;
4532						$this->add_contact($type_org, $principal, array(), array(), $contact['cat_id'], array(), $contact_relations, array());
4533					}
4534					else
4535					{
4536						$this->add_orgs_for_person($contact['relations'], $contact['preferred_org'], $contact['preferred_address'], $cid, PHPGW_SQL_RUN_SQL);
4537					}
4538				}
4539
4540				// update other data (delete old and add new others)
4541				$ret_other = array();
4542				$ret['other'] =& $ret_other;
4543				$old_others = $this->get_others_contact_data($cid);
4544				if(is_array($old_others) && (count($old_others) > 0))
4545				{
4546					$ret['other'] = $old_others;
4547					// 1. delete old others
4548					$this->delete_others($cid, PHPGW_SQL_RUN_SQL);
4549					if ($GLOBALS['phpgw']->db->Error)
4550						$ret_other['delete_others'] = false;
4551					else
4552						$ret_other['delete_others'] = true;
4553				}
4554				// 2. add new others
4555				if(is_array($others) && (count($others) > 0))
4556				{
4557					foreach($others as $other)
4558					{
4559						$this->add_others($other, $cid, PHPGW_SQL_RUN_SQL);
4560						$this->unlock_table();
4561						if ($GLOBALS['phpgw']->db->Error)
4562							$ret_other['add_other'][] = false;
4563						else
4564							$ret_other['add_other'][] = true;
4565					}
4566				}
4567
4568				return true; //$ret;
4569			}
4570			else
4571			{
4572				$cid = $this->add_contact($type, $contact, $comm_media, $locations, $contact['cat_id'], $others, $contact['relations'], $notes);
4573				if(isset($principal))
4574				{
4575					$type_org = $this->search_contact_type($this->_contact_org);
4576					$contact_relations[] = $cid;
4577					$this->add_contact($type_org, $principal, array(), array(), $contact['cat_id'], array(), $contact_relations, array());
4578				}
4579				return $cid;
4580			}
4581		}
4582	}
4583?>
4584