Completed
Push — master ( e72c23...de047a )
by Jeroen
25:41
created

ElggUser::setLastLogin()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 13
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 6

Importance

Changes 0
Metric Value
cc 2
eloc 6
nc 2
nop 0
dl 0
loc 13
ccs 0
cts 7
cp 0
crap 6
rs 9.4285
c 0
b 0
f 0
1
<?php
2
/**
3
 * A user entity
4
 *
5
 * @property      string $name             The display name that the user will be known by in the network
6
 * @property      string $username         The short, reference name for the user in the network
7
 * @property      string $email            The email address to which Elgg will send email notifications
8
 * @property      string $language         The language preference of the user (ISO 639-1 formatted)
9
 * @property      string $banned           'yes' if the user is banned from the network, 'no' otherwise
10
 * @property      string $admin            'yes' if the user is an administrator of the network, 'no' otherwise
11
 * @property-read string $password_hash    The hashed password of the user
12
 * @property-read int    $prev_last_action A UNIX timestamp of the previous last action
13
 * @property-read int    $last_login       A UNIX timestamp of the last login
14
 * @property-read int    $prev_last_login  A UNIX timestamp of the previous login
15
 */
16
class ElggUser extends \ElggEntity
17
	implements Friendable {
18
19
	/**
20
	 * {@inheritdoc}
21
	 */
22 504
	public function getType() {
23 504
		return 'user';
24
	}
25
	
26
	/**
27
	 * Get user language or default to site language
28
	 *
29
	 * @param string $fallback If this is provided, it will be returned if the user doesn't have a language set.
30
	 *                         If null, the site language will be returned.
31
	 *
32
	 * @return string
33
	 */
34
	public function getLanguage($fallback = null) {
35
		if (!empty($this->language)) {
36
			return $this->language;
37
		}
38
		if ($fallback !== null) {
39
			return $fallback;
40
		}
41
		return elgg_get_config('language');
42
	}
43
44
	/**
45
	 * {@inheritdoc}
46
	 */
47 286
	public function __set($name, $value) {
48
		switch ($name) {
49 286
			case 'salt':
50 286
			case 'password':
51
				_elgg_services()->logger->error("User entities no longer contain {$name}");
52
				return;
53 286
			case 'password_hash':
54
				_elgg_services()->logger->error("password_hash is a readonly attribute.");
55
				return;
56 286
			case 'email':
57 275
				if (!validate_email_address($value)) {
58
					throw new \InvalidParameterException("Email is not a valid email address");
59
				}
60 275
				break;
61 286
			case 'username':
62 286
				if (!validate_username($value)) {
63
					throw new \InvalidParameterException("Username is not a valid username");
64
				}
65 286
				$existing_user = get_user_by_username($value);
66 286
				if ($existing_user && ($existing_user->guid !== $this->guid)) {
67
					throw new \InvalidParameterException("{$name} is supposed to be unique for ElggUser");
68
				}
69 286
				break;
70
		}
71
		
72 286
		parent::__set($name, $value);
73 286
	}
74
	
75
	/**
76
	 * {@inheritdoc}
77
	 */
78 3
	public function getURL() {
79
		
80 3
		$result = parent::getURL();
81 3
		if ($result !== '') {
82
			return $result;
83
		}
84
		
85 3
		return elgg_normalize_url("user/view/{$this->guid}");
86
	}
87
88
	/**
89
	 * Ban this user.
90
	 *
91
	 * @param string $reason Optional reason
92
	 *
93
	 * @return bool
94
	 */
95 62 View Code Duplication
	public function ban($reason = '') {
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
96
97 62
		if (!$this->canEdit()) {
98
			return false;
99
		}
100
		
101 62
		if (!elgg_trigger_event('ban', 'user', $this)) {
0 ignored issues
show
Documentation introduced by
$this is of type this<ElggUser>, but the function expects a string|null.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
102
			return false;
103
		}
104
105 62
		$this->ban_reason = $reason;
1 ignored issue
show
Documentation introduced by
The property ban_reason does not exist on object<ElggUser>. Since you implemented __set, maybe consider adding a @property annotation.

Since your code implements the magic setter _set, this function will be called for any write access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

Since the property has write access only, you can use the @property-write annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
106 62
		$this->banned = 'yes';
107
				
108 62
		_elgg_invalidate_cache_for_entity($this->guid);
109 62
		_elgg_invalidate_memcache_for_entity($this->guid);
110
111 62
		return true;
112
	}
113
114
	/**
115
	 * Unban this user.
116
	 *
117
	 * @return bool
118
	 */
119 1 View Code Duplication
	public function unban() {
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
120
		
121 1
		if (!$this->canEdit()) {
122
			return false;
123
		}
124
125 1
		if (!elgg_trigger_event('unban', 'user', $this)) {
0 ignored issues
show
Documentation introduced by
$this is of type this<ElggUser>, but the function expects a string|null.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
126
			return false;
127
		}
128
129 1
		unset($this->ban_reason);
130 1
		$this->banned = 'yes';
131
				
132 1
		_elgg_invalidate_cache_for_entity($this->guid);
133 1
		_elgg_invalidate_memcache_for_entity($this->guid);
134
135 1
		return true;
136
	}
137
138
	/**
139
	 * Is this user banned or not?
140
	 *
141
	 * @return bool
142
	 */
143 20
	public function isBanned() {
144 20
		return $this->banned == 'yes';
145
	}
146
147
	/**
148
	 * Is this user admin?
149
	 *
150
	 * @return bool
151
	 */
152 450
	public function isAdmin() {
153 450
		$ia = elgg_set_ignore_access(true);
154 450
		$is_admin = ($this->admin == 'yes');
155 450
		elgg_set_ignore_access($ia);
156
		
157 450
		return $is_admin;
158
	}
159
160
	/**
161
	 * Make the user an admin
162
	 *
163
	 * @return bool
164
	 */
165 4 View Code Duplication
	public function makeAdmin() {
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
166
		
167 4
		if ($this->isAdmin()) {
168
			return true;
169
		}
170
171 4
		if (!elgg_trigger_event('make_admin', 'user', $this)) {
0 ignored issues
show
Documentation introduced by
$this is of type this<ElggUser>, but the function expects a string|null.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
172
			return false;
173
		}
174
175 4
		$this->admin = 'yes';
176
177 4
		_elgg_invalidate_cache_for_entity($this->guid);
178 4
		_elgg_invalidate_memcache_for_entity($this->guid);
179
		
180 4
		return true;
181
	}
182
183
	/**
184
	 * Remove the admin flag for user
185
	 *
186
	 * @return bool
187
	 */
188 2 View Code Duplication
	public function removeAdmin() {
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
189
190 2
		if (!$this->isAdmin()) {
191 1
			return true;
192
		}
193
194 1
		if (!elgg_trigger_event('remove_admin', 'user', $this)) {
0 ignored issues
show
Documentation introduced by
$this is of type this<ElggUser>, but the function expects a string|null.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
195
			return false;
196
		}
197
198 1
		$this->admin = 'no';
199
200 1
		_elgg_invalidate_cache_for_entity($this->guid);
201 1
		_elgg_invalidate_memcache_for_entity($this->guid);
202
		
203 1
		return true;
204
	}
205
	
206
	/**
207
	 * Sets the last logon time of the user to right now.
208
	 *
209
	 * @return void
210
	 */
211
	public function setLastLogin() {
212
		
213
		$time = $this->getCurrentTime()->getTimestamp();
214
		
215
		if ($this->last_login == $time) {
216
			// no change required
217
			return;
218
		}
219
		
220
		// these writes actually work, we just type hint read-only.
221
		$this->prev_last_login = $user->last_login;
0 ignored issues
show
Bug introduced by
The variable $user does not exist. Did you forget to declare it?

This check marks access to variables or properties that have not been declared yet. While PHP has no explicit notion of declaring a variable, accessing it before a value is assigned to it is most likely a bug.

Loading history...
222
		$this->last_login = $time;
223
	}
224
	
225
	/**
226
	 * Sets the last action time of the given user to right now.
227
	 *
228
	 * @see _elgg_session_boot The session boot calls this at the beginning of every request
229
	 *
230
	 * @return void
231
	 */
232
	public function setLastAction() {
233
		
234
		$time = $this->getCurrentTime()->getTimestamp();
235
		
236
		if ($this->last_action == $time) {
237
			// no change required
238
			return;
239
		}
240
		
241
		// these writes actually work, we just type hint read-only.
242
		$this->prev_last_action = $this->last_action;
243
		$this->last_action = $time;
244
	}
245
	
246
	/**
247
	 * Gets the validation status of a user.
248
	 *
249
	 * @return bool|null Null means status was not set for this user.
250
	 */
251
	public function isValidated() {
252
		if (!isset($this->validated)) {
253
			return null;
254
		}
255
		return (bool) $this->validated;
256
	}
257
	
258
	/**
259
	 * Set the validation status for a user.
260
	 *
261
	 * @param bool   $status    Validated (true) or unvalidated (false)
262
	 * @param string $method    Optional method to say how a user was validated
263
	 * @return void
264
	 */
265 63
	public function setValidationStatus($status, $method = '') {
266
		
267 63
		$this->validated = $status;
1 ignored issue
show
Documentation introduced by
The property validated does not exist on object<ElggUser>. Since you implemented __set, maybe consider adding a @property annotation.

Since your code implements the magic setter _set, this function will be called for any write access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

Since the property has write access only, you can use the @property-write annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
268 63
		$this->validated_method = $method;
1 ignored issue
show
Documentation introduced by
The property validated_method does not exist on object<ElggUser>. Since you implemented __set, maybe consider adding a @property annotation.

Since your code implements the magic setter _set, this function will be called for any write access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

Since the property has write access only, you can use the @property-write annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
269
		
270 63
		if ((bool) $status) {
271 44
			elgg_trigger_after_event('validate', 'user', $this);
0 ignored issues
show
Documentation introduced by
$this is of type this<ElggUser>, but the function expects a string|null.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
272
		} else {
273 26
			elgg_trigger_after_event('invalidate', 'user', $this);
0 ignored issues
show
Documentation introduced by
$this is of type this<ElggUser>, but the function expects a string|null.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
274
		}
275 63
	}
276
277
	/**
278
	 * Adds a user as a friend
279
	 *
280
	 * @param int  $friend_guid       The GUID of the user to add
281
	 * @param bool $create_river_item Create the river item announcing this friendship
282
	 *
283
	 * @return bool
284
	 */
285 1
	public function addFriend($friend_guid, $create_river_item = false) {
286 1
		if (!get_user($friend_guid)) {
287
			return false;
288
		}
289
290 1
		if (!add_entity_relationship($this->guid, "friend", $friend_guid)) {
291
			return false;
292
		}
293
294 1
		if ($create_river_item) {
295
			elgg_create_river_item([
296
				'view' => 'river/relationship/friend/create',
297
				'action_type' => 'friend',
298
				'subject_guid' => $this->guid,
299
				'object_guid' => $friend_guid,
300
			]);
301
		}
302
303 1
		return true;
304
	}
305
306
	/**
307
	 * Removes a user as a friend
308
	 *
309
	 * @param int $friend_guid The GUID of the user to remove
310
	 * @return bool
311
	 */
312
	public function removeFriend($friend_guid) {
313
		return $this->removeRelationship($friend_guid, 'friend');
314
	}
315
316
	/**
317
	 * Determines whether or not this user is a friend of the currently logged in user
318
	 *
319
	 * @return bool
320
	 */
321
	public function isFriend() {
322
		return $this->isFriendOf(_elgg_services()->session->getLoggedInUserGuid());
323
	}
324
325
	/**
326
	 * Determines whether this user is friends with another user
327
	 *
328
	 * @param int $user_guid The GUID of the user to check against
329
	 *
330
	 * @return bool
331
	 */
332
	public function isFriendsWith($user_guid) {
333
		return (bool) check_entity_relationship($this->guid, "friend", $user_guid);
334
	}
335
336
	/**
337
	 * Determines whether or not this user is another user's friend
338
	 *
339
	 * @param int $user_guid The GUID of the user to check against
340
	 *
341
	 * @return bool
342
	 */
343
	public function isFriendOf($user_guid) {
344
		return (bool) check_entity_relationship($user_guid, "friend", $this->guid);
345
	}
346
347
	/**
348
	 * {@inheritdoc}
349
	 */
350 View Code Duplication
	public function getFriends(array $options = []) {
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
351
		$options['relationship'] = 'friend';
352
		$options['relationship_guid'] = $this->getGUID();
353
		$options['type'] = 'user';
354
355
		return elgg_get_entities_from_relationship($options);
0 ignored issues
show
Bug Best Practice introduced by
The return type of return elgg_get_entities...relationship($options); (false|ElggBatch|integer|array) is incompatible with the return type declared by the interface Friendable::getFriends of type array|false.

If you return a value from a function or method, it should be a sub-type of the type that is given by the parent type f.e. an interface, or abstract method. This is more formally defined by the Lizkov substitution principle, and guarantees that classes that depend on the parent type can use any instance of a child type interchangably. This principle also belongs to the SOLID principles for object oriented design.

Let’s take a look at an example:

class Author {
    private $name;

    public function __construct($name) {
        $this->name = $name;
    }

    public function getName() {
        return $this->name;
    }
}

abstract class Post {
    public function getAuthor() {
        return 'Johannes';
    }
}

class BlogPost extends Post {
    public function getAuthor() {
        return new Author('Johannes');
    }
}

class ForumPost extends Post { /* ... */ }

function my_function(Post $post) {
    echo strtoupper($post->getAuthor());
}

Our function my_function expects a Post object, and outputs the author of the post. The base class Post returns a simple string and outputting a simple string will work just fine. However, the child class BlogPost which is a sub-type of Post instead decided to return an object, and is therefore violating the SOLID principles. If a BlogPost were passed to my_function, PHP would not complain, but ultimately fail when executing the strtoupper call in its body.

Loading history...
356
	}
357
358
	/**
359
	 * {@inheritdoc}
360
	 */
361 View Code Duplication
	public function getFriendsOf(array $options = []) {
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
362
		$options['relationship'] = 'friend';
363
		$options['relationship_guid'] = $this->getGUID();
364
		$options['inverse_relationship'] = true;
365
		$options['type'] = 'user';
366
367
		return elgg_get_entities_from_relationship($options);
0 ignored issues
show
Bug Best Practice introduced by
The return type of return elgg_get_entities...relationship($options); (false|ElggBatch|integer|array) is incompatible with the return type declared by the interface Friendable::getFriendsOf of type array|false.

If you return a value from a function or method, it should be a sub-type of the type that is given by the parent type f.e. an interface, or abstract method. This is more formally defined by the Lizkov substitution principle, and guarantees that classes that depend on the parent type can use any instance of a child type interchangably. This principle also belongs to the SOLID principles for object oriented design.

Let’s take a look at an example:

class Author {
    private $name;

    public function __construct($name) {
        $this->name = $name;
    }

    public function getName() {
        return $this->name;
    }
}

abstract class Post {
    public function getAuthor() {
        return 'Johannes';
    }
}

class BlogPost extends Post {
    public function getAuthor() {
        return new Author('Johannes');
    }
}

class ForumPost extends Post { /* ... */ }

function my_function(Post $post) {
    echo strtoupper($post->getAuthor());
}

Our function my_function expects a Post object, and outputs the author of the post. The base class Post returns a simple string and outputting a simple string will work just fine. However, the child class BlogPost which is a sub-type of Post instead decided to return an object, and is therefore violating the SOLID principles. If a BlogPost were passed to my_function, PHP would not complain, but ultimately fail when executing the strtoupper call in its body.

Loading history...
368
	}
369
370
	/**
371
	 * Gets the user's groups
372
	 *
373
	 * @param array $options Options array.
374
	 *
375
	 * @return array|false Array of \ElggGroup, or false, depending on success
376
	 */
377
	public function getGroups(array $options = []) {
378
		$options['type'] = 'group';
379
		$options['relationship'] = 'member';
380
		$options['relationship_guid'] = $this->guid;
381
382
		return elgg_get_entities_from_relationship($options);
383
	}
384
385
	/**
386
	 * {@inheritdoc}
387
	 */
388
	public function getObjects(array $options = []) {
389
		$options['type'] = 'object';
390
		$options['owner_guid'] = $this->getGUID();
391
392
		return elgg_get_entities($options);
0 ignored issues
show
Bug Best Practice introduced by
The return type of return elgg_get_entities($options); (ElggBatch|false|integer|array) is incompatible with the return type declared by the interface Friendable::getObjects of type array|false.

If you return a value from a function or method, it should be a sub-type of the type that is given by the parent type f.e. an interface, or abstract method. This is more formally defined by the Lizkov substitution principle, and guarantees that classes that depend on the parent type can use any instance of a child type interchangably. This principle also belongs to the SOLID principles for object oriented design.

Let’s take a look at an example:

class Author {
    private $name;

    public function __construct($name) {
        $this->name = $name;
    }

    public function getName() {
        return $this->name;
    }
}

abstract class Post {
    public function getAuthor() {
        return 'Johannes';
    }
}

class BlogPost extends Post {
    public function getAuthor() {
        return new Author('Johannes');
    }
}

class ForumPost extends Post { /* ... */ }

function my_function(Post $post) {
    echo strtoupper($post->getAuthor());
}

Our function my_function expects a Post object, and outputs the author of the post. The base class Post returns a simple string and outputting a simple string will work just fine. However, the child class BlogPost which is a sub-type of Post instead decided to return an object, and is therefore violating the SOLID principles. If a BlogPost were passed to my_function, PHP would not complain, but ultimately fail when executing the strtoupper call in its body.

Loading history...
393
	}
394
395
	/**
396
	 * {@inheritdoc}
397
	 */
398 View Code Duplication
	public function getFriendsObjects(array $options = []) {
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
399
		$options['type'] = 'object';
400
		$options['relationship'] = 'friend';
401
		$options['relationship_guid'] = $this->getGUID();
402
		$options['relationship_join_on'] = 'container_guid';
403
404
		return elgg_get_entities_from_relationship($options);
0 ignored issues
show
Bug Best Practice introduced by
The return type of return elgg_get_entities...relationship($options); (false|ElggBatch|integer|array) is incompatible with the return type declared by the interface Friendable::getFriendsObjects of type array|false.

If you return a value from a function or method, it should be a sub-type of the type that is given by the parent type f.e. an interface, or abstract method. This is more formally defined by the Lizkov substitution principle, and guarantees that classes that depend on the parent type can use any instance of a child type interchangably. This principle also belongs to the SOLID principles for object oriented design.

Let’s take a look at an example:

class Author {
    private $name;

    public function __construct($name) {
        $this->name = $name;
    }

    public function getName() {
        return $this->name;
    }
}

abstract class Post {
    public function getAuthor() {
        return 'Johannes';
    }
}

class BlogPost extends Post {
    public function getAuthor() {
        return new Author('Johannes');
    }
}

class ForumPost extends Post { /* ... */ }

function my_function(Post $post) {
    echo strtoupper($post->getAuthor());
}

Our function my_function expects a Post object, and outputs the author of the post. The base class Post returns a simple string and outputting a simple string will work just fine. However, the child class BlogPost which is a sub-type of Post instead decided to return an object, and is therefore violating the SOLID principles. If a BlogPost were passed to my_function, PHP would not complain, but ultimately fail when executing the strtoupper call in its body.

Loading history...
405
	}
406
407
	/**
408
	 * Get a user's owner GUID
409
	 *
410
	 * Returns it's own GUID if the user is not owned.
411
	 *
412
	 * @return int
413
	 */
414
	public function getOwnerGUID() {
415
		if ($this->owner_guid == 0) {
416
			return $this->guid;
417
		}
418
419
		return $this->owner_guid;
420
	}
421
422
	/**
423
	 * {@inheritdoc}
424
	 */
425
	protected function prepareObject($object) {
426
		$object = parent::prepareObject($object);
427
		$object->name = $this->getDisplayName();
428
		$object->username = $this->username;
429
		$object->language = $this->language;
430
		unset($object->read_access);
431
		return $object;
432
	}
433
434
	/**
435
	 * Can a user comment on this user?
436
	 *
437
	 * @see \ElggEntity::canComment()
438
	 *
439
	 * @param int  $user_guid User guid (default is logged in user)
440
	 * @param bool $default   Default permission
441
	 * @return bool
442
	 * @since 1.8.0
443
	 */
444 1
	public function canComment($user_guid = 0, $default = null) {
445 1
		$result = parent::canComment($user_guid, $default);
446 1
		if ($result !== null) {
447
			return $result;
448
		}
449 1
		return false;
450
	}
451
452
	/**
453
	 * Set the necessary metadata to store a hash of the user's password.
454
	 *
455
	 * @param string $password The password to be hashed
456
	 * @return void
457
	 * @since 1.10.0
458
	 */
459 63
	public function setPassword($password) {
460 63
		$this->setMetadata('password_hash', _elgg_services()->passwords->generateHash($password));
461 63
	}
462
463
	/**
464
	 * Enable or disable a notification delivery method
465
	 *
466
	 * @param string $method  Method name
467
	 * @param bool   $enabled Enabled or disabled
468
	 * @return bool
469
	 */
470 64
	public function setNotificationSetting($method, $enabled = true) {
471 64
		$this->{"notification:method:$method"} = (int) $enabled;
472 64
		return (bool) $this->save();
473
	}
474
475
	/**
476
	 * Returns users's notification settings
477
	 * <code>
478
	 *    [
479
	 *       'email' => true, // enabled
480
	 *       'ajax' => false, // disabled
481
	 *    ]
482
	 * </code>
483
	 *
484
	 * @return array
485
	 */
486 19
	public function getNotificationSettings() {
487
488 19
		$settings = [];
489
490 19
		$methods = _elgg_services()->notifications->getMethods();
491 19
		foreach ($methods as $method) {
492 19
			$settings[$method] = (bool) $this->{"notification:method:$method"};
493
		}
494
495 19
		return $settings;
496
	
497
	}
498
}
499