SoapSugarUsers.php ➔ get_gmt_time()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2
Metric Value
cc 1
eloc 2
nc 1
nop 0
dl 0
loc 3
ccs 0
cts 3
cp 0
crap 2
rs 10
1
<?php
2
if(!defined('sugarEntry') || !sugarEntry) die('Not A Valid Entry Point');
3
/*********************************************************************************
4
 * SugarCRM Community Edition is a customer relationship management program developed by
5
 * SugarCRM, Inc. Copyright (C) 2004-2013 SugarCRM Inc.
6
7
 * SuiteCRM is an extension to SugarCRM Community Edition developed by Salesagility Ltd.
8
 * Copyright (C) 2011 - 2014 Salesagility Ltd.
9
 *
10
 * This program is free software; you can redistribute it and/or modify it under
11
 * the terms of the GNU Affero General Public License version 3 as published by the
12
 * Free Software Foundation with the addition of the following permission added
13
 * to Section 15 as permitted in Section 7(a): FOR ANY PART OF THE COVERED WORK
14
 * IN WHICH THE COPYRIGHT IS OWNED BY SUGARCRM, SUGARCRM DISCLAIMS THE WARRANTY
15
 * OF NON INFRINGEMENT OF THIRD PARTY RIGHTS.
16
 *
17
 * This program is distributed in the hope that it will be useful, but WITHOUT
18
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
19
 * FOR A PARTICULAR PURPOSE.  See the GNU Affero General Public License for more
20
 * details.
21
 *
22
 * You should have received a copy of the GNU Affero General Public License along with
23
 * this program; if not, see http://www.gnu.org/licenses or write to the Free
24
 * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
25
 * 02110-1301 USA.
26
 *
27
 * You can contact SugarCRM, Inc. headquarters at 10050 North Wolfe Road,
28
 * SW2-130, Cupertino, CA 95014, USA. or at email address [email protected].
29
 *
30
 * The interactive user interfaces in modified source and object code versions
31
 * of this program must display Appropriate Legal Notices, as required under
32
 * Section 5 of the GNU Affero General Public License version 3.
33
 *
34
 * In accordance with Section 7(b) of the GNU Affero General Public License version 3,
35
 * these Appropriate Legal Notices must retain the display of the "Powered by
36
 * SugarCRM" logo and "Supercharged by SuiteCRM" logo. If the display of the logos is not
37
 * reasonably feasible for  technical reasons, the Appropriate Legal Notices must
38
 * display the words  "Powered by SugarCRM" and "Supercharged by SuiteCRM".
39
 ********************************************************************************/
40
41
require_once('soap/SoapHelperFunctions.php');
42
require_once('soap/SoapTypes.php');
43
44
/*************************************************************************************
45
46
THIS IS FOR SUGARCRM USERS
47
48
49
*************************************************************************************/
50
$disable_date_format = true;
51
52
$server->register(
53
    'is_user_admin',
54
    array('session'=>'xsd:string'),
55
    array('return'=>'xsd:int'),
56
    $NAMESPACE);
57
58
/**
59
 * Return if the user is an admin or not
60
 *
61
 * @param String $session -- Session ID returned by a previous call to login.
62
 * @return int 1 or 0 depending on if the user is an admin
63
 */
64
function is_user_admin($session){
65
	if(validate_authenticated($session)){
66
		global $current_user;
67
		return is_admin($current_user);
68
69
	}else{
70
		return 0;
71
	}
72
}
73
74
75
$server->register(
76
        'login',
77
        array('user_auth'=>'tns:user_auth', 'application_name'=>'xsd:string'),
78
        array('return'=>'tns:set_entry_result'),
79
        $NAMESPACE);
80
81
/**
82
 * Log the user into the application
83
 *
84
 * @param UserAuth array $user_auth -- Set user_name and password (password needs to be
85
 *      in the right encoding for the type of authentication the user is setup for.  For Base
86
 *      sugar validation, password is the MD5 sum of the plain text password.
87
 * @param String $application -- The name of the application you are logging in from.  (Currently unused).
88
 * @return Array(session_id, error) -- session_id is the id of the session that was
0 ignored issues
show
Documentation introduced by
The doc-type Array(session_id, could not be parsed: Expected "|" or "end of type", but got "(" at position 5. (view supported doc-types)

This check marks PHPDoc comments that could not be parsed by our parser. To see which comment annotations we can parse, please refer to our documentation on supported doc-types.

Loading history...
89
 *      created.  Error is set if there was any error during creation.
90
 */
91
function login($user_auth, $application){
92
	global $sugar_config, $system_config;
93
94
	$error = new SoapError();
95
	$user = new User();
96
	$success = false;
97
	//rrs
98
		$system_config = new Administration();
99
	$system_config->retrieveSettings('system');
100
	$authController = new AuthenticationController();
101
	//rrs
102
	$isLoginSuccess = $authController->login($user_auth['user_name'], $user_auth['password'], array('passwordEncrypted' => true));
103
	$usr_id=$user->retrieve_user_id($user_auth['user_name']);
104
	if($usr_id) {
105
		$user->retrieve($usr_id);
106
	}
107
108
	if ($isLoginSuccess) {
109
		if ($_SESSION['hasExpiredPassword'] =='1') {
110
			$error->set_error('password_expired');
111
			$GLOBALS['log']->fatal('password expired for user ' . $user_auth['user_name']);
112
			LogicHook::initialize();
113
			$GLOBALS['logic_hook']->call_custom_logic('Users', 'login_failed');
114
			return array('id'=>-1, 'error'=>$error);
115
		} // if
116
		if(!empty($user) && !empty($user->id) && !$user->is_group) {
117
			$success = true;
118
			global $current_user;
119
			$current_user = $user;
120
		} // if
121
	} else if($usr_id && isset($user->user_name) && ($user->getPreference('lockout') == '1')) {
122
			$error->set_error('lockout_reached');
123
			$GLOBALS['log']->fatal('Lockout reached for user ' . $user_auth['user_name']);
124
			LogicHook::initialize();
125
			$GLOBALS['logic_hook']->call_custom_logic('Users', 'login_failed');
126
			return array('id'=>-1, 'error'=>$error);
127
	} else if(function_exists('mcrypt_cbc')){
128
		$password = decrypt_string($user_auth['password']);
129
		$authController = new AuthenticationController();
130
		if($authController->login($user_auth['user_name'], $password) && isset($_SESSION['authenticated_user_id'])){
131
			$success = true;
132
		} // if
133
	} // else if
134
135
	if($success){
136
		session_start();
137
		global $current_user;
138
		//$current_user = $user;
139
		login_success();
140
		$current_user->loadPreferences();
141
		$_SESSION['is_valid_session']= true;
142
		$_SESSION['ip_address'] = query_client_ip();
143
		$_SESSION['user_id'] = $current_user->id;
144
		$_SESSION['type'] = 'user';
145
		$_SESSION['avail_modules']= get_user_module_list($current_user);
146
		$_SESSION['authenticated_user_id'] = $current_user->id;
147
		$_SESSION['unique_key'] = $sugar_config['unique_key'];
148
149
		$current_user->call_custom_logic('after_login');
150
		return array('id'=>session_id(), 'error'=>$error);
151
	}
152
	$error->set_error('invalid_login');
153
	$GLOBALS['log']->fatal('SECURITY: User authentication for '. $user_auth['user_name']. ' failed');
154
	LogicHook::initialize();
155
	$GLOBALS['logic_hook']->call_custom_logic('Users', 'login_failed');
156
	return array('id'=>-1, 'error'=>$error);
157
158
}
159
160
//checks if the soap server and client are running on the same machine
161
$server->register(
162
        'is_loopback',
163
        array(),
164
        array('return'=>'xsd:int'),
165
        $NAMESPACE);
166
167
/**
168
 * Check to see if the soap server and client are on the same machine.
169
 * We don't allow a server to sync to itself.
170
 *
171
 * @return true -- if the SOAP server and client are on the same machine
172
 * @return false -- if the SOAP server and client are not on the same machine.
173
 */
174
function is_loopback(){
175
	if(query_client_ip() == $_SERVER['SERVER_ADDR'])
176
		return 1;
177
	return 0;
178
}
179
180
/**
181
 * Validate the provided session information is correct and current.  Load the session.
182
 *
183
 * @param String $session_id -- The session ID that was returned by a call to login.
184
 * @return true -- If the session is valid and loaded.
185
 * @return false -- if the session is not valid.
186
 */
187
function validate_authenticated($session_id){
188
	if(!empty($session_id)){
189
		session_id($session_id);
190
		session_start();
191
192
		if(!empty($_SESSION['is_valid_session']) && is_valid_ip_address('ip_address') && $_SESSION['type'] == 'user'){
193
194
			global $current_user;
195
196
			$current_user = new User();
197
			$current_user->retrieve($_SESSION['user_id']);
198
			login_success();
199
			return true;
200
		}
201
202
		session_destroy();
203
	}
204
	LogicHook::initialize();
205
	$GLOBALS['log']->fatal('SECURITY: The session ID is invalid');
206
	$GLOBALS['logic_hook']->call_custom_logic('Users', 'login_failed');
207
	return false;
208
}
209
210
/**
211
 * Use the same logic as in SugarAuthenticate to validate the ip address
212
 *
213
 * @param string $session_var
214
 * @return bool - true if the ip address is valid, false otherwise.
215
 */
216
function is_valid_ip_address($session_var){
217
	global $sugar_config;
218
	// grab client ip address
219
	$clientIP = query_client_ip();
220
	$classCheck = 0;
221
	// check to see if config entry is present, if not, verify client ip
222
	if (!isset ($sugar_config['verify_client_ip']) || $sugar_config['verify_client_ip'] == true) {
223
		// check to see if we've got a current ip address in $_SESSION
224
		// and check to see if the session has been hijacked by a foreign ip
225
		if (isset ($_SESSION[$session_var])) {
226
			$session_parts = explode(".", $_SESSION[$session_var]);
227
			$client_parts = explode(".", $clientIP);
228
            if(count($session_parts) < 4) {
229
             	$classCheck = 0;
230
            }else {
231
    			// match class C IP addresses
232
    			for ($i = 0; $i < 3; $i ++) {
233
    				if ($session_parts[$i] == $client_parts[$i]) {
234
    					$classCheck = 1;
235
    						continue;
236
    				} else {
237
    					$classCheck = 0;
238
    					break;
239
    					}
240
    				}
241
                }
242
				// we have a different IP address
243
				if ($_SESSION[$session_var] != $clientIP && empty ($classCheck)) {
244
					$GLOBALS['log']->fatal("IP Address mismatch: SESSION IP: {$_SESSION[$session_var]} CLIENT IP: {$clientIP}");
245
					return false;
246
				}
247
			} else {
248
				return false;
249
			}
250
	}
251
	return true;
252
}
253
254
$server->register(
255
    'seamless_login',
256
    array('session'=>'xsd:string'),
257
    array('return'=>'xsd:int'),
258
    $NAMESPACE);
259
260
/**
261
 * Perform a seamless login.  This is used internally during the sync process.
262
 *
263
 * @param String $session -- Session ID returned by a previous call to login.
264
 * @return true -- if the session was authenticated
265
 * @return false -- if the session could not be authenticated
266
 */
267
function seamless_login($session){
268
		if(!validate_authenticated($session)){
269
			return 0;
270
		}
271
		
272
		return 1;
273
}
274
275
$server->register(
276
    'get_entry_list',
277
    array('session'=>'xsd:string', 'module_name'=>'xsd:string', 'query'=>'xsd:string', 'order_by'=>'xsd:string','offset'=>'xsd:int', 'select_fields'=>'tns:select_fields', 'max_results'=>'xsd:int', 'deleted'=>'xsd:int'),
278
    array('return'=>'tns:get_entry_list_result'),
279
    $NAMESPACE);
280
281
/**
282
 * Retrieve a list of beans.  This is the primary method for getting list of SugarBeans from Sugar using the SOAP API.
283
 *
284
 * @param String $session -- Session ID returned by a previous call to login.
285
 * @param String $module_name -- The name of the module to return records from.  This name should be the name the module was developed under (changing a tab name is studio does not affect the name that should be passed into this method)..
286
 * @param String $query -- SQL where clause without the word 'where'
287
 * @param String $order_by -- SQL order by clause without the phrase 'order by'
288
 * @param String $offset -- The record offset to start from.
289
 * @param Array  $select_fields -- A list of the fields to be included in the results. This optional parameter allows for only needed fields to be retrieved.
290
 * @param String $max_results -- The maximum number of records to return.  The default is the sugar configuration value for 'list_max_entries_per_page'
291
 * @param Number $deleted -- false if deleted records should not be include, true if deleted records should be included.
292
 * @return Array 'result_count' -- The number of records returned
293
 *               'next_offset' -- The start of the next page (This will always be the previous offset plus the number of rows returned.  It does not indicate if there is additional data unless you calculate that the next_offset happens to be closer than it should be.
294
 *               'field_list' -- The vardef information on the selected fields.
295
 *                      Array -- 'field'=>  'name' -- the name of the field
296
 *                                          'type' -- the data type of the field
297
 *                                          'label' -- the translation key for the label of the field
298
 *                                          'required' -- Is the field required?
299
 *                                          'options' -- Possible values for a drop down field
300
 *               'entry_list' -- The records that were retrieved
301
 *               'error' -- The SOAP error, if any
302
 */
