User   F
last analyzed

Complexity

Total Complexity 256

Size/Duplication

Total Lines 1813
Duplicated Lines 0 %

Coupling/Cohesion

Components 2
Dependencies 12

Test Coverage

Coverage 75.72%

Importance

Changes 2
Bugs 1 Features 1
Metric Value
c 2
b 1
f 1
dl 0
loc 1813
ccs 602
cts 795
cp 0.7572
rs 3.4838
wmc 256
lcom 2
cbo 12

69 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 5 1
A User() 0 10 2
A _loadUserPreferencesFocus() 0 4 1
A getSystemUser() 0 11 2
A getDefaultSignature() 0 7 2
A getSignature() 0 6 2
A getSignaturesArray() 0 13 2
B getSignatures() 0 25 6
A getSignatureButtons() 0 15 3
A hasPersonalEmail() 0 7 1
A getUserPrivGuid() 0 15 3
A setUserPrivGuid() 0 5 1
A setPreference() 0 17 2
A resetPreferences() 0 14 2
A savePreferencesToDB() 0 12 2
A reloadPreferences() 0 4 1
A getUserDateTimePreferences() 0 12 2
A loadPreferences() 0 14 2
A getPreference() 0 15 2
A incrementETag() 0 8 2
A getETagSeed() 0 7 2
A getLicensedUsersWhere() 0 5 1
C save() 0 42 8
C check_role_membership() 0 41 8
A get_summary_text() 0 4 1
A encrypt_password() 0 8 1
A retrieve() 0 9 3
A retrieve_by_email_address() 0 19 2
A bean_implements() 0 6 2
B getPasswordHash() 0 14 5
A checkPassword() 0 4 1
A checkPasswordMD5() 0 9 4
A findUserPassword() 0 17 4
A setNewPassword() 0 13 1
A is_authenticated() 0 3 1
A fill_in_additional_list_fields() 0 3 1
A fill_in_additional_detail_fields() 0 20 2
A retrieve_user_id() 0 11 2
C verify_data() 0 62 13
C get_list_view_data() 0 32 8
A list_view_parse_additional_sections() 0 3 1
A getAllUsers() 0 8 1
A getActiveUsers() 0 6 1
B create_export_query() 0 31 6
A get_meetings() 0 5 1
A get_calls() 0 5 1
C displayEmailCounts() 0 54 11
A getPreferredEmail() 0 15 2
A getUsersNameAndEmail() 0 13 2
A getSystemDefaultNameAndEmail() 0 8 1
A setDefaultsInConfig() 0 8 1
C getEmailInfo() 0 33 8
C getEmailLink2() 0 64 8
C getEmailLink() 0 66 9
B getLocaleFormatDesc() 0 30 3
A _fixupModuleForACL() 0 10 3
C _getModulesForACL() 0 44 8
A isAdmin() 0 7 4
A isDeveloperForAnyModule() 0 10 3
A getDeveloperModules() 0 8 2
A isDeveloperForModule() 0 19 4
A getAdminModules() 0 7 2
A isAdminForModule() 0 19 4
A showLastNameFirst() 0 9 2
B create_new_list_query() 0 57 7
A get_first_day_of_week() 0 10 2
D sendEmailForPassword() 0 123 16
B afterImportSave() 0 21 6
A isPrimaryEmail() 0 8 4

How to fix   Complexity   

Complex Class

Complex classes like User often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes. You can also have a look at the cohesion graph to spot any un-connected, or weakly-connected components.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use User, and based on these observations, apply Extract Interface, too.

1
<?php
2
if(!defined('sugarEntry') || !sugarEntry) die('Not A Valid Entry Point');
3
/*********************************************************************************
4
 * SugarCRM Community Edition is a customer relationship management program developed by
5
 * SugarCRM, Inc. Copyright (C) 2004-2013 SugarCRM Inc.
6
7
 * SuiteCRM is an extension to SugarCRM Community Edition developed by Salesagility Ltd.
8
 * Copyright (C) 2011 - 2014 Salesagility Ltd.
9
 *
10
 * This program is free software; you can redistribute it and/or modify it under
11
 * the terms of the GNU Affero General Public License version 3 as published by the
12
 * Free Software Foundation with the addition of the following permission added
13
 * to Section 15 as permitted in Section 7(a): FOR ANY PART OF THE COVERED WORK
14
 * IN WHICH THE COPYRIGHT IS OWNED BY SUGARCRM, SUGARCRM DISCLAIMS THE WARRANTY
15
 * OF NON INFRINGEMENT OF THIRD PARTY RIGHTS.
16
 *
17
 * This program is distributed in the hope that it will be useful, but WITHOUT
18
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
19
 * FOR A PARTICULAR PURPOSE.  See the GNU Affero General Public License for more
20
 * details.
21
 *
22
 * You should have received a copy of the GNU Affero General Public License along with
23
 * this program; if not, see http://www.gnu.org/licenses or write to the Free
24
 * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
25
 * 02110-1301 USA.
26
 *
27
 * You can contact SugarCRM, Inc. headquarters at 10050 North Wolfe Road,
28
 * SW2-130, Cupertino, CA 95014, USA. or at email address [email protected].
29
 *
30
 * The interactive user interfaces in modified source and object code versions
31
 * of this program must display Appropriate Legal Notices, as required under
32
 * Section 5 of the GNU Affero General Public License version 3.
33
 *
34
 * In accordance with Section 7(b) of the GNU Affero General Public License version 3,
35
 * these Appropriate Legal Notices must retain the display of the "Powered by
36
 * SugarCRM" logo and "Supercharged by SuiteCRM" logo. If the display of the logos is not
37
 * reasonably feasible for  technical reasons, the Appropriate Legal Notices must
38
 * display the words  "Powered by SugarCRM" and "Supercharged by SuiteCRM".
39
 ********************************************************************************/
