Skip to content

Commit

Permalink
pkp#10292 Refactored user interest to model and repository
Browse files Browse the repository at this point in the history
  • Loading branch information
touhidurabir committed Oct 23, 2024
1 parent 55f43a9 commit 5e2c9f3
Show file tree
Hide file tree
Showing 6 changed files with 151 additions and 138 deletions.
49 changes: 0 additions & 49 deletions classes/controlledVocab/Repository.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,8 @@

namespace PKP\controlledVocab;

use APP\facades\Repo;
use Illuminate\Support\Facades\DB;
use PKP\db\DAORegistry;
use PKP\user\UserInterest;
use PKP\user\InterestEntry;
use PKP\user\InterestEntryDAO;
use PKP\controlledVocab\ControlledVocab;
use PKP\controlledVocab\ControlledVocabEntryDAO;

Expand Down Expand Up @@ -151,49 +147,4 @@ public function insertBySymbolic(
}
}
}

/**
* Update a user's set of interests
*/
public function setUserInterests(array $interests, int $userId): void
{
$controlledVocab = Repo::controlledVocab()->build(
UserInterest::CONTROLLED_VOCAB_INTEREST
);

/** @var InterestEntryDAO $interestEntryDao */
$interestEntryDao = DAORegistry::getDAO('InterestEntryDAO');

DB::beginTransaction();

// Delete the existing interests association.
UserInterest::withUserId($userId)->delete();

collect($interests)
->map(fn (string $interest): string => trim($interest))
->unique()
->each(function (string $interest) use ($controlledVocab, $interestEntryDao, $userId): void {
$interestEntry = $interestEntryDao->getBySetting(
$interest,
$controlledVocab->symbolic,
$controlledVocab->assocId,
$controlledVocab->assocType,
$controlledVocab->symbolic
);

if (!$interestEntry) {
$interestEntry = $interestEntryDao->newDataObject(); /** @var InterestEntry $interestEntry */
$interestEntry->setInterest($interest);
$interestEntry->setControlledVocabId($controlledVocab->id);
$interestEntry->setId($interestEntryDao->insertObject($interestEntry));
}

UserInterest::create([
'userId' => $userId,
'controlledVocabEntryId' => $interestEntry->getId(),
]);
});

DB::commit();
}
}
6 changes: 6 additions & 0 deletions classes/facades/Repo.php
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@
use PKP\stageAssignment\Repository as StageAssignmentRepository;
use PKP\submissionFile\Repository as SubmissionFileRepository;
use PKP\userGroup\Repository as UserGroupRepository;
use PKP\user\interest\Repository as UserInterestRepository;

class Repo
{
Expand Down Expand Up @@ -146,4 +147,9 @@ public static function controlledVocab(): ControlledVocabRepository
{
return app(ControlledVocabRepository::class);
}

public static function userInterest(): UserInterestRepository
{
return app(UserInterestRepository::class);
}
}
8 changes: 4 additions & 4 deletions classes/user/InterestManager.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
use APP\facades\Repo;
use PKP\db\DAORegistry;
use PKP\user\User;
use PKP\user\UserInterest;
use PKP\user\interest\UserInterest;

