Completed
Pull Request — master (#3297)
by Robin
14:21 queued 05:09
created

User::setQuota()   A

Complexity

Conditions 3
Paths 2

Size

Total Lines 8
Code Lines 6

Duplication

Lines 4
Ratio 50 %

Importance

Changes 0
Metric Value
cc 3
eloc 6
nc 2
nop 1
dl 4
loc 8
rs 9.4285
c 0
b 0
f 0
1
<?php
2
/**
3
 * @copyright Copyright (c) 2016, ownCloud, Inc.
4
 *
5
 * @author Arthur Schiwon <[email protected]>
6
 * @author Bart Visscher <[email protected]>
7
 * @author Björn Schießle <[email protected]>
8
 * @author Jörn Friedrich Dreyer <[email protected]>
9
 * @author Lukas Reschke <[email protected]>
10
 * @author Morris Jobke <[email protected]>
11
 * @author Robin Appelman <[email protected]>
12
 * @author Roeland Jago Douma <[email protected]>
13
 * @author Thomas Müller <[email protected]>
14
 *
15
 * @license AGPL-3.0
16
 *
17
 * This code is free software: you can redistribute it and/or modify
18
 * it under the terms of the GNU Affero General Public License, version 3,
19
 * as published by the Free Software Foundation.
20
 *
21
 * This program is distributed in the hope that it will be useful,
22
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
23
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24
 * GNU Affero General Public License for more details.
25
 *
26
 * You should have received a copy of the GNU Affero General Public License, version 3,
27
 * along with this program.  If not, see <http://www.gnu.org/licenses/>
28
 *
29
 */
30
31
namespace OC\User;
32
33
use OC\Files\Cache\Storage;
34
use OC\Hooks\Emitter;
35
use OC_Helper;
36
use OCP\IAvatarManager;
37
use OCP\IImage;
38
use OCP\IURLGenerator;
39
use OCP\IUser;
40
use OCP\IConfig;
41
use OCP\UserInterface;
42
use \OCP\IUserBackend;
43
44
class User implements IUser {
45
	/** @var string $uid */
46
	private $uid;
47
48
	/** @var string $displayName */
49
	private $displayName;
50
51
	/** @var UserInterface $backend */
52
	private $backend;
53
54
	/** @var bool $enabled */
55
	private $enabled;
56
57
	/** @var Emitter|Manager $emitter */
58
	private $emitter;
59
60
	/** @var string $home */
61
	private $home;
62
63
	/** @var int $lastLogin */
64
	private $lastLogin;
65
66
	/** @var \OCP\IConfig $config */
67
	private $config;
68
69
	/** @var IAvatarManager */
70
	private $avatarManager;
71
72
	/** @var IURLGenerator */
73
	private $urlGenerator;
74
75
	/**
76
	 * @param string $uid
77
	 * @param UserInterface $backend
78
	 * @param \OC\Hooks\Emitter $emitter
79
	 * @param IConfig|null $config
80
	 * @param IURLGenerator $urlGenerator
81
	 */
82
	public function __construct($uid, $backend, $emitter = null, IConfig $config = null, $urlGenerator = null) {
83
		$this->uid = $uid;
84
		$this->backend = $backend;
85
		$this->emitter = $emitter;
86
		if(is_null($config)) {
87
			$config = \OC::$server->getConfig();
88
		}
89
		$this->config = $config;
90
		$this->urlGenerator = $urlGenerator;
91
		$enabled = $this->config->getUserValue($uid, 'core', 'enabled', 'true');
92
		$this->enabled = ($enabled === 'true');
93
		$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...
94
		if (is_null($this->urlGenerator)) {
95
			$this->urlGenerator = \OC::$server->getURLGenerator();
96
		}
97
	}
98
99
	/**
100
	 * get the user id
101
	 *
102
	 * @return string
103
	 */
104
	public function getUID() {
105
		return $this->uid;
106
	}
107
108
	/**
109
	 * get the display name for the user, if no specific display name is set it will fallback to the user id
110
	 *
111
	 * @return string
112
	 */
113
	public function getDisplayName() {
114
		if (!isset($this->displayName)) {
115
			$displayName = '';
116
			if ($this->backend and $this->backend->implementsActions(Backend::GET_DISPLAYNAME)) {
117
				// get display name and strip whitespace from the beginning and end of it
118
				$backendDisplayName = $this->backend->getDisplayName($this->uid);
119
				if (is_string($backendDisplayName)) {
120
					$displayName = trim($backendDisplayName);
121
				}
122
			}
123
124
			if (!empty($displayName)) {
125
				$this->displayName = $displayName;
126
			} else {
127
				$this->displayName = $this->uid;
128
			}
129
		}
130
		return $this->displayName;
131
	}
132
133
	/**
134
	 * set the displayname for the user
135
	 *
136
	 * @param string $displayName
137
	 * @return bool
138
	 */
139
	public function setDisplayName($displayName) {
140
		$displayName = trim($displayName);
141
		if ($this->backend->implementsActions(Backend::SET_DISPLAYNAME) && !empty($displayName)) {
142
			$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: OCA\Testing\AlternativeHomeUserBackend, 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...
143
			if ($result) {
144
				$this->displayName = $displayName;
145
				$this->triggerChange('displayName', $displayName);
146
			}
147
			return $result !== false;
148
		} else {
149
			return false;
150
		}
151
	}
152
153
	/**
154
	 * set the email address of the user
155
	 *
156
	 * @param string|null $mailAddress
157
	 * @return void
158
	 * @since 9.0.0
159
	 */
160
	public function setEMailAddress($mailAddress) {
161
		if($mailAddress === '') {
162
			$this->config->deleteUserValue($this->uid, 'settings', 'email');
163
		} else {
164
			$this->config->setUserValue($this->uid, 'settings', 'email', $mailAddress);
165
		}
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
		$firstTimeLogin = ($this->lastLogin === 0);
184
		$this->lastLogin = time();
185
		$this->config->setUserValue(
186
			$this->uid, 'login', 'lastLogin', $this->lastLogin);
187
188
		return $firstTimeLogin;
189
	}
190
191
	/**
192
	 * Delete the user
193
	 *
194
	 * @return bool
195
	 */
196
	public function delete() {
197
		if ($this->emitter) {
198
			$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...
199
		}
200
		// get the home now because it won't return it after user deletion
201
		$homePath = $this->getHome();
202
		$result = $this->backend->deleteUser($this->uid);
203
		if ($result) {
204
205
			// FIXME: Feels like an hack - suggestions?
206
207
			// We have to delete the user from all groups
208
			foreach (\OC::$server->getGroupManager()->getUserGroupIds($this) as $groupId) {
209
				\OC_Group::removeFromGroup($this->uid, $groupId);
210
			}
211
			// Delete the user's keys in preferences
212
			\OC::$server->getConfig()->deleteAllUserValues($this->uid);
213
214
			// Delete user files in /data/
215
			if ($homePath !== false) {
216
				// FIXME: this operates directly on FS, should use View instead...
217
				// also this is not testable/mockable...
218
				\OC_Helper::rmdirr($homePath);
219
			}
220
221
			// Delete the users entry in the storage table
222
			Storage::remove('home::' . $this->uid);
223
224
			\OC::$server->getCommentsManager()->deleteReferencesOfActor('users', $this->uid);
225
			\OC::$server->getCommentsManager()->deleteReadMarksFromUser($this);
226
227
			$notification = \OC::$server->getNotificationManager()->createNotification();
228
			$notification->setUser($this->uid);
229
			\OC::$server->getNotificationManager()->markProcessed($notification);
230
231
			if ($this->emitter) {
232
				$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...
233
			}
234
		}
235
		return !($result === false);
236
	}
237
238
	/**
239
	 * Set the password of the user
240
	 *
241
	 * @param string $password
242
	 * @param string $recoveryPassword for the encryption app to reset encryption keys
243
	 * @return bool
244
	 */
245
	public function setPassword($password, $recoveryPassword = null) {
246
		if ($this->emitter) {
247
			$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...
248
		}
249
		if ($this->backend->implementsActions(Backend::SET_PASSWORD)) {
250
			$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: OCA\Testing\AlternativeHomeUserBackend, OCA\User_LDAP\User_LDAP, OCA\User_LDAP\User_Proxy, 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...
251
			if ($this->emitter) {
252
				$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...
253
			}
254
			return !($result === false);
255
		} else {
256
			return false;
257
		}
258
	}
259
260
	/**
261
	 * get the users home folder to mount
262
	 *
263
	 * @return string
264
	 */
265
	public function getHome() {
266
		if (!$this->home) {
267
			if ($this->backend->implementsActions(Backend::GET_HOME) and $home = $this->backend->getHome($this->uid)) {
268
				$this->home = $home;
269
			} elseif ($this->config) {
270
				$this->home = $this->config->getSystemValue('datadirectory', \OC::$SERVERROOT . '/data') . '/' . $this->uid;
271
			} else {
272
				$this->home = \OC::$SERVERROOT . '/data/' . $this->uid;
273
			}
274
		}
275
		return $this->home;
276
	}
277
278
	/**
279
	 * Get the name of the backend class the user is connected with
280
	 *
281
	 * @return string
282
	 */
283
	public function getBackendClassName() {
284
		if($this->backend instanceof IUserBackend) {
285
			return $this->backend->getBackendName();
286
		}
287
		return get_class($this->backend);
288
	}
289
290
	/**
291
	 * check if the backend allows the user to change his avatar on Personal page
292
	 *
293
	 * @return bool
294
	 */
295
	public function canChangeAvatar() {
296
		if ($this->backend->implementsActions(Backend::PROVIDE_AVATAR)) {
297
			return $this->backend->canChangeAvatar($this->uid);
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 canChangeAvatar() does only exist in the following implementations of said interface: OCA\User_LDAP\User_LDAP, OCA\User_LDAP\User_Proxy.

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...
298
		}
299
		return true;
300
	}
301
302
	/**
303
	 * check if the backend supports changing passwords
304
	 *
305
	 * @return bool
306
	 */
307
	public function canChangePassword() {
308
		return $this->backend->implementsActions(Backend::SET_PASSWORD);
309
	}
310
311
	/**
312
	 * check if the backend supports changing display names
313
	 *
314
	 * @return bool
315
	 */
316
	public function canChangeDisplayName() {
317
		if ($this->config->getSystemValue('allow_user_to_change_display_name') === false) {
318
			return false;
319
		}
320
		return $this->backend->implementsActions(Backend::SET_DISPLAYNAME);
321
	}
322
323
	/**
324
	 * check if the user is enabled
325
	 *
326
	 * @return bool
327
	 */
328
	public function isEnabled() {
329
		return $this->enabled;
330
	}
331
332
	/**
333
	 * set the enabled status for the user
334
	 *
335
	 * @param bool $enabled
336
	 */
337
	public function setEnabled($enabled) {
338
		$this->enabled = $enabled;
339
		$enabled = ($enabled) ? 'true' : 'false';
340
		$this->config->setUserValue($this->uid, 'core', 'enabled', $enabled);
341
	}
342
343
	/**
344
	 * get the users email address
345
	 *
346
	 * @return string|null
347
	 * @since 9.0.0
348
	 */
349
	public function getEMailAddress() {
350
		return $this->config->getUserValue($this->uid, 'settings', 'email', null);
351
	}
352
353
	/**
354
	 * get the users' quota
355
	 *
356
	 * @return string
357
	 * @since 9.0.0
358
	 */
359
	public function getQuota() {
360
		$quota = $this->config->getUserValue($this->uid, 'files', 'quota', 'default');
361
		if($quota === 'default') {
362
			$quota = $this->config->getAppValue('files', 'default_quota', 'none');
363
		}
364
		return $quota;
365
	}
366
367
	/**
368
	 * set the users' quota
369
	 *
370
	 * @param string $quota
371
	 * @return void
372
	 * @since 9.0.0
373
	 */
374
	public function setQuota($quota) {
375 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...
376
			$quota = OC_Helper::computerFileSize($quota);
377
			$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...
378
		}
379
		$this->config->setUserValue($this->uid, 'files', 'quota', $quota);
380
		$this->triggerChange('quota', $quota);
381
	}
382
383
	/**
384
	 * get the avatar image if it exists
385
	 *
386
	 * @param int $size
387
	 * @return IImage|null
388
	 * @since 9.0.0
389
	 */
390
	public function getAvatarImage($size) {
391
		// delay the initialization
392
		if (is_null($this->avatarManager)) {
393
			$this->avatarManager = \OC::$server->getAvatarManager();
394
		}
395
396
		$avatar = $this->avatarManager->getAvatar($this->uid);
397
		$image = $avatar->get(-1);
0 ignored issues
show
Bug Compatibility introduced by
The expression $avatar->get(-1); of type boolean|OCP\IImage adds the type boolean to the return on line 399 which is incompatible with the return type declared by the interface OCP\IUser::getAvatarImage of type OCP\IImage|null.
Loading history...
398
		if ($image) {
399
			return $image;
400
		}
401
402
		return null;
403
	}
404
405
	/**
406
	 * get the federation cloud id
407
	 *
408
	 * @return string
409
	 * @since 9.0.0
410
	 */
411
	public function getCloudId() {
412
		$uid = $this->getUID();
413
		$server = $this->urlGenerator->getAbsoluteURL('/');
414
		$server =  rtrim( $this->removeProtocolFromUrl($server), '/');
415
		return \OC::$server->getCloudIdManager()->getCloudId($uid, $server)->getId();
416
	}
417
418
	/**
419
	 * @param string $url
420
	 * @return string
421
	 */
422 View Code Duplication
	private function removeProtocolFromUrl($url) {
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...
423
		if (strpos($url, 'https://') === 0) {
424
			return substr($url, strlen('https://'));
425
		} else if (strpos($url, 'http://') === 0) {
426
			return substr($url, strlen('http://'));
427
		}
428
429
		return $url;
430
	}
431
432
	public function triggerChange($feature, $value = null) {
433
		if ($this->emitter) {
434
			$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...
435
		}
436
	}
437
}
438