]> git.mxchange.org Git - friendica.git/blobdiff - src/Model/User.php
Language selector added, "channel" is now "channels"
[friendica.git] / src / Model / User.php
index b0ece93464ca70fc5518323056006cfbdf16a372..d6dfa3525361800e5174fdd40a44c139b2b35e22 100644 (file)
@@ -35,7 +35,9 @@ use Friendica\Core\System;
 use Friendica\Core\Worker;
 use Friendica\Database\DBA;
 use Friendica\DI;
+use Friendica\Module;
 use Friendica\Network\HTTPClient\Client\HttpClientAccept;
+use Friendica\Network\HTTPException\InternalServerErrorException;
 use Friendica\Security\TwoFactor\Model\AppSpecificPassword;
 use Friendica\Network\HTTPException;
 use Friendica\Object\Image;
@@ -87,7 +89,7 @@ class User
         * ACCOUNT_TYPE_NEWS - the account is a news reflector
         *      Associated page type: PAGE_FLAGS_SOAPBOX
         *
-        * ACCOUNT_TYPE_COMMUNITY - the account is community forum
+        * ACCOUNT_TYPE_COMMUNITY - the account is community group
         *      Associated page types: PAGE_COMMUNITY, PAGE_FLAGS_PRVGROUP
         *
         * ACCOUNT_TYPE_RELAY - the account is a relay
@@ -131,6 +133,17 @@ class User
                return null;
        }
 
+       /**
+        * Get the Uri-Id of the system account
+        *
+        * @return integer
+        */
+       public static function getSystemUriId(): int
+       {
+               $system = self::getSystemAccount();
+               return $system['uri-id'] ?? 0;
+       }
+
        /**
         * Fetch the system account
         *
@@ -166,11 +179,11 @@ class User
                $system['region'] = '';
                $system['postal-code'] = '';
                $system['country-name'] = '';
-               $system['homepage'] = DI::baseUrl();
+               $system['homepage'] = (string)DI::baseUrl();
                $system['dob'] = '0000-00-00';
 
                // Ensure that the user contains data
-               $user = DBA::selectFirst('user', ['prvkey', 'guid'], ['uid' => 0]);
+               $user = DBA::selectFirst('user', ['prvkey', 'guid', 'language'], ['uid' => 0]);
                if (empty($user['prvkey']) || empty($user['guid'])) {
                        $fields = [
                                'username' => $system['name'],
@@ -190,7 +203,8 @@ class User
 
                        $system['guid'] = $fields['guid'];
                } else {
-                       $system['guid'] = $user['guid'];
+                       $system['guid']     = $user['guid'];
+                       $system['language'] = $user['language'];
                }
 
                return $system;
@@ -482,23 +496,63 @@ class User
        }
 
        /**
-        * Returns the default group for a given user and network
+        * Returns the default circle for a given user
         *
         * @param int $uid User id
         *
-        * @return int group id
+        * @return int circle id
         * @throws Exception
         */