303
function get_entry_list($session, $module_name, $query, $order_by,$offset, $select_fields, $max_results, $deleted ){
304
	global  $beanList, $beanFiles, $current_user;
305
	$error = new SoapError();
306
	if(!validate_authenticated($session)){
307
		$error->set_error('invalid_login');
308
		return array('result_count'=>-1, 'entry_list'=>array(), 'error'=>$error->get_soap_array());
309
	}
310
    $using_cp = false;
311
    if($module_name == 'CampaignProspects'){
312
        $module_name = 'Prospects';
313
        $using_cp = true;
314
    }
315
	if(empty($beanList[$module_name])){
316
		$error->set_error('no_module');
317
		return array('result_count'=>-1, 'entry_list'=>array(), 'error'=>$error->get_soap_array());
318
	}
319
	global $current_user;
320
	if(!check_modules_access($current_user, $module_name, 'read')){
321
		$error->set_error('no_access');
322
		return array('result_count'=>-1, 'entry_list'=>array(), 'error'=>$error->get_soap_array());
323
	}
324
325
	// If the maximum number of entries per page was specified, override the configuration value.
326
	if($max_results > 0){
327
		global $sugar_config;
328
		$sugar_config['list_max_entries_per_page'] = $max_results;
329
	}
330
331
332
	$class_name = $beanList[$module_name];
333
	require_once($beanFiles[$class_name]);
334
	$seed = new $class_name();
335
	if(! ($seed->ACLAccess('Export') && $seed->ACLAccess('list')))
336
	{
337
		$error->set_error('no_access');
338
		return array('result_count'=>-1, 'entry_list'=>array(), 'error'=>$error->get_soap_array());
339
	}
340
341
	require_once 'include/SugarSQLValidate.php';
342
	$valid = new SugarSQLValidate();
343
	if(!$valid->validateQueryClauses($query, $order_by)) {
344
        $GLOBALS['log']->error("Bad query: $query $order_by");
345
	    $error->set_error('no_access');
346
	    return array(
347
    			'result_count' => -1,
348
    			'error' => $error->get_soap_array()
349
    	);
350
	}
351
	if($query == ''){
352
		$where = '';
353
	}
354
	if($offset == '' || $offset == -1){
355
		$offset = 0;
356
	}
357
    if($using_cp){
358
        $response = $seed->retrieveTargetList($query, $select_fields, $offset,-1,-1,$deleted);
359
    }else{
360
        $response = $seed->get_list($order_by, $query, $offset,-1,-1,$deleted,true);
361
    }
362
	$list = $response['list'];
363
364
365
	$output_list = array();
366
367
    $isEmailModule = false;
368
    if($module_name == 'Emails'){
369
        $isEmailModule = true;
370
    }
371
	// retrieve the vardef information on the bean's fields.
372
	$field_list = array();
373
    
374
    require_once 'modules/Currencies/Currency.php';
375
376
    $userCurrencyId = $current_user->getPreference('currency');
377
    $userCurrency = new Currency;
378
    $userCurrency->retrieve($userCurrencyId);
379
380
	foreach($list as $value)
381
	{
382
		if(isset($value->emailAddress)){
383
			$value->emailAddress->handleLegacyRetrieve($value);
384
		}
385
        if($isEmailModule){
386
            $value->retrieveEmailText();
387
        }
388
		$value->fill_in_additional_detail_fields();
389
390
        // bug 55129 - populate currency from user settings
391
        if (property_exists($value, 'currency_id') && $userCurrency->deleted != 1)
392
        {
393
            // walk through all currency-related fields
394
            foreach ($value->field_defs as $temp_field)
395
            {
396
                if (isset($temp_field['type']) && 'relate' == $temp_field['type']
397
                    && isset($temp_field['module'])  && 'Currencies' == $temp_field['module']
398
                    && isset($temp_field['id_name']) && 'currency_id' == $temp_field['id_name'])
399
                {
400
                    // populate related properties manually
401
                    $temp_property     = $temp_field['name'];
402
                    $currency_property = $temp_field['rname'];
403
                    $value->$temp_property = $userCurrency->$currency_property;
404
                }
405
                else if ($value->currency_id != $userCurrency->id
406
                         && isset($temp_field['type'])
407
                         && 'currency' == $temp_field['type']
408
                         && substr($temp_field['name'], -9) != '_usdollar')
409
                {
410
                    $temp_property = $temp_field['name'];
411
                    $value->$temp_property *= $userCurrency->conversion_rate;
412
                }
413
            }
414
415
            $value->currency_id = $userCurrencyId;
416
        }
417
        // end of bug 55129
418
419
		$output_list[] = get_return_value($value, $module_name);
420
		if(empty($field_list)){
421
			$field_list = get_field_list($value);
422
		}
423
	}
424
425
	// Filter the search results to only include the requested fields.
426
	$output_list = filter_return_list($output_list, $select_fields, $module_name);
427
428
	// Filter the list of fields to only include information on the requested fields.
429
	$field_list = filter_return_list($field_list,$select_fields, $module_name);
430
431
	// Calculate the offset for the start of the next page
432
	$next_offset = $offset + sizeof($output_list);
433
434
	return array('result_count'=>sizeof($output_list), 'next_offset'=>$next_offset,'field_list'=>$field_list, 'entry_list'=>$output_list, 'error'=>$error->get_soap_array());
435
}
436
437
$server->register(
438
    'get_entry',
439
    array('session'=>'xsd:string', 'module_name'=>'xsd:string', 'id'=>'xsd:string', 'select_fields'=>'tns:select_fields'),
440
    array('return'=>'tns:get_entry_result'),
441
    $NAMESPACE);
442
443
/**
444
 * Retrieve a single SugarBean based on ID.
445
 *
446
 * @param String $session -- Session ID returned by a previous call to login.
447
 * @param String $module_name -- The name of the module to return records from.  This name should be the name the module was developed under (changing a tab name is studio does not affect the name that should be passed into this method)..
448
 * @param String $id -- The SugarBean's ID value.
449
 * @param Array  $select_fields -- A list of the fields to be included in the results. This optional parameter allows for only needed fields to be retrieved.
450
 * @return unknown
451
 */
452
function get_entry($session, $module_name, $id,$select_fields ){
453
	return get_entries($session, $module_name, array($id), $select_fields);
454
}
455
456
$server->register(
457
    'get_entries',
458
    array('session'=>'xsd:string', 'module_name'=>'xsd:string', 'ids'=>'tns:select_fields', 'select_fields'=>'tns:select_fields'),
459
    array('return'=>'tns:get_entry_result'),
460
    $NAMESPACE);
461
462
/**
463
 * Retrieve a list of SugarBean's based on provided IDs.
464
 *
465
 * @param String $session -- Session ID returned by a previous call to login.
466
 * @param String $module_name -- The name of the module to return records from.  This name should be the name the module was developed under (changing a tab name is studio does not affect the name that should be passed into this method)..
467
 * @param Array $ids -- An array of SugarBean IDs.
468
 * @param Array $select_fields -- A list of the fields to be included in the results. This optional parameter allows for only needed fields to be retrieved.
469
 * @return Array 'field_list' -- Var def information about the returned fields
470
 *               'entry_list' -- The records that were retrieved
471
 *               'error' -- The SOAP error, if any
472
 */
473
function get_entries($session, $module_name, $ids,$select_fields ){
474
	global  $beanList, $beanFiles;
475
	$error = new SoapError();
476
	$field_list = array();
477
	$output_list = array();
478
	if(!validate_authenticated($session)){
479
		$error->set_error('invalid_login');
480
		return array('field_list'=>$field_list, 'entry_list'=>array(), 'error'=>$error->get_soap_array());
481
	}
482
    $using_cp = false;
483
    if($module_name == 'CampaignProspects'){
484
        $module_name = 'Prospects';
485
        $using_cp = true;
486
    }
487
	if(empty($beanList[$module_name])){
488
		$error->set_error('no_module');
489
		return array('field_list'=>$field_list, 'entry_list'=>array(), 'error'=>$error->get_soap_array());
490
	}
491
	global $current_user;
492
	if(!check_modules_access($current_user, $module_name, 'read')){
493
		$error->set_error('no_access');
494
		return array('field_list'=>$field_list, 'entry_list'=>array(), 'error'=>$error->get_soap_array());
495
	}
496
497
	$class_name = $beanList[$module_name];
498
	require_once($beanFiles[$class_name]);
499
500
	//todo can modify in there to call bean->get_list($order_by, $where, 0, -1, -1, $deleted);
501
	//that way we do not have to call retrieve for each bean
502
	//perhaps also add a select_fields to this, so we only get the fields we need
503
	//and not do a select *
504
	foreach($ids as $id){
505
		$seed = new $class_name();
506
507
    if($using_cp){
508
        $seed = $seed->retrieveTarget($id);
509
    }else{
510
		if ($seed->retrieve($id) == null)
511
			$seed->deleted = 1;
512
    }
513
514
    if ($seed->deleted == 1) {
515
    	$list = array();
516
    	$list[] = array('name'=>'warning', 'value'=>'Access to this object is denied since it has been deleted or does not exist');
517
		$list[] = array('name'=>'deleted', 'value'=>'1');
518
    	$output_list[] = Array('id'=>$id,
519
								'module_name'=> $module_name,
520
    							'name_value_list'=>$list,
521
    							);
522
		continue;
523
    }
524
	if(! $seed->ACLAccess('DetailView')){
525
		$error->set_error('no_access');
526
		return array('field_list'=>$field_list, 'entry_list'=>array(), 'error'=>$error->get_soap_array());
527
	}
528
		$output_list[] = get_return_value($seed, $module_name);
529
530
		if(empty($field_list)){
531
				$field_list = get_field_list($seed);
532
533
		}
534
	}
535
536
		$output_list = filter_return_list($output_list, $select_fields, $module_name);
537
		$field_list = filter_field_list($field_list,$select_fields, $module_name);
538
539
	return array( 'field_list'=>$field_list, 'entry_list'=>$output_list, 'error'=>$error->get_soap_array());
540
}
541
542
$server->register(
543
    'set_entry',
544
    array('session'=>'xsd:string', 'module_name'=>'xsd:string',  'name_value_list'=>'tns:name_value_list'),
545
    array('return'=>'tns:set_entry_result'),
546
    $NAMESPACE);
547
548
/**
549
 * Update or create a single SugarBean.
550
 *
551
 * @param String $session -- Session ID returned by a previous call to login.
552
 * @param String $module_name -- The name of the module to return records from.  This name should be the name the module was developed under (changing a tab name is studio does not affect the name that should be passed into this method)..
553
 * @param Array $name_value_list -- The keys of the array are the SugarBean attributes, the values of the array are the values the attributes should have.
554
 * @return Array    'id' -- the ID of the bean that was written to (-1 on error)
555
 *                  'error' -- The SOAP error if any.
556
 */
