]> git.mxchange.org Git - friendica.git/blobdiff - src/Model/User.php
Fixed wrong reference to user.expire in Model\User::getActorName
[friendica.git] / src / Model / User.php
index 57d5560a47cec7d4ad7e68c64f01b829c3309da7..cc6e11a42d3e031ef60e0e5ea36dda08a66ce98d 100644 (file)
@@ -1,6 +1,6 @@
 <?php
 /**
- * @copyright Copyright (C) 2010-2021, the Friendica project
+ * @copyright Copyright (C) 2010-2022, the Friendica project
  *
  * @license GNU AGPL version 3 or any later version
  *
@@ -30,10 +30,12 @@ use Friendica\Core\Hook;
 use Friendica\Core\L10n;
 use Friendica\Core\Logger;
 use Friendica\Core\Protocol;
+use Friendica\Core\Search;
 use Friendica\Core\System;
 use Friendica\Core\Worker;
 use Friendica\Database\DBA;
 use Friendica\DI;
+use Friendica\Network\HTTPClient\Client\HttpClientAccept;
 use Friendica\Security\TwoFactor\Model\AppSpecificPassword;
 use Friendica\Network\HTTPException;
 use Friendica\Object\Image;
@@ -115,16 +117,18 @@ class User
                switch ($accounttype) {
                        case 'person':
                                return User::ACCOUNT_TYPE_PERSON;
+
                        case 'organisation':
                                return User::ACCOUNT_TYPE_ORGANISATION;
+
                        case 'news':
                                return User::ACCOUNT_TYPE_NEWS;
+
                        case 'community':
                                return User::ACCOUNT_TYPE_COMMUNITY;
-                       default:
-                               return null;
-                       break;
+
                }
+               return null;
        }
 
        /**
@@ -132,7 +136,7 @@ class User
         *
         * @return array system account
         */
-       public static function getSystemAccount()
+       public static function getSystemAccount(): array
        {
                $system = Contact::selectFirst([], ['self' => true, 'uid' => 0]);
                if (!DBA::isResult($system)) {
@@ -208,32 +212,33 @@ class User
                        throw new Exception(DI::l10n()->t('SERIOUS ERROR: Generation of security keys failed.'));
                }
 
-               $system = [];
-               $system['uid'] = 0;
-               $system['created'] = DateTimeFormat::utcNow();
-               $system['self'] = true;
-               $system['network'] = Protocol::ACTIVITYPUB;
-               $system['name'] = 'System Account';
-               $system['addr'] = $system_actor_name . '@' . DI::baseUrl()->getHostname();
-               $system['nick'] = $system_actor_name;
-               $system['url'] = DI::baseUrl() . '/friendica';
+               $system = [
+                       'uid'          => 0,
+                       'created'      => DateTimeFormat::utcNow(),
+                       'self'         => true,
+                       'network'      => Protocol::ACTIVITYPUB,
+                       'name'         => 'System Account',
+                       'addr'         => $system_actor_name . '@' . DI::baseUrl()->getHostname(),
+                       'nick'         => $system_actor_name,
+                       'url'          => DI::baseUrl() . '/friendica',
+                       'pubkey'       => $keys['pubkey'],
+                       'prvkey'       => $keys['prvkey'],
+                       'blocked'      => 0,
+                       'pending'      => 0,
+                       'contact-type' => Contact::TYPE_RELAY, // In AP this is translated to 'Application'
+                       'name-date'    => DateTimeFormat::utcNow(),
+                       'uri-date'     => DateTimeFormat::utcNow(),
+                       'avatar-date'  => DateTimeFormat::utcNow(),
+                       'closeness'    => 0,
+                       'baseurl'      => DI::baseUrl(),
+               ];
 
                $system['avatar'] = $system['photo'] = Contact::getDefaultAvatar($system, Proxy::SIZE_SMALL);
-               $system['thumb'] = Contact::getDefaultAvatar($system, Proxy::SIZE_THUMB);
-               $system['micro'] = Contact::getDefaultAvatar($system, Proxy::SIZE_MICRO);
-
-               $system['nurl'] = Strings::normaliseLink($system['url']);
-               $system['pubkey'] = $keys['pubkey'];
-               $system['prvkey'] = $keys['prvkey'];
-               $system['blocked'] = 0;
-               $system['pending'] = 0;
-               $system['contact-type'] = Contact::TYPE_RELAY; // In AP this is translated to 'Application'
-               $system['name-date'] = DateTimeFormat::utcNow();
-               $system['uri-date'] = DateTimeFormat::utcNow();
-               $system['avatar-date'] = DateTimeFormat::utcNow();
-               $system['closeness'] = 0;
-               $system['baseurl'] = DI::baseUrl();
-               $system['gsid'] = GServer::getID($system['baseurl']);
+               $system['thumb']  = Contact::getDefaultAvatar($system, Proxy::SIZE_THUMB);
+               $system['micro']  = Contact::getDefaultAvatar($system, Proxy::SIZE_MICRO);
+               $system['nurl']   = Strings::normaliseLink($system['url']);
+               $system['gsid']   = GServer::getID($system['baseurl']);
+
                Contact::insert($system);
        }
 
