Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.
Common duplication problems, and corresponding solutions are:
Complex classes like OC_User often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes. You can also have a look at the cohesion graph to spot any un-connected, or weakly-connected components.
Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.
While breaking up the class, it is a good idea to analyze how other classes use OC_User, and based on these observations, apply Extract Interface, too.
| 1 | <?php |
||
| 58 | class OC_User { |
||
|
|
|||
| 59 | |||
| 60 | /** |
||
| 61 | * @return \OC\User\Session |
||
| 62 | */ |
||
| 63 | public static function getUserSession() { |
||
| 66 | |||
| 67 | private static $_usedBackends = array(); |
||
| 68 | |||
| 69 | private static $_setupedBackends = array(); |
||
| 70 | |||
| 71 | // bool, stores if a user want to access a resource anonymously, e.g if they open a public link |
||
| 72 | private static $incognitoMode = false; |
||
| 73 | |||
| 74 | /** |
||
| 75 | * Adds the backend to the list of used backends |
||
| 76 | * |
||
| 77 | * @param string|\OCP\UserInterface $backend default: database The backend to use for user management |
||
| 78 | * @return bool |
||
| 79 | * |
||
| 80 | * Set the User Authentication Module |
||
| 81 | */ |
||
| 82 | public static function useBackend($backend = 'database') { |
||
| 115 | |||
| 116 | /** |
||
| 117 | * remove all used backends |
||
| 118 | */ |
||
| 119 | public static function clearBackends() { |
||
| 123 | |||
| 124 | /** |
||
| 125 | * setup the configured backends in config.php |
||
| 126 | */ |
||
| 127 | public static function setupBackends() { |
||
| 157 | |||
| 158 | /** |
||
| 159 | * Try to login a user, assuming authentication |
||
| 160 | * has already happened (e.g. via Single Sign On). |
||
| 161 | * |
||
| 162 | * Log in a user and regenerate a new session. |
||
| 163 | * |
||
| 164 | * @param \OCP\Authentication\IApacheBackend $backend |
||
| 165 | * @return bool |
||
| 166 | */ |
||
| 167 | public static function loginWithApache(\OCP\Authentication\IApacheBackend $backend) { |
||
| 168 | |||
| 169 | $uid = $backend->getCurrentUserId(); |
||
| 170 | $run = true; |
||
| 171 | OC_Hook::emit("OC_User", "pre_login", array("run" => &$run, "uid" => $uid)); |
||
| 172 | |||
| 173 | if ($uid) { |
||
| 174 | if (self::getUser() !== $uid) { |
||
| 175 | self::setUserId($uid); |
||
| 176 | $setUidAsDisplayName = true; |
||
| 177 | if($backend instanceof \OCP\UserInterface |
||
| 178 | && $backend->implementsActions(OC_User_Backend::GET_DISPLAYNAME)) { |
||
| 179 | |||
| 180 | $backendDisplayName = $backend->getDisplayName($uid); |
||
| 181 | if(is_string($backendDisplayName) && trim($backendDisplayName) !== '') { |
||
| 182 | $setUidAsDisplayName = false; |
||
| 183 | } |
||
| 184 | } |
||
| 185 | if($setUidAsDisplayName) { |
||
| 186 | self::setDisplayName($uid); |
||
| 187 | } |
||
| 188 | $userSession = self::getUserSession(); |
||
| 189 | $userSession->setLoginName($uid); |
||
| 190 | $request = OC::$server->getRequest(); |
||
| 191 | $userSession->createSessionToken($request, $uid, $uid); |
||
| 192 | // setup the filesystem |
||
| 193 | OC_Util::setupFS($uid); |
||
| 194 | // first call the post_login hooks, the login-process needs to be |
||
| 195 | // completed before we can safely create the users folder. |
||
| 196 | // For example encryption needs to initialize the users keys first |
||
| 197 | // before we can create the user folder with the skeleton files |
||
| 198 | OC_Hook::emit("OC_User", "post_login", array("uid" => $uid, 'password' => '')); |
||
| 199 | //trigger creation of user home and /files folder |
||
| 200 | \OC::$server->getUserFolder($uid); |
||
| 201 | } |
||
| 202 | return true; |
||
| 203 | } |
||
| 204 | return false; |
||
| 205 | } |
||
| 206 | |||
| 207 | /** |
||
| 208 | * Verify with Apache whether user is authenticated. |
||
| 209 | * |
||
| 210 | * @return boolean|null |
||
| 211 | * true: authenticated |
||
| 212 | * false: not authenticated |
||
| 213 | * null: not handled / no backend available |
||
| 214 | */ |
||
| 215 | public static function handleApacheAuth() { |
||
| 216 | $backend = self::findFirstActiveUsedBackend(); |
||
| 217 | if ($backend) { |
||
| 218 | OC_App::loadApps(); |
||
| 219 | |||
| 220 | //setup extra user backends |
||
| 221 | self::setupBackends(); |
||
| 222 | self::getUserSession()->unsetMagicInCookie(); |
||
| 223 | |||
| 224 | return self::loginWithApache($backend); |
||
| 225 | } |
||
| 226 | |||
| 227 | return null; |
||
| 228 | } |
||
| 229 | |||
| 230 | |||
| 231 | /** |
||
| 232 | * Sets user id for session and triggers emit |
||
| 233 | * |
||
| 234 | * @param string $uid |
||
| 235 | */ |
||
| 236 | public static function setUserId($uid) { |
||
| 237 | $userSession = \OC::$server->getUserSession(); |
||
| 238 | $userManager = \OC::$server->getUserManager(); |
||
| 239 | if ($user = $userManager->get($uid)) { |
||
| 240 | $userSession->setUser($user); |
||
| 241 | } else { |
||
| 242 | \OC::$server->getSession()->set('user_id', $uid); |
||
| 243 | } |
||
| 244 | } |
||
| 245 | |||
| 246 | /** |
||
| 247 | * Sets user display name for session |
||
| 248 | * |
||
| 249 | * @param string $uid |
||
| 250 | * @param string $displayName |
||
| 251 | * @return bool Whether the display name could get set |
||
| 252 | */ |
||
| 253 | View Code Duplication | public static function setDisplayName($uid, $displayName = null) { |
|
| 254 | if (is_null($displayName)) { |
||
| 255 | $displayName = $uid; |
||
| 256 | } |
||
| 257 | $user = \OC::$server->getUserManager()->get($uid); |
||
| 258 | if ($user) { |
||
| 259 | return $user->setDisplayName($displayName); |
||
| 260 | } else { |
||
| 261 | return false; |
||
| 262 | } |
||
| 263 | } |
||
| 264 | |||
| 265 | /** |
||
| 266 | * Check if the user is logged in, considers also the HTTP basic credentials |
||
| 267 | * |
||
| 268 | * @deprecated use \OC::$server->getUserSession()->isLoggedIn() |
||
| 269 | * @return bool |
||
| 270 | */ |
||
| 271 | public static function isLoggedIn() { |
||
| 272 | return \OC::$server->getUserSession()->isLoggedIn(); |
||
| 273 | } |
||
| 274 | |||
| 275 | /** |
||
| 276 | * set incognito mode, e.g. if a user wants to open a public link |
||
| 277 | * |
||
| 278 | * @param bool $status |
||
| 279 | */ |
||
| 280 | public static function setIncognitoMode($status) { |
||
| 281 | self::$incognitoMode = $status; |
||
| 282 | } |
||
| 283 | |||
| 284 | /** |
||
| 285 | * get incognito mode status |
||
| 286 | * |
||
| 287 | * @return bool |
||
| 288 | */ |
||
| 289 | public static function isIncognitoMode() { |
||
| 290 | return self::$incognitoMode; |
||
| 291 | } |
||
| 292 | |||
| 293 | /** |
||
| 294 | * Supplies an attribute to the logout hyperlink. The default behaviour |
||
| 295 | * is to return an href with '?logout=true' appended. However, it can |
||
| 296 | * supply any attribute(s) which are valid for <a>. |
||
| 297 | * |
||
| 298 | * @return string with one or more HTML attributes. |
||
| 299 | */ |
||
| 300 | public static function getLogoutAttribute() { |
||
| 301 | $backend = self::findFirstActiveUsedBackend(); |
||
| 302 | if ($backend) { |
||
| 303 | return $backend->getLogoutAttribute(); |
||
| 304 | } |
||
| 305 | |||
| 306 | $logoutUrl = \OC::$server->getURLGenerator()->linkToRouteAbsolute( |
||
| 307 | 'core.login.logout', |
||
| 308 | [ |
||
| 309 | 'requesttoken' => \OCP\Util::callRegister(), |
||
| 310 | ] |
||
| 311 | ); |
||
| 312 | |||
| 313 | return 'href="'.$logoutUrl.'"'; |
||
| 314 | } |
||
| 315 | |||
| 316 | /** |
||
| 317 | * Check if the user is an admin user |
||
| 318 | * |
||
| 319 | * @param string $uid uid of the admin |
||
| 320 | * @return bool |
||
| 321 | */ |
||
| 322 | public static function isAdminUser($uid) { |
||
| 323 | $group = \OC::$server->getGroupManager()->get('admin'); |
||
| 324 | $user = \OC::$server->getUserManager()->get($uid); |
||
| 325 | if ($group && $user && $group->inGroup($user) && self::$incognitoMode === false) { |
||
| 326 | return true; |
||
| 327 | } |
||
| 328 | return false; |
||
| 329 | } |
||
| 330 | |||
| 331 | |||
| 332 | /** |
||
| 333 | * get the user id of the user currently logged in. |
||
| 334 | * |
||
| 335 | * @return string|bool uid or false |
||
| 336 | */ |
||
| 337 | public static function getUser() { |
||
| 345 | |||
| 346 | /** |
||
| 347 | * get the display name of the user currently logged in. |
||
| 348 | * |
||
| 349 | * @param string $uid |
||
| 350 | * @return string uid or false |
||
| 351 | */ |
||
| 352 | public static function getDisplayName($uid = null) { |
||
| 369 | |||
| 370 | /** |
||
| 371 | * Set password |
||
| 372 | * |
||
| 373 | * @param string $uid The username |
||
| 374 | * @param string $password The new password |
||
| 375 | * @param string $recoveryPassword for the encryption app to reset encryption keys |
||
| 376 | * @return bool |
||
| 377 | * |
||
| 378 | * Change the password of a user |
||
| 379 | */ |
||
| 380 | public static function setPassword($uid, $password, $recoveryPassword = null) { |
||
| 388 | |||
| 389 | /** |
||
| 390 | * Check if the password is correct |
||
| 391 | * |
||
| 392 | * @param string $uid The username |
||
| 393 | * @param string $password The password |
||
| 394 | * @return string|false user id a string on success, false otherwise |
||
| 395 | * |
||
| 396 | * Check if the password is correct without logging in the user |
||
| 397 | * returns the user id or false |
||
| 398 | */ |
||
| 399 | View Code Duplication | public static function checkPassword($uid, $password) { |
|
| 407 | |||
| 408 | /** |
||
| 409 | * @param string $uid The username |
||
| 410 | * @return string |
||
| 411 | * |
||
| 412 | * returns the path to the users home directory |
||
| 413 | * @deprecated Use \OC::$server->getUserManager->getHome() |
||
| 414 | */ |
||
| 415 | public static function getHome($uid) { |
||
| 423 | |||
| 424 | /** |
||
| 425 | * Get a list of all users |
||
| 426 | * |
||
| 427 | * @return array an array of all uids |
||
| 428 | * |
||
| 429 | * Get a list of all users. |
||
| 430 | * @param string $search |
||
| 431 | * @param integer $limit |
||
| 432 | * @param integer $offset |
||
| 433 | */ |
||
| 434 | View Code Duplication | public static function getUsers($search = '', $limit = null, $offset = null) { |
|
| 442 | |||
| 443 | /** |
||
| 444 | * Get a list of all users display name |
||
| 445 | * |
||
| 446 | * @param string $search |
||
| 447 | * @param int $limit |
||
| 448 | * @param int $offset |
||
| 449 | * @return array associative array with all display names (value) and corresponding uids (key) |
||
| 450 | * |
||
| 451 | * Get a list of all display names and user ids. |
||
| 452 | * @deprecated Use \OC::$server->getUserManager->searchDisplayName($search, $limit, $offset) instead. |
||
| 453 | */ |
||
| 454 | View Code Duplication | public static function getDisplayNames($search = '', $limit = null, $offset = null) { |
|
| 462 | |||
| 463 | /** |
||
| 464 | * check if a user exists |
||
| 465 | * |
||
| 466 | * @param string $uid the username |
||
| 467 | * @return boolean |
||
| 468 | */ |
||
| 469 | public static function userExists($uid) { |
||
| 472 | |||
| 473 | /** |
||
| 474 | * checks if a user is enabled |
||
| 475 | * |
||
| 476 | * @param string $uid |
||
| 477 | * @return bool |
||
| 478 | */ |
||
| 479 | public static function isEnabled($uid) { |
||
| 487 | |||
| 488 | /** |
||
| 489 | * Returns the first active backend from self::$_usedBackends. |
||
| 490 | * |
||
| 491 | * @return OCP\Authentication\IApacheBackend|null if no backend active, otherwise OCP\Authentication\IApacheBackend |
||
| 492 | */ |
||
| 493 | private static function findFirstActiveUsedBackend() { |
||
| 504 | } |
||
| 505 |
You can fix this by adding a namespace to your class:
When choosing a vendor namespace, try to pick something that is not too generic to avoid conflicts with other libraries.