313 lines
9.9 KiB
PHP
313 lines
9.9 KiB
PHP
<?php
|
|
/**
|
|
* @file classes/submission/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
|
|
*
|
|
* @brief Read and write submissions to the database.
|
|
*/
|
|
|
|
namespace PKP\submission;
|
|
|
|
use APP\core\Application;
|
|
use APP\facades\Repo;
|
|
use APP\submission\Collector;
|
|
use APP\submission\Submission;
|
|
use Illuminate\Support\Collection;
|
|
use Illuminate\Support\Enumerable;
|
|
use Illuminate\Support\Facades\DB;
|
|
use Illuminate\Support\LazyCollection;
|
|
use PKP\core\EntityDAO;
|
|
use PKP\core\traits\EntityWithParent;
|
|
use PKP\db\DAORegistry;
|
|
use PKP\log\event\EventLogEntry;
|
|
use PKP\log\SubmissionEmailLogDAO;
|
|
use PKP\note\NoteDAO;
|
|
use PKP\notification\NotificationDAO;
|
|
use PKP\query\QueryDAO;
|
|
use PKP\services\PKPSchemaService;
|
|
use PKP\stageAssignment\StageAssignmentDAO;
|
|
use PKP\submission\reviewAssignment\ReviewAssignmentDAO;
|
|
use PKP\submission\reviewRound\ReviewRoundDAO;
|
|
|
|
/**
|
|
* @template T of Submission
|
|
* @extends EntityDAO<T>
|
|
*/
|
|
class DAO extends EntityDAO
|
|
{
|
|
use EntityWithParent;
|
|
|
|
/** @copydoc EntityDAO::$schema */
|
|
public $schema = PKPSchemaService::SCHEMA_SUBMISSION;
|
|
|
|
/** @copydoc EntityDAO::$table */
|
|
public $table = 'submissions';
|
|
|
|
/** @copydoc EntityDAO::$settingsTable */
|
|
public $settingsTable = 'submission_settings';
|
|
|
|
/** @copydoc EntityDAO::$primaryKeyColumn */
|
|
public $primaryKeyColumn = 'submission_id';
|
|
|
|
/** @copydoc SchemaDAO::$primaryTableColumns */
|
|
public $primaryTableColumns = [
|
|
'id' => 'submission_id',
|
|
'contextId' => 'context_id',
|
|
'currentPublicationId' => 'current_publication_id',
|
|
'dateLastActivity' => 'date_last_activity',
|
|
'dateSubmitted' => 'date_submitted',
|
|
'lastModified' => 'last_modified',
|
|
'locale' => 'locale',
|
|
'stageId' => 'stage_id',
|
|
'status' => 'status',
|
|
'submissionProgress' => 'submission_progress',
|
|
];
|
|
|
|
/**
|
|
* Get the parent object ID column name
|
|
*/
|
|
public function getParentColumn(): string
|
|
{
|
|
return 'context_id';
|
|
}
|
|
|
|
/**
|
|
* Instantiate a new DataObject
|
|
*/
|
|
public function newDataObject(): Submission
|
|
{
|
|
return app(Submission::class);
|
|
}
|
|
|
|
/**
|
|
* Get the total count of submissions 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('s.' . $this->primaryKeyColumn)
|
|
->pluck('s.' . $this->primaryKeyColumn);
|
|
}
|
|
|
|
/**
|
|
* Get a collection of announcements matching the configured query
|
|
* @return LazyCollection<int,T>
|
|
*/
|
|
public function getMany(Collector $query): LazyCollection
|
|
{
|
|
$rows = $query
|
|
->getQueryBuilder()
|
|
->get();
|
|
|
|
return LazyCollection::make(function () use ($rows) {
|
|
foreach ($rows as $row) {
|
|
yield $row->submission_id => $this->fromRow($row);
|
|
}
|
|
});
|
|
}
|
|
|
|
/**
|
|
* Get the submission id by its url path
|
|
*/
|
|
public function getIdByUrlPath(string $urlPath, int $contextId): ?int
|
|
{
|
|
$publication = DB::table('publications as p')
|
|
->leftJoin('submissions as s', 's.submission_id', '=', 'p.submission_id')
|
|
->where('s.context_id', '=', $contextId)
|
|
->where('p.url_path', '=', $urlPath)
|
|
->first();
|
|
|
|
return $publication
|
|
? $publication->submission_id
|
|
: null;
|
|
}
|
|
|
|
/**
|
|
* Get submission ids that have a matching setting
|
|
*/
|
|
public function getIdsBySetting(string $settingName, $settingValue, int $contextId): Enumerable
|
|
{
|
|
return DB::table($this->table . ' as s')
|
|
->join($this->settingsTable . ' as ss', 's.submission_id', '=', 'ss.submission_id')
|
|
->where('ss.setting_name', '=', $settingName)
|
|
->where('ss.setting_value', '=', $settingValue)
|
|
->where('s.context_id', '=', (int) $contextId)
|
|
->select('s.submission_id')
|
|
->pluck('s.submission_id');
|
|
}
|
|
|
|
/**
|
|
* Retrieve a submission by public id
|
|
*
|
|
* @param string $pubIdType One of the NLM pub-id-type values or
|
|
* 'other::something' if not part of the official NLM list
|
|
* (see <http://dtd.nlm.nih.gov/publishing/tag-library/n-4zh0.html>).
|
|
* @param null|mixed $contextId
|
|
*/
|
|
public function getByPubId(string $pubIdType, string $pubId, $contextId = null): ?Submission
|
|
{
|
|
// Add check for incoming DOI request for legacy calls that bypass the Submission Repository
|
|
if ($pubIdType == 'doi') {
|
|
return $this->getByDoi($pubId, $contextId);
|
|
} else {
|
|
$qb = DB::table('publication_settings ps')
|
|
->join('publications p', 'p.publication_id', '=', 'ps.publication_id')
|
|
->join('submissions s', 'p.publication_id', '=', 's.current_publication_id')
|
|
->where('ps.setting_name', '=', 'pub-id::' . $pubIdType)
|
|
->where('ps.setting_value', '=', $pubId);
|
|
|
|
if ($contextId) {
|
|
$qb->where('s.context_id', '=', (int) $contextId);
|
|
}
|
|
|
|
$row = $qb->get(['s.submission_id'])->first();
|
|
|
|
return $row
|
|
? $this->get($row->submission_id)
|
|
: null;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Retrieve a submission by its current publication's DOI
|
|
*/
|
|
public function getByDoi(string $doi, int $contextId): ?Submission
|
|
{
|
|
$q = DB::table($this->table, 's')
|
|
->leftJoin('publications AS p', 'p.publication_id', '=', 's.current_publication_id')
|
|
->leftJoin('dois AS d', 'd.doi_id', '=', 'p.doi_id')
|
|
->where('d.doi', '=', $doi)
|
|
->where('s.context_id', '=', $contextId);
|
|
$row = $q->select(['s.submission_id AS submission_id'])->get()->first();
|
|
return $row ? $this->get($row->submission_id) : null;
|
|
}
|
|
|
|
/**
|
|
* @copydoc EntityDAO::fromRow()
|
|
*/
|
|
public function fromRow(object $row): Submission
|
|
{
|
|
$submission = parent::fromRow($row);
|
|
|
|
$submission->setData(
|
|
'publications',
|
|
Repo::publication()->getCollector()
|
|
->filterBySubmissionIds([$submission->getId()])
|
|
->getMany()
|
|
->remember()
|
|
);
|
|
|
|
return $submission;
|
|
}
|
|
|
|
/**
|
|
* @copydoc EntityDAO::_insert()
|
|
*/
|
|
public function insert(Submission $submission): int
|
|
{
|
|
return parent::_insert($submission);
|
|
}
|
|
|
|
/**
|
|
* @copydoc EntityDAO::_update()
|
|
*/
|
|
public function update(Submission $submission)
|
|
{
|
|
parent::_update($submission);
|
|
}
|
|
|
|
/**
|
|
* @copydoc EntityDAO::_delete()
|
|
*/
|
|
public function delete(Submission $submission)
|
|
{
|
|
parent::_delete($submission);
|
|
}
|
|
|
|
/**
|
|
* @copydoc \PKP\core\EntityDAO::deleteById()
|
|
*/
|
|
public function deleteById(int $id)
|
|
{
|
|
$submission = Repo::submission()->get($id);
|
|
|
|
// Delete publications
|
|
$publications = Repo::publication()->getCollector()
|
|
->filterBySubmissionIds([$id])
|
|
->getMany();
|
|
|
|
foreach ($publications as $publication) {
|
|
Repo::publication()->delete($publication);
|
|
}
|
|
|
|
// Delete submission files.
|
|
$submissionFiles = Repo::submissionFile()
|
|
->getCollector()
|
|
->filterBySubmissionIds([$submission->getId()])
|
|
->getMany();
|
|
|
|
foreach ($submissionFiles as $submissionFile) {
|
|
Repo::submissionFile()->delete($submissionFile);
|
|
}
|
|
|
|
Repo::decision()->deleteBySubmissionId($id);
|
|
|
|
$reviewAssignmentDao = DAORegistry::getDAO('ReviewAssignmentDAO'); /** @var ReviewAssignmentDAO $reviewAssignmentDao */
|
|
$reviewAssignmentDao->deleteBySubmissionId($id);
|
|
|
|
$reviewRoundDao = DAORegistry::getDAO('ReviewRoundDAO'); /** @var ReviewRoundDAO $reviewRoundDao */
|
|
$reviewRoundDao->deleteBySubmissionId($id);
|
|
|
|
// Delete the queries associated with a submission
|
|
$queryDao = DAORegistry::getDAO('QueryDAO'); /** @var QueryDAO $queryDao */
|
|
$queryDao->deleteByAssoc(Application::ASSOC_TYPE_SUBMISSION, $id);
|
|
|
|
// Delete the stage assignments.
|
|
$stageAssignmentDao = DAORegistry::getDAO('StageAssignmentDAO'); /** @var StageAssignmentDAO $stageAssignmentDao */
|
|
$stageAssignments = $stageAssignmentDao->getBySubmissionAndStageId($id);
|
|
while ($stageAssignment = $stageAssignments->next()) {
|
|
$stageAssignmentDao->deleteObject($stageAssignment);
|
|
}
|
|
|
|
$noteDao = DAORegistry::getDAO('NoteDAO'); /** @var NoteDAO $noteDao */
|
|
$noteDao->deleteByAssoc(Application::ASSOC_TYPE_SUBMISSION, $id);
|
|
|
|
$submissionCommentDao = DAORegistry::getDAO('SubmissionCommentDAO'); /** @var SubmissionCommentDAO $submissionCommentDao */
|
|
$submissionCommentDao->deleteBySubmissionId($id);
|
|
|
|
// Delete any outstanding notifications for this submission
|
|
$notificationDao = DAORegistry::getDAO('NotificationDAO'); /** @var NotificationDAO $notificationDao */
|
|
$notificationDao->deleteByAssoc(Application::ASSOC_TYPE_SUBMISSION, $id);
|
|
|
|
Repo::eventLog()->getCollector()
|
|
->filterByAssoc(Application::ASSOC_TYPE_SUBMISSION, [$id])
|
|
->getMany()
|
|
->each(function (EventLogEntry $logEntry) {
|
|
Repo::eventLog()->delete($logEntry);
|
|
});
|
|
|
|
$submissionEmailLogDao = DAORegistry::getDAO('SubmissionEmailLogDAO'); /** @var SubmissionEmailLogDAO $submissionEmailLogDao */
|
|
$submissionEmailLogDao->deleteByAssoc(Application::ASSOC_TYPE_SUBMISSION, $id);
|
|
|
|
parent::deleteById($id);
|
|
}
|
|
}
|