|
iTx Technologies offre gratuitement
|
||
[Vue sommaire] [Imprimer] [Vue textuelle]
1 <?php 2 if(!defined('sugarEntry') || !sugarEntry) die('Not A Valid Entry Point'); 3 /********************************************************************************* 4 * SugarCRM is a customer relationship management program developed by 5 * SugarCRM, Inc. Copyright (C) 2004 - 2009 SugarCRM Inc. 6 * 7 * This program is free software; you can redistribute it and/or modify it under 8 * the terms of the GNU General Public License version 3 as published by the 9 * Free Software Foundation with the addition of the following permission added 10 * to Section 15 as permitted in Section 7(a): FOR ANY PART OF THE COVERED WORK 11 * IN WHICH THE COPYRIGHT IS OWNED BY SUGARCRM, SUGARCRM DISCLAIMS THE WARRANTY 12 * OF NON INFRINGEMENT OF THIRD PARTY RIGHTS. 13 * 14 * This program is distributed in the hope that it will be useful, but WITHOUT 15 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 16 * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more 17 * details. 18 * 19 * You should have received a copy of the GNU General Public License along with 20 * this program; if not, see http://www.gnu.org/licenses or write to the Free 21 * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 22 * 02110-1301 USA. 23 * 24 * You can contact SugarCRM, Inc. headquarters at 10050 North Wolfe Road, 25 * SW2-130, Cupertino, CA 95014, USA. or at email address contact@sugarcrm.com. 26 * 27 * The interactive user interfaces in modified source and object code versions 28 * of this program must display Appropriate Legal Notices, as required under 29 * Section 5 of the GNU General Public License version 3. 30 * 31 * In accordance with Section 7(b) of the GNU General Public License version 3, 32 * these Appropriate Legal Notices must retain the display of the "Powered by 33 * SugarCRM" logo. If the display of the logo is not reasonably feasible for 34 * technical reasons, the Appropriate Legal Notices must display the words 35 * "Powered by SugarCRM". 36 ********************************************************************************/ 37 require_once ('soap/SoapHelperFunctions.php'); 38 require_once ('soap/SoapTypes.php'); 39 40 41 42 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 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((!empty($sugar_config['authenticationClass'])? $sugar_config['authenticationClass'] : 'SugarAuthenticate')); 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 if($authController->login($user_auth['user_name'], $password) && isset($_SESSION['authenticated_user_id'])){ 130 $success = true; 131 } // if 132 } // else if 133 134 if($success){ 135 session_start(); 136 global $current_user; 137 //$current_user = $user; 138 login_success(); 139 $current_user->loadPreferences(); 140 $_SESSION['is_valid_session']= true; 141 $_SESSION['ip_address'] = query_client_ip(); 142 $_SESSION['user_id'] = $current_user->id; 143 $_SESSION['type'] = 'user'; 144 $_SESSION['avail_modules']= get_user_module_list($current_user); 145 $_SESSION['authenticated_user_id'] = $current_user->id; 146 $_SESSION['unique_key'] = $sugar_config['unique_key']; 147 148 $current_user->call_custom_logic('after_login'); 149 return array('id'=>session_id(), 'error'=>$error); 150 } 151 $error->set_error('invalid_login'); 152 $GLOBALS['log']->fatal('SECURITY: User authentication for '. $user_auth['user_name']. ' failed'); 153 LogicHook::initialize(); 154 $GLOBALS['logic_hook']->call_custom_logic('Users', 'login_failed'); 155 return array('id'=>-1, 'error'=>$error); 156 157 } 158 159 //checks if the soap server and client are running on the same machine 160 $server->register( 161 'is_loopback', 162 array(), 163 array('return'=>'xsd:int'), 164 $NAMESPACE); 165 166 /** 167 * Check to see if the soap server and client are on the same machine. 168 * We don't allow a server to sync to itself. 169 * 170 * @return true -- if the SOAP server and client are on the same machine 171 * @return false -- if the SOAP server and client are not on the same machine. 172 */ 173 function is_loopback(){ 174 if(query_client_ip() == $_SERVER['SERVER_ADDR']) 175 return 1; 176 return 0; 177 } 178 179 /** 180 * Validate the provided session information is correct and current. Load the session. 181 * 182 * @param String $session_id -- The session ID that was returned by a call to login. 183 * @return true -- If the session is valid and loaded. 184 * @return false -- if the session is not valid. 185 */ 186 function validate_authenticated($session_id){ 187 if(!empty($session_id)){ 188 session_id($session_id); 189 session_start(); 190 191 if(!empty($_SESSION['is_valid_session']) && is_valid_ip_address('ip_address') && $_SESSION['type'] == 'user'){ 192 193 global $current_user; 194 195 $current_user = new User(); 196 $current_user->retrieve($_SESSION['user_id']); 197 login_success(); 198 return true; 199 } 200 201 session_destroy(); 202 } 203 LogicHook::initialize(); 204 $GLOBALS['log']->fatal('SECURITY: The session ID is invalid'); 205 $GLOBALS['logic_hook']->call_custom_logic('Users', 'login_failed'); 206 return false; 207 } 208 209 /** 210 * Use the same logic as in SugarAuthenticate to validate the ip address 211 * 212 * @param string $session_var 213 * @return bool - true if the ip address is valid, false otherwise. 214 */ 215 function is_valid_ip_address($session_var){ 216 global $sugar_config; 217 // grab client ip address 218 $clientIP = query_client_ip(); 219 $classCheck = 0; 220 // check to see if config entry is present, if not, verify client ip 221 if (!isset ($sugar_config['verify_client_ip']) || $sugar_config['verify_client_ip'] == true) { 222 // check to see if we've got a current ip address in $_SESSION 223 // and check to see if the session has been hijacked by a foreign ip 224 if (isset ($_SESSION[$session_var])) { 225 $session_parts = explode(".", $_SESSION[$session_var]); 226 $client_parts = explode(".", $clientIP); 227 if(count($session_parts) < 4) { 228 $classCheck = 0; 229 }else { 230 // match class C IP addresses 231 for ($i = 0; $i < 3; $i ++) { 232 if ($session_parts[$i] == $client_parts[$i]) { 233 $classCheck = 1; 234 continue; 235 } else { 236 $classCheck = 0; 237 break; 238 } 239 } 240 } 241 // we have a different IP address 242 if ($_SESSION[$session_var] != $clientIP && empty ($classCheck)) { 243 $GLOBALS['log']->fatal("IP Address mismatch: SESSION IP: {$_SESSION[$session_var]} CLIENT IP: {$clientIP}"); 244 return false; 245 } 246 } else { 247 return false; 248 } 249 } 250 return true; 251 } 252 253 $server->register( 254 'seamless_login', 255 array('session'=>'xsd:string'), 256 array('return'=>'xsd:int'), 257 $NAMESPACE); 258 259 /** 260 * Perform a seamless login. This is used internally during the sync process. 261 * 262 * @param String $session -- Session ID returned by a previous call to login. 263 * @return true -- if the session was authenticated 264 * @return false -- if the session could not be authenticated 265 */ 266 function seamless_login($session){ 267 if(!validate_authenticated($session)){ 268 return 0; 269 } 270 $_SESSION['seamless_login'] = true; 271 return 1; 272 } 273 274 $server->register( 275 'get_entry_list', 276 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'), 277 array('return'=>'tns:get_entry_list_result'), 278 $NAMESPACE); 279 280 /** 281 * Retrieve a list of beans. This is the primary method for getting list of SugarBeans from Sugar using the SOAP API. 282 * 283 * @param String $session -- Session ID returned by a previous call to login. 284 * @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).. 285 * @param String $query -- SQL where clause without the word 'where' 286 * @param String $order_by -- SQL order by clause without the phrase 'order by' 287 * @param String $offset -- The record offset to start from. 288 * @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. 289 * @param String $max_results -- The maximum number of records to return. The default is the sugar configuration value for 'list_max_entries_per_page' 290 * @param Number $deleted -- false if deleted records should not be include, true if deleted records should be included. 291 * @return Array 'result_count' -- The number of records returned 292 * '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. 293 * 'field_list' -- The vardef information on the selected fields. 294 * Array -- 'field'=> 'name' -- the name of the field 295 * 'type' -- the data type of the field 296 * 'label' -- the translation key for the label of the field 297 * 'required' -- Is the field required? 298 * 'options' -- Possible values for a drop down field 299 * 'entry_list' -- The records that were retrieved 300 * 'error' -- The SOAP error, if any 301 */ 302 function get_entry_list($session, $module_name, $query, $order_by,$offset, $select_fields, $max_results, $deleted ){ 303 global $beanList, $beanFiles; 304 $error = new SoapError(); 305 if(!validate_authenticated($session)){ 306 $error->set_error('invalid_login'); 307 return array('result_count'=>-1, 'entry_list'=>array(), 'error'=>$error->get_soap_array()); 308 } 309 $using_cp = false; 310 if($module_name == 'CampaignProspects'){ 311 $module_name = 'Prospects'; 312 $using_cp = true; 313 } 314 if(empty($beanList[$module_name])){ 315 $error->set_error('no_module'); 316 return array('result_count'=>-1, 'entry_list'=>array(), 'error'=>$error->get_soap_array()); 317 } 318 global $current_user; 319 if(!check_modules_access($current_user, $module_name, 'read')){ 320 $error->set_error('no_access'); 321 return array('result_count'=>-1, 'entry_list'=>array(), 'error'=>$error->get_soap_array()); 322 } 323 324 // If the maximum number of entries per page was specified, override the configuration value. 325 if($max_results > 0){ 326 global $sugar_config; 327 $sugar_config['list_max_entries_per_page'] = $max_results; 328 } 329 330 331 $class_name = $beanList[$module_name]; 332 require_once($beanFiles[$class_name]); 333 $seed = new $class_name(); 334 if(! ($seed->ACLAccess('Export') && $seed->ACLAccess('list'))) 335 { 336 $error->set_error('no_access'); 337 return array('result_count'=>-1, 'entry_list'=>array(), 'error'=>$error->get_soap_array()); 338 } 339 if($query == ''){ 340 $where = ''; 341 } 342 if($offset == '' || $offset == -1){ 343 $offset = 0; 344 } 345 if($using_cp){ 346 $response = $seed->retrieveTargetList($query, $select_fields, $offset,-1,-1,$deleted); 347 }else{ 348 $response = $seed->get_list($order_by, $query, $offset,-1,-1,$deleted,true); 349 } 350 $list = $response['list']; 351 352 353 $output_list = array(); 354 355 // retrieve the vardef information on the bean's fields. 356 $field_list = array(); 357 foreach($list as $value) 358 { 359 if(isset($value->emailAddress)){ 360 $value->emailAddress->handleLegacyRetrieve($value); 361 } 362 $value->fill_in_additional_detail_fields(); 363 $output_list[] = get_return_value($value, $module_name); 364 if(empty($field_list)){ 365 $field_list = get_field_list($value); 366 } 367 } 368 369 // Filter the search results to only include the requested fields. 370 $output_list = filter_return_list($output_list, $select_fields, $module_name); 371 372 // Filter the list of fields to only include information on the requested fields. 373 $field_list = filter_return_list($field_list,$select_fields, $module_name); 374 375 // Calculate the offset for the start of the next page 376 $next_offset = $offset + sizeof($output_list); 377 378 return array('result_count'=>sizeof($output_list), 'next_offset'=>$next_offset,'field_list'=>$field_list, 'entry_list'=>$output_list, 'error'=>$error->get_soap_array()); 379 } 380 381 $server->register( 382 'get_entry', 383 array('session'=>'xsd:string', 'module_name'=>'xsd:string', 'id'=>'xsd:string', 'select_fields'=>'tns:select_fields'), 384 array('return'=>'tns:get_entry_result'), 385 $NAMESPACE); 386 387 /** 388 * Retrieve a single SugarBean based on ID. 389 * 390 * @param String $session -- Session ID returned by a previous call to login. 391 * @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).. 392 * @param String $id -- The SugarBean's ID value. 393 * @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. 394 * @return unknown 395 */ 396 function get_entry($session, $module_name, $id,$select_fields ){ 397 return get_entries($session, $module_name, array($id), $select_fields); 398 } 399 400 $server->register( 401 'get_entries', 402 array('session'=>'xsd:string', 'module_name'=>'xsd:string', 'ids'=>'tns:select_fields', 'select_fields'=>'tns:select_fields'), 403 array('return'=>'tns:get_entry_result'), 404 $NAMESPACE); 405 406 /** 407 * Retrieve a list of SugarBean's based on provided IDs. 408 * 409 * @param String $session -- Session ID returned by a previous call to login. 410 * @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).. 411 * @param Array $ids -- An array of SugarBean IDs. 412 * @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. 413 * @return Array 'field_list' -- Var def information about the returned fields 414 * 'entry_list' -- The records that were retrieved 415 * 'error' -- The SOAP error, if any 416 */ 417 function get_entries($session, $module_name, $ids,$select_fields ){ 418 global $beanList, $beanFiles; 419 $error = new SoapError(); 420 $field_list = array(); 421 $output_list = array(); 422 if(!validate_authenticated($session)){ 423 $error->set_error('invalid_login'); 424 return array('field_list'=>$field_list, 'entry_list'=>array(), 'error'=>$error->get_soap_array()); 425 } 426 $using_cp = false; 427 if($module_name == 'CampaignProspects'){ 428 $module_name = 'Prospects'; 429 $using_cp = true; 430 } 431 if(empty($beanList[$module_name])){ 432 $error->set_error('no_module'); 433 return array('field_list'=>$field_list, 'entry_list'=>array(), 'error'=>$error->get_soap_array()); 434 } 435 global $current_user; 436 if(!check_modules_access($current_user, $module_name, 'read')){ 437 $error->set_error('no_access'); 438 return array('field_list'=>$field_list, 'entry_list'=>array(), 'error'=>$error->get_soap_array()); 439 } 440 441 $class_name = $beanList[$module_name]; 442 require_once($beanFiles[$class_name]); 443 444 //todo can modify in there to call bean->get_list($order_by, $where, 0, -1, -1, $deleted); 445 //that way we do not have to call retrieve for each bean 446 //perhaps also add a select_fields to this, so we only get the fields we need 447 //and not do a select * 448 foreach($ids as $id){ 449 $seed = new $class_name(); 450 451 if($using_cp){ 452 $seed = $seed->retrieveTarget($id); 453 }else{ 454 if ($seed->retrieve($id) == null) 455 $seed->deleted = 1; 456 } 457 458 if ($seed->deleted == 1) { 459 $list = array(); 460 $list[] = array('name'=>'warning', 'value'=>'Access to this object is denied since it has been deleted or does not exist'); 461 $list[] = array('name'=>'deleted', 'value'=>'1'); 462 $output_list[] = Array('id'=>$id, 463 'module_name'=> $module_name, 464 'name_value_list'=>$list, 465 ); 466 continue; 467 } 468 if(! $seed->ACLAccess('DetailView')){ 469 $error->set_error('no_access'); 470 return array('field_list'=>$field_list, 'entry_list'=>array(), 'error'=>$error->get_soap_array()); 471 } 472 473 474 475 476 477 478 479 $output_list[] = get_return_value($seed, $module_name); 480 481 482 483 484 if(empty($field_list)){ 485 $field_list = get_field_list($seed); 486 487 } 488 } 489 490 $output_list = filter_return_list($output_list, $select_fields, $module_name); 491 $field_list = filter_field_list($field_list,$select_fields, $module_name); 492 493 return array( 'field_list'=>$field_list, 'entry_list'=>$output_list, 'error'=>$error->get_soap_array()); 494 } 495 496 $server->register( 497 'set_entry', 498 array('session'=>'xsd:string', 'module_name'=>'xsd:string', 'name_value_list'=>'tns:name_value_list'), 499 array('return'=>'tns:set_entry_result'), 500 $NAMESPACE); 501 502 /** 503 * Update or create a single SugarBean. 504 * 505 * @param String $session -- Session ID returned by a previous call to login. 506 * @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).. 507 * @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. 508 * @return Array 'id' -- the ID of the bean that was written to (-1 on error) 509 * 'error' -- The SOAP error if any. 510 */ 511 function set_entry($session,$module_name, $name_value_list){ 512 global $beanList, $beanFiles; 513 514 $error = new SoapError(); 515 if(!validate_authenticated($session)){ 516 $error->set_error('invalid_login'); 517 return array('id'=>-1, 'error'=>$error->get_soap_array()); 518 } 519 if(empty($beanList[$module_name])){ 520 $error->set_error('no_module'); 521 return array('id'=>-1, 'error'=>$error->get_soap_array()); 522 } 523 global $current_user; 524 if(!check_modules_access($current_user, $module_name, 'write')){ 525 $error->set_error('no_access'); 526 return array('id'=>-1, 'error'=>$error->get_soap_array()); 527 } 528 529 $class_name = $beanList[$module_name]; 530 require_once($beanFiles[$class_name]); 531 $seed = new $class_name(); 532 533 foreach($name_value_list as $value){ 534 if($value['name'] == 'id'){ 535 $seed->retrieve($value['value']); 536 break; 537 } 538 } 539 foreach($name_value_list as $value){ 540 $GLOBALS['log']->debug($value['name']." : ".$value['value']); 541 $seed->$value['name'] = $value['value']; 542 } 543 if(! $seed->ACLAccess('Save') || ($seed->deleted == 1 && !$seed->ACLAccess('Delete'))) 544 { 545 $error->set_error('no_access'); 546 return array('id'=>-1, 'error'=>$error->get_soap_array()); 547 } 548 $seed->save(); 549 if($seed->deleted == 1){ 550 $seed->mark_deleted($seed->id); 551 } 552 return array('id'=>$seed->id, 'error'=>$error->get_soap_array()); 553 554 } 555 556 $server->register( 557 'set_entries', 558 array('session'=>'xsd:string', 'module_name'=>'xsd:string', 'name_value_lists'=>'tns:name_value_lists'), 559 array('return'=>'tns:set_entries_result'), 560 $NAMESPACE); 561 562 /** 563 * Update or create a list of SugarBeans 564 * 565 * @param String $session -- Session ID returned by a previous call to login. 566 * @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).. 567 * @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. 568 * @return Array 'ids' -- Array of the IDs of the beans that was written to (-1 on error) 569 * 'error' -- The SOAP error if any. 570 */ 571 function set_entries($session,$module_name, $name_value_lists){ 572 $error = new SoapError(); 573 574 if(!validate_authenticated($session)){ 575 $error->set_error('invalid_login'); 576 577 return array( 578 'ids' => array(), 579 'error' => $error->get_soap_array() 580 ); 581 } 582 583 return handle_set_entries($module_name, $name_value_lists, FALSE); 584 } 585 586 /* 587 NOTE SPECIFIC CODE 588 */ 589 $server->register( 590 'set_note_attachment', 591 array('session'=>'xsd:string','note'=>'tns:note_attachment'), 592 array('return'=>'tns:set_entry_result'), 593 $NAMESPACE); 594 595 /** 596 * Add or replace the attachment on a Note. 597 * 598 * @param String $session -- Session ID returned by a previous call to login. 599 * @param Binary $note -- The flie contents of the attachment. 600 * @return Array 'id' -- The ID of the new note or -1 on error 601 * 'error' -- The SOAP error if any. 602 */ 603 function set_note_attachment($session,$note) 604 { 605 606 $error = new SoapError(); 607 if(!validate_authenticated($session)){ 608 $error->set_error('invalid_login'); 609 return array('id'=>-1, 'error'=>$error->get_soap_array()); 610 } 611 612 require_once ('modules/Notes/NoteSoap.php'); 613 $ns = new NoteSoap(); 614 return array('id'=>$ns->saveFile($note), 'error'=>$error->get_soap_array()); 615 616 } 617 618 $server->register( 619 'get_note_attachment', 620 array('session'=>'xsd:string', 'id'=>'xsd:string'), 621 array('return'=>'tns:return_note_attachment'), 622 $NAMESPACE); 623 624 /** 625 * Retrieve an attachment from a note 626 * @param String $session -- Session ID returned by a previous call to login. 627 * @param Binary $note -- The flie contents of the attachment. 628 * @return Array 'id' -- The ID of the new note or -1 on error 629 * 'error' -- The SOAP error if any. 630 * 631 * @param String $session -- Session ID returned by a previous call to login. 632 * @param String $id -- The ID of the appropriate Note. 633 * @return Array 'note_attachment' -- Array String 'id' -- The ID of the Note containing the attachment 634 * String 'filename' -- The file name of the attachment 635 * Binary 'file' -- The binary contents of the file. 636 * 'error' -- The SOAP error if any. 637 */ 638 function get_note_attachment($session,$id) 639 { 640 $error = new SoapError(); 641 if(!validate_authenticated($session)){ 642 $error->set_error('invalid_login'); 643 return array('result_count'=>-1, 'entry_list'=>array(), 'error'=>$error->get_soap_array()); 644 } 645 646 $note = new Note(); 647 648 $note->retrieve($id); 649 if(!$note->ACLAccess('DetailView')){ 650 $error->set_error('no_access'); 651 return array('result_count'=>-1, 'entry_list'=>array(), 'error'=>$error->get_soap_array()); 652 } 653 require_once ('modules/Notes/NoteSoap.php'); 654 $ns = new NoteSoap(); 655 if(!isset($note->filename)){ 656 $note->filename = ''; 657 } 658 $file= $ns->retrieveFile($id,$note->filename); 659 if($file == -1){ 660 $error->set_error('no_file'); 661 $file = ''; 662 } 663 664 return array('note_attachment'=>array('id'=>$id, 'filename'=>$note->filename, 'file'=>$file), 'error'=>$error->get_soap_array()); 665 666 } 667 $server->register( 668 'relate_note_to_module', 669 array('session'=>'xsd:string', 'note_id'=>'xsd:string', 'module_name'=>'xsd:string', 'module_id'=>'xsd:string'), 670 array('return'=>'tns:error_value'), 671 $NAMESPACE); 672 673 /** 674 * Attach a note to another bean. Once you have created a note to store an 675 * attachment, the note needs to be related to the bean. 676 * 677 * @param String $session -- Session ID returned by a previous call to login. 678 * @param String $note_id -- The ID of the note that you want to associate with a bean 679 * @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).. 680 * @param String $module_id -- The ID of the bean that you want to associate the note with 681 * @return no error for success, error for failure 682 */ 683 function relate_note_to_module($session,$note_id, $module_name, $module_id){ 684 global $beanList, $beanFiles; 685 $error = new SoapError(); 686 if(!validate_authenticated($session)){ 687 $error->set_error('invalid_login'); 688 return $error->get_soap_array(); 689 } 690 if(empty($beanList[$module_name])){ 691 $error->set_error('no_module'); 692 return $error->get_soap_array(); 693 } 694 global $current_user; 695 if(!check_modules_access($current_user, $module_name, 'read')){ 696 $error->set_error('no_access'); 697 return $error->get_soap_array(); 698 } 699 $class_name = $beanList['Notes']; 700 require_once($beanFiles[$class_name]); 701 $seed = new $class_name(); 702 $seed->retrieve($note_id); 703 if(!$seed->ACLAccess('ListView')){ 704 $error->set_error('no_access'); 705 return array('result_count'=>-1, 'entry_list'=>array(), 'error'=>$error->get_soap_array()); 706 } 707 708 if($module_name != 'Contacts'){ 709 $seed->parent_type=$module_name; 710 $seed->parent_id = $module_id; 711 712 }else{ 713 714 $seed->contact_id=$module_id; 715 716 } 717 718 $seed->save(); 719 720 return $error->get_soap_array(); 721 722 } 723 $server->register( 724 'get_related_notes', 725 array('session'=>'xsd:string', 'module_name'=>'xsd:string', 'module_id'=>'xsd:string', 'select_fields'=>'tns:select_fields'), 726 array('return'=>'tns:get_entry_result'), 727 $NAMESPACE); 728 729 /** 730 * Retrieve the collection of notes that are related to a bean. 731 * 732 * @param String $session -- Session ID returned by a previous call to login. 733 * @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).. 734 * @param String $module_id -- The ID of the bean that you want to associate the note with 735 * @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. 736 * @return Array 'result_count' -- The number of records returned (-1 on error) 737 * '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. 738 * 'field_list' -- The vardef information on the selected fields. 739 * 'entry_list' -- The records that were retrieved 740 * 'error' -- The SOAP error, if any 741 */ 742 function get_related_notes($session,$module_name, $module_id, $select_fields){ 743 global $beanList, $beanFiles; 744 $error = new SoapError(); 745 if(!validate_authenticated($session)){ 746 $error->set_error('invalid_login'); 747 return array('result_count'=>-1, 'entry_list'=>array(), 'error'=>$error->get_soap_array()); 748 } 749 if(empty($beanList[$module_name])){ 750 $error->set_error('no_module'); 751 return array('result_count'=>-1, 'entry_list'=>array(), 'error'=>$error->get_soap_array()); 752 } 753 global $current_user; 754 if(!check_modules_access($current_user, $module_name, 'read')){ 755 $error->set_error('no_access'); 756 return array('result_count'=>-1, 'entry_list'=>array(), 'error'=>$error->get_soap_array()); 757 } 758 759 $class_name = $beanList[$module_name]; 760 require_once($beanFiles[$class_name]); 761 $seed = new $class_name(); 762 $seed->retrieve($module_id); 763 if(!$seed->ACLAccess('DetailView')){ 764 $error->set_error('no_access'); 765 return array('result_count'=>-1, 'entry_list'=>array(), 'error'=>$error->get_soap_array()); 766 } 767 $list = $seed->get_linked_beans('notes','Note', array(), 0, -1, 0); 768 769 $output_list = Array(); 770 $field_list = Array(); 771 foreach($list as $value) 772 { 773 $output_list[] = get_return_value($value, 'Notes'); 774 if(empty($field_list)) 775 { 776 $field_list = get_field_list($value); 777 } 778 } 779 $output_list = filter_return_list($output_list, $select_fields, $module_name); 780 $field_list = filter_field_list($field_list,$select_fields, $module_name); 781 782 return array('result_count'=>sizeof($output_list), 'next_offset'=>0,'field_list'=>$field_list, 'entry_list'=>$output_list, 'error'=>$error->get_soap_array()); 783 } 784 785 $server->register( 786 'logout', 787 array('session'=>'xsd:string'), 788 array('return'=>'tns:error_value'), 789 $NAMESPACE); 790 791 /** 792 * Log out of the session. This will destroy the session and prevent other's from using it. 793 * 794 * @param String $session -- Session ID returned by a previous call to login. 795 * @return Empty error on success, Error on failure 796 */ 797 function logout($session){ 798 global $current_user; 799 800 $error = new SoapError(); 801 LogicHook::initialize(); 802 if(validate_authenticated($session)){ 803 $current_user->call_custom_logic('before_logout'); 804 session_destroy(); 805 $GLOBALS['logic_hook']->call_custom_logic('Users', 'after_logout'); 806 return $error->get_soap_array(); 807 } 808 $error->set_error('no_session'); 809 $GLOBALS['logic_hook']->call_custom_logic('Users', 'after_logout'); 810 return $error->get_soap_array(); 811 } 812 813 $server->register( 814 'get_module_fields', 815 array('session'=>'xsd:string', 'module_name'=>'xsd:string'), 816 array('return'=>'tns:module_fields'), 817 $NAMESPACE); 818 819 /** 820 * Retrieve vardef information on the fields of the specified bean. 821 * 822 * @param String $session -- Session ID returned by a previous call to login. 823 * @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).. 824 * @return Array 'module_fields' -- The vardef information on the selected fields. 825 * 'error' -- The SOAP error, if any 826 */ 827 function get_module_fields($session, $module_name){ 828 global $beanList, $beanFiles; 829 $error = new SoapError(); 830 $module_fields = array(); 831 if(! validate_authenticated($session)){ 832 $error->set_error('invalid_session'); 833 return array('module_fields'=>$module_fields, 'error'=>$error->get_soap_array()); 834 } 835 if(empty($beanList[$module_name])){ 836 $error->set_error('no_module'); 837 return array('module_fields'=>$module_fields, 'error'=>$error->get_soap_array()); 838 } 839 global $current_user; 840 if(!check_modules_access($current_user, $module_name, 'read')){ 841 $error->set_error('no_access'); 842 return array('module_fields'=>$module_fields, 'error'=>$error->get_soap_array()); 843 } 844 $class_name = $beanList[$module_name]; 845 require_once($beanFiles[$class_name]); 846 $seed = new $class_name(); 847 if($seed->ACLAccess('ListView', true) || $seed->ACLAccess('DetailView', true) || $seed->ACLAccess('EditView', true) ) 848 { 849 return get_return_module_fields($seed, $module_name, $error); 850 } 851 else 852 { 853 $error->set_error('no_access'); 854 return array('module_fields'=>$module_fields, 'error'=>$error->get_soap_array()); 855 } 856 } 857 858 $server->register( 859 'get_available_modules', 860 array('session'=>'xsd:string'), 861 array('return'=>'tns:module_list'), 862 $NAMESPACE); 863 864 /** 865 * Retrieve the list of available modules on the system available to the currently logged in user. 866 * 867 * @param String $session -- Session ID returned by a previous call to login. 868 * @return Array 'modules' -- An array of module names 869 * 'error' -- The SOAP error, if any 870 */ 871 function get_available_modules($session){ 872 $error = new SoapError(); 873 $modules = array(); 874 if(! validate_authenticated($session)){ 875 $error->set_error('invalid_session'); 876 return array('modules'=> $modules, 'error'=>$error->get_soap_array()); 877 } 878 $modules = array_keys($_SESSION['avail_modules']); 879 880 return array('modules'=> $modules, 'error'=>$error->get_soap_array()); 881 } 882 883 884 $server->register( 885 'update_portal_user', 886 array('session'=>'xsd:string', 'portal_name'=>'xsd:string', 'name_value_list'=>'tns:name_value_list'), 887 array('return'=>'tns:error_value'), 888 $NAMESPACE); 889 890 /** 891 * Update the properties of a contact that is portal user. Add the portal user name to the user's properties. 892 * 893 * @param String $session -- Session ID returned by a previous call to login. 894 * @param String $portal_name -- The portal user_name of the contact 895 * @param Array $name_value_list -- collection of 'name'=>'value' pairs for finding the contact 896 * @return Empty error on success, Error on failure 897 */ 898 function update_portal_user($session,$portal_name, $name_value_list){ 899 global $beanList, $beanFiles; 900 $error = new SoapError(); 901 if(! validate_authenticated($session)){ 902 $error->set_error('invalid_session'); 903 return $error->get_soap_array(); 904 } 905 $contact = new Contact(); 906 907 $searchBy = array('deleted'=>0); 908 foreach($name_value_list as $name_value){ 909 $searchBy[$name_value['name']] = $name_value['value']; 910 } 911 if($contact->retrieve_by_string_fields($searchBy) != null){ 912 if(!$contact->duplicates_found){ 913 $contact->portal_name = $portal_name; 914 $contact->portal_active = 1; 915 if($contact->ACLAccess('Save')){ 916 $contact->save(); 917 }else{ 918 $error->set_error('no_access'); 919 } 920 return $error->get_soap_array(); 921 } 922 $error->set_error('duplicates'); 923 return $error->get_soap_array(); 924 } 925 $error->set_error('no_records'); 926 return $error->get_soap_array(); 927 } 928 929 $server->register( 930 'get_user_id', 931 array('session'=>'xsd:string'), 932 array('return'=>'xsd:string'), 933 $NAMESPACE); 934 935 /** 936 * Return the user_id of the user that is logged into the current session. 937 * 938 * @param String $session -- Session ID returned by a previous call to login. 939 * @return String -- the User ID of the current session 940 * -1 on error. 941 */ 942 function get_user_id($session){ 943 if(validate_authenticated($session)){ 944 global $current_user; 945 return $current_user->id; 946 947 }else{ 948 return '-1'; 949 } 950 } 951 952 $server->register( 953 'get_user_team_id', 954 array('session'=>'xsd:string'), 955 array('return'=>'xsd:string'), 956 $NAMESPACE); 957 958 /** 959 * Return the ID of the default team for the user that is logged into the current session. 960 * 961 * @param String $session -- Session ID returned by a previous call to login. 962 * @return String -- the Team ID of the current user's default team 963 * 1 for Community Edition 964 * -1 on error. 965 */ 966 function get_user_team_id($session){ 967 if(validate_authenticated($session)) 968 { 969 970 971 972 973 974 return 1; 975 976 977 978 }else{ 979 return '-1'; 980 } 981 } 982 983 $server->register( 984 'get_server_time', 985 array(), 986 array('return'=>'xsd:string'), 987 $NAMESPACE); 988 989 /** 990 * 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. 991 * 992 * @return String -- The current date/time 'Y-m-d H:i:s' 993 */ 994 function get_server_time(){ 995 return date('Y-m-d H:i:s'); 996 } 997 998 $server->register( 999 'get_gmt_time', 1000 array(), 1001 array('return'=>'xsd:string'), 1002 $NAMESPACE); 1003 1004 /** 1005 * Return the current time on the server in the format 'Y-m-d H:i:s'. This time is in GMT. 1006 * 1007 * @return String -- The current date/time 'Y-m-d H:i:s' 1008 */ 1009 function get_gmt_time(){ 1010 return gmdate('Y-m-d H:i:s'); 1011 } 1012 1013 $server->register( 1014 'get_sugar_flavor', 1015 array(), 1016 array('return'=>'xsd:string'), 1017 $NAMESPACE); 1018 1019 /** 1020 * Retrieve the specific flavor of sugar. 1021 * 1022 * @return String 'CE' -- For Community Edition 1023 * 'PRO' -- For Professional 1024 * 'ENT' -- For Enterprise 1025 */ 1026 function get_sugar_flavor(){ 1027 global $sugar_flavor; 1028 1029 return $sugar_flavor; 1030 } 1031 1032 1033 $server->register( 1034 'get_server_version', 1035 array(), 1036 array('return'=>'xsd:string'), 1037 $NAMESPACE); 1038 1039 /** 1040 * Retrieve the version number of Sugar that the server is running. 1041 * 1042 * @return String -- The current sugar version number. 1043 * '1.0' on error. 1044 */ 1045 function get_server_version(){ 1046 1047 $admin = new Administration(); 1048 $admin->retrieveSettings('info'); 1049 if(isset($admin->settings['info_sugar_version'])){ 1050 return $admin->settings['info_sugar_version']; 1051 }else{ 1052 return '1.0'; 1053 } 1054 1055 } 1056 1057 $server->register( 1058 'get_relationships', 1059 array('session'=>'xsd:string', 'module_name'=>'xsd:string', 'module_id'=>'xsd:string', 'related_module'=>'xsd:string', 'related_module_query'=>'xsd:string', 'deleted'=>'xsd:int'), 1060 array('return'=>'tns:get_relationships_result'), 1061 $NAMESPACE); 1062 1063 /** 1064 * Retrieve a collection of beans tha are related to the specified bean. 1065 * As of 4.5.1c, all combinations of related modules are supported 1066 * 1067 * @param String $session -- Session ID returned by a previous call to login. 1068 * @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).. 1069 * @param String $module_id -- The ID of the bean in the specified module 1070 * @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).. 1071 * @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. 1072 * @param Number $deleted -- false if deleted records should not be include, true if deleted records should be included. 1073 * @return unknown 1074 */ 1075 function get_relationships($session, $module_name, $module_id, $related_module, $related_module_query, $deleted){ 1076 $error = new SoapError(); 1077 $ids = array(); 1078 if(!validate_authenticated($session)){ 1079 $error->set_error('invalid_login'); 1080 return array('ids'=>$ids,'error'=> $error->get_soap_array()); 1081 } 1082 global $beanList, $beanFiles; 1083 $error = new SoapError(); 1084 1085 if(empty($beanList[$module_name]) || empty($beanList[$related_module])){ 1086 $error->set_error('no_module'); 1087 return array('ids'=>$ids, 'error'=>$error->get_soap_array()); 1088 } 1089 $class_name = $beanList[$module_name]; 1090 require_once($beanFiles[$class_name]); 1091 $mod = new $class_name(); 1092 $mod->retrieve($module_id); 1093 if(!$mod->ACLAccess('DetailView')){ 1094 $error->set_error('no_access'); 1095 return array('ids'=>$ids, 'error'=>$error->get_soap_array()); 1096 } 1097 1098 $id_list = get_linked_records($related_module, $module_name, $module_id); 1099 1100 if ($id_list === FALSE) { 1101 $error->set_error('no_relationship_support'); 1102 return array('ids'=>$ids, 'error'=>$error->get_soap_array()); 1103 } 1104 elseif (count($id_list) == 0) { 1105 return array('ids'=>$ids, 'error'=>$error->get_soap_array()); 1106 } 1107 1108 $list = array(); 1109 1110 $id_list_quoted = array_map("add_squotes", $id_list); 1111 $in = implode(", ", $id_list_quoted); 1112 1113 $related_class_name = $beanList[$related_module]; 1114 require_once($beanFiles[$related_class_name]); 1115 $related_mod = new $related_class_name(); 1116 1117 $sql = "SELECT {$related_mod->table_name}.id FROM {$related_mod->table_name} "; 1118 1119 1120 1121 1122 1123 $sql .= " WHERE {$related_mod->table_name}.id IN ({$in}) "; 1124 1125 if (!empty($related_module_query)) { 1126 $sql .= " AND ( {$related_module_query} )"; 1127 } 1128 1129 $result = $related_mod->db->query($sql); 1130 while ($row = $related_mod->db->fetchByAssoc($result)) { 1131 $list[] = $row['id']; 1132 } 1133 1134 $return_list = array(); 1135 1136 foreach($list as $id) { 1137 $related_class_name = $beanList[$related_module]; 1138 $related_mod = new $related_class_name(); 1139 $related_mod->retrieve($id); 1140 1141 $return_list[] = array( 1142 'id' => $id, 1143 'date_modified' => $related_mod->date_modified, 1144 'deleted' => $related_mod->deleted 1145 ); 1146 } 1147 1148 return array('ids' => $return_list, 'error' => $error->get_soap_array()); 1149 } 1150 1151 1152 $server->register( 1153 'set_relationship', 1154 array('session'=>'xsd:string','set_relationship_value'=>'tns:set_relationship_value'), 1155 array('return'=>'tns:error_value'), 1156 $NAMESPACE); 1157 1158 /** 1159 * Set a single relationship between two beans. The items are related by module name and id. 1160 * 1161 * @param String $session -- Session ID returned by a previous call to login. 1162 * @param Array $set_relationship_value -- 1163 * '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).. 1164 * 'module1_id' -- The ID of the bean in the specified module 1165 * '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).. 1166 * 'module2_id' -- The ID of the bean in the specified module 1167 * @return Empty error on success, Error on failure 1168 */ 1169 function set_relationship($session, $set_relationship_value){ 1170 $error = new SoapError(); 1171 if(!validate_authenticated($session)){ 1172 $error->set_error('invalid_login'); 1173 return $error->get_soap_array(); 1174 } 1175 return handle_set_relationship($set_relationship_value); 1176 } 1177 1178 $server->register( 1179 'set_relationships', 1180 array('session'=>'xsd:string','set_relationship_list'=>'tns:set_relationship_list'), 1181 array('return'=>'tns:set_relationship_list_result'), 1182 $NAMESPACE); 1183 1184 /** 1185 * Setup several relationships between pairs of beans. The items are related by module name and id. 1186 * 1187 * @param String $session -- Session ID returned by a previous call to login. 1188 * @param Array $set_relationship_list -- One for each relationship to setup. Each entry is itself an array. 1189 * '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).. 1190 * 'module1_id' -- The ID of the bean in the specified module 1191 * '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).. 1192 * 'module2_id' -- The ID of the bean in the specified module 1193 * @return Empty error on success, Error on failure 1194 */ 1195 function set_relationships($session, $set_relationship_list){ 1196 $error = new SoapError(); 1197 if(!validate_authenticated($session)){ 1198 $error->set_error('invalid_login'); 1199 return -1; 1200 } 1201 $count = 0; 1202 $failed = 0; 1203 foreach($set_relationship_list as $set_relationship_value){ 1204 $reter = handle_set_relationship($set_relationship_value); 1205 if($reter['number'] == 0){ 1206 $count++; 1207 }else{ 1208 $failed++; 1209 } 1210 } 1211 return array('created'=>$count , 'failed'=>$failed, 'error'=>$error); 1212 } 1213 1214 1215 1216 //INTERNAL FUNCTION NOT EXPOSED THROUGH SOAP 1217 /** 1218 * (Internal) Create a relationship between two beans. 1219 * 1220 * @param Array $set_relationship_value -- 1221 * '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).. 1222 * 'module1_id' -- The ID of the bean in the specified module 1223 * '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).. 1224 * 'module2_id' -- The ID of the bean in the specified module 1225 * @return Empty error on success, Error on failure 1226 */ 1227 function handle_set_relationship($set_relationship_value) 1228 { 1229 global $beanList, $beanFiles; 1230 $error = new SoapError(); 1231 1232 $module1 = $set_relationship_value['module1']; 1233 $module1_id = $set_relationship_value['module1_id']; 1234 $module2 = $set_relationship_value['module2']; 1235 $module2_id = $set_relationship_value['module2_id']; 1236 1237 if(empty($beanList[$module1]) || empty($beanList[$module2]) ) 1238 { 1239 $error->set_error('no_module'); 1240 return $error->get_soap_array(); 1241 } 1242 $class_name = $beanList[$module1]; 1243 require_once($beanFiles[$class_name]); 1244 $mod = new $class_name(); 1245 $mod->retrieve($module1_id); 1246 if(!$mod->ACLAccess('DetailView')){ 1247 $error->set_error('no_access'); 1248 return $error->get_soap_array(); 1249 } 1250 if($module1 == "Contacts" && $module2 == "Users"){ 1251 $key = 'contacts_users_id'; 1252 } 1253 else{ 1254 $key = array_search(strtolower($module2),$mod->relationship_fields); 1255 if (!$key) { 1256 1257 $key = Relationship::retrieve_by_modules($module1, $module2, $GLOBALS['db']); 1258 if (!empty($key)) { 1259 $mod->load_relationship($key); 1260 $mod->$key->add($module2_id); 1261 return $error->get_soap_array(); 1262 } // if 1263 } // if 1264 } 1265 1266 if(!$key) 1267 { 1268 $error->set_error('no_module'); 1269 return $error->get_soap_array(); 1270 } 1271 1272 if(($module1 == 'Meetings' || $module1 == 'Calls') && ($module2 == 'Contacts' || $module2 == 'Users')){ 1273 $key = strtolower($module2); 1274 $mod->load_relationship($key); 1275 $mod->$key->add($module2_id); 1276 }else{ 1277 $mod->$key = $module2_id; 1278 $mod->save_relationship_changes(false); 1279 } 1280 1281 return $error->get_soap_array(); 1282 } 1283 1284 1285 $server->register( 1286 'set_document_revision', 1287 array('session'=>'xsd:string','note'=>'tns:document_revision'), 1288 array('return'=>'tns:set_entry_result'), 1289 $NAMESPACE); 1290 1291 /** 1292 * Enter description here... 1293 * 1294 * @param String $session -- Session ID returned by a previous call to login. 1295 * @param unknown_type $document_revision 1296 * @return unknown 1297 */ 1298 function set_document_revision($session,$document_revision) 1299 { 1300 1301 $error = new SoapError(); 1302 if(!validate_authenticated($session)){ 1303 $error->set_error('invalid_login'); 1304 return array('id'=>-1, 'error'=>$error->get_soap_array()); 1305 } 1306 1307 require_once ('modules/Documents/DocumentSoap.php'); 1308 $dr = new DocumentSoap(); 1309 return array('id'=>$dr->saveFile($document_revision), 'error'=>$error->get_soap_array()); 1310 1311 } 1312 1313 $server->register( 1314 'search_by_module', 1315 array('user_name'=>'xsd:string','password'=>'xsd:string','search_string'=>'xsd:string', 'modules'=>'tns:select_fields', 'offset'=>'xsd:int', 'max_results'=>'xsd:int'), 1316 array('return'=>'tns:get_entry_list_result'), 1317 $NAMESPACE); 1318 1319 /** 1320 * Given a list of modules to search and a search string, return the id, module_name, along with the fields 1321 * as specified in the $query_array 1322 * 1323 * @param string $user_name - username of the Sugar User 1324 * @param string $password - password of the Sugar User 1325 * @param string $search_string - string to search 1326 * @param string[] $modules - array of modules to query 1327 * @param int $offset - a specified offset in the query 1328 * @param int $max_results - max number of records to return 1329 * @return get_entry_list_result - id, module_name, and list of fields from each record 1330 */ 1331 function search_by_module($user_name, $password, $search_string, $modules, $offset, $max_results){ 1332 global $beanList, $beanFiles; 1333 1334 $error = new SoapError(); 1335 if(!validate_user($user_name, $password)){ 1336 $error->set_error('invalid_login'); 1337 return array('result_count'=>-1, 'entry_list'=>array(), 'error'=>$error->get_soap_array()); 1338 } 1339 global $current_user; 1340 if($max_results > 0){ 1341 global $sugar_config; 1342 $sugar_config['list_max_entries_per_page'] = $max_results; 1343 } 1344 // MRF - BUG:19552 - added a join for accounts' emails below 1345 $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"), 1346 'Bugs'=>array('where'=>array('Bugs' => array(0 => "bugs.name like '{0}%'", 1 => "bugs.bug_number = {0}")),'fields'=>"bugs.id, bugs.name, bugs.bug_number"), 1347 'Cases'=>array('where'=>array('Cases' => array(0 => "cases.name like '{0}%'", 1 => "cases.case_number = {0}")),'fields'=>"cases.id, cases.name, cases.case_number"), 1348 '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"), 1349 '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"), 1350 'Opportunities'=>array('where'=>array('Opportunities' => array(0 => "opportunities.name like '{0}%'")), 'fields'=>"opportunities.id, opportunities.name"), 1351 'Project'=>array('where'=>array('Project' => array(0 => "project.name like '{0}%'")), 'fields'=>"project.id, project.name"), 1352 'ProjectTask'=>array('where'=>array('ProjectTask' => array(0 => "project.id = '{0}'")), 'fields'=>"project_task.id, project_task.name"), 1353 'Users'=>array('where'=>array('EmailAddresses' => array(0 => "ea.email_address like '{0}%'")),'fields'=>"users.id, users.user_name, users.first_name, ea.email_address"), 1354 ); 1355 1356 if(!empty($search_string) && isset($search_string)){ 1357 foreach($modules as $module_name){ 1358 $class_name = $beanList[$module_name]; 1359 require_once($beanFiles[$class_name]); 1360 $seed = new $class_name(); 1361 if(empty($beanList[$module_name])){ 1362 continue; 1363 } 1364 if(!check_modules_access($current_user, $module_name, 'read')){ 1365 continue; 1366 } 1367 if(! $seed->ACLAccess('ListView')) 1368 { 1369 continue; 1370 } 1371 1372 if(isset($query_array[$module_name])){ 1373 $query = ''; 1374 $tmpQuery = ''; 1375 //split here to do while loop 1376 foreach($query_array[$module_name]['where'] as $key => $value){ 1377 foreach($value as $where_clause){ 1378 $addQuery = true; 1379 if(!empty($query)) 1380 $tmpQuery = ' UNION '; 1381 $tmpQuery .= "SELECT ".$query_array[$module_name]['fields']." FROM $seed->table_name "; 1382 // We need to confirm that the user is a member of the team of the item. 1383 1384 1385 1386 1387 1388 1389 if($module_name == 'ProjectTask'){ 1390 $tmpQuery .= "INNER JOIN project ON $seed->table_name.project_id = project.id "; 1391 } 1392 if(isset($seed->emailAddress) && $key == 'EmailAddresses'){ 1393 $tmpQuery .= " INNER JOIN email_addr_bean_rel eabl ON eabl.bean_id = $seed->table_name.id and eabl.deleted=0"; 1394 $tmpQuery .= " INNER JOIN email_addresses ea ON (ea.id = eabl.email_address_id) "; 1395 } 1396 $where = "WHERE ("; 1397 $search_terms = explode(", ", $search_string); 1398 $termCount = count($search_terms); 1399 $count = 1; 1400 if($key != 'EmailAddresses'){ 1401 foreach($search_terms as $term){ 1402 if(!strpos($where_clause, 'number')){ 1403 $where .= string_format($where_clause,array($term)); 1404 }elseif(is_numeric($term)){ 1405 $where .= string_format($where_clause,array($term)); 1406 }else{ 1407 $addQuery = false; 1408 } 1409 if($count < $termCount){ 1410 $where .= " OR "; 1411 } 1412 $count++; 1413 } 1414 }else{ 1415 $where .= 'ea.email_address IN ('; 1416 foreach($search_terms as $term){ 1417 $where .= "'".$GLOBALS['db']->quote($term)."'"; 1418 if($count < $termCount){ 1419 $where .= ","; 1420 } 1421 $count++; 1422 } 1423 $where .= ')'; 1424 } 1425 $tmpQuery .= $where; 1426 $tmpQuery .= ") AND $seed->table_name.deleted = 0"; 1427 if($addQuery) 1428 $query .= $tmpQuery; 1429 } 1430 } 1431 //grab the items from the db 1432 $result = $seed->db->query($query, $offset, $max_results); 1433 1434 $list = Array(); 1435 if(empty($rows_found)){ 1436 $rows_found = $seed->db->getRowCount($result); 1437 }//fi 1438 1439 $row_offset = 0; 1440 1441 while(($row = $seed->db->fetchByAssoc($result)) != null){ 1442 $list = array(); 1443 $fields = explode(", ", $query_array[$module_name]['fields']); 1444 foreach($fields as $field){ 1445 $field_names = explode(".", $field); 1446 $list[$field] = array('name'=>$field_names[1], 'value'=>$row[$field_names[1]]); 1447 } 1448 1449 $output_list[] = array('id'=>$row['id'], 1450 'module_name'=>$module_name, 1451 'name_value_list'=>$list); 1452 if(empty($field_list)){ 1453 $field_list = get_field_list($row); 1454 } 1455 }//end while 1456 } 1457 }//end foreach 1458 } 1459 1460 $next_offset = $offset + sizeof($output_list); 1461 1462 return array('result_count'=>sizeof($output_list), 'next_offset'=>$next_offset,'field_list'=>$field_list, 'entry_list'=>$output_list, 'error'=>$error->get_soap_array()); 1463 1464 }//end function 1465 1466 1467 $server->register( 1468 'get_mailmerge_document', 1469 array('session'=>'xsd:string','file_name'=>'xsd:string', 'fields' => 'tns:select_fields'), 1470 array('return'=>'tns:get_sync_result_encoded'), 1471 $NAMESPACE); 1472 1473 /** 1474 * Enter description here... 1475 * 1476 * @param String $session -- Session ID returned by a previous call to login. 1477 * @param unknown_type $file_name 1478 * @param unknown_type $fields 1479 * @return unknown 1480 */ 1481 function get_mailmerge_document($session, $file_name, $fields) 1482 { 1483 global $beanList, $beanFiles, $app_list_strings; 1484 $error = new SoapError(); 1485 if(!validate_authenticated($session)) 1486 { 1487 $error->set_error('invalid_login'); 1488 return array('result'=>'', 'error'=>$error->get_soap_array()); 1489 } 1490 $html = ''; 1491 $file_name = $GLOBALS['sugar_config']['cache_dir'].'MergedDocuments/'.$file_name; 1492 1493 $master_fields = array(); 1494 $related_fields = array(); 1495 1496 if(file_exists($file_name)) 1497 { 1498 require_once($file_name); 1499 1500 $class1 = $merge_array['master_module']; 1501 $beanL = $beanList[$class1]; 1502 $bean1 = $beanFiles[$beanL]; 1503 require_once($bean1); 1504 $seed1 = new $beanL(); 1505 1506 if(isset($merge_array['related_module'])) 1507 { 1508 $class2 = $merge_array['related_module']; 1509 $beanR = $beanList[$class2]; 1510 $bean2 = $beanFiles[$beanR]; 1511 require_once($bean2); 1512 $seed2 = new $beanR(); 1513 } 1514 1515 //parse fields 1516 //$token1 = strtolower($class1); 1517 if($class1 == 'Prospects'){ 1518 $class1 = 'CampaignProspects'; 1519 } 1520 foreach($fields as $field) 1521 { 1522 $split_fields = split('_', $field); 1523 if(count($split_fields) > 1) 1524 { 1525 $name = ''; 1526 $index = 1; 1527 for($i = 1; $i < count($split_fields); $i++) 1528 { 1529 $name .= $split_fields[$i]; 1530 $index++; 1531 if($index < count($split_fields)) 1532 $name .= '_'; 1533 } 1534 if(strtolower($split_fields[0]) == strtolower($class1)) 1535 { 1536 array_push($master_fields, $name); 1537 } 1538 else if(strtolower($split_fields[0]) == strtolower($class2)) 1539 { 1540 array_push($related_fields, $name); 1541 } 1542 } 1543 } 1544 1545 $html = '<html><body><table border = 1><tr>'; 1546 1547 foreach($master_fields as $master_field){ 1548 $html .= '<td>'.$class1.'_'.$master_field.'</td>'; 1549 } 1550 foreach($related_fields as $related_field){ 1551 $html .= '<td>'.$class2.'_'.$related_field.'</td>'; 1552 } 1553 $html .= '</tr>'; 1554 1555 $ids = $merge_array['ids']; 1556 $is_prospect_merge = ($seed1->object_name == 'Prospect'); 1557 foreach($ids as $key=>$value){ 1558 if($is_prospect_merge){ 1559 $seed1 = $seed1->retrieveTarget($key); 1560 }else{ 1561 $seed1->retrieve($key); 1562 } 1563 $html .= '<tr>'; 1564 foreach($master_fields as $master_field){ 1565 if(isset($seed1->$master_field)){ 1566 if($seed1->field_name_map[$master_field]['type'] == 'enum'){ 1567 //pull in the translated dom 1568 $html .='<td>'.$app_list_strings[$seed1->field_name_map[$master_field]['options']][$seed1->$master_field].'</td>'; 1569 }else{ 1570 $html .='<td>'.$seed1->$master_field.'</td>'; 1571 } 1572 } 1573 else{ 1574 $html .= '<td></td>'; 1575 } 1576 } 1577 if(isset($value) && !empty($value)){ 1578 $seed2->retrieve($value); 1579 foreach($related_fields as $related_field){ 1580 if(isset($seed2->$related_field)){ 1581 if($seed2->field_name_map[$related_field]['type'] == 'enum'){ 1582 //pull in the translated dom 1583 $html .='<td>'.$app_list_strings[$seed2->field_name_map[$related_field]['options']][$seed2->$related_field].'</td>'; 1584 }else{ 1585 $html .= '<td>'.$seed2->$related_field.'</td>'; 1586 } 1587 } 1588 else{ 1589 $html .= '<td></td>'; 1590 } 1591 } 1592 } 1593 $html .= '</tr>'; 1594 } 1595 $html .= "</table></body></html>"; 1596 } 1597 1598 $result = base64_encode($html); 1599 return array('result' => $result, 'error' => $error); 1600 } 1601 1602 $server->register( 1603 'get_mailmerge_document2', 1604 array('session'=>'xsd:string','file_name'=>'xsd:string', 'fields' => 'tns:select_fields'), 1605 array('return'=>'tns:get_mailmerge_document_result'), 1606 $NAMESPACE); 1607 1608 /** 1609 * Enter description here... 1610 * 1611 * @param String $session -- Session ID returned by a previous call to login. 1612 * @param unknown_type $file_name 1613 * @param unknown_type $fields 1614 * @return unknown 1615 */ 1616 function get_mailmerge_document2($session, $file_name, $fields) 1617 { 1618 global $beanList, $beanFiles, $app_list_strings; 1619 $error = new SoapError(); 1620 if(!validate_authenticated($session)) 1621 { 1622 $error->set_error('invalid_login'); 1623 return array('result'=>'', 'error'=>$error->get_soap_array()); 1624 } 1625 $html = ''; 1626 $file_name = $GLOBALS['sugar_config']['cache_dir'].'MergedDocuments/'.$file_name; 1627 1628 $master_fields = array(); 1629 $related_fields = array(); 1630 1631 if(file_exists($file_name)) 1632 { 1633 require_once($file_name); 1634 1635 $class1 = $merge_array['master_module']; 1636 $beanL = $beanList[$class1]; 1637 $bean1 = $beanFiles[$beanL]; 1638 require_once($bean1); 1639 $seed1 = new $beanL(); 1640 1641 if(!empty($merge_array['related_module'])) 1642 { 1643 $class2 = $merge_array['related_module']; 1644 $beanR = $beanList[$class2]; 1645 $bean2 = $beanFiles[$beanR]; 1646 require_once($bean2); 1647 $seed2 = new $beanR(); 1648 } 1649 1650 //parse fields 1651 //$token1 = strtolower($class1); 1652 if($class1 == 'Prospects'){ 1653 $class1 = 'CampaignProspects'; 1654 } 1655 foreach($fields as $field) 1656 { 1657 $split_fields = split('_', $field); 1658 if(count($split_fields) > 1) 1659 { 1660 $name = ''; 1661 $index = 1; 1662 for($i = 1; $i < count($split_fields); $i++) 1663 { 1664 $name .= $split_fields[$i]; 1665 $index++; 1666 if($index < count($split_fields)) 1667 $name .= '_'; 1668 } 1669 if(strtolower($split_fields[0]) == strtolower($class1)) 1670 { 1671 array_push($master_fields, $name); 1672 } 1673 else if(strtolower($split_fields[0]) == strtolower($class2)) 1674 { 1675 array_push($related_fields, $name); 1676 } 1677 } 1678 } 1679 1680 $html = '<html><body><table border = 1><tr>'; 1681 1682 foreach($master_fields as $master_field){ 1683 $html .= '<td>'.$class1.'_'.$master_field.'</td>'; 1684 } 1685 foreach($related_fields as $related_field){ 1686 $html .= '<td>'.$class2.'_'.$related_field.'</td>'; 1687 } 1688 $html .= '</tr>'; 1689 1690 $ids = $merge_array['ids']; 1691 $resultIds = array(); 1692 $is_prospect_merge = ($seed1->object_name == 'Prospect'); 1693 if($is_prospect_merge){ 1694 $pSeed = $seed1; 1695 } 1696 foreach($ids as $key=>$value){ 1697 1698 if($is_prospect_merge){ 1699 $seed1 = $pSeed->retrieveTarget($key); 1700 }else{ 1701 $seed1->retrieve($key); 1702 } 1703 $resultIds[] = array('name' => $seed1->module_name, 'value' => $key); 1704 $html .= '<tr>'; 1705 foreach($master_fields as $master_field){ 1706 if(isset($seed1->$master_field)){ 1707 if($seed1->field_name_map[$master_field]['type'] == 'enum'){ 1708 //pull in the translated dom 1709 $html .='<td>'.$app_list_strings[$seed1->field_name_map[$master_field]['options']][$seed1->$master_field].'</td>'; 1710 }else{ 1711 $html .='<td>'.$seed1->$master_field.'</td>'; 1712 } 1713 } 1714 else{ 1715 $html .= '<td></td>'; 1716 } 1717 } 1718 if(isset($value) && !empty($value)){ 1719 $resultIds[] = array('name' => $seed2->module_name, 'value' => $value); 1720 $seed2->retrieve($value); 1721 foreach($related_fields as $related_field){ 1722 if(isset($seed2->$related_field)){ 1723 if($seed2->field_name_map[$related_field]['type'] == 'enum'){ 1724 //pull in the translated dom 1725 $html .='<td>'.$app_list_strings[$seed2->field_name_map[$related_field]['options']][$seed2->$related_field].'</td>'; 1726 }else{ 1727 $html .= '<td>'.$seed2->$related_field.'</td>'; 1728 } 1729 } 1730 else{ 1731 $html .= '<td></td>'; 1732 } 1733 } 1734 } 1735 $html .= '</tr>'; 1736 } 1737 $html .= "</table></body></html>"; 1738 } 1739 1740 $result = base64_encode($html); 1741 return array('html' => $result, 'name_value_list' => $resultIds, 'error' => $error); 1742 } 1743 1744 $server->register( 1745 'get_document_revision', 1746 array('session'=>'xsd:string','i'=>'xsd:string'), 1747 array('return'=>'tns:return_document_revision'), 1748 $NAMESPACE); 1749 1750 /** 1751 * This method is used as a result of the .htaccess lock down on the cache directory. It will allow a 1752 * properly authenticated user to download a document that they have proper rights to download. 1753 * 1754 * @param String $session -- Session ID returned by a previous call to login. 1755 * @param String $id -- ID of the document revision to obtain 1756 * @return return_document_revision - this is a complex type as defined in SoapTypes.php 1757 */ 1758 function get_document_revision($session,$id) 1759 { 1760 global $sugar_config; 1761 1762 $error = new SoapError(); 1763 if(!validate_authenticated($session)){ 1764 $error->set_error('invalid_login'); 1765 return array('id'=>-1, 'error'=>$error->get_soap_array()); 1766 } 1767 1768 1769 $dr = new DocumentRevision(); 1770 $dr->retrieve($id); 1771 if(!empty($dr->filename)){ 1772 $filename = $sugar_config['upload_dir']."/".$dr->id; 1773 $handle = sugar_fopen($filename, "r"); 1774 $contents = fread($handle, filesize($filename)); 1775 fclose($handle); 1776 $contents = base64_encode($contents); 1777 1778 $fh = sugar_fopen($sugar_config['upload_dir']."/rogerrsmith.doc", 'w'); 1779 fwrite($fh, base64_decode($contents)); 1780 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()); 1781 }else{ 1782 $error->set_error('no_records'); 1783 return array('id'=>-1, 'error'=>$error->get_soap_array()); 1784 } 1785 1786 } 1787 1788 $server->register( 1789 'set_campaign_merge', 1790 array('session'=>'xsd:string', 'targets'=>'tns:select_fields', 'campaign_id'=>'xsd:string'), 1791 array('return'=>'tns:error_value'), 1792 $NAMESPACE); 1793 /** 1794 * Once we have successfuly done a mail merge on a campaign, we need to notify Sugar of the targets 1795 * and the campaign_id for tracking purposes 1796 * 1797 * @param session the session id of the authenticated user 1798 * @param targets a string array of ids identifying the targets used in the merge 1799 * @param campaign_id the campaign_id used for the merge 1800 * 1801 * @return error_value 1802 */ 1803 function set_campaign_merge($session,$targets, $campaign_id){ 1804 $error = new SoapError(); 1805 if(!validate_authenticated($session)){ 1806 $error->set_error('invalid_login'); 1807 return $error->get_soap_array(); 1808 } 1809 if (empty($campaign_id) or !is_array($targets) or count($targets) == 0) { 1810 $GLOBALS['log']->debug('set_campaign_merge: Merge action status will not be updated, because, campaign_id is null or no targets were selected.'); 1811 } else { 1812 require_once ('modules/Campaigns/utils.php'); 1813 campaign_log_mail_merge($campaign_id,$targets); 1814 } 1815 1816 return $error->get_soap_array(); 1817 } 1818 1819 $server->register( 1820 'get_entries_count', 1821 array('session'=>'xsd:string', 'module_name'=>'xsd:string', 'query'=>'xsd:string', 'deleted' => 'xsd:int'), 1822 array('return'=>'tns:get_entries_count_result'), 1823 $NAMESPACE); 1824 1825 /** 1826 * Retrieve number of records in a given module 1827 * 1828 * @param session the session id of the authenticated user 1829 * @param module_name module to retrieve number of records from 1830 * @param query allows webservice user to provide a WHERE clause 1831 * @param deleted specify whether or not to include deleted records 1832 * 1833 @return get_entries_count_result - this is a complex type as defined in SoapTypes.php 1834 */ 1835 function get_entries_count($session, $module_name, $query, $deleted) { 1836 global $beanList, $beanFiles, $current_user; 1837 1838 $error = new SoapError(); 1839 1840 if (!validate_authenticated($session)) { 1841 $error->set_error('invalid_login'); 1842 return array( 1843 'result_count' => -1, 1844 'error' => $error->get_soap_array() 1845 ); 1846 } 1847 1848 if (empty($beanList[$module_name])) { 1849 $error->set_error('no_module'); 1850 return array( 1851 'result_count' => -1, 1852 'error' => $error->get_soap_array() 1853 ); 1854 } 1855 1856 if(!check_modules_access($current_user, $module_name, 'list')){ 1857 $error->set_error('no_access'); 1858 return array( 1859 'result_count' => -1, 1860 'error' => $error->get_soap_array() 1861 ); 1862 } 1863 1864 $class_name = $beanList[$module_name]; 1865 require_once($beanFiles[$class_name]); 1866 $seed = new $class_name(); 1867 1868 if (!$seed->ACLAccess('ListView')) { 1869 $error->set_error('no_access'); 1870 return array( 1871 'result_count' => -1, 1872 'error' => $error->get_soap_array() 1873 ); 1874 } 1875 1876 $sql = 'SELECT COUNT(*) result_count FROM ' . $seed->table_name . ' '; 1877 1878 1879 1880 1881 1882 // build WHERE clauses, if any 1883 $where_clauses = array(); 1884 if (!empty($query)) { 1885 $where_clauses[] = $query; 1886 } 1887 if ($deleted == 0) { 1888 $where_clauses[] = $seed->table_name . '.deleted = 0'; 1889 } 1890 1891 // if WHERE clauses exist, add them to query 1892 if (!empty($where_clauses)) { 1893 $sql .= ' WHERE ' . implode(' AND ', $where_clauses); 1894 } 1895 1896 $res = $GLOBALS['db']->query($sql); 1897 $row = $GLOBALS['db']->fetchByAssoc($res); 1898 1899 return array( 1900 'result_count' => $row['result_count'], 1901 'error' => $error->get_soap_array() 1902 ); 1903 } 1904 1905 $server->register( 1906 'set_entries_details', 1907 array('session'=>'xsd:string', 'module_name'=>'xsd:string', 'name_value_lists'=>'tns:name_value_lists', 'select_fields' => 'tns:select_fields'), 1908 array('return'=>'tns:set_entries_detail_result'), 1909 $NAMESPACE); 1910 1911 /** 1912 * Update or create a list of SugarBeans, returning details about the records created/updated 1913 * 1914 * @param String $session -- Session ID returned by a previous call to login. 1915 * @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).. 1916 * @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. 1917 * @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. 1918 * @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. 1919 * 'error' -- The SOAP error if any. 1920 */ 1921 function set_entries_details($session, $module_name, $name_value_lists, $select_fields) { 1922 $error = new SoapError(); 1923 1924 if(!validate_authenticated($session)){ 1925 $error->set_error('invalid_login'); 1926 1927 return array( 1928 'ids' => array(), 1929 'error' => $error->get_soap_array() 1930 ); 1931 } 1932 1933 return handle_set_entries($module_name, $name_value_lists, $select_fields); 1934 } 1935 1936 // INTERNAL FUNCTION NOT EXPOSED THROUGH API 1937 function handle_set_entries($module_name, $name_value_lists, $select_fields = FALSE) { 1938 global $beanList, $beanFiles, $app_list_strings; 1939 1940 $error = new SoapError(); 1941 $ret_values = array(); 1942 1943 if(empty($beanList[$module_name])){ 1944 $error->set_error('no_module'); 1945 return array('ids'=>array(), 'error'=>$error->get_soap_array()); 1946 } 1947 global $current_user; 1948 if(!check_modules_access($current_user, $module_name, 'write')){ 1949 $error->set_error('no_access'); 1950 return array('ids'=>-1, 'error'=>$error->get_soap_array()); 1951 } 1952 1953 $class_name = $beanList[$module_name]; 1954 require_once($beanFiles[$class_name]); 1955 $ids = array(); 1956 $count = 1; 1957 $total = sizeof($name_value_lists); 1958 foreach($name_value_lists as $name_value_list){ 1959 $seed = new $class_name(); 1960 1961 $seed->update_vcal = false; 1962 foreach($name_value_list as $value){ 1963 if($value['name'] == 'id'){ 1964 $seed->retrieve($value['value']); 1965 break; 1966 } 1967 } 1968 1969 foreach($name_value_list as $value) { 1970 $val = $value['value']; 1971 if($seed->field_name_map[$value['name']]['type'] == 'enum' ||$seed->field_name_map[$value['name']]['type'] == 'radioenum'){ 1972 $vardef = $seed->field_name_map[$value['name']]; 1973 if(isset($app_list_strings[$vardef['options']]) && !isset($app_list_strings[$vardef['options']][$value]) ) { 1974 if ( in_array($val,$app_list_strings[$vardef['options']]) ){ 1975 $val = array_search($val,$app_list_strings[$vardef['options']]); 1976 } 1977 } 1978 } else if($seed->field_name_map[$value['name']]['type'] == 'multienum') { 1979 $vardef = $seed->field_name_map[$value['name']]; 1980 if(isset($app_list_strings[$vardef['options']]) && !isset($app_list_strings[$vardef['options']][$value]) ) { 1981 $items = split(",", $val); 1982 $parsedItems = array(); 1983 foreach ($items as $item) { 1984 if ( in_array($item, $app_list_strings[$vardef['options']]) ){ 1985 $keyVal = array_search($item,$app_list_strings[$vardef['options']]); 1986 array_push($parsedItems, $keyVal); 1987 } 1988 } 1989 if (!empty($parsedItems)) { 1990 $val = encodeMultienumValue($parsedItems); 1991 } 1992 } 1993 } 1994 $seed->$value['name'] = $val; 1995 } 1996 1997 if($count == $total){ 1998 $seed->update_vcal = false; 1999 } 2000 $count++; 2001 2002 //Add the account to a contact 2003 if($module_name == 'Contacts'){ 2004 $GLOBALS['log']->debug('Creating Contact Account'); 2005 add_create_account($seed); 2006 $duplicate_id = check_for_duplicate_contacts($seed); 2007 if($duplicate_id == null){ 2008 if($seed->ACLAccess('Save') && ($seed->deleted != 1 || $seed->ACLAccess('Delete'))){ 2009 $seed->save(); 2010 if($seed->deleted == 1){ 2011 $seed->mark_deleted($seed->id); 2012 } 2013 $ids[] = $seed->id; 2014 } 2015 } 2016 else{ 2017 //since we found a duplicate we should set the sync flag 2018 if( $seed->ACLAccess('Save')){ 2019 $seed->id = $duplicate_id; 2020 $seed->contacts_users_id = $current_user->id; 2021 $seed->save(); 2022 $ids[] = $duplicate_id;//we have a conflict 2023 } 2024 } 2025 } 2026 else if($module_name == 'Meetings' || $module_name == 'Calls'){ 2027 //we are going to check if we have a meeting in the system 2028 //with the same outlook_id. If we do find one then we will grab that 2029 //id and save it 2030 if( $seed->ACLAccess('Save') && ($seed->deleted != 1 || $seed->ACLAccess('Delete'))){ 2031 if(empty($seed->id) && !isset($seed->id)){ 2032 if(!empty($seed->outlook_id) && isset($seed->outlook_id)){ 2033 //at this point we have an object that does not have 2034 //the id set, but does have the outlook_id set 2035 //so we need to query the db to find if we already 2036 //have an object with this outlook_id, if we do 2037 //then we can set the id, otherwise this is a new object 2038 $order_by = ""; 2039 $query = $seed->table_name.".outlook_id = '".$seed->outlook_id."'"; 2040 $response = $seed->get_list($order_by, $query, 0,-1,-1,0); 2041 $list = $response['list']; 2042 if(count($list) > 0){ 2043 foreach($list as $value) 2044 { 2045 $seed->id = $value->id; 2046 break; 2047 } 2048 }//fi 2049 }//fi 2050 }//fi 2051 if (empty($seed->reminder_time)) { 2052 $seed->reminder_time = -1; 2053 } 2054 if($seed->reminder_time == -1){ 2055 $defaultRemindrTime = $current_user->getPreference('reminder_time'); 2056 if ($defaultRemindrTime != -1){ 2057 $seed->reminder_checked = '1'; 2058 $seed->reminder_time = $defaultRemindrTime; 2059 } 2060 } 2061 $seed->save(); 2062 $ids[] = $seed->id; 2063 }//fi 2064 } 2065 else 2066 { 2067 if( $seed->ACLAccess('Save') && ($seed->deleted != 1 || $seed->ACLAccess('Delete'))){ 2068 $seed->save(); 2069 $ids[] = $seed->id; 2070 } 2071 } 2072 2073 // if somebody is calling set_entries_detail() and wants fields returned... 2074 if ($select_fields !== FALSE) { 2075 $ret_values[$count] = array(); 2076 2077 foreach ($select_fields as $select_field) { 2078 if (isset($seed->$select_field)) { 2079 $ret_values[$count][] = get_name_value($select_field, $seed->$select_field); 2080 } 2081 } 2082 } 2083 } 2084 2085 // handle returns for set_entries_detail() and set_entries() 2086 if ($select_fields !== FALSE) { 2087 return array( 2088 'name_value_lists' =>