557
function set_entry($session,$module_name, $name_value_list){
558
	global  $beanList, $beanFiles;
559
560
	$error = new SoapError();
561
	if(!validate_authenticated($session)){
562
		$error->set_error('invalid_login');
563
		return array('id'=>-1, 'error'=>$error->get_soap_array());
564
	}
565
	if(empty($beanList[$module_name])){
566
		$error->set_error('no_module');
567
		return array('id'=>-1, 'error'=>$error->get_soap_array());
568
	}
569
	global $current_user;
570
	if(!check_modules_access($current_user, $module_name, 'write')){
571
		$error->set_error('no_access');
572
		return array('id'=>-1, 'error'=>$error->get_soap_array());
573
	}
574
575
	$class_name = $beanList[$module_name];
576
	require_once($beanFiles[$class_name]);
577
	$seed = new $class_name();
578
579
	foreach($name_value_list as $value){
580
        if($value['name'] == 'id' && isset($value['value']) && strlen($value['value']) > 0){
581
			$result = $seed->retrieve($value['value']);
582
            //bug: 44680 - check to ensure the user has access before proceeding.
583
            if(is_null($result))
584
            {
585
                $error->set_error('no_access');
586
		        return array('id'=>-1, 'error'=>$error->get_soap_array());
587
            }
588
            else
589
            {
590
                break;
591
            }
592
593
		}
594
	}
595
	foreach($name_value_list as $value){
596
        $GLOBALS['log']->debug($value['name']." : ".$value['value']);
597
		$seed->{$value['name']} = $value['value'];
598
	}
599
	if(! $seed->ACLAccess('Save') || ($seed->deleted == 1  &&  !$seed->ACLAccess('Delete')))
600
	{
601
		$error->set_error('no_access');
602
		return array('id'=>-1, 'error'=>$error->get_soap_array());
603
	}
604
	$seed->save();
605
	if($seed->deleted == 1){
606
			$seed->mark_deleted($seed->id);
607
	}
608
	return array('id'=>$seed->id, 'error'=>$error->get_soap_array());
609
610
}
611
612
$server->register(
613
    'set_entries',
614
    array('session'=>'xsd:string', 'module_name'=>'xsd:string',  'name_value_lists'=>'tns:name_value_lists'),
615
    array('return'=>'tns:set_entries_result'),
616
    $NAMESPACE);
617
618
/**
619
 * Update or create a list of SugarBeans
620
 *
621
 * @param String $session -- Session ID returned by a previous call to login.
622
 * @param String $module_name -- The name of the module to return records from.  This name should be the name the module was developed under (changing a tab name is studio does not affect the name that should be passed into this method)..
623
 * @param Array $name_value_lists -- Array of Bean specific Arrays where the keys of the array are the SugarBean attributes, the values of the array are the values the attributes should have.
624
 * @return Array    'ids' -- Array of the IDs of the beans that was written to (-1 on error)
625
 *                  'error' -- The SOAP error if any.
626
 */
627
function set_entries($session,$module_name, $name_value_lists){
628
	$error = new SoapError();
629
630
	if(!validate_authenticated($session)){
631
		$error->set_error('invalid_login');
632
633
		return array(
634
			'ids' => array(),
635
			'error' => $error->get_soap_array()
636
		);
637
	}
638
639
	return handle_set_entries($module_name, $name_value_lists, FALSE);
640
}
641
642
/*
643
NOTE SPECIFIC CODE
644
*/
645
$server->register(
646
        'set_note_attachment',
647
        array('session'=>'xsd:string','note'=>'tns:note_attachment'),
648
        array('return'=>'tns:set_entry_result'),
649
        $NAMESPACE);
650
651
/**
652
 * Add or replace the attachment on a Note.
653
 *
654
 * @param String $session -- Session ID returned by a previous call to login.
655
 * @param Binary $note -- The flie contents of the attachment.
656
 * @return Array 'id' -- The ID of the new note or -1 on error
657
 *               'error' -- The SOAP error if any.
658
 */
659
function set_note_attachment($session,$note)
660
{
661
662
	$error = new SoapError();
663
	if(!validate_authenticated($session)){
664
		$error->set_error('invalid_login');
665
		return array('id'=>-1, 'error'=>$error->get_soap_array());
666
	}
667
668
	require_once('modules/Notes/NoteSoap.php');
669
	$ns = new NoteSoap();
670
	return array('id'=>$ns->saveFile($note), 'error'=>$error->get_soap_array());
671
672
}
673
674
$server->register(
675
    'get_note_attachment',
676
    array('session'=>'xsd:string', 'id'=>'xsd:string'),
677
    array('return'=>'tns:return_note_attachment'),
678
    $NAMESPACE);
679
680
/**
681
 * Retrieve an attachment from a note
682
 * @param String $session -- Session ID returned by a previous call to login.
683
 * @param Binary $note -- The flie contents of the attachment.
0 ignored issues
show
Bug introduced by
There is no parameter named $note. Was it maybe removed?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function.

Consider the following example. The parameter $italy is not defined by the method finale(...).

/**
 * @param array $germany
 * @param array $island
 * @param array $italy
 */
function finale($germany, $island) {
    return "2:1";
}

The most likely cause is that the parameter was removed, but the annotation was not.

Loading history...
684
 * @return Array 'id' -- The ID of the new note or -1 on error
685
 *               'error' -- The SOAP error if any.
686
 *
687
 * @param String $session -- Session ID returned by a previous call to login.
688
 * @param String $id -- The ID of the appropriate Note.
689
 * @return Array 'note_attachment' -- Array String 'id' -- The ID of the Note containing the attachment
690
 *                                          String 'filename' -- The file name of the attachment
691
 *                                          Binary 'file' -- The binary contents of the file.
692
 *               'error' -- The SOAP error if any.
693
 */
694
function get_note_attachment($session,$id)
695
{
696
	$error = new SoapError();
697
	if(!validate_authenticated($session)){
698
		$error->set_error('invalid_login');
699
		return array('result_count'=>-1, 'entry_list'=>array(), 'error'=>$error->get_soap_array());
700
	}
701
702
	$note = new Note();
703
704
	$note->retrieve($id);
705
	if(!$note->ACLAccess('DetailView')){
706
		$error->set_error('no_access');
707
		return array('result_count'=>-1, 'entry_list'=>array(), 'error'=>$error->get_soap_array());
708
	}
709
	require_once('modules/Notes/NoteSoap.php');
710
	$ns = new NoteSoap();
711
	if(!isset($note->filename)){
712
		$note->filename = '';
713
	}
714
	$file= $ns->retrieveFile($id,$note->filename);
715
	if($file == -1){
716
		$error->set_error('no_file');
717
		$file = '';
718
	}
719
720
	return array('note_attachment'=>array('id'=>$id, 'filename'=>$note->filename, 'file'=>$file), 'error'=>$error->get_soap_array());
721
722
}
723
$server->register(
724
    'relate_note_to_module',
725
    array('session'=>'xsd:string', 'note_id'=>'xsd:string', 'module_name'=>'xsd:string', 'module_id'=>'xsd:string'),
726
    array('return'=>'tns:error_value'),
727
    $NAMESPACE);
728
729
/**
730
 * Attach a note to another bean.  Once you have created a note to store an
731
 * attachment, the note needs to be related to the bean.
732
 *
733
 * @param String $session -- Session ID returned by a previous call to login.
734
 * @param String $note_id -- The ID of the note that you want to associate with a bean
735
 * @param String $module_name -- The name of the module to return records from.  This name should be the name the module was developed under (changing a tab name is studio does not affect the name that should be passed into this method)..
736
 * @param String $module_id -- The ID of the bean that you want to associate the note with
737
 * @return no error for success, error for failure
738
 */
739
function relate_note_to_module($session,$note_id, $module_name, $module_id){
740
	global  $beanList, $beanFiles;
741
	$error = new SoapError();
742
	if(!validate_authenticated($session)){
743
		$error->set_error('invalid_login');
744
		return $error->get_soap_array();
745
	}
746
	if(empty($beanList[$module_name])){
747
		$error->set_error('no_module');
748
		return $error->get_soap_array();
749
	}
750
	global $current_user;
751
	if(!check_modules_access($current_user, $module_name, 'read')){
752
		$error->set_error('no_access');
753
		return $error->get_soap_array();
754
	}
755
	$class_name = $beanList['Notes'];
756
	require_once($beanFiles[$class_name]);
757
	$seed = new $class_name();
758
	$seed->retrieve($note_id);
759
	if(!$seed->ACLAccess('ListView')){
760
		$error->set_error('no_access');
761
		return array('result_count'=>-1, 'entry_list'=>array(), 'error'=>$error->get_soap_array());
762
	}
763
764
	if($module_name != 'Contacts'){
765
		$seed->parent_type=$module_name;
766
		$seed->parent_id = $module_id;
767
768
	}else{
769
770
		$seed->contact_id=$module_id;
771
772
	}
773
774
	$seed->save();
775
776
	return $error->get_soap_array();
777
778
}
779
$server->register(
780
    'get_related_notes',
781
    array('session'=>'xsd:string', 'module_name'=>'xsd:string', 'module_id'=>'xsd:string', 'select_fields'=>'tns:select_fields'),
782
    array('return'=>'tns:get_entry_result'),
783
    $NAMESPACE);
784
785
/**
786
 * Retrieve the collection of notes that are related to a bean.
787
 *
788
 * @param String $session -- Session ID returned by a previous call to login.
789
 * @param String $module_name -- The name of the module to return records from.  This name should be the name the module was developed under (changing a tab name is studio does not affect the name that should be passed into this method)..
790
 * @param String $module_id -- The ID of the bean that you want to associate the note with
791
 * @param Array  $select_fields -- A list of the fields to be included in the results. This optional parameter allows for only needed fields to be retrieved.
792
 * @return Array    'result_count' -- The number of records returned (-1 on error)
793
 *                  'next_offset' -- The start of the next page (This will always be the previous offset plus the number of rows returned.  It does not indicate if there is additional data unless you calculate that the next_offset happens to be closer than it should be.
794
 *                  'field_list' -- The vardef information on the selected fields.
795
 *                  'entry_list' -- The records that were retrieved
796
 *                  'error' -- The SOAP error, if any
797
 */
798
function get_related_notes($session,$module_name, $module_id, $select_fields){
799
	global  $beanList, $beanFiles;
800
	$error = new SoapError();
801
	if(!validate_authenticated($session)){
802
		$error->set_error('invalid_login');
803
		return array('result_count'=>-1, 'entry_list'=>array(), 'error'=>$error->get_soap_array());
804
	}
805
	if(empty($beanList[$module_name])){
806
		$error->set_error('no_module');
807
		return array('result_count'=>-1, 'entry_list'=>array(), 'error'=>$error->get_soap_array());
808
	}
809
	global $current_user;
810
	if(!check_modules_access($current_user, $module_name, 'read')){
811
		$error->set_error('no_access');
812
		return array('result_count'=>-1, 'entry_list'=>array(), 'error'=>$error->get_soap_array());
813
	}
814
815
	$class_name = $beanList[$module_name];
816
	require_once($beanFiles[$class_name]);
817
	$seed = new $class_name();
818
	$seed->retrieve($module_id);
819
	if(!$seed->ACLAccess('DetailView')){
820
		$error->set_error('no_access');
821
		return array('result_count'=>-1, 'entry_list'=>array(), 'error'=>$error->get_soap_array());
822
	}
823
	$list = $seed->get_linked_beans('notes','Note', array(), 0, -1, 0);
824
825
	$output_list = Array();
826
	$field_list = Array();
827
	foreach($list as $value)
828
	{
829
		$output_list[] = get_return_value($value, 'Notes');
830
    	if(empty($field_list))
831
    	{
832
			$field_list = get_field_list($value);
833
		}
834
	}
835
	$output_list = filter_return_list($output_list, $select_fields, $module_name);
836
	$field_list = filter_field_list($field_list,$select_fields, $module_name);
837
838
	return array('result_count'=>sizeof($output_list), 'next_offset'=>0,'field_list'=>$field_list, 'entry_list'=>$output_list, 'error'=>$error->get_soap_array());
839
}
840
841
$server->register(
842
        'logout',
843
        array('session'=>'xsd:string'),
844
        array('return'=>'tns:error_value'),
845
        $NAMESPACE);
846
847
/**
848
 * Log out of the session.  This will destroy the session and prevent other's from using it.
849
 *
850
 * @param String $session -- Session ID returned by a previous call to login.
851
 * @return Empty error on success, Error on failure
852
 */
853
function logout($session){
854
	global $current_user;
855
856
	$error = new SoapError();
857
	LogicHook::initialize();
858
	if(validate_authenticated($session)){
859
		$current_user->call_custom_logic('before_logout');
860
		session_destroy();
861
		$GLOBALS['logic_hook']->call_custom_logic('Users', 'after_logout');
862
		return $error->get_soap_array();
863
	}
864
	$error->set_error('no_session');
865
	$GLOBALS['logic_hook']->call_custom_logic('Users', 'after_logout');
866
	return $error->get_soap_array();
867
}
868
869
$server->register(
870
    'get_module_fields',
871
    array('session'=>'xsd:string', 'module_name'=>'xsd:string'),
872
    array('return'=>'tns:module_fields'),
873
    $NAMESPACE);
874
875
/**
876
 * Retrieve vardef information on the fields of the specified bean.
877
 *
878
 * @param String $session -- Session ID returned by a previous call to login.
879
 * @param String $module_name -- The name of the module to return records from.  This name should be the name the module was developed under (changing a tab name is studio does not affect the name that should be passed into this method)..
880
 * @return Array    'module_fields' -- The vardef information on the selected fields.
881
 *                  'error' -- The SOAP error, if any
882
 */
