first commit
This commit is contained in:
@@ -0,0 +1,582 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @file controllers/wizard/fileUpload/FileUploadWizardHandler.php
|
||||
*
|
||||
* Copyright (c) 2014-2021 Simon Fraser University
|
||||
* Copyright (c) 2003-2021 John Willinsky
|
||||
* Distributed under the GNU GPL v3. For full terms see the file docs/COPYING.
|
||||
*
|
||||
* @class FileUploadWizardHandler
|
||||
*
|
||||
* @ingroup controllers_wizard_fileUpload
|
||||
*
|
||||
* @brief A controller that handles basic server-side
|
||||
* operations of the file upload wizard.
|
||||
*/
|
||||
|
||||
namespace PKP\controllers\wizard\fileUpload;
|
||||
|
||||
use APP\core\Application;
|
||||
use APP\core\Request;
|
||||
use APP\facades\Repo;
|
||||
use APP\handler\Handler;
|
||||
use APP\template\TemplateManager;
|
||||
use PKP\controllers\wizard\fileUpload\form\SubmissionFilesMetadataForm;
|
||||
use PKP\controllers\wizard\fileUpload\form\SubmissionFilesUploadForm;
|
||||
use PKP\core\JSONMessage;
|
||||
use PKP\db\DAORegistry;
|
||||
use PKP\security\authorization\internal\RepresentationUploadAccessPolicy;
|
||||
use PKP\security\authorization\internal\ReviewRoundRequiredPolicy;
|
||||
use PKP\security\authorization\internal\SubmissionFileStageAccessPolicy;
|
||||
use PKP\security\authorization\NoteAccessPolicy;
|
||||
use PKP\security\authorization\QueryAccessPolicy;
|
||||
use PKP\security\authorization\ReviewAssignmentFileWritePolicy;
|
||||
use PKP\security\authorization\ReviewStageAccessPolicy;
|
||||
use PKP\security\authorization\SubmissionFileAccessPolicy;
|
||||
use PKP\security\authorization\WorkflowStageAccessPolicy;
|
||||
use PKP\security\Role;
|
||||
use PKP\security\Validation;
|
||||
use PKP\submission\GenreDAO;
|
||||
use PKP\submissionFile\SubmissionFile;
|
||||
|
||||
class FileUploadWizardHandler extends Handler
|
||||
{
|
||||
/** @var int */
|
||||
public $_fileStage;
|
||||
|
||||
/** @var array */
|
||||
public $_uploaderRoles;
|
||||
|
||||
/** @var bool */
|
||||
public $_revisionOnly;
|
||||
|
||||
/** @var int */
|
||||
public $_reviewRound;
|
||||
|
||||
/** @var int */
|
||||
public $_revisedFileId;
|
||||
|
||||
/** @var int */
|
||||
public $_assocType;
|
||||
|
||||
/** @var int */
|
||||
public $_assocId;
|
||||
|
||||
/** @var int */
|
||||
public $_queryId;
|
||||
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct();
|
||||
$this->addRoleAssignment(
|
||||
[Role::ROLE_ID_MANAGER, Role::ROLE_ID_SITE_ADMIN, Role::ROLE_ID_SUB_EDITOR, Role::ROLE_ID_AUTHOR, Role::ROLE_ID_REVIEWER, Role::ROLE_ID_ASSISTANT],
|
||||
[
|
||||
'startWizard', 'displayFileUploadForm',
|
||||
'uploadFile',
|
||||
'editMetadata',
|
||||
'finishFileSubmission'
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// Implement template methods from PKPHandler
|
||||
//
|
||||
public function authorize($request, &$args, $roleAssignments)
|
||||
{
|
||||
// We validate file stage outside a policy because
|
||||
// we don't need to validate in another places.
|
||||
$fileStage = (int) $request->getUserVar('fileStage');
|
||||
if ($fileStage) {
|
||||
$fileStages = Repo::submissionFile()->getFileStages();
|
||||
if (!in_array($fileStage, $fileStages)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Validate file ids. We have two cases where we might have a file id.
|
||||
// CASE 1: user is uploading a revision to a file, the revised file id
|
||||
// will need validation.
|
||||
$revisedFileId = (int)$request->getUserVar('revisedFileId');
|
||||
// CASE 2: user already have uploaded a file (and it's editing the metadata),
|
||||
// we will need to validate the uploaded file id.
|
||||
$submissionFileId = (int)$request->getUserVar('submissionFileId');
|
||||
// Get the right one to validate.
|
||||
$submissionFileIdToValidate = null;
|
||||
if ($revisedFileId && !$submissionFileId) {
|
||||
$submissionFileIdToValidate = $revisedFileId;
|
||||
} elseif ($submissionFileId && !$revisedFileId) {
|
||||
$submissionFileIdToValidate = $submissionFileId;
|
||||
} elseif ($revisedFileId && $submissionFileId) {
|
||||
// Those two cases will not happen at the same time.
|
||||
return false;
|
||||
}
|
||||
|
||||
// Allow access to modify a specific file
|
||||
if ($submissionFileIdToValidate) {
|
||||
$this->addPolicy(new SubmissionFileAccessPolicy($request, $args, $roleAssignments, SubmissionFileAccessPolicy::SUBMISSION_FILE_ACCESS_MODIFY, $submissionFileIdToValidate));
|
||||
|
||||
// Allow uploading to review attachments
|
||||
} elseif ($fileStage === SubmissionFile::SUBMISSION_FILE_REVIEW_ATTACHMENT) {
|
||||
$assocType = (int) $request->getUserVar('assocType');
|
||||
$assocId = (int) $request->getUserVar('assocId');
|
||||
$stageId = (int) $request->getUserVar('stageId');
|
||||
if (empty($assocType) || $assocType !== Application::ASSOC_TYPE_REVIEW_ASSIGNMENT || empty($assocId)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$stageId = (int) $request->getUserVar('stageId');
|
||||
$this->addPolicy(new ReviewStageAccessPolicy($request, $args, $roleAssignments, 'submissionId', $stageId));
|
||||
$this->addPolicy(new ReviewRoundRequiredPolicy($request, $args));
|
||||
$this->addPolicy(new ReviewAssignmentFileWritePolicy($request, $assocId));
|
||||
|
||||
// Allow uploading to a note
|
||||
} elseif ($fileStage === SubmissionFile::SUBMISSION_FILE_QUERY) {
|
||||
$assocType = (int) $request->getUserVar('assocType');
|
||||
$assocId = (int) $request->getUserVar('assocId');
|
||||
$stageId = (int) $request->getUserVar('stageId');
|
||||
if (empty($assocType) || $assocType !== Application::ASSOC_TYPE_NOTE || empty($assocId)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$this->addPolicy(new QueryAccessPolicy($request, $args, $roleAssignments, $stageId));
|
||||
$this->addPolicy(new NoteAccessPolicy($request, $assocId, NoteAccessPolicy::NOTE_ACCESS_WRITE));
|
||||
|
||||
// Allow uploading a dependent file to another file
|
||||
} elseif ($fileStage === SubmissionFile::SUBMISSION_FILE_DEPENDENT) {
|
||||
$assocType = (int) $request->getUserVar('assocType');
|
||||
$assocId = (int) $request->getUserVar('assocId');
|
||||
if (empty($assocType) || $assocType !== Application::ASSOC_TYPE_SUBMISSION_FILE || empty($assocId)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$this->addPolicy(new SubmissionFileAccessPolicy($request, $args, $roleAssignments, SubmissionFileAccessPolicy::SUBMISSION_FILE_ACCESS_MODIFY, $assocId));
|
||||
|
||||
// Allow uploading to other file stages in the workflow
|
||||
} else {
|
||||
$stageId = (int) $request->getUserVar('stageId');
|
||||
$assocType = (int) $request->getUserVar('assocType');
|
||||
$assocId = (int) $request->getUserVar('assocId');
|
||||
$this->addPolicy(new WorkflowStageAccessPolicy($request, $args, $roleAssignments, 'submissionId', $stageId));
|
||||
$this->addPolicy(new SubmissionFileStageAccessPolicy($fileStage, SubmissionFileAccessPolicy::SUBMISSION_FILE_ACCESS_MODIFY, 'api.submissionFiles.403.unauthorizedFileStageIdWrite'));
|
||||
|
||||
// Additional checks before uploading to a review file stage
|
||||
if (in_array($fileStage, [
|
||||
SubmissionFile::SUBMISSION_FILE_REVIEW_REVISION,
|
||||
SubmissionFile::SUBMISSION_FILE_REVIEW_FILE,
|
||||
SubmissionFile::SUBMISSION_FILE_INTERNAL_REVIEW_REVISION,
|
||||
SubmissionFile::SUBMISSION_FILE_INTERNAL_REVIEW_FILE,
|
||||
SubmissionFile::SUBMISSION_FILE_ATTACHMENT
|
||||
]) || $assocType === Application::ASSOC_TYPE_REVIEW_ROUND) {
|
||||
$this->addPolicy(new ReviewRoundRequiredPolicy($request, $args));
|
||||
}
|
||||
|
||||
// Additional checks before uploading to a representation
|
||||
if ($fileStage === SubmissionFile::SUBMISSION_FILE_PROOF || $assocType === Application::ASSOC_TYPE_REPRESENTATION) {
|
||||
if (empty($assocType) || $assocType !== Application::ASSOC_TYPE_REPRESENTATION || empty($assocId)) {
|
||||
return false;
|
||||
}
|
||||
$this->addPolicy(new RepresentationUploadAccessPolicy($request, $args, $assocId));
|
||||
}
|
||||
}
|
||||
|
||||
return parent::authorize($request, $args, $roleAssignments);
|
||||
}
|
||||
|
||||
/**
|
||||
* @copydoc PKPHandler::initialize()
|
||||
*/
|
||||
public function initialize($request)
|
||||
{
|
||||
parent::initialize($request);
|
||||
// Configure the wizard with the authorized submission and file stage.
|
||||
// Validated in authorize.
|
||||
$this->_fileStage = (int)$request->getUserVar('fileStage');
|
||||
|
||||
// Set the uploader roles (if given).
|
||||
$uploaderRoles = $request->getUserVar('uploaderRoles');
|
||||
if (!empty($uploaderRoles)) {
|
||||
$this->_uploaderRoles = [];
|
||||
$uploaderRoles = explode('-', $uploaderRoles);
|
||||
foreach ($uploaderRoles as $uploaderRole) {
|
||||
if (!is_numeric($uploaderRole)) {
|
||||
fatalError('Invalid uploader role!');
|
||||
}
|
||||
$this->_uploaderRoles[] = (int)$uploaderRole;
|
||||
}
|
||||
}
|
||||
|
||||
// Do we allow revisions only?
|
||||
$this->_revisionOnly = (bool)$request->getUserVar('revisionOnly');
|
||||
$reviewRound = $this->getReviewRound();
|
||||
$this->_assocType = $request->getUserVar('assocType') ? (int)$request->getUserVar('assocType') : null;
|
||||
$this->_assocId = $request->getUserVar('assocId') ? (int)$request->getUserVar('assocId') : null;
|
||||
$this->_queryId = $request->getUserVar('queryId') ? (int) $request->getUserVar('queryId') : null;
|
||||
|
||||
// The revised file will be non-null if we revise a single existing file.
|
||||
if ($this->getRevisionOnly() && $request->getUserVar('revisedFileId')) {
|
||||
// Validated in authorize.
|
||||
$this->_revisedFileId = (int)$request->getUserVar('revisedFileId');
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// Getters and Setters
|
||||
//
|
||||
/**
|
||||
* The submission to which we upload files.
|
||||
*
|
||||
* @return Submission
|
||||
*/
|
||||
public function getSubmission()
|
||||
{
|
||||
return $this->getAuthorizedContextObject(Application::ASSOC_TYPE_SUBMISSION);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get the authorized workflow stage.
|
||||
*
|
||||
* @return int One of the WORKFLOW_STAGE_ID_* constants.
|
||||
*/
|
||||
public function getStageId()
|
||||
{
|
||||
return $this->getAuthorizedContextObject(Application::ASSOC_TYPE_WORKFLOW_STAGE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the workflow stage file storage that
|
||||
* we upload files to. One of the SubmissionFile::SUBMISSION_FILE_*
|
||||
* constants.
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function getFileStage()
|
||||
{
|
||||
return $this->_fileStage;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the uploader roles.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getUploaderRoles()
|
||||
{
|
||||
return $this->_uploaderRoles;
|
||||
}
|
||||
|
||||
/**
|
||||
* Does this uploader only allow revisions and no new files?
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function getRevisionOnly()
|
||||
{
|
||||
return $this->_revisionOnly;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get review round object.
|
||||
*
|
||||
* @return ReviewRound
|
||||
*/
|
||||
public function getReviewRound()
|
||||
{
|
||||
return $this->getAuthorizedContextObject(Application::ASSOC_TYPE_REVIEW_ROUND);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the id of the file to be revised (if any).
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function getRevisedFileId()
|
||||
{
|
||||
return $this->_revisedFileId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the assoc type (if any)
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function getAssocType()
|
||||
{
|
||||
return $this->_assocType;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the assoc id (if any)
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function getAssocId()
|
||||
{
|
||||
return $this->_assocId;
|
||||
}
|
||||
|
||||
//
|
||||
// Public handler methods
|
||||
//
|
||||
/**
|
||||
* Displays the file upload wizard.
|
||||
*
|
||||
* @param array $args
|
||||
* @param Request $request
|
||||
*
|
||||
* @return JSONMessage JSON object
|
||||
*/
|
||||
public function startWizard($args, $request)
|
||||
{
|
||||
$templateMgr = TemplateManager::getManager($request);
|
||||
$reviewRound = $this->getReviewRound();
|
||||
$templateMgr->assign([
|
||||
'submissionId' => $this->getSubmission()->getId(),
|
||||
'stageId' => $this->getStageId(),
|
||||
'uploaderRoles' => implode('-', (array) $this->getUploaderRoles()),
|
||||
'fileStage' => $this->getFileStage(),
|
||||
'isReviewer' => $request->getUserVar('isReviewer'),
|
||||
'revisionOnly' => $this->getRevisionOnly(),
|
||||
'reviewRoundId' => is_a($reviewRound, 'ReviewRound') ? $reviewRound->getId() : null,
|
||||
'revisedFileId' => $this->getRevisedFileId(),
|
||||
'assocType' => $this->getAssocType(),
|
||||
'assocId' => $this->getAssocId(),
|
||||
'dependentFilesOnly' => $request->getUserVar('dependentFilesOnly'),
|
||||
'queryId' => $this->_queryId,
|
||||
]);
|
||||
return $templateMgr->fetchJson('controllers/wizard/fileUpload/fileUploadWizard.tpl');
|
||||
}
|
||||
|
||||
/**
|
||||
* Render the file upload form in its initial state.
|
||||
*
|
||||
* @param array $args
|
||||
* @param Request $request
|
||||
*
|
||||
* @return JSONMessage JSON object
|
||||
*/
|
||||
public function displayFileUploadForm($args, $request)
|
||||
{
|
||||
// Instantiate, configure and initialize the form.
|
||||
$submission = $this->getSubmission();
|
||||
$fileForm = new SubmissionFilesUploadForm(
|
||||
$request,
|
||||
$submission->getId(),
|
||||
$this->getStageId(),
|
||||
$this->getUploaderRoles(),
|
||||
$this->getFileStage(),
|
||||
$this->getRevisionOnly(),
|
||||
$this->getReviewRound(),
|
||||
$this->getRevisedFileId(),
|
||||
$this->getAssocType(),
|
||||
$this->getAssocId(),
|
||||
$this->_queryId
|
||||
);
|
||||
$fileForm->initData();
|
||||
|
||||
// Render the form.
|
||||
return new JSONMessage(true, $fileForm->fetch($request));
|
||||
}
|
||||
|
||||
/**
|
||||
* Upload a file and render the modified upload wizard.
|
||||
*
|
||||
* @param array $args
|
||||
* @param Request $request
|
||||
*
|
||||
* @return JSONMessage JSON object
|
||||
*/
|
||||
public function uploadFile($args, $request)
|
||||
{
|
||||
// Instantiate the file upload form.
|
||||
$submission = $this->getSubmission();
|
||||
$uploadForm = new SubmissionFilesUploadForm(
|
||||
$request,
|
||||
$submission->getId(),
|
||||
$this->getStageId(),
|
||||
null,
|
||||
$this->getFileStage(),
|
||||
$this->getRevisionOnly(),
|
||||
$this->getReviewRound(),
|
||||
null,
|
||||
$this->getAssocType(),
|
||||
$this->getAssocId(),
|
||||
$this->_queryId
|
||||
);
|
||||
$uploadForm->readInputData();
|
||||
|
||||
// Validate the form and upload the file.
|
||||
if (!$uploadForm->validate()) {
|
||||
return new JSONMessage(false, $uploadForm->fetch($request));
|
||||
}
|
||||
|
||||
$submissionFileId = $uploadForm->getRevisedFileId();
|
||||
// Store the data of the submission file before it's replaced by the revised file
|
||||
if ($submissionFileId) {
|
||||
$originalFile = Repo::submissionFile()->get($submissionFileId);
|
||||
}
|
||||
|
||||
$uploadedFile = $uploadForm->execute(); /** @var SubmissionFile $uploadedFile */
|
||||
if (!is_a($uploadedFile, 'SubmissionFile')) {
|
||||
return new JSONMessage(false, __('common.uploadFailed'));
|
||||
}
|
||||
|
||||
// Retrieve file info to be used in a JSON response.
|
||||
$uploadedFileInfo = $this->_getUploadedFileInfo($uploadedFile, $originalFile ?? null);
|
||||
$reviewRound = $this->getReviewRound();
|
||||
|
||||
// Advance to the next step (i.e. meta-data editing).
|
||||
return new JSONMessage(true, '', '0', $uploadedFileInfo);
|
||||
}
|
||||
|
||||
/**
|
||||
* Edit the metadata of the latest revision of
|
||||
* the requested submission file.
|
||||
*
|
||||
* @param array $args
|
||||
* @param Request $request
|
||||
*
|
||||
* @return JSONMessage JSON object
|
||||
*/
|
||||
public function editMetadata($args, $request)
|
||||
{
|
||||
$templateMgr = TemplateManager::getManager($request);
|
||||
$templateMgr->assign([
|
||||
'primaryLocale' => $this->getSubmission()->getLocale(),
|
||||
]);
|
||||
|
||||
$submissionFile = $this->getAuthorizedContextObject(Application::ASSOC_TYPE_SUBMISSION_FILE);
|
||||
$form = new SubmissionFilesMetadataForm($submissionFile, $this->getStageId(), $this->getReviewRound());
|
||||
$form->initData();
|
||||
|
||||
/** @var GenreDAO $genreDao */
|
||||
$genreDao = DAORegistry::getDAO('GenreDAO');
|
||||
$fileGenres = $genreDao->getByContextId($request->getContext()->getId())->toArray();
|
||||
|
||||
$fileData = Repo::submissionFile()
|
||||
->getSchemaMap()
|
||||
->map($submissionFile, $fileGenres);
|
||||
|
||||
$json = new JSONMessage(true, $form->fetch($request));
|
||||
$json->setGlobalEvent('submissionFile:added', $fileData);
|
||||
|
||||
return $json;
|
||||
}
|
||||
|
||||
/**
|
||||
* Display the final tab of the modal
|
||||
*
|
||||
* @param array $args
|
||||
* @param Request $request
|
||||
*
|
||||
* @return JSONMessage JSON object
|
||||
*/
|
||||
public function finishFileSubmission($args, $request)
|
||||
{
|
||||
$submission = $this->getSubmission();
|
||||
|
||||
// Validation not req'd -- just generating a JSON update message.
|
||||
$fileId = (int)$request->getUserVar('fileId');
|
||||
/** @var SubmissionFile $file */
|
||||
$submissionFile = $this->getAuthorizedContextObject(Application::ASSOC_TYPE_SUBMISSION_FILE);
|
||||
|
||||
$templateMgr = TemplateManager::getManager($request);
|
||||
$templateMgr->assign('submissionId', $submission->getId());
|
||||
$templateMgr->assign('fileId', $submissionFile->getId());
|
||||
if (isset($args['fileStage'])) {
|
||||
$templateMgr->assign('fileStage', $submissionFile->getData('fileStage'));
|
||||
}
|
||||
|
||||
/** @var GenreDAO $genreDao */
|
||||
$genreDao = DAORegistry::getDAO('GenreDAO');
|
||||
$fileGenres = $genreDao->getByContextId($request->getContext()->getId())->toArray();
|
||||
|
||||
$fileData = Repo::submissionFile()
|
||||
->getSchemaMap()
|
||||
->map($submissionFile, $fileGenres);
|
||||
|
||||
$json = $templateMgr->fetchJson('controllers/wizard/fileUpload/form/fileSubmissionComplete.tpl');
|
||||
$json->setGlobalEvent('submissionFile:edited', $fileData);
|
||||
return $json;
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// Private helper methods
|
||||
//
|
||||
|
||||
/**
|
||||
* Helper function: check if the only difference between $a and $b
|
||||
* is numeric. Used to exclude well-named but nearly identical file
|
||||
* names from the revision detection pile (e.g. "Chapter 1" and
|
||||
* "Chapter 2")
|
||||
*
|
||||
* @param string $a
|
||||
* @param string $b
|
||||
*/
|
||||
public function _onlyNumbersDiffer($a, $b)
|
||||
{
|
||||
if ($a == $b) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$pattern = '/([^0-9]*)([0-9]*)([^0-9]*)/';
|
||||
$aMatchCount = preg_match_all($pattern, $a, $aMatches, PREG_SET_ORDER);
|
||||
$bMatchCount = preg_match_all($pattern, $b, $bMatches, PREG_SET_ORDER);
|
||||
if ($aMatchCount != $bMatchCount || $aMatchCount == 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check each match. If the 1st and 3rd (text) parts all match
|
||||
// then only numbers differ in the two supplied strings.
|
||||
for ($i = 0; $i < count($aMatches); $i++) {
|
||||
if ($aMatches[$i][1] != $bMatches[$i][1]) {
|
||||
return false;
|
||||
}
|
||||
if ($aMatches[$i][3] != $bMatches[$i][3]) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// No counterexamples were found. Only numbers differ.
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an array that describes an uploaded file which can
|
||||
* be used in a JSON response.
|
||||
*
|
||||
* @param SubmissionFile $uploadedFile
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function _getUploadedFileInfo(SubmissionFile $uploadedFile, ?SubmissionFile $originalFile = null)
|
||||
{
|
||||
$uploadedFile = [
|
||||
'uploadedFile' => [
|
||||
'id' => $uploadedFile->getId(),
|
||||
'fileId' => $uploadedFile->getData('fileId'),
|
||||
'name' => $uploadedFile->getLocalizedData('name'),
|
||||
'genreId' => $uploadedFile->getGenreId(),
|
||||
]
|
||||
];
|
||||
|
||||
if ($originalFile) {
|
||||
$uploadedFile['uploadedFile']['originalFile'] = [
|
||||
'fileId' => $originalFile->getData('fileId'),
|
||||
'name' => $originalFile->getData('name'),
|
||||
'uploaderUserId' => $originalFile->getData('uploaderUserId'),
|
||||
];
|
||||
}
|
||||
|
||||
return $uploadedFile;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,377 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @file controllers/wizard/fileUpload/form/PKPSubmissionFilesUploadBaseForm.php
|
||||
*
|
||||
* Copyright (c) 2014-2021 Simon Fraser University
|
||||
* Copyright (c) 2003-2021 John Willinsky
|
||||
* Distributed under the GNU GPL v3. For full terms see the file docs/COPYING.
|
||||
*
|
||||
* @class PKPSubmissionFilesUploadBaseForm
|
||||
*
|
||||
* @ingroup controllers_wizard_fileUpload_form
|
||||
*
|
||||
* @brief Form for adding/editing a submission file
|
||||
*/
|
||||
|
||||
namespace PKP\controllers\wizard\fileUpload\form;
|
||||
|
||||
use APP\core\Application;
|
||||
use APP\core\Request;
|
||||
use APP\facades\Repo;
|
||||
use APP\template\TemplateManager;
|
||||
use Exception;
|
||||
use PKP\db\DAORegistry;
|
||||
use PKP\form\Form;
|
||||
use PKP\linkAction\LinkAction;
|
||||
use PKP\linkAction\request\ConfirmationModal;
|
||||
use PKP\security\Role;
|
||||
use PKP\stageAssignment\StageAssignmentDAO;
|
||||
use PKP\submission\reviewAssignment\ReviewAssignmentDAO;
|
||||
use PKP\submission\reviewRound\ReviewRound;
|
||||
use PKP\submission\reviewRound\ReviewRoundDAO;
|
||||
use PKP\submissionFile\SubmissionFile;
|
||||
use PKP\user\User;
|
||||
|
||||
class PKPSubmissionFilesUploadBaseForm extends Form
|
||||
{
|
||||
/** @var int */
|
||||
public $_stageId;
|
||||
|
||||
/** @var ReviewRound */
|
||||
public $_reviewRound;
|
||||
|
||||
/** @var array the submission files for this submission and file stage */
|
||||
public $_submissionFiles;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param Request $request
|
||||
* @param string $template
|
||||
* @param int $submissionId
|
||||
* @param int $stageId One of the WORKFLOW_STAGE_ID_* constants.
|
||||
* @param int $fileStage
|
||||
* @param bool $revisionOnly
|
||||
* @param ReviewRound $reviewRound
|
||||
* @param int $revisedFileId
|
||||
* @param int $assocType
|
||||
* @param int $assocId
|
||||
* @param int $queryId
|
||||
*/
|
||||
public function __construct(
|
||||
$request,
|
||||
$template,
|
||||
$submissionId,
|
||||
$stageId,
|
||||
$fileStage,
|
||||
$revisionOnly = false,
|
||||
$reviewRound = null,
|
||||
$revisedFileId = null,
|
||||
$assocType = null,
|
||||
$assocId = null,
|
||||
$queryId = null
|
||||
) {
|
||||
// Check the incoming parameters.
|
||||
if (!is_numeric($submissionId) || $submissionId <= 0 ||
|
||||
!is_numeric($fileStage) || $fileStage <= 0 ||
|
||||
!is_numeric($stageId) || $stageId < 1 || $stageId > 5 ||
|
||||
isset($assocType) !== isset($assocId)) {
|
||||
fatalError('Invalid parameters!');
|
||||
}
|
||||
|
||||
// Initialize class.
|
||||
parent::__construct($template);
|
||||
$this->_stageId = $stageId;
|
||||
|
||||
if ($reviewRound) {
|
||||
$this->_reviewRound = & $reviewRound;
|
||||
} elseif ($assocType == Application::ASSOC_TYPE_REVIEW_ASSIGNMENT && !$reviewRound) {
|
||||
// Get the review assignment object.
|
||||
/** @var ReviewAssignmentDAO */
|
||||
$reviewAssignmentDao = DAORegistry::getDAO('ReviewAssignmentDAO');
|
||||
/** @var \PKP\submission\reviewAssignment\ReviewAssignment */
|
||||
$reviewAssignment = $reviewAssignmentDao->getById((int) $assocId);
|
||||
if ($reviewAssignment->getDateCompleted()) {
|
||||
fatalError('Review already completed!');
|
||||
}
|
||||
|
||||
// Get the review round object.
|
||||
/** @var ReviewRoundDAO */
|
||||
$reviewRoundDao = DAORegistry::getDAO('ReviewRoundDAO');
|
||||
$this->_reviewRound = $reviewRoundDao->getById($reviewAssignment->getReviewRoundId());
|
||||
} elseif (!$assocType && !$reviewRound) {
|
||||
$reviewRound = null;
|
||||
}
|
||||
|
||||
$this->setData('fileStage', (int)$fileStage);
|
||||
$this->setData('submissionId', (int)$submissionId);
|
||||
$this->setData('revisionOnly', (bool)$revisionOnly);
|
||||
$this->setData('revisedFileId', $revisedFileId ? (int)$revisedFileId : null);
|
||||
$this->setData('reviewRoundId', $reviewRound ? $reviewRound->getId() : null);
|
||||
$this->setData('assocType', $assocType ? (int)$assocType : null);
|
||||
$this->setData('assocId', $assocId ? (int)$assocId : null);
|
||||
$this->setData('queryId', $queryId ? (int) $queryId : null);
|
||||
|
||||
// Add validators.
|
||||
$this->addCheck(new \PKP\form\validation\FormValidatorPost($this));
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// Setters and Getters
|
||||
//
|
||||
/**
|
||||
* Get the workflow stage id.
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function getStageId()
|
||||
{
|
||||
return $this->_stageId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the review round object (if any).
|
||||
*
|
||||
* @return ReviewRound
|
||||
*/
|
||||
public function getReviewRound()
|
||||
{
|
||||
return $this->_reviewRound;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the revised file id (if any).
|
||||
*
|
||||
* @return int the revised file id
|
||||
*/
|
||||
public function getRevisedFileId()
|
||||
{
|
||||
return $this->getData('revisedFileId') ? (int)$this->getData('revisedFileId') : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the associated type
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function getAssocType()
|
||||
{
|
||||
return $this->getData('assocType');
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the associated id.
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function getAssocId()
|
||||
{
|
||||
return $this->getData('assocId');
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the submission files belonging to the
|
||||
* submission and to the file stage.
|
||||
*
|
||||
* @return array a list of SubmissionFile instances.
|
||||
*/
|
||||
public function getSubmissionFiles()
|
||||
{
|
||||
if (is_null($this->_submissionFiles)) {
|
||||
if ($this->getStageId() == WORKFLOW_STAGE_ID_INTERNAL_REVIEW || $this->getStageId() == WORKFLOW_STAGE_ID_EXTERNAL_REVIEW) {
|
||||
// If we have a review stage id then we also expect a review round.
|
||||
if (!$this->getData('fileStage') == SubmissionFile::SUBMISSION_FILE_QUERY && !is_a($this->getReviewRound(), 'ReviewRound')) {
|
||||
throw new Exception('Can not request submission files for a review stage without specifying a review round.');
|
||||
}
|
||||
// Can only upload submission files, review files, review attachments, dependent files, or query attachments.
|
||||
if (!in_array($this->getData('fileStage'), [
|
||||
SubmissionFile::SUBMISSION_FILE_SUBMISSION,
|
||||
SubmissionFile::SUBMISSION_FILE_REVIEW_FILE,
|
||||
SubmissionFile::SUBMISSION_FILE_INTERNAL_REVIEW_FILE,
|
||||
SubmissionFile::SUBMISSION_FILE_REVIEW_ATTACHMENT,
|
||||
SubmissionFile::SUBMISSION_FILE_REVIEW_REVISION,
|
||||
SubmissionFile::SUBMISSION_FILE_INTERNAL_REVIEW_REVISION,
|
||||
SubmissionFile::SUBMISSION_FILE_QUERY,
|
||||
SubmissionFile::SUBMISSION_FILE_DEPENDENT,
|
||||
SubmissionFile::SUBMISSION_FILE_ATTACHMENT,
|
||||
])) {
|
||||
throw new Exception('The file stage is not valid for the review stage.');
|
||||
}
|
||||
|
||||
// Hide the revision selector for review
|
||||
// attachments to make it easier for reviewers
|
||||
$reviewRound = $this->getReviewRound();
|
||||
if ($this->getData('fileStage') == SubmissionFile::SUBMISSION_FILE_REVIEW_ATTACHMENT) {
|
||||
$this->_submissionFiles = [];
|
||||
} elseif ($reviewRound) {
|
||||
// Retrieve the submission files for the given review round.
|
||||
$submissionId = (int) $this->getData('submissionId');
|
||||
$submission = Repo::submission()->get($submissionId);
|
||||
if ($submission->getData('contextId') !== Application::get()->getRequest()->getContext()->getId()) {
|
||||
throw new Exception('Can not request submission files from another context.');
|
||||
}
|
||||
|
||||
$this->_submissionFiles = Repo::submissionFile()
|
||||
->getCollector()
|
||||
->filterByReviewRoundIds([(int) $reviewRound->getId()])
|
||||
->filterBySubmissionIds([$submissionId])
|
||||
->getMany()
|
||||
->toArray();
|
||||
} else {
|
||||
// No review round, e.g. for dependent or query files
|
||||
$this->_submissionFiles = [];
|
||||
}
|
||||
} else {
|
||||
$collector = Repo::submissionFile()
|
||||
->getCollector()
|
||||
->filterByFileStages([(int) $this->getData('fileStage')])
|
||||
->filterBySubmissionIds([(int) $this->getData('submissionId')]);
|
||||
if ($this->getAssocType() && $this->getAssocType() != Application::ASSOC_TYPE_SUBMISSION) {
|
||||
$collector = $collector->filterByAssoc(
|
||||
$this->getAssocType(),
|
||||
[$this->getAssocId()]
|
||||
);
|
||||
}
|
||||
|
||||
$this->_submissionFiles = $collector->getMany()->toArray();
|
||||
}
|
||||
}
|
||||
|
||||
return $this->_submissionFiles;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the submission files possible to select/consider for revision by the given user.
|
||||
*
|
||||
* @param User $user
|
||||
* @param SubmissionFile $uploadedFile uploaded file
|
||||
*
|
||||
* @return array a list of SubmissionFile instances.
|
||||
*/
|
||||
public function getRevisionSubmissionFilesSelection($user, $uploadedFile = null)
|
||||
{
|
||||
$stageAssignmentDao = DAORegistry::getDAO('StageAssignmentDAO'); /** @var StageAssignmentDAO $stageAssignmentDao */
|
||||
$allSubmissionFiles = $this->getSubmissionFiles();
|
||||
$submissionFiles = [];
|
||||
foreach ($allSubmissionFiles as $submissionFile) {
|
||||
// The uploaded file must be excluded from the list of revisable files.
|
||||
if ($uploadedFile && $uploadedFile->getId() == $submissionFile->getId()) {
|
||||
continue;
|
||||
}
|
||||
if (
|
||||
($submissionFile->getFileStage() == SubmissionFile::SUBMISSION_FILE_REVIEW_ATTACHMENT || $submissionFile->getFileStage() == SubmissionFile::SUBMISSION_FILE_REVIEW_FILE) &&
|
||||
$stageAssignmentDao->getBySubmissionAndRoleIds($submissionFile->getData('submissionId'), [Role::ROLE_ID_AUTHOR], $this->getStageId(), $user->getId())
|
||||
) {
|
||||
// Authors are not permitted to revise reviewer documents.
|
||||
continue;
|
||||
}
|
||||
$submissionFiles[] = $submissionFile;
|
||||
}
|
||||
return $submissionFiles;
|
||||
}
|
||||
|
||||
//
|
||||
// Implement template methods from Form
|
||||
//
|
||||
/**
|
||||
* @copydoc Form::readInputData()
|
||||
*/
|
||||
public function readInputData()
|
||||
{
|
||||
// Only Genre and revised file can be set in the form. All other
|
||||
// information is generated on our side.
|
||||
$this->readUserVars(['revisedFileId']);
|
||||
}
|
||||
|
||||
/**
|
||||
* @copydoc Form::fetch()
|
||||
*
|
||||
* @param null|mixed $template
|
||||
*/
|
||||
public function fetch($request, $template = null, $display = false)
|
||||
{
|
||||
// Set the workflow stage.
|
||||
$this->setData('stageId', $this->getStageId());
|
||||
|
||||
// Set the review round id, if any.
|
||||
$reviewRound = $this->getReviewRound();
|
||||
if (is_a($reviewRound, 'ReviewRound')) {
|
||||
$this->setData('reviewRoundId', $reviewRound->getId());
|
||||
}
|
||||
|
||||
// Retrieve the uploaded file (if any).
|
||||
$uploadedFile = $this->getData('uploadedFile');
|
||||
|
||||
$user = $request->getUser();
|
||||
|
||||
// Initialize the list with files available for review.
|
||||
$submissionFileOptions = [];
|
||||
$currentSubmissionFileGenres = [];
|
||||
|
||||
// Go through all files and build a list of files available for review.
|
||||
$revisedFileId = $this->getRevisedFileId();
|
||||
$foundRevisedFile = false;
|
||||
$submissionFiles = $this->getRevisionSubmissionFilesSelection($user, $uploadedFile);
|
||||
|
||||
foreach ((array) $submissionFiles as $submissionFile) {
|
||||
// Is this the revised file?
|
||||
if ($revisedFileId && $revisedFileId == $submissionFile->getId()) {
|
||||
// This is the revised submission file, so pass its data on to the form.
|
||||
$this->setData('genreId', $submissionFile->getGenreId());
|
||||
$foundRevisedFile = true;
|
||||
}
|
||||
|
||||
// Create an entry in the list of existing files which
|
||||
// the user can select from in case he chooses to upload
|
||||
// a revision.
|
||||
$fileName = $submissionFile->getLocalizedData('name') != '' ? $submissionFile->getLocalizedData('name') : __('common.untitled');
|
||||
|
||||
$submissionFileOptions[$submissionFile->getId()] = $fileName;
|
||||
$currentSubmissionFileGenres[$submissionFile->getId()] = $submissionFile->getGenreId();
|
||||
|
||||
$lastSubmissionFile = $submissionFile;
|
||||
}
|
||||
|
||||
// If there is only one option for a file to review, and user must revise, do not show the selector.
|
||||
if (count($submissionFileOptions) == 1 && $this->getData('revisionOnly')) {
|
||||
// There was only one option, use the last added submission file
|
||||
$this->setData('revisedFileId', $lastSubmissionFile->getId());
|
||||
$this->setData('genreId', $lastSubmissionFile->getGenreId());
|
||||
}
|
||||
|
||||
// If this is not a "review only" form then add a default item.
|
||||
if (count($submissionFileOptions) && !$this->getData('revisionOnly')) {
|
||||
$submissionFileOptions = ['' => __('submission.upload.uploadNewFile')] + $submissionFileOptions;
|
||||
}
|
||||
|
||||
// Make sure that the revised file (if any) really was among
|
||||
// the retrieved submission files in the current file stage.
|
||||
if ($revisedFileId && !$foundRevisedFile) {
|
||||
fatalError('Invalid revised file id!');
|
||||
}
|
||||
|
||||
// Set the review file candidate data in the template.
|
||||
$this->setData('currentSubmissionFileGenres', $currentSubmissionFileGenres);
|
||||
$this->setData('submissionFileOptions', $submissionFileOptions);
|
||||
|
||||
// Show ensuring an anonymous review link.
|
||||
$context = $request->getContext();
|
||||
if ($context->getData('showEnsuringLink') && in_array($this->getStageId(), [WORKFLOW_STAGE_ID_SUBMISSION, WORKFLOW_STAGE_ID_INTERNAL_REVIEW, WORKFLOW_STAGE_ID_EXTERNAL_REVIEW])) {
|
||||
$ensuringLink = new LinkAction(
|
||||
'addUser',
|
||||
new ConfirmationModal(
|
||||
__('review.anonymousPeerReview'),
|
||||
__('review.anonymousPeerReview.title')
|
||||
),
|
||||
__('review.anonymousPeerReview.title')
|
||||
);
|
||||
|
||||
$templateMgr = TemplateManager::getManager($request);
|
||||
$templateMgr->assign('ensuringLink', $ensuringLink);
|
||||
}
|
||||
|
||||
return parent::fetch($request, $template, $display);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,206 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @file controllers/wizard/fileUpload/form/SubmissionFilesMetadataForm.php
|
||||
*
|
||||
* Copyright (c) 2014-2021 Simon Fraser University
|
||||
* Copyright (c) 2003-2021 John Willinsky
|
||||
* Distributed under the GNU GPL v3. For full terms see the file docs/COPYING.
|
||||
*
|
||||
* @class SubmissionFilesMetadataForm
|
||||
*
|
||||
* @ingroup controllers_wizard_fileUpload_form
|
||||
*
|
||||
* @brief Form for editing a submission file's metadata
|
||||
*/
|
||||
|
||||
namespace PKP\controllers\wizard\fileUpload\form;
|
||||
|
||||
use APP\facades\Repo;
|
||||
use APP\template\TemplateManager;
|
||||
use PKP\db\DAORegistry;
|
||||
use PKP\form\Form;
|
||||
use PKP\submission\GenreDAO;
|
||||
use PKP\submission\reviewRound\ReviewRound;
|
||||
use PKP\submissionFile\SubmissionFile;
|
||||
|
||||
class SubmissionFilesMetadataForm extends Form
|
||||
{
|
||||
/** @var SubmissionFile */
|
||||
public $_submissionFile;
|
||||
|
||||
/** @var int */
|
||||
public $_stageId;
|
||||
|
||||
/** @var ReviewRound */
|
||||
public $_reviewRound;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param SubmissionFile $submissionFile
|
||||
* @param int $stageId One of the WORKFLOW_STAGE_ID_* constants.
|
||||
* @param ReviewRound $reviewRound (optional) Current review round, if any.
|
||||
* @param string $template Path and filename to template file (optional).
|
||||
*/
|
||||
public function __construct($submissionFile, $stageId, $reviewRound = null, $template = null)
|
||||
{
|
||||
if ($template === null) {
|
||||
$template = 'controllers/wizard/fileUpload/form/submissionFileMetadataForm.tpl';
|
||||
}
|
||||
parent::__construct($template);
|
||||
|
||||
// Initialize the object.
|
||||
$this->_submissionFile = $submissionFile;
|
||||
$this->_stageId = $stageId;
|
||||
if (is_a($reviewRound, 'ReviewRound')) {
|
||||
$this->_reviewRound = $reviewRound;
|
||||
}
|
||||
|
||||
$submissionLocale = $submissionFile->getData('locale');
|
||||
$this->setDefaultFormLocale($submissionLocale);
|
||||
|
||||
// Add validation checks.
|
||||
$this->addCheck(new \PKP\form\validation\FormValidatorLocale($this, 'name', 'required', 'submission.submit.fileNameRequired', $submissionLocale));
|
||||
$this->addCheck(new \PKP\form\validation\FormValidatorPost($this));
|
||||
$this->addCheck(new \PKP\form\validation\FormValidatorCSRF($this));
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// Getters and Setters
|
||||
//
|
||||
/**
|
||||
* Get the submission file.
|
||||
*
|
||||
* @return SubmissionFile
|
||||
*/
|
||||
public function getSubmissionFile()
|
||||
{
|
||||
return $this->_submissionFile;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the workflow stage id.
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function getStageId()
|
||||
{
|
||||
return $this->_stageId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get review round.
|
||||
*
|
||||
* @return ReviewRound
|
||||
*/
|
||||
public function getReviewRound()
|
||||
{
|
||||
return $this->_reviewRound;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the "show buttons" flag
|
||||
*
|
||||
* @param bool $showButtons
|
||||
*/
|
||||
public function setShowButtons($showButtons)
|
||||
{
|
||||
$this->setData('showButtons', $showButtons);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the "show buttons" flag
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function getShowButtons()
|
||||
{
|
||||
return $this->getData('showButtons');
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// Implement template methods from Form
|
||||
//
|
||||
/**
|
||||
* @copydoc Form::getLocaleFieldNames()
|
||||
*/
|
||||
public function getLocaleFieldNames()
|
||||
{
|
||||
return ['name'];
|
||||
}
|
||||
|
||||
/**
|
||||
* @copydoc Form::readInputData()
|
||||
*/
|
||||
public function readInputData()
|
||||
{
|
||||
$this->readUserVars(['name', 'showButtons',
|
||||
'artworkCaption', 'artworkCredit', 'artworkCopyrightOwner',
|
||||
'artworkCopyrightOwnerContact', 'artworkPermissionTerms',
|
||||
'creator', 'subject', 'description', 'publisher', 'sponsor', 'source', 'language', 'dateCreated',
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @copydoc Form::fetch()
|
||||
*
|
||||
* @param null|mixed $template
|
||||
*/
|
||||
public function fetch($request, $template = null, $display = false)
|
||||
{
|
||||
$templateMgr = TemplateManager::getManager($request);
|
||||
$reviewRound = $this->getReviewRound();
|
||||
/** @var GenreDAO */
|
||||
$genreDao = DAORegistry::getDAO('GenreDAO');
|
||||
$genre = $genreDao->getById($this->getSubmissionFile()->getData('genreId'), $request->getContext()->getId());
|
||||
|
||||
$templateMgr->assign([
|
||||
'submissionFile' => $this->getSubmissionFile(),
|
||||
'stageId' => $this->getStageId(),
|
||||
'reviewRoundId' => $reviewRound ? $reviewRound->getId() : null,
|
||||
'supportsDependentFiles' => Repo::submissionFile()->supportsDependentFiles($this->getSubmissionFile()),
|
||||
'genre' => $genre,
|
||||
]);
|
||||
return parent::fetch($request, $template, $display);
|
||||
}
|
||||
|
||||
/**
|
||||
* @copydoc Form::execute()
|
||||
*/
|
||||
public function execute(...$functionParams)
|
||||
{
|
||||
$props = [
|
||||
'name' => $this->getData('name'),
|
||||
];
|
||||
|
||||
// Artwork metadata
|
||||
$props = array_merge($props, [
|
||||
'caption' => $this->getData('artworkCaption'),
|
||||
'credit' => $this->getData('artworkCredit'),
|
||||
'copyrightOwner' => $this->getData('artworkCopyrightOwner'),
|
||||
'terms' => $this->getData('artworkPermissionTerms'),
|
||||
]);
|
||||
|
||||
// Supplementary file metadata
|
||||
$props = array_merge($props, [
|
||||
'subject' => $this->getData('subject'),
|
||||
'creator' => $this->getData('creator'),
|
||||
'description' => $this->getData('description'),
|
||||
'publisher' => $this->getData('publisher'),
|
||||
'sponsor' => $this->getData('sponsor'),
|
||||
'source' => $this->getData('source'),
|
||||
'language' => $this->getData('language'),
|
||||
'dateCreated' => $this->getData('dateCreated'),
|
||||
]);
|
||||
|
||||
Repo::submissionFile()->edit($this->getSubmissionFile(), $props);
|
||||
$this->_submissionFile = Repo::submissionFile()->get(
|
||||
$this->getSubmissionFile()->getId()
|
||||
);
|
||||
|
||||
parent::execute(...$functionParams);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,273 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @file controllers/wizard/fileUpload/form/SubmissionFilesUploadForm.php
|
||||
*
|
||||
* Copyright (c) 2014-2021 Simon Fraser University
|
||||
* Copyright (c) 2003-2021 John Willinsky
|
||||
* Distributed under the GNU GPL v3. For full terms see the file docs/COPYING.
|
||||
*
|
||||
* @class SubmissionFilesUploadForm
|
||||
*
|
||||
* @ingroup controllers_wizard_fileUpload_form
|
||||
*
|
||||
* @brief Form for adding/editing a submission file
|
||||
*/
|
||||
|
||||
namespace PKP\controllers\wizard\fileUpload\form;
|
||||
|
||||
use APP\core\Application;
|
||||
use APP\core\Request;
|
||||
use APP\core\Services;
|
||||
use APP\facades\Repo;
|
||||
use APP\submission\Submission;
|
||||
use PKP\db\DAORegistry;
|
||||
use PKP\file\FileManager;
|
||||
use PKP\form\validation\FormValidator;
|
||||
use PKP\submission\GenreDAO;
|
||||
use PKP\submission\reviewRound\ReviewRound;
|
||||
use PKP\submissionFile\SubmissionFile;
|
||||
|
||||
class SubmissionFilesUploadForm extends PKPSubmissionFilesUploadBaseForm
|
||||
{
|
||||
/** @var array */
|
||||
public $_uploaderRoles;
|
||||
|
||||
/** @var Submission */
|
||||
protected $_submission;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param Request $request
|
||||
* @param int $submissionId
|
||||
* @param int $stageId One of the WORKFLOW_STAGE_ID_* constants.
|
||||
* @param array $uploaderRoles
|
||||
* @param int $fileStage
|
||||
* @param bool $revisionOnly
|
||||
* @param int $stageId
|
||||
* @param ReviewRound $reviewRound
|
||||
* @param int $revisedFileId
|
||||
* @param int $assocType
|
||||
* @param int $assocId
|
||||
* @param int $queryId
|
||||
*/
|
||||
public function __construct(
|
||||
$request,
|
||||
$submissionId,
|
||||
$stageId,
|
||||
$uploaderRoles,
|
||||
$fileStage,
|
||||
$revisionOnly = false,
|
||||
$reviewRound = null,
|
||||
$revisedFileId = null,
|
||||
$assocType = null,
|
||||
$assocId = null,
|
||||
$queryId = null
|
||||
) {
|
||||
// Initialize class.
|
||||
assert(is_null($uploaderRoles) || (is_array($uploaderRoles) && count($uploaderRoles) >= 1));
|
||||
$this->_uploaderRoles = $uploaderRoles;
|
||||
|
||||
parent::__construct(
|
||||
$request,
|
||||
'controllers/wizard/fileUpload/form/fileUploadForm.tpl',
|
||||
$submissionId,
|
||||
$stageId,
|
||||
$fileStage,
|
||||
$revisionOnly,
|
||||
$reviewRound,
|
||||
$revisedFileId,
|
||||
$assocType,
|
||||
$assocId,
|
||||
$queryId
|
||||
);
|
||||
|
||||
$this->_submission = Repo::submission()->get($submissionId);
|
||||
|
||||
// Disable the genre selector for review file attachments
|
||||
if ($fileStage == SubmissionFile::SUBMISSION_FILE_REVIEW_ATTACHMENT) {
|
||||
$this->setData('isReviewAttachment', true);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// Getters and Setters
|
||||
//
|
||||
/**
|
||||
* Get the uploader roles.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getUploaderRoles()
|
||||
{
|
||||
assert(!is_null($this->_uploaderRoles));
|
||||
return $this->_uploaderRoles;
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// Implement template methods from Form
|
||||
//
|
||||
/**
|
||||
* @copydoc Form::readInputData()
|
||||
*/
|
||||
public function readInputData()
|
||||
{
|
||||
$this->readUserVars(['genreId']);
|
||||
return parent::readInputData();
|
||||
}
|
||||
|
||||
/**
|
||||
* @copydoc Form::validate()
|
||||
*/
|
||||
public function validate($callHooks = true)
|
||||
{
|
||||
// Is this a revision?
|
||||
$revisedFileId = $this->getRevisedFileId();
|
||||
if ($this->getData('revisionOnly')) {
|
||||
assert($revisedFileId > 0);
|
||||
}
|
||||
|
||||
// Retrieve the request context.
|
||||
$request = Application::get()->getRequest();
|
||||
$router = $request->getRouter();
|
||||
$context = $router->getContext($request);
|
||||
if (
|
||||
$this->getData('fileStage') != SubmissionFile::SUBMISSION_FILE_REVIEW_ATTACHMENT and
|
||||
!$revisedFileId
|
||||
) {
|
||||
// Add an additional check for the genre to the form.
|
||||
$this->addCheck(new \PKP\form\validation\FormValidatorCustom(
|
||||
$this,
|
||||
'genreId',
|
||||
FormValidator::FORM_VALIDATOR_REQUIRED_VALUE,
|
||||
'submission.upload.noGenre',
|
||||
function ($genreId) use ($context) {
|
||||
$genreDao = DAORegistry::getDAO('GenreDAO'); /** @var GenreDAO $genreDao */
|
||||
return is_a($genreDao->getById($genreId, $context->getId()), 'Genre');
|
||||
}
|
||||
));
|
||||
}
|
||||
|
||||
return parent::validate($callHooks);
|
||||
}
|
||||
|
||||
/**
|
||||
* @copydoc Form::fetch()
|
||||
*
|
||||
* @param null|mixed $template
|
||||
*/
|
||||
public function fetch($request, $template = null, $display = false)
|
||||
{
|
||||
// Retrieve available submission file genres.
|
||||
$genreList = $this->_retrieveGenreList($request);
|
||||
$this->setData('submissionFileGenres', $genreList);
|
||||
|
||||
return parent::fetch($request, $template, $display);
|
||||
}
|
||||
|
||||
/**
|
||||
* Save the submission file upload form.
|
||||
*
|
||||
* @see Form::execute()
|
||||
*
|
||||
* @return ?SubmissionFile if successful, otherwise null
|
||||
*/
|
||||
public function execute(...$functionParams)
|
||||
{
|
||||
// Identify the uploading user.
|
||||
$request = Application::get()->getRequest();
|
||||
$user = $request->getUser();
|
||||
assert(is_a($user, 'User'));
|
||||
|
||||
// Upload the file.
|
||||
$fileManager = new FileManager();
|
||||
$extension = $fileManager->parseFileExtension($_FILES['uploadedFile']['name']);
|
||||
|
||||
$submissionDir = Repo::submissionFile()->getSubmissionDir($request->getContext()->getId(), $this->getData('submissionId'));
|
||||
$fileId = Services::get('file')->add(
|
||||
$_FILES['uploadedFile']['tmp_name'],
|
||||
$submissionDir . '/' . uniqid() . '.' . $extension
|
||||
);
|
||||
|
||||
if ($this->getRevisedFileId()) {
|
||||
$submissionFile = Repo::submissionFile()->get($this->getRevisedFileId());
|
||||
Repo::submissionFile()->edit(
|
||||
$submissionFile,
|
||||
[
|
||||
'fileId' => $fileId,
|
||||
'name' => [
|
||||
$this->_submission->getLocale() => $_FILES['uploadedFile']['name'],
|
||||
],
|
||||
'uploaderUserId' => $user->getId(),
|
||||
]
|
||||
);
|
||||
|
||||
$submissionFile = Repo::submissionFile()->get($this->getRevisedFileId());
|
||||
} else {
|
||||
$submissionFile = Repo::submissionFile()->dao->newDataObject();
|
||||
$submissionFile->setData('fileId', $fileId);
|
||||
$submissionFile->setData('fileStage', $this->getData('fileStage'));
|
||||
$submissionFile->setData('name', $_FILES['uploadedFile']['name'], $this->_submission->getLocale());
|
||||
$submissionFile->setData('submissionId', $this->getData('submissionId'));
|
||||
$submissionFile->setData('uploaderUserId', $user->getId());
|
||||
$submissionFile->setData('assocType', $this->getData('assocType') ? (int) $this->getData('assocType') : null);
|
||||
$submissionFile->setData('assocId', $this->getData('assocId') ? (int) $this->getData('assocId') : null);
|
||||
|
||||
$genreId = (int) $this->getData('genreId');
|
||||
if ($genreId === 0) {
|
||||
$genreId = null;
|
||||
}
|
||||
$submissionFile->setData('genreId', $genreId);
|
||||
|
||||
if ($this->getReviewRound() && $this->getReviewRound()->getId() && empty($submissionFile->getData('assocType'))) {
|
||||
$submissionFile->setData('assocType', Application::ASSOC_TYPE_REVIEW_ROUND);
|
||||
$submissionFile->setData('assocId', $this->getReviewRound()->getId());
|
||||
}
|
||||
|
||||
$id = Repo::submissionFile()->add($submissionFile);
|
||||
|
||||
$submissionFile = Repo::submissionFile()->get($id);
|
||||
}
|
||||
|
||||
if (!$submissionFile) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$hookResult = parent::execute($submissionFile, ...$functionParams);
|
||||
if ($hookResult) {
|
||||
return $hookResult;
|
||||
}
|
||||
|
||||
return $submissionFile;
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// Private helper methods
|
||||
//
|
||||
/**
|
||||
* Retrieve the genre list.
|
||||
*
|
||||
* @param Request $request
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function _retrieveGenreList($request)
|
||||
{
|
||||
$context = $request->getContext();
|
||||
$genreDao = DAORegistry::getDAO('GenreDAO'); /** @var GenreDAO $genreDao */
|
||||
$dependentFilesOnly = $request->getUserVar('dependentFilesOnly') ? true : false;
|
||||
$genres = $genreDao->getByDependenceAndContextId($dependentFilesOnly, $context->getId());
|
||||
|
||||
// Transform the genres into an array and
|
||||
// assign them to the form.
|
||||
$genreList = [];
|
||||
while ($genre = $genres->next()) {
|
||||
$genreList[$genre->getId()] = $genre->getLocalizedName();
|
||||
}
|
||||
return $genreList;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user