-       public static function getDefaultGroup(int $uid): int
+       public static function getDefaultCircle(int $uid): int
        {
                $user = DBA::selectFirst('user', ['def_gid'], ['uid' => $uid]);
                if (DBA::isResult($user)) {
-                       $default_group = $user["def_gid"];
+                       $default_circle = $user['def_gid'];
                } else {
-                       $default_group = 0;
+                       $default_circle = 0;
+               }
+
+               return $default_circle;
+       }
+
+       /**
+        * Returns the default circle for groups for a given user
+        *
+        * @param int $uid User id
+        *
+        * @return int circle id
+        * @throws Exception
+        */
+       public static function getDefaultGroupCircle(int $uid): int
+       {
+               $default_circle = DI::pConfig()->get($uid, 'system', 'default-group-gid');
+               if (empty($default_circle)) {
+                       $default_circle = self::getDefaultCircle($uid);
                }
 
-               return $default_group;
+               return $default_circle;
+       }
+
+/**
+ * Fetch the language code from the given user. If the code is invalid, return the system language
+ *
+ * @param integer $uid   User-Id
+ * @param boolean $short If true, return the short form g.g. "en", otherwise the long form e.g. "en-gb"
+ * @return string
+ */
+       public static function getLanguageCode(int $uid, bool $short): string
+       {
+               $owner = self::getOwnerDataById($uid);
+               $languages = DI::l10n()->getAvailableLanguages();
+               if (in_array($owner['language'], array_keys($languages))) {
+                       $language = $owner['language'];
+               } else {
+                       $language = DI::config()->get('system', 'language');
+               }
+               if ($short) {
+                       return substr($language, 0, 2);
+               }
+               return $language;
        }
 
        /**
@@ -528,7 +582,7 @@ class User
                        // Addons can create users, and since this 'catch' branch should only
                        // execute if getAuthenticationInfo can't find an existing user, that's
                        // exactly what will happen here. Creating a numeric username would create
-                       // abiguity with user IDs, possibly opening up an attack vector.
+                       // ambiguity with user IDs, possibly opening up an attack vector.
                        // So let's be very careful about that.
                        if (empty($username) || is_numeric($username)) {
                                throw $e;
@@ -674,6 +728,10 @@ class User
         */
        public static function updateLastActivity(int $uid)
        {
+               if (!$uid) {
+                       return;
+               }
+
                $user = User::getById($uid, ['last-activity']);
                if (empty($user)) {
                        return;
@@ -683,7 +741,7 @@ class User
 
                if ($user['last-activity'] != $current_day) {
                        User::update(['last-activity' => $current_day], $uid);
-                       // Set the last actitivy for all identities of the user
+                       // Set the last activity for all identities of the user
                        DBA::update('user', ['last-activity' => $current_day], ['parent-uid' => $uid, 'account_removed' => false]);
                }
        }
@@ -815,14 +873,14 @@ class User
         * Empties the password reset token field just in case.
         *
         * @param int    $uid
-        * @param string $pasword_hashed
+        * @param string $password_hashed
         * @return bool
         * @throws Exception
         */
-       private static function updatePasswordHashed(int $uid, string $pasword_hashed): bool
+       private static function updatePasswordHashed(int $uid, string $password_hashed): bool
        {
                $fields = [
-                       'password' => $pasword_hashed,
+                       'password' => $password_hashed,
                        'pwdreset' => null,
                        'pwdreset_time' => null,
                        'legacy_password' => false
@@ -846,11 +904,25 @@ class User
                ]);
        }
 
