[ Mini Kiebo ]
Server: Windows NT DESKTOP-5B8S0D4 6.2 build 9200 (Windows 8 Professional Edition) i586
Path:
D:
/
Backup
/
05122024
/
htdocs
/
jurnal-kesmas
/
v1
/
lib
/
pkp
/
classes
/
user
/
[
Home
]
File: DAO.php
<?php /** * @file classes/user/DAO.php * * Copyright (c) 2014-2021 Simon Fraser University * Copyright (c) 2000-2021 John Willinsky * Distributed under the GNU GPL v3. For full terms see the file docs/COPYING. * * @class DAO * * @ingroup user * * @see User * * @brief Operations for retrieving and modifying User objects. */ namespace PKP\user; use APP\facades\Repo; use Carbon\Carbon; use Illuminate\Support\Collection; use Illuminate\Support\Facades\DB; use Illuminate\Support\LazyCollection; use PKP\core\DataObject; use PKP\core\EntityDAO; use PKP\identity\Identity; /** * @template T of User * @extends EntityDAO<T> */ class DAO extends EntityDAO { /** @copydoc EntityDAO::$schema */ public $schema = \PKP\services\PKPSchemaService::SCHEMA_USER; /** @copydoc EntityDAO::$table */ public $table = 'users'; /** @copydoc EntityDAO::$settingsTable */ public $settingsTable = 'user_settings'; /** @copydoc EntityDAO::$primarykeyColumn */ public $primaryKeyColumn = 'user_id'; /** @copydoc EntityDAO::$primaryTableColumns */ public $primaryTableColumns = [ 'id' => 'user_id', 'userName' => 'username', 'password' => 'password', 'email' => 'email', 'url' => 'url', 'phone' => 'phone', 'mailingAddress' => 'mailing_address', 'billingAddress' => 'billing_address', 'country' => 'country', 'locales' => 'locales', 'gossip' => 'gossip', 'dateLastEmail' => 'date_last_email', 'dateRegistered' => 'date_registered', 'dateValidated' => 'date_validated', 'dateLastLogin' => 'date_last_login', 'mustChangePassword' => 'must_change_password', 'authStr' => 'auth_str', 'disabled' => 'disabled', 'disabledReason' => 'disabled_reason', 'inlineHelp' => 'inline_help', ]; /* These constants are used user-selectable search fields. */ public const USER_FIELD_USERID = 'user_id'; public const USER_FIELD_USERNAME = 'username'; public const USER_FIELD_EMAIL = 'email'; public const USER_FIELD_URL = 'url'; public const USER_FIELD_INTERESTS = 'interests'; public const USER_FIELD_AFFILIATION = 'affiliation'; public const USER_FIELD_NONE = null; /** * Construct a new User object. */ public function newDataObject() { return new User(); } /** * Get a user * * @param bool $allowDisabled If true, allow fetching a disabled user. */ public function get(int $id, $allowDisabled = false): ?User { $row = DB::table($this->table) ->where($this->primaryKeyColumn, $id) ->first(); /** @var User */ $user = $row ? $this->fromRow($row) : null; if (!$allowDisabled && $user?->getDisabled()) { return null; } return $user; } /** * Check if a user exists */ public function exists(int $id): bool { return DB::table($this->table) ->where($this->primaryKeyColumn, '=', $id) ->exists(); } /** * Get a collection of users matching the configured query * @return LazyCollection<int,T> */ public function getMany(Collector $query): LazyCollection { $rows = $query ->getQueryBuilder() ->get(); return LazyCollection::make(function () use ($rows, $query) { foreach ($rows as $row) { yield $row->user_id => $this->fromRow($row, $query->includeReviewerData); } }); } /** * Get the total count of users matching the configured query */ public function getCount(Collector $query): int { return $query ->getQueryBuilder() ->count(); } /** * Get a list of ids matching the configured query * * @return Collection<int,int> */ public function getIds(Collector $query): Collection { return $query ->getQueryBuilder() ->select('u.' . $this->primaryKeyColumn) ->pluck('u.' . $this->primaryKeyColumn); } /** * Retrieve a user by username. * * @return ?User */ public function getByUsername(string $username, bool $allowDisabled = false): ?User { $row = DB::table('users') ->whereRaw('LOWER(username) = LOWER(?)', [$username]) ->when(!$allowDisabled, function ($query) { return $query->where('disabled', '=', false); }) ->get('user_id') ->first(); return $row ? $this->get($row->user_id, $allowDisabled) : null; } /** * Retrieve a user by email address. * * @return ?User */ public function getByEmail(string $email, bool $allowDisabled = false): ?User { $row = DB::table('users') ->whereRaw('LOWER(email) = LOWER(?)', [$email]) ->when(!$allowDisabled, function ($query) { return $query->where('disabled', '=', false); }) ->get('user_id') ->first(); return $row ? $this->get($row->user_id, $allowDisabled) : null; } /** * Get the user by the TDL ID (implicit authentication). * * @param string $authstr * @param bool $allowDisabled * * @return ?User */ public function getUserByAuthStr($authstr, $allowDisabled = true): ?User { $row = DB::table('users') ->where('auth_str', $authstr) ->when(!$allowDisabled, function ($query) { return $query->where('disabled', 0); }) ->get('user_id') ->first(); return $row ? $this->get($row->user_id) : null; } /** * Retrieve a user by username and (encrypted) password. * * @param string $username * @param string $password encrypted password * @param bool $allowDisabled * * @return ?User */ public function getUserByCredentials($username, $password, $allowDisabled = true): ?User { $row = DB::table('users') ->where('username', '=', $username) ->where('password', '=', $password) ->when(!$allowDisabled, function ($query) { return $query->where('disabled', '=', false); }) ->get('user_id') ->first(); return $row ? $this->get($row->user_id) : null; } /** * @copydoc EntityDAO::fromRow * */ public function fromRow(object $row, bool $includeReviewerData = false): DataObject { $user = parent::fromRow($row); if ($includeReviewerData) { $user->setData('lastAssigned', $row->last_assigned); $user->setData('incompleteCount', (int) $row->incomplete_count); $user->setData('completeCount', (int) $row->complete_count); $user->setData('declinedCount', (int) $row->declined_count); $user->setData('cancelledCount', (int) $row->cancelled_count); $user->setData('averageTime', (int) $row->average_time); // 0 values should return null. They represent a reviewer with no ratings if ($reviewerRating = $row->reviewer_rating) { $user->setData('reviewerRating', max(1, round($reviewerRating))); } } return $user; } /** * @copydoc EntityDAO::_insert() */ public function insert(User $user): int { return parent::_insert($user); } /** * @copydoc EntityDAO::update() */ public function update(User $user) { parent::_update($user); } /** * @copydoc EntityDAO::_delete() */ public function delete(User $user) { parent::_delete($user); } /** * Update user names when the site primary locale changes. * * @param string $oldLocale * @param string $newLocale */ public function changeSitePrimaryLocale($oldLocale, $newLocale) { // remove all empty user names in the new locale // so that we do not have to take care if we should insert or update them -- we can then only insert them if needed $settingNames = [Identity::IDENTITY_SETTING_GIVENNAME, Identity::IDENTITY_SETTING_FAMILYNAME, 'preferredPublicName']; foreach ($settingNames as $settingName) { DB::delete("DELETE from user_settings WHERE locale = ? AND setting_name = ? AND setting_value = ''", [$newLocale, $settingName]); } // get all names of all users in the new locale $result = DB::select( 'SELECT DISTINCT us.user_id, usg.setting_value AS given_name, usf.setting_value AS family_name, usp.setting_value AS preferred_public_name FROM user_settings us LEFT JOIN user_settings usg ON (usg.user_id = us.user_id AND usg.locale = ? AND usg.setting_name = ?) LEFT JOIN user_settings usf ON (usf.user_id = us.user_id AND usf.locale = ? AND usf.setting_name = ?) LEFT JOIN user_settings usp ON (usp.user_id = us.user_id AND usp.locale = ? AND usp.setting_name = ?)', [$newLocale, Identity::IDENTITY_SETTING_GIVENNAME, $newLocale, Identity::IDENTITY_SETTING_FAMILYNAME, $newLocale, 'preferredPublicName'] ); foreach ($result as $row) { $userId = $row->user_id; if (empty($row->given_name) && empty($row->family_name) && empty($row->preferred_public_name)) { // if no user name exists in the new locale, insert them all foreach ($settingNames as $settingName) { DB::insert( 'INSERT INTO user_settings (user_id, locale, setting_name, setting_value) SELECT DISTINCT us.user_id, ?, ?, us.setting_value FROM user_settings us WHERE us.setting_name = ? AND us.locale = ? AND us.user_id = ?', [$newLocale, $settingName, $settingName, $oldLocale, $userId] ); } } elseif (empty($row->given_name)) { // if the given name does not exist in the new locale (but one of the other names do exist), insert it DB::insert( 'INSERT INTO user_settings (user_id, locale, setting_name, setting_value) SELECT DISTINCT us.user_id, ?, ?, us.setting_value FROM user_settings us WHERE us.setting_name = ? AND us.locale = ? AND us.user_id = ?', [$newLocale, Identity::IDENTITY_SETTING_GIVENNAME, Identity::IDENTITY_SETTING_GIVENNAME, $oldLocale, $userId] ); } } } /** * Delete unvalidated expired users * * @param Carbon $dateTillValid The dateTime till before which user will consider expired * @param array $excludableUsersId The users id to exclude form delete operation * * @return int The number rows affected by DB operation */ public function deleteUnvalidatedExpiredUsers(Carbon $dateTillValid, array $excludableUsersId = []) { $users = DB::table('users') ->whereNull('date_validated') ->whereNull('date_last_login') ->where('date_registered', '<', $dateTillValid) ->when(!empty($excludableUsersId), fn ($query) => $query->whereNotIn('id', $excludableUsersId)) ->get(); $userRepository = Repo::user(); $users->each(fn ($user) => $userRepository->delete($userRepository->get($user->user_id, true))); return $users->count(); } }