883
function get_module_fields($session, $module_name){
884
	global  $beanList, $beanFiles;
885
	$error = new SoapError();
886
	$module_fields = array();
887
	if(! validate_authenticated($session)){
888
		$error->set_error('invalid_session');
889
		return array('module_fields'=>$module_fields, 'error'=>$error->get_soap_array());
890
	}
891
	if(empty($beanList[$module_name])){
892
		$error->set_error('no_module');
893
		return array('module_fields'=>$module_fields, 'error'=>$error->get_soap_array());
894
	}
895
	global $current_user;
896
	if(!check_modules_access($current_user, $module_name, 'read')){
897
		$error->set_error('no_access');
898
		return array('module_fields'=>$module_fields, 'error'=>$error->get_soap_array());
899
	}
900
	$class_name = $beanList[$module_name];
901
902
	if(empty($beanFiles[$class_name]))
903
	{
904
       $error->set_error('no_file');
905
       return array('module_fields'=>$module_fields, 'error'=>$error->get_soap_array());
906
	}
907
908
	require_once($beanFiles[$class_name]);
909
	$seed = new $class_name();
910
	if($seed->ACLAccess('ListView', true) || $seed->ACLAccess('DetailView', true) || 	$seed->ACLAccess('EditView', true) )
911
    {
912
    	return get_return_module_fields($seed, $module_name, $error);
913
    }
914
    else
915
    {
916
    	$error->set_error('no_access');
917
    	return array('module_fields'=>$module_fields, 'error'=>$error->get_soap_array());
918
    }
919
}
920
921
$server->register(
922
    'get_available_modules',
923
    array('session'=>'xsd:string'),
924
    array('return'=>'tns:module_list'),
925
    $NAMESPACE);
926
927
/**
928
 * Retrieve the list of available modules on the system available to the currently logged in user.
929
 *
930
 * @param String $session -- Session ID returned by a previous call to login.
931
 * @return Array    'modules' -- An array of module names
932
 *                  'error' -- The SOAP error, if any
933
 */
934
function get_available_modules($session){
935
	$error = new SoapError();
936
	$modules = array();
937
	if(! validate_authenticated($session)){
938
		$error->set_error('invalid_session');
939
		return array('modules'=> $modules, 'error'=>$error->get_soap_array());
940
	}
941
	$modules = array_keys($_SESSION['avail_modules']);
942
943
	return array('modules'=> $modules, 'error'=>$error->get_soap_array());
944
}
945
946
947
$server->register(
948
    'update_portal_user',
949
    array('session'=>'xsd:string', 'portal_name'=>'xsd:string', 'name_value_list'=>'tns:name_value_list'),
950
    array('return'=>'tns:error_value'),
951
    $NAMESPACE);
952
953
/**
954
 * Update the properties of a contact that is portal user.  Add the portal user name to the user's properties.
955
 *
956
 * @param String $session -- Session ID returned by a previous call to login.
957
 * @param String $portal_name -- The portal user_name of the contact
958
 * @param Array $name_value_list -- collection of 'name'=>'value' pairs for finding the contact
959
 * @return Empty error on success, Error on failure
960
 */
961
function update_portal_user($session,$portal_name, $name_value_list){
962
	global  $beanList, $beanFiles;
963
	$error = new SoapError();
964
	if(! validate_authenticated($session)){
965
		$error->set_error('invalid_session');
966
		return $error->get_soap_array();
967
	}
968
	$contact = new Contact();
969
970
	$searchBy = array('deleted'=>0);
971
	foreach($name_value_list as $name_value){
972
			$searchBy[$name_value['name']] = $name_value['value'];
973
	}
974
	if($contact->retrieve_by_string_fields($searchBy) != null){
975
		if(!$contact->duplicates_found){
976
			$contact->portal_name = $portal_name;
977
			$contact->portal_active = 1;
978
			if($contact->ACLAccess('Save')){
979
				$contact->save();
980
			}else{
981
				$error->set_error('no_access');
982
			}
983
			return $error->get_soap_array();
984
		}
985
		$error->set_error('duplicates');
986
		return $error->get_soap_array();
987
	}
988
	$error->set_error('no_records');
989
	return $error->get_soap_array();
990
}
991
992
$server->register(
993
    'get_user_id',
994
    array('session'=>'xsd:string'),
995
    array('return'=>'xsd:string'),
996
    $NAMESPACE);
997
998
/**
999
 * Return the user_id of the user that is logged into the current session.
1000
 *
1001
 * @param String $session -- Session ID returned by a previous call to login.
1002
 * @return String -- the User ID of the current session
1003
 *                  -1 on error.
1004
 */
1005
function get_user_id($session){
1006
	if(validate_authenticated($session)){
1007
		global $current_user;
1008
		return $current_user->id;
1009
1010
	}else{
1011
		return '-1';
1012
	}
1013
}
1014
1015
$server->register(
1016
    'get_user_team_id',
1017
    array('session'=>'xsd:string'),
1018
    array('return'=>'xsd:string'),
1019
    $NAMESPACE);
1020
1021
/**
1022
 * Return the ID of the default team for the user that is logged into the current session.
1023
 *
1024
 * @param String $session -- Session ID returned by a previous call to login.
1025
 * @return String -- the Team ID of the current user's default team
1026
 *                  1 for Community Edition
1027
 *                  -1 on error.
1028
 */
1029
function get_user_team_id($session){
1030
	if(validate_authenticated($session))
1031
	{
1032
		 return 1;
1033
	}else{
1034
		return '-1';
1035
	}
1036
}
1037
1038
$server->register(
1039
    'get_user_team_set_id',
1040
    array('session'=>'xsd:string'),
1041
    array('return'=>'xsd:string'),
1042
    $NAMESPACE);
1043
1044
/**
1045
 * Return the Team Set ID for the user that is logged into the current session.
1046
 *
1047
 * @param String $session -- Session ID returned by a previous call to login.
1048
 * @return String -- the Team Set ID of the current user
1049
 *                  1 for Community Edition
1050
 *                  -1 on error.
1051
 */
1052
function get_user_team_set_id($session){
1053
    if(validate_authenticated($session))
1054
    {
1055
         return 1;
1056
    }else{
1057
        return '-1';
1058
    }
1059
}
1060
1061
$server->register(
1062
    'get_server_time',
1063
    array(),
1064
    array('return'=>'xsd:string'),
1065
    $NAMESPACE);
1066
1067
/**
1068
 * Return the current time on the server in the format 'Y-m-d H:i:s'.  This time is in the server's default timezone.
1069
 *
1070
 * @return String -- The current date/time 'Y-m-d H:i:s'
1071
 */
1072
function get_server_time(){
1073
	return date('Y-m-d H:i:s');
1074
}
1075
1076
$server->register(
1077
    'get_gmt_time',
1078
    array(),
1079
    array('return'=>'xsd:string'),
1080
    $NAMESPACE);
1081
1082
/**
1083
 * Return the current time on the server in the format 'Y-m-d H:i:s'.  This time is in GMT.
1084
 *
1085
 * @return String -- The current date/time 'Y-m-d H:i:s'
1086
 */
1087
function get_gmt_time(){
1088
	return TimeDate::getInstance()->nowDb();
1089
}
1090
1091
$server->register(
1092
    'get_sugar_flavor',
1093
    array(),
1094
    array('return'=>'xsd:string'),
1095
    $NAMESPACE);
1096
1097
/**
1098
 * Retrieve the specific flavor of sugar.
1099
 *
1100
 * @return String   'CE' -- For Community Edition
1101
 *                  'PRO' -- For Professional
1102
 *                  'ENT' -- For Enterprise
1103
 */
1104
function get_sugar_flavor(){
1105
 global $sugar_flavor;
1106
1107
 return $sugar_flavor;
1108
}
1109
1110
1111
$server->register(
1112
    'get_server_version',
1113
    array(),
1114
    array('return'=>'xsd:string'),
1115
    $NAMESPACE);
1116
1117
/**
1118
 * Retrieve the version number of Sugar that the server is running.
1119
 *
1120
 * @return String -- The current sugar version number.
1121
 *                   '1.0' on error.
1122
 */
1123
function get_server_version(){
1124
1125
	$admin  = new Administration();
1126
	$admin->retrieveSettings('info');
1127
	if(isset($admin->settings['info_sugar_version'])){
1128
		return $admin->settings['info_sugar_version'];
1129
	}else{
1130
		return '1.0';
1131
	}
1132
1133
}
1134
1135
$server->register(
1136
    'get_relationships',
1137
    array('session'=>'xsd:string', 'module_name'=>'xsd:string', 'module_id'=>'xsd:string', 'related_module'=>'xsd:string', 'related_module_query'=>'xsd:string', 'deleted'=>'xsd:int'),
1138
    array('return'=>'tns:get_relationships_result'),
1139
    $NAMESPACE);
1140
1141
/**
1142
 * Retrieve a collection of beans tha are related to the specified bean.
1143
 * As of 4.5.1c, all combinations of related modules are supported
1144
 *
1145
 * @param String $session -- Session ID returned by a previous call to login.
1146
 * @param String $module_name -- The name of the module that the primary record is from.  This name should be the name the module was developed under (changing a tab name is studio does not affect the name that should be passed into this method)..
1147
 * @param String $module_id -- The ID of the bean in the specified module
1148
 * @param String $related_module -- The name of the related module to return records from.  This name should be the name the module was developed under (changing a tab name is studio does not affect the name that should be passed into this method)..
1149
 * @param String $related_module_query -- A portion of the where clause of the SQL statement to find the related items.  The SQL query will already be filtered to only include the beans that are related to the specified bean.
1150
 * @param Number $deleted -- false if deleted records should not be include, true if deleted records should be included.
1151
 * @return unknown
1152
 */
1153
function get_relationships($session, $module_name, $module_id, $related_module, $related_module_query, $deleted){
1154
		$error = new SoapError();
1155
	$ids = array();
1156
	if(!validate_authenticated($session)){
1157
		$error->set_error('invalid_login');
1158
		return array('ids'=>$ids,'error'=> $error->get_soap_array());
1159
	}
1160
	global  $beanList, $beanFiles;
1161
	$error = new SoapError();
1162
1163
	if(empty($beanList[$module_name]) || empty($beanList[$related_module])){
1164
		$error->set_error('no_module');
1165
		return array('ids'=>$ids, 'error'=>$error->get_soap_array());
1166
	}
1167
	$class_name = $beanList[$module_name];
1168
	require_once($beanFiles[$class_name]);
1169
	$mod = new $class_name();
1170
	$mod->retrieve($module_id);
1171
	if(!$mod->ACLAccess('DetailView')){
1172
		$error->set_error('no_access');
1173
		return array('ids'=>$ids, 'error'=>$error->get_soap_array());
1174
	}
1175
1176
	require_once 'include/SugarSQLValidate.php';
1177
	$valid = new SugarSQLValidate();
1178
	if(!$valid->validateQueryClauses($related_module_query)) {
1179
        $GLOBALS['log']->error("Bad query: $related_module_query");
1180
        $error->set_error('no_access');
1181
	    return array(
1182
    			'result_count' => -1,
1183
    			'error' => $error->get_soap_array()
1184
    		);
1185
    }
1186
1187
    $id_list = get_linked_records($related_module, $module_name, $module_id);
1188
1189
	if ($id_list === FALSE) {
1190
		$error->set_error('no_relationship_support');
1191
		return array('ids'=>$ids, 'error'=>$error->get_soap_array());
1192
	}
1193
	elseif (count($id_list) == 0) {
1194
		return array('ids'=>$ids, 'error'=>$error->get_soap_array());
1195
	}
1196
1197
	$list = array();
1198
1199
	$in = "'".implode("', '", $id_list)."'";
1200
1201
	$related_class_name = $beanList[$related_module];
1202
	require_once($beanFiles[$related_class_name]);
1203
	$related_mod = new $related_class_name();
1204
1205
	$sql = "SELECT {$related_mod->table_name}.id FROM {$related_mod->table_name} ";
1206
1207
1208
    if (isset($related_mod->custom_fields)) {
1209
        $customJoin = $related_mod->custom_fields->getJOIN();
1210
        $sql .= $customJoin ? $customJoin['join'] : '';
1211
    }
1212
1213
	$sql .= " WHERE {$related_mod->table_name}.id IN ({$in}) ";
1214
1215
	if (!empty($related_module_query)) {
1216
		$sql .= " AND ( {$related_module_query} )";
1217
	}
1218
1219
	$result = $related_mod->db->query($sql);
1220
	while ($row = $related_mod->db->fetchByAssoc($result)) {
1221
		$list[] = $row['id'];
1222
	}
1223
1224
	$return_list = array();
1225
1226
	foreach($list as $id) {
1227
		$related_class_name = $beanList[$related_module];
1228
		$related_mod = new $related_class_name();
1229
		$related_mod->retrieve($id);
1230
1231
		$return_list[] = array(
1232
			'id' => $id,
1233
			'date_modified' => $related_mod->date_modified,
1234
			'deleted' => $related_mod->deleted
1235
		);
1236
	}
1237
1238
	return array('ids' => $return_list, 'error' => $error->get_soap_array());
1239
}
1240
1241
1242
$server->register(
1243
    'set_relationship',
1244
    array('session'=>'xsd:string','set_relationship_value'=>'tns:set_relationship_value'),
1245
    array('return'=>'tns:error_value'),
1246
    $NAMESPACE);
