[ Mini Kiebo ]
Server: Windows NT DESKTOP-5B8S0D4 6.2 build 9200 (Windows 8 Professional Edition) i586
Path:
D:
/
Backup
/
05122024
/
htdocs
/
jurnal-kesmas
/
v1
/
lib
/
pkp
/
controllers
/
grid
/
queries
/
form
/
[
Home
]
File: QueryForm.php
<?php /** * @file controllers/grid/queries/form/QueryForm.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 QueryForm * * @ingroup controllers_grid_users_queries_form * * @brief Form for adding/editing a new query */ namespace PKP\controllers\grid\queries\form; use APP\core\Application; use APP\core\Request; use APP\facades\Repo; use APP\template\TemplateManager; use Illuminate\Support\Facades\Mail; use PKP\controllers\grid\queries\traits\StageMailable; use PKP\core\Core; use PKP\core\PKPApplication; use PKP\core\PKPRequest; use PKP\db\DAORegistry; use PKP\form\Form; use PKP\note\NoteDAO; use PKP\notification\NotificationDAO; use PKP\query\Query; use PKP\query\QueryDAO; use PKP\security\Role; use PKP\stageAssignment\StageAssignmentDAO; use PKP\submission\reviewAssignment\ReviewAssignment; use PKP\submission\reviewAssignment\ReviewAssignmentDAO; class QueryForm extends Form { use StageMailable; /** @var int Application::ASSOC_TYPE_... */ public $_assocType; /** @var int Assoc ID (per _assocType) */ public $_assocId; /** @var int The stage id associated with the query being edited */ public $_stageId; /** @var Query The query being edited */ public $_query; /** @var bool True iff this is a newly-created query */ public $_isNew; /** * Constructor. * * @param Request $request * @param int $assocType Application::ASSOC_TYPE_... * @param int $assocId Assoc ID (per assocType) * @param int $stageId WORKFLOW_STAGE_... * @param int $queryId Optional query ID to edit. If none provided, a * (potentially temporary) query will be created. */ public function __construct($request, $assocType, $assocId, $stageId, $queryId = null) { parent::__construct('controllers/grid/queries/form/queryForm.tpl'); $this->setStageId($stageId); $queryDao = DAORegistry::getDAO('QueryDAO'); /** @var QueryDAO $queryDao */ if (!$queryId) { $this->_isNew = true; // Create a query $query = $queryDao->newDataObject(); $query->setAssocType($assocType); $query->setAssocId($assocId); $query->setStageId($stageId); $query->setSequence(REALLY_BIG_NUMBER); $queryDao->insertObject($query); $queryDao->resequence($assocType, $assocId); // Add the current user as a participant by default. $queryDao->insertParticipant($query->getId(), $request->getUser()->getId()); // Create a head note $noteDao = DAORegistry::getDAO('NoteDAO'); /** @var NoteDAO $noteDao */ $headNote = $noteDao->newDataObject(); $headNote->setUserId($request->getUser()->getId()); $headNote->setAssocType(Application::ASSOC_TYPE_QUERY); $headNote->setAssocId($query->getId()); $headNote->setDateCreated(Core::getCurrentDate()); $noteDao->insertObject($headNote); } else { $query = $queryDao->getById($queryId, $assocType, $assocId); assert(isset($query)); // New queries will not have a head note. $this->_isNew = !$query->getHeadNote(); } $this->setQuery($query); // Validation checks for this form $this->addCheck(new \PKP\form\validation\FormValidatorCustom($this, 'users', 'required', 'stageParticipants.notify.warning', function ($users) { return count($users) > 1; })); $this->addCheck(new \PKP\form\validation\FormValidator($this, 'subject', 'required', 'submission.queries.subjectRequired')); $this->addCheck(new \PKP\form\validation\FormValidator($this, 'comment', 'required', 'submission.queries.messageRequired')); $this->addCheck(new \PKP\form\validation\FormValidatorPost($this)); $this->addCheck(new \PKP\form\validation\FormValidatorCSRF($this)); } // // Getters and Setters // /** * Set the flag indicating whether the query is new (i.e. creates a placeholder that needs deleting on cancel) * */ public function setIsNew(bool $isNew) { $this->_isNew = $isNew; } /** * Get the query * * @return Query */ public function getQuery() { return $this->_query; } /** * Set the query * * @param Query $query */ public function setQuery($query) { $this->_query = $query; } /** * Get the stage id * * @return int */ public function getStageId() { return $this->_stageId; } /** * Set the stage id * * @param int $stageId */ public function setStageId($stageId) { $this->_stageId = $stageId; } /** * Get assoc type * * @return int Application::ASSOC_TYPE_... */ public function getAssocType() { return $this->getData('assocType'); } /** * Set assoc type * * @param int $assocType Application::ASSOC_TYPE_... */ public function setAssocType($assocType) { $this->setData('assocType', $assocType); } /** * Get assoc id * * @return int */ public function getAssocId() { return $this->getData('assocId'); } /** * Set assoc id * * @param int $assocId */ public function setAssocId($assocId) { $this->setData('assocId', $assocId); } // // Overridden template methods // /** * Initialize form data from the associated author. */ public function initData() { $queryDao = DAORegistry::getDAO('QueryDAO'); /** @var QueryDAO $queryDao */ if ($query = $this->getQuery()) { $headNote = $query->getHeadNote(); $this->_data = [ 'queryId' => $query->getId(), 'subject' => $headNote ? $headNote->getTitle() : null, 'comment' => $headNote ? $headNote->getContents() : null, 'userIds' => $queryDao->getParticipantIds($query->getId()), 'template' => null, ]; } else { // set initial defaults for queries. } // in order to be able to use the hook return parent::initData(); } /** * Fetch the form. * * @see Form::fetch() * * @param PKPRequest $request * @param array $actionArgs Optional list of additional arguments * @param null|mixed $template */ public function fetch($request, $template = null, $display = false, $actionArgs = []) { $query = $this->getQuery(); $headNote = $query->getHeadNote(); $user = $request->getUser(); $context = $request->getContext(); $templateMgr = TemplateManager::getManager($request); $templateMgr->assign([ 'isNew' => $this->_isNew, 'noteId' => $headNote->getId(), 'actionArgs' => $actionArgs, 'csrfToken' => $request->getSession()->getCSRFToken(), 'stageId' => $this->getStageId(), 'assocId' => $query->getAssocId(), 'assocType' => $query->getAssocType(), ]); // Queries only support Application::ASSOC_TYPE_SUBMISSION so far if ($query->getAssocType() !== PKPApplication::ASSOC_TYPE_SUBMISSION) { return parent::fetch($request, $template, $display); } $submission = Repo::submission()->get($query->getAssocId()); // Add the templates that can be used for this discussion $templateKeySubjectPairs = []; if ($user->hasRole([Role::ROLE_ID_MANAGER, Role::ROLE_ID_SUB_EDITOR, Role::ROLE_ID_ASSISTANT], $context->getId())) { $mailable = $this->getStageMailable($context, $submission); $data = $mailable->getData(); $defaultTemplate = Repo::emailTemplate()->getByKey($context->getId(), $mailable::getEmailTemplateKey()); $templateKeySubjectPairs = [$mailable::getEmailTemplateKey() => $defaultTemplate->getLocalizedData('name')]; $alternateTemplates = Repo::emailTemplate()->getCollector($context->getId()) ->alternateTo([$mailable::getEmailTemplateKey()]) ->getMany(); foreach ($alternateTemplates as $alternateTemplate) { $templateKeySubjectPairs[$alternateTemplate->getData('key')] = Mail::compileParams( $alternateTemplate->getLocalizedData('name'), $data ); } } $templateMgr->assign('templates', $templateKeySubjectPairs); $stageAssignmentDao = DAORegistry::getDAO('StageAssignmentDAO'); /** @var StageAssignmentDAO $stageAssignmentDao */ // Get currently selected participants in the query $queryDao = DAORegistry::getDAO('QueryDAO'); /** @var QueryDAO $queryDao */ $assignedParticipants = $query->getId() ? $queryDao->getParticipantIds($query->getId()) : []; // Always include current user, even if not with a stage assignment $includeUsers[] = $user->getId(); $excludeUsers = null; // When in review stage, include/exclude users depending on the current users role $reviewAssignments = []; // Get current users roles $assignedRoles = (function () use ($stageAssignmentDao, $query, $user) { $assignedRoles = []; $usersAssignments = $stageAssignmentDao->getBySubmissionAndStageId($query->getAssocId(), $query->getStageId(), null, $user->getId()); while ($usersAssignment = $usersAssignments->next()) { $userGroup = Repo::userGroup()->get($usersAssignment->getUserGroupId()); $assignedRoles[] = $userGroup->getRoleId(); } return $assignedRoles; })(); if ($query->getStageId() == WORKFLOW_STAGE_ID_EXTERNAL_REVIEW || $query->getStageId() == WORKFLOW_STAGE_ID_INTERNAL_REVIEW) { // Get all review assignments for current submission $reviewAssignmentDao = DAORegistry::getDAO('ReviewAssignmentDAO'); /** @var ReviewAssignmentDAO $reviewAssignmentDao */ $reviewAssignments = $reviewAssignmentDao->getBySubmissionId($submission->getId()); // if current user is editor/journal manager/site admin and not have author role , add all reviewers if (array_intersect($assignedRoles, [Role::ROLE_ID_MANAGER, Role::ROLE_ID_SUB_EDITOR]) || (empty($assignedRoles) && ($user->hasRole([Role::ROLE_ID_MANAGER], $context->getId()) || $user->hasRole([Role::ROLE_ID_SITE_ADMIN], PKPApplication::CONTEXT_SITE)))) { foreach ($reviewAssignments as $reviewAssignment) { $includeUsers[] = $reviewAssignment->getReviewerId(); } } // if current user is an anonymous reviewer, filter out authors foreach ($reviewAssignments as $reviewAssignment) { if ($reviewAssignment->getReviewerId() == $user->getId()) { if ($reviewAssignment->getReviewMethod() != ReviewAssignment::SUBMISSION_REVIEW_METHOD_OPEN) { $authorAssignments = $stageAssignmentDao->getBySubmissionAndRoleId($query->getAssocId(), Role::ROLE_ID_AUTHOR); while ($assignment = $authorAssignments->next()) { $excludeUsers[] = $assignment->getUserId(); } } } } // if current user is author, add open reviewers who have accepted the request if (array_intersect([Role::ROLE_ID_AUTHOR], $assignedRoles)) { foreach ($reviewAssignments as $reviewAssignment) { if ($reviewAssignment->getReviewMethod() == ReviewAssignment::SUBMISSION_REVIEW_METHOD_OPEN && $reviewAssignment->getDateConfirmed() && !$reviewAssignment->getDeclined()) { $includeUsers[] = $reviewAssignment->getReviewerId(); } } } } $usersIterator = Repo::user()->getCollector() ->filterByContextIds([$context->getId()]) ->limit(100) ->offset(0) ->assignedTo($query->getAssocId(), $query->getStageId()) ->excludeUserIds($excludeUsers) ->getMany(); $includedUsersIterator = Repo::user()->getCollector()->filterByUserIds($includeUsers)->getMany(); $usersIterator = $usersIterator->merge($includedUsersIterator); $allParticipants = []; foreach ($usersIterator as $user) { $allUserGroups = Repo::userGroup()->userUserGroups($user->getId(), $context->getId()); $userRoles = []; $userAssignments = $stageAssignmentDao->getBySubmissionAndStageId($query->getAssocId(), $query->getStageId(), null, $user->getId())->toArray(); foreach ($userAssignments as $userAssignment) { foreach ($allUserGroups as $userGroup) { if ($userGroup->getId() == $userAssignment->getUserGroupId()) { $userRoles[] = $userGroup->getLocalizedName(); } } } foreach ($reviewAssignments as $assignment) { if ($assignment->getReviewerId() == $user->getId()) { $userRoles[] = __('user.role.reviewer') . ' (' . __($assignment->getReviewMethodKey()) . ')'; } } if (!count($userRoles)) { $userRoles[] = __('submission.status.unassigned'); } $allParticipants[$user->getId()] = __('submission.query.participantTitle', [ 'fullName' => $user->getFullName(), 'userGroup' => join(__('common.commaListSeparator'), $userRoles), ]); } // Notify assistants, authors and reviewers that they have x minutes to update their own discussion $allowedEditTimeNotice = ['show' => false, 'limit' => 60]; if (array_intersect($assignedRoles, [Role::ROLE_ID_ASSISTANT, Role::ROLE_ID_AUTHOR, Role::ROLE_ID_REVIEWER])) { $allowedEditTimeNotice['show'] = true; $allowedEditTimeNotice['limit'] = (int) ($allowedEditTimeNotice['limit'] - (time() - strtotime($headNote->getDateCreated())) / 60); } $templateMgr->assign([ 'allParticipants' => $allParticipants, 'assignedParticipants' => $assignedParticipants, 'allowedEditTimeNotice' => $allowedEditTimeNotice, ]); return parent::fetch($request, $template, $display); } /** * Assign form data to user-submitted data. * * @see Form::readInputData() */ public function readInputData() { $this->readUserVars([ 'subject', 'comment', 'users', 'template', ]); } /** * @copydoc Form::validate() */ public function validate($callHooks = true) { // Display error if anonymity is impacted in a review stage: // 1) several blind reviewers are selected, or // 2) a blind reviewer and another participant (other than editor or assistant) are selected. // Editors and assistants are ignored, they can see everything. // Also admin and manager, if they are creating the discussion, are ignored -- they can see everything. // In other stages validate that participants are assigned to that stage. $query = $this->getQuery(); // Queries only support Application::ASSOC_TYPE_SUBMISSION so far (see above) if ($query->getAssocType() == Application::ASSOC_TYPE_SUBMISSION) { $request = Application::get()->getRequest(); $user = $request->getUser(); $context = $request->getContext(); $submissionId = $query->getAssocId(); $stageId = $query->getStageId(); $reviewAssignmentDao = DAORegistry::getDAO('ReviewAssignmentDAO'); /** @var ReviewAssignmentDAO $reviewAssignmentDao */ $stageAssignmentDao = DAORegistry::getDAO('StageAssignmentDAO'); /** @var StageAssignmentDAO $stageAssignmentDao */ // get the selected participants $newParticipantIds = (array) $this->getData('users'); $participantsToConsider = $blindReviewerCount = 0; foreach ($newParticipantIds as $participantId) { // get participant roles in this workflow stage $assignedRoles = []; $usersAssignments = $stageAssignmentDao->getBySubmissionAndStageId($submissionId, $stageId, null, $participantId); while ($usersAssignment = $usersAssignments->next()) { $userGroup = Repo::userGroup()->get($usersAssignment->getUserGroupId()); $assignedRoles[] = $userGroup->getRoleId(); } if ($stageId == WORKFLOW_STAGE_ID_EXTERNAL_REVIEW || $stageId == WORKFLOW_STAGE_ID_INTERNAL_REVIEW) { // validate the anonymity // get participant review assignments $reviewAssignments = $reviewAssignmentDao->getBySubmissionReviewer($submissionId, $participantId, $stageId); // if participant has no role in this stage and is not a reviewer if (empty($assignedRoles) && empty($reviewAssignments)) { // if participant is current user and the user has admin or manager role, ignore participant if (($participantId == $user->getId()) && ($user->hasRole([Role::ROLE_ID_SITE_ADMIN], PKPApplication::CONTEXT_SITE) || $user->hasRole([Role::ROLE_ID_MANAGER], $context->getId()))) { continue; } else { $this->addError('users', __('editor.discussion.errorNotStageParticipant')); $this->addErrorField('users'); break; } } // is participant a blind reviewer $blindReviewer = false; foreach ($reviewAssignments as $reviewAssignment) { if ($reviewAssignment->getReviewMethod() != ReviewAssignment::SUBMISSION_REVIEW_METHOD_OPEN) { $blindReviewerCount++; $blindReviewer = true; break; } } // if participant is not a blind reviewer and has a role different than editor or assistant if (!$blindReviewer && !array_intersect([Role::ROLE_ID_MANAGER, Role::ROLE_ID_SUB_EDITOR, Role::ROLE_ID_ASSISTANT], $assignedRoles)) { $participantsToConsider++; } // if anonymity is impacted, display error if (($blindReviewerCount > 1) || ($blindReviewerCount > 0 && $participantsToConsider > 0)) { $this->addError('users', __('editor.discussion.errorAnonymousParticipants')); $this->addErrorField('users'); break; } } else { // if participant has no role/assignment in the current stage if (empty($assignedRoles)) { // if participant is current user and the user has admin or manager role, ignore participant if (($participantId == $user->getId()) && ($user->hasRole([Role::ROLE_ID_SITE_ADMIN], PKPApplication::CONTEXT_SITE) || $user->hasRole([Role::ROLE_ID_MANAGER], $context->getId()))) { continue; } else { $this->addError('users', __('editor.discussion.errorNotStageParticipant')); $this->addErrorField('users'); break; } } } } } return parent::validate($callHooks); } /** * @copydoc Form::execute() */ public function execute(...$functionArgs) { $request = Application::get()->getRequest(); $queryDao = DAORegistry::getDAO('QueryDAO'); /** @var QueryDAO $queryDao */ $query = $this->getQuery(); $headNote = $query->getHeadNote(); $headNote->setTitle($this->getData('subject')); $headNote->setContents($this->getData('comment')); $noteDao = DAORegistry::getDAO('NoteDAO'); /** @var NoteDAO $noteDao */ $noteDao->updateObject($headNote); $queryDao->updateObject($query); // Update participants $oldParticipantIds = $queryDao->getParticipantIds($query->getId()); $newParticipantIds = $this->getData('users'); $queryDao->removeAllParticipants($query->getId()); foreach ($newParticipantIds as $userId) { $queryDao->insertParticipant($query->getId(), $userId); } $removed = array_diff($oldParticipantIds, $newParticipantIds); foreach ($removed as $userId) { // Delete this users' notifications relating to this query $notificationDao = DAORegistry::getDAO('NotificationDAO'); /** @var NotificationDAO $notificationDao */ $notificationDao->deleteByAssoc(Application::ASSOC_TYPE_QUERY, $query->getId(), $userId); } // Stamp the submission status modification date. if ($query->getAssocType() == Application::ASSOC_TYPE_SUBMISSION) { $submission = Repo::submission()->get($query->getAssocId()); $submission->stampLastActivity(); Repo::submission()->dao->update($submission); } parent::execute(...$functionArgs); } }