]> CyberLeo.Net >> Repos - Github/sugarcrm.git/blob - service/core/SugarWebServiceImpl.php
Release 6.4.0beta1
[Github/sugarcrm.git] / service / core / SugarWebServiceImpl.php
1 <?php
2 if(!defined('sugarEntry'))define('sugarEntry', true);
3 /*********************************************************************************
4  * SugarCRM Community Edition is a customer relationship management program developed by
5  * SugarCRM, Inc. Copyright (C) 2004-2011 SugarCRM Inc.
6  * 
7  * This program is free software; you can redistribute it and/or modify it under
8  * the terms of the GNU Affero 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 Affero General Public License for more
17  * details.
18  * 
19  * You should have received a copy of the GNU Affero 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 Affero General Public License version 3.
30  * 
31  * In accordance with Section 7(b) of the GNU Affero 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
38
39 /**
40  * This class is an implemenatation class for all the web services
41  */
42 require_once('service/core/SoapHelperWebService.php');
43 SugarWebServiceImpl::$helperObject = new SoapHelperWebServices();
44
45 class SugarWebServiceImpl{
46
47         public static $helperObject = null;
48
49 /**
50  * Retrieve a single SugarBean based on ID.
51  *
52  * @param String $session -- Session ID returned by a previous call to login.
53  * @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)..
54  * @param String $id -- The SugarBean's ID value.
55  * @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.
56 * @param Array $link_name_to_fields_array -- A list of link_names and for each link_name, what fields value to be returned. For ex.'link_name_to_fields_array' => array(array('name' =>  'email_addresses', 'value' => array('id', 'email_address', 'opt_out', 'primary_address')))
57 * @return Array
58 *        'entry_list' -- Array - The records name value pair for the simple data types excluding link field data.
59 *            'relationship_list' -- Array - The records link field data. The example is if asked about accounts email address then return data would look like Array ( [0] => Array ( [name] => email_addresses [records] => Array ( [0] => Array ( [0] => Array ( [name] => id [value] => 3fb16797-8d90-0a94-ac12-490b63a6be67 ) [1] => Array ( [name] => email_address [value] => hr.kid.qa@example.com ) [2] => Array ( [name] => opt_out [value] => 0 ) [3] => Array ( [name] => primary_address [value] => 1 ) ) [1] => Array ( [0] => Array ( [name] => id [value] => 403f8da1-214b-6a88-9cef-490b63d43566 ) [1] => Array ( [name] => email_address [value] => kid.hr@example.name ) [2] => Array ( [name] => opt_out [value] => 0 ) [3] => Array ( [name] => primary_address [value] => 0 ) ) ) ) )
60 * @exception 'SoapFault' -- The SOAP error, if any
61 */
62 function get_entry($session, $module_name, $id,$select_fields, $link_name_to_fields_array){
63         $GLOBALS['log']->info('Begin: SugarWebServiceImpl->get_entry');
64         return self::get_entries($session, $module_name, array($id), $select_fields, $link_name_to_fields_array);
65         $GLOBALS['log']->info('end: SugarWebServiceImpl->get_entry');
66 }
67
68 /**
69  * Retrieve a list of SugarBean's based on provided IDs. This API will not wotk with report module
70  *
71  * @param String $session -- Session ID returned by a previous call to login.
72  * @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)..
73  * @param Array $ids -- An array of SugarBean IDs.
74  * @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.
75 * @param Array $link_name_to_fields_array -- A list of link_names and for each link_name, what fields value to be returned. For ex.'link_name_to_fields_array' => array(array('name' =>  'email_addresses', 'value' => array('id', 'email_address', 'opt_out', 'primary_address')))
76 * @return Array
77 *        'entry_list' -- Array - The records name value pair for the simple data types excluding link field data.
78 *            'relationship_list' -- Array - The records link field data. The example is if asked about accounts email address then return data would look like Array ( [0] => Array ( [name] => email_addresses [records] => Array ( [0] => Array ( [0] => Array ( [name] => id [value] => 3fb16797-8d90-0a94-ac12-490b63a6be67 ) [1] => Array ( [name] => email_address [value] => hr.kid.qa@example.com ) [2] => Array ( [name] => opt_out [value] => 0 ) [3] => Array ( [name] => primary_address [value] => 1 ) ) [1] => Array ( [0] => Array ( [name] => id [value] => 403f8da1-214b-6a88-9cef-490b63d43566 ) [1] => Array ( [name] => email_address [value] => kid.hr@example.name ) [2] => Array ( [name] => opt_out [value] => 0 ) [3] => Array ( [name] => primary_address [value] => 0 ) ) ) ) )
79 * @exception 'SoapFault' -- The SOAP error, if any
80 */
81 function get_entries($session, $module_name, $ids, $select_fields, $link_name_to_fields_array){
82         $GLOBALS['log']->info('Begin: SugarWebServiceImpl->get_entries');
83         global  $beanList, $beanFiles;
84         $error = new SoapError();
85
86         $linkoutput_list = array();
87         $output_list = array();
88     $using_cp = false;
89     if($module_name == 'CampaignProspects'){
90         $module_name = 'Prospects';
91         $using_cp = true;
92     }
93         if (!self::$helperObject->checkSessionAndModuleAccess($session, 'invalid_session', $module_name, 'read', 'no_access', $error)) {
94                 $GLOBALS['log']->info('End: SugarWebServiceImpl->get_entries');
95                 return;
96         } // if
97
98         if($module_name == 'Reports'){
99                 $error->set_error('invalid_call_error');
100                 self::$helperObject->setFaultObject($error);
101                 $GLOBALS['log']->info('End: SugarWebServiceImpl->get_entries');
102                 return;
103         }
104
105         $class_name = $beanList[$module_name];
106         require_once($beanFiles[$class_name]);
107
108         $temp = new $class_name();
109         foreach($ids as $id) {
110                 $seed = @clone($temp);
111             if($using_cp){
112                 $seed = $seed->retrieveTarget($id);
113             }else{
114                         if ($seed->retrieve($id) == null)
115                                 $seed->deleted = 1;
116                 }
117
118                 if ($seed->deleted == 1) {
119                         $list = array();
120                         $list[] = array('name'=>'warning', 'value'=>'Access to this object is denied since it has been deleted or does not exist');
121                         $list[] = array('name'=>'deleted', 'value'=>'1');
122                         $output_list[] = Array('id'=>$id,
123                                                                         'module_name'=> $module_name,
124                                                                         'name_value_list'=>$list,
125                                                                         );
126                         continue;
127     }
128             if (!self::$helperObject->checkACLAccess($seed, 'DetailView', $error, 'no_access')) {
129                 return;
130             }
131                 $output_list[] = self::$helperObject->get_return_value_for_fields($seed, $module_name, $select_fields);
132                 if (!empty($link_name_to_fields_array)) {
133                         $linkoutput_list[] = self::$helperObject->get_return_value_for_link_fields($seed, $module_name, $link_name_to_fields_array);
134                 }
135         }
136         $GLOBALS['log']->info('End: SugarWebServiceImpl->get_entries');
137         return array('entry_list'=>$output_list, 'relationship_list' => $linkoutput_list);
138 }
139
140
141 /**
142  * Retrieve a list of beans.  This is the primary method for getting list of SugarBeans from Sugar using the SOAP API.
143  *
144  * @param String $session -- Session ID returned by a previous call to login.
145  * @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)..
146  * @param String $query -- SQL where clause without the word 'where'
147  * @param String $order_by -- SQL order by clause without the phrase 'order by'
148  * @param integer $offset -- The record offset to start from.
149  * @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.
150  * @param Array $link_name_to_fields_array -- A list of link_names and for each link_name, what fields value to be returned. For ex.'link_name_to_fields_array' => array(array('name' =>  'email_addresses', 'value' => array('id', 'email_address', 'opt_out', 'primary_address')))
151 * @param integer $max_results -- The maximum number of records to return.  The default is the sugar configuration value for 'list_max_entries_per_page'
152  * @param integer $deleted -- false if deleted records should not be include, true if deleted records should be included.
153  * @return Array 'result_count' -- integer - The number of records returned
154  *               'next_offset' -- integer - 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.
155  *               'entry_list' -- Array - The records that were retrieved
156  *                       'relationship_list' -- Array - The records link field data. The example is if asked about accounts email address then return data would look like Array ( [0] => Array ( [name] => email_addresses [records] => Array ( [0] => Array ( [0] => Array ( [name] => id [value] => 3fb16797-8d90-0a94-ac12-490b63a6be67 ) [1] => Array ( [name] => email_address [value] => hr.kid.qa@example.com ) [2] => Array ( [name] => opt_out [value] => 0 ) [3] => Array ( [name] => primary_address [value] => 1 ) ) [1] => Array ( [0] => Array ( [name] => id [value] => 403f8da1-214b-6a88-9cef-490b63d43566 ) [1] => Array ( [name] => email_address [value] => kid.hr@example.name ) [2] => Array ( [name] => opt_out [value] => 0 ) [3] => Array ( [name] => primary_address [value] => 0 ) ) ) ) )
157 * @exception 'SoapFault' -- The SOAP error, if any
158 */
159 function get_entry_list($session, $module_name, $query, $order_by,$offset, $select_fields, $link_name_to_fields_array, $max_results, $deleted ){
160
161         $GLOBALS['log']->info('Begin: SugarWebServiceImpl->get_entry_list');
162         global  $beanList, $beanFiles;
163         $error = new SoapError();
164     $using_cp = false;
165     if($module_name == 'CampaignProspects'){
166         $module_name = 'Prospects';
167         $using_cp = true;
168     }
169         if (!self::$helperObject->checkSessionAndModuleAccess($session, 'invalid_session', $module_name, 'read', 'no_access', $error)) {
170                 $GLOBALS['log']->info('End: SugarWebServiceImpl->get_entry_list');
171                 return;
172         } // if
173
174         // If the maximum number of entries per page was specified, override the configuration value.
175         if($max_results > 0){
176                 global $sugar_config;
177                 $sugar_config['list_max_entries_per_page'] = $max_results;
178         } // if
179
180         $class_name = $beanList[$module_name];
181         require_once($beanFiles[$class_name]);
182         $seed = new $class_name();
183
184     if (!self::$helperObject->checkACLAccess($seed, 'Export', $error, 'no_access')) {
185                 $GLOBALS['log']->info('End: SugarWebServiceImpl->get_entry_list');
186         return;
187     } // if
188
189     if (!self::$helperObject->checkACLAccess($seed, 'list', $error, 'no_access')) {
190                 $GLOBALS['log']->info('End: SugarWebServiceImpl->get_entry_list');
191         return;
192     } // if
193
194         if($query == ''){
195                 $where = '';
196         } // if
197         if($offset == '' || $offset == -1){
198                 $offset = 0;
199         } // if
200     if($using_cp){
201         $response = $seed->retrieveTargetList($query, $select_fields, $offset,-1,-1,$deleted);
202     }else{
203            $response = $seed->get_list($order_by, $query, $offset,-1,-1,$deleted);
204     } // else
205         $list = $response['list'];
206
207         $output_list = array();
208         $linkoutput_list = array();
209
210         foreach($list as $value) {
211                 if(isset($value->emailAddress)){
212                         $value->emailAddress->handleLegacyRetrieve($value);
213                 } // if
214                 $value->fill_in_additional_detail_fields();
215
216                 $output_list[] = self::$helperObject->get_return_value_for_fields($value, $module_name, $select_fields);
217                 if(!empty($link_name_to_fields_array)){
218                         $linkoutput_list[] = self::$helperObject->get_return_value_for_link_fields($value, $module_name, $link_name_to_fields_array);
219                 }
220         } // foreach
221
222         // Calculate the offset for the start of the next page
223         $next_offset = $offset + sizeof($output_list);
224
225         $GLOBALS['log']->info('End: SugarWebServiceImpl->get_entry_list');
226         return array('result_count'=>sizeof($output_list), 'next_offset'=>$next_offset, 'entry_list'=>$output_list, 'relationship_list' => $linkoutput_list);
227 } // fn
228
229
230 /**
231  * Set a single relationship between two beans.  The items are related by module name and id.
232  *
233  * @param String $session -- Session ID returned by a previous call to login.
234  * @param String $module_name -- 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)..
235  * @param String $module_id - The ID of the bean in the specified module_name
236  * @param String link_field_name -- name of the link field which relates to the other module for which the relationship needs to be generated.
237  * @param array related_ids -- array of related record ids for which relationships needs to be generated
238  * @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.
239  * @param integer $delete -- Optional, if the value 0 or nothing is passed then it will add the relationship for related_ids and if 1 is passed, it will delete this relationship for related_ids
240  * @return Array - created - integer - How many relationships has been created
241  *               - failed - integer - How many relationsip creation failed
242  *                               - deleted - integer - How many relationships were deleted
243  * @exception 'SoapFault' -- The SOAP error, if any
244  */
245 function set_relationship($session, $module_name, $module_id, $link_field_name, $related_ids, $name_value_list, $delete){
246         $GLOBALS['log']->info('Begin: SugarWebServiceImpl->set_relationship');
247         $error = new SoapError();
248         if (!self::$helperObject->checkSessionAndModuleAccess($session, 'invalid_session', '', '', '', $error)) {
249                 $GLOBALS['log']->info('End: SugarWebServiceImpl->set_relationship');
250                 return;
251         } // if
252
253         $count = 0;
254         $deletedCount = 0;
255         $failed = 0;
256         $deleted = 0;
257         $name_value_array = array();
258         if (is_array($name_value_list)) {
259                 $name_value_array = $name_value_list;
260         }
261
262         if (isset($delete)) {
263                 $deleted = $delete;
264         }
265         if (self::$helperObject->new_handle_set_relationship($module_name, $module_id, $link_field_name, $related_ids,$name_value_array, $deleted)) {
266                 if ($deleted) {
267                         $deletedCount++;
268                 } else {
269                         $count++;
270                 }
271         } else {
272                 $failed++;
273         } // else
274         $GLOBALS['log']->info('End: SugarWebServiceImpl->set_relationship');
275         return array('created'=>$count , 'failed'=>$failed, 'deleted' => $deletedCount);
276 }
277
278 /**
279  * Set a single relationship between two beans.  The items are related by module name and id.
280  *
281  * @param String $session -- Session ID returned by a previous call to login.
282  * @param array $module_names -- Array of 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)..
283  * @param array $module_ids - The array of ID of the bean in the specified module_name
284  * @param array $link_field_names -- Array of the name of the link field which relates to the other module for which the relationships needs to be generated.
285  * @param array $related_ids -- array of an array of related record ids for which relationships needs to be generated
286  * @param array $name_value_lists -- Array of Array. The keys of the inner array are the SugarBean attributes, the values of the inner array are the values the attributes should have.
287  * @param array int $delete_array -- Optional, array of 0 or 1. If the value 0 or nothing is passed then it will add the relationship for related_ids and if 1 is passed, it will delete this relationship for related_ids
288  * @return Array - created - integer - How many relationships has been created
289  *               - failed - integer - How many relationsip creation failed
290  *                               - deleted - integer - How many relationships were deleted
291 *
292  * @exception 'SoapFault' -- The SOAP error, if any
293 */
294 function set_relationships($session, $module_names, $module_ids, $link_field_names, $related_ids, $name_value_lists, $delete_array) {
295         $GLOBALS['log']->info('Begin: SugarWebServiceImpl->set_relationships');
296         $error = new SoapError();
297         if (!self::$helperObject->checkSessionAndModuleAccess($session, 'invalid_session', '', '', '', $error)) {
298                 $GLOBALS['log']->info('End: SugarWebServiceImpl->set_relationships');
299                 return;
300         } // if
301
302         if ((empty($module_names) || empty($module_ids) || empty($link_field_names) || empty($related_ids)) ||
303                 (sizeof($module_names) != (sizeof($module_ids) || sizeof($link_field_names) || sizeof($related_ids)))) {
304                 $error->set_error('invalid_data_format');
305                 self::$helperObject->setFaultObject($error);
306                 $GLOBALS['log']->info('End: SugarWebServiceImpl->set_relationships');
307                 return;
308         } // if
309
310         $count = 0;
311         $deletedCount = 0;
312         $failed = 0;
313         $counter = 0;
314         $deleted = 0;
315         foreach($module_names as $module_name) {
316                 $name_value_list = array();
317                 if (is_array($name_value_lists) && isset($name_value_lists[$counter])) {
318                         $name_value_list = $name_value_lists[$counter];
319                 }
320                 if (is_array($delete_array) && isset($delete_array[$counter])) {
321                         $deleted = $delete_array[$counter];
322                 }
323                 if (self::$helperObject->new_handle_set_relationship($module_name, $module_ids[$counter], $link_field_names[$counter], $related_ids[$counter], $name_value_list, $deleted)) {
324                         if ($deleted) {
325                                 $deletedCount++;
326                         } else {
327                                 $count++;
328                         }
329                 } else {
330                         $failed++;
331                 } // else
332                 $counter++;
333         } // foreach
334         $GLOBALS['log']->info('End: SugarWebServiceImpl->set_relationships');
335         return array('created'=>$count , 'failed'=>$failed, 'deleted' => $deletedCount);
336 } // fn
337
338 /**
339  * Retrieve a collection of beans that are related to the specified bean and optionally return relationship data for those related beans.
340  * So in this API you can get contacts info for an account and also return all those contact's email address or an opportunity info also.
341  *
342  * @param String $session -- Session ID returned by a previous call to login.
343  * @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)..
344  * @param String $module_id -- The ID of the bean in the specified module
345  * @param String $link_field_name -- The name of the lnk field to return records from.  This name should be the name the relationship.
346  * @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.
347  * @param Array $related_fields - Array of related bean fields to be returned.
348  * @param Array $related_module_link_name_to_fields_array - For every related bean returrned, specify link fields name to fields info for that bean to be returned. For ex.'link_name_to_fields_array' => array(array('name' =>  'email_addresses', 'value' => array('id', 'email_address', 'opt_out', 'primary_address'))).
349  * @param Number $deleted -- false if deleted records should not be include, true if deleted records should be included.
350  * @return Array 'entry_list' -- Array - The records that were retrieved
351  *                       'relationship_list' -- Array - The records link field data. The example is if asked about accounts contacts email address then return data would look like Array ( [0] => Array ( [name] => email_addresses [records] => Array ( [0] => Array ( [0] => Array ( [name] => id [value] => 3fb16797-8d90-0a94-ac12-490b63a6be67 ) [1] => Array ( [name] => email_address [value] => hr.kid.qa@example.com ) [2] => Array ( [name] => opt_out [value] => 0 ) [3] => Array ( [name] => primary_address [value] => 1 ) ) [1] => Array ( [0] => Array ( [name] => id [value] => 403f8da1-214b-6a88-9cef-490b63d43566 ) [1] => Array ( [name] => email_address [value] => kid.hr@example.name ) [2] => Array ( [name] => opt_out [value] => 0 ) [3] => Array ( [name] => primary_address [value] => 0 ) ) ) ) )
352 * @exception 'SoapFault' -- The SOAP error, if any
353 */
354 function get_relationships($session, $module_name, $module_id, $link_field_name, $related_module_query, $related_fields, $related_module_link_name_to_fields_array, $deleted){
355
356         $GLOBALS['log']->info('Begin: SugarWebServiceImpl->get_relationships');
357         global  $beanList, $beanFiles;
358         $error = new SoapError();
359         if (!self::$helperObject->checkSessionAndModuleAccess($session, 'invalid_session', $module_name, 'read', 'no_access', $error)) {
360                 $GLOBALS['log']->info('End: SugarWebServiceImpl->get_relationships');
361                 return;
362         } // if
363
364         $class_name = $beanList[$module_name];
365         require_once($beanFiles[$class_name]);
366         $mod = new $class_name();
367         $mod->retrieve($module_id);
368
369     if (!self::$helperObject->checkACLAccess($mod, 'DetailView', $error, 'no_access')) {
370                 $GLOBALS['log']->info('End: SugarWebServiceImpl->get_relationships');
371         return;
372     } // if
373
374     $output_list = array();
375         $linkoutput_list = array();
376
377         // get all the related mmodules data.
378     $result = self::$helperObject->getRelationshipResults($mod, $link_field_name, $related_fields, $related_module_query);
379     if (self::$helperObject->isLogLevelDebug()) {
380                 $GLOBALS['log']->debug('SoapHelperWebServices->get_relationships - return data for getRelationshipResults is ' . var_export($result, true));
381     } // if
382         if ($result) {
383                 $list = $result['rows'];
384                 $filterFields = $result['fields_set_on_rows'];
385
386                 if (sizeof($list) > 0) {
387                         // get the related module name and instantiate a bean for that.
388                         $submodulename = $mod->$link_field_name->getRelatedModuleName();
389                         $submoduleclass = $beanList[$submodulename];
390                         require_once($beanFiles[$submoduleclass]);
391
392                         $submoduletemp = new $submoduleclass();
393                         foreach($list as $row) {
394                                 $submoduleobject = @clone($submoduletemp);
395                                 // set all the database data to this object
396                                 foreach ($filterFields as $field) {
397                                         $submoduleobject->$field = $row[$field];
398                                 } // foreach
399                                 if (isset($row['id'])) {
400                                         $submoduleobject->id = $row['id'];
401                                 }
402                                 $output_list[] = self::$helperObject->get_return_value_for_fields($submoduleobject, $submodulename, $filterFields);
403                                 if (!empty($related_module_link_name_to_fields_array)) {
404                                         $linkoutput_list[] = self::$helperObject->get_return_value_for_link_fields($submoduleobject, $submodulename, $related_module_link_name_to_fields_array);
405                                 } // if
406
407                         } // foreach
408                 }
409
410         } // if
411
412         $GLOBALS['log']->info('End: SugarWebServiceImpl->get_relationships');
413         return array('entry_list'=>$output_list, 'relationship_list' => $linkoutput_list);
414
415 } // fn
416
417 /**
418  * Update or create a single SugarBean.
419  *
420  * @param String $session -- Session ID returned by a previous call to login.
421  * @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)..
422  * @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.
423  * @return Array    'id' -- the ID of the bean that was written to (-1 on error)
424  * @exception 'SoapFault' -- The SOAP error, if any
425 */
426 function set_entry($session,$module_name, $name_value_list){
427         global  $beanList, $beanFiles, $current_user;
428
429         $GLOBALS['log']->info('Begin: SugarWebServiceImpl->set_entry');
430     if (self::$helperObject->isLogLevelDebug()) {
431                 $GLOBALS['log']->debug('SoapHelperWebServices->set_entry - input data is ' . var_export($name_value_list, true));
432     } // if
433         $error = new SoapError();
434         if (!self::$helperObject->checkSessionAndModuleAccess($session, 'invalid_session', $module_name, 'write', 'no_access', $error)) {
435                 $GLOBALS['log']->info('End: SugarWebServiceImpl->set_entry');
436                 return;
437         } // if
438         $class_name = $beanList[$module_name];
439         require_once($beanFiles[$class_name]);
440         $seed = new $class_name();
441         foreach($name_value_list as $name=>$value){
442                 if(is_array($value) &&  $value['name'] == 'id'){
443                         $seed->retrieve($value['value']);
444                         break;
445                 }else if($name === 'id' ){
446
447                         $seed->retrieve($value);
448                 }
449         }
450
451         foreach($name_value_list as $name=>$value){
452                 if($module_name == 'Users' && !empty($seed->id) && ($seed->id != $current_user->id) && $name == 'user_hash'){
453                         continue;
454                 }
455                 if(!is_array($value)){
456                         $seed->$name = $value;
457                 }else{
458                         $seed->$value['name'] = $value['value'];
459                 }
460         }
461     if (!self::$helperObject->checkACLAccess($seed, 'Save', $error, 'no_access') || ($seed->deleted == 1  && !self::$helperObject->checkACLAccess($seed, 'Delete', $error, 'no_access'))) {
462                 $GLOBALS['log']->info('End: SugarWebServiceImpl->set_entry');
463         return;
464     } // if
465
466         $seed->save(self::$helperObject->checkSaveOnNotify());
467         if($seed->deleted == 1){
468                 $seed->mark_deleted($seed->id);
469         }
470         $GLOBALS['log']->info('End: SugarWebServiceImpl->set_entry');
471         return array('id'=>$seed->id);
472 } // fn
473
474 /**
475  * Update or create a list of SugarBeans
476  *
477  * @param String $session -- Session ID returned by a previous call to login.
478  * @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)..
479  * @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.
480  * @return Array    'ids' -- Array of the IDs of the beans that was written to (-1 on error)
481  * @exception 'SoapFault' -- The SOAP error, if any
482  */
483 function set_entries($session,$module_name, $name_value_lists){
484         $GLOBALS['log']->info('Begin: SugarWebServiceImpl->set_entries');
485     if (self::$helperObject->isLogLevelDebug()) {
486                 $GLOBALS['log']->debug('SoapHelperWebServices->set_entries - input data is ' . var_export($name_value_lists, true));
487     } // if
488         $error = new SoapError();
489         if (!self::$helperObject->checkSessionAndModuleAccess($session, 'invalid_session', $module_name, 'write', 'no_access', $error)) {
490                 $GLOBALS['log']->info('End: SugarWebServiceImpl->set_entries');
491                 return;
492         } // if
493
494         $GLOBALS['log']->info('End: SugarWebServiceImpl->set_entries');
495         return self::$helperObject->new_handle_set_entries($module_name, $name_value_lists, FALSE);
496 }
497
498 /**
499  * Log the user into the application
500  *
501  * @param UserAuth array $user_auth -- Set user_name and password (password needs to be
502  *      in the right encoding for the type of authentication the user is setup for.  For Base
503  *      sugar validation, password is the MD5 sum of the plain text password.
504  * @param String $application -- The name of the application you are logging in from.  (Currently unused).
505  * @param array $name_value_list -- Array of name value pair of extra parameters. As of today only 'language' and 'notifyonsave' is supported
506  * @return Array - id - String id is the session_id of the session that was created.
507  *                               - module_name - String - module name of user
508  *                               - name_value_list - Array - The name value pair of user_id, user_name, user_language, user_currency_id, user_currency_name
509  * @exception 'SoapFault' -- The SOAP error, if any
510  */
511 public function login($user_auth, $application, $name_value_list){
512         $GLOBALS['log']->info('Begin: SugarWebServiceImpl->login');
513         global $sugar_config, $system_config;
514         $error = new SoapError();
515         $user = new User();
516         $success = false;
517         if(!empty($user_auth['encryption']) && $user_auth['encryption'] === 'PLAIN'){
518                 $user_auth['password'] = md5($user_auth['password']);
519         }
520         //rrs
521                 $system_config = new Administration();
522         $system_config->retrieveSettings('system');
523         $authController = new AuthenticationController((!empty($sugar_config['authenticationClass'])? $sugar_config['authenticationClass'] : 'SugarAuthenticate'));
524         //rrs
525         $isLoginSuccess = $authController->login($user_auth['user_name'], $user_auth['password'], array('passwordEncrypted' => true));
526         $usr_id=$user->retrieve_user_id($user_auth['user_name']);
527         if($usr_id) {
528                 $user->retrieve($usr_id);
529         }
530         if ($isLoginSuccess) {
531                 if ($_SESSION['hasExpiredPassword'] =='1') {
532                         $error->set_error('password_expired');
533                         $GLOBALS['log']->fatal('password expired for user ' . $user_auth['user_name']);
534                         LogicHook::initialize();
535                         $GLOBALS['logic_hook']->call_custom_logic('Users', 'login_failed');
536                         self::$helperObject->setFaultObject($error);
537                         return;
538                 } // if
539                 if(!empty($user) && !empty($user->id) && !$user->is_group) {
540                         $success = true;
541                         global $current_user;
542                         $current_user = $user;
543                 } // if
544         } else if($usr_id && isset($user->user_name) && ($user->getPreference('lockout') == '1')) {
545                         $error->set_error('lockout_reached');
546                         $GLOBALS['log']->fatal('Lockout reached for user ' . $user_auth['user_name']);
547                         LogicHook::initialize();
548                         $GLOBALS['logic_hook']->call_custom_logic('Users', 'login_failed');
549                         self::$helperObject->setFaultObject($error);
550                         return;
551         } else if(function_exists('mcrypt_cbc')){
552                 $password = self::$helperObject->decrypt_string($user_auth['password']);
553                 if($authController->login($user_auth['user_name'], $password) && isset($_SESSION['authenticated_user_id'])){
554                         $success = true;
555                 } // if
556         } // else if
557
558         if($success){
559                 session_start();
560                 global $current_user;
561                 //$current_user = $user;
562                 self::$helperObject->login_success($name_value_list);
563                 $current_user->loadPreferences();
564                 $_SESSION['is_valid_session']= true;
565                 $_SESSION['ip_address'] = query_client_ip();
566                 $_SESSION['user_id'] = $current_user->id;
567                 $_SESSION['type'] = 'user';
568                 $_SESSION['avail_modules']= self::$helperObject->get_user_module_list($current_user);
569                 $_SESSION['authenticated_user_id'] = $current_user->id;
570                 $_SESSION['unique_key'] = $sugar_config['unique_key'];
571                 $current_user->call_custom_logic('after_login');
572                 $GLOBALS['log']->info('End: SugarWebServiceImpl->login - succesful login');
573                 $nameValueArray = array();
574                 global $current_language;
575                 $nameValueArray['user_id'] = self::$helperObject->get_name_value('user_id', $current_user->id);
576                 $nameValueArray['user_name'] = self::$helperObject->get_name_value('user_name', $current_user->user_name);
577                 $nameValueArray['user_language'] = self::$helperObject->get_name_value('user_language', $current_language);
578                 $cur_id = $current_user->getPreference('currency');
579                 $nameValueArray['user_currency_id'] = self::$helperObject->get_name_value('user_currency_id', $cur_id);
580                 $currencyObject = new Currency();
581                 $currencyObject->retrieve($cur_id);
582                 $nameValueArray['user_currency_name'] = self::$helperObject->get_name_value('user_currency_name', $currencyObject->name);
583                 $_SESSION['user_language'] = $current_language;
584                 return array('id'=>session_id(), 'module_name'=>'Users', 'name_value_list'=>$nameValueArray);
585 } // if
586         LogicHook::initialize();
587         $GLOBALS['logic_hook']->call_custom_logic('Users', 'login_failed');
588         $error->set_error('invalid_login');
589         self::$helperObject->setFaultObject($error);
590         $GLOBALS['log']->info('End: SugarWebServiceImpl->login - failed login');
591 }
592
593 /**
594  * Log out of the session.  This will destroy the session and prevent other's from using it.
595  *
596  * @param String $session -- Session ID returned by a previous call to login.
597  * @return Empty
598  * @exception 'SoapFault' -- The SOAP error, if any
599  */
600 function logout($session){
601         global $current_user;
602
603         $GLOBALS['log']->info('Begin: SugarWebServiceImpl->logout');
604         $error = new SoapError();
605         LogicHook::initialize();
606         if (!self::$helperObject->checkSessionAndModuleAccess($session, 'invalid_session', '', '', '', $error)) {
607                 $GLOBALS['logic_hook']->call_custom_logic('Users', 'after_logout');
608                 $GLOBALS['log']->info('End: SugarWebServiceImpl->logout');
609                 return;
610         } // if
611
612         $current_user->call_custom_logic('before_logout');
613         session_destroy();
614         $GLOBALS['logic_hook']->call_custom_logic('Users', 'after_logout');
615         $GLOBALS['log']->info('End: SugarWebServiceImpl->logout');
616 } // fn
617
618 /**
619  * Gets server info. This will return information like version, flavor and gmt_time.
620  * @return Array - flavor - String - Retrieve the specific flavor of sugar.
621  *                               - version - String - Retrieve the version number of Sugar that the server is running.
622  *                               - gmt_time - String - Return the current time on the server in the format 'Y-m-d H:i:s'. This time is in GMT.
623  * @exception 'SoapFault' -- The SOAP error, if any
624  */
625 function get_server_info(){
626         $GLOBALS['log']->info('Begin: SugarWebServiceImpl->get_server_info');
627         global $sugar_flavor;
628         require_once('sugar_version.php');
629         require_once('modules/Administration/Administration.php');
630
631         $admin  = new Administration();
632         $admin->retrieveSettings('info');
633         $sugar_version = '';
634         if(isset($admin->settings['info_sugar_version'])){
635                 $sugar_version = $admin->settings['info_sugar_version'];
636         }else{
637                 $sugar_version = '1.0';
638         }
639
640         $GLOBALS['log']->info('End: SugarWebServiceImpl->get_server_info');
641         return array('flavor' => $sugar_flavor, 'version' => $sugar_version, 'gmt_time' => TimeDate::getInstance()->nowDb());
642 } // fn
643
644 /**
645  * Return the user_id of the user that is logged into the current session.
646  *
647  * @param String $session -- Session ID returned by a previous call to login.
648  * @return String -- the User ID of the current session
649  * @exception 'SoapFault' -- The SOAP error, if any
650  */
651 function get_user_id($session){
652         $GLOBALS['log']->info('Begin: SugarWebServiceImpl->get_user_id');
653         $error = new SoapError();
654         if (!self::$helperObject->checkSessionAndModuleAccess($session, 'invalid_session', '', '', '', $error)) {
655                 return;
656         } // if
657         global $current_user;
658         $GLOBALS['log']->info('End: SugarWebServiceImpl->get_user_id');
659         return $current_user->id;
660 } // fn
661
662 /**
663  * Retrieve vardef information on the fields of the specified bean.
664  *
665  * @param String $session -- Session ID returned by a previous call to login.
666  * @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)..
667  * @param Array $fields -- Optional, if passed then retrieve vardef information on these fields only.
668  * @return Array    'module_fields' -- Array - The vardef information on the selected fields.
669  *                  'link_fields' -- Array - The vardef information on the link fields
670  * @exception 'SoapFault' -- The SOAP error, if any
671  */
672 function get_module_fields($session, $module_name, $fields = array()){
673         $GLOBALS['log']->info('Begin: SugarWebServiceImpl->get_module_fields for ' . $module_name);
674         global  $beanList, $beanFiles;
675         $error = new SoapError();
676         $module_fields = array();
677
678         if (!self::$helperObject->checkSessionAndModuleAccess($session, 'invalid_session', $module_name, 'read', 'no_access', $error)) {
679                 $GLOBALS['log']->error('End: SugarWebServiceImpl->get_module_fields FAILED on checkSessionAndModuleAccess for ' . $module_name);
680                 return;
681         } // if
682
683         $class_name = $beanList[$module_name];
684         require_once($beanFiles[$class_name]);
685         $seed = new $class_name();
686         if($seed->ACLAccess('ListView', true) || $seed->ACLAccess('DetailView', true) ||        $seed->ACLAccess('EditView', true) ) {
687         $return = self::$helperObject->get_return_module_fields($seed, $module_name, $fields);
688         $GLOBALS['log']->info('End: SugarWebServiceImpl->get_module_fields SUCCESS for ' . $module_name);
689         return $return;
690     }
691     $error->set_error('no_access');
692         self::$helperObject->setFaultObject($error);
693     $GLOBALS['log']->error('End: SugarWebServiceImpl->get_module_fields FAILED NO ACCESS to ListView, DetailView or EditView for ' . $module_name);
694 }
695
696 /**
697  * Perform a seamless login. This is used internally during the sync process.
698  *
699  * @param String $session -- Session ID returned by a previous call to login.
700  * @return 1 -- integer - if the session was authenticated
701  * @return 0 -- integer - if the session could not be authenticated
702  */
703 function seamless_login($session){
704         $GLOBALS['log']->info('Begin: SugarWebServiceImpl->seamless_login');
705         if(!self::$helperObject->validate_authenticated($session)){
706                 return 0;
707         }
708         $_SESSION['seamless_login'] = true;
709         $GLOBALS['log']->info('End: SugarWebServiceImpl->seamless_login');
710         return 1;
711 }
712
713 /**
714  * Add or replace the attachment on a Note.
715  * Optionally you can set the relationship of this note to Accounts/Contacts and so on by setting related_module_id, related_module_name
716  *
717  * @param String $session -- Session ID returned by a previous call to login.
718  * @param Array 'note' -- Array String 'id' -- The ID of the Note containing the attachment
719  *                              String 'filename' -- The file name of the attachment
720  *                              Binary 'file' -- The binary contents of the file.
721  *                                                              String 'related_module_id' -- module id to which this note to related to
722  *                                                              String 'related_module_name' - module name to which this note to related to
723  *
724  * @return Array 'id' -- String - The ID of the Note
725  * @exception 'SoapFault' -- The SOAP error, if any
726  */
727 function set_note_attachment($session, $note) {
728         $GLOBALS['log']->info('Begin: SugarWebServiceImpl->set_note_attachment');
729         $error = new SoapError();
730         $module_name = '';
731         $module_access = '';
732         $module_id = '';
733         if (!empty($note['related_module_id']) && !empty($note['related_module_name'])) {
734                 $module_name = $note['related_module_name'];
735                 $module_id = $note['related_module_id'];
736                 $module_access = 'read';
737         }
738         if (!self::$helperObject->checkSessionAndModuleAccess($session, 'invalid_session', $module_name, $module_access, 'no_access', $error)) {
739                 $GLOBALS['log']->info('End: SugarWebServiceImpl->set_note_attachment');
740                 return;
741         } // if
742
743         require_once('modules/Notes/NoteSoap.php');
744         $ns = new NoteSoap();
745         $GLOBALS['log']->info('End: SugarWebServiceImpl->set_note_attachment');
746         return array('id'=>$ns->newSaveFile($note));
747 } // fn
748
749 /**
750  * Retrieve an attachment from a note
751  * @param String $session -- Session ID returned by a previous call to login.
752  * @param String $id -- The ID of the appropriate Note.
753  * @return Array 'note_attachment' -- Array String 'id' -- The ID of the Note containing the attachment
754  *                                          String 'filename' -- The file name of the attachment
755  *                                          Binary 'file' -- The binary contents of the file.
756  *                                                                                      String 'related_module_id' -- module id to which this note is related
757  *                                                                                      String 'related_module_name' - module name to which this note is related
758  * @exception 'SoapFault' -- The SOAP error, if any
759  */
760 function get_note_attachment($session,$id) {
761         $GLOBALS['log']->info('Begin: SugarWebServiceImpl->get_note_attachment');
762         $error = new SoapError();
763         if (!self::$helperObject->checkSessionAndModuleAccess($session, 'invalid_session', '', '', '', $error)) {
764                 $GLOBALS['log']->info('End: SugarWebServiceImpl->get_note_attachment');
765                 return;
766         } // if
767         require_once('modules/Notes/Note.php');
768         $note = new Note();
769
770         $note->retrieve($id);
771     if (!self::$helperObject->checkACLAccess($note, 'DetailView', $error, 'no_access')) {
772                 $GLOBALS['log']->info('End: SugarWebServiceImpl->get_note_attachment');
773         return;
774     } // if
775
776         require_once('modules/Notes/NoteSoap.php');
777         $ns = new NoteSoap();
778         if(!isset($note->filename)){
779                 $note->filename = '';
780         }
781         $file= $ns->retrieveFile($id,$note->filename);
782         if($file == -1){
783                 $file = '';
784         }
785
786         $GLOBALS['log']->info('End: SugarWebServiceImpl->get_note_attachment');
787         return array('note_attachment'=>array('id'=>$id, 'filename'=>$note->filename, 'file'=>$file, 'related_module_id' => $note->parent_id, 'related_module_name' => $note->parent_type));
788
789 } // fn
790
791 /**
792  * sets a new revision for this document
793  *
794  * @param String $session -- Session ID returned by a previous call to login.
795  * @param Array $document_revision -- Array String 'id' --      The ID of the document object
796  *                                                                                      String 'document_name' - The name of the document
797  *                                                                                      String 'revision' - The revision value for this revision
798  *                                              String 'filename' -- The file name of the attachment
799  *                                          String 'file' -- The binary contents of the file.
800  * @return Array - 'id' - String - document revision id
801  * @exception 'SoapFault' -- The SOAP error, if any
802  */
803 function set_document_revision($session, $document_revision) {
804         $GLOBALS['log']->info('Begin: SugarWebServiceImpl->set_document_revision');
805         $error = new SoapError();
806         if (!self::$helperObject->checkSessionAndModuleAccess($session, 'invalid_session', '', '', '', $error)) {
807                 $GLOBALS['log']->info('End: SugarWebServiceImpl->set_document_revision');
808                 return;
809         } // if
810
811         require_once('modules/Documents/DocumentSoap.php');
812         $dr = new DocumentSoap();
813         $GLOBALS['log']->info('End: SugarWebServiceImpl->set_document_revision');
814         return array('id'=>$dr->saveFile($document_revision));
815 }
816
817 /**
818  * This method is used as a result of the .htaccess lock down on the cache directory. It will allow a
819  * properly authenticated user to download a document that they have proper rights to download.
820  *
821  * @param String $session -- Session ID returned by a previous call to login.
822  * @param String $id      -- ID of the document revision to obtain
823  * @return new_return_document_revision - Array String 'id' -- The ID of the document revision containing the attachment
824  *                                                                                              String document_name - The name of the document
825  *                                                                                              String revision - The revision value for this revision
826  *                                                      String 'filename' -- The file name of the attachment
827  *                                              Binary 'file' -- The binary contents of the file.
828  * @exception 'SoapFault' -- The SOAP error, if any
829  */
830 function get_document_revision($session, $id) {
831         $GLOBALS['log']->info('Begin: SugarWebServiceImpl->get_document_revision');
832     global $sugar_config;
833
834     $error = new SoapError();
835         if (!self::$helperObject->checkSessionAndModuleAccess($session, 'invalid_session', '', '', '', $error)) {
836                 $GLOBALS['log']->info('End: SugarWebServiceImpl->get_document_revision');
837                 return;
838         } // if
839
840     require_once('modules/DocumentRevisions/DocumentRevision.php');
841     $dr = new DocumentRevision();
842     $dr->retrieve($id);
843     if(!empty($dr->filename)){
844         $filename = "upload://{$dr->id}";
845         if (filesize($filename) > 0) {
846                 $contents = sugar_file_get_contents($filename);
847         } else {
848             $contents = '';
849         }
850         $contents = base64_encode($contents);
851         $GLOBALS['log']->info('End: SugarWebServiceImpl->get_document_revision');
852         return array('document_revision'=>array('id' => $dr->id, 'document_name' => $dr->document_name, 'revision' => $dr->revision, 'filename' => $dr->filename, 'file' => $contents));
853     }else{
854         $error->set_error('no_records');
855         self::$helperObject->setFaultObject($error);
856                 $GLOBALS['log']->info('End: SugarWebServiceImpl->get_document_revision');
857     }
858
859 }
860
861 /**
862  * Given a list of modules to search and a search string, return the id, module_name, along with the fields
863  * We will support Accounts, Bug Tracker, Cases, Contacts, Leads, Opportunities, Project, ProjectTask, Quotes
864  *
865  * @param string $session                       - Session ID returned by a previous call to login.
866  * @param string $search_string         - string to search
867  * @param string[] $modules                     - array of modules to query
868  * @param int $offset                           - a specified offset in the query
869  * @param int $max_results                      - max number of records to return
870  * @return Array return_search_result   - Array('Accounts' => array(array('name' => 'first_name', 'value' => 'John', 'name' => 'last_name', 'value' => 'Do')))
871  * @exception 'SoapFault' -- The SOAP error, if any
872  */
873 function search_by_module($session, $search_string, $modules, $offset, $max_results){
874         $GLOBALS['log']->info('Begin: SugarWebServiceImpl->search_by_module');
875         global  $beanList, $beanFiles;
876         global $sugar_config,$current_language;
877
878         $error = new SoapError();
879         $output_list = array();
880         if (!self::$helperObject->checkSessionAndModuleAccess($session, 'invalid_session', '', '', '', $error)) {
881                 $error->set_error('invalid_login');
882                 $GLOBALS['log']->info('End: SugarWebServiceImpl->search_by_module');
883                 return;
884         }
885         global $current_user;
886         if($max_results > 0){
887                 $sugar_config['list_max_entries_per_page'] = $max_results;
888         }
889
890         require_once('modules/Home/UnifiedSearchAdvanced.php');
891         require_once 'include/utils.php';
892         $usa = new UnifiedSearchAdvanced();
893     if(!file_exists($cachedfile = sugar_cached('modules/unified_search_modules.php'))) {
894         $usa->buildCache();
895     }
896
897         include($cachedfile);
898         $modules_to_search = array();
899         $unified_search_modules['Users'] =   array('fields' => array());
900
901         $unified_search_modules['ProjectTask'] =   array('fields' => array());
902
903     foreach($unified_search_modules as $module=>$data) {
904         if (in_array($module, $modules)) {
905                 $modules_to_search[$module] = $beanList[$module];
906         } // if
907     } // foreach
908
909     $GLOBALS['log']->info('SugarWebServiceImpl->search_by_module - search string = ' . $search_string);
910
911         if(!empty($search_string) && isset($search_string)) {
912                 $search_string = trim($GLOBALS['db']->quote(securexss(from_html(clean_string($search_string, 'UNIFIED_SEARCH')))));
913         foreach($modules_to_search as $name => $beanName) {
914                 $where_clauses_array = array();
915                         $unifiedSearchFields = array () ;
916                         foreach ($unified_search_modules[$name]['fields'] as $field=>$def ) {
917                                 $unifiedSearchFields[$name] [ $field ] = $def ;
918                                 $unifiedSearchFields[$name] [ $field ]['value'] = $search_string;
919                         }
920
921                         require_once $beanFiles[$beanName] ;
922                         $seed = new $beanName();
923                         require_once 'include/SearchForm/SearchForm2.php' ;
924                         if ($beanName == "User"
925                             || $beanName == "ProjectTask"
926                             ) {
927                                 if(!self::$helperObject->check_modules_access($current_user, $seed->module_dir, 'read')){
928                                         continue;
929                                 } // if
930                                 if(!$seed->ACLAccess('ListView')) {
931                                         continue;
932                                 } // if
933                         }
934
935                         if ($beanName != "User"
936                             && $beanName != "ProjectTask"
937                             ) {
938                                 $searchForm = new SearchForm ($seed, $name ) ;
939
940                                 $searchForm->setup(array ($name => array()) ,$unifiedSearchFields , '' , 'saved_views' /* hack to avoid setup doing further unwanted processing */ ) ;
941                                 $where_clauses = $searchForm->generateSearchWhere() ;
942                                 require_once 'include/SearchForm/SearchForm2.php' ;
943                                 $searchForm = new SearchForm ($seed, $name ) ;
944
945                                 $searchForm->setup(array ($name => array()) ,$unifiedSearchFields , '' , 'saved_views' /* hack to avoid setup doing further unwanted processing */ ) ;
946                                 $where_clauses = $searchForm->generateSearchWhere() ;
947                                 $emailQuery = false;
948
949                                 $where = '';
950                                 if (count($where_clauses) > 0 ) {
951                                         $where = '('. implode(' ) OR ( ', $where_clauses) . ')';
952                                 }
953
954                                 $mod_strings = return_module_language($current_language, $seed->module_dir);
955                                 if(file_exists('custom/modules/'.$seed->module_dir.'/metadata/listviewdefs.php')){
956                                         require_once('custom/modules/'.$seed->module_dir.'/metadata/listviewdefs.php');
957                                 }else{
958                                         require_once('modules/'.$seed->module_dir.'/metadata/listviewdefs.php');
959                                 }
960                     $filterFields = array();
961                                 foreach($listViewDefs[$seed->module_dir] as $colName => $param) {
962                         if(!empty($param['default']) && $param['default'] == true) {
963                             $filterFields[] = strtolower($colName);
964                         } // if
965                     } // foreach
966
967                     if (!in_array('id', $filterFields)) {
968                         $filterFields[] = 'id';
969                     } // if
970                                 $ret_array = $seed->create_new_list_query('', $where, $filterFields, array(), 0, '', true, $seed, true);
971                         if(empty($params) or !is_array($params)) $params = array();
972                         if(!isset($params['custom_select'])) $params['custom_select'] = '';
973                         if(!isset($params['custom_from'])) $params['custom_from'] = '';
974                         if(!isset($params['custom_where'])) $params['custom_where'] = '';
975                         if(!isset($params['custom_order_by'])) $params['custom_order_by'] = '';
976                                 $main_query = $ret_array['select'] . $params['custom_select'] . $ret_array['from'] . $params['custom_from'] . $ret_array['where'] . $params['custom_where'] . $ret_array['order_by'] . $params['custom_order_by'];
977                         } else {
978                                 if ($beanName == "User") {
979                                         $filterFields = array('id', 'user_name', 'first_name', 'last_name', 'email_address');
980                                         $main_query = "select users.id, ea.email_address, users.user_name, first_name, last_name from users ";
981                                         $main_query = $main_query . " LEFT JOIN email_addr_bean_rel eabl ON eabl.bean_module = '{$seed->module_dir}'
982 LEFT JOIN email_addresses ea ON (ea.id = eabl.email_address_id) ";
983                                         $main_query = $main_query . "where ((users.first_name like '{$search_string}') or (users.last_name like '{$search_string}') or (users.user_name like '{$search_string}') or (ea.email_address like '{$search_string}')) and users.deleted = 0 and users.is_group = 0 and users.employee_status = 'Active'";
984                                 } // if
985                                 if ($beanName == "ProjectTask") {
986                                         $filterFields = array('id', 'name', 'project_id', 'project_name');
987                                         $main_query = "select {$seed->table_name}.project_task_id id,{$seed->table_name}.project_id, {$seed->table_name}.name, project.name project_name from {$seed->table_name} ";
988                                         $seed->add_team_security_where_clause($main_query);
989                                         $main_query .= "LEFT JOIN teams ON $seed->table_name.team_id=teams.id AND (teams.deleted=0) ";
990                             $main_query .= "LEFT JOIN project ON $seed->table_name.project_id = project.id ";
991                             $main_query .= "where {$seed->table_name}.name like '{$search_string}%'";
992                                 } // if
993                         } // else
994
995                         $GLOBALS['log']->info('SugarWebServiceImpl->search_by_module - query = ' . $main_query);
996                         if($max_results < -1) {
997                                 $result = $seed->db->query($main_query);
998                         }
999                         else {
1000                                 if($max_results == -1) {
1001                                         $limit = $sugar_config['list_max_entries_per_page'];
1002                     } else {
1003                         $limit = $max_results;
1004                     }
1005                     $result = $seed->db->limitQuery($main_query, $offset, $limit + 1);
1006                         }
1007
1008                         $rowArray = array();
1009                         while($row = $seed->db->fetchByAssoc($result)) {
1010                                 $nameValueArray = array();
1011                                 foreach ($filterFields as $field) {
1012                                         $nameValue = array();
1013                                         if (isset($row[$field])) {
1014                                                 $nameValueArray[$field] = self::$helperObject->get_name_value($field, $row[$field]);
1015                                         } // if
1016                                 } // foreach
1017                                 $rowArray[] = $nameValueArray;
1018                         } // while
1019                         $output_list[] = array('name' => $name, 'records' => $rowArray);
1020         } // foreach
1021
1022         $GLOBALS['log']->info('End: SugarWebServiceImpl->search_by_module');
1023         return array('entry_list'=>$output_list);
1024         } // if
1025         return array('entry_list'=>$output_list);
1026 } // fn
1027
1028
1029 /**
1030  * Retrieve the list of available modules on the system available to the currently logged in user.
1031  *
1032  * @param String $session -- Session ID returned by a previous call to login.
1033  * @return Array    'modules' -- Array - An array of module names
1034  * @exception 'SoapFault' -- The SOAP error, if any
1035  */
1036 function get_available_modules($session){
1037         $GLOBALS['log']->info('Begin: SugarWebServiceImpl->get_available_modules');
1038
1039         $error = new SoapError();
1040         if (!self::$helperObject->checkSessionAndModuleAccess($session, 'invalid_session', '', '', '', $error)) {
1041                 $error->set_error('invalid_login');
1042                 $GLOBALS['log']->info('End: SugarWebServiceImpl->get_available_modules');
1043                 return;
1044         } // if
1045
1046         $modules = array();
1047         $modules = array_keys($_SESSION['avail_modules']);
1048
1049         $GLOBALS['log']->info('End: SugarWebServiceImpl->get_available_modules');
1050         return array('modules'=> $modules);
1051 } // fn
1052
1053
1054 /**
1055 *   Once we have successfuly done a mail merge on a campaign, we need to notify Sugar of the targets
1056 *   and the campaign_id for tracking purposes
1057 *
1058 * @param String session  -- Session ID returned by a previous call to login.
1059 * @param Array targets   -- a string array of ids identifying the targets used in the merge
1060 * @param String campaign_id  --  the campaign_id used for the merge
1061 * @return - No output
1062 *
1063 * @exception 'SoapFault' -- The SOAP error, if any
1064 */
1065 function set_campaign_merge($session,$targets, $campaign_id){
1066         $GLOBALS['log']->info('Begin: SugarWebServiceImpl->set_campaign_merge');
1067
1068         $error = new SoapError();
1069         if (!self::$helperObject->checkSessionAndModuleAccess($session, 'invalid_session', '', '', '', $error)) {
1070                 $error->set_error('invalid_login');
1071                 $GLOBALS['log']->info('End: SugarWebServiceImpl->set_campaign_merge');
1072                 return;
1073         } // if
1074     if (empty($campaign_id) or !is_array($targets) or count($targets) == 0) {
1075                 $error->set_error('invalid_set_campaign_merge_data');
1076                 self::$helperObject->setFaultObject($error);
1077         $GLOBALS['log']->debug('set_campaign_merge: Merge action status will not be updated, because, campaign_id is null or no targets were selected.');
1078                 $GLOBALS['log']->info('End: SugarWebServiceImpl->set_campaign_merge');
1079                 return;
1080     } else {
1081         require_once('modules/Campaigns/utils.php');
1082         campaign_log_mail_merge($campaign_id,$targets);
1083     } // else
1084 } // fn
1085 /**
1086 *   Retrieve number of records in a given module
1087 *
1088 * @param String session      -- Session ID returned by a previous call to login.
1089 * @param String module_name  -- module to retrieve number of records from
1090 * @param String query        -- allows webservice user to provide a WHERE clause
1091 * @param int deleted         -- specify whether or not to include deleted records
1092 *
1093 * @return Array  result_count - integer - Total number of records for a given module and query
1094 * @exception 'SoapFault' -- The SOAP error, if any
1095 */
1096 function get_entries_count($session, $module_name, $query, $deleted) {
1097         $GLOBALS['log']->info('Begin: SugarWebServiceImpl->get_entries_count');
1098
1099         $error = new SoapError();
1100         if (!self::$helperObject->checkSessionAndModuleAccess($session, 'invalid_session', $module_name, 'list', 'no_access', $error)) {
1101                 $GLOBALS['log']->info('End: SugarWebServiceImpl->get_entries_count');
1102                 return;
1103         } // if
1104
1105         global $beanList, $beanFiles, $current_user;
1106
1107         $class_name = $beanList[$module_name];
1108         require_once($beanFiles[$class_name]);
1109         $seed = new $class_name();
1110
1111     if (!self::$helperObject->checkACLAccess($seed, 'ListView', $error, 'no_access')) {
1112         return;
1113     }
1114
1115         $sql = 'SELECT COUNT(*) result_count FROM ' . $seed->table_name . ' ';
1116
1117
1118         // build WHERE clauses, if any
1119         $where_clauses = array();
1120         if (!empty($query)) {
1121                 $where_clauses[] = $query;
1122         }
1123         if ($deleted == 0) {
1124                 $where_clauses[] = $seed->table_name . '.deleted = 0';
1125         }
1126
1127         // if WHERE clauses exist, add them to query
1128         if (!empty($where_clauses)) {
1129                 $sql .= ' WHERE ' . implode(' AND ', $where_clauses);
1130         }
1131
1132         $res = $GLOBALS['db']->query($sql);
1133         $row = $GLOBALS['db']->fetchByAssoc($res);
1134
1135         $GLOBALS['log']->info('End: SugarWebServiceImpl->get_entries_count');
1136         return array(
1137                 'result_count' => $row['result_count'],
1138         );
1139 }
1140
1141
1142
1143 } // clazz
1144