@@ -242,7 +247,7 @@ class User
         *
         * @return string actor account name
         */
-       public static function getActorName()
+       public static function getActorName(): string
        {
                $system_actor_name = DI::config()->get('system', 'actor_name');
                if (!empty($system_actor_name)) {
@@ -260,7 +265,7 @@ class User
                // List of possible actor names
                $possible_accounts = ['friendica', 'actor', 'system', 'internal'];
                foreach ($possible_accounts as $name) {
-                       if (!DBA::exists('user', ['nickname' => $name, 'account_removed' => false, 'expire' => false]) &&
+                       if (!DBA::exists('user', ['nickname' => $name, 'account_removed' => false, 'account_expired' => false]) &&
                                !DBA::exists('userd', ['username' => $name])) {
                                DI::config()->set('system', 'actor_name', $name);
                                return $name;
@@ -272,11 +277,12 @@ class User
        /**
         * Returns true if a user record exists with the provided id
         *
-        * @param  integer $uid
+        * @param  int $uid
+        *
         * @return boolean
         * @throws Exception
         */
-       public static function exists($uid)
+       public static function exists(int $uid): bool
        {
                return DBA::exists('user', ['uid' => $uid]);
        }
@@ -287,7 +293,7 @@ class User
         * @return array|boolean User record if it exists, false otherwise
         * @throws Exception
         */
-       public static function getById($uid, array $fields = [])
+       public static function getById(int $uid, array $fields = [])
        {
                return !empty($uid) ? DBA::selectFirst('user', $fields, ['uid' => $uid]) : [];
        }
@@ -319,7 +325,7 @@ class User
         * @return array|boolean User record if it exists, false otherwise
         * @throws Exception
         */
-       public static function getByNickname($nickname, array $fields = [])
+       public static function getByNickname(string $nickname, array $fields = [])
        {
                return DBA::selectFirst('user', $fields, ['nickname' => $nickname]);
        }
@@ -332,7 +338,7 @@ class User
         * @return integer user id
         * @throws Exception
         */
-       public static function getIdForURL(string $url)
+       public static function getIdForURL(string $url): int
        {
                // Avoid database queries when the local node hostname isn't even part of the url.
                if (!Contact::isLocal($url)) {
@@ -360,14 +366,12 @@ class User
        /**
         * Get a user based on its email
         *
-        * @param string        $email
-        * @param array          $fields
-        *
+        * @param string $email
+        * @param array  $fields
         * @return array|boolean User record if it exists, false otherwise
-        *
         * @throws Exception
         */
-       public static function getByEmail($email, array $fields = [])
+       public static function getByEmail(string $email, array $fields = [])
        {
                return DBA::selectFirst('user', $fields, ['email' => $email]);
        }
@@ -378,7 +382,7 @@ class User
         * @param array $fields
         * @return array user
         */
-       public static function getFirstAdmin(array $fields = [])
+       public static function getFirstAdmin(array $fields = []) : array
        {
                if (!empty(DI::config()->get('config', 'admin_nickname'))) {
                        return self::getByNickname(DI::config()->get('config', 'admin_nickname'), $fields);
@@ -410,7 +414,7 @@ class User
 
                $owner = DBA::selectFirst('owner-view', [], ['uid' => $uid]);
                if (!DBA::isResult($owner)) {
-                       if (!DBA::exists('user', ['uid' => $uid]) || !$repairMissing) {
+                       if (!self::exists($uid) || !$repairMissing) {
                                return false;
                        }
                        if (!DBA::exists('profile', ['uid' => $uid])) {
@@ -467,7 +471,7 @@ class User
         * @return boolean|array
         * @throws Exception
         */
-       public static function getOwnerDataByNick($nick)
+       public static function getOwnerDataByNick(string $nick)
        {
                $user = DBA::selectFirst('user', ['uid'], ['nickname' => $nick]);
 
@@ -481,13 +485,12 @@ class User
        /**
         * Returns the default group for a given user and network
         *
-        * @param int    $uid     User id
-        * @param string $network network name
+        * @param int $uid User id
         *
         * @return int group id
         * @throws Exception
         */
-       public static function getDefaultGroup($uid, $network = '')
+       public static function getDefaultGroup(int $uid): int
        {
                $user = DBA::selectFirst('user', ['def_gid'], ['uid' => $uid]);
                if (DBA::isResult($user)) {
@@ -499,26 +502,6 @@ class User
                return $default_group;
        }
 
-
-       /**
-        * Authenticate a user with a clear text password
-        *
-        * @param mixed  $user_info
-        * @param string $password
-        * @param bool   $third_party
-        * @return int|boolean
-        * @deprecated since version 3.6
-        * @see        User::getIdFromPasswordAuthentication()
-        */
-       public static function authenticate($user_info, $password, $third_party = false)
-       {
-               try {
-                       return self::getIdFromPasswordAuthentication($user_info, $password, $third_party);
-               } catch (Exception $ex) {
-                       return false;
-               }
-       }
-
        /**
         * Authenticate a user with a clear text password
         *
@@ -531,7 +514,7 @@ class User
         * @throws HTTPException\ForbiddenException
         * @throws HTTPException\NotFoundException
         */
-       public static function getIdFromPasswordAuthentication($user_info, $password, $third_party = false)
+       public static function getIdFromPasswordAuthentication($user_info, string $password, bool $third_party = false): int
        {
                // Addons registered with the "authenticate" hook may create the user on the
                // fly. `getAuthenticationInfo` will fail if the user doesn't exist yet. If
@@ -599,7 +582,7 @@ class User
         * @return int User Id if authentication is successful
         * @throws HTTPException\ForbiddenException
         */
-       public static function getIdFromAuthenticateHooks($username, $password)
+       public static function getIdFromAuthenticateHooks(string $username, string $password): int
        {
                $addon_auth = [
                        'username'      => $username,
@@ -632,7 +615,7 @@ class User
         * - User array with at least the uid and the hashed password
         *
         * @param mixed $user_info
-        * @return array
+        * @return array|null Null if not found/determined
         * @throws HTTPException\NotFoundException
         */
        public static function getAuthenticationInfo($user_info)
@@ -690,7 +673,7 @@ class User
         * @return string
         * @throws Exception
         */
-       public static function generateNewPassword()
+       public static function generateNewPassword(): string
        {
                return ucfirst(Strings::getRandomName(8)) . random_int(1000, 9999);
        }
@@ -702,7 +685,7 @@ class User
         * @return bool
         * @throws Exception
         */
-       public static function isPasswordExposed($password)
+       public static function isPasswordExposed(string $password): bool
        {
                $cache = new CacheItemPool();
                $cache->changeConfig([
@@ -731,7 +714,7 @@ class User
         * @param string $password
         * @return string
         */
-       private static function hashPasswordLegacy($password)
+       private static function hashPasswordLegacy(string $password): string
        {
                return hash('whirlpool', $password);
        }
@@ -743,7 +726,7 @@ class User
         * @return string
         * @throws Exception
         */
-       public static function hashPassword($password)
+       public static function hashPassword(string $password): string
        {
                if (!trim($password)) {
                        throw new Exception(DI::l10n()->t('Password can\'t be empty'));
@@ -752,6 +735,29 @@ class User
                return password_hash($password, PASSWORD_DEFAULT);
        }
 
+       /**
+        * Allowed characters are a-z, A-Z, 0-9 and special characters except white spaces, accentuated letters and colon (:).
+        *
+        * Password length is limited to 72 characters if the current default password hashing algorithm is Blowfish.
+        * From the manual: "Using the PASSWORD_BCRYPT as the algorithm, will result in the password parameter being
+        * truncated to a maximum length of 72 bytes."
+        *
+        * @see https://www.php.net/manual/en/function.password-hash.php#refsect1-function.password-hash-parameters
+        *
+        * @param string|null $delimiter Whether the regular expression is meant to be wrapper in delimiter characters
+        * @return string
+        */
+       public static function getPasswordRegExp(string $delimiter = null): string
+       {
+               $allowed_characters = '!"#$%&\'()*+,-./;<=>?@[\]^_`{|}~';
+
+               if ($delimiter) {
+                       $allowed_characters = preg_quote($allowed_characters, $delimiter);
+               }
+
+               return '^[a-zA-Z0-9' . $allowed_characters . ']' . (PASSWORD_DEFAULT !== PASSWORD_BCRYPT ? '{1,72}' : '+') . '$';
+       }
+
        /**
         * Updates a user row with a new plaintext password
         *
@@ -760,7 +766,7 @@ class User
         * @return bool
         * @throws Exception
         */
-       public static function updatePassword($uid, $password)
+       public static function updatePassword(int $uid, string $password): bool
        {
                $password = trim($password);
 
@@ -772,9 +778,11 @@ class User
                        throw new Exception(DI::l10n()->t('The new password has been exposed in a public data dump, please choose another.'));
                }
 
-               $allowed_characters = '!"#$%&\'()*+,-./;<=>?@[\]^_`{|}~';
+               if (PASSWORD_DEFAULT === PASSWORD_BCRYPT && strlen($password) > 72) {
+                       throw new Exception(DI::l10n()->t('The password length is limited to 72 characters.'));
+               }
 
-               if (!preg_match('/^[a-z0-9' . preg_quote($allowed_characters, '/') . ']+$/i', $password)) {
+               if (!preg_match('/' . self::getPasswordRegExp('/') . '/', $password)) {
                        throw new Exception(DI::l10n()->t('The password can\'t contain accentuated letters, white spaces or colons (:)'));
                }
 
@@ -790,7 +798,7 @@ class User
         * @return bool
         * @throws Exception
         */
-       private static function updatePasswordHashed($uid, $pasword_hashed)
+       private static function updatePasswordHashed(int $uid, string $pasword_hashed): bool
        {
                $fields = [
                        'password' => $pasword_hashed,
@@ -811,7 +819,7 @@ class User
         * @param string $nickname The nickname that should be checked
         * @return boolean True is the nickname is blocked on the node
         */
-       public static function isNicknameBlocked($nickname)
+       public static function isNicknameBlocked(string $nickname): bool
        {
                $forbidden_nicknames = DI::config()->get('system', 'forbidden_nicknames', '');
                if (!empty($forbidden_nicknames)) {
@@ -848,7 +856,7 @@ class User
         * @return string avatar link
         * @throws Exception
         */
-       public static function getAvatarUrl(array $user, string $size = ''):string
+       public static function getAvatarUrl(array $user, string $size = ''): string
        {
                if (empty($user['nickname'])) {
                        DI::logger()->warning('Missing user nickname key', ['trace' => System::callstack(20)]);
@@ -871,19 +879,46 @@ class User
                                break;
                }
 
-               $updated =  '';
-               $imagetype = IMAGETYPE_JPEG;
+               $updated  =  '';
+               $mimetype = '';
 
                $photo = Photo::selectFirst(['type', 'created', 'edited', 'updated'], ["scale" => $scale, 'uid' => $user['uid'], 'profile' => true]);
                if (!empty($photo)) {
-                       $updated = max($photo['created'], $photo['edited'], $photo['updated']);
+                       $updated  = max($photo['created'], $photo['edited'], $photo['updated']);
+                       $mimetype = $photo['type'];
+               }
 
-                       if (in_array($photo['type'], ['image/png', 'image/gif'])) {
-                               $imagetype = IMAGETYPE_PNG;
-                       }
+               return $url . $user['nickname'] . Images::getExtensionByMimeType($mimetype) . ($updated ? '?ts=' . strtotime($updated) : '');
+       }
+
+       /**
+        * Get banner link for given user
+        *
+        * @param array  $user
+        * @return string banner link
+        * @throws Exception
+        */
+       public static function getBannerUrl(array $user): string
+       {
+               if (empty($user['nickname'])) {
+                       DI::logger()->warning('Missing user nickname key', ['trace' => System::callstack(20)]);
                }
 
-               return $url . $user['nickname'] . image_type_to_extension($imagetype) . ($updated ? '?ts=' . strtotime($updated) : '');
+               $url = DI::baseUrl() . '/photo/banner/';
+
+               $updated  = '';
+               $mimetype = '';
+
+               $photo = Photo::selectFirst(['type', 'created', 'edited', 'updated'], ["scale" => 3, 'uid' => $user['uid'], 'photo-type' => Photo::USER_BANNER]);
+               if (!empty($photo)) {
+                       $updated  = max($photo['created'], $photo['edited'], $photo['updated']);
+                       $mimetype = $photo['type'];
+               } else {
+                       // Only for the RC phase: Don't return an image link for the default picture
+                       return '';
+               }
+
+               return $url . $user['nickname'] . Images::getExtensionByMimeType($mimetype) . ($updated ? '?ts=' . strtotime($updated) : '');
        }
 
        /**
@@ -905,7 +940,7 @@ class User
         * @throws ImagickException
         * @throws Exception
         */
-       public static function create(array $data)
+       public static function create(array $data): array
        {
                $return = ['user' => null, 'password' => ''];
 
@@ -959,7 +994,7 @@ class User
                                try {
                                        $authurl = $openid->authUrl();
                                } catch (Exception $e) {
-                                       throw new Exception(DI::l10n()->t('We encountered a problem while logging in with the OpenID you provided. Please check the correct spelling of the ID.') . EOL . EOL . DI::l10n()->t('The error message was:') . $e->getMessage(), 0, $e);
+                                       throw new Exception(DI::l10n()->t('We encountered a problem while logging in with the OpenID you provided. Please check the correct spelling of the ID.') . '<br />' . DI::l10n()->t('The error message was:') . $e->getMessage(), 0, $e);
                                }
                                System::externalRedirect($authurl);
                                // NOTREACHED
@@ -1144,8 +1179,9 @@ class User
                        $photo_failure = false;
 
                        $filename = basename($photo);
-                       $curlResult = DI::httpClient()->get($photo);
+                       $curlResult = DI::httpClient()->get($photo, HttpClientAccept::IMAGE);
                        if ($curlResult->isSuccess()) {
+                               Logger::debug('Got picture', ['Content-Type' => $curlResult->getHeader('Content-Type'), 'url' => $photo]);
                                $img_str = $curlResult->getBody();
                                $type = $curlResult->getContentType();
                        } else {
@@ -1155,32 +1191,32 @@ class User
 
                        $type = Images::getMimeTypeByData($img_str, $photo, $type);
 
-                       $Image = new Image($img_str, $type);
-                       if ($Image->isValid()) {
-                               $Image->scaleToSquare(300);
+                       $image = new Image($img_str, $type);
+                       if ($image->isValid()) {
+                               $image->scaleToSquare(300);
 
                                $resource_id = Photo::newResource();
 
                                // Not using Photo::PROFILE_PHOTOS here, so that it is discovered as translateble string
                                $profile_album = DI::l10n()->t('Profile Photos');
 
-                               $r = Photo::store($Image, $uid, 0, $resource_id, $filename, $profile_album, 4);
+                               $r = Photo::store($image, $uid, 0, $resource_id, $filename, $profile_album, 4);
 
                                if ($r === false) {
                                        $photo_failure = true;
                                }
 
-                               $Image->scaleDown(80);
+                               $image->scaleDown(80);
 
-                               $r = Photo::store($Image, $uid, 0, $resource_id, $filename, $profile_album, 5);
+                               $r = Photo::store($image, $uid, 0, $resource_id, $filename, $profile_album, 5);
 
                                if ($r === false) {
                                        $photo_failure = true;
                                }
 
-                               $Image->scaleDown(48);
+                               $image->scaleDown(48);
 
-                               $r = Photo::store($Image, $uid, 0, $resource_id, $filename, $profile_album, 6);
+                               $r = Photo::store($image, $uid, 0, $resource_id, $filename, $profile_album, 6);
 
                                if ($r === false) {
                                        $photo_failure = true;
@@ -1246,7 +1282,7 @@ class User
 
         * @throws Exception
         */
-       public static function block(int $uid, bool $block = true)
+       public static function block(int $uid, bool $block = true): bool
        {
                return DBA::update('user', ['blocked' => $block], ['uid' => $uid]);
        }
@@ -1261,7 +1297,7 @@ class User
         * @throws HTTPException\InternalServerErrorException
         * @throws Exception
         */
-       public static function allow(string $hash)
+       public static function allow(string $hash): bool
        {
                $register = Register::getByHash($hash);
                if (!DBA::isResult($register)) {
@@ -1279,9 +1315,9 @@ class User
 
                $profile = DBA::selectFirst('profile', ['net-publish'], ['uid' => $register['uid']]);
 
-               if (DBA::isResult($profile) && $profile['net-publish'] && DI::config()->get('system', 'directory')) {
+               if (DBA::isResult($profile) && $profile['net-publish'] && Search::getGlobalDirectory()) {
                        $url = DI::baseUrl() . '/profile/' . $user['nickname'];
-                       Worker::add(PRIORITY_LOW, "Directory", $url);
+                       Worker::add(Worker::PRIORITY_LOW, "Directory", $url);
                }
 
                $l10n = DI::l10n()->withLang($register['language']);
@@ -1307,7 +1343,7 @@ class User
         * @return bool True, if the deny was successfull
         * @throws Exception
         */
-       public static function deny(string $hash)
+       public static function deny(string $hash): bool
        {
                $register = Register::getByHash($hash);
                if (!DBA::isResult($register)) {
@@ -1333,13 +1369,12 @@ class User
         * @param string $email The user's email address
         * @param string $nick  The user's nick name
         * @param string $lang  The user's language (default is english)
-        *
         * @return bool True, if the user was created successfully
         * @throws HTTPException\InternalServerErrorException
         * @throws ErrorException
         * @throws ImagickException
         */
-       public static function createMinimal(string $name, string $email, string $nick, string $lang = L10n::DEFAULT)
+       public static function createMinimal(string $name, string $email, string $nick, string $lang = L10n::DEFAULT): bool
        {
                if (empty($name) ||
                    empty($email) ||
@@ -1383,7 +1418,7 @@ class User
                If you are new and do not know anybody here, they may help
                you to make some new and interesting friends.
 
-               If you ever want to delete your account, you can do so at %1$s/removeme
+               If you ever want to delete your account, you can do so at %1$s/settings/removeme
 
                Thank you and welcome to %4$s.'));
 
@@ -1409,7 +1444,7 @@ class User
         * @return NULL|boolean from notification() and email() inherited
         * @throws HTTPException\InternalServerErrorException
         */
-       public static function sendRegisterPendingEmail($user, $sitename, $siteurl, $password)
+       public static function sendRegisterPendingEmail(array $user, string $sitename, string $siteurl, string $password)
        {
                $body = Strings::deindent(DI::l10n()->t(
                        '
@@ -1452,7 +1487,7 @@ class User
         * @return NULL|boolean from notification() and email() inherited
         * @throws HTTPException\InternalServerErrorException
         */
-       public static function sendRegisterOpenEmail(L10n $l10n, $user, $sitename, $siteurl, $password)
+       public static function sendRegisterOpenEmail(L10n $l10n, array $user, string $sitename, string $siteurl, string $password)
        {
                $preamble = Strings::deindent($l10n->t(
                        '
@@ -1487,7 +1522,7 @@ class User
                        If you are new and do not know anybody here, they may help
                        you to make some new and interesting friends.
 
-                       If you ever want to delete your account, you can do so at %3$s/removeme
+                       If you ever want to delete your account, you can do so at %3$s/settings/removeme
 
                        Thank you and welcome to %2$s.',
                        $user['nickname'],
@@ -1511,7 +1546,7 @@ class User
         * @return bool
         * @throws HTTPException\InternalServerErrorException
         */
-       public static function remove(int $uid)
+       public static function remove(int $uid): bool
        {
                if (empty($uid)) {
                        return false;
@@ -1532,14 +1567,14 @@ class User
 
                // The user and related data will be deleted in Friendica\Worker\ExpireAndRemoveUsers
                DBA::update('user', ['account_removed' => true, 'account_expires_on' => DateTimeFormat::utc('now + 7 day')], ['uid' => $uid]);
-               Worker::add(PRIORITY_HIGH, 'Notifier', Delivery::REMOVAL, $uid);
+               Worker::add(Worker::PRIORITY_HIGH, 'Notifier', Delivery::REMOVAL, $uid);
 
                // Send an update to the directory
                $self = DBA::selectFirst('contact', ['url'], ['uid' => $uid, 'self' => true]);
-               Worker::add(PRIORITY_LOW, 'Directory', $self['url']);
+               Worker::add(Worker::PRIORITY_LOW, 'Directory', $self['url']);
 
                // Remove the user relevant data
-               Worker::add(PRIORITY_NEGLIGIBLE, 'RemoveUser', $uid);
+               Worker::add(Worker::PRIORITY_NEGLIGIBLE, 'RemoveUser', $uid);
 
                return true;
        }
@@ -1565,7 +1600,7 @@ class User
         *    ]
         * @throws Exception
         */
-       public static function identities($uid)
+       public static function identities(int $uid): array
        {
                if (empty($uid)) {
                        return [];
@@ -1637,7 +1672,7 @@ class User
         * @param int $uid
         * @return bool
         */
-       public static function hasIdentities(int $uid):bool
+       public static function hasIdentities(int $uid): bool
        {
                if (empty($uid)) {
                        return false;
@@ -1670,7 +1705,7 @@ class User
         *
         * @throws Exception
         */
-       public static function getStatistics()
+       public static function getStatistics(): array
        {
                $statistics = [
                        'total_users'           => 0,
@@ -1722,11 +1757,10 @@ class User
         * @param string $type  The type of users, which should get (all, bocked, removed)
         * @param string $order Order of the user list (Default is 'contact.name')
         * @param bool   $descending Order direction (Default is ascending)
-        *
-        * @return array The list of the users
+        * @return array|bool The list of the users
         * @throws Exception
         */
-       public static function getList($start = 0, $count = Pager::ITEMS_PER_PAGE, $type = 'all', $order = 'name', bool $descending = false)
+       public static function getList(int $start = 0, int $count = Pager::ITEMS_PER_PAGE, string $type = 'all', string $order = 'name', bool $descending = false)
        {
                $param = ['limit' => [$start, $count], 'order' => [$order => $descending]];
                $condition = [];
@@ -1735,11 +1769,13 @@ class User
                                $condition['account_removed'] = false;
                                $condition['blocked'] = false;
                                break;
+
                        case 'blocked':
                                $condition['account_removed'] = false;
                                $condition['blocked'] = true;
                                $condition['verified'] = true;
                                break;
+
                        case 'removed':
                                $condition['account_removed'] = true;
                                break;