Completed
Push — master ( 812bae...fa8bfe )
by Thomas
13:53
created

User::setPassword()   B

Complexity

Conditions 5
Paths 8

Size

Total Lines 17
Code Lines 12

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 5
eloc 12
nc 8
nop 2
dl 0
loc 17
rs 8.8571
c 0
b 0
f 0
1
<?php
2
/**
3
 * @author Arthur Schiwon <[email protected]>
4
 * @author Bart Visscher <[email protected]>
5
 * @author Björn Schießle <[email protected]>
6
 * @author Jörn Friedrich Dreyer <[email protected]>
7
 * @author Lukas Reschke <[email protected]>
8
 * @author Morris Jobke <[email protected]>
9
 * @author Robin Appelman <[email protected]>
10
 * @author Roeland Jago Douma <[email protected]>
11
 * @author Thomas Müller <[email protected]>
12
 *
13
 * @copyright Copyright (c) 2016, ownCloud GmbH.
14
 * @license AGPL-3.0
15
 *
16
 * This code is free software: you can redistribute it and/or modify
17
 * it under the terms of the GNU Affero General Public License, version 3,
18
 * as published by the Free Software Foundation.
19
 *
20
 * This program is distributed in the hope that it will be useful,
21
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
22
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23
 * GNU Affero General Public License for more details.
24
 *
25
 * You should have received a copy of the GNU Affero General Public License, version 3,
26
 * along with this program.  If not, see <http://www.gnu.org/licenses/>
27
 *
28
 */