+       /**
+        * Returns if the given uid is valid and a moderator
+        *
+        * @param int $uid
+        *
+        * @return bool
+        * @throws Exception
+        */
+       public static function isModerator(int $uid): bool
+       {
+               // @todo Replace with a moderator check in the future
+               return self::isSiteAdmin($uid);
+       }
+
        /**
         * Checks if a nickname is in the list of the forbidden nicknames
         *
         * Check if a nickname is forbidden from registration on the node by the
-        * admin. Forbidden nicknames (e.g. role namess) can be configured in the
+        * admin. Forbidden nicknames (e.g. role names) can be configured in the
         * admin panel.
         *
         * @param string $nickname The nickname that should be checked
@@ -1187,13 +1259,13 @@ class User
                        throw new Exception(DI::l10n()->t('An error occurred creating your self contact. Please try again.'));
                }
 
-               // Create a group with no members. This allows somebody to use it
-               // right away as a default group for new contacts.
-               $def_gid = Group::create($uid, DI::l10n()->t('Friends'));
+               // Create a circle with no members. This allows somebody to use it
+               // right away as a default circle for new contacts.
+               $def_gid = Circle::create($uid, DI::l10n()->t('Friends'));
                if (!$def_gid) {
                        DBA::delete('user', ['uid' => $uid]);
 
-                       throw new Exception(DI::l10n()->t('An error occurred creating your default contact group. Please try again.'));
+                       throw new Exception(DI::l10n()->t('An error occurred creating your default contact circle. Please try again.'));
                }
 
                $fields = ['def_gid' => $def_gid];
@@ -1203,6 +1275,11 @@ class User
 
                DBA::update('user', $fields, ['uid' => $uid]);
 
+               $def_gid_groups = Circle::create($uid, DI::l10n()->t('Groups'));
+               if ($def_gid_groups) {
+                       DI::pConfig()->set($uid, 'system', 'default-group-gid', $def_gid_groups);
+               }
+
                // if we have no OpenID photo try to look up an avatar
                if (!strlen($photo)) {
                        $photo = Network::lookupAvatarByEmail($email);
@@ -1231,7 +1308,7 @@ class User
 
                                $resource_id = Photo::newResource();
 
-                               // Not using Photo::PROFILE_PHOTOS here, so that it is discovered as translateble string
+                               // Not using Photo::PROFILE_PHOTOS here, so that it is discovered as translatable string
                                $profile_album = DI::l10n()->t('Profile Photos');
 
                                $r = Photo::store($image, $uid, 0, $resource_id, $filename, $profile_album, 4);
@@ -1266,6 +1343,8 @@ class User
 
                Hook::callAll('register_account', $uid);
 
+               self::setRegisterMethodByUserCount();
+
                $return['user'] = $user;
                return $return;
        }
@@ -1273,33 +1352,18 @@ class User
        /**
         * Update a user entry and distribute the changes if needed
         *
-        * @param array $fields
+        * @param array   $fields
         * @param integer $uid
         * @return boolean
+        * @throws Exception
         */
        public static function update(array $fields, int $uid): bool
        {
-               $old_owner = self::getOwnerDataById($uid);
-               if (empty($old_owner)) {
-                       return false;
-               }
-
                if (!DBA::update('user', $fields, ['uid' => $uid])) {
                        return false;
                }
 
-               $update = Contact::updateSelfFromUserID($uid);
-
-               $owner = self::getOwnerDataById($uid);
-               if (empty($owner)) {
-                       return false;
-               }
-
-               if ($old_owner['name'] != $owner['name']) {
-                       Profile::update(['name' => $owner['name']], $uid);
-               }
-
-               if ($update) {
+               if (Contact::updateSelfFromUserID($uid)) {
                        Profile::publishUpdate($uid);
                }
 
@@ -1374,7 +1438,7 @@ class User
         * permanently against re-registration, as the person was not yet
         * allowed to have friends on this system
         *
-        * @return bool True, if the deny was successfull
+        * @return bool True, if the deny was successful
         * @throws Exception
         */
        public static function deny(string $hash): bool
@@ -1610,6 +1674,7 @@ class User
                // Remove the user relevant data
                Worker::add(Worker::PRIORITY_NEGLIGIBLE, 'RemoveUser', $uid);
 
+               self::setRegisterMethodByUserCount();
                return true;
        }
 
@@ -1636,7 +1701,7 @@ class User
         */
        public static function identities(int $uid): array
        {
-               if (empty($uid)) {
+               if (!$uid) {
                        return [];
                }
 
@@ -1647,7 +1712,7 @@ class User
                        return $identities;
                }
 
-               if ($user['parent-uid'] == 0) {
+               if (!$user['parent-uid']) {
                        // First add our own entry
                        $identities = [[
                                'uid' => $user['uid'],
@@ -1708,7 +1773,7 @@ class User
         */
        public static function hasIdentities(int $uid): bool
        {
-               if (empty($uid)) {
+               if (!$uid) {
                        return false;
                }
 
@@ -1717,7 +1782,7 @@ class User
                        return false;
                }
 
-               if ($user['parent-uid'] != 0) {
+               if ($user['parent-uid']) {
                        return true;
                }
 
@@ -1788,7 +1853,7 @@ class User
         *
         * @param int    $start Start count (Default is 0)
         * @param int    $count Count of the items per page (Default is @see Pager::ITEMS_PER_PAGE)
-        * @param string $type  The type of users, which should get (all, bocked, removed)
+        * @param string $type  The type of users, which should get (all, blocked, removed)
         * @param string $order Order of the user list (Default is 'contact.name')
         * @param bool   $descending Order direction (Default is ascending)
         * @return array|bool The list of the users
@@ -1844,8 +1909,8 @@ class User
        {
                $condition = [
                        'email'           => self::getAdminEmailList(),
-                       'parent-uid'      => 0,
-                       'blocked'         => 0,
+                       'parent-uid'      => null,
+                       'blocked'         => false,
                        'verified'        => true,
                        'account_removed' => false,
                        'account_expired' => false,
@@ -1877,4 +1942,29 @@ class User
                        return true;
                });
        }
+
+       public static function setRegisterMethodByUserCount()
+       {
+               $max_registered_users = DI::config()->get('config', 'max_registered_users');
+               if ($max_registered_users <= 0) {
+                       return;
+               }
+
+               $register_policy = DI::config()->get('config', 'register_policy');
+               if (!in_array($register_policy, [Module\Register::OPEN, Module\Register::CLOSED])) {
+                       Logger::debug('Unsupported register policy.', ['policy' => $register_policy]);
+                       return;
+               }
+
+               $users = DBA::count('user', ['blocked' => false, 'account_removed' => false, 'account_expired' => false]);
+               if (($users >= $max_registered_users) && ($register_policy == Module\Register::OPEN)) {
+                       DI::config()->set('config', 'register_policy', Module\Register::CLOSED);
+                       Logger::notice('Max users reached, registration is closed.', ['users' => $users, 'max' => $max_registered_users]);
+               } elseif (($users < $max_registered_users) && ($register_policy == Module\Register::CLOSED)) {
+                       DI::config()->set('config', 'register_policy', Module\Register::OPEN);
+                       Logger::notice('Below maximum users, registration is opened.', ['users' => $users, 'max' => $max_registered_users]);
+               } else {
+                       Logger::debug('Unchanged register policy', ['policy' => $register_policy, 'users' => $users, 'max' => $max_registered_users]);
+               }
+       }
 }