| 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/ |
Upload File : |
<?php
/**
* @file controllers/grid/queries/QueriesGridHandler.inc.php
*
* Copyright (c) 2016-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 QueriesGridHandler
* @ingroup controllers_grid_query
*
* @brief base PKP class to handle query grid requests.
*/
// import grid base classes
import('lib.pkp.classes.controllers.grid.GridHandler');
// Link action & modal classes
import('lib.pkp.classes.linkAction.request.AjaxModal');
class QueriesGridHandler extends GridHandler {
/** @var integer WORKFLOW_STAGE_ID_... */
var $_stageId;
/** @var PKPRequest */
var $_request;
/**
* Constructor
*/
function __construct() {
parent::__construct();
$this->addRoleAssignment(
array(ROLE_ID_MANAGER, ROLE_ID_SUB_EDITOR, ROLE_ID_ASSISTANT, ROLE_ID_REVIEWER, ROLE_ID_AUTHOR),
array('fetchGrid', 'fetchRow', 'readQuery', 'participants', 'addQuery', 'editQuery', 'updateQuery', 'deleteQuery'));
$this->addRoleAssignment(
array(ROLE_ID_MANAGER, ROLE_ID_SUB_EDITOR, ROLE_ID_ASSISTANT),
array('openQuery', 'closeQuery', 'saveSequence'));
$this->addRoleAssignment(
array(ROLE_ID_MANAGER),
array('leaveQuery'));
}
//
// Getters/Setters
//
/**
* Get the authorized submission.
* @return Submission
*/
function getSubmission() {
return $this->getAuthorizedContextObject(ASSOC_TYPE_SUBMISSION);
}
/**
* Get the authorized query.
* @return Query
*/
function getQuery() {
return $this->getAuthorizedContextObject(ASSOC_TYPE_QUERY);
}
/**
* Get the stage id.
* @return integer
*/
function getStageId() {
return $this->_stageId;
}
/**
* Get the query assoc type.
* @return int ASSOC_TYPE_...
*/
function getAssocType() {
return ASSOC_TYPE_SUBMISSION;
}
/**
* Get the query assoc ID.
* @return int
*/
function getAssocId() {
return $this->getSubmission()->getId();
}
/**
* Create and return a data provider for this grid.
* @return GridCellProvider
*/
function getCellProvider() {
import('lib.pkp.controllers.grid.queries.QueriesGridCellProvider');
return new QueriesGridCellProvider(
$this->getSubmission(),
$this->getStageId(),
$this->getAccessHelper()
);
}
//
// Overridden methods from PKPHandler.
// Note: this is subclassed in application-specific grids.
//
/**
* @copydoc PKPHandler::authorize()
*/
function authorize($request, &$args, $roleAssignments) {
$this->_stageId = (int) $request->getUserVar('stageId'); // This is being validated in WorkflowStageAccessPolicy
$this->_request = $request;
if ($request->getUserVar('queryId')) {
import('lib.pkp.classes.security.authorization.QueryAccessPolicy');
$this->addPolicy(new QueryAccessPolicy($request, $args, $roleAssignments, $this->_stageId));
} else {
import('lib.pkp.classes.security.authorization.QueryWorkflowStageAccessPolicy');
$this->addPolicy(new QueryWorkflowStageAccessPolicy($request, $args, $roleAssignments, 'submissionId', $this->_stageId));
}
return parent::authorize($request, $args, $roleAssignments);
}
/**
* @copydoc GridHandler::initialize()
*/
function initialize($request, $args = null) {
parent::initialize($request, $args);
import('lib.pkp.controllers.grid.queries.QueriesGridCellProvider');
switch ($this->getStageId()) {
case WORKFLOW_STAGE_ID_SUBMISSION: $this->setTitle('submission.queries.submission'); break;
case WORKFLOW_STAGE_ID_EDITING: $this->setTitle('submission.queries.editorial'); break;
case WORKFLOW_STAGE_ID_PRODUCTION: $this->setTitle('submission.queries.production'); break;
case WORKFLOW_STAGE_ID_INTERNAL_REVIEW:
case WORKFLOW_STAGE_ID_EXTERNAL_REVIEW:
$this->setTitle('submission.queries.review');
break;
default: assert(false);
}
// Load pkp-lib translations
AppLocale::requireComponents(
LOCALE_COMPONENT_PKP_SUBMISSION,
LOCALE_COMPONENT_PKP_USER,
LOCALE_COMPONENT_PKP_EDITOR,
LOCALE_COMPONENT_APP_SUBMISSION
);
// Columns
import('lib.pkp.controllers.grid.queries.QueryTitleGridColumn');
$cellProvider = $this->getCellProvider();
$this->addColumn(new QueryTitleGridColumn($this->getRequestArgs()));
$this->addColumn(new GridColumn(
'from',
'submission.query.from',
null,
null,
$cellProvider,
array('html' => TRUE, 'width' => 20)
));
$this->addColumn(new GridColumn(
'lastReply',
'submission.query.lastReply',
null,
null,
$cellProvider,
array('html' => TRUE, 'width' => 20)
));
$this->addColumn(new GridColumn(
'replies',
'submission.query.replies',
null,
null,
$cellProvider,
array('width' => 10, 'alignment' => COLUMN_ALIGNMENT_CENTER)
));
$this->addColumn(
new GridColumn(
'closed',
'submission.query.closed',
null,
'controllers/grid/common/cell/selectStatusCell.tpl',
$cellProvider,
array('width' => 10, 'alignment' => COLUMN_ALIGNMENT_CENTER)
)
);
$router = $request->getRouter();
if ($this->getAccessHelper()->getCanCreate($this->getStageId())) $this->addAction(new LinkAction(
'addQuery',
new AjaxModal(
$router->url($request, null, null, 'addQuery', null, $this->getRequestArgs()),
__('grid.action.addQuery'),
'modal_add_item'
),
__('grid.action.addQuery'),
'add_item'
));
}
//
// Overridden methods from GridHandler
//
/**
* @copydoc GridHandler::initFeatures()
*/
function initFeatures($request, $args) {
$features = parent::initFeatures($request, $args);
if ($this->getAccessHelper()->getCanOrder($this->getStageId())) {
import('lib.pkp.classes.controllers.grid.feature.OrderGridItemsFeature');
$features[] = new OrderGridItemsFeature();
}
return $features;
}
/**
* @copydoc GridHandler::getDataElementSequence()
*/
function getDataElementSequence($row) {
return $row->getSequence();
}
/**
* @copydoc GridHandler::setDataElementSequence()
*/
function setDataElementSequence($request, $rowId, $gridDataElement, $newSequence) {
$queryDao = DAORegistry::getDAO('QueryDAO'); /* @var $queryDao QueryDAO */
$query = $queryDao->getById($rowId, $this->getAssocType(), $this->getAssocId());
$query->setSequence($newSequence);
$queryDao->updateObject($query);
}
/**
* @copydoc GridHandler::getRowInstance()
* @return QueriesGridRow
*/
function getRowInstance() {
import('lib.pkp.controllers.grid.queries.QueriesGridRow');
return new QueriesGridRow(
$this->getSubmission(),
$this->getStageId(),
$this->getAccessHelper()
);
}
/**
* Get an instance of the queries grid access helper
* @return QueriesGridAccessHelper
*/
function getAccessHelper() {
import('lib.pkp.controllers.grid.queries.QueriesAccessHelper');
return new QueriesAccessHelper($this->getAuthorizedContext(), $this->_request->getUser());
}
/**
* Get the arguments that will identify the data in the grid.
* Overridden by child grids.
* @return array
*/
function getRequestArgs() {
return array(
'submissionId' => $this->getSubmission()->getId(),
'stageId' => $this->getStageId(),
);
}
/**
* @copydoc GridHandler::loadData()
*/
function loadData($request, $filter = null) {
$queryDao = DAORegistry::getDAO('QueryDAO'); /* @var $queryDao QueryDAO */
return $queryDao->getByAssoc(
$this->getAssocType(),
$this->getAssocId(),
$this->getStageId(),
$this->getAccessHelper()->getCanListAll($this->getStageId())?null:$request->getUser()->getId()
);
}
//
// Public Query Grid Actions
//
/**
* Add a query
* @param $args array
* @param $request PKPRequest
* @return JSONMessage JSON object
*/
function addQuery($args, $request) {
if (!$this->getAccessHelper()->getCanCreate($this->getStageId())) return new JSONMessage(false);
import('lib.pkp.controllers.grid.queries.form.QueryForm');
$queryForm = new QueryForm(
$request,
$this->getAssocType(),
$this->getAssocId(),
$this->getStageId()
);
$queryForm->initData();
return new JSONMessage(true, $queryForm->fetch($request, null, false, $this->getRequestArgs()));
}
/**
* Delete a query.
* @param $args array
* @param $request PKPRequest
* @return JSONMessage JSON object
*/
function deleteQuery($args, $request) {
$query = $this->getQuery();
if (!$request->checkCSRF() || !$query || !$this->getAccessHelper()->getCanDelete($query->getId())) return new JSONMessage(false);
$queryDao = DAORegistry::getDAO('QueryDAO'); /* @var $queryDao QueryDAO */
$queryDao->deleteObject($query);
$notificationDao = DAORegistry::getDAO('NotificationDAO'); /* @var $notificationDao NotificationDAO */
$notificationDao->deleteByAssoc(ASSOC_TYPE_QUERY, $query->getId());
if ($this->getStageId() == WORKFLOW_STAGE_ID_EDITING ||
$this->getStageId() == WORKFLOW_STAGE_ID_PRODUCTION) {
// Update submission notifications
$notificationMgr = new NotificationManager();
$notificationMgr->updateNotification(
$request,
array(
NOTIFICATION_TYPE_ASSIGN_COPYEDITOR,
NOTIFICATION_TYPE_AWAITING_COPYEDITS,
NOTIFICATION_TYPE_ASSIGN_PRODUCTIONUSER,
NOTIFICATION_TYPE_AWAITING_REPRESENTATIONS,
),
null,
ASSOC_TYPE_SUBMISSION,
$this->getAssocId()
);
}
return DAO::getDataChangedEvent($query->getId());
}
/**
* Open a closed query.
* @param $args array
* @param $request PKPRequest
* @return JSONMessage JSON object
*/
function openQuery($args, $request) {
$query = $this->getQuery();
if (!$query || !$this->getAccessHelper()->getCanOpenClose($query)) return new JSONMessage(false);
$queryDao = DAORegistry::getDAO('QueryDAO'); /* @var $queryDao QueryDAO */
$query->setIsClosed(false);
$queryDao->updateObject($query);
return DAO::getDataChangedEvent($query->getId());
}
/**
* Close an open query.
* @param $args array
* @param $request PKPRequest
* @return JSONMessage JSON object
*/
function closeQuery($args, $request) {
$query = $this->getQuery();
if (!$query || !$this->getAccessHelper()->getCanOpenClose($query)) return new JSONMessage(false);
$queryDao = DAORegistry::getDAO('QueryDAO'); /* @var $queryDao QueryDAO */
$query->setIsClosed(true);
$queryDao->updateObject($query);
return DAO::getDataChangedEvent($query->getId());
}
/**
* Get the name of the query notes grid handler.
* @return string
*/
function getQueryNotesGridHandlerName() {
return 'grid.queries.QueryNotesGridHandler';
}
/**
* Read a query
* @param $args array
* @param $request PKPRequest
* @return JSONMessage JSON object
*/
function readQuery($args, $request) {
$query = $this->getQuery();
$router = $request->getRouter();
$user = $request->getUser();
$context = $request->getContext();
$actionArgs = array_merge($this->getRequestArgs(), array('queryId' => $query->getId()));
// If appropriate, create an Edit action for the participants list
if ($this->getAccessHelper()->getCanEdit($query->getId())) {
import('lib.pkp.classes.linkAction.request.AjaxModal');
$editAction = new LinkAction(
'editQuery',
new AjaxModal(
$router->url($request, null, null, 'editQuery', null, $actionArgs),
__('grid.action.updateQuery'),
'modal_edit'
),
__('grid.action.edit'),
'edit'
);
} else {
$editAction = null;
}
import('lib.pkp.classes.linkAction.request.RemoteActionConfirmationModal');
$leaveQueryLinkAction = new LinkAction(
'leaveQuery',
new RemoteActionConfirmationModal(
$request->getSession(),
__('submission.query.leaveQuery.confirm'),
__('submission.query.leaveQuery'),
$router->url($request, null, null, 'leaveQuery', null, $actionArgs),
'modal_delete'
),
__('submission.query.leaveQuery'),
'leaveQuery'
);
// Show leave query button for journal managers included in the query
if ($user && $this->_getCurrentUserCanLeave($query->getId())) {
$showLeaveQueryButton = true;
} else {
$showLeaveQueryButton = false;
}
$templateMgr = TemplateManager::getManager($request);
$templateMgr->assign(array(
'queryNotesGridHandlerName' => $this->getQueryNotesGridHandlerName(),
'requestArgs' => $this->getRequestArgs(),
'query' => $query,
'editAction' => $editAction,
'leaveQueryLinkAction' => $leaveQueryLinkAction,
'showLeaveQueryButton' => $showLeaveQueryButton,
));
return new JSONMessage(true, $templateMgr->fetch('controllers/grid/queries/readQuery.tpl'));
}
/**
* Fetch the list of participants for a query
* @param $args array
* @param $request PKPRequest
* @return JSONMessage JSON object
*/
function participants($args, $request) {
$query = $this->getQuery();
$queryDao = DAORegistry::getDAO('QueryDAO'); /* @var $queryDao QueryDAO */
$userDao = DAORegistry::getDAO('UserDAO'); /* @var $userDao UserDAO */
$context = $request->getContext();
$user = $request->getUser();
$participants = array();
foreach ($queryDao->getParticipantIds($query->getId()) as $userId) {
$participants[] = $userDao->getById($userId);
}
$templateMgr = TemplateManager::getManager($request);
$templateMgr->assign('participants', $participants);
if ($user && $this->_getCurrentUserCanLeave($query->getId())) {
$showLeaveQueryButton = true;
} else {
$showLeaveQueryButton = false;
}
$json = new JSONMessage();
$json->setStatus(true);
$json->setContent($templateMgr->fetch('controllers/grid/queries/participants.tpl'));
$json->setAdditionalAttributes(array('showLeaveQueryButton' => $showLeaveQueryButton));
return $json;
}
/**
* Edit a query
* @param $args array
* @param $request PKPRequest
* @return JSONMessage JSON object
*/
function editQuery($args, $request) {
$query = $this->getQuery();
if (!$this->getAccessHelper()->getCanEdit($query->getId())) return new JSONMessage(false);
// Form handling
import('lib.pkp.controllers.grid.queries.form.QueryForm');
$queryForm = new QueryForm(
$request,
$this->getAssocType(),
$this->getAssocId(),
$this->getStageId(),
$query->getId()
);
$queryForm->initData();
return new JSONMessage(true, $queryForm->fetch($request, null, false, $this->getRequestArgs()));
}
/**
* Save a query
* @param $args array
* @param $request PKPRequest
* @return JSONMessage JSON object
*/
function updateQuery($args, $request) {
$query = $this->getQuery();
if (!$this->getAccessHelper()->getCanEdit($query->getId())) return new JSONMessage(false);
import('lib.pkp.controllers.grid.queries.form.QueryForm');
$queryForm = new QueryForm(
$request,
$this->getAssocType(),
$this->getAssocId(),
$this->getStageId(),
$query->getId()
);
$queryForm->readInputData();
if ($queryForm->validate()) {
$queryForm->execute();
if ($this->getStageId() == WORKFLOW_STAGE_ID_EDITING ||
$this->getStageId() == WORKFLOW_STAGE_ID_PRODUCTION) {
// Update submission notifications
$notificationMgr = new NotificationManager();
$notificationMgr->updateNotification(
$request,
array(
NOTIFICATION_TYPE_ASSIGN_COPYEDITOR,
NOTIFICATION_TYPE_AWAITING_COPYEDITS,
NOTIFICATION_TYPE_ASSIGN_PRODUCTIONUSER,
NOTIFICATION_TYPE_AWAITING_REPRESENTATIONS,
),
null,
ASSOC_TYPE_SUBMISSION,
$this->getAssocId()
);
}
return DAO::getDataChangedEvent($query->getId());
}
// If this was new (placeholder) query that didn't validate, remember whether or not
// we need to delete it on cancellation.
if ($request->getUserVar('wasNew')) $queryForm->setIsNew(true);
return new JSONMessage(
true,
$queryForm->fetch(
$request,
null,
false,
array_merge(
$this->getRequestArgs(),
array('queryId' => $query->getId())
)
)
);
}
/**
* Leave query
* @param $args array
* @param $request PKPRequest
* @return JSONMessage JSON object
*/
function leaveQuery($args, $request) {
$queryId = $args['queryId'];
$user = $request->getUser();
$context = $request->getContext();
if ($user && $this->_getCurrentUserCanLeave($queryId)) {
$queryDao = DAORegistry::getDAO('QueryDAO'); /* @var $queryDao QueryDAO */
$queryDao->removeParticipant($queryId, $user->getId());
$json = new JSONMessage();
$json->setEvent('user-left-discussion');
} else {
$json = new JSONMessage(false);
}
return $json;
}
/**
* Check if the current user can leave a query. Only allow if query has more than two participants.
* @param $queryId int
* @return boolean
*/
function _getCurrentUserCanLeave($queryId) {
$userRoles = $this->getAuthorizedContextObject(ASSOC_TYPE_USER_ROLES);
if (!in_array(ROLE_ID_MANAGER, $userRoles)) {
return false;
}
$queryDao = DAORegistry::getDAO('QueryDAO'); /* @var $queryDao QueryDAO */
$participantIds = $queryDao->getParticipantIds($queryId);
if (count($participantIds) < 3) {
return false;
}
$user = Application::get()->getRequest()->getUser();
return in_array($user->getId(), $participantIds);
}
}