1247
1248
/**
1249
 * Set a single relationship between two beans.  The items are related by module name and id.
1250
 *
1251
 * @param String $session -- Session ID returned by a previous call to login.
1252
 * @param Array $set_relationship_value --
1253
 *      'module1' -- The name of the module that the primary record is from.  This name should be the name the module was developed under (changing a tab name is studio does not affect the name that should be passed into this method)..
1254
 *      'module1_id' -- The ID of the bean in the specified module
1255
 *      'module2' -- The name of the module that the related record is from.  This name should be the name the module was developed under (changing a tab name is studio does not affect the name that should be passed into this method)..
1256
 *      'module2_id' -- The ID of the bean in the specified module
1257
 * @return Empty error on success, Error on failure
1258
 */
1259
function set_relationship($session, $set_relationship_value){
1260
	$error = new SoapError();
1261
	if(!validate_authenticated($session)){
1262
		$error->set_error('invalid_login');
1263
		return $error->get_soap_array();
1264
	}
1265
	return handle_set_relationship($set_relationship_value, $session);
1266
}
1267
1268
$server->register(
1269
    'set_relationships',
1270
    array('session'=>'xsd:string','set_relationship_list'=>'tns:set_relationship_list'),
1271
    array('return'=>'tns:set_relationship_list_result'),
1272
    $NAMESPACE);
1273
1274
/**
1275
 * Setup several relationships between pairs of beans.  The items are related by module name and id.
1276
 *
1277
 * @param String $session -- Session ID returned by a previous call to login.
1278
 * @param Array $set_relationship_list -- One for each relationship to setup.  Each entry is itself an array.
1279
 *      'module1' -- The name of the module that the primary record is from.  This name should be the name the module was developed under (changing a tab name is studio does not affect the name that should be passed into this method)..
1280
 *      'module1_id' -- The ID of the bean in the specified module
1281
 *      'module2' -- The name of the module that the related record is from.  This name should be the name the module was developed under (changing a tab name is studio does not affect the name that should be passed into this method)..
1282
 *      'module2_id' -- The ID of the bean in the specified module
1283
 * @return Empty error on success, Error on failure
1284
 */
1285
function set_relationships($session, $set_relationship_list){
1286
	$error = new SoapError();
1287
	if(!validate_authenticated($session)){
1288
		$error->set_error('invalid_login');
1289
		return -1;
1290
	}
1291
	$count = 0;
1292
	$failed = 0;
1293
	foreach($set_relationship_list as $set_relationship_value){
1294
		$reter = handle_set_relationship($set_relationship_value, $session);
1295
		if($reter['number'] == 0){
1296
			$count++;
1297
		}else{
1298
			$failed++;
1299
		}
1300
	}
1301
	return array('created'=>$count , 'failed'=>$failed, 'error'=>$error);
1302
}
1303
1304
1305
1306
//INTERNAL FUNCTION NOT EXPOSED THROUGH SOAP
1307
/**
1308
 * (Internal) Create a relationship between two beans.
1309
 *
1310
 * @param Array $set_relationship_value --
1311
 *      'module1' -- The name of the module that the primary record is from.  This name should be the name the module was developed under (changing a tab name is studio does not affect the name that should be passed into this method)..
1312
 *      'module1_id' -- The ID of the bean in the specified module
1313
 *      'module2' -- The name of the module that the related record is from.  This name should be the name the module was developed under (changing a tab name is studio does not affect the name that should be passed into this method)..
1314
 *      'module2_id' -- The ID of the bean in the specified module
1315
 * @return Empty error on success, Error on failure
1316
 */
1317
function handle_set_relationship($set_relationship_value, $session='')
1318
{
1319
    global  $beanList, $beanFiles;
1320
    $error = new SoapError();
1321
1322
    $module1 = $set_relationship_value['module1'];
1323
    $module1_id = $set_relationship_value['module1_id'];
1324
    $module2 = $set_relationship_value['module2'];
1325
    $module2_id = $set_relationship_value['module2_id'];
1326
1327
    if(empty($beanList[$module1]) || empty($beanList[$module2]) )
1328
    {
1329
        $error->set_error('no_module');
1330
        return $error->get_soap_array();
1331
    }
1332
    $class_name = $beanList[$module1];
1333
    require_once($beanFiles[$class_name]);
1334
    $mod = new $class_name();
1335
    $mod->retrieve($module1_id);
1336
	if(!$mod->ACLAccess('DetailView')){
1337
		$error->set_error('no_access');
1338
		return $error->get_soap_array();
1339
	}
1340
	if($module1 == "Contacts" && $module2 == "Users"){
1341
		$key = 'contacts_users_id';
1342
	}
1343
	else{
1344
    	$key = array_search(strtolower($module2),$mod->relationship_fields);
1345
    	if(!$key) {
1346
    	    $key = Relationship::retrieve_by_modules($module1, $module2, $GLOBALS['db']);
1347
1348
            // BEGIN SnapLogic fix for bug 32064
1349
            if ($module1 == "Quotes" && $module2 == "ProductBundles") {
1350
                // Alternative solution is perhaps to
1351
                // do whatever Sugar does when the same
1352
                // request is received from the web:
1353
                $pb_cls = $beanList[$module2];
1354
                $pb = new $pb_cls();
1355
                $pb->retrieve($module2_id);
1356
1357
                // Check if this relationship already exists
1358
                $query = "SELECT count(*) AS count FROM product_bundle_quote WHERE quote_id = '{$module1_id}' AND bundle_id = '{$module2_id}' AND deleted = '0'";
1359
                $result = $GLOBALS['db']->query($query, true, "Error checking for previously existing relationship between quote and product_bundle");
1360
                $row = $GLOBALS['db']->fetchByAssoc($result);
1361
                if(isset($row['count']) && $row['count'] > 0){
1362
                    return $error->get_soap_array();
1363
                }
1364
1365
                $query = "SELECT MAX(bundle_index)+1 AS idx FROM product_bundle_quote WHERE quote_id = '{$module1_id}' AND deleted='0'";
1366
                $result = $GLOBALS['db']->query($query, true, "Error getting bundle_index");
1367
                $GLOBALS['log']->debug("*********** Getting max bundle_index");
1368
                $GLOBALS['log']->debug($query);
1369
                $row = $GLOBALS['db']->fetchByAssoc($result);
1370
1371
                $idx = 0;
1372
                if ($row) {
1373
                    $idx = $row['idx'];
1374
                }
1375
1376
                $pb->set_productbundle_quote_relationship($module1_id,$module2_id,$idx);
1377
                $pb->save();
1378
                return $error->get_soap_array();
1379
1380
            } else if ($module1 == "ProductBundles" && $module2 == "Products") {
1381
                // And, well, similar things apply in this case
1382
                $pb_cls = $beanList[$module1];
1383
                $pb = new $pb_cls();
1384
                $pb->retrieve($module1_id);
1385
1386
                // Check if this relationship already exists
1387
                $query = "SELECT count(*) AS count FROM product_bundle_product WHERE bundle_id = '{$module1_id}' AND product_id = '{$module2_id}' AND deleted = '0'";
1388
                $result = $GLOBALS['db']->query($query, true, "Error checking for previously existing relationship between quote and product_bundle");
1389
                $row = $GLOBALS['db']->fetchByAssoc($result);
1390
                if(isset($row['count']) && $row['count'] > 0){
1391
                    return $error->get_soap_array();
1392
                }
1393
1394
                $query = "SELECT MAX(product_index)+1 AS idx FROM product_bundle_product WHERE bundle_id='{$module1_id}'";
1395
                $result = $GLOBALS['db']->query($query, true, "Error getting bundle_index");
1396
                $GLOBALS['log']->debug("*********** Getting max bundle_index");
1397
                $GLOBALS['log']->debug($query);
1398
                $row = $GLOBALS['db']->fetchByAssoc($result);
1399
1400
                $idx = 0;
1401
                if ($row) {
1402
                    $idx = $row['idx'];
1403
                }
1404
                $pb->set_productbundle_product_relationship($module2_id,$idx,$module1_id);
1405
                $pb->save();
1406
1407
                $prod_cls = $beanList[$module2];
1408
                $prod = new $prod_cls();
1409
                $prod->retrieve($module2_id);
1410
                $prod->quote_id = $pb->quote_id;
1411
                $prod->save();
1412
                return $error->get_soap_array();
1413
            }
1414
            // END SnapLogic fix for bug 32064
1415
1416
    		if (!empty($key)) {
1417
    			$mod->load_relationship($key);
1418
    			$mod->$key->add($module2_id);
1419
    			return $error->get_soap_array();
1420
    		} // if
1421
        }
1422
    }
1423
1424
    if(!$key)
1425
    {
1426
        $error->set_error('no_module');
1427
        return $error->get_soap_array();
1428
    }
1429
1430
    if(($module1 == 'Meetings' || $module1 == 'Calls') && ($module2 == 'Contacts' || $module2 == 'Users')){
1431
    	$key = strtolower($module2);
1432
    	$mod->load_relationship($key);
1433
    	$mod->$key->add($module2_id);
1434
    }
1435
    else if ($module1 == 'Contacts' && ($module2 == 'Notes' || $module2 == 'Calls' || $module2 == 'Meetings' || $module2 == 'Tasks') && !empty($session)){
1436
        $mod->$key = $module2_id;
1437
        $mod->save_relationship_changes(false);
1438
        if (!empty($mod->account_id)) {
1439
            // when setting a relationship from a Contact to these activities, if the Contacts is related to an Account,
1440
            // we want to associate that Account to the activity as well
1441
            $ret = set_relationship($session, array('module1'=>'Accounts', 'module1_id'=>$mod->account_id, 'module2'=>$module2, 'module2_id'=>$module2_id));
1442
        }
1443
    }
1444
    else{
1445
    	$mod->$key = $module2_id;
1446
    	$mod->save_relationship_changes(false);
1447
    }
1448
1449
    return $error->get_soap_array();
1450
}
1451
1452
1453
$server->register(
1454
        'set_document_revision',
1455
        array('session'=>'xsd:string','note'=>'tns:document_revision'),
1456
        array('return'=>'tns:set_entry_result'),
1457
        $NAMESPACE);
1458
1459
/**
1460
 * Enter description here...
1461
 *
1462
 * @param String $session -- Session ID returned by a previous call to login.
1463
 * @param unknown_type $document_revision
1464
 * @return unknown
1465
 */
1466
function set_document_revision($session,$document_revision)
1467
{
1468
1469
	$error = new SoapError();
1470
	if(!validate_authenticated($session)){
1471
		$error->set_error('invalid_login');
1472
		return array('id'=>-1, 'error'=>$error->get_soap_array());
1473
	}
1474
1475
	require_once('modules/Documents/DocumentSoap.php');
1476
	$dr = new DocumentSoap();
1477
	return array('id'=>$dr->saveFile($document_revision), 'error'=>$error->get_soap_array());
1478
1479
}
1480
1481
$server->register(
1482
        'search_by_module',
1483
        array('user_name'=>'xsd:string','password'=>'xsd:string','search_string'=>'xsd:string', 'modules'=>'tns:select_fields', 'offset'=>'xsd:int', 'max_results'=>'xsd:int'),
1484
        array('return'=>'tns:get_entry_list_result'),
1485
        $NAMESPACE);
1486
1487
/**
1488
 * Given a list of modules to search and a search string, return the id, module_name, along with the fields
1489
 * as specified in the $query_array
1490
 *
1491
 * @param string $user_name 		- username of the Sugar User
1492
 * @param string $password			- password of the Sugar User
1493
 * @param string $search_string 	- string to search
1494
 * @param string[] $modules			- array of modules to query
1495
 * @param int $offset				- a specified offset in the query
1496
 * @param int $max_results			- max number of records to return
1497
 * @return get_entry_list_result 	- id, module_name, and list of fields from each record
1498
 */
