diff --git a/classes/category/Collector.php b/classes/category/Collector.php index b85c768975e..74db393353f 100644 --- a/classes/category/Collector.php +++ b/classes/category/Collector.php @@ -19,6 +19,8 @@ use Illuminate\Support\LazyCollection; use PKP\core\interfaces\CollectorInterface; use PKP\plugins\Hook; +use PKP\publication\PublicationCategory; + /** * @template T of Category @@ -136,9 +138,10 @@ public function getQueryBuilder(): Builder }); $qb->when($this->publicationIds !== null, function ($query) { - $query->whereIn('c.category_id', function ($query) { - $query->select('category_id')->from('publication_categories')->whereIn('publication_id', $this->publicationIds); - }); + $query->whereIn('c.category_id', PublicationCategory::select('category_id') + ->whereIn('publication_id', $this->publicationIds) + ->toBase() + ); }); $qb->when($this->parentIds !== null, function ($query) { diff --git a/classes/category/DAO.php b/classes/category/DAO.php index 7d1d69e1627..9912a3a5e4b 100644 --- a/classes/category/DAO.php +++ b/classes/category/DAO.php @@ -155,22 +155,4 @@ public function resequenceCategories(int $contextId, ?int $parentCategoryId = nu } } - /** - * Assign a publication to a category - */ - public function insertPublicationAssignment(int $categoryId, int $publicationId) - { - DB::table('publication_categories')->insert([ - 'category_id' => $categoryId, - 'publication_id' => $publicationId, - ]); - } - - /** - * Delete the assignment of a category to a publication - */ - public function deletePublicationAssignments(int $publicationId) - { - DB::table('publication_categories')->where('publication_id', '=', $publicationId)->delete(); - } } diff --git a/classes/publication/DAO.php b/classes/publication/DAO.php index 3bfececa21d..8f0dd3821c7 100644 --- a/classes/publication/DAO.php +++ b/classes/publication/DAO.php @@ -441,36 +441,27 @@ protected function deleteControlledVocab(int $publicationId) /** * Set a publication's category property */ - protected function setCategories(Publication $publication) + protected function setCategories(Publication $publication): void { - $publication->setData( - 'categoryIds', - Repo::category()->getCollector() - ->filterByPublicationIds([$publication->getId()]) - ->getIds() - ->toArray() - ); + $categoryIds = PublicationCategory::withPublicationId($publication->getId())->pluck('category_id'); + $publication->setData('categoryIds', $categoryIds); } /** * Save the assigned categories */ - protected function saveCategories(Publication $publication) + protected function saveCategories(Publication $publication): void { - Repo::category()->dao->deletePublicationAssignments($publication->getId()); - if (!empty($publication->getData('categoryIds'))) { - foreach ($publication->getData('categoryIds') as $categoryId) { - Repo::category()->dao->insertPublicationAssignment($categoryId, $publication->getId()); - } - } + $categoryIds = (array) $publication->getData('categoryIds'); + Repo::publication()->assignCategoriesToPublication($publication->getId(), $categoryIds); } /** * Delete the category assignments */ - protected function deleteCategories(int $publicationId) + protected function deleteCategories(int $publicationId): void { - Repo::category()->dao->deletePublicationAssignments($publicationId); + PublicationCategory::where('publication_id', $publicationId)->delete(); } /** diff --git a/classes/publication/PublicationCategory.php b/classes/publication/PublicationCategory.php new file mode 100644 index 00000000000..eb670d27d22 --- /dev/null +++ b/classes/publication/PublicationCategory.php @@ -0,0 +1,50 @@ +where('publication_id', $publicationId); + } + + /** + * Scope a query to only include records with specific categoryIds + * + * @param int[] $categoryIds Array of category IDs + */ + public function scopeWithCategoryIds(Builder $query, array $categoryIds): Builder + { + return $query->whereIn('category_id', $categoryIds); + } + +} diff --git a/classes/publication/Repository.php b/classes/publication/Repository.php index c829375ab29..56dc336996d 100644 --- a/classes/publication/Repository.php +++ b/classes/publication/Repository.php @@ -766,6 +766,23 @@ protected function getErrorMessageOverrides(): array ]; } + /** + * Assign categories to a publication. + * + * @param int[] $categoryIds + */ + public function assignCategoriesToPublication(int $publicationId, array $categoryIds): void + { + $records = array_map(fn ($categoryId) => ['publication_id' => $publicationId, 'category_id' => $categoryId], $categoryIds); + + PublicationCategory::upsert($records, ['publication_id', 'category_id']); + + // delete categories that are no longer assigned + PublicationCategory::where('publication_id', $publicationId) + ->whereNotIn('category_id', $categoryIds) + ->delete(); + } + /** * Create all DOIs associated with the publication. */ diff --git a/classes/submission/Collector.php b/classes/submission/Collector.php index b2c73684adb..a6e70fa18c1 100644 --- a/classes/submission/Collector.php +++ b/classes/submission/Collector.php @@ -31,6 +31,8 @@ use PKP\search\SubmissionSearch; use PKP\security\Role; use PKP\submission\reviewRound\ReviewRound; +use PKP\publication\PublicationCategory; + /** * @template T of Submission @@ -623,8 +625,11 @@ public function getQueryBuilder(): Builder } if (isset($this->categoryIds)) { - $q->join('publication_categories as pc', 's.current_publication_id', '=', 'pc.publication_id') - ->whereIn('pc.category_id', $this->categoryIds); + $publicationIds = PublicationCategory::withCategoryIds($this->categoryIds) + ->select('publication_id') + ->toBase(); + + $q->whereIn('s.current_publication_id', $publicationIds); } $q = $this->buildReviewStageQueries($q); diff --git a/schemas/publication.json b/schemas/publication.json index 025f0d3fd58..2e4864a16ca 100644 --- a/schemas/publication.json +++ b/schemas/publication.json @@ -49,6 +49,7 @@ "categoryIds": { "type": "array", "apiSummary": true, + "readOnly": true, "items": { "type": "integer" }