40
41
require_once('include/SugarObjects/templates/person/Person.php');
42
43
// User is used to store customer information.
44
class User extends Person {
45
	// Stored fields
46
	var $name = '';
47
	var $full_name;
48
	var $id;
49
	var $user_name;
50
	var $user_hash;
51
	var $salutation;
52
	var $first_name;
53
	var $last_name;
54
	var $date_entered;
55
	var $date_modified;
56
	var $modified_user_id;
57
	var $created_by;
58
	var $created_by_name;
59
	var $modified_by_name;
60
	var $description;
61
	var $phone_home;
62
	var $phone_mobile;
63
	var $phone_work;
64
	var $phone_other;
65
	var $phone_fax;
66
	var $email1;
67
	var $email2;
68
	var $address_street;
69
	var $address_city;
70
	var $address_state;
71
	var $address_postalcode;
72
	var $address_country;
73
	var $status;
74
	var $title;
75
    var $photo;
76
	var $portal_only;
77
	var $department;
78
	var $authenticated = false;
79
	var $error_string;
80
	var $is_admin;
81
	var $employee_status;
82
	var $messenger_id;
83
	var $messenger_type;
84
	var $is_group;
85
	var $accept_status; // to support Meetings
86
	//adding a property called team_id so we can populate it for use in the team widget
87
	var $team_id;
88
89
	var $receive_notifications;
90
91
	var $reports_to_name;
92
	var $reports_to_id;
93
	var $team_exists = false;
94
	var $table_name = "users";
95
	var $module_dir = 'Users';
96
	var $object_name = "User";
97
	var $user_preferences;
98
99
	var $importable = true;
100
	var $_userPreferenceFocus;
101
102
	var $encodeFields = Array ("first_name", "last_name", "description");
103
104
	// This is used to retrieve related fields from form posts.
105
	var $additional_column_fields = array ('reports_to_name'
106
	);
107
108
	var $emailAddress;
109
110
111
	var $new_schema = true;
112
113 156
	function __construct() {
114 156
		parent::__construct();
115
116 156
		$this->_loadUserPreferencesFocus();
117 156
	}
118
119
    /**
120
     * @deprecated deprecated since version 7.6, PHP4 Style Constructors are deprecated and will be remove in 7.8, please update your code, use __construct instead
121
     */
122
    function User(){
123
        $deprecatedMessage = 'PHP4 Style Constructors are deprecated and will be remove in 7.8, please update your code';
124
        if(isset($GLOBALS['log'])) {
125
            $GLOBALS['log']->deprecated($deprecatedMessage);
126
        }
127
        else {
128
            trigger_error($deprecatedMessage, E_USER_DEPRECATED);
129
        }
130
        self::__construct();
131
    }
132
133
134 156
	protected function _loadUserPreferencesFocus()
135
	{
136 156
	    $this->_userPreferenceFocus = new UserPreference($this);
137 156
	}
138
139
    /**
140
     * returns an admin user
141
     */
142 1
    public function getSystemUser()
143
    {
144 1
        if (null === $this->retrieve('1'))
145
            // handle cases where someone deleted user with id "1"
146
            $this->retrieve_by_string_fields(array(
147
                'status' => 'Active',
148
                'is_admin' => '1',
149
                ));
150
151 1
        return $this;
152
    }
153
154
155
	/**
156
	 * convenience function to get user's default signature
157
	 */
158 1
	function getDefaultSignature() {
159 1
		if($defaultId = $this->getPreference('signature_default')) {
160
			return $this->getSignature($defaultId);
161
		} else {
162 1
			return array();
163
		}
164
	}
165
166
	/**
167
	 * retrieves the signatures for a user
168
	 * @param string id ID of user_signature
169
	 * @return array ID, signature, and signature_html
170
	 */
171 1
	public function getSignature($id)
172
	{
173 1
	    $signatures = $this->getSignaturesArray();
174
175 1
	    return isset($signatures[$id]) ? $signatures[$id] : FALSE;
176
	}
177
178 3
	function getSignaturesArray() {
179 3
		$q = 'SELECT * FROM users_signatures WHERE user_id = \''.$this->id.'\' AND deleted = 0 ORDER BY name ASC';
180 3
		$r = $this->db->query($q);
181
182
		// provide "none"
183 3
		$sig = array(""=>"");
184
185 3
		while($a = $this->db->fetchByAssoc($r)) {
186
			$sig[$a['id']] = $a;
187
		}
188
189 3
		return $sig;
190
	}
191
192
	/**
193
	 * retrieves any signatures that the User may have created as <select>
194
	 */
195 1
	public function getSignatures(
196
	    $live = false,
197
	    $defaultSig = '',
198
	    $forSettings = false
199
	    )
200
	{
201 1
		$sig = $this->getSignaturesArray();
202 1
		$sigs = array();
203 1
		foreach ($sig as $key => $arr)
204
		{
205 1
			$sigs[$key] = !empty($arr['name']) ? $arr['name'] : '';
206
		}
207
208 1
		$change = '';
209 1
		if(!$live) {
210 1
			$change = ($forSettings) ? "onChange='displaySignatureEdit();'" : "onChange='setSigEditButtonVisibility();'";
211
		}
212
213 1
		$id = (!$forSettings) ? 'signature_id' : 'signature_idDisplay';
214
215 1
		$out  = "<select {$change} id='{$id}' name='{$id}'>";
216 1
		$out .= get_select_options_with_id($sigs, $defaultSig).'</select>';
217
218 1
		return $out;
219
	}
220
221
	/**
222
	 * returns buttons and JS for signatures
223
	 */
224 1
	function getSignatureButtons($jscall='', $defaultDisplay=false) {
225 1
		global $mod_strings;
226
227 1
		$jscall = empty($jscall) ? 'open_email_signature_form' : $jscall;
228
229 1
		$butts  = "<input class='button' onclick='javascript:{$jscall}(\"\", \"{$this->id}\");' value='{$mod_strings['LBL_BUTTON_CREATE']}' type='button'>&nbsp;";
230 1
		if($defaultDisplay) {
231 1
			$butts .= '<span name="edit_sig" id="edit_sig" style="visibility:inherit;"><input class="button" onclick="javascript:'.$jscall.'(document.getElementById(\'signature_id\', \'\').value)" value="'.$mod_strings['LBL_BUTTON_EDIT'].'" type="button" tabindex="392">&nbsp;
232 1
					</span>';
233
		} else {
234 1
			$butts .= '<span name="edit_sig" id="edit_sig" style="visibility:hidden;"><input class="button" onclick="javascript:'.$jscall.'(document.getElementById(\'signature_id\', \'\').value)" value="'.$mod_strings['LBL_BUTTON_EDIT'].'" type="button" tabindex="392">&nbsp;
235 1
					</span>';
236
		}
237 1
		return $butts;
238
	}
239
240
	/**
241
	 * performs a rudimentary check to verify if a given user has setup personal
242
	 * InboundEmail
243
	 *
244
	 * @return bool
245
	 */
246 3
	public function hasPersonalEmail()
247
	{
248 3
	    $focus = new InboundEmail;
249 3
	    $focus->retrieve_by_string_fields(array('group_id' => $this->id));
250
251 3
	    return !empty($focus->id);
252
	}
253
254
	/* Returns the User's private GUID; this is unassociated with the User's
255
	 * actual GUID.  It is used to secure file names that must be HTTP://
256
	 * accesible, but obfusicated.
257
	 */
258 1
	function getUserPrivGuid() {
259 1
        $userPrivGuid = $this->getPreference('userPrivGuid', 'global', $this);
260 1
		if ($userPrivGuid) {
261 1
			return $userPrivGuid;
262
		} else {
263 1
			$this->setUserPrivGuid();
264 1
			if (!isset ($_SESSION['setPrivGuid'])) {
265 1
				$_SESSION['setPrivGuid'] = true;
266 1
				$userPrivGuid = $this->getUserPrivGuid();
267 1
				return $userPrivGuid;
268
			} else {
269
				sugar_die("Breaking Infinite Loop Condition: Could not setUserPrivGuid.");
270
			}
271
		}
272
	}
273
274 2
	function setUserPrivGuid() {
275 2
		$privGuid = create_guid();
276
		//($name, $value, $nosession=0)
277 2
		$this->setPreference('userPrivGuid', $privGuid, 0, 'global', $this);
278 2
	}
279
280
	/**
281
	 * Interface for the User object to calling the UserPreference::setPreference() method in modules/UserPreferences/UserPreference.php
282
	 *
283
	 * @see UserPreference::setPreference()
284
	 *
285
	 * @param string $name Name of the preference to set
286
	 * @param string $value Value to set preference to
287
	 * @param null $nosession For BC, ignored
288
	 * @param string $category Name of the category to retrieve
289
	 */
290 12
	public function setPreference(
291
	    $name,
292
	    $value,
293
	    $nosession = 0,
294
	    $category = 'global'
295
	    )
296
	{
297
	    // for BC
298 12
	    if ( func_num_args() > 4 ) {
299 3
	        $user = func_get_arg(4);
300 3
	        $GLOBALS['log']->deprecated('User::setPreferences() should not be used statically.');
301
	    }
302
	    else
303 9
	        $user = $this;
304
305 12
        $user->_userPreferenceFocus->setPreference($name, $value, $category);
306 12
	}
307
308
	/**
309
	 * Interface for the User object to calling the UserPreference::resetPreferences() method in modules/UserPreferences/UserPreference.php
310
	 *
311
	 * @see UserPreference::resetPreferences()
312
	 *
313
	 * @param string $category category to reset
314
	 */
315 1
	public function resetPreferences(
316
	    $category = null
317
	    )
318
	{
319
	    // for BC
320 1
	    if ( func_num_args() > 1 ) {
321
	        $user = func_get_arg(1);
322
	        $GLOBALS['log']->deprecated('User::resetPreferences() should not be used statically.');
323
	    }
324
	    else
325 1
	        $user = $this;
326
327 1
        $user->_userPreferenceFocus->resetPreferences($category);
328 1
	}
329
330
	/**
331
	 * Interface for the User object to calling the UserPreference::savePreferencesToDB() method in modules/UserPreferences/UserPreference.php
332
	 *
333
	 * @see UserPreference::savePreferencesToDB()
334
	 */
335 4
	public function savePreferencesToDB()
336
	{
337
        // for BC
338 4
	    if ( func_num_args() > 0 ) {
339
	        $user = func_get_arg(0);
340
	        $GLOBALS['log']->deprecated('User::savePreferencesToDB() should not be used statically.');
341
	    }
342
	    else
343 4
	        $user = $this;
344
345 4
        $user->_userPreferenceFocus->savePreferencesToDB();
346 4
	}
347
348
	/**
349
	 * Unconditionally reloads user preferences from the DB and updates the session
350
	 * @param string $category name of the category to retreive, defaults to global scope
351
	 * @return bool successful?
352
	 */
353 1
	public function reloadPreferences($category = 'global')
354
	{
355 1
	    return $this->_userPreferenceFocus->reloadPreferences($category = 'global');
356
	}
357
358
	/**
359
	 * Interface for the User object to calling the UserPreference::getUserDateTimePreferences() method in modules/UserPreferences/UserPreference.php
360
	 *
361
	 * @see UserPreference::getUserDateTimePreferences()
362
	 *
363
	 * @return array 'date' - date format for user ; 'time' - time format for user
364
	 */
365 6
	public function getUserDateTimePreferences()
366
	{
367
        // for BC
368 6
	    if ( func_num_args() > 0 ) {
369
	        $user = func_get_arg(0);
370
	        $GLOBALS['log']->deprecated('User::getUserDateTimePreferences() should not be used statically.');
371
	    }
372
	    else
373 6
	        $user = $this;
374
375 6
        return $user->_userPreferenceFocus->getUserDateTimePreferences();
376
	}
377
378
	/**
379
	 * Interface for the User object to calling the UserPreference::loadPreferences() method in modules/UserPreferences/UserPreference.php
380
	 *
381
	 * @see UserPreference::loadPreferences()
382
	 *
383
	 * @param string $category name of the category to retreive, defaults to global scope
384
	 * @return bool successful?
385
	 */
386 10
	public function loadPreferences(
387
	    $category = 'global'
388
	    )
389
	{
390
	    // for BC
391 10
	    if ( func_num_args() > 1 ) {
392
	        $user = func_get_arg(1);
393
	        $GLOBALS['log']->deprecated('User::loadPreferences() should not be used statically.');
394
	    }
395
	    else
396 10
	        $user = $this;
397
398 10
        return $user->_userPreferenceFocus->loadPreferences($category);
399
	}
400
401
	/**
402
	 * Interface for the User object to calling the UserPreference::setPreference() method in modules/UserPreferences/UserPreference.php
403
	 *
404
	 * @see UserPreference::getPreference()
405
	 *
406
	 * @param string $name name of the preference to retreive
407
	 * @param string $category name of the category to retreive, defaults to global scope
408
	 * @return mixed the value of the preference (string, array, int etc)
409
	 */
410 212
	public function getPreference(
411
	    $name,
412
	    $category = 'global'
413
	    )
414
	{
415
	    // for BC
416 212
	    if ( func_num_args() > 2 ) {
417 4
	        $user = func_get_arg(2);
418 4
	        $GLOBALS['log']->deprecated('User::getPreference() should not be used statically.');
419
	    }
420
	    else
421 212
	        $user = $this;
422
423 212
        return $user->_userPreferenceFocus->getPreference($name, $category);
424
	}
425
426
	/**
427
     * incrementETag
428
     *
429
     * This function increments any ETag seed needed for a particular user's
430
     * UI. For example, if the user changes their theme, the ETag seed for the
431
     * main menu needs to be updated, so you call this function with the seed name
432
     * to do so:
433
     *
434
     * UserPreference::incrementETag("mainMenuETag");
435
     *
436
     * @param string $tag ETag seed name.
437
     * @return nothing
438
     */
439 1
    public function incrementETag($tag){
440 1
    	$val = $this->getETagSeed($tag);
441 1
    	if($val == 2147483648){
442
    		$val = 0;
443
    	}
444 1
    	$val++;
445 1
    	$this->setPreference($tag, $val, 0, "ETag");
446 1
    }
447
448
    /**
449
     * getETagSeed
450
     *
451
     * This function is a wrapper to encapsulate getting the ETag seed and
452
     * making sure it's sanitized for use in the app.
453
     *
454
     * @param string $tag ETag seed name.
455
     * @return integer numeric value of the seed
456
     */
457 2
    public function getETagSeed($tag){
458 2
    	$val = $this->getPreference($tag, "ETag");
459 2
    	if($val == null){
460 2
    		$val = 0;
461
    	}
462 2
    	return $val;
463
    }
464
465
466
   /**
467
    * Get WHERE clause that fetches all users counted for licensing purposes
468
    * @return string
469
    */
470 4
	public static function getLicensedUsersWhere()
471
	{
472 4
		return "deleted=0 AND status='Active' AND user_name IS NOT NULL AND is_group=0 AND portal_only=0  AND ".$GLOBALS['db']->convert('user_name', 'length').">0";
473
	    return "1<>1";
0 ignored issues
show
Unused Code introduced by
return '1<>1'; does not seem to be reachable.

This check looks for unreachable code. It uses sophisticated control flow analysis techniques to find statements which will never be executed.

Unreachable code is most often the result of return, die or exit statements that have been added for debug purposes.

function fx() {
    try {
        doSomething();
        return true;
    }
    catch (\Exception $e) {
        return false;
    }

    return false;
}

In the above example, the last return false will never be executed, because a return statement has already been met in every possible execution path.

Loading history...
474
	}
475
476 3
	function save($check_notify = false) {
477 3
		$isUpdate = !empty($this->id) && !$this->new_with_id;
478
479
480 3
		$query = "SELECT count(id) as total from users WHERE ".self::getLicensedUsersWhere();
481
482
483
        // is_group & portal should be set to 0 by default
484 3
        if (!isset($this->is_group)) {
485 2
            $this->is_group = 0;
486
        }
487 3
        if (!isset($this->portal_only)) {
488
            $this->portal_only = 0;
489
        }
490
491
        // wp: do not save user_preferences in this table, see user_preferences module
492 3
		$this->user_preferences = '';
493
494
		// if this is an admin user, do not allow is_group or portal_only flag to be set.
495 3
		if ($this->is_admin) {
496 1
			$this->is_group = 0;
497 1
			$this->portal_only = 0;
498
		}
499
500
501
		// set some default preferences when creating a new user
502 3
		$setNewUserPreferences = empty($this->id) || !empty($this->new_with_id);
503
504
505 3
		parent::save($check_notify);
506
507
508
		// set some default preferences when creating a new user
509 3
		if ( $setNewUserPreferences ) {
510 2
	        if(!$this->getPreference('calendar_publish_key')) {
511 2
		        $this->setPreference('calendar_publish_key', create_guid());
512
	        }
513
		}
514
515 3
        $this->savePreferencesToDB();
516 3
        return $this->id;
517
	}
518
519
	/**
520
	* @return boolean true if the user is a member of the role_name, false otherwise
521
	* @param string $role_name - Must be the exact name of the acl_role
522
	* @param string $user_id - The user id to check for the role membership, empty string if current user
523
	* @desc Determine whether or not a user is a member of an ACL Role. This function caches the
524
	*       results in the session or to prevent running queries after the first time executed.
525
	* Portions created by SugarCRM are Copyright (C) SugarCRM, Inc..
526
	* All Rights Reserved..
527
	* Contributor(s): ______________________________________..
528
	*/
529 1
	function check_role_membership($role_name, $user_id = ''){
530
531 1
		global $current_user;
532
533 1
		if(empty($user_id))
534 1
			$user_id = $current_user->id;
535
536
		// Check the Sugar External Cache to see if this users memberships were cached
537 1
		$role_array = sugar_cache_retrieve("RoleMemberships_".$user_id);
538
539
		// If we are pulling the roles for the current user
540 1
		if($user_id == $current_user->id){
541
			// If the Session doesn't contain the values
542 1
			if(!isset($_SESSION['role_memberships'])){
543
				// This means the external cache already had it loaded
544 1
				if(!empty($role_array))
545
					$_SESSION['role_memberships'] = $role_array;
546
				else{
547 1
					$_SESSION['role_memberships'] = ACLRole::getUserRoleNames($user_id);
548 1
					$role_array = $_SESSION['role_memberships'];
549
				}
550
			}
551
			// else the session had the values, so we assign to the role array
552
			else{
553 1
				$role_array = $_SESSION['role_memberships'];
554
			}
555
		}
556
		else{
557
			// If the external cache didn't contain the values, we get them and put them in cache
558 1
			if(!$role_array){
559 1
				$role_array = ACLRole::getUserRoleNames($user_id);
560 1
				sugar_cache_put("RoleMemberships_".$user_id, $role_array);
0 ignored issues
show
Bug introduced by
It seems like $role_array defined by \ACLRole::getUserRoleNames($user_id) on line 559 can also be of type array; however, sugar_cache_put() does only seem to accept object<Serializable>, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
561
			}
562
		}
563
564
		// If the role doesn't exist in the list of the user's roles
565 1
		if(!empty($role_array) && in_array($role_name, $role_array))
566
			return true;
567
		else
568 1
			return false;
569
	}
570
571 6
    function get_summary_text() {
572
        //$this->_create_proper_name_field();
573 6
        return $this->name;
574
	}
575
576
	/**
577
	 * @deprecated
578
	* @param string $user_name - Must be non null and at least 2 characters
0 ignored issues
show
Bug introduced by
There is no parameter named $user_name. Was it maybe removed?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function.

Consider the following example. The parameter $italy is not defined by the method finale(...).

/**
 * @param array $germany
 * @param array $island
 * @param array $italy
 */
function finale($germany, $island) {
    return "2:1";
}

The most likely cause is that the parameter was removed, but the annotation was not.

Loading history...
579
	* @param string $user_password - Must be non null and at least 1 character.
580
	* @desc Take an unencrypted username and password and return the encrypted password
581
	* @return string encrypted password for storage in DB and comparison against DB password.
582
	*/
583 1
	function encrypt_password($user_password)
584
	{
585
		// encrypt the password.
586 1
		$salt = substr($this->user_name, 0, 2);
587 1
		$encrypted_password = crypt($user_password, $salt);
588
589 1
		return $encrypted_password;
590
	}
591
592
	/**
593
	 * Authenicates the user; returns true if successful
594
	 *
595
	 * @param string $password MD5-encoded password
596
	 * @return bool
597
	 */
598 1
	public function authenticate_user($password)
599
	{
600 1
	    $row = self::findUserPassword($this->user_name, $password);
601 1
	    if(empty($row)) {
602 1
	        return false;
603
		} else {
604 1
			$this->id = $row['id'];
605 1
			return true;
606
		}
607
	}
608
609
    /**
610
     * retrieves an User bean
611
     * preformat name & full_name attribute with first/last
612
     * loads User's preferences
613
     *
614
     * @param string id ID of the User
615
     * @param bool encode encode the result
616
     * @return object User bean
617
     * @return null null if no User found
618
     */
619 52
	function retrieve($id = -1, $encode = true, $deleted = true) {
620 52
		$ret = parent::retrieve($id, $encode, $deleted);
621 52
		if ($ret) {
622 48
			if (isset ($_SESSION)) {
623 4
				$this->loadPreferences();
624
			}
625
		}
626 52
		return $ret;
627
	}
628
629 1
	function retrieve_by_email_address($email) {
630
631 1
		$email1= strtoupper($email);
632
		$q=<<<EOQ
633
634
		select id from users where id in ( SELECT  er.bean_id AS id FROM email_addr_bean_rel er,
635
			email_addresses ea WHERE ea.id = er.email_address_id
636 1
		    AND ea.deleted = 0 AND er.deleted = 0 AND er.bean_module = 'Users' AND email_address_caps IN ('{$email1}') )
637
EOQ;
638
639
640 1
		$res=$this->db->query($q);
641 1
		$row=$this->db->fetchByAssoc($res);
642
643 1
		if (!empty($row['id'])) {
644 1
			return $this->retrieve($row['id']);
645
		}
646 1
		return '';
647
	}
648
649 156
   function bean_implements($interface) {
650
        switch($interface){
651 156
            case 'ACL':return true;
0 ignored issues
show
Coding Style introduced by
The case body in a switch statement must start on the line following the statement.

According to the PSR-2, the body of a case statement must start on the line immediately following the case statement.

switch ($expr) {
case "A":
    doSomething(); //right
    break;
case "B":

    doSomethingElse(); //wrong
    break;

}

To learn more about the PSR-2 coding standard, please refer to the PHP-Fig.

Loading history...
Coding Style introduced by
Terminating statement must be on a line by itself

As per the PSR-2 coding standard, the break (or other terminating) statement must be on a line of its own.

switch ($expr) {
     case "A":
         doSomething();
         break; //wrong
     case "B":
         doSomething();
         break; //right
     case "C:":
         doSomething();
         return true; //right
 }

To learn more about the PSR-2 coding standard, please refer to the PHP-Fig.

Loading history...
652
        }
653 2
        return false;
654
    }
655
656
657
	/**
658
	 * Load a user based on the user_name in $this
659
	 * @param string $user_password Password
660
	 * @param bool $password_encoded Is password md5-encoded or plain text?
661
	 * @return -- this if load was successul and null if load failed.
0 ignored issues
show
Documentation introduced by
The doc-type -- could not be parsed: Unknown type name "--" at position 0. (view supported doc-types)

This check marks PHPDoc comments that could not be parsed by our parser. To see which comment annotations we can parse, please refer to our documentation on supported doc-types.

Loading history...
662
	 */
663 1
	function load_user($user_password, $password_encoded = false)
664
	{
665 1
		global $login_error;
666 1
		unset($GLOBALS['login_error']);
667 1
		if(isset ($_SESSION['loginattempts'])) {
668
			$_SESSION['loginattempts'] += 1;
669
		} else {
670 1
			$_SESSION['loginattempts'] = 1;
671
		}
672 1
		if($_SESSION['loginattempts'] > 5) {
673
			$GLOBALS['log']->fatal('SECURITY: '.$this->user_name.' has attempted to login '.$_SESSION['loginattempts'].' times from IP address: '.$_SERVER['REMOTE_ADDR'].'.');
674
			return null;
675
		}
676
677 1
		$GLOBALS['log']->debug("Starting user load for $this->user_name");
678
679 1
		if (!isset ($this->user_name) || $this->user_name == "" || !isset ($user_password) || $user_password == "")
680
			return null;
681
682 1
	    if(!$password_encoded) {
683 1
	        $user_password = md5($user_password);
684
	    }
685 1
        $row = self::findUserPassword($this->user_name, $user_password);
686 1
		if(empty($row) || !empty ($GLOBALS['login_error'])) {
687
			$GLOBALS['log']->fatal('SECURITY: User authentication for '.$this->user_name.' failed - could not Load User from Database');
688
			return null;
689
		}
690
691
		// now fill in the fields.
692 1
		$this->loadFromRow($row);
693 1
		$this->loadPreferences();
694
695 1
		if ($this->status != "Inactive")
696 1
			$this->authenticated = true;
697
698 1
		unset ($_SESSION['loginattempts']);
699 1
		return $this;
700
	}
701
702
	/**
703
	 * Generate a new hash from plaintext password
704
	 * @param string $password
705
	 */
706 1
	public static function getPasswordHash($password)
707
	{
708 1
	    if(!defined('CRYPT_MD5') || !constant('CRYPT_MD5')) {
709
	        // does not support MD5 crypt - leave as is
710
	        if(defined('CRYPT_EXT_DES') && constant('CRYPT_EXT_DES')) {
711
	            return crypt(strtolower(md5($password)),
712
	            	"_.012".substr(str_shuffle('./ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'), -4));
713
	        }
714
	        // plain crypt cuts password to 8 chars, which is not enough
715
	        // fall back to old md5
716
	        return strtolower(md5($password));
717
	    }
718 1
	    return @crypt(strtolower(md5($password)));
719
	}
720
721
	/**
722
	 * Check that password matches existing hash
723
	 * @param string $password Plaintext password
724
	 * @param string $user_hash DB hash
725
	 */
726 1
	public static function checkPassword($password, $user_hash)
727
	{
728 1
	    return self::checkPasswordMD5(md5($password), $user_hash);
729
	}
730
731
	/**
732
	 * Check that md5-encoded password matches existing hash
733
	 * @param string $password MD5-encoded password
0 ignored issues
show
Documentation introduced by
There is no parameter named $password. Did you maybe mean $password_md5?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function. It has, however, found a similar but not annotated parameter which might be a good fit.

Consider the following example. The parameter $ireland is not defined by the method finale(...).

/**
 * @param array $germany
 * @param array $ireland
 */
function finale($germany, $island) {
    return "2:1";
}

The most likely cause is that the parameter was changed, but the annotation was not.

Loading history...
734
	 * @param string $user_hash DB hash
735
	 * @return bool Match or not?
736
	 */
737 3
	public static function checkPasswordMD5($password_md5, $user_hash)
738
	{
739 3
	    if(empty($user_hash)) return false;
740 3
	    if($user_hash[0] != '$' && strlen($user_hash) == 32) {
741
	        // Old way - just md5 password
742
	        return strtolower($password_md5) == $user_hash;
743
	    }
744 3
	    return crypt(strtolower($password_md5), $user_hash) == $user_hash;
745
	}
746
747
	/**
748
	 * Find user with matching password
749
	 * @param string $name Username
750
	 * @param string $password MD5-encoded password
751
	 * @param string $where Limiting query
752
	 * @return the matching User of false if not found
753
	 */
754 1
	public static function findUserPassword($name, $password, $where = '')
755
	{
756 1
	    global $db;
757 1
		$name = $db->quote($name);
758 1
		$query = "SELECT * from users where user_name='$name'";
759 1
		if(!empty($where)) {
760
		    $query .= " AND $where";
761
		}
762 1
		$result = $db->limitQuery($query,0,1,false);
763 1
		if(!empty($result)) {
764 1
		    $row = $db->fetchByAssoc($result);
765 1
		    if(self::checkPasswordMD5($password, $row['user_hash'])) {
766 1
		        return $row;
767
		    }
768
		}
769 1
		return false;
770
	}
771
772
	/**
773
	 * Sets new password and resets password expiration timers
774
	 * @param string $new_password
775
	 */
776 1
	public function setNewPassword($new_password, $system_generated = '0')
777
	{
778 1
        $user_hash = self::getPasswordHash($new_password);
779 1
        $this->setPreference('loginexpiration','0');
780 1
	    $this->setPreference('lockout','');
781 1
		$this->setPreference('loginfailed','0');
782 1
		$this->savePreferencesToDB();
783
        //set new password
784 1
        $now = TimeDate::getInstance()->nowDb();
785 1
		$query = "UPDATE $this->table_name SET user_hash='$user_hash', system_generated_password='$system_generated', pwd_last_changed='$now' where id='$this->id'";
786 1
		$this->db->query($query, true, "Error setting new password for $this->user_name: ");
787 1
        $_SESSION['hasExpiredPassword'] = '0';
788 1
	}
789
790
	/**
791
	 * Verify that the current password is correct and write the new password to the DB.
792
	 *
793
	 * @param string $user_password - Must be non null and at least 1 character.
794
	 * @param string $new_password - Must be non null and at least 1 character.
795
     * @param string $system_generated
796
	 * @return boolean - If passwords pass verification and query succeeds, return true, else return false.
797
	 */
798 1
	function change_password($user_password, $new_password, $system_generated = '0')
799
	{
800 1
	    global $mod_strings;
801 1
		global $current_user;
802 1
		$GLOBALS['log']->debug("Starting password change for $this->user_name");
803
804 1
		if (!isset ($new_password) || $new_password == "") {
805
			$this->error_string = $mod_strings['ERR_PASSWORD_CHANGE_FAILED_1'].$current_user->user_name.$mod_strings['ERR_PASSWORD_CHANGE_FAILED_2'];
806
			return false;
807
		}
808
809
810
		//check old password current user is not an admin or current user is an admin editing themselves
811 1
		if (!$current_user->isAdminForModule('Users')  || ($current_user->isAdminForModule('Users') && ($current_user->id == $this->id))) {
812
			//check old password first
813 1
			$row = self::findUserPassword($this->user_name, md5($user_password));
814 1
            if (empty($row)) {
815
				$GLOBALS['log']->warn("Incorrect old password for ".$this->user_name."");
816
				$this->error_string = $mod_strings['ERR_PASSWORD_INCORRECT_OLD_1'].$this->user_name.$mod_strings['ERR_PASSWORD_INCORRECT_OLD_2'];
817
				return false;
818
			}
819
		}
820
821 1
		$this->setNewPassword($new_password, $system_generated);
822 1
		return true;
823
	}
824
825
826 1
	function is_authenticated() {
827 1
		return $this->authenticated;
828
	}
829
830 5
	function fill_in_additional_list_fields() {
831 5
		$this->fill_in_additional_detail_fields();
832 5
	}
833
834 54
	function fill_in_additional_detail_fields() {
835
        // jmorais@dri Bug #56269
836 54
        parent::fill_in_additional_detail_fields();
837
        // ~jmorais@dri
838 54
		global $locale;
839
840 54
		$query = "SELECT u1.first_name, u1.last_name from users  u1, users  u2 where u1.id = u2.reports_to_id AND u2.id = '$this->id' and u1.deleted=0";
841 54
		$result = $this->db->query($query, true, "Error filling in additional detail fields");
842
843 54
		$row = $this->db->fetchByAssoc($result);
844
845 54
		if ($row != null) {
846
			$this->reports_to_name = stripslashes($row['first_name'].' '.$row['last_name']);
847
		} else {
848 54
			$this->reports_to_name = '';
849
		}
850
851
852 54
		$this->_create_proper_name_field();
853 54
	}
854
855 2
	public function retrieve_user_id(
856
	    $user_name
857
	    )
858
	{
859 2
	    $userFocus = new User;
860 2
	    $userFocus->retrieve_by_string_fields(array('user_name'=>$user_name));
861 2
	    if ( empty($userFocus->id) )
862 1
	        return false;
863
864 1
        return $userFocus->id;
865
	}
866
867
	/**
868
	 * @return -- returns a list of all users in the system.
0 ignored issues
show
Documentation introduced by
The doc-type -- could not be parsed: Unknown type name "--" at position 0. (view supported doc-types)

This check marks PHPDoc comments that could not be parsed by our parser. To see which comment annotations we can parse, please refer to our documentation on supported doc-types.

Loading history...
869
	 * Portions created by SugarCRM are Copyright (C) SugarCRM, Inc..
870
	 * All Rights Reserved..
871
	 * Contributor(s): ______________________________________..
872
	 */
873 1
	function verify_data($ieVerified=true) {
874 1
		global $mod_strings, $current_user;
875 1
		$verified = TRUE;
876
877 1
		if (!empty ($this->id)) {
878
			// Make sure the user doesn't report to themselves.
879 1
			$reports_to_self = 0;
880 1
			$check_user = $this->reports_to_id;
881 1
			$already_seen_list = array ();
882 1
			while (!empty ($check_user)) {
883
				if (isset ($already_seen_list[$check_user])) {
884
					// This user doesn't actually report to themselves
885
					// But someone above them does.
886
					$reports_to_self = 1;
887
					break;
888
				}
889
				if ($check_user == $this->id) {
890
					$reports_to_self = 1;
891
					break;
892
				}
893
				$already_seen_list[$check_user] = 1;
894
				$query = "SELECT reports_to_id FROM users WHERE id='".$this->db->quote($check_user)."'";
895
				$result = $this->db->query($query, true, "Error checking for reporting-loop");
896
				$row = $this->db->fetchByAssoc($result);
897
				echo ("fetched: ".$row['reports_to_id']." from ".$check_user."<br>");
898
				$check_user = $row['reports_to_id'];
899
			}
900
901 1
			if ($reports_to_self == 1) {
902
				$this->error_string .= $mod_strings['ERR_REPORT_LOOP'];
903
				$verified = FALSE;
904
			}
905
		}
906
907 1
		$query = "SELECT user_name from users where user_name='$this->user_name' AND deleted=0";
908 1
		if(!empty($this->id))$query .=  " AND id<>'$this->id'";
909 1
		$result = $this->db->query($query, true, "Error selecting possible duplicate users: ");
910 1
		$dup_users = $this->db->fetchByAssoc($result);
911
912 1
		if (!empty($dup_users)) {
913
			$this->error_string .= $mod_strings['ERR_USER_NAME_EXISTS_1'].$this->user_name.$mod_strings['ERR_USER_NAME_EXISTS_2'];
914
			$verified = FALSE;
915
		}
916
917 1
		if (is_admin($current_user)) {
918
		    $remaining_admins = $this->db->getOne("SELECT COUNT(*) as c from users where is_admin = 1 AND deleted=0");
919
920
			if (($remaining_admins <= 1) && ($this->is_admin != '1') && ($this->id == $current_user->id)) {
921
				$GLOBALS['log']->debug("Number of remaining administrator accounts: {$remaining_admins}");
922
				$this->error_string .= $mod_strings['ERR_LAST_ADMIN_1'].$this->user_name.$mod_strings['ERR_LAST_ADMIN_2'];
923
				$verified = FALSE;
924
			}
925
		}
926
		///////////////////////////////////////////////////////////////////////
927
		////	InboundEmail verification failure
928 1
		if(!$ieVerified) {
929 1
			$verified = false;
930 1
			$this->error_string .= '<br />'.$mod_strings['ERR_EMAIL_NO_OPTS'];
931
		}
932
933 1
		return $verified;
934
	}
935
936 4
	function get_list_view_data() {
937
938 4
		global $mod_strings;
939
940 4
		$user_fields = parent::get_list_view_data();
941
942 4
		if ($this->is_admin)
943 3
			$user_fields['IS_ADMIN_IMAGE'] = SugarThemeRegistry::current()->getImage('check_inline', '',null,null,'.gif',$mod_strings['LBL_CHECKMARK']);
944 3
		elseif (!$this->is_admin) $user_fields['IS_ADMIN'] = '';
945 4
		if ($this->is_group)
946
			$user_fields['IS_GROUP_IMAGE'] = SugarThemeRegistry::current()->getImage('check_inline', '',null,null,'.gif',$mod_strings['LBL_CHECKMARK']);
947
		else
948 4
			$user_fields['IS_GROUP_IMAGE'] = '';
949
950
951 4
        if ($this->is_admin) {
952 3
      			$user_fields['IS_ADMIN_IMAGE'] = SugarThemeRegistry::current()->getImage('check_inline', '',null,null,'.gif',translate('LBL_CHECKMARK', 'Users'));
953 3
        } elseif (!$this->is_admin) {
954 3
              $user_fields['IS_ADMIN'] = '';
955
        }
956
957 4
      	if ($this->is_group) {
958
      		$user_fields['IS_GROUP_IMAGE'] = SugarThemeRegistry::current()->getImage('check_inline', '',null,null,'.gif',translate('LBL_CHECKMARK', 'Users'));
959
        } else {
960 4
            $user_fields['NAME'] = empty ($this->name) ? '' : $this->name;
961
        }
962
963 4
		$user_fields['REPORTS_TO_NAME'] = $this->reports_to_name;
964
965
966 4
		return $user_fields;
967
	}
968
969 1
	function list_view_parse_additional_sections(&$list_form) {
970 1
		return $list_form;
971
	}
972
973
974
975
976
    /**
977
     * getAllUsers
978
     *
979
     * Returns all active and inactive users
980
     * @return Array of all users in the system
981
     */
982
983 1
    public static function getAllUsers()
984
    {
985 1
        $active_users = get_user_array(FALSE);
986 1
        $inactive_users = get_user_array(FALSE, "Inactive");
987 1
        $result = $active_users + $inactive_users;
988 1
        asort($result);
989 1
        return $result;
990
    }
991
992
    /**
993
     * getActiveUsers
994
     *
995
     * Returns all active users
996
     * @return Array of active users in the system
997
     */
998
999 1
    public static function getActiveUsers()
1000
    {
1001 1
        $active_users = get_user_array(FALSE);
1002 1
        asort($active_users);
1003 1
        return $active_users;
1004
    }
1005
1006
1007
1008 1
	function create_export_query($order_by, $where, $relate_link_join = '') {
1009 1
		include('modules/Users/field_arrays.php');
1010
1011 1
		$cols = '';
1012 1
		foreach($fields_array['User']['export_fields'] as $field) {
1013 1
			$cols .= (empty($cols)) ? '' : ', ';
1014 1
			$cols .= $field;
1015
		}
1016
1017 1
		$query = "SELECT {$cols} FROM users ";
1018
1019 1
		$where_auto = " users.deleted = 0";
1020
1021 1
		if ($where != "")
1022 1
			$query .= " WHERE $where AND ".$where_auto;
1023
		else
1024 1
			$query .= " WHERE ".$where_auto;
1025
1026
		// admin for module user is not be able to export a super-admin
1027 1
		global $current_user;
1028 1
		if(!$current_user->is_admin){
1029 1
			$query .= " AND users.is_admin=0";
1030
		}
1031
1032 1
		if ($order_by != "")
1033 1
			$query .= " ORDER BY $order_by";
1034
		else
1035 1
			$query .= " ORDER BY users.user_name";
1036
1037 1
		return $query;
1038
	}
1039
1040
	/** Returns a list of the associated users
1041
	 * Portions created by SugarCRM are Copyright (C) SugarCRM, Inc..
1042
	 * All Rights Reserved..
1043
	 * Contributor(s): ______________________________________..
1044
	*/
1045 1
	function get_meetings() {
1046
		// First, get the list of IDs.
1047 1
		$query = "SELECT meeting_id as id from meetings_users where user_id='$this->id' AND deleted=0";
1048 1
		return $this->build_related_list($query, new Meeting());
1049
	}
1050
	function get_calls() {
1051
		// First, get the list of IDs.
1052
		$query = "SELECT call_id as id from calls_users where user_id='$this->id' AND deleted=0";
1053
		return $this->build_related_list($query, new Call());
1054
	}
1055
1056
	/**
1057
	 * generates Javascript to display I-E mail counts, both personal and group
1058
	 */
1059 1
	function displayEmailCounts() {
1060 1
		global $theme;
1061 1
		$new = translate('LBL_NEW', 'Emails');
1062 1
		$default = 'index.php?module=Emails&action=ListView&assigned_user_id='.$this->id;
1063 1
		$count = '';
1064 1
		$verts = array('Love', 'Links', 'Pipeline', 'RipCurl', 'SugarLite');
1065
1066 1
		if($this->hasPersonalEmail()) {
1067
			$r = $this->db->query('SELECT count(*) AS c FROM emails WHERE deleted=0 AND assigned_user_id = \''.$this->id.'\' AND type = \'inbound\' AND status = \'unread\'');
1068
			$a = $this->db->fetchByAssoc($r);
1069
			if(in_array($theme, $verts)) {
1070
				$count .= '<br />';
1071
			} else {
1072
				$count .= '&nbsp;&nbsp;&nbsp;&nbsp;';
1073
			}
1074
			$count .= '<a href='.$default.'&type=inbound>'.translate('LBL_LIST_TITLE_MY_INBOX', 'Emails').': ('.$a['c'].' '.$new.')</a>';
1075
1076
			if(!in_array($theme, $verts)) {
1077
				$count .= ' - ';
1078
			}
1079
		}
1080
1081 1
		$r = $this->db->query('SELECT id FROM users WHERE users.is_group = 1 AND deleted = 0');
1082 1
		$groupIds = '';
1083 1
		$groupNew = '';
1084 1
		while($a = $this->db->fetchByAssoc($r)) {
1085
			if($groupIds != '') {$groupIds .= ', ';}
1086
			$groupIds .= "'".$a['id']."'";
1087
		}
1088
1089 1
		$total = 0;
1090 1
		if(strlen($groupIds) > 0) {
1091
			$groupQuery = 'SELECT count(*) AS c FROM emails ';
1092
			$groupQuery .= ' WHERE emails.deleted=0 AND emails.assigned_user_id IN ('.$groupIds.') AND emails.type = \'inbound\' AND emails.status = \'unread\'';
1093
			$r = $this->db->query($groupQuery);
1094
			if(is_resource($r)) {
1095
				$a = $this->db->fetchByAssoc($r);
1096
				if($a['c'] > 0) {
1097
					$total = $a['c'];
1098
				}
1099
			}
1100
		}
1101 1
		if(in_array($theme, $verts)) $count .= '<br />';
1102 1
		if(empty($count)) $count .= '&nbsp;&nbsp;&nbsp;&nbsp;';
1103 1
		$count .= '<a href=index.php?module=Emails&action=ListViewGroup>'.translate('LBL_LIST_TITLE_GROUP_INBOX', 'Emails').': ('.$total.' '.$new.')</a>';
1104
1105 1
		$out  = '<script type="text/javascript" language="Javascript">';
1106 1
		$out .= 'var welcome = document.getElementById("welcome");';
1107 1
		$out .= 'var welcomeContent = welcome.innerHTML;';
1108 1
		$out .= 'welcome.innerHTML = welcomeContent + "'.$count.'";';
1109 1
		$out .= '</script>';
1110
1111 1
		echo $out;
1112 1
	}
1113
1114 1
	function getPreferredEmail() {
1115 1
		$ret = array ();
1116 1
		$nameEmail = $this->getUsersNameAndEmail();
1117 1
		$prefAddr = $nameEmail['email'];
1118 1
		$fullName = $nameEmail['name'];
1119 1
		if (empty ($prefAddr)) {
1120
			$nameEmail = $this->getSystemDefaultNameAndEmail();
1121
			$prefAddr = $nameEmail['email'];
1122
			$fullName = $nameEmail['name'];
1123
		} // if
1124 1
		$fullName = from_html($fullName);
1125 1
		$ret['name'] = $fullName;
1126 1
		$ret['email'] = $prefAddr;
1127 1
		return $ret;
1128
	}
1129
1130 1
	function getUsersNameAndEmail()
1131
	{
1132
	    // Bug #48555 Not User Name Format of User's locale.
1133 1
	    $this->_create_proper_name_field();
1134
1135 1
		$prefAddr = $this->emailAddress->getPrimaryAddress($this);
1136
1137 1
		if (empty ($prefAddr)) {
1138
			$prefAddr = $this->emailAddress->getReplyToAddress($this);
1139
		}
1140 1
		return array('email' => $prefAddr , 'name' => $this->name);
1141
1142
	} // fn
1143
1144 1
	function getSystemDefaultNameAndEmail() {
1145
1146 1
		$email = new Email();
1147 1
		$return = $email->getSystemDefaultEmail();
1148 1
		$prefAddr = $return['email'];
1149 1
		$fullName = $return['name'];
1150 1
		return array('email' => $prefAddr , 'name' => $fullName);
1151
	} // fn
1152
1153
	/**
1154
	 * sets User email default in config.php if not already set by install - i.
1155
	 * e., upgrades
1156
	 */
1157 1
	function setDefaultsInConfig() {
1158 1
		global $sugar_config;
1159 1
		$sugar_config['email_default_client'] = 'sugar';
1160 1
		$sugar_config['email_default_editor'] = 'html';
1161 1
		ksort($sugar_config);
1162 1
		write_array_to_file('sugar_config', $sugar_config, 'config.php');
1163 1
		return $sugar_config;
1164
	}
1165
1166
    /**
1167
     * returns User's email address based on descending order of preferences
1168
     *
1169
     * @param string id GUID of target user if needed
1170
     * @return array Assoc array for an email and name
1171
     */
1172 1
    function getEmailInfo($id='') {
1173 1
        $user = $this;
1174 1
        if(!empty($id)) {
1175 1
            $user = new User();
1176 1
            $user->retrieve($id);
1177
        }
1178
1179
        // from name
1180 1
        $fromName = $user->getPreference('mail_fromname');
1181 1
        if(empty($fromName)) {
1182
        	// cn: bug 8586 - localized name format
1183 1
            $fromName = $user->full_name;
1184
        }
1185
1186
        // from address
1187 1
        $fromaddr = $user->getPreference('mail_fromaddress');
1188 1
        if(empty($fromaddr)) {
1189 1
            if(!empty($user->email1) && isset($user->email1)) {
1190 1
                $fromaddr = $user->email1;
1191
            } elseif(!empty($user->email2) && isset($user->email2)) {
1192
                $fromaddr = $user->email2;
1193
            } else {
1194
                $r = $user->db->query("SELECT value FROM config WHERE name = 'fromaddress'");
1195
                $a = $user->db->fetchByAssoc($r);
1196
                $fromddr = $a['value'];
1197
            }
1198
        }
1199
1200 1
        $ret['name'] = $fromName;
1201 1
        $ret['email'] = $fromaddr;
1202
1203 1
        return $ret;
1204
    }
1205
1206
	/**
1207
	 * returns opening <a href=xxxx for a contact, account, etc
1208
	 * cascades from User set preference to System-wide default
1209
	 * @return string	link
1210
	 * @param attribute the email addy
1211
	 * @param focus the parent bean
1212
	 * @param contact_id
1213
	 * @param return_module
1214
	 * @param return_action
1215
	 * @param return_id
1216
	 * @param class
1217
	 */
1218 1
	function getEmailLink2($emailAddress, &$focus, $contact_id='', $ret_module='', $ret_action='DetailView', $ret_id='', $class='') {
1219 1
		$emailLink = '';
1220 1
		global $sugar_config;
1221
1222 1
		if(!isset($sugar_config['email_default_client'])) {
1223
			$this->setDefaultsInConfig();
1224
		}
1225
1226 1
		$userPref = $this->getPreference('email_link_type');
1227 1
		$defaultPref = $sugar_config['email_default_client'];
1228 1
		if($userPref != '') {
1229 1
			$client = $userPref;
1230
		} else {
1231
			$client = $defaultPref;
1232
		}
1233
1234 1
		if($client == 'sugar') {
1235 1
			$email = '';
1236 1
			$to_addrs_ids = '';
1237 1
			$to_addrs_names = '';
1238 1
			$to_addrs_emails = '';
1239
1240 1
			$fullName = !empty($focus->name) ? $focus->name : '';
1241
1242 1
			if(empty($ret_module)) $ret_module = $focus->module_dir;
1243 1
			if(empty($ret_id)) $ret_id = $focus->id;
1244 1
			if($focus->object_name == 'Contact') {
1245 1
				$contact_id = $focus->id;
1246 1
				$to_addrs_ids = $focus->id;
1247
				// Bug #48555 Not User Name Format of User's locale.
1248 1
				$focus->_create_proper_name_field();
1249 1
			    $fullName = $focus->name;
1250 1
			    $to_addrs_names = $fullName;
1251 1
				$to_addrs_emails = $focus->email1;
1252
			}
1253
1254 1
			$emailLinkUrl = 'contact_id='.$contact_id.
1255 1
				'&parent_type='.$focus->module_dir.
1256 1
				'&parent_id='.$focus->id.
1257 1
				'&parent_name='.urlencode($fullName).
1258 1
				'&to_addrs_ids='.$to_addrs_ids.
1259 1
				'&to_addrs_names='.urlencode($to_addrs_names).
1260 1
				'&to_addrs_emails='.urlencode($to_addrs_emails).
1261 1
				'&to_email_addrs='.urlencode($fullName . '&nbsp;&lt;' . $emailAddress . '&gt;').
1262 1
				'&return_module='.$ret_module.
1263 1
				'&return_action='.$ret_action.
1264 1
				'&return_id='.$ret_id;
1265
1266
    		//Generate the compose package for the quick create options.
1267
    		//$json = getJSONobj();
1268
    		//$composeOptionsLink = $json->encode( array('composeOptionsLink' => $emailLinkUrl,'id' => $focus->id) );
1269 1
			require_once('modules/Emails/EmailUI.php');
1270 1
            $eUi = new EmailUI();
1271 1
            $j_quickComposeOptions = $eUi->generateComposePackageForQuickCreateFromComposeUrl($emailLinkUrl, true);
1272
1273 1
    		$emailLink = "<a href='javascript:void(0);' onclick='SUGAR.quickCompose.init($j_quickComposeOptions);' class='$class'>";
1274
1275
		} else {
1276
			// straight mailto:
1277
			$emailLink = '<a href="mailto:'.$emailAddress.'" class="'.$class.'">';
1278
		}
1279
1280 1
		return $emailLink;
1281
	}
1282
1283
	/**
1284
	 * returns opening <a href=xxxx for a contact, account, etc
1285
	 * cascades from User set preference to System-wide default
1286
	 * @return string	link
1287
	 * @param attribute the email addy
1288
	 * @param focus the parent bean
1289
	 * @param contact_id
1290
	 * @param return_module
1291
	 * @param return_action
1292
	 * @param return_id
1293
	 * @param class
1294
	 */
1295 10
	function getEmailLink($attribute, &$focus, $contact_id='', $ret_module='', $ret_action='DetailView', $ret_id='', $class='') {
1296 10
	    $emailLink = '';
1297 10
		global $sugar_config;
1298
1299 10
		if(!isset($sugar_config['email_default_client'])) {
1300
			$this->setDefaultsInConfig();
1301
		}
1302
1303 10
		$userPref = $this->getPreference('email_link_type');
1304 10
		$defaultPref = $sugar_config['email_default_client'];
1305 10
		if($userPref != '') {
1306 10
			$client = $userPref;
1307
		} else {
1308
			$client = $defaultPref;
1309
		}
1310
1311 10
		if($client == 'sugar') {
1312 10
			$email = '';
1313 10
			$to_addrs_ids = '';
1314 10
			$to_addrs_names = '';
1315 10
			$to_addrs_emails = '';
1316
1317 10
            $fullName = !empty($focus->name) ? $focus->name : '';
1318
1319 10
			if(!empty($focus->$attribute)) {
1320 1
				$email = $focus->$attribute;
1321
			}
1322
1323
1324 10
			if(empty($ret_module)) $ret_module = $focus->module_dir;
1325 10
			if(empty($ret_id)) $ret_id = $focus->id;
1326 10
			if($focus->object_name == 'Contact') {
1327
				// Bug #48555 Not User Name Format of User's locale.
1328 2
				$focus->_create_proper_name_field();
1329 2
			    $fullName = $focus->name;
1330 2
			    $contact_id = $focus->id;
1331 2
				$to_addrs_ids = $focus->id;
1332 2
				$to_addrs_names = $fullName;
1333 2
				$to_addrs_emails = $focus->email1;
1334
			}
1335
1336 10
			$emailLinkUrl = 'contact_id='.$contact_id.
1337 10
				'&parent_type='.$focus->module_dir.
1338 10
				'&parent_id='.$focus->id.
1339 10
				'&parent_name='.urlencode($fullName).
1340 10
				'&to_addrs_ids='.$to_addrs_ids.
1341 10
				'&to_addrs_names='.urlencode($to_addrs_names).
1342 10
				'&to_addrs_emails='.urlencode($to_addrs_emails).
1343 10
				'&to_email_addrs='.urlencode($fullName . '&nbsp;&lt;' . $email . '&gt;').
1344 10
				'&return_module='.$ret_module.
1345 10
				'&return_action='.$ret_action.
1346 10
				'&return_id='.$ret_id;
1347
1348
			//Generate the compose package for the quick create options.
1349 10
    		require_once('modules/Emails/EmailUI.php');
1350 10
            $eUi = new EmailUI();
1351 10
            $j_quickComposeOptions = $eUi->generateComposePackageForQuickCreateFromComposeUrl($emailLinkUrl, true);
1352 10
    		$emailLink = "<a href='javascript:void(0);' onclick='SUGAR.quickCompose.init($j_quickComposeOptions);' class='$class'>";
1353
1354
		} else {
1355
			// straight mailto:
1356
			$emailLink = '<a href="mailto:'.$focus->$attribute.'" class="'.$class.'">';
1357
		}
1358
1359 10
		return $emailLink;
1360
	}
1361
1362
1363
	/**
1364
	 * gets a human-readable explanation of the format macro
1365
	 * @return string Human readable name format
1366
	 */
1367 1
	function getLocaleFormatDesc() {
1368 1
		global $locale;
1369 1
		global $mod_strings;
1370 1
		global $app_strings;
1371
1372 1
		$format['f'] = $mod_strings['LBL_LOCALE_DESC_FIRST'];
1373 1
		$format['l'] = $mod_strings['LBL_LOCALE_DESC_LAST'];
1374 1
		$format['s'] = $mod_strings['LBL_LOCALE_DESC_SALUTATION'];
1375 1
		$format['t'] = $mod_strings['LBL_LOCALE_DESC_TITLE'];
1376
1377 1
		$name['f'] = $app_strings['LBL_LOCALE_NAME_EXAMPLE_FIRST'];
1378 1
		$name['l'] = $app_strings['LBL_LOCALE_NAME_EXAMPLE_LAST'];
1379 1
		$name['s'] = $app_strings['LBL_LOCALE_NAME_EXAMPLE_SALUTATION'];
1380 1
		$name['t'] = $app_strings['LBL_LOCALE_NAME_EXAMPLE_TITLE'];
1381
1382 1
		$macro = $locale->getLocaleFormatMacro();
1383
1384 1
		$ret1 = '';
1385 1
		$ret2 = '';
1386 1
		for($i=0; $i<strlen($macro); $i++) {
1387 1
			if(array_key_exists($macro{$i}, $format)) {
1388 1
				$ret1 .= "<i>".$format[$macro{$i}]."</i>";
1389 1
				$ret2 .= "<i>".$name[$macro{$i}]."</i>";
1390
			} else {
1391 1
				$ret1 .= $macro{$i};
1392 1
				$ret2 .= $macro{$i};
1393
			}
1394
		}
1395 1
		return $ret1."<br />".$ret2;
1396
	}
1397
1398
1399
    /*
1400
     *
1401
     * Here are the multi level admin access check functions.
1402
     *
1403
     */
1404
    /**
1405
     * Helper function to remap some modules around ACL wise
1406
     *
1407
     * @return string
1408
     */
1409 5
    protected function _fixupModuleForACL($module) {
1410 5
        if($module=='ContractTypes') {
1411
            $module = 'Contracts';
1412
        }
1413 5
        if(preg_match('/Product[a-zA-Z]*/',$module)) {
1414 5
            $module = 'Products';
1415
        }
1416
1417 5
        return $module;
1418
    }
1419
    /**
1420
     * Helper function that enumerates the list of modules and checks if they are an admin/dev.
1421
     * The code was just too similar to copy and paste.
1422
     *
1423
     * @return array
1424
     */
1425 5
    protected function _getModulesForACL($type='dev'){
1426 5
        $isDev = $type=='dev';
1427 5
        $isAdmin = $type=='admin';
1428
1429 5
        global $beanList;
1430 5
        $myModules = array();
1431
1432 5
        if (!is_array($beanList) ) {
1433
            return $myModules;
1434
        }
1435
1436
        // These modules don't take kindly to the studio trying to play about with them.
1437 5
        static $ignoredModuleList = array('iFrames','Feeds','Home','Dashboard','Calendar','Activities','Reports');
1438
1439
1440 5
        $actions = ACLAction::getUserActions($this->id);
1441
1442 5
        foreach ($beanList as $module=>$val) {
1443
            // Remap the module name
1444 5
            $module = $this->_fixupModuleForACL($module);
1445 5
            if (in_array($module,$myModules)) {
1446
                // Already have the module in the list
1447
                continue;
1448
            }
1449 5
            if (in_array($module,$ignoredModuleList)) {
1450
                // You can't develop on these modules.
1451
                continue;
1452
            }
1453
1454 5
            $focus = SugarModule::get($module)->loadBean();
1455 5
            if ( $focus instanceOf SugarBean ) {
1456 5
                $key = $focus->acltype;
1457
            } else {
1458 5
                $key = 'module';
1459
            }
1460
1461 5
            if (($this->isAdmin() && isset($actions[$module][$key]))
1462
                ) {
1463 5
                $myModules[] = $module;
1464
            }
1465
        }
1466
1467 5
        return $myModules;
1468
    }
1469
    /**
1470
     * Is this user a system wide admin
1471
     *
1472
     * @return bool
1473
     */
1474 99
    public function isAdmin() {
1475 99
        if(isset($this->is_admin)
1476 99
           &&($this->is_admin == '1' || $this->is_admin === 'on')){
1477 7
            return true;
1478
        }
1479 96
        return false;
1480
    }
1481
    /**
1482
     * Is this user a developer for any module
1483
     *
1484
     * @return bool
1485
     */
1486 3
    public function isDeveloperForAnyModule() {
1487 3
        if(empty($this->id)) {
1488
            // empty user is no developer
1489 3
            return false;
1490
        }
1491 1
        if ($this->isAdmin()) {
1492 1
            return true;
1493
        }
1494 1
        return false;
1495
    }
1496
    /**
1497
     * List the modules a user has developer access to
1498
     *
1499
     * @return array
1500
     */
1501 2
    public function getDeveloperModules() {
1502 2
        static $developerModules;
1503 2
        if (!isset($_SESSION[$this->user_name.'_get_developer_modules_for_user']) ) {
1504 2
            $_SESSION[$this->user_name.'_get_developer_modules_for_user'] = $this->_getModulesForACL('dev');
1505
        }
1506
1507 2
        return $_SESSION[$this->user_name.'_get_developer_modules_for_user'];
1508
    }
1509
    /**
1510
     * Is this user a developer for the specified module
1511
     *
1512
     * @return bool
1513
     */
1514 1
    public function isDeveloperForModule($module) {
1515 1
        if(empty($this->id)) {
1516
            // empty user is no developer
1517 1
            return false;
1518
        }
1519 1
        if ($this->isAdmin()) {
1520 1
            return true;
1521
        }
1522
1523 1
        $devModules = $this->getDeveloperModules();
1524
1525 1
        $module = $this->_fixupModuleForACL($module);
1526
1527 1
        if (in_array($module,$devModules) ) {
1528
            return true;
1529
        }
1530
1531 1
        return false;
1532
    }
1533
    /**
1534
     * List the modules a user has admin access to
1535
     *
1536
     * @return array
1537
     */
1538 3
    public function getAdminModules() {
1539 3
        if (!isset($_SESSION[$this->user_name.'_get_admin_modules_for_user']) ) {
1540 3
            $_SESSION[$this->user_name.'_get_admin_modules_for_user'] = $this->_getModulesForACL('admin');
1541
        }
1542
1543 3
        return $_SESSION[$this->user_name.'_get_admin_modules_for_user'];
1544
    }
1545
    /**
1546
     * Is this user an admin for the specified module
1547
     *
1548
     * @return bool
1549
     */
1550 52
    public function isAdminForModule($module) {
1551 52
        if(empty($this->id)) {
1552
            // empty user is no admin
1553 51
            return false;
1554
        }
1555 2
        if ($this->isAdmin()) {
1556 1
            return true;
1557
        }
1558
1559 2
        $adminModules = $this->getAdminModules();
1560
1561 2
        $module = $this->_fixupModuleForACL($module);
1562
1563 2
        if (in_array($module,$adminModules) ) {
1564
            return true;
1565
        }
1566
1567 2
        return false;
1568
    }
1569
	/**
1570
	 * Whether or not based on the user's locale if we should show the last name first.
1571
	 *
1572
	 * @return bool
1573
	 */
1574 1
	public function showLastNameFirst(){
1575 1
		global $locale;
1576 1
    	$localeFormat = $locale->getLocaleFormatMacro($this);
1577 1
		if ( strpos($localeFormat,'l') > strpos($localeFormat,'f') ) {
1578 1
                    return false;
1579
        }else {
1580
        	return true;
1581
        }
1582
	}
1583
1584 2
   function create_new_list_query($order_by, $where,$filter=array(),$params=array(), $show_deleted = 0,$join_type='', $return_array = false,$parentbean=null, $singleSelect = false,$ifListForExport = false)
1585
   {	//call parent method, specifying for array to be returned
1586 2
   	$ret_array = parent::create_new_list_query($order_by, $where,$filter,$params, $show_deleted,$join_type, true,$parentbean, $singleSelect,$ifListForExport);
1587
1588
   	//if this is being called from webservices, then run additional code
1589 2
   	if(!empty($GLOBALS['soap_server_object'])){
1590
1591
		//if this is a single select, then secondary queries are being run that may result in duplicate rows being returned through the
1592
		//left joins with meetings/tasks/call.  We need to change the left joins to include a null check (bug 40250)
1593
	   	if($singleSelect)
1594
	    	{
1595
			//retrieve the 'from' string and make lowercase for easier manipulation
1596
		        $left_str = strtolower($ret_array['from']);
1597
		        $lefts = explode('left join', $left_str);
1598
		        $new_left_str = '';
1599
1600
        		//explode on the left joins and process each one
1601
		        foreach($lefts as $ljVal){
1602
		        	//grab the join alias
1603
	        	        $onPos = strpos( $ljVal, ' on');
1604
	                	if($onPos === false){
1605
		                	$new_left_str .=' '.$ljVal.' ';
1606
		                        continue;
1607
		                }
1608
		                $spacePos = strrpos(substr($ljVal, 0, $onPos),' ');
1609
		                $alias = substr($ljVal,$spacePos,$onPos-$spacePos);
1610
1611
		                //add null check to end of the Join statement
1612
                        // Bug #46390 to use id_c field instead of id field for custom tables
1613
                        if(substr($alias, -5) != '_cstm')
1614
                        {
1615
                            $ljVal ='  LEFT JOIN '.$ljVal.' and '.$alias.'.id is null ';
1616
                        }
1617
                        else
1618
                        {
1619
                            $ljVal ='  LEFT JOIN '.$ljVal.' and '.$alias.'.id_c is null ';
1620
                        }
1621
1622
		                //add statement into new string
1623
		                $new_left_str .= $ljVal;
1624
		         }
1625
	        	 //replace the old string with the new one
1626
        		 $ret_array['from'] = $new_left_str;
1627
	    	}
1628
   	}
1629
1630
   		//return array or query string
1631 2
   		if($return_array)
1632
    	{
1633 2
    		return $ret_array;
1634
    	}
1635
1636
    	return  $ret_array['select'] . $ret_array['from'] . $ret_array['where']. $ret_array['order_by'];
1637
1638
1639
1640
   }
1641
1642
    /**
1643
     * Get user first day of week.
1644
     *
1645
     * @param [User] $user user object, current user if not specified
0 ignored issues
show
Documentation introduced by
The doc-type [User] could not be parsed: Unknown type name "" at position 0. [(view supported doc-types)

This check marks PHPDoc comments that could not be parsed by our parser. To see which comment annotations we can parse, please refer to our documentation on supported doc-types.

Loading history...
Bug introduced by
There is no parameter named $user. Was it maybe removed?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function.

Consider the following example. The parameter $italy is not defined by the method finale(...).

/**
 * @param array $germany
 * @param array $island
 * @param array $italy
 */
function finale($germany, $island) {
    return "2:1";
}

The most likely cause is that the parameter was removed, but the annotation was not.

Loading history...
1646
     * @return int : 0 = Sunday, 1 = Monday, etc...
1647
     */
1648 10
    public function get_first_day_of_week()
1649
    {
1650 10
        $fdow = $this->getPreference('fdow');
1651 10
        if (empty($fdow))
1652
        {
1653 10
            $fdow = 0;
1654
        }
1655
1656 10
        return $fdow;
1657
    }
1658
1659
    /**
1660
     * Method for password generation
1661
     *
1662
     * @static
1663
     * @return string password
1664
     */
1665 1
    public static function generatePassword()
1666
    {
1667 1
        $res = $GLOBALS['sugar_config']['passwordsetting'];
1668 1
        $charBKT = '';
1669
        //chars to select from
1670 1
        $LOWERCASE = "abcdefghijklmnpqrstuvwxyz";
1671 1
        $NUMBER = "0123456789";
1672 1
        $UPPERCASE = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
1673 1
        $SPECIAL = '~!@#$%^&*()_+=-{}|';
1674 1
        $condition = 0;
1675 1
        $charBKT .= $UPPERCASE . $LOWERCASE . $NUMBER;
1676 1
        $password = "";
1677 1
            $length = '6';
1678
1679
        // Create random characters for the ones that doesnt have requirements
1680 1
        for ($i=0; $i < $length - $condition; $i ++)  // loop and create password
1681
        {
1682 1
            $password = $password . substr ($charBKT, rand() % strlen($charBKT), 1);
1683
        }
1684
1685 1
        return $password;
1686
    }
1687
1688
    /**
1689
     * Send new password or link to user
1690
     *
1691
     * @param string $templateId Id of email template
1692
     * @param array $additionalData additional params: link, url, password
1693
     * @return array status: true|false, message: error message, if status = false and message = '' it means that send method has returned false
1694
     */
1695 1
    public function sendEmailForPassword($templateId, array $additionalData = array())
1696
    {
1697 1
        global $sugar_config, $current_user;
1698 1
        $mod_strings = return_module_language('', 'Users');
1699
        $result = array(
1700 1
            'status' => false,
1701
            'message' => ''
1702
        );
1703
1704 1
        $emailTemp = new EmailTemplate();
1705 1
        $emailTemp->disable_row_level_security = true;
1706 1
        if ($emailTemp->retrieve($templateId) == '')
1707
        {
1708 1
            $result['message'] = $mod_strings['LBL_EMAIL_TEMPLATE_MISSING'];
1709 1
            return $result;
1710
        }
1711
1712
        //replace instance variables in email templates
1713
        $htmlBody = $emailTemp->body_html;
1714
        $body = $emailTemp->body;
1715
        if (isset($additionalData['link']) && $additionalData['link'] == true)
1716
        {
1717
            $htmlBody = str_replace('$contact_user_link_guid', $additionalData['url'], $htmlBody);
1718
            $body = str_replace('$contact_user_link_guid', $additionalData['url'], $body);
1719
        }
1720
        else
1721
        {
1722
            $htmlBody = str_replace('$contact_user_user_hash', $additionalData['password'], $htmlBody);
1723
            $body = str_replace('$contact_user_user_hash', $additionalData['password'], $body);
1724
        }
1725
        // Bug 36833 - Add replacing of special value $instance_url
1726
        $htmlBody = str_replace('$config_site_url', $sugar_config['site_url'], $htmlBody);
1727
        $body = str_replace('$config_site_url', $sugar_config['site_url'], $body);
1728
1729
        $htmlBody = str_replace('$contact_user_user_name', $this->user_name, $htmlBody);
1730
        $htmlBody = str_replace('$contact_user_pwd_last_changed', TimeDate::getInstance()->nowDb(), $htmlBody);
1731
        $body = str_replace('$contact_user_user_name', $this->user_name, $body);
1732
        $body = str_replace('$contact_user_pwd_last_changed', TimeDate::getInstance()->nowDb(), $body);
1733
        $emailTemp->body_html = $htmlBody;
1734
        $emailTemp->body = $body;
1735
1736
        $itemail = $this->emailAddress->getPrimaryAddress($this);
1737
        //retrieve IT Admin Email
1738
        //_ppd( $emailTemp->body_html);
1739
        //retrieve email defaults
1740
        $emailObj = new Email();
1741
        $defaults = $emailObj->getSystemDefaultEmail();
1742
        require_once('include/SugarPHPMailer.php');
1743
        $mail = new SugarPHPMailer();
1744
        $mail->setMailerForSystem();
1745
        //$mail->IsHTML(true);
1746
        $mail->From = $defaults['email'];
1747
        $mail->FromName = $defaults['name'];
1748
        $mail->ClearAllRecipients();
1749
        $mail->ClearReplyTos();
1750
        $mail->Subject = from_html($emailTemp->subject);
1751
        if ($emailTemp->text_only != 1)
1752
        {
1753
            $mail->IsHTML(true);
1754
            $mail->Body = from_html($emailTemp->body_html);
1755
            $mail->AltBody = from_html($emailTemp->body);
1756
        }
1757
        else
1758
        {
1759
            $mail->Body_html = from_html($emailTemp->body_html);
1760
            $mail->Body = from_html($emailTemp->body);
1761
        }
1762
        if ($mail->Body == '' && $current_user->is_admin)
1763
        {
1764
            global $app_strings;
1765
            $result['message'] = $app_strings['LBL_EMAIL_TEMPLATE_EDIT_PLAIN_TEXT'];
1766
            return $result;
1767
        }
1768
        if ($mail->Mailer == 'smtp' && $mail->Host =='' && $current_user->is_admin)
1769
        {
1770
            $result['message'] = $mod_strings['ERR_SERVER_SMTP_EMPTY'];
1771
            return $result;
1772
        }
1773
1774
        $mail->prepForOutbound();
1775
        $hasRecipients = false;
1776
1777
        if (!empty($itemail))
1778
        {
1779
            if ($hasRecipients)
1780
            {
1781
                $mail->AddBCC($itemail);
1782
            }
1783
            else
1784
            {
1785
                $mail->AddAddress($itemail);
1786
            }
1787
            $hasRecipients = true;
1788
        }
1789
        if ($hasRecipients)
1790
        {
1791
            $result['status'] = @$mail->Send();
1792
        }
1793
1794
        if ($result['status'] == true)
1795
        {
1796
            $emailObj->team_id = 1;
1797
            $emailObj->to_addrs = '';
1798
            $emailObj->type = 'archived';
1799
            $emailObj->deleted = '0';
1800
            $emailObj->name = $mail->Subject ;
1801
            $emailObj->description = $mail->Body;
1802
            $emailObj->description_html = null;
1803
            $emailObj->from_addr = $mail->From;
1804
            $emailObj->parent_type = 'User';
1805
            $emailObj->date_sent = TimeDate::getInstance()->nowDb();
1806
            $emailObj->modified_user_id = '1';
1807
            $emailObj->created_by = '1';
1808
            $emailObj->status = 'sent';
1809
            $emailObj->save();
1810
            if (!isset($additionalData['link']) || $additionalData['link'] == false)
1811
            {
1812
                $this->setNewPassword($additionalData['password'], '1');
1813
            }
1814
        }
1815
1816
        return $result;
1817
    }
1818
1819
    // Bug #48014 Must to send password to imported user if this action is required
1820 1
    function afterImportSave()
1821
    {
1822
        if(
1823 1
            $this->user_hash == false
1824 1
            && !$this->is_group
1825 1
            && !$this->portal_only
1826 1
            && isset($GLOBALS['sugar_config']['passwordsetting']['SystemGeneratedPasswordON'])
1827 1
            && $GLOBALS['sugar_config']['passwordsetting']['SystemGeneratedPasswordON']
1828
        )
1829
        {
1830 1
            $backUpPost = $_POST;
1831
            $_POST = array(
1832 1
                'userId' => $this->id
1833
            );
1834 1
            ob_start();
1835 1
            require('modules/Users/GeneratePassword.php');
1836 1
            $result = ob_get_clean();
1837 1
            $_POST = $backUpPost;
1838 1
            return $result == true;
0 ignored issues
show
Bug Best Practice introduced by
It seems like you are loosely comparing $result of type string to the boolean true. If you are specifically checking for a non-empty string, consider using the more explicit !== '' instead.
Loading history...
1839
        }
1840
    }
1841
1842
    /**
1843
     * Checks if the passed email is primary.
1844
     *
1845
     * @param string $email
1846
     * @return bool Returns TRUE if the passed email is primary.
1847
     */
1848 1
    public function isPrimaryEmail($email)
1849
    {
1850 1
        if (!empty($this->email1) && !empty($email) && strcasecmp($this->email1, $email) == 0) {
1851 1
            return true;
1852
        } else {
1853 1
            return false;
1854
        }
1855
    }
1856
}
1857