1499
function search_by_module($user_name, $password, $search_string, $modules, $offset, $max_results){
1500
	global  $beanList, $beanFiles;
1501
1502
	$error = new SoapError();
1503
    $hasLoginError = false;
1504
1505
    if(empty($user_name) && !empty($password))
1506
    {
1507
        if(!validate_authenticated($password))
1508
        {
1509
            $hasLoginError = true;
1510
        }
1511
    } else if(!validate_user($user_name, $password)) {
1512
		$hasLoginError = true;
1513
	}
1514
1515
    //If there is a login error, then return the error here
1516
    if($hasLoginError)
1517
    {
1518
        $error->set_error('invalid_login');
1519
        return array('result_count'=>-1, 'entry_list'=>array(), 'error'=>$error->get_soap_array());
1520
    }
1521
1522
	global $current_user;
1523
	if($max_results > 0){
1524
		global $sugar_config;
1525
		$sugar_config['list_max_entries_per_page'] = $max_results;
1526
	}
1527
	//  MRF - BUG:19552 - added a join for accounts' emails below
1528
	$query_array = array('Accounts'=>array('where'=>array('Accounts' => array(0 => "accounts.name like '{0}%'"), 'EmailAddresses' => array(0 => "ea.email_address like '{0}%'")),'fields'=>"accounts.id, accounts.name"),
1529
	                        'Bugs'=>array('where'=>array('Bugs' => array(0 => "bugs.name like '{0}%'", 1 => "bugs.bug_number = {0}")),'fields'=>"bugs.id, bugs.name, bugs.bug_number"),
1530
							'Cases'=>array('where'=>array('Cases' => array(0 => "cases.name like '{0}%'", 1 => "cases.case_number = {0}")),'fields'=>"cases.id, cases.name, cases.case_number"),
1531
							'Leads'=>array('where'=>array('Leads' => array(0 => "leads.first_name like '{0}%'",1 => "leads.last_name like '{0}%'"), 'EmailAddresses' => array(0 => "ea.email_address like '{0}%'")), 'fields'=>"leads.id, leads.first_name, leads.last_name, leads.status"),
1532
 							'Project'=>array('where'=>array('Project' => array(0 => "project.name like '{0}%'")), 'fields'=>"project.id, project.name"),
1533
                            'ProjectTask'=>array('where'=>array('ProjectTask' => array(0 => "project.id = '{0}'")), 'fields'=>"project_task.id, project_task.name"),
1534
							'Contacts'=>array('where'=>array('Contacts' => array(0 => "contacts.first_name like '{0}%'", 1 => "contacts.last_name like '{0}%'"), 'EmailAddresses' => array(0 => "ea.email_address like '{0}%'")),'fields'=>"contacts.id, contacts.first_name, contacts.last_name"),
1535
							'Opportunities'=>array('where'=>array('Opportunities' => array(0 => "opportunities.name like '{0}%'")), 'fields'=>"opportunities.id, opportunities.name"),
1536
							'Users'=>array('where'=>array('EmailAddresses' => array(0 => "ea.email_address like '{0}%'")),'fields'=>"users.id, users.user_name, users.first_name, ea.email_address"),
1537
						);
1538
1539
	$more_query_array = array();
1540
	foreach($modules as $module) {
1541
	    if (!array_key_exists($module, $query_array)) {
1542
            $seed = new $beanList[$module]();
1543
            $table_name = $seed->table_name;
1544
            if (!empty($seed->field_defs['name']['db_concat_fields'])) {
1545
                $namefield = $seed->db->concat($table_name, $seed->field_defs['name']['db_concat_fields']);
1546
            } else {
1547
                $namefield = "$table_name.name";
1548
            }
1549
            $more_query_array[$module] = array(
1550
                'where' => array(
1551
                    $module => array(
1552
                        0 => "$namefield like '%{0}%'",
1553
                    ),
1554
                ),
1555
                'fields' => "$table_name.id, $namefield AS name"
1556
            );
1557
     }
1558
	}
1559
1560
	if (!empty($more_query_array)) {
1561
	    $query_array = array_merge($query_array, $more_query_array);
1562
	}
1563
1564
	if(!empty($search_string) && isset($search_string)){
1565
		foreach($modules as $module_name){
1566
			$class_name = $beanList[$module_name];
1567
			require_once($beanFiles[$class_name]);
1568
			$seed = new $class_name();
1569
			if(empty($beanList[$module_name])){
1570
				continue;
1571
			}
1572
			if(!check_modules_access($current_user, $module_name, 'read')){
1573
				continue;
1574
			}
1575
			if(! $seed->ACLAccess('ListView'))
1576
			{
1577
				continue;
1578
			}
1579
1580
			if(isset($query_array[$module_name])){
1581
				$query = '';
1582
				$tmpQuery = '';
1583
				//split here to do while loop
1584
				foreach($query_array[$module_name]['where'] as $key => $value){
1585
					foreach($value as $where_clause){
1586
						$addQuery = true;
1587
						if(!empty($query))
1588
							$tmpQuery = ' UNION ';
1589
						$tmpQuery .= "SELECT ".$query_array[$module_name]['fields']." FROM $seed->table_name ";
1590
						// We need to confirm that the user is a member of the team of the item.
1591
1592
1593
		                if($module_name == 'ProjectTask'){
1594
		                    $tmpQuery .= "INNER JOIN project ON $seed->table_name.project_id = project.id ";
1595
		                }
1596
1597
		               	if(isset($seed->emailAddress) && $key == 'EmailAddresses'){
1598
		               		$tmpQuery .= " INNER JOIN email_addr_bean_rel eabl  ON eabl.bean_id = $seed->table_name.id and eabl.deleted=0";
1599
		              		$tmpQuery .= " INNER JOIN email_addresses ea ON (ea.id = eabl.email_address_id) ";
1600
		                }
1601
						$where = "WHERE (";
1602
						$search_terms = explode(", ", $search_string);
1603
						$termCount = count($search_terms);
1604
						$count = 1;
1605
						if($key != 'EmailAddresses'){
1606
							foreach($search_terms as $term){
1607
								if(!strpos($where_clause, 'number')){
1608
									$where .= string_format($where_clause,array($GLOBALS['db']->quote($term)));
1609
								}elseif(is_numeric($term)){
1610
									$where .= string_format($where_clause,array($GLOBALS['db']->quote($term)));
1611
								}else{
1612
									$addQuery = false;
1613
								}
1614
								if($count < $termCount){
1615
									$where .= " OR ";
1616
								}
1617
								$count++;
1618
							}
1619
						}else{
1620
                            $where .= '(';
1621
                            foreach ($search_terms as $term)
1622
                            {
1623
                                $where .= "ea.email_address LIKE '".$GLOBALS['db']->quote($term)."'";
1624
                                if ($count < $termCount)
1625
                                {
1626
                                    $where .= " OR ";
1627
                                }
1628
                                $count++;
1629
                            }
1630
                            $where .= ')';
1631
						}
1632
						$tmpQuery .= $where;
1633
						$tmpQuery .= ") AND $seed->table_name.deleted = 0";
1634
						if($addQuery)
1635
							$query .= $tmpQuery;
1636
					}
1637
				}
1638
				//grab the items from the db
1639
				$result = $seed->db->query($query, $offset, $max_results);
1640
1641
				while(($row = $seed->db->fetchByAssoc($result)) != null){
1642
					$list = array();
1643
                    foreach ($row as $field_key => $field_value) {
1644
                        $list[$field_key] = array('name'=>$field_key, 'value'=>$field_value);
1645
					}
1646
1647
					$output_list[] = array('id'=>$row['id'],
1648
									   'module_name'=>$module_name,
1649
									   'name_value_list'=>$list);
1650
					if(empty($field_list)){
1651
						$field_list = get_field_list($row);
1652
					}
1653
				}//end while
1654
			}
1655
		}//end foreach
1656
	}
1657
1658
	$next_offset = $offset + sizeof($output_list);
1659
1660
	return array('result_count'=>sizeof($output_list), 'next_offset'=>$next_offset,'field_list'=>$field_list, 'entry_list'=>$output_list, 'error'=>$error->get_soap_array());
1661
1662
}//end function
1663
1664
1665
$server->register(
1666
'get_mailmerge_document',
1667
array('session'=>'xsd:string','file_name'=>'xsd:string', 'fields' => 'tns:select_fields'),
1668
array('return'=>'tns:get_sync_result_encoded'),
1669
$NAMESPACE);
1670
1671
/**
1672
 * Get MailMerge document
1673
 *
1674
 * @param String $session -- Session ID returned by a previous call to login.
1675
 * @param unknown_type $file_name
1676
 * @param unknown_type $fields
1677
 * @return unknown
1678
 */
1679
function get_mailmerge_document($session, $file_name, $fields)
1680
{
1681
    global  $beanList, $beanFiles, $app_list_strings;
1682
    $error = new SoapError();
1683
    if(!validate_authenticated($session))
1684
    {
1685
        $error->set_error('invalid_login');
1686
        return array('result'=>'', 'error'=>$error->get_soap_array());
1687
    }
1688
    if(!preg_match('/^sugardata[\.\d\s]+\.php$/', $file_name)) {
1689
        $error->set_error('no_records');
1690
        return array('result'=>'', 'error'=>$error->get_soap_array());
1691
    }
1692
    $html = '';
1693
1694
    $file_name = sugar_cached('MergedDocuments/').pathinfo($file_name, PATHINFO_BASENAME);
1695
1696
    $master_fields = array();
1697
    $related_fields = array();
1698
1699
    if(file_exists($file_name))
1700
    {
1701
        include($file_name);
1702
1703
        $class1 = $merge_array['master_module'];
1704
        $beanL = $beanList[$class1];
1705
        $bean1 = $beanFiles[$beanL];
1706
        require_once($bean1);
1707
        $seed1 = new $beanL();
1708
1709
        if(!empty($merge_array['related_module']))
1710
        {
1711
            $class2 = $merge_array['related_module'];
1712
            $beanR = $beanList[$class2];
1713
            $bean2 = $beanFiles[$beanR];
1714
            require_once($bean2);
1715
            $seed2 = new $beanR();
1716
        }
1717
1718
        //parse fields
1719
        //$token1 = strtolower($class1);
1720
        if($class1 == 'Prospects'){
1721
            $class1 = 'CampaignProspects';
1722
        }
1723
        foreach($fields as $field)
1724
        {
1725
            $pos = strpos(strtolower($field), strtolower($class1));
1726
            $pos2 = strpos(strtolower($field), strtolower($class2));
1727
            if($pos !== false){
1728
            	$fieldName = str_replace(strtolower($class1).'_', '', strtolower($field));
1729
            	array_push($master_fields, $fieldName);
1730
            }else if($pos2 !== false){
1731
            	$fieldName = str_replace(strtolower($class2).'_', '', strtolower($field));
1732
            	array_push($related_fields, $fieldName);
1733
            }
1734
        }
1735
1736
        $html = '<html ' . get_language_header() .'><body><table border = 1><tr>';
1737
1738
        foreach($master_fields as $master_field){
1739
            $html .= '<td>'.$class1.'_'.$master_field.'</td>';
1740
        }
1741
        foreach($related_fields as $related_field){
1742
            $html .= '<td>'.$class2.'_'.$related_field.'</td>';
1743
        }
1744
        $html .= '</tr>';
1745
1746
        $ids = $merge_array['ids'];
1747
        $is_prospect_merge = ($seed1->object_name == 'Prospect');
1748
        foreach($ids as $key=>$value){
1749
            if($is_prospect_merge){
1750
                $seed1 = $seed1->retrieveTarget($key);
1751
            }else{
1752
                $seed1->retrieve($key);
1753
            }
1754
            $html .= '<tr>';
1755
            foreach($master_fields as $master_field){
1756
                if(isset($seed1->$master_field)){
1757
                    if($seed1->field_name_map[$master_field]['type'] == 'enum'){
1758
                        //pull in the translated dom
1759
                         $html .='<td>'.$app_list_strings[$seed1->field_name_map[$master_field]['options']][$seed1->$master_field].'</td>';
1760
                    }else{
1761
                        $html .='<td>'.$seed1->$master_field.'</td>';
1762
                    }
1763
                }
1764
                else{
1765
                    $html .= '<td></td>';
1766
                    }
1767
            }
1768
            if(isset($value) && !empty($value)){
1769
                $seed2->retrieve($value);
1770
                foreach($related_fields as $related_field){
1771
                    if(isset($seed2->$related_field)){
1772
                        if($seed2->field_name_map[$related_field]['type'] == 'enum'){
1773
                            //pull in the translated dom
1774
                            $html .='<td>'.$app_list_strings[$seed2->field_name_map[$related_field]['options']][$seed2->$related_field].'</td>';
1775
                        }else{
1776
                            $html .= '<td>'.$seed2->$related_field.'</td>';
1777
                        }
1778
                    }
1779
                    else{
1780
                        $html .= '<td></td>';
1781
                    }
1782
                }
1783
            }
1784
            $html .= '</tr>';
1785
        }
1786
        $html .= "</table></body></html>";
1787
     }
1788
1789
    $result = base64_encode($html);
1790
    return array('result' => $result, 'error' => $error);
1791
}
1792
1793
$server->register(
1794
'get_mailmerge_document2',
1795
array('session'=>'xsd:string','file_name'=>'xsd:string', 'fields' => 'tns:select_fields'),
1796
array('return'=>'tns:get_mailmerge_document_result'),
1797
$NAMESPACE);
1798
1799
/**
1800
 * Enter description here...
1801
 *
1802
 * @param String $session -- Session ID returned by a previous call to login.
1803
 * @param unknown_type $file_name
1804
 * @param unknown_type $fields
1805
 * @return unknown
1806
 */
