]> CyberLeo.Net >> Repos - Github/sugarcrm.git/blob - service/core/SugarWebServiceImpl.php
Release 6.1.4
[Github/sugarcrm.git] / service / core / SugarWebServiceImpl.php
1 <?php
2 if(!defined('sugarEntry'))define('sugarEntry', true);
3 /*********************************************************************************
4  * SugarCRM 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' => gmdate('Y-m-d H:i:s'));
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){
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         $handle = sugar_fopen($filename, "r");
844         $contents = '';
845         if (filesize($filename) > 0) {
846                 $contents = fread($handle, filesize($filename));
847         }
848         fclose($handle);
849         $contents = base64_encode($contents);
850                 $GLOBALS['log']->info('End: SugarWebServiceImpl->get_document_revision');
851         return array('document_revision'=>array('id' => $dr->id, 'document_name' => $dr->document_name, 'revision' => $dr->revision, 'filename' => $dr->filename, 'file' => $contents));
852     }else{
853         $error->set_error('no_records');
854         self::$helperObject->setFaultObject($error);
855                 $GLOBALS['log']->info('End: SugarWebServiceImpl->get_document_revision');
856     }
857
858 }
859
860 /**
861  * Given a list of modules to search and a search string, return the id, module_name, along with the fields
862  * We will support Accounts, Bug Tracker, Cases, Contacts, Leads, Opportunities, Project, ProjectTask, Quotes
863  *
864  * @param string $session                       - Session ID returned by a previous call to login.
865  * @param string $search_string         - string to search
866  * @param string[] $modules                     - array of modules to query
867  * @param int $offset                           - a specified offset in the query
868  * @param int $max_results                      - max number of records to return
869  * @return Array return_search_result   - Array('Accounts' => array(array('name' => 'first_name', 'value' => 'John', 'name' => 'last_name', 'value' => 'Do')))
870  * @exception 'SoapFault' -- The SOAP error, if any
871  */
872 function search_by_module($session, $search_string, $modules, $offset, $max_results){
873         $GLOBALS['log']->info('Begin: SugarWebServiceImpl->search_by_module');
874         global  $beanList, $beanFiles;
875         global $sugar_config,$current_language;
876
877         $error = new SoapError();
878         $output_list = array();
879         if (!self::$helperObject->checkSessionAndModuleAccess($session, 'invalid_session', '', '', '', $error)) {
880                 $error->set_error('invalid_login');
881                 $GLOBALS['log']->info('End: SugarWebServiceImpl->search_by_module');
882                 return;
883         }
884         global $current_user;
885         if($max_results > 0){
886                 $sugar_config['list_max_entries_per_page'] = $max_results;
887         }
888
889         require_once('modules/Home/UnifiedSearchAdvanced.php');
890         require_once 'include/utils.php';
891         $usa = new UnifiedSearchAdvanced();
892     if(!file_exists($GLOBALS['sugar_config']['cache_dir'].'modules/unified_search_modules.php')) {
893         $usa->buildCache();
894     }
895
896         include($GLOBALS['sugar_config']['cache_dir'].'modules/unified_search_modules.php');
897         $modules_to_search = array();
898         $unified_search_modules['Users'] =   array('fields' => array());
899         
900         $unified_search_modules['ProjectTask'] =   array('fields' => array());
901         
902     foreach($unified_search_modules as $module=>$data) {
903         if (in_array($module, $modules)) {
904                 $modules_to_search[$module] = $beanList[$module];
905         } // if
906     } // foreach
907
908     $GLOBALS['log']->info('SugarWebServiceImpl->search_by_module - search string = ' . $search_string);
909
910         if(!empty($search_string) && isset($search_string)) {
911                 $search_string = trim($GLOBALS['db']->quote(securexss(from_html(clean_string($search_string, 'UNIFIED_SEARCH')))));
912         foreach($modules_to_search as $name => $beanName) {
913                 $where_clauses_array = array();
914                         $unifiedSearchFields = array () ;
915                         foreach ($unified_search_modules[$name]['fields'] as $field=>$def ) {
916                                 $unifiedSearchFields[$name] [ $field ] = $def ;
917                                 $unifiedSearchFields[$name] [ $field ]['value'] = $search_string;
918                         }
919
920                         require_once $beanFiles[$beanName] ;
921                         $seed = new $beanName();
922                         require_once 'include/SearchForm/SearchForm2.php' ;
923                         if ($beanName == "User" 
924                             || $beanName == "ProjectTask"
925                             ) {
926                                 if(!self::$helperObject->check_modules_access($current_user, $seed->module_dir, 'read')){
927                                         continue;
928                                 } // if
929                                 if(!$seed->ACLAccess('ListView')) {
930                                         continue;
931                                 } // if
932                         }
933
934                         if ($beanName != "User" 
935                             && $beanName != "ProjectTask"
936                             ) {
937                                 $searchForm = new SearchForm ($seed, $name ) ;
938
939                                 $searchForm->setup(array ($name => array()) ,$unifiedSearchFields , '' , 'saved_views' /* hack to avoid setup doing further unwanted processing */ ) ;
940                                 $where_clauses = $searchForm->generateSearchWhere() ;
941                                 require_once 'include/SearchForm/SearchForm2.php' ;
942                                 $searchForm = new SearchForm ($seed, $name ) ;
943
944                                 $searchForm->setup(array ($name => array()) ,$unifiedSearchFields , '' , 'saved_views' /* hack to avoid setup doing further unwanted processing */ ) ;
945                                 $where_clauses = $searchForm->generateSearchWhere() ;
946                                 $emailQuery = false;
947
948                                 $where = '';
949                                 if (count($where_clauses) > 0 ) {
950                                         $where = '('. implode(' ) OR ( ', $where_clauses) . ')';
951                                 }
952
953                                 $mod_strings = return_module_language($current_language, $seed->module_dir);
954                                 if(file_exists('custom/modules/'.$seed->module_dir.'/metadata/listviewdefs.php')){
955                                         require_once('custom/modules/'.$seed->module_dir.'/metadata/listviewdefs.php');
956                                 }else{
957                                         require_once('modules/'.$seed->module_dir.'/metadata/listviewdefs.php');
958                                 }
959                     $filterFields = array();
960                                 foreach($listViewDefs[$seed->module_dir] as $colName => $param) {
961                         if(!empty($param['default']) && $param['default'] == true) {
962                             $filterFields[] = strtolower($colName);
963                         } // if
964                     } // foreach
965
966                     if (!in_array('id', $filterFields)) {
967                         $filterFields[] = 'id';
968                     } // if
969                                 $ret_array = $seed->create_new_list_query('', $where, $filterFields, array(), 0, '', true, $seed, true);
970                         if(empty($params) or !is_array($params)) $params = array();
971                         if(!isset($params['custom_select'])) $params['custom_select'] = '';
972                         if(!isset($params['custom_from'])) $params['custom_from'] = '';
973                         if(!isset($params['custom_where'])) $params['custom_where'] = '';
974                         if(!isset($params['custom_order_by'])) $params['custom_order_by'] = '';
975                                 $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'];
976                         } else {
977                                 if ($beanName == "User") {
978                                         $filterFields = array('id', 'user_name', 'first_name', 'last_name', 'email_address');
979                                         $main_query = "select users.id, ea.email_address, users.user_name, first_name, last_name from users ";
980                                         $main_query = $main_query . " LEFT JOIN email_addr_bean_rel eabl ON eabl.bean_module = '{$seed->module_dir}'
981 LEFT JOIN email_addresses ea ON (ea.id = eabl.email_address_id) ";
982                                         $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'";
983                                 } // if
984                                 if ($beanName == "ProjectTask") {
985                                         $filterFields = array('id', 'name', 'project_id', 'project_name');
986                                         $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} ";
987                                         $seed->add_team_security_where_clause($main_query);
988                                         $main_query .= "LEFT JOIN teams ON $seed->table_name.team_id=teams.id AND (teams.deleted=0) ";
989                             $main_query .= "LEFT JOIN project ON $seed->table_name.project_id = project.id ";
990                             $main_query .= "where {$seed->table_name}.name like '{$search_string}%'";
991                                 } // if
992                         } // else
993
994                         $GLOBALS['log']->info('SugarWebServiceImpl->search_by_module - query = ' . $main_query);
995                         if($max_results < -1) {
996                                 $result = $seed->db->query($main_query);
997                         }
998                         else {
999                                 if($max_results == -1) {
1000                                         $limit = $sugar_config['list_max_entries_per_page'];
1001                     } else {
1002                         $limit = $max_results;
1003                     }
1004                     $result = $seed->db->limitQuery($main_query, $offset, $limit + 1);
1005                         }
1006
1007                         $rowArray = array();
1008                         while($row = $seed->db->fetchByAssoc($result)) {
1009                                 $nameValueArray = array();
1010                                 foreach ($filterFields as $field) {
1011                                         $nameValue = array();
1012                                         if (isset($row[$field])) {
1013                                                 $nameValueArray[$field] = self::$helperObject->get_name_value($field, $row[$field]);
1014                                         } // if
1015                                 } // foreach
1016                                 $rowArray[] = $nameValueArray;
1017                         } // while
1018                         $output_list[] = array('name' => $name, 'records' => $rowArray);
1019         } // foreach
1020
1021         $GLOBALS['log']->info('End: SugarWebServiceImpl->search_by_module');
1022         return array('entry_list'=>$output_list);
1023         } // if
1024         return array('entry_list'=>$output_list);
1025 } // fn
1026
1027
1028 /**
1029  * Retrieve the list of available modules on the system available to the currently logged in user.
1030  *
1031  * @param String $session -- Session ID returned by a previous call to login.
1032  * @return Array    'modules' -- Array - An array of module names
1033  * @exception 'SoapFault' -- The SOAP error, if any
1034  */
1035 function get_available_modules($session){
1036         $GLOBALS['log']->info('Begin: SugarWebServiceImpl->get_available_modules');
1037
1038         $error = new SoapError();
1039         if (!self::$helperObject->checkSessionAndModuleAccess($session, 'invalid_session', '', '', '', $error)) {
1040                 $error->set_error('invalid_login');
1041                 $GLOBALS['log']->info('End: SugarWebServiceImpl->get_available_modules');
1042                 return;
1043         } // if
1044
1045         $modules = array();
1046         $modules = array_keys($_SESSION['avail_modules']);
1047
1048         $GLOBALS['log']->info('End: SugarWebServiceImpl->get_available_modules');
1049         return array('modules'=> $modules);
1050 } // fn
1051
1052
1053 /**
1054 *   Once we have successfuly done a mail merge on a campaign, we need to notify Sugar of the targets
1055 *   and the campaign_id for tracking purposes
1056 *
1057 * @param String session  -- Session ID returned by a previous call to login.
1058 * @param Array targets   -- a string array of ids identifying the targets used in the merge
1059 * @param String campaign_id  --  the campaign_id used for the merge
1060 * @return - No output
1061 *
1062 * @exception 'SoapFault' -- The SOAP error, if any
1063 */
1064 function set_campaign_merge($session,$targets, $campaign_id){
1065         $GLOBALS['log']->info('Begin: SugarWebServiceImpl->set_campaign_merge');
1066
1067         $error = new SoapError();
1068         if (!self::$helperObject->checkSessionAndModuleAccess($session, 'invalid_session', '', '', '', $error)) {
1069                 $error->set_error('invalid_login');
1070                 $GLOBALS['log']->info('End: SugarWebServiceImpl->set_campaign_merge');
1071                 return;
1072         } // if
1073     if (empty($campaign_id) or !is_array($targets) or count($targets) == 0) {
1074                 $error->set_error('invalid_set_campaign_merge_data');
1075                 self::$helperObject->setFaultObject($error);
1076         $GLOBALS['log']->debug('set_campaign_merge: Merge action status will not be updated, because, campaign_id is null or no targets were selected.');
1077                 $GLOBALS['log']->info('End: SugarWebServiceImpl->set_campaign_merge');
1078                 return;
1079     } else {
1080         require_once('modules/Campaigns/utils.php');
1081         campaign_log_mail_merge($campaign_id,$targets);
1082     } // else
1083 } // fn
1084 /**
1085 *   Retrieve number of records in a given module
1086 *
1087 * @param String session      -- Session ID returned by a previous call to login.
1088 * @param String module_name  -- module to retrieve number of records from
1089 * @param String query        -- allows webservice user to provide a WHERE clause
1090 * @param int deleted         -- specify whether or not to include deleted records
1091 *
1092 * @return Array  result_count - integer - Total number of records for a given module and query
1093 * @exception 'SoapFault' -- The SOAP error, if any
1094 */
1095 function get_entries_count($session, $module_name, $query, $deleted) {
1096         $GLOBALS['log']->info('Begin: SugarWebServiceImpl->get_entries_count');
1097
1098         $error = new SoapError();
1099         if (!self::$helperObject->checkSessionAndModuleAccess($session, 'invalid_session', $module_name, 'list', 'no_access', $error)) {
1100                 $GLOBALS['log']->info('End: SugarWebServiceImpl->get_entries_count');
1101                 return;
1102         } // if
1103
1104         global $beanList, $beanFiles, $current_user;
1105
1106         $class_name = $beanList[$module_name];
1107         require_once($beanFiles[$class_name]);
1108         $seed = new $class_name();
1109
1110     if (!self::$helperObject->checkACLAccess($seed, 'ListView', $error, 'no_access')) {
1111         return;
1112     }
1113
1114         $sql = 'SELECT COUNT(*) result_count FROM ' . $seed->table_name . ' ';
1115
1116
1117         // build WHERE clauses, if any
1118         $where_clauses = array();
1119         if (!empty($query)) {
1120                 $where_clauses[] = $query;
1121         }
1122         if ($deleted == 0) {
1123                 $where_clauses[] = $seed->table_name . '.deleted = 0';
1124         }
1125
1126         // if WHERE clauses exist, add them to query
1127         if (!empty($where_clauses)) {
1128                 $sql .= ' WHERE ' . implode(' AND ', $where_clauses);
1129         }
1130
1131         $res = $GLOBALS['db']->query($sql);
1132         $row = $GLOBALS['db']->fetchByAssoc($res);
1133
1134         $GLOBALS['log']->info('End: SugarWebServiceImpl->get_entries_count');
1135         return array(
1136                 'result_count' => $row['result_count'],
1137         );
1138 }
1139
1140
1141
1142 } // clazz
1143