| Server IP : 195.134.90.114 / Your IP : 216.73.216.86 Web Server : Apache/2.4.58 System : Linux nepub 6.8.0-88-generic #89-Ubuntu SMP PREEMPT_DYNAMIC Sat Oct 11 01:02:46 UTC 2025 x86_64 User : www-data ( 33) PHP Version : 8.2.30 Disable Function : NONE MySQL : OFF | cURL : ON | WGET : ON | Perl : ON | Python : OFF | Sudo : ON | Pkexec : OFF Directory : /var/www/html/public_html/lib/pkp/controllers/grid/queries/form/ |
Upload File : |
<?php
/**
* @file controllers/grid/users/queries/form/QueryForm.inc.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
*/
import('lib.pkp.classes.form.Form');
class QueryForm extends Form {
/** @var int ASSOC_TYPE_... */
var $_assocType;
/** @var int Assoc ID (per _assocType) */
var $_assocId;
/** @var int The stage id associated with the query being edited **/
var $_stageId;
/** @var Query The query being edited **/
var $_query;
/** @var boolean True iff this is a newly-created query */
var $_isNew;
/**
* Constructor.
* @param $request Request
* @param $assocType int ASSOC_TYPE_...
* @param $assocId int Assoc ID (per assocType)
* @param $stageId int WORKFLOW_STAGE_...
* @param $queryId int Optional query ID to edit. If none provided, a
* (potentially temporary) query will be created.
*/
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(); /** @var Query $query */
$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(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 FormValidatorCustom($this, 'users', 'required', 'stageParticipants.notify.warning', function($users) {
return count($users) > 1;
}));
$this->addCheck(new FormValidator($this, 'subject', 'required', 'submission.queries.subjectRequired'));
$this->addCheck(new FormValidator($this, 'comment', 'required', 'submission.queries.messageRequired'));
$this->addCheck(new FormValidatorPost($this));
$this->addCheck(new FormValidatorCSRF($this));
}
//
// Getters and Setters
//
/**
* Set the flag indiciating whether the query is new (i.e. creates a placeholder that needs deleting on cancel)
* @param $isNew boolean
*/
function setIsNew($isNew) {
$this->_isNew = $isNew;
}
/**
* Get the query
* @return Query
*/
function getQuery() {
return $this->_query;
}
/**
* Set the query
* @param @query Query
*/
function setQuery($query) {
$this->_query = $query;
}
/**
* Get the stage id
* @return int
*/
function getStageId() {
return $this->_stageId;
}
/**
* Set the stage id
* @param int
*/
function setStageId($stageId) {
$this->_stageId = $stageId;
}
/**
* Get assoc type
* @return int ASSOC_TYPE_...
*/
function getAssocType() {
return $this->getData('assocType');
}
/**
* Set assoc type
* @param $assocType int ASSOC_TYPE_...
*/
function setAssocType($assocType) {
$this->setData('assocType', $assocType);
}
/**
* Get assoc id
* @return int
*/
function getAssocId() {
return $this->getData('assocId');
}
/**
* Set assoc id
* @param $assocId int
*/
function setAssocId($assocId) {
$this->setData('assocId', $assocId);
}
//
// Overridden template methods
//
/**
* Initialize form data from the associated author.
*/
function initData() {
$queryDao = DAORegistry::getDAO('QueryDAO'); /** @var QueryDAO $queryDao */
if ($query = $this->getQuery()) {
$headNote = $query->getHeadNote();
$this->_data = array(
'queryId' => $query->getId(),
'subject' => $headNote?$headNote->getTitle():null,
'comment' => $headNote?$headNote->getContents():null,
'userIds' => $queryDao->getParticipantIds($query->getId()),
);
} else {
// set intial defaults for queries.
}
// in order to be able to use the hook
return parent::initData();
}
/**
* Fetch the form.
* @see Form::fetch()
* @param $request PKPRequest
* @param $actionArgs array Optional list of additional arguments
*/
function fetch($request, $template = null, $display = false, $actionArgs = array()) {
AppLocale::requireComponents(LOCALE_COMPONENT_PKP_EDITOR);
$query = $this->getQuery();
$headNote = $query->getHeadNote();
$user = $request->getUser(); /** @var User $user */
$context = $request->getContext();
$templateMgr = TemplateManager::getManager($request);
$templateMgr->assign(array(
'isNew' => $this->_isNew,
'noteId' => $headNote->getId(),
'actionArgs' => $actionArgs,
'csrfToken' => $request->getSession()->getCSRFToken(),
));
// Queryies only support ASSOC_TYPE_SUBMISSION so far
if ($query->getAssocType() == ASSOC_TYPE_SUBMISSION) {
$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()) : array();
// 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 = array();
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($query->getAssocId());
// Get current users roles
$assignedRoles = [];
$usersAssignments = $stageAssignmentDao->getBySubmissionAndStageId($query->getAssocId(), $query->getStageId(), null, $user->getId());
while ($usersAssignment = $usersAssignments->next()) {
$userGroupDao = DAORegistry::getDAO('UserGroupDAO'); /** @var UserGroupDAO $userGroupDao */
$userGroup = $userGroupDao->getById($usersAssignment->getUserGroupId());
$assignedRoles[] = $userGroup->getRoleId();
}
// if current user is editor/journal manager/site admin and not have author role , add all reviewers
if ( array_intersect($assignedRoles, [ROLE_ID_MANAGER, ROLE_ID_SUB_EDITOR]) || ( empty($assignedRoles) && ( $user->hasRole([ROLE_ID_MANAGER], $context->getId()) || $user->hasRole([ROLE_ID_SITE_ADMIN], 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() != SUBMISSION_REVIEW_METHOD_OPEN){
$authorAssignments = $stageAssignmentDao->getBySubmissionAndRoleId($query->getAssocId(), 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(array(ROLE_ID_AUTHOR), $assignedRoles)) {
foreach ($reviewAssignments as $reviewAssignment) {
if ($reviewAssignment->getReviewMethod() == SUBMISSION_REVIEW_METHOD_OPEN && $reviewAssignment->getDateConfirmed() && !$reviewAssignment->getDeclined()) {
$includeUsers[] = $reviewAssignment->getReviewerId();
}
}
}
}
// Get list of participants to include in query
$params = [
'contextId' => $context->getId(),
'count' => 100, // high upper value
'offset' => 0,
'assignedToSubmission' => $query->getAssocId(),
'assignedToSubmissionStage' => $query->getStageId(),
'includeUsers' => $includeUsers,
'excludeUsers' => $excludeUsers,
];
$userService = Services::get('user');
$usersIterator = $userService->getMany($params);
$allParticipants = [];
$userGroupDao = DAORegistry::getDAO('UserGroupDAO'); /** @var UserGroupDAO $userGroupDao */
foreach ($usersIterator as $user) {
$allUserGroups = $userGroupDao->getByUserId($user->getId(), $context->getId())->toArray();
$userRoles = array();
$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),
]);
}
$templateMgr->assign([
'allParticipants' => $allParticipants,
'assignedParticipants' => $assignedParticipants,
]);
}
return parent::fetch($request, $template, $display);
}
/**
* Assign form data to user-submitted data.
* @see Form::readInputData()
*/
function readInputData() {
$this->readUserVars(array(
'subject',
'comment',
'users',
));
}
/**
* @copydoc Form::validate()
*/
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();
// Queryies only support ASSOC_TYPE_SUBMISSION so far (see above)
if ($query->getAssocType() == 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 */
$userGroupDao = DAORegistry::getDAO('UserGroupDAO'); /** @var UserGroupDAO $userGroupDao */
// 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 = $userGroupDao->getById($usersAssignment->getUserGroupId());
$assignedRoles[] = $userGroup->getRoleId();
}
if ($stageId == WORKFLOW_STAGE_ID_EXTERNAL_REVIEW || $stageId == WORKFLOW_STAGE_ID_INTERNAL_REVIEW) {
// validate the anonymity
// get participant review assignemnts
$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_ID_SITE_ADMIN], CONTEXT_SITE) || $user->hasRole([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() != 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_ID_MANAGER, ROLE_ID_SUB_EDITOR, 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_ID_SITE_ADMIN], CONTEXT_SITE) || $user->hasRole([ROLE_ID_MANAGER], $context->getId()))) {
continue;
} else {
$this->addError('users', __('editor.discussion.errorNotStageParticipant'));
$this->addErrorField('users');
break;
}
}
}
}
}
return parent::validate($callHooks);
}
/**
* @copydoc Form::execute()
*/
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);
}
// Update participant notifications
$notificationManager = new NotificationManager();
$removed = array_diff($oldParticipantIds, $newParticipantIds);
$added = array_diff($newParticipantIds, $oldParticipantIds);
foreach($removed as $userId) {
// Delete this users's notifications relating to this query
$notificationDao = DAORegistry::getDAO('NotificationDAO'); /** @var NotificationDAO $notificationDao */
$notificationDao->deleteByAssoc(ASSOC_TYPE_QUERY, $query->getId(), $userId);
}
$currentUser = $request->getUser();
foreach($added as $userId) {
// Skip sending a message to the current user.
if ($currentUser->getId() == $userId) {
continue;
}
$notificationManager->createNotification(
$request,
$userId,
NOTIFICATION_TYPE_NEW_QUERY,
$request->getContext()->getId(),
ASSOC_TYPE_QUERY,
$query->getId(),
NOTIFICATION_LEVEL_TASK
);
}
// Stamp the submission status modification date.
if ($query->getAssocType() == ASSOC_TYPE_SUBMISSION) {
$submission = Services::get('submission')->get($query->getAssocId());
$submission->stampLastActivity();
$submissionDao = DAORegistry::getDAO('SubmissionDAO'); /** @var SubmissionDAO $submissionDao */
$submissionDao->updateObject($submission);
}
parent::execute(...$functionArgs);
}
}