1807
function get_mailmerge_document2($session, $file_name, $fields)
1808
{
1809
    global  $beanList, $beanFiles, $app_list_strings, $app_strings;
1810
1811
    $error = new SoapError();
1812
    if(!validate_authenticated($session))
1813
    {
1814
        $GLOBALS['log']->error('invalid_login');
1815
        $error->set_error('invalid_login');
1816
        return array('result'=>'', 'error'=>$error->get_soap_array());
1817
    }
1818
    if(!preg_match('/^sugardata[\.\d\s]+\.php$/', $file_name)) {
1819
        $GLOBALS['log']->error($app_strings['ERR_NO_SUCH_FILE'] . " ({$file_name})");
1820
        $error->set_error('no_records');
1821
        return array('result'=>'', 'error'=>$error->get_soap_array());
1822
    }
1823
    $html = '';
1824
1825
    $file_name = sugar_cached('MergedDocuments/').pathinfo($file_name, PATHINFO_BASENAME);
1826
1827
    $master_fields = array();
1828
    $related_fields = array();
1829
1830
    if(file_exists($file_name))
1831
    {
1832
        include($file_name);
1833
1834
        $class1 = $merge_array['master_module'];
1835
        $beanL = $beanList[$class1];
1836
        $bean1 = $beanFiles[$beanL];
1837
        require_once($bean1);
1838
        $seed1 = new $beanL();
1839
1840
        if(!empty($merge_array['related_module']))
1841
        {
1842
            $class2 = $merge_array['related_module'];
1843
            $beanR = $beanList[$class2];
1844
            $bean2 = $beanFiles[$beanR];
1845
            require_once($bean2);
1846
            $seed2 = new $beanR();
1847
        }
1848
1849
        //parse fields
1850
        //$token1 = strtolower($class1);
1851
        if($class1 == 'Prospects'){
1852
            $class1 = 'CampaignProspects';
1853
        }
1854
        foreach($fields as $field)
1855
        {
1856
        	$pos = strpos(strtolower($field), strtolower($class1));
1857
            $pos2 = strpos(strtolower($field), strtolower($class2));
1858
            if($pos !== false){
1859
            	$fieldName = str_replace(strtolower($class1).'_', '', strtolower($field));
1860
            	array_push($master_fields, $fieldName);
1861
            }else if($pos2 !== false){
1862
            	$fieldName = str_replace(strtolower($class2).'_', '', strtolower($field));
1863
            	array_push($related_fields, $fieldName);
1864
            }
1865
        }
1866
1867
        $html = '<html ' . get_language_header() . '><body><table border = 1><tr>';
1868
1869
        foreach($master_fields as $master_field){
1870
            $html .= '<td>'.$class1.'_'.$master_field.'</td>';
1871
        }
1872
        foreach($related_fields as $related_field){
1873
            $html .= '<td>'.$class2.'_'.$related_field.'</td>';
1874
        }
1875
        $html .= '</tr>';
1876
1877
        $ids = $merge_array['ids'];
1878
        $resultIds = array();
1879
        $is_prospect_merge = ($seed1->object_name == 'Prospect');
1880
        if($is_prospect_merge){
1881
        	$pSeed = $seed1;
1882
        }
1883
        foreach($ids as $key=>$value){
1884
1885
            if($is_prospect_merge){
1886
                $seed1 = $pSeed->retrieveTarget($key);
1887
            }else{
1888
                $seed1->retrieve($key);
1889
            }
1890
             $resultIds[] = array('name' => $seed1->module_name, 'value' => $key);
1891
            $html .= '<tr>';
1892
            foreach($master_fields as $master_field){
1893
                if(isset($seed1->$master_field)){
1894
                    if($seed1->field_name_map[$master_field]['type'] == 'enum'){
1895
                        //pull in the translated dom
1896
                         $html .='<td>'.$app_list_strings[$seed1->field_name_map[$master_field]['options']][$seed1->$master_field].'</td>';
1897
                    } else if ($seed1->field_name_map[$master_field]['type'] == 'multienum') {
1898
1899
                        if(isset($app_list_strings[$seed1->field_name_map[$master_field]['options']]) )
1900
                        {
1901
                            $items = unencodeMultienum($seed1->$master_field);
1902
                            $output = array();
1903
                            foreach($items as $item) {
1904
                                if ( !empty($app_list_strings[$seed1->field_name_map[$master_field]['options']][$item]) )
1905
                                {
1906
                                    array_push($output, $app_list_strings[$seed1->field_name_map[$master_field]['options']][$item]);
1907
1908
                                }
1909
1910
                            } // foreach
1911
1912
                            $encoded_output = encodeMultienumValue($output);
1913
                            $html .= "<td>$encoded_output</td>";
1914
1915
                        }
1916
                    } else if ($seed1->field_name_map[$master_field]['type'] == 'currency') {
1917
                        $amount_field = $seed1->$master_field;
1918
                        $params = array( 'currency_symbol' => false );
1919
                        $amount_field = currency_format_number($amount_field, $params);
1920
                        $html .='<td>'.$amount_field.'</td>';
1921
                    } else {
1922
                       $html .='<td>'.$seed1->$master_field.'</td>';
1923
                    }
1924
                }
1925
                else{
1926
                    $html .= '<td></td>';
1927
                    }
1928
            }
1929
            if(isset($value) && !empty($value)){
1930
                $resultIds[] = array('name' => $seed2->module_name, 'value' => $value);
1931
				$seed2->retrieve($value);
1932
                foreach($related_fields as $related_field){
1933
                    if(isset($seed2->$related_field)){
1934
                        if($seed2->field_name_map[$related_field]['type'] == 'enum'){
1935
                            //pull in the translated dom
1936
                            $html .='<td>'.$app_list_strings[$seed2->field_name_map[$related_field]['options']][$seed2->$related_field].'</td>';
1937
                        } else if ($seed2->field_name_map[$related_field]['type'] == 'currency') {
1938
                            $amount_field = $seed2->$related_field;
1939
                            $params = array( 'currency_symbol' => false );
1940
                            $amount_field = currency_format_number($amount_field, $params);
1941
                            $html .='<td>'.$amount_field.'</td>';
1942
                        }else{
1943
                            $html .= '<td>'.$seed2->$related_field.'</td>';
1944
                        }
1945
                    }
1946
                    else{
1947
                        $html .= '<td></td>';
1948
                    }
1949
                }
1950
            }
1951
            $html .= '</tr>';
1952
        }
1953
        $html .= "</table></body></html>";
1954
     }
1955
    $result = base64_encode($html);
1956
1957
    return array('html' => $result, 'name_value_list' => $resultIds, 'error' => $error);
1958
}
1959
1960
$server->register(
1961
        'get_document_revision',
1962
        array('session'=>'xsd:string','i'=>'xsd:string'),
1963
        array('return'=>'tns:return_document_revision'),
1964
        $NAMESPACE);
1965
1966
/**
1967
 * This method is used as a result of the .htaccess lock down on the cache directory. It will allow a
1968
 * properly authenticated user to download a document that they have proper rights to download.
1969
 *
1970
 * @param String $session -- Session ID returned by a previous call to login.
1971
 * @param String $id      -- ID of the document revision to obtain
1972
 * @return return_document_revision - this is a complex type as defined in SoapTypes.php
1973
 */
1974
function get_document_revision($session,$id)
1975
{
1976
    global $sugar_config;
1977
1978
    $error = new SoapError();
1979
    if(!validate_authenticated($session)){
1980
        $error->set_error('invalid_login');
1981
        return array('id'=>-1, 'error'=>$error->get_soap_array());
1982
    }
1983
1984
1985
    $dr = new DocumentRevision();
1986
    $dr->retrieve($id);
1987
    if(!empty($dr->filename)){
1988
        $filename = "upload://{$dr->id}";
1989
        $contents = base64_encode(sugar_file_get_contents($filename));
1990
        return array('document_revision'=>array('id' => $dr->id, 'document_name' => $dr->document_name, 'revision' => $dr->revision, 'filename' => $dr->filename, 'file' => $contents), 'error'=>$error->get_soap_array());
1991
    }else{
1992
        $error->set_error('no_records');
1993
        return array('id'=>-1, 'error'=>$error->get_soap_array());
1994
    }
1995
1996
}
1997
$server->register(
1998
    'set_campaign_merge',
1999
    array('session'=>'xsd:string', 'targets'=>'tns:select_fields', 'campaign_id'=>'xsd:string'),
2000
    array('return'=>'tns:error_value'),
2001
    $NAMESPACE);
2002
/**
2003
*   Once we have successfuly done a mail merge on a campaign, we need to notify Sugar of the targets
2004
*   and the campaign_id for tracking purposes
2005
*
2006
* @param session        the session id of the authenticated user
2007
* @param targets        a string array of ids identifying the targets used in the merge
2008
* @param campaign_id    the campaign_id used for the merge
2009
*
2010
* @return error_value
2011
*/
2012
function set_campaign_merge($session,$targets, $campaign_id){
2013
    $error = new SoapError();
2014
    if(!validate_authenticated($session)){
2015
        $error->set_error('invalid_login');
2016
        return $error->get_soap_array();
2017
    }
2018
    if (empty($campaign_id) or !is_array($targets) or count($targets) == 0) {
2019
        $GLOBALS['log']->debug('set_campaign_merge: Merge action status will not be updated, because, campaign_id is null or no targets were selected.');
2020
    } else {
2021
        require_once('modules/Campaigns/utils.php');
2022
        campaign_log_mail_merge($campaign_id,$targets);
2023
    }
2024
2025
    return $error->get_soap_array();
2026
}
2027
$server->register(
2028
    'get_entries_count',
2029
    array('session'=>'xsd:string', 'module_name'=>'xsd:string', 'query'=>'xsd:string', 'deleted' => 'xsd:int'),
2030
    array('return'=>'tns:get_entries_count_result'),
2031
    $NAMESPACE);
