first commit

This commit is contained in:
CHIEFSOFT\ameye
2024-06-08 17:09:23 -04:00
commit df3a033196
17887 changed files with 8637778 additions and 0 deletions
@@ -0,0 +1,215 @@
<?php
/**
* @defgroup controllers_api_file File API controller
*/
/**
* @file controllers/api/file/FileApiHandler.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 FileApiHandler
*
* @ingroup controllers_api_file
*
* @brief Class defining an AJAX API for supplying file information.
*/
namespace PKP\controllers\api\file;
use APP\core\Application;
use APP\core\Request;
use APP\core\Services;
use APP\facades\Repo;
use APP\handler\Handler;
use Exception;
use PKP\config\Config;
use PKP\core\JSONMessage;
use PKP\db\DAORegistry;
use PKP\file\FileArchive;
use PKP\file\FileManager;
use PKP\pages\libraryFiles\LibraryFileHandler;
use PKP\security\authorization\ContextAccessPolicy;
use PKP\security\authorization\PolicySet;
use PKP\security\authorization\SubmissionFileAccessPolicy;
use PKP\security\Role;
use PKP\submission\GenreDAO;
use PKP\submission\reviewAssignment\ReviewAssignment;
use PKP\submissionFile\SubmissionFile;
class FileApiHandler extends Handler
{
/**
* 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_ASSISTANT, Role::ROLE_ID_REVIEWER, Role::ROLE_ID_AUTHOR],
['downloadFile', 'downloadLibraryFile', 'downloadAllFiles', 'recordDownload', 'enableLinkAction']
);
}
//
// Implement methods from PKPHandler
//
public function authorize($request, &$args, $roleAssignments)
{
$submissionId = (int) $request->getUserVar('submissionId');
$submissionFileId = (int) $request->getUserVar('submissionFileId');
$fileStage = (int) $request->getUserVar('fileStage');
$libraryFileId = $request->getUserVar('libraryFileId');
if (!empty($submissionFileId)) {
$this->addPolicy(new SubmissionFileAccessPolicy($request, $args, $roleAssignments, SubmissionFileAccessPolicy::SUBMISSION_FILE_ACCESS_READ, $submissionFileId));
} elseif (is_numeric($libraryFileId)) {
$this->addPolicy(new ContextAccessPolicy($request, $roleAssignments));
} elseif (!empty($fileStage) && empty($submissionFileId)) {
$submissionFileIds = Repo::submissionFile()
->getCollector()
->filterBySubmissionIds([$submissionId])
->filterByFileStages([$fileStage])
->includeDependentFiles($fileStage === SubmissionFile::SUBMISSION_FILE_DEPENDENT)
->getIds();
$allFilesAccessPolicy = new PolicySet(PolicySet::COMBINING_DENY_OVERRIDES);
foreach ($submissionFileIds as $submissionFileId) {
$allFilesAccessPolicy->addPolicy(new SubmissionFileAccessPolicy($request, $args, $roleAssignments, SubmissionFileAccessPolicy::SUBMISSION_FILE_ACCESS_READ, $submissionFileId));
}
$this->addPolicy($allFilesAccessPolicy);
}
return parent::authorize($request, $args, $roleAssignments);
}
//
// Public handler methods
//
/**
* Download a file.
*
* @param array $args
* @param Request $request
*/
public function downloadFile($args, $request)
{
$submissionFile = $this->getAuthorizedContextObject(Application::ASSOC_TYPE_SUBMISSION_FILE);
$fileId = $request->getUserVar('fileId') ?? $submissionFile->getData('fileId');
$revisions = Repo::submissionFile()
->getRevisions($submissionFile->getId());
$file = null;
foreach ($revisions as $revision) {
if ($revision->fileId == $fileId) {
$file = $revision;
}
}
if (!$file) {
throw new Exception('File ' . $fileId . ' is not a revision of submission file ' . $submissionFile->getId());
}
if (!Services::get('file')->fs->has($file->path)) {
$request->getDispatcher()->handle404();
}
$filename = $request->getUserVar('filename') ?? $submissionFile->getLocalizedData('name');
// Enforce anonymous filenames for anonymous review assignments
$reviewAssignment = $this->getAuthorizedContextObject(Application::ASSOC_TYPE_REVIEW_ASSIGNMENT);
if ($reviewAssignment
&& $reviewAssignment->getReviewMethod() == ReviewAssignment::SUBMISSION_REVIEW_METHOD_DOUBLEANONYMOUS
&& $reviewAssignment->getReviewerId() == $request->getUser()->getId()) {
$genreDao = DAORegistry::getDAO('GenreDAO'); /** @var GenreDAO $genreDao */
$genre = $genreDao->getById($submissionFile->getData('genreId'));
$filename = sprintf(
'%s-%s-%d-%s-%d',
\Stringy\Stringy::create($request->getContext()->getLocalizedData('acronym'))->toLowerCase(),
\Stringy\Stringy::create(__('submission.list.reviewAssignment'))->dasherize(),
$submissionFile->getData('submissionId'),
$genre ? $genre->getLocalizedName() : 'none',
$submissionFile->getId()
);
}
$filename = Services::get('file')->formatFilename($file->path, $filename);
Services::get('file')->download((int) $fileId, $filename);
}
/**
* Download a library file.
*
* @param array $args
* @param Request $request
*/
public function downloadLibraryFile($args, $request)
{
$libraryFileHandler = new LibraryFileHandler($this);
return $libraryFileHandler->downloadLibraryFile($args, $request);
}
/**
* Download all passed files.
*
* @param array $args
* @param Request $request
*/
public function downloadAllFiles($args, $request)
{
// Retrieve the authorized objects.
$submissionFiles = $this->getAuthorizedContextObject(Application::ASSOC_TYPE_SUBMISSION_FILES);
$files = [];
foreach ($submissionFiles as $submissionFile) {
$path = $submissionFile->getData('path');
$files[$path] = Services::get('file')->formatFilename($path, $submissionFile->getLocalizedData('name'));
}
$filename = !empty($args['nameLocaleKey'])
? __($args['nameLocaleKey'])
: __('submission.files');
$filename = $args['submissionId'] . '-' . $filename;
$filename = \Stringy\Stringy::create($filename)->toLowerCase()->dasherize()->regexReplace('[^a-z0-9\-\_.]', '');
$fileArchive = new FileArchive();
$archivePath = $fileArchive->create($files, rtrim(Config::getVar('files', 'files_dir'), '/'));
if (file_exists($archivePath)) {
$fileManager = new FileManager();
if ($fileArchive->zipFunctional()) {
$fileManager->downloadByPath($archivePath, 'application/x-zip', false, $filename . '.zip');
} else {
$fileManager->downloadByPath($archivePath, 'application/x-gtar', false, $filename . '.tar.gz');
}
$fileManager->deleteByPath($archivePath);
} else {
throw new Exception('Creating archive with submission files failed!');
}
}
/**
* Record file download and return js event to update grid rows.
*
* @param array $args
* @param Request $request
*
* @return JSONMessage
*/
public function recordDownload($args, $request)
{
return $this->enableLinkAction($args, $request);
}
/**
* Returns a data changd event to re-enable the link action. Refactored out of
* recordDownload since library files do not have downloads recorded and are in a
* different context.
*
* @param array $args
* @param Request $request
*
* @return JSONMessage JSON object
*/
public function enableLinkAction($args, $request)
{
return \PKP\db\DAO::getDataChangedEvent();
}
}
@@ -0,0 +1,307 @@
<?php
/**
* @file controllers/api/file/PKPManageFileApiHandler.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 PKPManageFileApiHandler
*
* @ingroup controllers_api_file
*
* @brief Class defining an AJAX API for file manipulation.
*/
namespace PKP\controllers\api\file;
use APP\core\Application;
use APP\core\Request;
use APP\core\Services;
use APP\facades\Repo;
use APP\handler\Handler;
use APP\notification\NotificationManager;
use APP\template\TemplateManager;
use PKP\controllers\wizard\fileUpload\form\SubmissionFilesMetadataForm;
use PKP\core\JSONMessage;
use PKP\core\PKPApplication;
use PKP\db\DAORegistry;
use PKP\log\event\EventLogEntry;
use PKP\notification\NotificationDAO;
use PKP\notification\PKPNotification;
use PKP\observers\events\MetadataChanged;
use PKP\security\authorization\SubmissionFileAccessPolicy;
use PKP\security\Role;
use PKP\stageAssignment\StageAssignmentDAO;
use PKP\submissionFile\SubmissionFile;
abstract class PKPManageFileApiHandler extends Handler
{
/**
* 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_ASSISTANT, Role::ROLE_ID_REVIEWER, Role::ROLE_ID_AUTHOR],
['deleteFile', 'editMetadata', 'editMetadataTab', 'saveMetadata', 'cancelFileUpload']
);
}
//
// Implement methods from PKPHandler
//
public function authorize($request, &$args, $roleAssignments)
{
$this->addPolicy(new SubmissionFileAccessPolicy($request, $args, $roleAssignments, SubmissionFileAccessPolicy::SUBMISSION_FILE_ACCESS_MODIFY, (int) $args['submissionFileId']));
return parent::authorize($request, $args, $roleAssignments);
}
//
// Public handler methods
//
/**
* Delete a file or revision
*
* @param array $args
* @param Request $request
*
* @return JSONMessage JSON object
*/
public function deleteFile($args, $request)
{
if (!$request->checkCSRF()) {
return new JSONMessage(false);
}
$submissionFile = $this->getAuthorizedContextObject(Application::ASSOC_TYPE_SUBMISSION_FILE);
Repo::submissionFile()->delete($submissionFile);
$this->setupTemplate($request);
$user = $request->getUser();
if (!$request->getUserVar('suppressNotification')) {
$notificationMgr = new NotificationManager();
$notificationMgr->createTrivialNotification(
$user->getId(),
PKPNotification::NOTIFICATION_TYPE_SUCCESS,
['contents' => __('notification.removedFile')]
);
}
return \PKP\db\DAO::getDataChangedEvent();
}
/**
* Restore original file when cancelling the upload wizard
*/
public function cancelFileUpload(array $args, Request $request): JSONMessage
{
if (!$request->checkCSRF()) {
return new JSONMessage(false);
}
$submissionFile = $this->getAuthorizedContextObject(Application::ASSOC_TYPE_SUBMISSION_FILE);
$originalFile = $request->getUserVar('originalFile') ? (array)$request->getUserVar('originalFile') : null;
$revisedFileId = $request->getUserVar('fileId') ? (int)$request->getUserVar('fileId') : null;
// Get revisions and check file IDs
$revisions = Repo::submissionFile()->getRevisions($submissionFile->getId());
$revisionIds = [];
foreach ($revisions as $revision) {
$revisionIds[] = $revision->fileId;
}
if (!$revisedFileId || !in_array($revisedFileId, $revisionIds)) {
return new JSONMessage(false);
}
if (!isset($originalFile['fileId']) || !in_array($originalFile['fileId'], $revisionIds)) {
return new JSONMessage(false);
}
$originalFileId = (int) $originalFile['fileId'];
// Get the file name and uploader user ID
$originalUserId = $originalFile['uploaderUserId'] ? (int)$originalFile['uploaderUserId'] : null;
$originalFileName = $originalFile['name'] ? (array)$originalFile['name'] : null;
if (!$originalUserId || !$originalFileName) {
return new JSONMessage(false);
}
$originalUser = Repo::user()->get($originalUserId);
if (!$originalUser) {
return new JSONMessage(false);
}
$originalUsername = $originalUser->getUsername();
$matchedLogEntry = $this->findMatchedLogEntry($submissionFile, $originalFileId, $originalUsername, $originalFileName);
if (!$matchedLogEntry) {
return new JSONMessage(false);
}
// Restore original submission file
Repo::submissionFile()->edit(
$submissionFile,
[
'fileId' => $matchedLogEntry->getData('fileId'),
'name' => $matchedLogEntry->getData('filename'),
'uploaderUserId' => Repo::user()->getByUsername($matchedLogEntry->getData('username'))->getId(),
]
);
// Remove uploaded file
Services::get('file')->delete($revisedFileId);
$this->setupTemplate($request);
return \PKP\db\DAO::getDataChangedEvent();
}
/**
* Edit submission file metadata modal.
*
* @param array $args
* @param Request $request
*
* @return JSONMessage JSON object
*/
public function editMetadata($args, $request)
{
$submissionFile = $this->getAuthorizedContextObject(Application::ASSOC_TYPE_SUBMISSION_FILE);
if ($submissionFile->getFileStage() == SubmissionFile::SUBMISSION_FILE_PROOF) {
$templateMgr = TemplateManager::getManager($request);
$templateMgr->assign('submissionFile', $submissionFile);
$templateMgr->assign('stageId', $request->getUserVar('stageId'));
return new JSONMessage(true, $templateMgr->fetch('controllers/api/file/editMetadata.tpl'));
} else {
return $this->editMetadataTab($args, $request);
}
}
/**
* Edit submission file metadata tab.
*
* @param array $args
* @param Request $request
*
* @return JSONMessage JSON object
*/
public function editMetadataTab($args, $request)
{
$submissionFile = $this->getAuthorizedContextObject(Application::ASSOC_TYPE_SUBMISSION_FILE);
$reviewRound = $this->getAuthorizedContextObject(Application::ASSOC_TYPE_REVIEW_ROUND);
$stageId = $request->getUserVar('stageId');
$form = new SubmissionFilesMetadataForm($submissionFile, $stageId, $reviewRound);
$form->setShowButtons(true);
return new JSONMessage(true, $form->fetch($request));
}
/**
* Save the metadata of the latest revision of
* the requested submission file.
*
* @param array $args
* @param Request $request
*
* @return JSONMessage JSON object
*/
public function saveMetadata($args, $request)
{
$submission = $this->getAuthorizedContextObject(Application::ASSOC_TYPE_SUBMISSION);
$submissionFile = $this->getAuthorizedContextObject(Application::ASSOC_TYPE_SUBMISSION_FILE);
$reviewRound = $this->getAuthorizedContextObject(Application::ASSOC_TYPE_REVIEW_ROUND);
$stageId = $request->getUserVar('stageId');
$form = new SubmissionFilesMetadataForm($submissionFile, $stageId, $reviewRound);
$form->readInputData();
if ($form->validate()) {
$form->execute();
$submissionFile = $form->getSubmissionFile();
// Get a list of author user IDs
$authorUserIds = [];
$stageAssignmentDao = DAORegistry::getDAO('StageAssignmentDAO'); /** @var StageAssignmentDAO $stageAssignmentDao */
$submitterAssignments = $stageAssignmentDao->getBySubmissionAndRoleIds($submission->getId(), [Role::ROLE_ID_AUTHOR]);
while ($assignment = $submitterAssignments->next()) {
$authorUserIds[] = $assignment->getUserId();
}
// Update the notifications
$notificationMgr = new NotificationManager(); /** @var NotificationManager $notificationMgr */
$notificationMgr->updateNotification(
$request,
$this->getUpdateNotifications(),
$authorUserIds,
Application::ASSOC_TYPE_SUBMISSION,
$submission->getId()
);
if ($reviewRound) {
// Delete any 'revision requested' notifications since revisions are now in.
$context = $request->getContext();
$notificationDao = DAORegistry::getDAO('NotificationDAO'); /** @var NotificationDAO $notificationDao */
$stageAssignmentDao = DAORegistry::getDAO('StageAssignmentDAO'); /** @var StageAssignmentDAO $stageAssignmentDao */
$submitterAssignments = $stageAssignmentDao->getBySubmissionAndRoleIds($submission->getId(), [Role::ROLE_ID_AUTHOR]);
while ($assignment = $submitterAssignments->next()) {
$notificationDao->deleteByAssoc(Application::ASSOC_TYPE_SUBMISSION, $submission->getId(), $assignment->getUserId(), PKPNotification::NOTIFICATION_TYPE_EDITOR_DECISION_PENDING_REVISIONS, $context->getId());
}
}
// Inform SearchIndex of changes
event(new MetadataChanged($submission));
return \PKP\db\DAO::getDataChangedEvent();
} else {
return new JSONMessage(true, $form->fetch($request));
}
}
/**
* Get the list of notifications to be updated on metadata form submission.
*
* @return array
*/
protected function getUpdateNotifications()
{
return [PKPNotification::NOTIFICATION_TYPE_PENDING_EXTERNAL_REVISIONS];
}
/**
* Compare user supplied data when cancelling file upload with saved in the event log;
* assuming we found the right entry if they match
*/
protected function findMatchedLogEntry(
SubmissionFile $submissionFile,
int $originalFileId,
string $originalUsername,
array $originalFileName
): ?EventLogEntry
{
$logEntries = Repo::eventLog()->getCollector()
->filterByAssoc(PKPApplication::ASSOC_TYPE_SUBMISSION_FILE, [$submissionFile->getId()])
->getMany();
$match = null;
foreach ($logEntries as $logEntry) {
$loggedUsername = $logEntry->getData('username');
$loggedFileName = $logEntry->getData('filename');
$loggedFileId = $logEntry->getData('fileId');
if (!$loggedUsername || !$loggedFileName || !$loggedFileId) {
continue;
}
if (
$loggedUsername === $originalUsername &&
$loggedFileName == $originalFileName &&
$loggedFileId === $originalFileId
) {
$match = $logEntry;
break;
}
}
return $match;
}
}
@@ -0,0 +1,167 @@
<?php
/**
* @file controllers/api/file/linkAction/AddFileLinkAction.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 AddFileLinkAction
*
* @ingroup controllers_api_file_linkAction
*
* @brief An action to add a submission file.
*/
namespace PKP\controllers\api\file\linkAction;
use APP\core\Request;
use PKP\submissionFile\SubmissionFile;
class AddFileLinkAction extends BaseAddFileLinkAction
{
/**
* Constructor
*
* @param Request $request
* @param int $submissionId The submission the file should be
* uploaded to.
* @param int $stageId The workflow stage in which the file
* uploader is being instantiated (one of the WORKFLOW_STAGE_ID_*
* constants).
* @param array $uploaderRoles The ids of all roles allowed to upload
* in the context of this action.
* @param int $fileStage The file stage the file should be
* uploaded to (one of the SubmissionFile::SUBMISSION_FILE_* constants).
* @param int $assocType The type of the element the file should
* be associated with (one fo the Application::ASSOC_TYPE_* constants).
* @param int $assocId The id of the element the file should be
* associated with.
* @param int $reviewRoundId The current review round ID (if any)
* @param int $revisedFileId Revised file ID, if any
* @param bool $dependentFilesOnly whether to only include dependent
* files in the Genres dropdown.
* @param int $queryId The query id. Use when the assoc details point
* to a note
*/
public function __construct(
$request,
$submissionId,
$stageId,
$uploaderRoles,
$fileStage,
$assocType = null,
$assocId = null,
$reviewRoundId = null,
$revisedFileId = null,
$dependentFilesOnly = false,
$queryId = null
) {
// Create the action arguments array.
$actionArgs = ['fileStage' => $fileStage, 'reviewRoundId' => $reviewRoundId];
if (is_numeric($assocType) && is_numeric($assocId)) {
$actionArgs['assocType'] = (int)$assocType;
$actionArgs['assocId'] = (int)$assocId;
}
if ($revisedFileId) {
$actionArgs['revisedFileId'] = $revisedFileId;
$actionArgs['revisionOnly'] = true;
}
if ($dependentFilesOnly) {
$actionArgs['dependentFilesOnly'] = true;
}
if ($queryId) {
$actionArgs['queryId'] = $queryId;
}
// Identify text labels based on the file stage.
$textLabels = AddFileLinkAction::_getTextLabels($fileStage);
// Call the parent class constructor.
parent::__construct(
$request,
$submissionId,
$stageId,
$uploaderRoles,
$actionArgs,
__($textLabels['wizardTitle']),
__($textLabels['buttonLabel'])
);
}
//
// Private methods
//
/**
* Static method to return text labels
* for upload to different file stages.
*
* @param int $fileStage One of the
* SubmissionFile::SUBMISSION_FILE_* constants.
*
* @return array
*/
public static function _getTextLabels($fileStage)
{
static $textLabels = [
SubmissionFile::SUBMISSION_FILE_SUBMISSION => [
'wizardTitle' => 'submission.submit.uploadSubmissionFile',
'buttonLabel' => 'submission.addFile'
],
SubmissionFile::SUBMISSION_FILE_REVIEW_FILE => [
'wizardTitle' => 'editor.submissionReview.uploadFile',
'buttonLabel' => 'editor.submissionReview.uploadFile'
],
SubmissionFile::SUBMISSION_FILE_INTERNAL_REVIEW_FILE => [
'wizardTitle' => 'editor.submissionReview.uploadFile',
'buttonLabel' => 'editor.submissionReview.uploadFile'
],
SubmissionFile::SUBMISSION_FILE_REVIEW_ATTACHMENT => [
'wizardTitle' => 'editor.submissionReview.uploadAttachment',
'buttonLabel' => 'editor.submissionReview.uploadAttachment'
],
SubmissionFile::SUBMISSION_FILE_ATTACHMENT => [
'wizardTitle' => 'editor.submissionReview.uploadFile',
'buttonLabel' => 'submission.addFile'
],
SubmissionFile::SUBMISSION_FILE_REVIEW_REVISION => [
'wizardTitle' => 'editor.submissionReview.uploadFile',
'buttonLabel' => 'submission.addFile'
],
SubmissionFile::SUBMISSION_FILE_INTERNAL_REVIEW_REVISION => [
'wizardTitle' => 'editor.submissionReview.uploadFile',
'buttonLabel' => 'submission.addFile'
],
SubmissionFile::SUBMISSION_FILE_FINAL => [
'wizardTitle' => 'submission.upload.finalDraft',
'buttonLabel' => 'submission.addFile'
],
SubmissionFile::SUBMISSION_FILE_COPYEDIT => [
'wizardTitle' => 'submission.upload.copyeditedVersion',
'buttonLabel' => 'submission.addFile'
],
SubmissionFile::SUBMISSION_FILE_PRODUCTION_READY => [
'wizardTitle' => 'submission.upload.productionReady',
'buttonLabel' => 'submission.addFile'
],
SubmissionFile::SUBMISSION_FILE_PROOF => [
'wizardTitle' => 'submission.upload.proof',
'buttonLabel' => 'submission.changeFile'
],
SubmissionFile::SUBMISSION_FILE_DEPENDENT => [
'wizardTitle' => 'submission.upload.dependent',
'buttonLabel' => 'submission.addFile'
],
SubmissionFile::SUBMISSION_FILE_QUERY => [
'wizardTitle' => 'submission.upload.query',
'buttonLabel' => 'submission.addFile'
],
];
assert(isset($textLabels[$fileStage]));
return $textLabels[$fileStage];
}
}
@@ -0,0 +1,54 @@
<?php
/**
* @file controllers/api/file/linkAction/AddRevisionLinkAction.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 AddRevisionLinkAction
*
* @ingroup controllers_api_file_linkAction
*
* @brief An action to upload a revision of file currently under review.
*/
namespace PKP\controllers\api\file\linkAction;
use APP\core\Request;
use PKP\submission\reviewRound\ReviewRound;
use PKP\submissionFile\SubmissionFile;
class AddRevisionLinkAction extends BaseAddFileLinkAction
{
/**
* Constructor
*
* @param Request $request
* @param ReviewRound $reviewRound The review round to upload to.
* @param array $uploaderRoles The ids of all roles allowed to upload
* in the context of this action.
*/
public function __construct($request, $reviewRound, $uploaderRoles)
{
// Create the action arguments array.
$actionArgs = [
'fileStage' => SubmissionFile::SUBMISSION_FILE_REVIEW_REVISION,
'stageId' => $reviewRound->getStageId(),
'reviewRoundId' => $reviewRound->getId(),
'revisionOnly' => '1'
];
// Call the parent class constructor.
parent::__construct(
$request,
$reviewRound->getSubmissionId(),
$reviewRound->getStageId(),
$uploaderRoles,
$actionArgs,
__('submission.review.uploadRevisionToRound', ['round' => $reviewRound->getRound()]),
__('submission.addFile')
);
}
}
@@ -0,0 +1,80 @@
<?php
/**
* @defgroup controllers_api_file_linkAction Link action API controller
*/
/**
* @file controllers/api/file/linkAction/BaseAddFileLinkAction.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 BaseAddFileLinkAction
*
* @ingroup controllers_api_file_linkAction
*
* @brief Abstract base class for file upload actions.
*/
namespace PKP\controllers\api\file\linkAction;
use APP\core\Request;
use PKP\core\PKPApplication;
use PKP\linkAction\LinkAction;
use PKP\linkAction\request\WizardModal;
class BaseAddFileLinkAction extends LinkAction
{
/**
* Constructor
*
* @param Request $request
* @param int $submissionId The submission the file should be
* uploaded to.
* @param int $stageId The workflow stage in which the file
* uploader is being instantiated (one of the WORKFLOW_STAGE_ID_*
* constants).
* @param array $uploaderRoles The ids of all roles allowed to upload
* in the context of this action.
* @param array $actionArgs The arguments to be passed into the file
* upload wizard.
* @param string $wizardTitle The title to be displayed in the file
* upload wizard.
* @param string $buttonLabel The link action's button label.
*/
public function __construct(
$request,
$submissionId,
$stageId,
$uploaderRoles,
$actionArgs,
$wizardTitle,
$buttonLabel
) {
// Augment the action arguments array.
$actionArgs['submissionId'] = $submissionId;
$actionArgs['stageId'] = $stageId;
assert(is_array($uploaderRoles) && count($uploaderRoles) >= 1);
$actionArgs['uploaderRoles'] = implode('-', (array) $uploaderRoles);
// Instantiate the file upload modal.
$dispatcher = $request->getDispatcher();
$modal = new WizardModal(
$dispatcher->url(
$request,
PKPApplication::ROUTE_COMPONENT,
null,
'wizard.fileUpload.FileUploadWizardHandler',
'startWizard',
null,
$actionArgs
),
$wizardTitle,
'modal_add_file'
);
// Configure the link action.
parent::__construct('addFile', $modal, $buttonLabel, 'add');
}
}
@@ -0,0 +1,56 @@
<?php
/**
* @file controllers/api/file/linkAction/DeleteFileLinkAction.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 DeleteFileLinkAction
*
* @ingroup controllers_api_file_linkAction
*
* @brief An action to delete a file.
*/
namespace PKP\controllers\api\file\linkAction;
use APP\core\Request;
use PKP\linkAction\request\RemoteActionConfirmationModal;
use PKP\submissionFile\SubmissionFile;
class DeleteFileLinkAction extends FileLinkAction
{
/**
* Constructor
*
* @param Request $request
* @param SubmissionFile $submissionFile the submission file to be deleted
* @param int $stageId (optional)
* @param string $localeKey (optional) Locale key to use for delete link
* be deleted.
*/
public function __construct($request, $submissionFile, $stageId, $localeKey = 'grid.action.delete')
{
$router = $request->getRouter();
parent::__construct(
'deleteFile',
new RemoteActionConfirmationModal(
$request->getSession(),
__('common.confirmDelete'),
__('common.delete'),
$router->url(
$request,
null,
'api.file.ManageFileApiHandler',
'deleteFile',
null,
$this->getActionArgs($submissionFile, $stageId)
),
'modal_delete'
),
__($localeKey),
'delete'
);
}
}
@@ -0,0 +1,91 @@
<?php
/**
* @file controllers/api/file/linkAction/DownloadFileLinkAction.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 DownloadFileLinkAction
*
* @ingroup controllers_api_file_linkAction
*
* @brief An action to download a file.
*/
namespace PKP\controllers\api\file\linkAction;
use APP\core\Request;
use PKP\linkAction\request\PostAndRedirectAction;
use PKP\submissionFile\SubmissionFile;
class DownloadFileLinkAction extends FileLinkAction
{
/** @var string Optional label to use instead of file name */
public $label;
/**
* Constructor
*
* @param Request $request
* @param SubmissionFile $submissionFile the submission file to
* link to.
* @param int $stageId (optional)
* @param string $label (optional) Label to use instead of filename
* @param int $fileId (optional) Download a specific revision of a file
* @param string $filename (optional) The filename to use for the file
*/
public function __construct($request, $submissionFile, $stageId = null, $label = null, $fileId = null, $filename = null)
{
// Instantiate the redirect action request.
$router = $request->getRouter();
$this->label = $label;
$actionArgs = $this->getActionArgs($submissionFile, $stageId);
if ($fileId) {
$actionArgs['fileId'] = $fileId;
}
if ($filename) {
$actionArgs['filename'] = $filename;
}
$redirectRequest = new PostAndRedirectAction(
$router->url(
$request,
null,
'api.file.FileApiHandler',
'recordDownload',
null,
$actionArgs
),
$router->url(
$request,
null,
'api.file.FileApiHandler',
'downloadFile',
null,
$actionArgs
)
);
// Configure the file link action.
parent::__construct(
'downloadFile',
$redirectRequest,
htmlspecialchars($this->getLabel($submissionFile))
);
}
/**
* Get the label for the file download action.
*
* @param SubmissionFile $submissionFile
*
* @return string
*/
public function getLabel($submissionFile)
{
if ($this->label !== null) {
return $this->label;
}
return $submissionFile->getLocalizedData('name');
}
}
@@ -0,0 +1,84 @@
<?php
/**
* @file controllers/api/file/linkAction/DownloadLibraryFileLinkAction.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 DownloadLibraryFileLinkAction
*
* @ingroup controllers_api_file_linkAction
*
* @brief An action to download a library file.
*/
namespace PKP\controllers\api\file\linkAction;
use APP\core\Request;
use PKP\context\LibraryFile;
use PKP\linkAction\LinkAction;
use PKP\linkAction\request\PostAndRedirectAction;
class DownloadLibraryFileLinkAction extends LinkAction
{
/**
* Constructor
*
* @param Request $request
* @param LibraryFile $libraryFile the library file to
* link to.
*/
public function __construct($request, $libraryFile)
{
// Instantiate the redirect action request.
$router = $request->getRouter();
$redirectRequest = new PostAndRedirectAction(
$router->url(
$request,
null,
'api.file.FileApiHandler',
'enableLinkAction',
null,
$this->getActionArgs($libraryFile)
),
$router->url(
$request,
null,
'api.file.FileApiHandler',
'downloadLibraryFile',
null,
$this->getActionArgs($libraryFile)
)
);
// Configure the file link action.
parent::__construct(
'downloadFile',
$redirectRequest,
htmlspecialchars($libraryFile->getLocalizedName()),
$libraryFile->getDocumentType()
);
}
/**
* Return the action arguments to address a file.
*
* @param LibraryFile $libraryFile
*
* @return array
*/
public function getActionArgs(&$libraryFile)
{
assert($libraryFile instanceof LibraryFile);
// Create the action arguments array.
$args = ['libraryFileId' => $libraryFile->getId()];
if ($libraryFile->getSubmissionId()) {
$args['submissionId'] = $libraryFile->getSubmissionId();
}
return $args;
}
}
@@ -0,0 +1,59 @@
<?php
/**
* @file controllers/api/file/linkAction/EditFileLinkAction.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 EditFileLinkAction
*
* @ingroup controllers_api_file_linkAction
*
* @brief An action to edit a file's metadata.
*/
namespace PKP\controllers\api\file\linkAction;
use APP\core\Request;
use PKP\core\PKPApplication;
use PKP\linkAction\request\AjaxModal;
use PKP\submissionFile\SubmissionFile;
class EditFileLinkAction extends FileLinkAction
{
/**
* Constructor
*
* @param Request $request
* @param SubmissionFile $submissionFile the submission file to edit.
* @param int $stageId Stage ID
*/
public function __construct($request, $submissionFile, $stageId)
{
// Instantiate the AJAX modal request.
$router = $request->getRouter();
$dispatcher = $router->getDispatcher();
$modal = new AjaxModal(
$dispatcher->url(
$request,
PKPApplication::ROUTE_COMPONENT,
null,
'api.file.ManageFileApiHandler',
'editMetadata',
null,
$this->getActionArgs($submissionFile, $stageId)
),
__('grid.action.editFile'),
'modal_information'
);
// Configure the file link action.
parent::__construct(
'editFile',
$modal,
__('common.edit'),
'edit'
);
}
}
@@ -0,0 +1,49 @@
<?php
/**
* @file controllers/api/file/linkAction/FileLinkAction.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 FileLinkAction
*
* @ingroup controllers_api_file_linkAction
*
* @brief An abstract file action.
*/
namespace PKP\controllers\api\file\linkAction;
use PKP\linkAction\LinkAction;
use PKP\submissionFile\SubmissionFile;
class FileLinkAction extends LinkAction
{
//
// Protected helper function
//
/**
* Return the action arguments to address a file.
*
* @param SubmissionFile $submissionFile
* @param int $stageId (optional)
*
* @return array
*/
public function getActionArgs($submissionFile, $stageId = null)
{
assert($submissionFile instanceof SubmissionFile);
// Create the action arguments array.
$args = [
'submissionFileId' => $submissionFile->getId(),
'submissionId' => $submissionFile->getData('submissionId')
];
if ($stageId) {
$args['stageId'] = $stageId;
}
return $args;
}
}
@@ -0,0 +1,50 @@
<?php
/**
* @file controllers/api/task/SendReminderLinkAction.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 SendReminderLinkAction
*
* @ingroup controllers_api_task
*
* @brief An action to open up a modal to send a reminder to users assigned to a task.
*/
namespace PKP\controllers\api\task;
use APP\core\Request;
use PKP\linkAction\LinkAction;
use PKP\linkAction\request\AjaxModal;
class SendReminderLinkAction extends LinkAction
{
/**
* Constructor
*
* @param Request $request
* @param array $actionArgs The action arguments.
*/
public function __construct($request, $modalTitle, $actionArgs)
{
// Instantiate the send review modal.
$router = $request->getRouter();
$ajaxModal = new AjaxModal(
$router->url($request, null, null, 'editReminder', null, $actionArgs),
__($modalTitle),
'review_reminder'
);
// Configure the link action.
parent::__construct(
'sendReminder',
$ajaxModal,
__('editor.review.sendReminder'),
'overdue'
);
}
}
@@ -0,0 +1,50 @@
<?php
/**
* @file controllers/api/task/SendThankYouLinkAction.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 SendThankYouLinkAction
*
* @ingroup controllers_api_task
*
* @brief An action to open up a modal to send a thank you email to users assigned to a review task.
*/
namespace PKP\controllers\api\task;
use APP\core\Request;
use PKP\linkAction\LinkAction;
use PKP\linkAction\request\AjaxModal;
class SendThankYouLinkAction extends LinkAction
{
/**
* Constructor
*
* @param Request $request
* @param array $actionArgs The action arguments.
*/
public function __construct($request, $modalTitle, $actionArgs)
{
// Instantiate the send thank you modal.
$router = $request->getRouter();
$ajaxModal = new AjaxModal(
$router->url($request, null, null, 'editThankReviewer', null, $actionArgs),
__($modalTitle),
'modal_email'
);
// Configure the link action.
parent::__construct(
'thankReviewer',
$ajaxModal,
__('editor.review.thankReviewer'),
'accepted'
);
}
}
@@ -0,0 +1,67 @@
<?php
/**
* @defgroup controllers_api_user User API controller
*/
/**
* @file controllers/api/user/UserApiHandler.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 UserApiHandler
*
* @ingroup controllers_api_user
*
* @brief Class defining the headless AJAX API for backend user manipulation.
*/
namespace PKP\controllers\api\user;
use PKP\core\JSONMessage;
use PKP\core\PKPRequest;
use PKP\handler\PKPHandler;
use PKP\security\authorization\PKPSiteAccessPolicy;
use PKP\security\Validation;
class UserApiHandler extends PKPHandler
{
//
// Implement template methods from PKPHandler
//
/**
* @copydoc PKPHandler::authorize()
*/
public function authorize($request, &$args, $roleAssignments)
{
$this->addPolicy(new PKPSiteAccessPolicy(
$request,
['suggestUsername'],
PKPSiteAccessPolicy::SITE_ACCESS_ALL_ROLES
));
return parent::authorize($request, $args, $roleAssignments);
}
//
// Public handler methods
//
/**
* Get a suggested username, making sure it's not already used.
*
* @param array $args
* @param PKPRequest $request
*
* @return JSONMessage JSON object
*/
public function suggestUsername($args, $request)
{
$suggestion = Validation::suggestUsername(
$request->getUserVar('givenName'),
$request->getUserVar('familyName')
);
return new JSONMessage(true, $suggestion);
}
}