Skip to content

Commit 595a631

Browse files
committed
pkp#9456 Allowing user private editorial notes
1 parent 0ede440 commit 595a631

File tree

16 files changed

+416
-15
lines changed

16 files changed

+416
-15
lines changed

classes/components/listPanels/PKPSelectReviewerListPanel.php

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -121,11 +121,18 @@ public function getConfig()
121121
];
122122

123123
if (!empty($this->lastRoundReviewers)) {
124-
$config['lastRoundReviewers'] = Repo::user()
124+
$reviewers = Repo::user()
125125
->getSchemaMap()
126126
->summarizeManyReviewers($this->lastRoundReviewers)
127127
->values()
128128
->toArray();
129+
$contextId = $this->getParams['contextId'];
130+
$privateNotesDAO = DAORegistry::getDAO('PrivateNotesDAO');
131+
foreach ($reviewers as $key => $reviewer) {
132+
$privateNote = $privateNotesDAO->getPrivateNote($contextId, $reviewer['id']);
133+
$reviewers[$key]['privateNotes'] = $privateNote ? $privateNote->getNote() : null;
134+
}
135+
$config['lastRoundReviewers'] = $reviewers;
129136
}
130137

131138
if (!empty($this->getParams)) {
@@ -147,6 +154,7 @@ public function getConfig()
147154
$config['declinedReviewsLabel'] = __('reviewer.list.declinedReviews');
148155
$config['emptyLabel'] = __('reviewer.list.empty');
149156
$config['gossipLabel'] = __('user.gossip');
157+
$config['privateNotesLabel'] = __('user.private.notes');
150158
$config['neverAssignedLabel'] = __('reviewer.list.neverAssigned');
151159
$config['reassignLabel'] = __('reviewer.list.reassign');
152160
$config['reassignWithNameLabel'] = __('reviewer.list.reassign.withName');
@@ -172,8 +180,13 @@ public function getItems($request)
172180
$reviewers = $this->_getCollector()->getMany();
173181
$items = [];
174182
$map = Repo::user()->getSchemaMap();
183+
$contextId = $request->getContext()->getId();
184+
$privateNotesDAO = DAORegistry::getDAO('PrivateNotesDAO');
175185
foreach ($reviewers as $reviewer) {
176-
$items[] = $map->summarizeReviewer($reviewer);
186+
$item = $map->summarizeReviewer($reviewer);
187+
$privateNote = $privateNotesDAO->getPrivateNote($contextId, $reviewer->getId());
188+
$item['privateNotes'] = $privateNote ? $privateNote->getNote() : null;
189+
$items[] = $item;
177190
}
178191

179192
return $items;

classes/controllers/grid/users/reviewer/PKPReviewerGridHandler.php

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1011,8 +1011,17 @@ public function gossip($args, $request)
10111011
return new JSONMessage(false, __('user.authorization.roleBasedAccessDenied'));
10121012
}
10131013

1014+
$privateNotesDAO = DAORegistry::getDAO('PrivateNotesDAO');
1015+
$privateNote = $privateNotesDAO->getPrivateNote($request->getContext()->getId(), $user->getId());
1016+
if (!$privateNote) {
1017+
$privateNote = $privateNotesDAO->newDataObject();
1018+
$privateNote->setContextId($request->getContext()->getId());
1019+
$privateNote->setUserId($user->getId());
1020+
$privateNote->setNote('');
1021+
}
1022+
10141023
$requestArgs = array_merge($this->getRequestArgs(), ['reviewAssignmentId' => $reviewAssignment->getId()]);
1015-
$reviewerGossipForm = new ReviewerGossipForm($user, $requestArgs);
1024+
$reviewerGossipForm = new ReviewerGossipForm($user, $privateNote, $requestArgs);
10161025