2032
2033
/**
2034
*   Retrieve number of records in a given module
2035
*
2036
* @param session        the session id of the authenticated user
2037
* @param module_name    module to retrieve number of records from
2038
* @param query          allows webservice user to provide a WHERE clause
2039
* @param deleted        specify whether or not to include deleted records
2040
*
2041
@return get_entries_count_result - this is a complex type as defined in SoapTypes.php
2042
*/
2043
function get_entries_count($session, $module_name, $query, $deleted) {
2044
	global $beanList, $beanFiles, $current_user;
2045
2046
	$error = new SoapError();
2047
2048
	if (!validate_authenticated($session)) {
2049
		$error->set_error('invalid_login');
2050
		return array(
2051
			'result_count' => -1,
2052
			'error' => $error->get_soap_array()
2053
		);
2054
	}
2055
2056
	if (empty($beanList[$module_name])) {
2057
		$error->set_error('no_module');
2058
		return array(
2059
			'result_count' => -1,
2060
			'error' => $error->get_soap_array()
2061
		);
2062
	}
2063
2064
	if(!check_modules_access($current_user, $module_name, 'list')){
2065
		$error->set_error('no_access');
2066
		return array(
2067
			'result_count' => -1,
2068
			'error' => $error->get_soap_array()
2069
		);
2070
	}
2071
2072
	$class_name = $beanList[$module_name];
2073
	require_once($beanFiles[$class_name]);
2074
	$seed = new $class_name();
2075
2076
	if (!$seed->ACLAccess('ListView')) {
2077
		$error->set_error('no_access');
2078
		return array(
2079
			'result_count' => -1,
2080
			'error' => $error->get_soap_array()
2081
		);
2082
	}
2083
2084
	$sql = 'SELECT COUNT(*) result_count FROM ' . $seed->table_name . ' ';
2085
2086
2087
    $customJoin = $seed->getCustomJoin();
2088
    $sql .= $customJoin['join'];
2089
2090
	// build WHERE clauses, if any
2091
	$where_clauses = array();
2092
	if (!empty($query)) {
2093
	    require_once 'include/SugarSQLValidate.php';
2094
	    $valid = new SugarSQLValidate();
2095
	    if(!$valid->validateQueryClauses($query)) {
2096
            $GLOBALS['log']->error("Bad query: $query");
2097
	        $error->set_error('no_access');
2098
	        return array(
2099
    			'result_count' => -1,
2100
    			'error' => $error->get_soap_array()
2101
    		);
2102
	    }
2103
		$where_clauses[] = $query;
2104
	}
2105
	if ($deleted == 0) {
2106
		$where_clauses[] = $seed->table_name . '.deleted = 0';
2107
	}
2108
2109
	// if WHERE clauses exist, add them to query
2110
	if (!empty($where_clauses)) {
2111
		$sql .= ' WHERE ' . implode(' AND ', $where_clauses);
2112
	}
2113
2114
	$res = $GLOBALS['db']->query($sql);
2115
	$row = $GLOBALS['db']->fetchByAssoc($res);
2116
2117
	return array(
2118
		'result_count' => $row['result_count'],
2119
		'error' => $error->get_soap_array()
2120
	);
2121
}
2122
2123
$server->register(
2124
    'set_entries_details',
2125
    array('session'=>'xsd:string', 'module_name'=>'xsd:string',  'name_value_lists'=>'tns:name_value_lists', 'select_fields' => 'tns:select_fields'),
2126
    array('return'=>'tns:set_entries_detail_result'),
2127
    $NAMESPACE);
2128
2129
/**
2130
 * Update or create a list of SugarBeans, returning details about the records created/updated
2131
 *
2132
 * @param String $session -- Session ID returned by a previous call to login.
2133
 * @param String $module_name -- The name of the module to return records from.  This name should be the name the module was developed under (changing a tab name is studio does not affect the name that should be passed into this method)..
2134
 * @param Array $name_value_lists -- Array of Bean specific Arrays where the keys of the array are the SugarBean attributes, the values of the array are the values the attributes should have.
2135
 * @param Array  $select_fields -- A list of the fields to be included in the results. This optional parameter allows for only needed fields to be retrieved.
2136
 * @return Array    'name_value_lists' --  Array of Bean specific Arrays where the keys of the array are the SugarBean attributes, the values of the array are the values the attributes should have.
2137
 *                  'error' -- The SOAP error if any.
2138
 */
2139
function set_entries_details($session, $module_name, $name_value_lists, $select_fields) {
2140
	$error = new SoapError();
2141
2142
	if(!validate_authenticated($session)){
2143
		$error->set_error('invalid_login');
2144
2145
		return array(
2146
			'ids' => array(),
2147
			'error' => $error->get_soap_array()
2148
		);
2149
	}
2150
2151
	return handle_set_entries($module_name, $name_value_lists, $select_fields);
2152
}
2153
2154
// INTERNAL FUNCTION NOT EXPOSED THROUGH API
2155
function handle_set_entries($module_name, $name_value_lists, $select_fields = FALSE) {
2156
	global $beanList, $beanFiles, $app_list_strings, $current_user;
2157
2158
	$error = new SoapError();
2159
	$ret_values = array();
2160
2161
	if(empty($beanList[$module_name])){
2162
		$error->set_error('no_module');
2163
		return array('ids'=>array(), 'error'=>$error->get_soap_array());
2164
	}
2165
2166
    if(!check_modules_access($current_user, $module_name, 'write')){
2167
		$error->set_error('no_access');
2168
		return array('ids'=>-1, 'error'=>$error->get_soap_array());
2169
	}
2170
2171
	$class_name = $beanList[$module_name];
2172
	require_once($beanFiles[$class_name]);
2173
	$ids = array();
2174
	$count = 1;
2175
	$total = sizeof($name_value_lists);
2176
2177
	foreach($name_value_lists as $name_value_list){
2178
		$seed = new $class_name();
2179
2180
		$seed->update_vcal = false;
2181
2182
        //See if we can retrieve the seed by a given id value
2183
		foreach($name_value_list as $value)
2184
        {
2185
			if($value['name'] == 'id')
2186
            {
2187
				$seed->retrieve($value['value']);
2188
				break;
2189
			}
2190
		}
2191
2192
2193
        $dataValues = array();
2194
2195
		foreach($name_value_list as $value)
2196
        {
2197
			$val = $value['value'];
2198
2199
			if($seed->field_name_map[$value['name']]['type'] == 'enum' || $seed->field_name_map[$value['name']]['type'] == 'radioenum')
2200
            {
2201
				$vardef = $seed->field_name_map[$value['name']];
2202
				if(isset($app_list_strings[$vardef['options']]) && !isset($app_list_strings[$vardef['options']][$val]) )
2203
                {
2204
		            if ( in_array($val,$app_list_strings[$vardef['options']]) )
2205
                    {
2206
		                $val = array_search($val,$app_list_strings[$vardef['options']]);
2207
		            }
2208
		        }
2209
2210
			} else if($seed->field_name_map[$value['name']]['type'] == 'multienum') {
2211
2212
                $vardef = $seed->field_name_map[$value['name']];
2213
2214
                if(isset($app_list_strings[$vardef['options']]) && !isset($app_list_strings[$vardef['options']][$value]) )
2215
                {
2216
					$items = explode(",", $val);
2217
					$parsedItems = array();
2218
					foreach ($items as $item)
2219
                    {
2220
						if ( in_array($item, $app_list_strings[$vardef['options']]) )
2221
                        {
2222
							$keyVal = array_search($item,$app_list_strings[$vardef['options']]);
2223
							array_push($parsedItems, $keyVal);
2224
						}
2225
					}
2226
2227
		           	if (!empty($parsedItems))
2228
                    {
2229
						$val = encodeMultienumValue($parsedItems);
2230
		           	}
2231
		        }
2232
			}
2233
2234
            //Apply the non-empty values now since this will be used for duplicate checks
2235
            //allow string or int of 0 to be updated if set.
2236
            if(!empty($val) || ($val==='0' || $val===0))
2237
            {
2238
                $seed->{$value['name']} = $val;
2239
            }
2240
            //Store all the values in dataValues Array to apply later
2241
            $dataValues[$value['name']] = $val;
2242
		}
2243
2244
		if($count == $total)
2245
        {
2246
			$seed->update_vcal = false;
2247
		}
2248
		$count++;
2249
2250
		//Add the account to a contact
2251
		if($module_name == 'Contacts'){
2252
			$GLOBALS['log']->debug('Creating Contact Account');
2253
			add_create_account($seed);
2254
			$duplicate_id = check_for_duplicate_contacts($seed);
2255
			if($duplicate_id == null)
2256
            {
2257
				if($seed->ACLAccess('Save') && ($seed->deleted != 1 || $seed->ACLAccess('Delete')))
2258
                {
2259
                    //Now apply the values, since this is not a duplicate we can just pass false for the $firstSync argument
2260
                    apply_values($seed, $dataValues, false);
2261
					$seed->save();
2262
					if($seed->deleted == 1){
2263
						$seed->mark_deleted($seed->id);
2264
					}
2265
					$ids[] = $seed->id;
2266
				}
2267
			}else{
2268
				//since we found a duplicate we should set the sync flag
2269
				if( $seed->ACLAccess('Save'))
2270
                {
2271
                    //Determine if this is a first time sync.  We find out based on whether or not a contacts_users relationship exists
2272
                    $seed->id = $duplicate_id;
2273
                    $seed->load_relationship("user_sync");
2274
                    $beans = $seed->user_sync->getBeans();
2275
                    $first_sync = empty($beans);
2276
2277
                    //Now apply the values and indicate whether or not this is a first time sync
2278
                    apply_values($seed, $dataValues, $first_sync);
2279
					$seed->contacts_users_id = $current_user->id;
2280
					$seed->save();
2281
					$ids[] = $duplicate_id;//we have a conflict
2282
				}
2283
			}
2284
2285
        } else if($module_name == 'Meetings' || $module_name == 'Calls'){
2286
			//we are going to check if we have a meeting in the system
2287
			//with the same outlook_id. If we do find one then we will grab that
2288
			//id and save it
2289
            if ($seed->ACLAccess('Save') && ($seed->deleted != 1 || $seed->ACLAccess('Delete'))) {
2290
                // Check if we're updating an old record, or creating a new
2291
                if (empty($seed->id)) {
2292
                    // If it's a new one, and we have outlook_id set
2293
                    // which means we're syncing from OPI check if it already exists
2294
                    if (!empty($seed->outlook_id)) {
2295
                        $GLOBALS['log']->debug(
2296
                            'Looking for ' . $module_name . ' with outlook_id ' . $seed->outlook_id
2297
                        );
2298
2299
                        $fields = array(
2300
                            'outlook_id' => $seed->outlook_id
2301
                        );
2302
                        // Try to fetch a bean with this outlook_id
2303
                        $temp = BeanFactory::getBean($module_name);
2304
                        $temp = $temp->retrieve_by_string_fields($fields);
2305
2306
                        // If we fetched one, just copy the ID to the one we're syncing
2307
                        if (!empty($temp)) {
2308
                            $seed->id = $temp->id;
2309
                        } else {
2310
                            $GLOBALS['log']->debug(
2311
                                'Looking for ' . $module_name .
2312
                                ' with name/date_start/duration_hours/duration_minutes ' .
2313
                                $seed->name . '/' . $seed->date_start . '/' .
2314
                                $seed->duration_hours . '/' . $seed->duration_minutes
2315
                            );
2316
2317
                            // If we didn't, try to find the meeting by comparing the passed
2318
                            // Subject, start date and duration
2319
                            $fields = array(
2320
                                'name' => $seed->name,
2321
                                'date_start' => $seed->date_start,
2322
                                'duration_hours' => $seed->duration_hours,
2323
                                'duration_minutes' => $seed->duration_minutes
2324
                            );
2325
                            $temp = BeanFactory::getBean($module_name);
2326
                            $temp = $temp->retrieve_by_string_fields($fields);
2327
2328
                            if (!empty($temp)) {
2329
                                $seed->id = $temp->id;
2330
                            }
2331
                        }
2332
                        $GLOBALS['log']->debug(
2333
                            $module_name . ' found: ' . !empty($seed->id)
2334
                        );
2335
                    }
2336
                }
2337
				if (empty($seed->reminder_time)) {
2338
                    $seed->reminder_time = -1;
2339
                }
2340
				if($seed->reminder_time == -1){
2341
					$defaultRemindrTime = $current_user->getPreference('reminder_time');
2342
					if ($defaultRemindrTime != -1){
2343
                        $seed->reminder_checked = '1';
2344
                        $seed->reminder_time = $defaultRemindrTime;
2345
					}
2346
				}
2347
				$seed->save();
2348
				if ($seed->deleted == 1) {
2349
					$seed->mark_deleted($seed->id);
2350
				}
2351
				$ids[] = $seed->id;
2352
			}//fi
2353
		}
2354
		else
2355
		{
2356
			if( $seed->ACLAccess('Save') && ($seed->deleted != 1 || $seed->ACLAccess('Delete'))){
2357
				$seed->save();
2358
				$ids[] = $seed->id;
2359
			}
2360
		}
2361
2362
		// if somebody is calling set_entries_detail() and wants fields returned...
2363
		if ($select_fields !== FALSE) {
2364
			$ret_values[$count] = array();
2365
2366
			foreach ($select_fields as $select_field) {
0 ignored issues
show
Bug introduced by
The expression $select_fields of type boolean is not traversable.
Loading history...
2367
				if (isset($seed->$select_field)) {
2368
					$ret_values[$count][] = get_name_value($select_field, $seed->$select_field);
2369
				}
2370
			}
2371
		}
2372
	}
2373
2374
	// handle returns for set_entries_detail() and set_entries()
2375
	if ($select_fields !== FALSE) {
2376
		return array(
2377
			'name_value_lists' => $ret_values,
2378
			'error' => $error->get_soap_array()
2379
		);
2380
	}
2381
	else {
2382
		return array(
2383
			'ids' => $ids,
2384
			'error' => $error->get_soap_array()
2385
		);
2386
	}
2387
}
2388
2389