29
30
namespace OC\User;
31
32
use OC\Files\Cache\Storage;
33
use OC\Hooks\Emitter;
34
use OC_Helper;
35
use OCP\IAvatarManager;
36
use OCP\IImage;
37
use OCP\IURLGenerator;
38
use OCP\IUser;
39
use OCP\IConfig;
40
use OCP\UserInterface;
41
use \OCP\IUserBackend;
42
43
class User implements IUser {
44
	/** @var string $uid */
45
	private $uid;
46
47
	/** @var string $displayName */
48
	private $displayName;
49
50
	/** @var UserInterface $backend */
51
	private $backend;
52
53
	/** @var bool $enabled */
54
	private $enabled;
55
56
	/** @var Emitter|Manager $emitter */
57
	private $emitter;
58
59
	/** @var string $home */
60
	private $home;
61
62
	/** @var int $lastLogin */
63
	private $lastLogin;
64
65
	/** @var \OCP\IConfig $config */
66
	private $config;
67
68
	/** @var IAvatarManager */
69
	private $avatarManager;
70
71
	/** @var IURLGenerator */
72
	private $urlGenerator;
73
74
	/**
75
	 * @param string $uid
76
	 * @param UserInterface $backend
77
	 * @param \OC\Hooks\Emitter $emitter
78
	 * @param IConfig|null $config
79
	 * @param IURLGenerator $urlGenerator
80
	 */
81
	public function __construct($uid, $backend, $emitter = null, IConfig $config = null, $urlGenerator = null) {
82
		$this->uid = $uid;
83
		$this->backend = $backend;
84
		$this->emitter = $emitter;
85
		if(is_null($config)) {
86
			$config = \OC::$server->getConfig();
87
		}
88
		$this->config = $config;
89
		$this->urlGenerator = $urlGenerator;
90
		$enabled = $this->config->getUserValue($uid, 'core', 'enabled', 'true');
91
		$this->enabled = ($enabled === 'true');
92
		$this->lastLogin = $this->config->getUserValue($uid, 'login', 'lastLogin', 0);
0 ignored issues
show
Documentation Bug introduced by
The property $lastLogin was declared of type integer, but $this->config->getUserVa...login', 'lastLogin', 0) is of type string. Maybe add a type cast?

This check looks for assignments to scalar types that may be of the wrong type.

To ensure the code behaves as expected, it may be a good idea to add an explicit type cast.

$answer = 42;

$correct = false;

$correct = (bool) $answer;
Loading history...
93
		if (is_null($this->urlGenerator)) {
94
			$this->urlGenerator = \OC::$server->getURLGenerator();
95
		}
96
	}
97
98
	/**
99
	 * get the user id
100
	 *
101
	 * @return string
102
	 */
103
	public function getUID() {
104
		return $this->uid;
105
	}
106
107
	/**
108
	 * get the display name for the user, if no specific display name is set it will fallback to the user id
109
	 *
110
	 * @return string
111
	 */
112
	public function getDisplayName() {
113
		if (!isset($this->displayName)) {
114
			$displayName = '';
115
			if ($this->backend and $this->backend->implementsActions(Backend::GET_DISPLAYNAME)) {
116
				// get display name and strip whitespace from the beginning and end of it
117
				$backendDisplayName = $this->backend->getDisplayName($this->uid);
118
				if (is_string($backendDisplayName)) {
119
					$displayName = trim($backendDisplayName);
120
				}
121
			}
122
123
			if (!empty($displayName)) {
124
				$this->displayName = $displayName;
125
			} else {
126
				$this->displayName = $this->uid;
127
			}
128
		}
129
		return $this->displayName;
130
	}
131
132
	/**
133
	 * set the displayname for the user
134
	 *
135
	 * @param string $displayName
136
	 * @return bool
137
	 */
138
	public function setDisplayName($displayName) {
139
		$displayName = trim($displayName);
140
		if ($this->backend->implementsActions(Backend::SET_DISPLAYNAME) && !empty($displayName)) {
141
			$result = $this->backend->setDisplayName($this->uid, $displayName);
0 ignored issues
show
Bug introduced by
It seems like you code against a concrete implementation and not the interface OCP\UserInterface as the method setDisplayName() does only exist in the following implementations of said interface: OC\User\Database.

Let’s take a look at an example:

interface User
{
    /** @return string */
    public function getPassword();
}

class MyUser implements User
{
    public function getPassword()
    {
        // return something
    }

    public function getDisplayName()
    {
        // return some name.
    }
}

class AuthSystem
{
    public function authenticate(User $user)
    {
        $this->logger->info(sprintf('Authenticating %s.', $user->getDisplayName()));
        // do something.
    }
}

In the above example, the authenticate() method works fine as long as you just pass instances of MyUser. However, if you now also want to pass a different implementation of User which does not have a getDisplayName() method, the code will break.

Available Fixes

  1. Change the type-hint for the parameter:

    class AuthSystem
    {
        public function authenticate(MyUser $user) { /* ... */ }
    }
    
  2. Add an additional type-check:

    class AuthSystem
    {
        public function authenticate(User $user)
        {
            if ($user instanceof MyUser) {
                $this->logger->info(/** ... */);
            }
    
            // or alternatively
            if ( ! $user instanceof MyUser) {
                throw new \LogicException(
                    '$user must be an instance of MyUser, '
                   .'other instances are not supported.'
                );
            }
    
        }
    }
    
Note: PHP Analyzer uses reverse abstract interpretation to narrow down the types inside the if block in such a case.
  1. Add the method to the interface:

    interface User
    {
        /** @return string */
        public function getPassword();
    
        /** @return string */
        public function getDisplayName();
    }
    
Loading history...
142
			if ($result) {
143
				$this->displayName = $displayName;
144
				$this->triggerChange('displayName', $displayName);
145
			}
146
			return $result !== false;
147
		} else {
148
			return false;
149
		}
150
	}
151
152
	/**
153
	 * set the email address of the user
154
	 *
155
	 * @param string|null $mailAddress
156
	 * @return void
157
	 * @since 9.0.0
158
	 */
159
	public function setEMailAddress($mailAddress) {
160
		if(is_null($mailAddress) || $mailAddress === '') {
161
			$this->config->deleteUserValue($this->uid, 'settings', 'email');
162
		} else {
163
			$this->config->setUserValue($this->uid, 'settings', 'email', $mailAddress);
164
		}
165
		$this->config->deleteUserValue($this->getUID(), 'owncloud', 'lostpassword');
166
		$this->triggerChange('eMailAddress', $mailAddress);
167
	}
168
169
	/**
170
	 * returns the timestamp of the user's last login or 0 if the user did never
171
	 * login
172
	 *
173
	 * @return int
174
	 */
175
	public function getLastLogin() {
176
		return $this->lastLogin;
177
	}
178
179
	/**
180
	 * updates the timestamp of the most recent login of this user
181
	 */
182
	public function updateLastLoginTimestamp() {
183
		$this->lastLogin = time();
184
		\OC::$server->getConfig()->setUserValue(
185
			$this->uid, 'login', 'lastLogin', $this->lastLogin);
186
	}
187
188
	/**
189
	 * Delete the user
190
	 *
191
	 * @return bool
192
	 */
193
	public function delete() {
194
		if ($this->emitter) {
195
			$this->emitter->emit('\OC\User', 'preDelete', array($this));
0 ignored issues
show
Bug introduced by
It seems like you code against a concrete implementation and not the interface OC\Hooks\Emitter as the method emit() does only exist in the following implementations of said interface: OCA\Files_Sharing\External\Scanner, OCA\Files_Sharing\Scanner, OC\App\CodeChecker\CodeChecker, OC\App\CodeChecker\InfoChecker, OC\Files\Cache\Scanner, OC\Files\Config\MountProviderCollection, OC\Files\Node\LazyRoot, OC\Files\Node\Root, OC\Files\ObjectStore\NoopScanner, OC\Files\Utils\Scanner, OC\Group\Manager, OC\Hooks\BasicEmitter, OC\Hooks\ForwardingEmitter, OC\Hooks\LegacyEmitter, OC\Hooks\PublicEmitter, OC\SubAdmin, OC\Updater, OC\User\Manager.

Let’s take a look at an example:

interface User
{
    /** @return string */
    public function getPassword();
}

class MyUser implements User
{
    public function getPassword()
    {
        // return something
    }

    public function getDisplayName()
    {
        // return some name.
    }
}

class AuthSystem
{
    public function authenticate(User $user)
    {
        $this->logger->info(sprintf('Authenticating %s.', $user->getDisplayName()));
        // do something.
    }
}

In the above example, the authenticate() method works fine as long as you just pass instances of MyUser. However, if you now also want to pass a different implementation of User which does not have a getDisplayName() method, the code will break.

Available Fixes

  1. Change the type-hint for the parameter:

    class AuthSystem
    {
        public function authenticate(MyUser $user) { /* ... */ }
    }
    
  2. Add an additional type-check:

    class AuthSystem
    {
        public function authenticate(User $user)
        {
            if ($user instanceof MyUser) {
                $this->logger->info(/** ... */);
            }
    
            // or alternatively
            if ( ! $user instanceof MyUser) {
                throw new \LogicException(
                    '$user must be an instance of MyUser, '
                   .'other instances are not supported.'
                );
            }
    
        }
    }
    
Note: PHP Analyzer uses reverse abstract interpretation to narrow down the types inside the if block in such a case.
  1. Add the method to the interface:

    interface User
    {
        /** @return string */
        public function getPassword();
    
        /** @return string */
        public function getDisplayName();
    }
    
Loading history...
196
		}
197
		$result = $this->backend->deleteUser($this->uid);
198
		if ($result) {
199
200
			// FIXME: Feels like an hack - suggestions?
201
202
			// We have to delete the user from all groups
203
			foreach (\OC::$server->getGroupManager()->getUserGroupIds($this) as $groupId) {
204
				\OC_Group::removeFromGroup($this->uid, $groupId);
205
			}
206
			// Delete the user's keys in preferences
207
			\OC::$server->getConfig()->deleteAllUserValues($this->uid);
208
209
			// Delete user files in /data/
210
			\OC_Helper::rmdirr($this->getHome());
211
212
			// Delete the users entry in the storage table
213
			Storage::remove('home::' . $this->uid);
214
215
			\OC::$server->getCommentsManager()->deleteReferencesOfActor('users', $this->uid);
216
			\OC::$server->getCommentsManager()->deleteReadMarksFromUser($this);
217
		}
218
219
		if ($this->emitter) {
220
			$this->emitter->emit('\OC\User', 'postDelete', array($this));
0 ignored issues
show
Bug introduced by
It seems like you code against a concrete implementation and not the interface OC\Hooks\Emitter as the method emit() does only exist in the following implementations of said interface: OCA\Files_Sharing\External\Scanner, OCA\Files_Sharing\Scanner, OC\App\CodeChecker\CodeChecker, OC\App\CodeChecker\InfoChecker, OC\Files\Cache\Scanner, OC\Files\Config\MountProviderCollection, OC\Files\Node\LazyRoot, OC\Files\Node\Root, OC\Files\ObjectStore\NoopScanner, OC\Files\Utils\Scanner, OC\Group\Manager, OC\Hooks\BasicEmitter, OC\Hooks\ForwardingEmitter, OC\Hooks\LegacyEmitter, OC\Hooks\PublicEmitter, OC\SubAdmin, OC\Updater, OC\User\Manager.

Let’s take a look at an example:

interface User
{
    /** @return string */
    public function getPassword();
}

class MyUser implements User
{
    public function getPassword()
    {
        // return something
    }

    public function getDisplayName()
    {
        // return some name.
    }
}

class AuthSystem
{
    public function authenticate(User $user)
    {
        $this->logger->info(sprintf('Authenticating %s.', $user->getDisplayName()));
        // do something.
    }
}

In the above example, the authenticate() method works fine as long as you just pass instances of MyUser. However, if you now also want to pass a different implementation of User which does not have a getDisplayName() method, the code will break.

Available Fixes

  1. Change the type-hint for the parameter:

    class AuthSystem
    {
        public function authenticate(MyUser $user) { /* ... */ }
    }
    
  2. Add an additional type-check:

    class AuthSystem
    {
        public function authenticate(User $user)
        {
            if ($user instanceof MyUser) {
                $this->logger->info(/** ... */);
            }
    
            // or alternatively
            if ( ! $user instanceof MyUser) {
                throw new \LogicException(
                    '$user must be an instance of MyUser, '
                   .'other instances are not supported.'
                );
            }
    
        }
    }
    
Note: PHP Analyzer uses reverse abstract interpretation to narrow down the types inside the if block in such a case.
  1. Add the method to the interface:

    interface User
    {
        /** @return string */
        public function getPassword();
    
        /** @return string */
        public function getDisplayName();
    }
    
Loading history...
221
		}
222
		return !($result === false);
223
	}
224
225
	/**
226
	 * Set the password of the user
227
	 *
228
	 * @param string $password
229
	 * @param string $recoveryPassword for the encryption app to reset encryption keys
230
	 * @return bool
231
	 */
232
	public function setPassword($password, $recoveryPassword = null) {
233
		if ($this->emitter) {
234
			$this->emitter->emit('\OC\User', 'preSetPassword', array($this, $password, $recoveryPassword));
0 ignored issues
show
Bug introduced by
It seems like you code against a concrete implementation and not the interface OC\Hooks\Emitter as the method emit() does only exist in the following implementations of said interface: OCA\Files_Sharing\External\Scanner, OCA\Files_Sharing\Scanner, OC\App\CodeChecker\CodeChecker, OC\App\CodeChecker\InfoChecker, OC\Files\Cache\Scanner, OC\Files\Config\MountProviderCollection, OC\Files\Node\LazyRoot, OC\Files\Node\Root, OC\Files\ObjectStore\NoopScanner, OC\Files\Utils\Scanner, OC\Group\Manager, OC\Hooks\BasicEmitter, OC\Hooks\ForwardingEmitter, OC\Hooks\LegacyEmitter, OC\Hooks\PublicEmitter, OC\SubAdmin, OC\Updater, OC\User\Manager.

Let’s take a look at an example:

interface User
{
    /** @return string */
    public function getPassword();
}

class MyUser implements User
{
    public function getPassword()
    {
        // return something
    }

    public function getDisplayName()
    {
        // return some name.
    }
}

class AuthSystem
{
    public function authenticate(User $user)
    {
        $this->logger->info(sprintf('Authenticating %s.', $user->getDisplayName()));
        // do something.
    }
}

In the above example, the authenticate() method works fine as long as you just pass instances of MyUser. However, if you now also want to pass a different implementation of User which does not have a getDisplayName() method, the code will break.

Available Fixes

  1. Change the type-hint for the parameter:

    class AuthSystem
    {
        public function authenticate(MyUser $user) { /* ... */ }
    }
    
  2. Add an additional type-check:

    class AuthSystem
    {
        public function authenticate(User $user)
        {
            if ($user instanceof MyUser) {
                $this->logger->info(/** ... */);
            }
    
            // or alternatively
            if ( ! $user instanceof MyUser) {
                throw new \LogicException(
                    '$user must be an instance of MyUser, '
                   .'other instances are not supported.'
                );
            }
    
        }
    }
    
Note: PHP Analyzer uses reverse abstract interpretation to narrow down the types inside the if block in such a case.
  1. Add the method to the interface:

    interface User
    {
        /** @return string */
        public function getPassword();
    
        /** @return string */
        public function getDisplayName();
    }
    
Loading history...
235
		}
236
		if ($this->backend->implementsActions(Backend::SET_PASSWORD)) {
237
			$result = $this->backend->setPassword($this->uid, $password);
0 ignored issues
show
Bug introduced by
It seems like you code against a concrete implementation and not the interface OCP\UserInterface as the method setPassword() does only exist in the following implementations of said interface: OC\User\Database.

Let’s take a look at an example:

interface User
{
    /** @return string */
    public function getPassword();
}

class MyUser implements User
{
    public function getPassword()
    {
        // return something
    }

    public function getDisplayName()
    {
        // return some name.
    }
}

class AuthSystem
{
    public function authenticate(User $user)
    {
        $this->logger->info(sprintf('Authenticating %s.', $user->getDisplayName()));
        // do something.
    }
}

In the above example, the authenticate() method works fine as long as you just pass instances of MyUser. However, if you now also want to pass a different implementation of User which does not have a getDisplayName() method, the code will break.

Available Fixes

  1. Change the type-hint for the parameter:

    class AuthSystem
    {
        public function authenticate(MyUser $user) { /* ... */ }
    }
    
  2. Add an additional type-check:

    class AuthSystem
    {
        public function authenticate(User $user)
        {
            if ($user instanceof MyUser) {
                $this->logger->info(/** ... */);
            }
    
            // or alternatively
            if ( ! $user instanceof MyUser) {
                throw new \LogicException(
                    '$user must be an instance of MyUser, '
                   .'other instances are not supported.'
                );
            }
    
        }
    }
    
Note: PHP Analyzer uses reverse abstract interpretation to narrow down the types inside the if block in such a case.
  1. Add the method to the interface:

    interface User
    {
        /** @return string */
        public function getPassword();
    
        /** @return string */
        public function getDisplayName();
    }
    
Loading history...
238
			if ($result) {
239
				if ($this->emitter) {
240
					$this->emitter->emit('\OC\User', 'postSetPassword', array($this, $password, $recoveryPassword));
0 ignored issues
show
Bug introduced by
It seems like you code against a concrete implementation and not the interface OC\Hooks\Emitter as the method emit() does only exist in the following implementations of said interface: OCA\Files_Sharing\External\Scanner, OCA\Files_Sharing\Scanner, OC\App\CodeChecker\CodeChecker, OC\App\CodeChecker\InfoChecker, OC\Files\Cache\Scanner, OC\Files\Config\MountProviderCollection, OC\Files\Node\LazyRoot, OC\Files\Node\Root, OC\Files\ObjectStore\NoopScanner, OC\Files\Utils\Scanner, OC\Group\Manager, OC\Hooks\BasicEmitter, OC\Hooks\ForwardingEmitter, OC\Hooks\LegacyEmitter, OC\Hooks\PublicEmitter, OC\SubAdmin, OC\Updater, OC\User\Manager.

Let’s take a look at an example:

interface User
{
    /** @return string */
    public function getPassword();
}

class MyUser implements User
{
    public function getPassword()
    {
        // return something
    }

    public function getDisplayName()
    {
        // return some name.
    }
}

class AuthSystem
{
    public function authenticate(User $user)
    {
        $this->logger->info(sprintf('Authenticating %s.', $user->getDisplayName()));
        // do something.
    }
}

In the above example, the authenticate() method works fine as long as you just pass instances of MyUser. However, if you now also want to pass a different implementation of User which does not have a getDisplayName() method, the code will break.

Available Fixes

  1. Change the type-hint for the parameter:

    class AuthSystem
    {
        public function authenticate(MyUser $user) { /* ... */ }
    }
    
  2. Add an additional type-check:

    class AuthSystem
    {
        public function authenticate(User $user)
        {
            if ($user instanceof MyUser) {
                $this->logger->info(/** ... */);
            }
    
            // or alternatively
            if ( ! $user instanceof MyUser) {
                throw new \LogicException(
                    '$user must be an instance of MyUser, '
                   .'other instances are not supported.'
                );
            }
    
        }
    }
    
Note: PHP Analyzer uses reverse abstract interpretation to narrow down the types inside the if block in such a case.
  1. Add the method to the interface:

    interface User
    {
        /** @return string */
        public function getPassword();
    
        /** @return string */
        public function getDisplayName();
    }
    
Loading history...
241
				}
242
				$this->config->deleteUserValue($this->getUID(), 'owncloud', 'lostpassword');
243
			}
244
			return !($result === false);
245
		} else {
246
			return false;
247
		}
248
	}
249
250
	/**
251
	 * get the users home folder to mount
252
	 *
253
	 * @return string
254
	 */
255
	public function getHome() {
256
		if (!$this->home) {
257
			if ($this->backend->implementsActions(Backend::GET_HOME) and $home = $this->backend->getHome($this->uid)) {
258
				$this->home = $home;
259
			} elseif ($this->config) {
260
				$this->home = $this->config->getSystemValue('datadirectory') . '/' . $this->uid;
261
			} else {
262
				$this->home = \OC::$SERVERROOT . '/data/' . $this->uid;
263
			}
264
		}
265
		return $this->home;
266
	}
267
268
	/**
269
	 * Get the name of the backend class the user is connected with
270
	 *
271
	 * @return string
272
	 */
273
	public function getBackendClassName() {
274
		if($this->backend instanceof IUserBackend) {
275
			return $this->backend->getBackendName();
276
		}
277
		return get_class($this->backend);
278
	}
279
280
	/**
281
	 * check if the backend allows the user to change his avatar on Personal page
282
	 *
283
	 * @return bool
284
	 */
285
	public function canChangeAvatar() {
286
		if ($this->backend->implementsActions(Backend::PROVIDE_AVATAR)) {
287
			return $this->backend->canChangeAvatar($this->uid);
288
		}
289
		return true;
290
	}
291
292
	/**
293
	 * check if the backend supports changing passwords
294
	 *
295
	 * @return bool
296
	 */
297
	public function canChangePassword() {
298
		return $this->backend->implementsActions(Backend::SET_PASSWORD);
299
	}
300
301
	/**
302
	 * check if the backend supports changing display names
303
	 *
304
	 * @return bool
305
	 */
306
	public function canChangeDisplayName() {
307
		if ($this->config->getSystemValue('allow_user_to_change_display_name') === false) {
308
			return false;
309
		}
310
		return $this->backend->implementsActions(Backend::SET_DISPLAYNAME);
311
	}
312
313
	/**
314
	 * check if the user is enabled
315
	 *
316
	 * @return bool
317
	 */
318
	public function isEnabled() {
319
		return $this->enabled;
320
	}
321
322
	/**
323
	 * set the enabled status for the user
324
	 *
325
	 * @param bool $enabled
326
	 */
327
	public function setEnabled($enabled) {
328
		$this->enabled = $enabled;
329
		$enabled = ($enabled) ? 'true' : 'false';
330
		$this->config->setUserValue($this->uid, 'core', 'enabled', $enabled);
331
	}
332
333
	/**
334
	 * get the users email address
335
	 *
336
	 * @return string|null
337
	 * @since 9.0.0
338
	 */
339
	public function getEMailAddress() {
340
		return $this->config->getUserValue($this->uid, 'settings', 'email', null);
341
	}
342
343
	/**
344
	 * get the users' quota
345
	 *
346
	 * @return string
347
	 * @since 9.0.0
348
	 */
349
	public function getQuota() {
350
		$quota = $this->config->getUserValue($this->uid, 'files', 'quota', 'default');
351
		if($quota === 'default') {
352
			$quota = $this->config->getAppValue('files', 'default_quota', 'none');
353
		}
354
		return $quota;
355
	}
356
357
	/**
358
	 * set the users' quota
359
	 *
360
	 * @param string $quota
361
	 * @return void
362
	 * @since 9.0.0
363
	 */
364
	public function setQuota($quota) {
365 View Code Duplication
		if($quota !== 'none' and $quota !== 'default') {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across 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...
366
			$quota = OC_Helper::computerFileSize($quota);
367
			$quota = OC_Helper::humanFileSize($quota);
0 ignored issues
show
Documentation introduced by
$quota is of type double|false, but the function expects a integer.

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...
368
		}
369
		$this->config->setUserValue($this->uid, 'files', 'quota', $quota);
370
		$this->triggerChange('quota', $quota);
371
	}
372
373
	/**
374
	 * get the avatar image if it exists
375
	 *
376
	 * @param int $size
377
	 * @return IImage|null
378
	 * @since 9.0.0
379
	 */
380
	public function getAvatarImage($size) {
381
		// delay the initialization
382
		if (is_null($this->avatarManager)) {
383
			$this->avatarManager = \OC::$server->getAvatarManager();
384
		}
385
386
		$avatar = $this->avatarManager->getAvatar($this->uid);
387
		$image = $avatar->get($size);
0 ignored issues
show
Bug Compatibility introduced by
The expression $avatar->get($size); of type boolean|OCP\IImage adds the type boolean to the return on line 389 which is incompatible with the return type declared by the interface OCP\IUser::getAvatarImage of type OCP\IImage|null.
Loading history...
388
		if ($image) {
389
			return $image;
390
		}
391
392
		return null;
393
	}
394
395
	/**
396
	 * get the federation cloud id
397
	 *
398
	 * @return string
399
	 * @since 9.0.0
400
	 */
401
	public function getCloudId() {
402
		$uid = $this->getUID();
403
		$server = $this->urlGenerator->getAbsoluteURL('/');
404
		return $uid . '@' . rtrim( $this->removeProtocolFromUrl($server), '/');
405
	}
406
407
	/**
408
	 * @param string $url
409
	 * @return string
410
	 */
411 View Code Duplication
	private function removeProtocolFromUrl($url) {
412
		if (strpos($url, 'https://') === 0) {
413
			return substr($url, strlen('https://'));
414
		} else if (strpos($url, 'http://') === 0) {
415
			return substr($url, strlen('http://'));
416
		}
417
418
		return $url;
419
	}
420
421
	public function triggerChange($feature, $value = null) {
422
		if ($this->emitter) {
423
			$this->emitter->emit('\OC\User', 'changeUser', array($this, $feature, $value));
0 ignored issues
show
Bug introduced by
It seems like you code against a concrete implementation and not the interface OC\Hooks\Emitter as the method emit() does only exist in the following implementations of said interface: OCA\Files_Sharing\External\Scanner, OCA\Files_Sharing\Scanner, OC\App\CodeChecker\CodeChecker, OC\App\CodeChecker\InfoChecker, OC\Files\Cache\Scanner, OC\Files\Config\MountProviderCollection, OC\Files\Node\LazyRoot, OC\Files\Node\Root, OC\Files\ObjectStore\NoopScanner, OC\Files\Utils\Scanner, OC\Group\Manager, OC\Hooks\BasicEmitter, OC\Hooks\ForwardingEmitter, OC\Hooks\LegacyEmitter, OC\Hooks\PublicEmitter, OC\SubAdmin, OC\Updater, OC\User\Manager.

Let’s take a look at an example:

interface User
{
    /** @return string */
    public function getPassword();
}

class MyUser implements User
{
    public function getPassword()
    {
        // return something
    }

    public function getDisplayName()
    {
        // return some name.
    }
}

class AuthSystem
{
    public function authenticate(User $user)
    {
        $this->logger->info(sprintf('Authenticating %s.', $user->getDisplayName()));
        // do something.
    }
}

In the above example, the authenticate() method works fine as long as you just pass instances of MyUser. However, if you now also want to pass a different implementation of User which does not have a getDisplayName() method, the code will break.

Available Fixes

  1. Change the type-hint for the parameter:

    class AuthSystem
    {
        public function authenticate(MyUser $user) { /* ... */ }
    }
    
  2. Add an additional type-check:

    class AuthSystem
    {
        public function authenticate(User $user)
        {
            if ($user instanceof MyUser) {
                $this->logger->info(/** ... */);
            }
    
            // or alternatively
            if ( ! $user instanceof MyUser) {
                throw new \LogicException(
                    '$user must be an instance of MyUser, '
                   .'other instances are not supported.'
                );
            }
    
        }
    }
    
Note: PHP Analyzer uses reverse abstract interpretation to narrow down the types inside the if block in such a case.
  1. Add the method to the interface:

    interface User
    {
        /** @return string */
        public function getPassword();
    
        /** @return string */
        public function getDisplayName();
    }
    
Loading history...
424
		}
425
	}
426
}
427