10171026
// View form
10181027
if (!$request->isPost()) {

classes/core/PKPApplication.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -490,6 +490,7 @@ public function getDAOMap()
490490
'NotificationSubscriptionSettingsDAO' => 'PKP\notification\NotificationSubscriptionSettingsDAO',
491491
'PluginGalleryDAO' => 'PKP\plugins\PluginGalleryDAO',
492492
'PluginSettingsDAO' => 'PKP\plugins\PluginSettingsDAO',
493+
'PrivateNotesDAO' => 'PKP\user\PrivateNotesDAO',
493494
'PublicationDAO' => 'APP\publication\PublicationDAO',
494495
'QueuedPaymentDAO' => 'PKP\payment\QueuedPaymentDAO',
495496
'ReviewFilesDAO' => 'PKP\submission\ReviewFilesDAO',

classes/migration/install/CommonMigration.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
namespace PKP\migration\install;
1616

1717
use APP\core\Application;
18+
use APP\facades\Repo;
1819
use Illuminate\Database\Schema\Blueprint;
1920
use Illuminate\Support\Facades\DB;
2021
use Illuminate\Support\Facades\Schema;
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
<?php
2+
3+
/**
4+
* @file classes/migration/upgrade/v3_5_0/I9456_PrivateNotes.php
5+
*
6+
* Copyright (c) 2014-2023 Simon Fraser University
7+
* Copyright (c) 2000-2023 John Willinsky
8+
* Distributed under the GNU GPL v3. For full terms see the file docs/COPYING.
9+
*
10+
* @class I9456_PrivateNotes
11+
*/
12+
13+
namespace PKP\migration\upgrade\v3_5_0;
14+
15+
use APP\core\Application;
16+
use APP\facades\Repo;
17+
use Illuminate\Database\Schema\Blueprint;
18+
use Illuminate\Support\Facades\Schema;
19+
use PKP\migration\Migration;
20+
21+
class I9456_PrivateNotes extends Migration
22+
{
23+
/**
24+
* Run the migrations.
25+
*/
26+
public function up(): void
27+
{
28+
Schema::create('user_private_notes', function (Blueprint $table) {
29+
$table->comment('User private notes are an addition to the gossip, but this one is private to each context.');
30+
$table->bigInteger('private_note_id')->autoIncrement();
31+
32+
$table->bigInteger('context_id');
33+
$contextDao = Application::getContextDAO();
34+
$table->foreign('context_id')->references($contextDao->primaryKeyColumn)->on($contextDao->tableName)->onDelete('cascade');
35+
36+
$table->bigInteger('user_id');
37+
$userDao = Repo::user()->dao;
38+
$table->foreign('user_id')->references($userDao->primaryKeyColumn)->on($userDao->table)->onDelete('cascade');
39+
40+
$table->unique(['context_id', 'user_id'], 'user_private_notes_unique');
41+
$table->index(['context_id'], 'user_private_notes_context_id_foreign');
42+
43+
$table->string('note')->default('');
44+
});
45+
}
46+
47+
/**
48+
* Reverse the migration.
49+
*/
50+
public function down(): void
51+
{
52+
Schema::drop('user_private_notes');
53+
}
54+
}

classes/user/PrivateNote.php

Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
<?php
2+
3+
/**
4+
* @file classes/user/PrivateNote.php
5+
*
6+
* Copyright (c) 2014-2021 Simon Fraser University
7+
* Copyright (c) 2000-2021 John Willinsky
8+
* Distributed under the GNU GPL v3. For full terms see the file docs/COPYING.
9+
*
10+
* @class PrivateNote
11+
*
12+
* @ingroup user
13+
*
14+
* @see PrivateNotesDAO
15+
*
16+
* @brief Basic class describing user private note existing in the system.
17+
*/
18+
19+
namespace PKP\user;
20+
21+
use PKP\core\DataObject;
22+
23+
class PrivateNote extends DataObject
24+
{
25+
/**
26+
* Get private note ID.
27+
*
28+
* @return int
29+
*/
30+
public function getId(): int
31+
{
32+
return $this->getData('id');
33+
}
34+
35+
/**
36+
* Set private note ID.
37+
*
38+
* @param $id int
39+
*/
40+
public function setId($id): void
41+
{
42+
$this->setData('id', $id);
43+
}
44+
45+
/**
46+
* Get private note context ID.
47+
*
48+
* @return int
49+
*/
50+
public function getContextId(): int
51+
{
52+
return $this->getData('contextId');
53+
}
54+
55+
/**
56+
* Set private note context ID.
57+
*
58+
* @param $contextId int
59+
*/
60+
public function setContextId(int $contextId): void
61+
{
62+
$this->setData('contextId', $contextId);
63+
}
64+
65+
/**
66+
* Get private note user ID.
67+
*
68+
* @return int
69+
*/
70+
public function getUserId(): int
71+
{
72+
return $this->getData('userId');
73+
}
74+
75+
/**
76+
* Set private note user ID.
77+
*
78+
* @param $userId int
79+
*/
80+
public function setUserId(int $userId): void
81+
{
82+
$this->setData('userId', $userId);
83+
}
84+
85+
86+
/**
87+
* Get private note value.
88+
*
89+
* @return string
90+
*/
91+
public function getNote(): string
92+
{
93+
return $this->getData('note');
94+
}
95+
96+
/**
97+
* Set private note value.
98+
*
99+
* @param $note string
100+
*/
101+
public function setNote(string $note): void
102+
{
103+
$this->setData('note', $note);
104+
}
105+
}
106+
107+
if (!PKP_STRICT_MODE) {
108+
class_alias('\PKP\user\PrivateNote', '\PrivateNote');
109+
}

classes/user/PrivateNotesDAO.php

Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
1+
<?php
2+
3+
/**
4+
* @file classes/user/PrivateNotesDAO.php
5+
*
6+
* Copyright (c) 2014-2021 Simon Fraser University
7+
* Copyright (c) 2003-2021 John Willinsky
8+
* Distributed under the GNU GPL v3. For full terms see the file docs/COPYING.
9+
*
10+
* @class PrivateNotesDAO
11+
*
12+
* @ingroup user
13+
*
14+
* @see PrivateNote
15+
*
16+
* @brief Operations for retrieving and modifying user private notes.
17+
*/
18+
19+
namespace PKP\user;
20+
21+
use PKP\db\DAO;
22+
use PKP\db\DAOResultFactory;
23+
24+
class PrivateNotesDAO extends DAO
25+
{
26+
/**
27+
* Construct a new PrivateNote object.
28+
*
29+
* @return PrivateNote
30+
*/
31+
public function newDataObject(): PrivateNote
32+
{
33+
return new PrivateNote();
34+
}
35+
36+
/**
37+
* Retrieve a user private note value.
38+
*
39+
* @param int $journalId
40+
* @param int $userId
41+
*
42+
* @return PrivateNote|null
43+
*/
44+
public function getPrivateNote(int $journalId, int $userId): PrivateNote|null
45+
{
46+
$params = [
47+
$journalId,
48+
$userId
49+
];
50+
$result = $this->retrieve(
51+
'SELECT * FROM user_private_notes WHERE context_id = ? AND user_id = ?',
52+
$params
53+
);
54+
$factory = new DAOResultFactory($result, $this, '_fromRow');
55+
return $factory->toIterator()->current();
56+
}
57+
58+
/**
59+
* Set a user private note value.
60+
*
61+
* @param int $journalId
62+
* @param int $userId
63+
* @param string $note
64+
*/
65+
public function setPrivateNote(int $journalId, int $userId, string $note): void
66+
{
67+
$params = [
68+
$note,
69+
$journalId,
70+
$userId
71+
];
72+
$dbPrivateNote = $this->getPrivateNote($journalId, $userId);
73+
if ($dbPrivateNote) {
74+
$this->update(
75+
'UPDATE user_private_notes SET note = ? WHERE context_id = ? AND user_id = ?',
76+
$params
77+
);
78+
} else {
79+
$this->update(
80+
'INSERT INTO user_private_notes (note, context_id, user_id) VALUES (?, ?, ?)',
81+
$params
82+
);
83+
}
84+
}
85+
86+
/**
87+
* Internal function to return a PrivateNote object from a row.
88+
*
89+
* @param array $row
90+
*
91+
* @return PrivateNote
92+
*/
93+
function _fromRow(array $row): PrivateNote
94+
{
95+
$privateNote = $this->newDataObject();
96+
97+
$privateNote->setId($row['private_note_id']);
98+
$privateNote->setContextId($row['context_id']);
99+
$privateNote->setUserId($row['user_id']);
100+
$privateNote->setNote($row['note']);
101+
102+
return $privateNote;
103+
}
104+
}
105+
106+
if (!PKP_STRICT_MODE) {
107+
class_alias('\PKP\user\PrivateNotesDAO', '\PrivateNotesDAO');
108+
}

controllers/grid/settings/user/form/UserDetailsForm.php

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -177,6 +177,9 @@ public function initData()
177177
$data['canCurrentUserGossip'] = Repo::user()->canCurrentUserGossip($user->getId());
178178
if ($data['canCurrentUserGossip']) {
179179
$data['gossip'] = $user->getGossip();
180+
$privateNotesDAO = DAORegistry::getDAO('PrivateNotesDAO');
181+
$privateNote = $privateNotesDAO->getPrivateNote($request->getContext()->getId(), $user->getId());
182+
$data['privateNote'] = $privateNote ? $privateNote->getNote() : '';
180183
}
181184
} elseif (isset($this->author)) {
182185
$author = $this->author;
@@ -268,6 +271,7 @@ public function readInputData()
268271
'country',
269272
'biography',
270273
'gossip',
274+
'privateNote',
271275
'interests',
272276
'locales',
273277
'generatePassword',
@@ -359,6 +363,7 @@ public function execute(...$functionParams)
359363
}
360364

361365
Repo::user()->edit($this->user);
366+
$userId = $this->user->getId();
362367
} else {
363368
$this->user->setUsername($this->getData('username'));
364369
if ($this->getData('generatePassword')) {
@@ -372,7 +377,7 @@ public function execute(...$functionParams)
372377
$this->user->setPassword(Validation::encryptCredentials($this->getData('username'), $password));
373378

374379
$this->user->setDateRegistered(Core::getCurrentDate());
375-
Repo::user()->add($this->user);
380+
$userId = Repo::user()->add($this->user);
376381

377382
if ($sendNotify) {
378383
// Send welcome email to user
@@ -398,6 +403,12 @@ public function execute(...$functionParams)
398403
}
399404
}
400405

406+
// Users can never view/edit their own private notes fields
407+
if (Repo::user()->canCurrentUserGossip($userId)) {
408+
$privateNotesDAO = DAORegistry::getDAO('PrivateNotesDAO');
409+
$privateNotesDAO->setPrivateNote($context->getId(), $userId, $this->getData('privateNote'));
410+
}
411+
401412
$interestManager = new InterestManager();
402413
$interestManager->setInterestsForUser($this->user, $this->getData('interests'));
403414

0 commit comments

Comments
 (0)