2 /*********************************************************************************
3 * SugarCRM Community Edition is a customer relationship management program developed by
4 * SugarCRM, Inc. Copyright (C) 2004-2012 SugarCRM Inc.
6 * This program is free software; you can redistribute it and/or modify it under
7 * the terms of the GNU Affero General Public License version 3 as published by the
8 * Free Software Foundation with the addition of the following permission added
9 * to Section 15 as permitted in Section 7(a): FOR ANY PART OF THE COVERED WORK
10 * IN WHICH THE COPYRIGHT IS OWNED BY SUGARCRM, SUGARCRM DISCLAIMS THE WARRANTY
11 * OF NON INFRINGEMENT OF THIRD PARTY RIGHTS.
13 * This program is distributed in the hope that it will be useful, but WITHOUT
14 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
15 * FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
18 * You should have received a copy of the GNU Affero General Public License along with
19 * this program; if not, see http://www.gnu.org/licenses or write to the Free
20 * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
23 * You can contact SugarCRM, Inc. headquarters at 10050 North Wolfe Road,
24 * SW2-130, Cupertino, CA 95014, USA. or at email address contact@sugarcrm.com.
26 * The interactive user interfaces in modified source and object code versions
27 * of this program must display Appropriate Legal Notices, as required under
28 * Section 5 of the GNU Affero General Public License version 3.
30 * In accordance with Section 7(b) of the GNU Affero General Public License version 3,
31 * these Appropriate Legal Notices must retain the display of the "Powered by
32 * SugarCRM" logo. If the display of the logo is not reasonably feasible for
33 * technical reasons, the Appropriate Legal Notices must display the words
34 * "Powered by SugarCRM".
35 ********************************************************************************/
37 require_once('service/v3_1/SugarWebServiceUtilv3_1.php');
39 class SugarWebServiceUtilv4 extends SugarWebServiceUtilv3_1
41 function get_module_view_defs($moduleName, $type, $view)
43 require_once('include/MVC/View/SugarView.php');
46 if( empty($moduleName) )
49 $view = strtolower($view);
50 switch (strtolower($type)){
53 if ($view == 'subpanel')
54 $results = $this->get_subpanel_defs($moduleName, $type);
57 $v = new SugarView(null,array());
58 $v->module = $moduleName;
60 $fullView = ucfirst($view) . 'View';
61 $metadataFile = $v->getMetaDataFile();
62 require_once($metadataFile);
64 $results = $listViewDefs[$moduleName];
66 $results = $viewdefs[$moduleName][$fullView];
70 //Add field level acls.
71 $results = $this->addFieldLevelACLs($moduleName,$type, $view, $results);
78 * Equivalent of get_list function within SugarBean but allows the possibility to pass in an indicator
79 * if the list should filter for favorites. Should eventually update the SugarBean function as well.
82 function get_data_list($seed, $order_by = "", $where = "", $row_offset = 0, $limit=-1, $max=-1, $show_deleted = 0, $favorites = false)
84 $GLOBALS['log']->debug("get_list: order_by = '$order_by' and where = '$where' and limit = '$limit'");
85 if(isset($_SESSION['show_deleted']))
89 $order_by=$seed->process_order_by($order_by, null);
92 if(!empty($favorites)) {
93 $params['favorites'] = true;
96 $query = $seed->create_new_list_query($order_by, $where,array(),$params, $show_deleted);
97 return $seed->process_list_query($query, $row_offset, $limit, $max, $where);
101 * Convert modules list to Web services result
103 * @param array $list List of module candidates (only keys are used)
104 * @param array $availModules List of module availability from Session
106 public function getModulesFromList($list, $availModules)
108 global $app_list_strings;
109 $enabled_modules = array();
110 $availModulesKey = array_flip($availModules);
111 foreach ($list as $key=>$value)
113 if( isset($availModulesKey[$key]) )
115 $label = !empty( $app_list_strings['moduleList'][$key] ) ? $app_list_strings['moduleList'][$key] : '';
116 $acl = $this->checkModuleRoleAccess($key);
117 $fav = $this->is_favorites_enabled($key);
118 $enabled_modules[] = array('module_key' => $key,'module_label' => $label, 'favorite_enabled' => $fav, 'acls' => $acl);
121 return $enabled_modules;
125 * Return a boolean indicating if the bean name is favorites enabled.
127 * @param string The module name
128 * @return bool true indicating bean is favorites enabled
130 function is_favorites_enabled($module_name)
132 global $beanList, $beanFiles;
140 * Processes the filter_fields attribute to use with SugarBean::create_new_list_query()
142 * @param object $value SugarBean
143 * @param array $fields
146 protected function filter_fields_for_query(SugarBean $value, array $fields)
148 $GLOBALS['log']->info('Begin: SoapHelperWebServices->filter_fields_for_query');
149 $filterFields = array();
150 foreach($fields as $field)
152 if (isset($value->field_defs[$field]))
154 $filterFields[$field] = $value->field_defs[$field];
157 $GLOBALS['log']->info('End: SoapHelperWebServices->filter_fields_for_query');
158 return $filterFields;
161 function get_field_list($value,$fields, $translate=true) {
163 $GLOBALS['log']->info('Begin: SoapHelperWebServices->get_field_list(too large a struct, '.print_r($fields, true).", $translate");
164 $module_fields = array();
165 $link_fields = array();
166 if(!empty($value->field_defs)){
168 foreach($value->field_defs as $var){
169 if(!empty($fields) && !in_array( $var['name'], $fields))continue;
170 if(isset($var['source']) && ($var['source'] != 'db' && $var['source'] != 'non-db' &&$var['source'] != 'custom_fields') && $var['name'] != 'email1' && $var['name'] != 'email2' && (!isset($var['type'])|| $var['type'] != 'relate'))continue;
171 if ((isset($var['source']) && $var['source'] == 'non_db') && (isset($var['type']) && $var['type'] != 'link')) {
175 $options_dom = array();
176 $options_ret = array();
177 // Apparently the only purpose of this check is to make sure we only return fields
178 // when we've read a record. Otherwise this function is identical to get_module_field_list
179 if( isset($var['required']) && ($var['required'] || $var['required'] == 'true' ) ){
183 if($var['type'] == 'bool')
184 $var['options'] = 'checkbox_dom';
186 if(isset($var['options'])){
187 $options_dom = translate($var['options'], $value->module_dir);
188 if(!is_array($options_dom)) $options_dom = array();
189 foreach($options_dom as $key=>$oneOption)
190 $options_ret[$key] = $this->get_name_value($key,$oneOption);
193 if(!empty($var['dbType']) && $var['type'] == 'bool') {
194 $options_ret['type'] = $this->get_name_value('type', $var['dbType']);
198 $entry['name'] = $var['name'];
199 $entry['type'] = $var['type'];
200 $entry['group'] = isset($var['group']) ? $var['group'] : '';
201 $entry['id_name'] = isset($var['id_name']) ? $var['id_name'] : '';
203 if ($var['type'] == 'link') {
204 $entry['relationship'] = (isset($var['relationship']) ? $var['relationship'] : '');
205 $entry['module'] = (isset($var['module']) ? $var['module'] : '');
206 $entry['bean_name'] = (isset($var['bean_name']) ? $var['bean_name'] : '');
207 $link_fields[$var['name']] = $entry;
210 $entry['label'] = isset($var['vname']) ? translate($var['vname'], $value->module_dir) : $var['name'];
212 $entry['label'] = isset($var['vname']) ? $var['vname'] : $var['name'];
214 $entry['required'] = $required;
215 $entry['options'] = $options_ret;
216 $entry['related_module'] = (isset($var['id_name']) && isset($var['module'])) ? $var['module'] : '';
217 $entry['calculated'] = (isset($var['calculated']) && $var['calculated']) ? true : false;
218 $entry['len'] = isset($var['len']) ? $var['len'] : '';
220 if(isset($var['default'])) {
221 $entry['default_value'] = $var['default'];
223 if( $var['type'] == 'parent' && isset($var['type_name']) )
224 $entry['type_name'] = $var['type_name'];
226 $module_fields[$var['name']] = $entry;
231 if($value->module_dir == 'Meetings' || $value->module_dir == 'Calls')
233 if( isset($module_fields['duration_minutes']) && isset($GLOBALS['app_list_strings']['duration_intervals']))
235 $options_dom = $GLOBALS['app_list_strings']['duration_intervals'];
236 $options_ret = array();
237 foreach($options_dom as $key=>$oneOption)
238 $options_ret[$key] = $this->get_name_value($key,$oneOption);
240 $module_fields['duration_minutes']['options'] = $options_ret;
244 if($value->module_dir == 'Bugs'){
245 require_once('modules/Releases/Release.php');
246 $seedRelease = new Release();
247 $options = $seedRelease->get_releases(TRUE, "Active");
248 $options_ret = array();
249 foreach($options as $name=>$value){
250 $options_ret[] = array('name'=> $name , 'value'=>$value);
252 if(isset($module_fields['fixed_in_release'])){
253 $module_fields['fixed_in_release']['type'] = 'enum';
254 $module_fields['fixed_in_release']['options'] = $options_ret;
256 if(isset($module_fields['found_in_release'])){
257 $module_fields['found_in_release']['type'] = 'enum';
258 $module_fields['found_in_release']['options'] = $options_ret;
260 if(isset($module_fields['release'])){
261 $module_fields['release']['type'] = 'enum';
262 $module_fields['release']['options'] = $options_ret;
264 if(isset($module_fields['release_name'])){
265 $module_fields['release_name']['type'] = 'enum';
266 $module_fields['release_name']['options'] = $options_ret;
270 if(isset($value->assigned_user_name) && isset($module_fields['assigned_user_id'])) {
271 $module_fields['assigned_user_name'] = $module_fields['assigned_user_id'];
272 $module_fields['assigned_user_name']['name'] = 'assigned_user_name';
274 if(isset($value->assigned_name) && isset($module_fields['team_id'])) {
275 $module_fields['team_name'] = $module_fields['team_id'];
276 $module_fields['team_name']['name'] = 'team_name';
278 if(isset($module_fields['modified_user_id'])) {
279 $module_fields['modified_by_name'] = $module_fields['modified_user_id'];
280 $module_fields['modified_by_name']['name'] = 'modified_by_name';
282 if(isset($module_fields['created_by'])) {
283 $module_fields['created_by_name'] = $module_fields['created_by'];
284 $module_fields['created_by_name']['name'] = 'created_by_name';
287 $GLOBALS['log']->info('End: SoapHelperWebServices->get_field_list');
288 return array('module_fields' => $module_fields, 'link_fields' => $link_fields);
292 function new_handle_set_entries($module_name, $name_value_lists, $select_fields = FALSE) {
293 $GLOBALS['log']->info('Begin: SoapHelperWebServices->new_handle_set_entries');
294 global $beanList, $beanFiles, $current_user, $app_list_strings;
296 $ret_values = array();
298 $class_name = $beanList[$module_name];
299 require_once($beanFiles[$class_name]);
302 $total = sizeof($name_value_lists);
303 foreach($name_value_lists as $name_value_list){
304 $seed = new $class_name();
306 $seed->update_vcal = false;
307 foreach($name_value_list as $name => $value){
308 if(is_array($value) && $value['name'] == 'id'){
309 $seed->retrieve($value['value']);
312 else if($name === 'id' ){
313 $seed->retrieve($value);
317 foreach($name_value_list as $name => $value) {
318 //Normalize the input
319 if(!is_array($value)){
324 $field_name = $value['name'];
325 $val = $value['value'];
328 if($seed->field_name_map[$field_name]['type'] == 'enum'){
329 $vardef = $seed->field_name_map[$field_name];
330 if(isset($app_list_strings[$vardef['options']]) && !isset($app_list_strings[$vardef['options']][$val]) ) {
331 if ( in_array($val,$app_list_strings[$vardef['options']]) ){
332 $val = array_search($val,$app_list_strings[$vardef['options']]);
336 if($module_name == 'Users' && !empty($seed->id) && ($seed->id != $current_user->id) && $field_name == 'user_hash'){
339 if(!empty($seed->field_name_map[$field_name]['sensitive'])) {
342 $seed->$field_name = $val;
345 if($count == $total){
346 $seed->update_vcal = false;
350 //Add the account to a contact
351 if($module_name == 'Contacts'){
352 $GLOBALS['log']->debug('Creating Contact Account');
353 $this->add_create_account($seed);
354 $duplicate_id = $this->check_for_duplicate_contacts($seed);
355 if($duplicate_id == null){
356 if($seed->ACLAccess('Save') && ($seed->deleted != 1 || $seed->ACLAccess('Delete'))){
358 if($seed->deleted == 1){
359 $seed->mark_deleted($seed->id);
365 //since we found a duplicate we should set the sync flag
366 if( $seed->ACLAccess('Save')){
367 $seed = new $class_name();
368 $seed->id = $duplicate_id;
369 $seed->contacts_users_id = $current_user->id;
371 $ids[] = $duplicate_id;//we have a conflict
375 else if($module_name == 'Meetings' || $module_name == 'Calls'){
376 //we are going to check if we have a meeting in the system
377 //with the same outlook_id. If we do find one then we will grab that
379 if( $seed->ACLAccess('Save') && ($seed->deleted != 1 || $seed->ACLAccess('Delete'))){
380 if(empty($seed->id) && !isset($seed->id)){
381 if(!empty($seed->outlook_id) && isset($seed->outlook_id)){
382 //at this point we have an object that does not have
383 //the id set, but does have the outlook_id set
384 //so we need to query the db to find if we already
385 //have an object with this outlook_id, if we do
386 //then we can set the id, otherwise this is a new object
388 $query = $seed->table_name.".outlook_id = '".$seed->outlook_id."'";
389 $response = $seed->get_list($order_by, $query, 0,-1,-1,0);
390 $list = $response['list'];
391 if(count($list) > 0){
392 foreach($list as $value)
394 $seed->id = $value->id;
400 if (empty($seed->reminder_time)) {
401 $seed->reminder_time = -1;
403 if($seed->reminder_time == -1){
404 $defaultRemindrTime = $current_user->getPreference('reminder_time');
405 if ($defaultRemindrTime != -1){
406 $seed->reminder_checked = '1';
407 $seed->reminder_time = $defaultRemindrTime;
411 if($seed->deleted == 1){
412 $seed->mark_deleted($seed->id);
419 if( $seed->ACLAccess('Save') && ($seed->deleted != 1 || $seed->ACLAccess('Delete'))){
425 // if somebody is calling set_entries_detail() and wants fields returned...
426 if ($select_fields !== FALSE) {
427 $ret_values[$count] = array();
429 foreach ($select_fields as $select_field) {
430 if (isset($seed->$select_field)) {
431 $ret_values[$count][$select_field] = $this->get_name_value($select_field, $seed->$select_field);
437 // handle returns for set_entries_detail() and set_entries()
438 if ($select_fields !== FALSE) {
439 $GLOBALS['log']->info('End: SoapHelperWebServices->new_handle_set_entries');
441 'name_value_lists' => $ret_values,
445 $GLOBALS['log']->info('End: SoapHelperWebServices->new_handle_set_entries');
453 function checkSessionAndModuleAccess($session, $login_error_key, $module_name, $access_level, $module_access_level_error_key, $errorObject)
455 if(isset($_REQUEST['oauth_token'])) {
456 $session = $this->checkOAuthAccess($errorObject);
458 if(!$session) return false;
459 return parent::checkSessionAndModuleAccess($session, $login_error_key, $module_name, $access_level, $module_access_level_error_key, $errorObject);
462 public function checkOAuthAccess($errorObject)
464 require_once "include/SugarOAuthServer.php";
466 $oauth = new SugarOAuthServer();
467 $token = $oauth->authorizedToken();
468 if(empty($token) || empty($token->assigned_user_id)) {
471 } catch(OAuthException $e) {
472 $GLOBALS['log']->debug("OAUTH Exception: $e");
473 $errorObject->set_error('invalid_login');
474 $this->setFaultObject($errorObject);
479 $user->retrieve($token->assigned_user_id);
480 if(empty($user->id)) {
483 global $current_user;
484 $current_user = $user;
485 ini_set("session.use_cookies", 0); // disable cookies to prevent session ID from going out
487 session_regenerate_id();
488 $_SESSION['oauth'] = $oauth->authorization();
489 $_SESSION['avail_modules'] = $this->get_user_module_list($user);
492 $_SESSION['is_valid_session']= true;
493 $_SESSION['ip_address'] = query_client_ip();
494 $_SESSION['user_id'] = $current_user->id;
495 $_SESSION['type'] = 'user';
496 $_SESSION['authenticated_user_id'] = $current_user->id;
504 * @param String $module The name of the module to get the subpanel definition for
505 * @param String $type The type of subpanel definition ('wireless' or 'default')
506 * @return array Array of the subpanel definition; empty array if no matching definition found
508 function get_subpanel_defs($module, $type)
510 global $beanList, $beanFiles;
516 if (file_exists('custom/modules/'.$module.'/metadata/wireless.subpaneldefs.php'))
517 require_once('custom/modules/'.$module.'/metadata/wireless.subpaneldefs.php');
518 else if (file_exists('modules/'.$module.'/metadata/wireless.subpaneldefs.php'))
519 require_once('modules/'.$module.'/metadata/wireless.subpaneldefs.php');
521 //If an Ext/WirelessLayoutdefs/wireless.subpaneldefs.ext.php file exists, then also load it as well
522 if(file_exists('custom/modules/'.$module.'/Ext/WirelessLayoutdefs/wireless.subpaneldefs.ext.php'))
524 require_once('custom/modules/'.$module.'/Ext/WirelessLayoutdefs/wireless.subpaneldefs.ext.php');
530 if (file_exists ('modules/'.$module.'/metadata/subpaneldefs.php' ))
531 require ('modules/'.$module.'/metadata/subpaneldefs.php');
532 if ( file_exists('custom/modules/'.$module.'/Ext/Layoutdefs/layoutdefs.ext.php' ))
533 require ('custom/modules/'.$module.'/Ext/Layoutdefs/layoutdefs.ext.php');
536 //Filter results for permissions
537 foreach ($layout_defs[$module]['subpanel_setup'] as $subpanel => $subpaneldefs)
539 $moduleToCheck = $subpaneldefs['module'];
540 if(!isset($beanList[$moduleToCheck]))
542 $class_name = $beanList[$moduleToCheck];
543 $bean = new $class_name();
544 if($bean->ACLAccess('list'))
545 $results[$subpanel] = $subpaneldefs;