792 lines
25 KiB
PHP
792 lines
25 KiB
PHP
<?php
|
|
|
|
/**
|
|
* @file controllers/grid/queries/QueriesGridHandler.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.
|
|
*/
|
|
|
|
namespace PKP\controllers\grid\queries;
|
|
|
|
use APP\core\Application;
|
|
use APP\facades\Repo;
|
|
use APP\notification\Notification;
|
|
use APP\notification\NotificationManager;
|
|
use APP\submission\Submission;
|
|
use APP\template\TemplateManager;
|
|
use Illuminate\Support\Facades\Mail;
|
|
use PKP\controllers\grid\feature\OrderGridItemsFeature;
|
|
use PKP\controllers\grid\GridColumn;
|
|
use PKP\controllers\grid\GridHandler;
|
|
use PKP\controllers\grid\queries\form\QueryForm;
|
|
use PKP\controllers\grid\queries\traits\StageMailable;
|
|
use PKP\core\JSONMessage;
|
|
use PKP\core\PKPApplication;
|
|
use PKP\core\PKPRequest;
|
|
use PKP\db\DAORegistry;
|
|
use PKP\linkAction\LinkAction;
|
|
use PKP\linkAction\request\AjaxModal;
|
|
use PKP\linkAction\request\RemoteActionConfirmationModal;
|
|
use PKP\log\SubmissionEmailLogDAO;
|
|
use PKP\log\SubmissionEmailLogEntry;
|
|
use PKP\notification\NotificationDAO;
|
|
use PKP\notification\NotificationSubscriptionSettingsDAO;
|
|
use PKP\notification\PKPNotification;
|
|
use PKP\query\Query;
|
|
use PKP\query\QueryDAO;
|
|
use PKP\security\authorization\QueryAccessPolicy;
|
|
use PKP\security\authorization\QueryWorkflowStageAccessPolicy;
|
|
use PKP\security\Role;
|
|
use PKP\submissionFile\SubmissionFile;
|
|
|
|
class QueriesGridHandler extends GridHandler
|
|
{
|
|
use StageMailable;
|
|
|
|
/** @var int WORKFLOW_STAGE_ID_... */
|
|
public $_stageId;
|
|
|
|
/** @var PKPRequest */
|
|
public $_request;
|
|
|
|
/**
|
|
* 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],
|
|
['fetchGrid', 'fetchRow', 'readQuery', 'participants', 'addQuery', 'editQuery', 'updateQuery', 'deleteQuery']
|
|
);
|
|
$this->addRoleAssignment(
|
|
[Role::ROLE_ID_MANAGER, Role::ROLE_ID_SITE_ADMIN, Role::ROLE_ID_SUB_EDITOR, Role::ROLE_ID_ASSISTANT],
|
|
['openQuery', 'closeQuery', 'saveSequence', 'fetchTemplateBody']
|
|
);
|
|
$this->addRoleAssignment(
|
|
[Role::ROLE_ID_MANAGER, Role::ROLE_ID_SITE_ADMIN],
|
|
['leaveQuery']
|
|
);
|
|
}
|
|
|
|
|
|
//
|
|
// Getters/Setters
|
|
//
|
|
/**
|
|
* Get the authorized submission.
|
|
*
|
|
* @return Submission
|
|
*/
|
|
public function getSubmission()
|
|
{
|
|
return $this->getAuthorizedContextObject(PKPApplication::ASSOC_TYPE_SUBMISSION);
|
|
}
|
|
|
|
/**
|
|
* Get the authorized query.
|
|
*
|
|
* @return Query
|
|
*/
|
|
public function getQuery()
|
|
{
|
|
return $this->getAuthorizedContextObject(PKPApplication::ASSOC_TYPE_QUERY);
|
|
}
|
|
|
|
/**
|
|
* Get the stage id.
|
|
*
|
|
* @return int
|
|
*/
|
|
public function getStageId()
|
|
{
|
|
return $this->_stageId;
|
|
}
|
|
|
|
/**
|
|
* Get the query assoc type.
|
|
*
|
|
* @return int Application::ASSOC_TYPE_...
|
|
*/
|
|
public function getAssocType()
|
|
{
|
|
return PKPApplication::ASSOC_TYPE_SUBMISSION;
|
|
}
|
|
|
|
/**
|
|
* Get the query assoc ID.
|
|
*
|
|
* @return int
|
|
*/
|
|
public function getAssocId()
|
|
{
|
|
return $this->getSubmission()->getId();
|
|
}
|
|
|
|
/**
|
|
* Create and return a data provider for this grid.
|
|
*
|
|
* @return QueriesGridCellProvider
|
|
*/
|
|
public function getCellProvider()
|
|
{
|
|
return new QueriesGridCellProvider(
|
|
$this->getSubmission(),
|
|
$this->getStageId(),
|
|
$this->getAccessHelper()
|
|
);
|
|
}
|
|
|
|
|
|
//
|
|
// Overridden methods from PKPHandler.
|
|
// Note: this is subclassed in application-specific grids.
|
|
//
|
|
/**
|
|
* @copydoc PKPHandler::authorize()
|
|
*/
|
|
public function authorize($request, &$args, $roleAssignments)
|
|
{
|
|
$this->_stageId = (int) $request->getUserVar('stageId'); // This is being validated in WorkflowStageAccessPolicy
|
|
|
|
$this->_request = $request;
|
|
|
|
if ($request->getUserVar('queryId')) {
|
|
$this->addPolicy(new QueryAccessPolicy($request, $args, $roleAssignments, $this->_stageId));
|
|
} else {
|
|
$this->addPolicy(new QueryWorkflowStageAccessPolicy($request, $args, $roleAssignments, 'submissionId', $this->_stageId));
|
|
}
|
|
|
|
return parent::authorize($request, $args, $roleAssignments);
|
|
}
|
|
|
|
/**
|
|
* @copydoc GridHandler::initialize()
|
|
*
|
|
* @param null|mixed $args
|
|
*/
|
|
public function initialize($request, $args = null)
|
|
{
|
|
parent::initialize($request, $args);
|
|
|
|
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);
|
|
}
|
|
|
|
// Columns
|
|
$cellProvider = $this->getCellProvider();
|
|
$this->addColumn(new QueryTitleGridColumn($this->getRequestArgs()));
|
|
|
|
$this->addColumn(new GridColumn(
|
|
'from',
|
|
'submission.query.from',
|
|
null,
|
|
null,
|
|
$cellProvider,
|
|
['html' => true, 'width' => 20]
|
|
));
|
|
$this->addColumn(new GridColumn(
|
|
'lastReply',
|
|
'submission.query.lastReply',
|
|
null,
|
|
null,
|
|
$cellProvider,
|
|
['html' => true, 'width' => 20]
|
|
));
|
|
$this->addColumn(new GridColumn(
|
|
'replies',
|
|
'submission.query.replies',
|
|
null,
|
|
null,
|
|
$cellProvider,
|
|
['width' => 10, 'alignment' => GridColumn::COLUMN_ALIGNMENT_CENTER]
|
|
));
|
|
|
|
$this->addColumn(
|
|
new GridColumn(
|
|
'closed',
|
|
'submission.query.closed',
|
|
null,
|
|
'controllers/grid/common/cell/selectStatusCell.tpl',
|
|
$cellProvider,
|
|
['width' => 10, 'alignment' => GridColumn::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()
|
|
*/
|
|
public function initFeatures($request, $args)
|
|
{
|
|
$features = parent::initFeatures($request, $args);
|
|
if ($this->getAccessHelper()->getCanOrder($this->getStageId())) {
|
|
$features[] = new OrderGridItemsFeature();
|
|
}
|
|
return $features;
|
|
}
|
|
|
|
/**
|
|
* @copydoc GridHandler::getDataElementSequence()
|
|
*/
|
|
public function getDataElementSequence($row)
|
|
{
|
|
return $row->getSequence();
|
|
}
|
|
|
|
/**
|
|
* @copydoc GridHandler::setDataElementSequence()
|
|
*/
|
|
public 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
|
|
*/
|
|
public function getRowInstance()
|
|
{
|
|
return new QueriesGridRow(
|
|
$this->getSubmission(),
|
|
$this->getStageId(),
|
|
$this->getAccessHelper()
|
|
);
|
|
}
|
|
|
|
/**
|
|
* Get an instance of the queries grid access helper
|
|
*
|
|
* @return QueriesAccessHelper
|
|
*/
|
|
public function getAccessHelper()
|
|
{
|
|
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
|
|
*/
|
|
public function getRequestArgs()
|
|
{
|
|
return [
|
|
'submissionId' => $this->getSubmission()->getId(),
|
|
'stageId' => $this->getStageId(),
|
|
];
|
|
}
|
|
|
|
/**
|
|
* @copydoc GridHandler::loadData()
|
|
*
|
|
* @param null|mixed $filter
|
|
*/
|
|
public 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 array $args
|
|
* @param PKPRequest $request
|
|
*
|
|
* @return JSONMessage JSON object
|
|
*/
|
|
public function addQuery($args, $request)
|
|
{
|
|
if (!$this->getAccessHelper()->getCanCreate($this->getStageId())) {
|
|
return new JSONMessage(false);
|
|
}
|
|
|
|
$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 array $args
|
|
* @param PKPRequest $request
|
|
*
|
|
* @return JSONMessage JSON object
|
|
*/
|
|
public 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(PKPApplication::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,
|
|
[
|
|
PKPNotification::NOTIFICATION_TYPE_ASSIGN_COPYEDITOR,
|
|
PKPNotification::NOTIFICATION_TYPE_AWAITING_COPYEDITS,
|
|
PKPNotification::NOTIFICATION_TYPE_ASSIGN_PRODUCTIONUSER,
|
|
PKPNotification::NOTIFICATION_TYPE_AWAITING_REPRESENTATIONS,
|
|
],
|
|
null,
|
|
PKPApplication::ASSOC_TYPE_SUBMISSION,
|
|
$this->getAssocId()
|
|
);
|
|
}
|
|
|
|
return \PKP\db\DAO::getDataChangedEvent($query->getId());
|
|
}
|
|
|
|
/**
|
|
* Open a closed query.
|
|
*
|
|
* @param array $args
|
|
* @param PKPRequest $request
|
|
*
|
|
* @return JSONMessage JSON object
|
|
*/
|
|
public 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 \PKP\db\DAO::getDataChangedEvent($query->getId());
|
|
}
|
|
|
|
/**
|
|
* Close an open query.
|
|
*
|
|
* @param array $args
|
|
* @param PKPRequest $request
|
|
*
|
|
* @return JSONMessage JSON object
|
|
*/
|
|
public 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 \PKP\db\DAO::getDataChangedEvent($query->getId());
|
|
}
|
|
|
|
/**
|
|
* Get the name of the query notes grid handler.
|
|
*
|
|
* @return string
|
|
*/
|
|
public function getQueryNotesGridHandlerName()
|
|
{
|
|
return 'grid.queries.QueryNotesGridHandler';
|
|
}
|
|
|
|
/**
|
|
* Read a query
|
|
*
|
|
* @param array $args
|
|
* @param PKPRequest $request
|
|
*
|
|
* @return JSONMessage JSON object
|
|
*/
|
|
public function readQuery($args, $request)
|
|
{
|
|
$query = $this->getQuery();
|
|
$router = $request->getRouter();
|
|
$user = $request->getUser();
|
|
$context = $request->getContext();
|
|
|
|
$actionArgs = array_merge($this->getRequestArgs(), ['queryId' => $query->getId()]);
|
|
|
|
// If appropriate, create an Edit action for the participants list
|
|
if ($this->getAccessHelper()->getCanEdit($query->getId())) {
|
|
$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;
|
|
}
|
|
|
|
$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([
|
|
'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 array $args
|
|
* @param PKPRequest $request
|
|
*
|
|
* @return JSONMessage JSON object
|
|
*/
|
|
public function participants($args, $request)
|
|
{
|
|
$query = $this->getQuery();
|
|
$queryDao = DAORegistry::getDAO('QueryDAO'); /** @var QueryDAO $queryDao */
|
|
$context = $request->getContext();
|
|
$user = $request->getUser();
|
|
|
|
$participants = [];
|
|
foreach ($queryDao->getParticipantIds($query->getId()) as $userId) {
|
|
$user = Repo::user()->get($userId);
|
|
if ($user) {
|
|
$participants[] = $user;
|
|
}
|
|
}
|
|
|
|
$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(['showLeaveQueryButton' => $showLeaveQueryButton]);
|
|
return $json;
|
|
}
|
|
|
|
/**
|
|
* Edit a query
|
|
*
|
|
* @param array $args
|
|
* @param PKPRequest $request
|
|
*
|
|
* @return JSONMessage JSON object
|
|
*/
|
|
public function editQuery($args, $request)
|
|
{
|
|
$query = $this->getQuery();
|
|
if (!$this->getAccessHelper()->getCanEdit($query->getId())) {
|
|
return new JSONMessage(false);
|
|
}
|
|
|
|
// Form handling
|
|
$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 array $args
|
|
* @param PKPRequest $request
|
|
*
|
|
* @return JSONMessage JSON object
|
|
*/
|
|
public function updateQuery($args, $request)
|
|
{
|
|
$query = $this->getQuery();
|
|
if (!$this->getAccessHelper()->getCanEdit($query->getId())) {
|
|
return new JSONMessage(false);
|
|
}
|
|
/** @var QueryDAO */
|
|
$queryDao = DAORegistry::getDAO('QueryDAO');
|
|
$oldParticipantIds = $queryDao->getParticipantIds($query->getId());
|
|
|
|
$queryForm = new QueryForm(
|
|
$request,
|
|
$this->getAssocType(),
|
|
$this->getAssocId(),
|
|
$this->getStageId(),
|
|
$query->getId()
|
|
);
|
|
$queryForm->readInputData();
|
|
|
|
if ($queryForm->validate()) {
|
|
$queryForm->execute();
|
|
$notificationMgr = new NotificationManager();
|
|
|
|
if ($this->getStageId() == WORKFLOW_STAGE_ID_EDITING ||
|
|
$this->getStageId() == WORKFLOW_STAGE_ID_PRODUCTION) {
|
|
// Update submission notifications
|
|
$notificationMgr->updateNotification(
|
|
$request,
|
|
[
|
|
PKPNotification::NOTIFICATION_TYPE_ASSIGN_COPYEDITOR,
|
|
PKPNotification::NOTIFICATION_TYPE_AWAITING_COPYEDITS,
|
|
PKPNotification::NOTIFICATION_TYPE_ASSIGN_PRODUCTIONUSER,
|
|
PKPNotification::NOTIFICATION_TYPE_AWAITING_REPRESENTATIONS,
|
|
],
|
|
null,
|
|
PKPApplication::ASSOC_TYPE_SUBMISSION,
|
|
$this->getAssocId()
|
|
);
|
|
}
|
|
|
|
// Send notifications
|
|
$currentUser = $request->getUser();
|
|
$newParticipantIds = $queryForm->getData('users');
|
|
$added = array_diff($newParticipantIds, $oldParticipantIds);
|
|
// Don't notify the current user
|
|
if ($key = array_search($currentUser->getId(), $added)) {
|
|
unset($added[$key]);
|
|
}
|
|
|
|
/** @var NotificationSubscriptionSettingsDAO */
|
|
$notificationSubscriptionSettingsDao = DAORegistry::getDAO('NotificationSubscriptionSettingsDAO');
|
|
$note = $query->getHeadNote();
|
|
$submission = $this->getSubmission();
|
|
|
|
// Find attachments if any
|
|
$submissionFiles = Repo::submissionFile()
|
|
->getCollector()
|
|
->filterByAssoc(
|
|
PKPApplication::ASSOC_TYPE_NOTE,
|
|
[$note->getId()]
|
|
)->filterBySubmissionIds([$submission->getId()])
|
|
->getMany();
|
|
|
|
foreach ($added as $userId) {
|
|
$user = Repo::user()->get((int) $userId);
|
|
|
|
$notification = $notificationMgr->createNotification(
|
|
$request,
|
|
$userId,
|
|
PKPNotification::NOTIFICATION_TYPE_NEW_QUERY,
|
|
$request->getContext()->getId(),
|
|
PKPApplication::ASSOC_TYPE_QUERY,
|
|
$query->getId(),
|
|
Notification::NOTIFICATION_LEVEL_TASK
|
|
);
|
|
|
|
// Check if the user is unsubscribed
|
|
$notificationSubscriptionSettings = $notificationSubscriptionSettingsDao->getNotificationSubscriptionSettings(
|
|
NotificationSubscriptionSettingsDAO::BLOCKED_EMAIL_NOTIFICATION_KEY,
|
|
$user->getId(),
|
|
$request->getContext()->getId()
|
|
);
|
|
if (in_array(PKPNotification::NOTIFICATION_TYPE_NEW_QUERY, $notificationSubscriptionSettings)) {
|
|
continue;
|
|
}
|
|
|
|
$mailable = $this->getStageMailable($request->getContext(), $submission)
|
|
->sender($currentUser)
|
|
->recipients([$user])
|
|
->subject($note->getData('title'))
|
|
->body($note->getData('contents'))
|
|
->allowUnsubscribe($notification);
|
|
|
|
$submissionFiles->each(fn(SubmissionFile $item) => $mailable->attachSubmissionFile(
|
|
$item->getId(),
|
|
$item->getLocalizedData('name')
|
|
));
|
|
|
|
Mail::send($mailable);
|
|
$logDao = DAORegistry::getDAO('SubmissionEmailLogDAO'); /** @var SubmissionEmailLogDAO $logDao */
|
|
$logDao->logMailable(SubmissionEmailLogEntry::SUBMISSION_EMAIL_DISCUSSION_NOTIFY, $mailable, $submission);
|
|
}
|
|
|
|
return \PKP\db\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(),
|
|
['queryId' => $query->getId()]
|
|
)
|
|
)
|
|
);
|
|
}
|
|
|
|
/**
|
|
* Leave query
|
|
*
|
|
* @param array $args
|
|
* @param PKPRequest $request
|
|
*
|
|
* @return JSONMessage JSON object
|
|
*/
|
|
public function leaveQuery($args, $request)
|
|
{
|
|
$queryId = $args['queryId'];
|
|
$user = $request->getUser();
|
|
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 int $queryId
|
|
*
|
|
* @return bool
|
|
*/
|
|
public function _getCurrentUserCanLeave($queryId)
|
|
{
|
|
$userRoles = $this->getAuthorizedContextObject(PKPApplication::ASSOC_TYPE_USER_ROLES);
|
|
if (!count(array_intersect([Role::ROLE_ID_MANAGER, Role::ROLE_ID_SITE_ADMIN, ], $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);
|
|
}
|
|
|
|
/**
|
|
* Fetches an email template's message body.
|
|
*
|
|
* @return JSONMessage JSON object
|
|
*/
|
|
public function fetchTemplateBody(array $args, PKPRequest $request): JSONMessage
|
|
{
|
|
$templateId = $request->getUserVar('template');
|
|
$context = $request->getContext();
|
|
$template = Repo::emailTemplate()->getByKey($context->getId(), $templateId);
|
|
if ($template) {
|
|
$mailable = $this->getStageMailable($context, $this->getSubmission());
|
|
$mailable->sender($request->getUser());
|
|
$data = $mailable->getData();
|
|
|
|
return new JSONMessage(
|
|
true,
|
|
[
|
|
'body' => Mail::compileParams($template->getLocalizedData('body'), $data),
|
|
'subject' => Mail::compileParams($template->getLocalizedData('subject'), $data),
|
|
]
|
|
);
|
|
}
|
|
}
|
|
}
|