]> CyberLeo.Net >> Repos - Github/sugarcrm.git/blob - service/core/SugarWebServiceImpl.php
Release 6.2.0
[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');
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']->info('End: SugarWebServiceImpl->get_module_fields');
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     }
689     $error->set_error('no_access');
690         self::$helperObject->setFaultObject($error);
691         $GLOBALS['log']->info('End: SugarWebServiceImpl->get_module_fields');
692 }
693
694 /**
695  * Perform a seamless login. This is used internally during the sync process.
696  *
697  * @param String $session -- Session ID returned by a previous call to login.
698  * @return 1 -- integer - if the session was authenticated
699  * @return 0 -- integer - if the session could not be authenticated
700  */
701 function seamless_login($session){
702         $GLOBALS['log']->info('Begin: SugarWebServiceImpl->seamless_login');
703         if(!self::$helperObject->validate_authenticated($session)){
704                 return 0;
705         }
706         $_SESSION['seamless_login'] = true;
707         $GLOBALS['log']->info('End: SugarWebServiceImpl->seamless_login');
708         return 1;
709 }
710
711 /**
712  * Add or replace the attachment on a Note.
713  * Optionally you can set the relationship of this note to Accounts/Contacts and so on by setting related_module_id, related_module_name
714  *
715  * @param String $session -- Session ID returned by a previous call to login.
716  * @param Array 'note' -- Array String 'id' -- The ID of the Note containing the attachment
717  *                              String 'filename' -- The file name of the attachment
718  *                              Binary 'file' -- The binary contents of the file.
719  *                                                              String 'related_module_id' -- module id to which this note to related to
720  *                                                              String 'related_module_name' - module name to which this note to related to
721  *
722  * @return Array 'id' -- String - The ID of the Note
723  * @exception 'SoapFault' -- The SOAP error, if any
724  */
725 function set_note_attachment($session, $note) {
726         $GLOBALS['log']->info('Begin: SugarWebServiceImpl->set_note_attachment');
727         $error = new SoapError();
728         $module_name = '';
729         $module_access = '';
730         $module_id = '';
731         if (!empty($note['related_module_id']) && !empty($note['related_module_name'])) {
732                 $module_name = $note['related_module_name'];
733                 $module_id = $note['related_module_id'];
734                 $module_access = 'read';
735         }
736         if (!self::$helperObject->checkSessionAndModuleAccess($session, 'invalid_session', $module_name, $module_access, 'no_access', $error)) {
737                 $GLOBALS['log']->info('End: SugarWebServiceImpl->set_note_attachment');
738                 return;
739         } // if
740
741         require_once('modules/Notes/NoteSoap.php');
742         $ns = new NoteSoap();
743         $GLOBALS['log']->info('End: SugarWebServiceImpl->set_note_attachment');
744         return array('id'=>$ns->newSaveFile($note));
745 } // fn
746
747 /**
748  * Retrieve an attachment from a note
749  * @param String $session -- Session ID returned by a previous call to login.
750  * @param String $id -- The ID of the appropriate Note.
751  * @return Array 'note_attachment' -- Array String 'id' -- The ID of the Note containing the attachment
752  *                                          String 'filename' -- The file name of the attachment
753  *                                          Binary 'file' -- The binary contents of the file.
754  *                                                                                      String 'related_module_id' -- module id to which this note is related
755  *                                                                                      String 'related_module_name' - module name to which this note is related
756  * @exception 'SoapFault' -- The SOAP error, if any
757  */
758 function get_note_attachment($session,$id) {
759         $GLOBALS['log']->info('Begin: SugarWebServiceImpl->get_note_attachment');
760         $error = new SoapError();
761         if (!self::$helperObject->checkSessionAndModuleAccess($session, 'invalid_session', '', '', '', $error)) {
762                 $GLOBALS['log']->info('End: SugarWebServiceImpl->get_note_attachment');
763                 return;
764         } // if
765         require_once('modules/Notes/Note.php');
766         $note = new Note();
767
768         $note->retrieve($id);
769     if (!self::$helperObject->checkACLAccess($note, 'DetailView', $error, 'no_access')) {
770                 $GLOBALS['log']->info('End: SugarWebServiceImpl->get_note_attachment');
771         return;
772     } // if
773
774         require_once('modules/Notes/NoteSoap.php');
775         $ns = new NoteSoap();
776         if(!isset($note->filename)){
777                 $note->filename = '';
778         }
779         $file= $ns->retrieveFile($id,$note->filename);
780         if($file == -1){
781                 $file = '';
782         }
783
784         $GLOBALS['log']->info('End: SugarWebServiceImpl->get_note_attachment');
785         return array('note_attachment'=>array('id'=>$id, 'filename'=>$note->filename, 'file'=>$file, 'related_module_id' => $note->parent_id, 'related_module_name' => $note->parent_type));
786
787 } // fn
788
789 /**
790  * sets a new revision for this document
791  *
792  * @param String $session -- Session ID returned by a previous call to login.
793  * @param Array $document_revision -- Array String 'id' --      The ID of the document object
794  *                                                                                      String 'document_name' - The name of the document
795  *                                                                                      String 'revision' - The revision value for this revision
796  *                                              String 'filename' -- The file name of the attachment
797  *                                          String 'file' -- The binary contents of the file.
798  * @return Array - 'id' - String - document revision id
799  * @exception 'SoapFault' -- The SOAP error, if any
800  */
801 function set_document_revision($session, $document_revision) {
802         $GLOBALS['log']->info('Begin: SugarWebServiceImpl->set_document_revision');
803         $error = new SoapError();
804         if (!self::$helperObject->checkSessionAndModuleAccess($session, 'invalid_session', '', '', '', $error)) {
805                 $GLOBALS['log']->info('End: SugarWebServiceImpl->set_document_revision');
806                 return;
807         } // if
808
809         require_once('modules/Documents/DocumentSoap.php');
810         $dr = new DocumentSoap();
811         $GLOBALS['log']->info('End: SugarWebServiceImpl->set_document_revision');
812         return array('id'=>$dr->saveFile($document_revision));
813 }
814
815 /**
816  * This method is used as a result of the .htaccess lock down on the cache directory. It will allow a
817  * properly authenticated user to download a document that they have proper rights to download.
818  *
819  * @param String $session -- Session ID returned by a previous call to login.
820  * @param String $id      -- ID of the document revision to obtain
821  * @return new_return_document_revision - Array String 'id' -- The ID of the document revision containing the attachment
822  *                                                                                              String document_name - The name of the document
823  *                                                                                              String revision - The revision value for this revision
824  *                                                      String 'filename' -- The file name of the attachment
825  *                                              Binary 'file' -- The binary contents of the file.
826  * @exception 'SoapFault' -- The SOAP error, if any
827  */
828 function get_document_revision($session, $id) {
829         $GLOBALS['log']->info('Begin: SugarWebServiceImpl->get_document_revision');
830     global $sugar_config;
831
832     $error = new SoapError();
833         if (!self::$helperObject->checkSessionAndModuleAccess($session, 'invalid_session', '', '', '', $error)) {
834                 $GLOBALS['log']->info('End: SugarWebServiceImpl->get_document_revision');
835                 return;
836         } // if
837
838     require_once('modules/DocumentRevisions/DocumentRevision.php');
839     $dr = new DocumentRevision();
840     $dr->retrieve($id);
841     if(!empty($dr->filename)){
842         $filename = $sugar_config['upload_dir']."/".$dr->id;
843         if (filesize($filename) > 0) {
844                 $contents = sugar_file_get_contents($filename);
845         } else {
846             $contents = '';
847         }
848         $contents = base64_encode($contents);
849         $GLOBALS['log']->info('End: SugarWebServiceImpl->get_document_revision');
850         return array('document_revision'=>array('id' => $dr->id, 'document_name' => $dr->document_name, 'revision' => $dr->revision, 'filename' => $dr->filename, 'file' => $contents));
851     }else{
852         $error->set_error('no_records');
853         self::$helperObject->setFaultObject($error);
854                 $GLOBALS['log']->info('End: SugarWebServiceImpl->get_document_revision');
855     }
856
857 }
858
859 /**
860  * Given a list of modules to search and a search string, return the id, module_name, along with the fields
861  * We will support Accounts, Bug Tracker, Cases, Contacts, Leads, Opportunities, Project, ProjectTask, Quotes
862  *
863  * @param string $session                       - Session ID returned by a previous call to login.
864  * @param string $search_string         - string to search
865  * @param string[] $modules                     - array of modules to query
866  * @param int $offset                           - a specified offset in the query
867  * @param int $max_results                      - max number of records to return
868  * @return Array return_search_result   - Array('Accounts' => array(array('name' => 'first_name', 'value' => 'John', 'name' => 'last_name', 'value' => 'Do')))
869  * @exception 'SoapFault' -- The SOAP error, if any
870  */
871 function search_by_module($session, $search_string, $modules, $offset, $max_results){
872         $GLOBALS['log']->info('Begin: SugarWebServiceImpl->search_by_module');
873         global  $beanList, $beanFiles;
874         global $sugar_config,$current_language;
875
876         $error = new SoapError();
877         $output_list = array();
878         if (!self::$helperObject->checkSessionAndModuleAccess($session, 'invalid_session', '', '', '', $error)) {
879                 $error->set_error('invalid_login');
880                 $GLOBALS['log']->info('End: SugarWebServiceImpl->search_by_module');
881                 return;
882         }
883         global $current_user;
884         if($max_results > 0){
885                 $sugar_config['list_max_entries_per_page'] = $max_results;
886         }
887
888         require_once('modules/Home/UnifiedSearchAdvanced.php');
889         require_once 'include/utils.php';
890         $usa = new UnifiedSearchAdvanced();
891     if(!file_exists($GLOBALS['sugar_config']['cache_dir'].'modules/unified_search_modules.php')) {
892         $usa->buildCache();
893     }
894
895         include($GLOBALS['sugar_config']['cache_dir'].'modules/unified_search_modules.php');
896         $modules_to_search = array();
897         $unified_search_modules['Users'] =   array('fields' => array());
898
899         $unified_search_modules['ProjectTask'] =   array('fields' => array());
900
901     foreach($unified_search_modules as $module=>$data) {
902         if (in_array($module, $modules)) {
903                 $modules_to_search[$module] = $beanList[$module];
904         } // if
905     } // foreach
906
907     $GLOBALS['log']->info('SugarWebServiceImpl->search_by_module - search string = ' . $search_string);
908
909         if(!empty($search_string) && isset($search_string)) {
910                 $search_string = trim($GLOBALS['db']->quote(securexss(from_html(clean_string($search_string, 'UNIFIED_SEARCH')))));
911         foreach($modules_to_search as $name => $beanName) {
912                 $where_clauses_array = array();
913                         $unifiedSearchFields = array () ;
914                         foreach ($unified_search_modules[$name]['fields'] as $field=>$def ) {
915                                 $unifiedSearchFields[$name] [ $field ] = $def ;
916                                 $unifiedSearchFields[$name] [ $field ]['value'] = $search_string;
917                         }
918
919                         require_once $beanFiles[$beanName] ;
920                         $seed = new $beanName();
921                         require_once 'include/SearchForm/SearchForm2.php' ;
922                         if ($beanName == "User"
923                             || $beanName == "ProjectTask"
924                             ) {
925                                 if(!self::$helperObject->check_modules_access($current_user, $seed->module_dir, 'read')){
926                                         continue;
927                                 } // if
928                                 if(!$seed->ACLAccess('ListView')) {
929                                         continue;
930                                 } // if
931                         }
932
933                         if ($beanName != "User"
934                             && $beanName != "ProjectTask"
935                             ) {
936                                 $searchForm = new SearchForm ($seed, $name ) ;
937
938                                 $searchForm->setup(array ($name => array()) ,$unifiedSearchFields , '' , 'saved_views' /* hack to avoid setup doing further unwanted processing */ ) ;
939                                 $where_clauses = $searchForm->generateSearchWhere() ;
940                                 require_once 'include/SearchForm/SearchForm2.php' ;
941                                 $searchForm = new SearchForm ($seed, $name ) ;
942
943                                 $searchForm->setup(array ($name => array()) ,$unifiedSearchFields , '' , 'saved_views' /* hack to avoid setup doing further unwanted processing */ ) ;
944                                 $where_clauses = $searchForm->generateSearchWhere() ;
945                                 $emailQuery = false;
946
947                                 $where = '';
948                                 if (count($where_clauses) > 0 ) {
949                                         $where = '('. implode(' ) OR ( ', $where_clauses) . ')';
950                                 }
951
952                                 $mod_strings = return_module_language($current_language, $seed->module_dir);
953                                 if(file_exists('custom/modules/'.$seed->module_dir.'/metadata/listviewdefs.php')){
954                                         require_once('custom/modules/'.$seed->module_dir.'/metadata/listviewdefs.php');
955                                 }else{
956                                         require_once('modules/'.$seed->module_dir.'/metadata/listviewdefs.php');
957                                 }
958                     $filterFields = array();
959                                 foreach($listViewDefs[$seed->module_dir] as $colName => $param) {
960                         if(!empty($param['default']) && $param['default'] == true) {
961                             $filterFields[] = strtolower($colName);
962                         } // if
963                     } // foreach
964
965                     if (!in_array('id', $filterFields)) {
966                         $filterFields[] = 'id';
967                     } // if
968                                 $ret_array = $seed->create_new_list_query('', $where, $filterFields, array(), 0, '', true, $seed, true);
969                         if(empty($params) or !is_array($params)) $params = array();
970                         if(!isset($params['custom_select'])) $params['custom_select'] = '';
971                         if(!isset($params['custom_from'])) $params['custom_from'] = '';
972                         if(!isset($params['custom_where'])) $params['custom_where'] = '';
973                         if(!isset($params['custom_order_by'])) $params['custom_order_by'] = '';
974                                 $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'];
975                         } else {
976                                 if ($beanName == "User") {
977                                         $filterFields = array('id', 'user_name', 'first_name', 'last_name', 'email_address');
978                                         $main_query = "select users.id, ea.email_address, users.user_name, first_name, last_name from users ";
979                                         $main_query = $main_query . " LEFT JOIN email_addr_bean_rel eabl ON eabl.bean_module = '{$seed->module_dir}'
980 LEFT JOIN email_addresses ea ON (ea.id = eabl.email_address_id) ";
981                                         $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'";
982                                 } // if
983                                 if ($beanName == "ProjectTask") {
984                                         $filterFields = array('id', 'name', 'project_id', 'project_name');
985                                         $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} ";
986                                         $seed->add_team_security_where_clause($main_query);
987                                         $main_query .= "LEFT JOIN teams ON $seed->table_name.team_id=teams.id AND (teams.deleted=0) ";
988                             $main_query .= "LEFT JOIN project ON $seed->table_name.project_id = project.id ";
989                             $main_query .= "where {$seed->table_name}.name like '{$search_string}%'";
990                                 } // if
991                         } // else
992
993                         $GLOBALS['log']->info('SugarWebServiceImpl->search_by_module - query = ' . $main_query);
994                         if($max_results < -1) {
995                                 $result = $seed->db->query($main_query);
996                         }
997                         else {
998                                 if($max_results == -1) {
999                                         $limit = $sugar_config['list_max_entries_per_page'];
1000                     } else {
1001                         $limit = $max_results;
1002                     }
1003                     $result = $seed->db->limitQuery($main_query, $offset, $limit + 1);
1004                         }
1005
1006                         $rowArray = array();
1007                         while($row = $seed->db->fetchByAssoc($result)) {
1008                                 $nameValueArray = array();
1009                                 foreach ($filterFields as $field) {
1010                                         $nameValue = array();
1011                                         if (isset($row[$field])) {
1012                                                 $nameValueArray[$field] = self::$helperObject->get_name_value($field, $row[$field]);
1013                                         } // if
1014                                 } // foreach
1015                                 $rowArray[] = $nameValueArray;
1016                         } // while
1017                         $output_list[] = array('name' => $name, 'records' => $rowArray);
1018         } // foreach
1019
1020         $GLOBALS['log']->info('End: SugarWebServiceImpl->search_by_module');
1021         return array('entry_list'=>$output_list);
1022         } // if
1023         return array('entry_list'=>$output_list);
1024 } // fn
1025
1026
1027 /**
1028  * Retrieve the list of available modules on the system available to the currently logged in user.
1029  *
1030  * @param String $session -- Session ID returned by a previous call to login.
1031  * @return Array    'modules' -- Array - An array of module names
1032  * @exception 'SoapFault' -- The SOAP error, if any
1033  */
1034 function get_available_modules($session){
1035         $GLOBALS['log']->info('Begin: SugarWebServiceImpl->get_available_modules');
1036
1037         $error = new SoapError();
1038         if (!self::$helperObject->checkSessionAndModuleAccess($session, 'invalid_session', '', '', '', $error)) {
1039                 $error->set_error('invalid_login');
1040                 $GLOBALS['log']->info('End: SugarWebServiceImpl->get_available_modules');
1041                 return;
1042         } // if
1043
1044         $modules = array();
1045         $modules = array_keys($_SESSION['avail_modules']);
1046
1047         $GLOBALS['log']->info('End: SugarWebServiceImpl->get_available_modules');
1048         return array('modules'=> $modules);
1049 } // fn
1050
1051
1052 /**
1053 *   Once we have successfuly done a mail merge on a campaign, we need to notify Sugar of the targets
1054 *   and the campaign_id for tracking purposes
1055 *
1056 * @param String session  -- Session ID returned by a previous call to login.
1057 * @param Array targets   -- a string array of ids identifying the targets used in the merge
1058 * @param String campaign_id  --  the campaign_id used for the merge
1059 * @return - No output
1060 *
1061 * @exception 'SoapFault' -- The SOAP error, if any
1062 */
1063 function set_campaign_merge($session,$targets, $campaign_id){
1064         $GLOBALS['log']->info('Begin: SugarWebServiceImpl->set_campaign_merge');
1065
1066         $error = new SoapError();
1067         if (!self::$helperObject->checkSessionAndModuleAccess($session, 'invalid_session', '', '', '', $error)) {
1068                 $error->set_error('invalid_login');
1069                 $GLOBALS['log']->info('End: SugarWebServiceImpl->set_campaign_merge');
1070                 return;
1071         } // if
1072     if (empty($campaign_id) or !is_array($targets) or count($targets) == 0) {
1073                 $error->set_error('invalid_set_campaign_merge_data');
1074                 self::$helperObject->setFaultObject($error);
1075         $GLOBALS['log']->debug('set_campaign_merge: Merge action status will not be updated, because, campaign_id is null or no targets were selected.');
1076                 $GLOBALS['log']->info('End: SugarWebServiceImpl->set_campaign_merge');
1077                 return;
1078     } else {
1079         require_once('modules/Campaigns/utils.php');
1080         campaign_log_mail_merge($campaign_id,$targets);
1081     } // else
1082 } // fn
1083 /**
1084 *   Retrieve number of records in a given module
1085 *
1086 * @param String session      -- Session ID returned by a previous call to login.
1087 * @param String module_name  -- module to retrieve number of records from
1088 * @param String query        -- allows webservice user to provide a WHERE clause
1089 * @param int deleted         -- specify whether or not to include deleted records
1090 *
1091 * @return Array  result_count - integer - Total number of records for a given module and query
1092 * @exception 'SoapFault' -- The SOAP error, if any
1093 */
1094 function get_entries_count($session, $module_name, $query, $deleted) {
1095         $GLOBALS['log']->info('Begin: SugarWebServiceImpl->get_entries_count');
1096
1097         $error = new SoapError();
1098         if (!self::$helperObject->checkSessionAndModuleAccess($session, 'invalid_session', $module_name, 'list', 'no_access', $error)) {
1099                 $GLOBALS['log']->info('End: SugarWebServiceImpl->get_entries_count');
1100                 return;
1101         } // if
1102
1103         global $beanList, $beanFiles, $current_user;
1104
1105         $class_name = $beanList[$module_name];
1106         require_once($beanFiles[$class_name]);
1107         $seed = new $class_name();
1108
1109     if (!self::$helperObject->checkACLAccess($seed, 'ListView', $error, 'no_access')) {
1110         return;
1111     }
1112
1113         $sql = 'SELECT COUNT(*) result_count FROM ' . $seed->table_name . ' ';
1114
1115
1116         // build WHERE clauses, if any
1117         $where_clauses = array();
1118         if (!empty($query)) {
1119                 $where_clauses[] = $query;
1120         }
1121         if ($deleted == 0) {
1122                 $where_clauses[] = $seed->table_name . '.deleted = 0';
1123         }
1124
1125         // if WHERE clauses exist, add them to query
1126         if (!empty($where_clauses)) {
1127                 $sql .= ' WHERE ' . implode(' AND ', $where_clauses);
1128         }
1129
1130         $res = $GLOBALS['db']->query($sql);
1131         $row = $GLOBALS['db']->fetchByAssoc($res);
1132
1133         $GLOBALS['log']->info('End: SugarWebServiceImpl->get_entries_count');
1134         return array(
1135                 'result_count' => $row['result_count'],
1136         );
1137 }
1138
1139
1140
1141 } // clazz
1142