class InterestManager
{
Expand All @@ -26,7 +26,7 @@ class InterestManager
*/
public function getAllInterests(?string $filter = null): array
{
$interests = UserInterest::getAllInterests($filter);
$interests = Repo::userInterest()->getAllInterests($filter);

$interestReturner = [];
while ($interest = $interests->next()) {
Expand All @@ -46,7 +46,7 @@ public function getInterestsForUser(User $user): array
$interestEntryDao = DAORegistry::getDAO('InterestEntryDAO'); /** @var InterestEntryDAO $interestEntryDao */
$controlledVocab = Repo::controlledVocab()->build(UserInterest::CONTROLLED_VOCAB_INTEREST);

foreach (UserInterest::getUserInterestIds($user->getId()) as $interestEntryId) {
foreach (Repo::userInterest()->getUserInterestIds($user->getId()) as $interestEntryId) {
/** @var InterestEntry */
$interestEntry = $interestsCache[$interestEntryId] ??= $interestEntryDao->getById(
$interestEntryId,
Expand Down Expand Up @@ -79,7 +79,7 @@ public function setInterestsForUser(User $user, string|array|null $interests = n
? $interests
: (empty($interests) ? [] : explode(',', $interests));

Repo::controlledVocab()->setUserInterests($interests, $user->getId());
Repo::userInterest()->setUserInterests($interests, $user->getId());
}
}

Expand Down
144 changes: 61 additions & 83 deletions classes/user/UserInterest.php → classes/user/interest/Repository.php
Original file line number Diff line number Diff line change
@@ -1,106 +1,39 @@
<?php

/**
* @file classes/user/UserInterest.php
* @file classes/user/userInterest/Repository.php
*
* Copyright (c) 2024 Simon Fraser University
* Copyright (c) 2024 John Willinsky
* Distributed under the GNU GPL v3. For full terms see the file docs/COPYING.
*
* @class UserInterest
* @class Repository
*
* @brief UserInterest model calss
* @brief
*/

namespace PKP\user;
namespace PKP\user\interest;

use APP\facades\Repo;
use Eloquence\Behaviours\HasCamelCasing;
use Illuminate\Database\Eloquent\Model;
use PKP\db\DAORegistry;
use PKP\user\InterestEntry;
use PKP\user\InterestEntryDAO;
use PKP\core\ArrayItemIterator;
use Illuminate\Support\Facades\DB;
use PKP\user\interest\UserInterest;
use Illuminate\Database\Query\JoinClause;
use Illuminate\Database\Eloquent\Casts\Attribute;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Support\Collection;
use PKP\core\ArrayItemIterator;
use PKP\user\InterestEntryDAO;
use PKP\db\DAORegistry;

class UserInterest extends Model
class Repository
{
use HasCamelCasing;

public const CONTROLLED_VOCAB_INTEREST = 'interest';

protected $table = 'user_interests';
protected $primaryKey = 'user_interest_id';

protected $guarded = [
'user_interest_id',
];

/**
* Indicates if the model should be timestamped.
*
* @var bool
*/
public $timestamps = false;

protected function casts(): array
{
return [
'user_id' => 'integer',
'controlled_vocab_entry_id' => 'integer',
];
}

/**
* Accessor and Mutator for primary key => id
*/
protected function id(): Attribute
{
return Attribute::make(
get: fn($value, $attributes) => $attributes[$this->primaryKey] ?? null,
set: fn($value) => [$this->primaryKey => $value],
);
}

/**
* Compatibility function for including note IDs in grids.
*
* @deprecated 3.5.0 Use $model->id instead. Can be removed once the DataObject pattern is removed.
*/
public function getId(): int
{
return $this->id;
}

/**
* Compatibility function for including notes in grids.
*
* @deprecated 3.5. Use $model or $model->$field instead. Can be removed once the DataObject pattern is removed.
*/
public function getData(?string $field): mixed
{
return $field ? $this->$field : $this;
}

/**
* Scope a query to only include notes with a specific assoc type and assoc ID.
*/
public function scopeWithUserId(Builder $query, int $userId): Builder
{
return $query->where('user_id', $userId);
}

/**
* Get a list of controlled vocabulary entry IDs (corresponding to interest keywords)
* attributed to a user
*/
public static function getUserInterestIds(int $userId): array
public function getUserInterestIds(int $userId): array
{
$controlledVocab = Repo::controlledVocab()->build(
static::CONTROLLED_VOCAB_INTEREST
UserInterest::CONTROLLED_VOCAB_INTEREST
);

return DB::table('controlled_vocab_entries AS cve')
Expand All @@ -120,15 +53,15 @@ public static function getUserInterestIds(int $userId): array
/**
* Get a list of user IDs attributed to an interest
*/
public static function getUserIdsByInterest(string $interest): array
public function getUserIdsByInterest(string $interest): array
{
return DB::table('user_interests AS ui')
->select('ui.user_id')
->join(
'controlled_vocab_entry_settings AS cves',
fn (JoinClause $join) => $join
->on('cves.controlled_vocab_entry_id', '=', 'ui.controlled_vocab_entry_id')
->where('cves.setting_name', STATIC::CONTROLLED_VOCAB_INTEREST)
->where('cves.setting_name', UserInterest::CONTROLLED_VOCAB_INTEREST)
->where(DB::raw('LOWER(cves.setting_value)'), trim(strtolower($interest)))
)
->get()
Expand All @@ -140,10 +73,10 @@ public static function getUserIdsByInterest(string $interest): array
/**
* Get all user's interests
*/
public static function getAllInterests(?string $filter = null): object
public function getAllInterests(?string $filter = null): object
{
$controlledVocab = Repo::controlledVocab()->build(
static::CONTROLLED_VOCAB_INTEREST
UserInterest::CONTROLLED_VOCAB_INTEREST
);

$interestEntryDao = DAORegistry::getDAO('InterestEntryDAO'); /** @var InterestEntryDAO $interestEntryDao */
Expand All @@ -158,4 +91,49 @@ public static function getAllInterests(?string $filter = null): object
// Turn back into an iterator.
return new ArrayItemIterator($interests);
}

/**
* Update a user's set of interests
*/
public function setUserInterests(array $interests, int $userId): void
{
$controlledVocab = Repo::controlledVocab()->build(
UserInterest::CONTROLLED_VOCAB_INTEREST
);

/** @var InterestEntryDAO $interestEntryDao */
$interestEntryDao = DAORegistry::getDAO('InterestEntryDAO');

DB::beginTransaction();

// Delete the existing interests association.
UserInterest::withUserId($userId)->delete();

collect($interests)
->map(fn (string $interest): string => trim($interest))
->unique()
->each(function (string $interest) use ($controlledVocab, $interestEntryDao, $userId): void {
$interestEntry = $interestEntryDao->getBySetting(
$interest,
$controlledVocab->symbolic,
$controlledVocab->assocId,
$controlledVocab->assocType,
$controlledVocab->symbolic
);

if (!$interestEntry) {
$interestEntry = $interestEntryDao->newDataObject(); /** @var InterestEntry $interestEntry */
$interestEntry->setInterest($interest);
$interestEntry->setControlledVocabId($controlledVocab->id);
$interestEntry->setId($interestEntryDao->insertObject($interestEntry));
}

UserInterest::create([
'userId' => $userId,
'controlledVocabEntryId' => $interestEntry->getId(),
]);
});

DB::commit();
}
}
79 changes: 79 additions & 0 deletions classes/user/interest/UserInterest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
<?php

/**
* @file classes/user/interest/UserInterest.php
*
* Copyright (c) 2024 Simon Fraser University
* Copyright (c) 2024 John Willinsky
* Distributed under the GNU GPL v3. For full terms see the file docs/COPYING.
*
* @class UserInterest
*
* @brief UserInterest model calss
*/

namespace PKP\user\interest;

use Eloquence\Behaviours\HasCamelCasing;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Casts\Attribute;
use Illuminate\Database\Eloquent\Builder;


class UserInterest extends Model
{
use HasCamelCasing;

public const CONTROLLED_VOCAB_INTEREST = 'interest';

protected $table = 'user_interests';
protected $primaryKey = 'user_interest_id';

protected $guarded = [
'user_interest_id',
];

/**
* Indicates if the model should be timestamped.
*
* @var bool
*/
public $timestamps = false;

protected function casts(): array
{
return [
'user_id' => 'integer',
'controlled_vocab_entry_id' => 'integer',
];
}

/**
* Accessor and Mutator for primary key => id
*/
protected function id(): Attribute
{
return Attribute::make(
get: fn($value, $attributes) => $attributes[$this->primaryKey] ?? null,
set: fn($value) => [$this->primaryKey => $value],
);
}

/**
* Compatibility function for including note IDs in grids.
*
* @deprecated 3.5.0 Use $model->id instead. Can be removed once the DataObject pattern is removed.
*/
public function getId(): int
{
return $this->id;
}

/**
* Scope a query to only include notes with a specific assoc type and assoc ID.
*/
public function scopeWithUserId(Builder $query, int $userId): Builder
{
return $query->where('user_id', $userId);
}
}
Loading

0 comments on commit 5e2c9f3

Please sign in to comment.