368 lines
11 KiB
PHP
368 lines
11 KiB
PHP
<?php
|
|
|
|
/**
|
|
* @file controllers/grid/queries/QueryNotesGridHandler.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 QueryNotesGridHandler
|
|
*
|
|
* @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 Illuminate\Support\Facades\Mail;
|
|
use PKP\controllers\grid\GridColumn;
|
|
use PKP\controllers\grid\GridHandler;
|
|
use PKP\controllers\grid\queries\form\QueryNoteForm;
|
|
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\note\Note;
|
|
use PKP\note\NoteDAO;
|
|
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\Role;
|
|
use PKP\submissionFile\SubmissionFile;
|
|
use PKP\user\User;
|
|
|
|
class QueryNotesGridHandler extends GridHandler
|
|
{
|
|
use StageMailable;
|
|
|
|
/** @var User */
|
|
public $_user;
|
|
|
|
/**
|
|
* Constructor
|
|
*/
|
|
public function __construct()
|
|
{
|
|
parent::__construct();
|
|
$this->addRoleAssignment(
|
|
[Role::ROLE_ID_MANAGER, Role::ROLE_ID_SITE_ADMIN, Role::ROLE_ID_REVIEWER, Role::ROLE_ID_AUTHOR, Role::ROLE_ID_SUB_EDITOR, Role::ROLE_ID_ASSISTANT],
|
|
['fetchGrid', 'fetchRow', 'addNote', 'insertNote', 'deleteNote']
|
|
);
|
|
}
|
|
|
|
|
|
//
|
|
// Getters/Setters
|
|
//
|
|
/**
|
|
* Get the authorized submission.
|
|
*/
|
|
public function getSubmission(): Submission
|
|
{
|
|
return $this->getAuthorizedContextObject(Application::ASSOC_TYPE_SUBMISSION);
|
|
}
|
|
|
|
/**
|
|
* Get the query.
|
|
*
|
|
* @return Query
|
|
*/
|
|
public function getQuery(): ?Query
|
|
{
|
|
return $this->getAuthorizedContextObject(Application::ASSOC_TYPE_QUERY);
|
|
}
|
|
|
|
/**
|
|
* Get the stage id.
|
|
*
|
|
* @return int
|
|
*/
|
|
public function getStageId()
|
|
{
|
|
return $this->getAuthorizedContextObject(Application::ASSOC_TYPE_WORKFLOW_STAGE);
|
|
}
|
|
|
|
//
|
|
// Overridden methods from PKPHandler.
|
|
// Note: this is subclassed in application-specific grids.
|
|
//
|
|
/**
|
|
* @copydoc PKPHandler::authorize()
|
|
*/
|
|
public function authorize($request, &$args, $roleAssignments)
|
|
{
|
|
$stageId = $request->getUserVar('stageId'); // This is being validated in WorkflowStageAccessPolicy
|
|
|
|
// Get the access policy
|
|
$this->addPolicy(new QueryAccessPolicy($request, $args, $roleAssignments, $stageId));
|
|
return parent::authorize($request, $args, $roleAssignments);
|
|
}
|
|
|
|
/**
|
|
* @copydoc GridHandler::initialize()
|
|
*
|
|
* @param null|mixed $args
|
|
*/
|
|
public function initialize($request, $args = null)
|
|
{
|
|
parent::initialize($request, $args);
|
|
$this->setTitle('submission.query.messages');
|
|
|
|
$cellProvider = new QueryNotesGridCellProvider($this->getSubmission());
|
|
|
|
// Columns
|
|
$this->addColumn(
|
|
new GridColumn(
|
|
'contents',
|
|
'common.note',
|
|
null,
|
|
null,
|
|
$cellProvider,
|
|
['width' => 80, 'html' => true]
|
|
)
|
|
);
|
|
$this->addColumn(
|
|
new GridColumn(
|
|
'from',
|
|
'submission.query.from',
|
|
null,
|
|
null,
|
|
$cellProvider,
|
|
['html' => true]
|
|
)
|
|
);
|
|
|
|
$this->_user = $request->getUser();
|
|
}
|
|
|
|
|
|
//
|
|
// Overridden methods from GridHandler
|
|
//
|
|
/**
|
|
* @copydoc GridHandler::getRowInstance()
|
|
*
|
|
* @return QueryNotesGridRow
|
|
*/
|
|
public function getRowInstance()
|
|
{
|
|
return new QueryNotesGridRow($this->getRequestArgs(), $this->getQuery(), $this);
|
|
}
|
|
|
|
/**
|
|
* 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(),
|
|
'queryId' => $this->getQuery()->getId(),
|
|
];
|
|
}
|
|
|
|
/**
|
|
* @copydoc GridHandler::loadData()
|
|
*
|
|
* Incomplete notes are hidden from everyone except
|
|
* the user who created them. These are considered
|
|
* in-progress and not yet saved.
|
|
*
|
|
* @see https://github.com/pkp/pkp-lib/issues/1155
|
|
*
|
|
* @param null|mixed $filter
|
|
*/
|
|
public function loadData($request, $filter = null)
|
|
{
|
|
return $this->getQuery()
|
|
->getReplies(null, NoteDAO::NOTE_ORDER_DATE_CREATED, \PKP\db\DAO::SORT_DIRECTION_ASC)
|
|
->filter(function (Note $note) use ($request) {
|
|
return (bool) $note->getContents() || (
|
|
$note->getUserId() === $request->getUser()->getId()
|
|
);
|
|
});
|
|
}
|
|
|
|
//
|
|
// Public Query Notes Grid Actions
|
|
//
|
|
/**
|
|
* Present the form to add a new note.
|
|
*
|
|
* @param array $args
|
|
* @param PKPRequest $request
|
|
*/
|
|
public function addNote($args, $request)
|
|
{
|
|
$queryNoteForm = new QueryNoteForm($this->getRequestArgs(), $this->getQuery(), $request->getUser());
|
|
$queryNoteForm->initData();
|
|
return new JSONMessage(true, $queryNoteForm->fetch($request));
|
|
}
|
|
|
|
/**
|
|
* Insert a new note.
|
|
*
|
|
* @param array $args
|
|
* @param PKPRequest $request
|
|
*/
|
|
public function insertNote($args, $request)
|
|
{
|
|
$queryNoteForm = new QueryNoteForm($this->getRequestArgs(), $this->getQuery(), $request->getUser(), $request->getUserVar('noteId'));
|
|
$queryNoteForm->readInputData();
|
|
if ($queryNoteForm->validate()) {
|
|
$note = $queryNoteForm->execute();
|
|
$this->insertedNoteNotify($note);
|
|
return \PKP\db\DAO::getDataChangedEvent($this->getQuery()->getId());
|
|
} else {
|
|
return new JSONMessage(true, $queryNoteForm->fetch($request));
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Determine whether the current user can manage (delete) a note.
|
|
*
|
|
* @param Note $note optional
|
|
*
|
|
* @return bool
|
|
*/
|
|
public function getCanManage($note)
|
|
{
|
|
$isAdmin = (0 != count(array_intersect(
|
|
$this->getAuthorizedContextObject(Application::ASSOC_TYPE_USER_ROLES),
|
|
[Role::ROLE_ID_MANAGER, Role::ROLE_ID_SITE_ADMIN, Role::ROLE_ID_ASSISTANT, Role::ROLE_ID_SUB_EDITOR]
|
|
)));
|
|
|
|
if ($note === null) {
|
|
return $isAdmin;
|
|
} else {
|
|
return ($note->getUserId() == $this->_user->getId() || $isAdmin);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Delete a query note.
|
|
*
|
|
* @param array $args
|
|
* @param PKPRequest $request
|
|
*
|
|
* @return JSONMessage JSON object
|
|
*/
|
|
public function deleteNote($args, $request)
|
|
{
|
|
$query = $this->getQuery();
|
|
$noteDao = DAORegistry::getDAO('NoteDAO'); /** @var NoteDAO $noteDao */
|
|
$note = $noteDao->getById($request->getUserVar('noteId'));
|
|
$user = $request->getUser();
|
|
|
|
if (!$request->checkCSRF() || !$note || $note->getAssocType() != Application::ASSOC_TYPE_QUERY || $note->getAssocId() != $query->getId()) {
|
|
// The note didn't exist or has the wrong assoc info.
|
|
return new JSONMessage(false);
|
|
}
|
|
|
|
if (!$this->getCanManage($note)) {
|
|
// The user doesn't own the note and isn't privileged enough to delete it.
|
|
return new JSONMessage(false);
|
|
}
|
|
|
|
$noteDao->deleteObject($note);
|
|
return \PKP\db\DAO::getDataChangedEvent($note->getId());
|
|
}
|
|
|
|
/**
|
|
* Sends notification and email to the query participants
|
|
*/
|
|
protected function insertedNoteNotify(Note $note): void
|
|
{
|
|
$notificationManager = new NotificationManager();
|
|
$notificationDao = DAORegistry::getDAO('NotificationDAO'); /** @var NotificationDAO $notificationDao */
|
|
$queryDao = DAORegistry::getDAO('QueryDAO'); /** @var QueryDAO $queryDao */
|
|
$query = $queryDao->getById($note->getData('assocId'));
|
|
$sender = Repo::user()->get($note->getData('userId'));
|
|
$request = Application::get()->getRequest();
|
|
$context = $request->getContext();
|
|
$submission = $this->getSubmission();
|
|
$title = $query->getHeadNote()->getData('title');
|
|
|
|
/** @var NotificationSubscriptionSettingsDAO $notificationSubscriptionSettingsDao */
|
|
$notificationSubscriptionSettingsDao = DAORegistry::getDAO('NotificationSubscriptionSettingsDAO');
|
|
|
|
// Find attachments if any
|
|
$submissionFiles = Repo::submissionFile()
|
|
->getCollector()
|
|
->filterByAssoc(
|
|
PKPApplication::ASSOC_TYPE_NOTE,
|
|
[$note->getId()]
|
|
)->filterBySubmissionIds([$submission->getId()])
|
|
->getMany();
|
|
|
|
foreach ($queryDao->getParticipantIds($query->getId()) as $userId) {
|
|
// Delete any prior notifications of the same type (e.g. prior "new" comments)
|
|
$notificationDao->deleteByAssoc(
|
|
PKPApplication::ASSOC_TYPE_QUERY,
|
|
$query->getId(),
|
|
$userId,
|
|
PKPNotification::NOTIFICATION_TYPE_QUERY_ACTIVITY,
|
|
$context->getId()
|
|
);
|
|
|
|
// No need to additionally notify the posting user.
|
|
if ($userId == $sender->getId()) {
|
|
continue;
|
|
}
|
|
|
|
// Notify the user of a new query.
|
|
$notification = $notificationManager->createNotification(
|
|
$request,
|
|
$userId,
|
|
PKPNotification::NOTIFICATION_TYPE_QUERY_ACTIVITY,
|
|
$request->getContext()->getId(),
|
|
PKPApplication::ASSOC_TYPE_QUERY,
|
|
$query->getId(),
|
|
Notification::NOTIFICATION_LEVEL_TASK
|
|
);
|
|
|
|
// Check if user is subscribed to this type of notification emails
|
|
if (!$notification || in_array(
|
|
PKPNotification::NOTIFICATION_TYPE_QUERY_ACTIVITY,
|
|
$notificationSubscriptionSettingsDao->getNotificationSubscriptionSettings(
|
|
NotificationSubscriptionSettingsDAO::BLOCKED_EMAIL_NOTIFICATION_KEY,
|
|
$userId,
|
|
(int) $context->getId()
|
|
)
|
|
)
|
|
) {
|
|
continue;
|
|
}
|
|
|
|
$recipient = Repo::user()->get($userId);
|
|
$mailable = $this->getStageMailable($context, $submission)
|
|
->sender($sender)
|
|
->recipients([$recipient])
|
|
->subject(__('common.re') . ' ' . $title)
|
|
->body($note->getContents())
|
|
->allowUnsubscribe($notification);
|
|
|
|
$submissionFiles->each(fn(SubmissionFile $item) => $mailable->attachSubmissionFile(
|
|
$item->getId(),
|
|
$item->getLocalizedData('name')
|
|
));
|
|
|
|
Mail::send($mailable);
|
|
}
|
|
}
|
|
}
|