first commit
This commit is contained in:
@@ -0,0 +1,110 @@
|
||||
<?php
|
||||
/**
|
||||
* @file classes/log/event/Collector.php
|
||||
*
|
||||
* Copyright (c) 2014-2023 Simon Fraser University
|
||||
* Copyright (c) 2000-2023 John Willinsky
|
||||
* Distributed under the GNU GPL v3. For full terms see the file docs/COPYING.
|
||||
*
|
||||
* @class Collector
|
||||
*
|
||||
* @brief A helper class to configure a Query Builder to get a collection of log entries
|
||||
*/
|
||||
|
||||
namespace PKP\log\event;
|
||||
|
||||
use Illuminate\Database\Query\Builder;
|
||||
use Illuminate\Support\Collection;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Illuminate\Support\LazyCollection;
|
||||
use PKP\core\interfaces\CollectorInterface;
|
||||
use PKP\plugins\Hook;
|
||||
|
||||
class Collector implements CollectorInterface
|
||||
{
|
||||
public DAO $dao;
|
||||
protected ?int $assocType = null;
|
||||
protected ?array $assocIds = null;
|
||||
protected ?array $userIds = null;
|
||||
public ?int $count = null;
|
||||
public ?int $offset = null;
|
||||
|
||||
public function __construct(DAO $dao)
|
||||
{
|
||||
$this->dao = $dao;
|
||||
}
|
||||
|
||||
public function getCount(): int
|
||||
{
|
||||
return $this->dao->getCount($this);
|
||||
}
|
||||
|
||||
public function getIds(): Collection
|
||||
{
|
||||
return $this->dao->getIds($this);
|
||||
}
|
||||
|
||||
public function getMany(): LazyCollection
|
||||
{
|
||||
return $this->dao->getMany($this);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param null|int $assocType One of the Application::ASSOC_TYPE_ constants
|
||||
* @param null|array $assocIds Match for the specified assoc type
|
||||
*/
|
||||
public function filterByAssoc(?int $assocType, ?array $assocIds = null): self
|
||||
{
|
||||
$this->assocType = $assocType;
|
||||
$this->assocIds = $assocIds;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function filterByUserIds(?array $userIds): self
|
||||
{
|
||||
$this->userIds = $userIds;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function limit(?int $count): self
|
||||
{
|
||||
$this->count = $count;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function offset(?int $offset): self
|
||||
{
|
||||
$this->offset = $offset;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function getQueryBuilder(): Builder
|
||||
{
|
||||
$q = DB::table($this->dao->table . ' as e')
|
||||
->select(['e.*'])
|
||||
->when(!is_null($this->assocType), function (Builder $q) {
|
||||
return $q->where('assoc_type', $this->assocType);
|
||||
})
|
||||
->when(!is_null($this->assocIds), function (Builder $q) {
|
||||
return $q->whereIn('assoc_id', $this->assocIds);
|
||||
})
|
||||
->when(!is_null($this->userIds), function (Builder $q) {
|
||||
return $q->whereIn('user_id', $this->userIds);
|
||||
})
|
||||
->orderBy('date_logged', 'desc')
|
||||
->when(!is_null($this->count), function (Builder $q) {
|
||||
return $q->limit($this->count);
|
||||
})
|
||||
->when(!is_null($this->count) && !is_null($this->offset), function (Builder $q) {
|
||||
return $q->offset($this->offset);
|
||||
});
|
||||
|
||||
Hook::call('EventLog::Collector::getQueryBuilder', [&$q, $this]);
|
||||
|
||||
return $q;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,169 @@
|
||||
<?php
|
||||
/**
|
||||
* @file classes/log/event/DAO.php
|
||||
*
|
||||
* Copyright (c) 2014-2023 Simon Fraser University
|
||||
* Copyright (c) 2000-2023 John Willinsky
|
||||
* Distributed under the GNU GPL v3. For full terms see the file docs/COPYING.
|
||||
*
|
||||
* @class DAO
|
||||
*
|
||||
* @brief Read and write event information to the database.
|
||||
*/
|
||||
|
||||
namespace PKP\log\event;
|
||||
|
||||
use Illuminate\Support\Collection;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Illuminate\Support\LazyCollection;
|
||||
use PKP\core\EntityDAO;
|
||||
use PKP\services\PKPSchemaService;
|
||||
|
||||
class DAO extends EntityDAO
|
||||
{
|
||||
/** @copydoc EntityDAO::$schema */
|
||||
public $schema = PKPSchemaService::SCHEMA_EVENT_LOG;
|
||||
|
||||
/** @copydoc EntityDAO::$table */
|
||||
public $table = 'event_log';
|
||||
|
||||
/** @copydoc EntityDAO::$settingsTable */
|
||||
public $settingsTable = 'event_log_settings';
|
||||
|
||||
/** @copydoc EntityDAO::$primaryKeyColumn */
|
||||
public $primaryKeyColumn = 'log_id';
|
||||
|
||||
/** @copydoc EntityDAO::$primaryTableColumns */
|
||||
public $primaryTableColumns = [
|
||||
'id' => 'log_id',
|
||||
'assocType' => 'assoc_type',
|
||||
'assocId' => 'assoc_id',
|
||||
'userId' => 'user_id',
|
||||
'dateLogged' => 'date_logged',
|
||||
'eventType' => 'event_type',
|
||||
'message' => 'message',
|
||||
'isTranslated' => 'is_translated',
|
||||
];
|
||||
|
||||
/**
|
||||
* Instantiate a new DataObject
|
||||
*/
|
||||
public function newDataObject(): EventLogEntry
|
||||
{
|
||||
return app(EventLogEntry::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if a log entry exists
|
||||
*/
|
||||
public function exists(int $id): bool
|
||||
{
|
||||
return DB::table($this->table)
|
||||
->where($this->primaryKeyColumn, '=', $id)
|
||||
->exists();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get an event log entry
|
||||
*/
|
||||
public function get(int $id): ?EventLogEntry
|
||||
{
|
||||
$row = DB::table($this->table)
|
||||
->where($this->primaryKeyColumn, $id)
|
||||
->first();
|
||||
return $row ? $this->fromRow($row) : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the number of log entries matching the configured query
|
||||
*/
|
||||
public function getCount(Collector $query): int
|
||||
{
|
||||
return $query
|
||||
->getQueryBuilder()
|
||||
->count();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a list of ids matching the configured query
|
||||
*/
|
||||
public function getIds(Collector $query): Collection
|
||||
{
|
||||
return $query
|
||||
->getQueryBuilder()
|
||||
->select('e.' . $this->primaryKeyColumn)
|
||||
->pluck('e.' . $this->primaryKeyColumn);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a collection of log entries matching the configured query
|
||||
*/
|
||||
public function getMany(Collector $query): LazyCollection
|
||||
{
|
||||
$rows = $query
|
||||
->getQueryBuilder()
|
||||
->get();
|
||||
|
||||
return LazyCollection::make(function () use ($rows) {
|
||||
foreach ($rows as $row) {
|
||||
yield $row->log_id => $this->fromRow($row);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* @copydoc EntityDAO::fromRow()
|
||||
*/
|
||||
public function fromRow(object $row): EventLogEntry
|
||||
{
|
||||
$logEntry = parent::fromRow($row);
|
||||
$schema = $this->schemaService->get($this->schema);
|
||||
|
||||
DB::table($this->settingsTable)
|
||||
->where($this->primaryKeyColumn, '=', $row->{$this->primaryKeyColumn})
|
||||
->get()
|
||||
->each(function ($row) use ($logEntry, $schema) {
|
||||
if (!empty($schema->properties->{$row->setting_name})) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Retrieve custom properties
|
||||
if (!empty($row->setting_type)) {
|
||||
$logEntry->setData(
|
||||
$row->setting_name,
|
||||
$this->convertFromDB(
|
||||
$row->setting_value,
|
||||
$row->setting_type
|
||||
),
|
||||
empty($row->locale) ? null : $row->locale
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
return $logEntry;
|
||||
}
|
||||
|
||||
/**
|
||||
* @copydoc EntityDAO::insert()
|
||||
*/
|
||||
public function insert(EventLogEntry $eventLog): int
|
||||
{
|
||||
return parent::_insert($eventLog);
|
||||
}
|
||||
|
||||
/**
|
||||
* @copydoc EntityDAO::delete()
|
||||
*/
|
||||
public function delete(EventLogEntry $eventLog)
|
||||
{
|
||||
parent::_delete($eventLog);
|
||||
}
|
||||
|
||||
/**
|
||||
* Transfer all log entries to another user.
|
||||
*/
|
||||
public function changeUser(int $oldUserId, int $newUserId)
|
||||
{
|
||||
DB::table($this->table)->where('user_id', $oldUserId)->update(['user_id' => $newUserId]);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,285 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @file classes/log/event/EventLogEntry.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 EventLogEntry
|
||||
*
|
||||
* @ingroup log
|
||||
*
|
||||
* @brief Describes an entry in the event log.
|
||||
*/
|
||||
|
||||
namespace PKP\log\event;
|
||||
|
||||
use APP\core\Application;
|
||||
use APP\facades\Repo;
|
||||
use PKP\db\DAORegistry;
|
||||
use PKP\facades\Locale;
|
||||
use PKP\submission\reviewAssignment\ReviewAssignment;
|
||||
use PKP\submissionFile\SubmissionFile;
|
||||
|
||||
class EventLogEntry extends \PKP\core\DataObject
|
||||
{
|
||||
// Information Center events
|
||||
public const SUBMISSION_LOG_NOTE_POSTED = 0x01000000;
|
||||
public const SUBMISSION_LOG_MESSAGE_SENT = 0x01000001;
|
||||
|
||||
//
|
||||
// Get/set methods
|
||||
//
|
||||
|
||||
/**
|
||||
* Get user ID of user that initiated the event.
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function getUserId()
|
||||
{
|
||||
return $this->getData('userId');
|
||||
}
|
||||
|
||||
/**
|
||||
* Set user ID of user that initiated the event.
|
||||
*
|
||||
* @param int $userId
|
||||
*/
|
||||
public function setUserId($userId)
|
||||
{
|
||||
$this->setData('userId', $userId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get date entry was logged.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getDateLogged()
|
||||
{
|
||||
return $this->getData('dateLogged');
|
||||
}
|
||||
|
||||
/**
|
||||
* Set date entry was logged.
|
||||
*
|
||||
* @param string $dateLogged
|
||||
*/
|
||||
public function setDateLogged($dateLogged)
|
||||
{
|
||||
$this->setData('dateLogged', $dateLogged);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get event type.
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function getEventType()
|
||||
{
|
||||
return $this->getData('eventType');
|
||||
}
|
||||
|
||||
/**
|
||||
* Set event type.
|
||||
*
|
||||
* @param int $eventType
|
||||
*/
|
||||
public function setEventType($eventType)
|
||||
{
|
||||
$this->setData('eventType', $eventType);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get associated type.
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function getAssocType()
|
||||
{
|
||||
return $this->getData('assocType');
|
||||
}
|
||||
|
||||
/**
|
||||
* Set associated type.
|
||||
*
|
||||
* @param int $assocType
|
||||
*/
|
||||
public function setAssocType($assocType)
|
||||
{
|
||||
$this->setData('assocType', $assocType);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get associated ID.
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function getAssocId()
|
||||
{
|
||||
return $this->getData('assocId');
|
||||
}
|
||||
|
||||
/**
|
||||
* Set associated ID.
|
||||
*
|
||||
* @param int $assocId
|
||||
*/
|
||||
public function setAssocId($assocId)
|
||||
{
|
||||
$this->setData('assocId', $assocId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get custom log message (either locale key or literal string).
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getMessage()
|
||||
{
|
||||
return $this->getData('message');
|
||||
}
|
||||
|
||||
/**
|
||||
* Set custom log message (either locale key or literal string).
|
||||
*
|
||||
* @param string $message
|
||||
*/
|
||||
public function setMessage($message)
|
||||
{
|
||||
$this->setData('message', $message);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get flag indicating whether or not message is translated.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function getIsTranslated()
|
||||
{
|
||||
return $this->getData('isTranslated');
|
||||
}
|
||||
|
||||
/**
|
||||
* Set flag indicating whether or not message is translated.
|
||||
*
|
||||
* @param int $isTranslated
|
||||
*/
|
||||
public function setIsTranslated($isTranslated)
|
||||
{
|
||||
$this->setData('isTranslated', $isTranslated);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get translated message, translating it if necessary.
|
||||
*
|
||||
* @param string $locale optional
|
||||
* @param bool $hideReviewerName optional Don't reveal reviewer names in
|
||||
* log descriptions.
|
||||
*/
|
||||
public function getTranslatedMessage($locale = null, $hideReviewerName = false)
|
||||
{
|
||||
$message = $this->getMessage();
|
||||
// If it's already translated, just return the message.
|
||||
if ($this->getData('isTranslated')) {
|
||||
return $message;
|
||||
}
|
||||
|
||||
// Otherwise, translate it and include parameters.
|
||||
if ($locale === null) {
|
||||
$locale = Locale::getLocale();
|
||||
}
|
||||
|
||||
$eventLog = clone $this;
|
||||
|
||||
if ($hideReviewerName) {
|
||||
$reviewAssignmentDao = DAORegistry::getDAO('ReviewAssignmentDAO'); /** @var \PKP\submission\reviewAssignment\ReviewAssignmentDAO $reviewAssignmentDao */
|
||||
// Reviewer activity log entries (assigning, accepting, declining)
|
||||
if ($eventLog->getData('reviewerName')) {
|
||||
$anonymousAuthor = true;
|
||||
if ($reviewAssignmentId = $eventLog->getData('reviewAssignmentId')) {
|
||||
$reviewAssignment = $reviewAssignmentDao->getById($reviewAssignmentId);
|
||||
if ($reviewAssignment && !in_array($reviewAssignment->getReviewMethod(), [ReviewAssignment::SUBMISSION_REVIEW_METHOD_ANONYMOUS, ReviewAssignment::SUBMISSION_REVIEW_METHOD_DOUBLEANONYMOUS])) {
|
||||
$anonymousAuthor = false;
|
||||
}
|
||||
}
|
||||
if ($anonymousAuthor) {
|
||||
$eventLog->setData('reviewerName', __('editor.review.anonymousReviewer'));
|
||||
}
|
||||
}
|
||||
// Files submitted by reviewers
|
||||
$fileStage = $eventLog->getData('fileStage');
|
||||
if ($fileStage && $fileStage === SubmissionFile::SUBMISSION_FILE_REVIEW_ATTACHMENT) {
|
||||
$submissionFileId = $eventLog->getData('submissionFileId');
|
||||
assert($eventLog->getData('fileId') && $eventLog->getData('submissionId') && $submissionFileId);
|
||||
$anonymousAuthor = true;
|
||||
$submissionFile = Repo::submissionFile()->get($submissionFileId);
|
||||
if ($submissionFile && $submissionFile->getData('assocType') === Application::ASSOC_TYPE_REVIEW_ASSIGNMENT) {
|
||||
$reviewAssignment = $reviewAssignmentDao->getById($submissionFile->getData('assocId'));
|
||||
if ($reviewAssignment && !in_array($reviewAssignment->getReviewMethod(), [ReviewAssignment::SUBMISSION_REVIEW_METHOD_ANONYMOUS, ReviewAssignment::SUBMISSION_REVIEW_METHOD_DOUBLEANONYMOUS])) {
|
||||
$anonymousAuthor = false;
|
||||
}
|
||||
}
|
||||
if ($eventLog->getData('username') && $anonymousAuthor) {
|
||||
$eventLog->setData('username', __('editor.review.anonymousReviewer'));
|
||||
$filenames = $eventLog->getData('filename');
|
||||
$eventLog->setData('filename', array_map(function (string $value) {
|
||||
return '';
|
||||
}, $filenames));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$params = [];
|
||||
foreach ($eventLog->getAllData() as $key => $data) {
|
||||
if (!is_array($data)) {
|
||||
$params[$key] = $eventLog->getData($key);
|
||||
continue;
|
||||
}
|
||||
|
||||
$params[$key] = $eventLog->getData($key, $locale);
|
||||
}
|
||||
|
||||
return __($message, $params, $locale);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the full name of the user.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getUserFullName()
|
||||
{
|
||||
$userFullName = & $this->getData('userFullName');
|
||||
if (!isset($userFullName) && $this->getUserId()) {
|
||||
$userFullName = Repo::user()->get($this->getUserId(), true)->getFullName();
|
||||
}
|
||||
|
||||
return $userFullName ?: '';
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the email address of the user.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getUserEmail()
|
||||
{
|
||||
$userEmail = $this->getData('userEmail');
|
||||
|
||||
if (!isset($userEmail)) {
|
||||
$userEmail = Repo::user()->get($this->getUserId(), true)->getEmail();
|
||||
}
|
||||
|
||||
return $userEmail ?: '';
|
||||
}
|
||||
}
|
||||
|
||||
if (!PKP_STRICT_MODE) {
|
||||
class_alias('\PKP\log\event\EventLogEntry', '\EventLogEntry');
|
||||
define('SUBMISSION_LOG_NOTE_POSTED', EventLogEntry::SUBMISSION_LOG_NOTE_POSTED);
|
||||
define('SUBMISSION_LOG_MESSAGE_SENT', EventLogEntry::SUBMISSION_LOG_MESSAGE_SENT);
|
||||
}
|
||||
@@ -0,0 +1,109 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @file classes/log/event/PKPSubmissionEventLogEntry.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 PKPSubmissionEventLogEntry
|
||||
*
|
||||
* @ingroup log
|
||||
*
|
||||
* @brief Describes an entry in the submission history log.
|
||||
*/
|
||||
|
||||
namespace PKP\log\event;
|
||||
|
||||
use APP\core\Application;
|
||||
|
||||
class PKPSubmissionEventLogEntry extends EventLogEntry
|
||||
{
|
||||
public const SUBMISSION_LOG_SUBMISSION_SUBMIT = 0x10000001;
|
||||
public const SUBMISSION_LOG_METADATA_UPDATE = 0x10000002;
|
||||
public const SUBMISSION_LOG_ADD_PARTICIPANT = 0x10000003;
|
||||
public const SUBMISSION_LOG_REMOVE_PARTICIPANT = 0x10000004;
|
||||
|
||||
public const SUBMISSION_LOG_METADATA_PUBLISH = 0x10000006;
|
||||
public const SUBMISSION_LOG_METADATA_UNPUBLISH = 0x10000007;
|
||||
|
||||
public const SUBMISSION_LOG_CREATE_VERSION = 0x10000008;
|
||||
|
||||
public const SUBMISSION_LOG_COPYRIGHT_AGREED = 0x10000009;
|
||||
|
||||
public const SUBMISSION_LOG_EDITOR_DECISION = 0x30000003;
|
||||
public const SUBMISSION_LOG_EDITOR_RECOMMENDATION = 0x30000004;
|
||||
public const SUBMISSION_LOG_DECISION_EMAIL_SENT = 0x30000007;
|
||||
|
||||
public const SUBMISSION_LOG_REVIEW_ASSIGN = 0x40000001;
|
||||
public const SUBMISSION_LOG_REVIEW_REINSTATED = 0x40000005;
|
||||
public const SUBMISSION_LOG_REVIEW_ACCEPT = 0x40000006;
|
||||
public const SUBMISSION_LOG_REVIEW_DECLINE = 0x40000007;
|
||||
public const SUBMISSION_LOG_REVIEW_UNCONSIDERED = 0x40000009;
|
||||
public const SUBMISSION_LOG_REVIEW_SET_DUE_DATE = 0x40000011;
|
||||
public const SUBMISSION_LOG_REVIEW_CLEAR = 0x40000014;
|
||||
public const SUBMISSION_LOG_REVIEW_READY = 0x40000018;
|
||||
public const SUBMISSION_LOG_REVIEW_CONFIRMED = 0x40000019;
|
||||
public const SUBMISSION_LOG_REVIEW_REMIND = 0x40000020;
|
||||
public const SUBMISSION_LOG_REVIEW_REMIND_AUTO = 0x40000021;
|
||||
|
||||
|
||||
//
|
||||
// Getters/setters
|
||||
//
|
||||
/**
|
||||
* Set the submission ID
|
||||
*/
|
||||
public function setSubmissionId($submissionId)
|
||||
{
|
||||
return $this->setAssocId($submissionId);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get the submission ID
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function getSubmissionId()
|
||||
{
|
||||
return $this->getAssocId();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get the assoc ID
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function getAssocType()
|
||||
{
|
||||
return Application::ASSOC_TYPE_SUBMISSION;
|
||||
}
|
||||
}
|
||||
|
||||
if (!PKP_STRICT_MODE) {
|
||||
class_alias('\PKP\log\event\PKPSubmissionEventLogEntry', '\PKPSubmissionEventLogEntry');
|
||||
foreach ([
|
||||
'SUBMISSION_LOG_SUBMISSION_SUBMIT',
|
||||
'SUBMISSION_LOG_METADATA_UPDATE',
|
||||
'SUBMISSION_LOG_ADD_PARTICIPANT',
|
||||
'SUBMISSION_LOG_REMOVE_PARTICIPANT',
|
||||
'SUBMISSION_LOG_METADATA_PUBLISH',
|
||||
'SUBMISSION_LOG_METADATA_UNPUBLISH',
|
||||
'SUBMISSION_LOG_CREATE_VERSION',
|
||||
'SUBMISSION_LOG_EDITOR_DECISION',
|
||||
'SUBMISSION_LOG_EDITOR_RECOMMENDATION',
|
||||
'SUBMISSION_LOG_REVIEW_ASSIGN',
|
||||
'SUBMISSION_LOG_REVIEW_REINSTATED',
|
||||
'SUBMISSION_LOG_REVIEW_DECLINE',
|
||||
'SUBMISSION_LOG_REVIEW_UNCONSIDERED',
|
||||
'SUBMISSION_LOG_REVIEW_SET_DUE_DATE',
|
||||
'SUBMISSION_LOG_REVIEW_CLEAR',
|
||||
'SUBMISSION_LOG_REVIEW_READY',
|
||||
'SUBMISSION_LOG_REVIEW_CONFIRMED',
|
||||
] as $constantName) {
|
||||
define($constantName, constant('\PKPSubmissionEventLogEntry::' . $constantName));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,152 @@
|
||||
<?php
|
||||
/**
|
||||
* @file classes/log/event/Repository.php
|
||||
*
|
||||
* Copyright (c) 2014-2023 Simon Fraser University
|
||||
* Copyright (c) 2000-2023 John Willinsky
|
||||
* Distributed under the GNU GPL v3. For full terms see the file docs/COPYING.
|
||||
*
|
||||
* @class Repository
|
||||
*
|
||||
* @brief A repository to find and manage event log entries.
|
||||
*/
|
||||
|
||||
namespace PKP\log\event;
|
||||
|
||||
use APP\facades\Repo;
|
||||
use PKP\context\Context;
|
||||
use PKP\core\PKPApplication;
|
||||
use PKP\core\PKPRequest;
|
||||
use PKP\plugins\Hook;
|
||||
use PKP\services\PKPSchemaService;
|
||||
use PKP\validation\ValidatorFactory;
|
||||
|
||||
class Repository
|
||||
{
|
||||
public DAO $dao;
|
||||
|
||||
// The name of the class to map this entity to its schema
|
||||
public string $schemaMap = maps\Schema::class;
|
||||
|
||||
protected PKPRequest $request;
|
||||
|
||||
protected PKPSchemaService $schemaService;
|
||||
|
||||
public function __construct(DAO $dao, PKPRequest $request, PKPSchemaService $schemaService)
|
||||
{
|
||||
$this->dao = $dao;
|
||||
$this->request = $request;
|
||||
$this->schemaService = $schemaService;
|
||||
}
|
||||
|
||||
/** @copydoc DAO::newDataObject() */
|
||||
public function newDataObject(array $params = []): EventLogEntry
|
||||
{
|
||||
$object = $this->dao->newDataObject();
|
||||
if (!empty($params)) {
|
||||
$object->setAllData($params);
|
||||
}
|
||||
return $object;
|
||||
}
|
||||
|
||||
/** @copydoc DAO::getByKey() */
|
||||
public function get(int $key): ?EventLogEntry
|
||||
{
|
||||
return $this->dao->get($key);
|
||||
}
|
||||
|
||||
/** @copydoc DAO::getCollector() */
|
||||
public function getCollector(): Collector
|
||||
{
|
||||
return app(Collector::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get an instance of the map class for mapping
|
||||
* log entries to their schema
|
||||
*/
|
||||
public function getSchemaMap(): maps\Schema
|
||||
{
|
||||
return app('maps')->withExtensions($this->schemaMap);
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate properties for an event log entry
|
||||
*
|
||||
* Perform validation checks on data used to add or edit an event log entry.
|
||||
*
|
||||
* @param array $props A key/value array with the new data to validate
|
||||
* @param array $allowedLocales The context's supported locales
|
||||
* @param string $primaryLocale The context's primary locale
|
||||
*
|
||||
* @return array A key/value array with validation errors. Empty if no errors
|
||||
*/
|
||||
public function validate(?EventLogEntry $object, array $props, Context $context): array
|
||||
{
|
||||
$allowedLocales = $context->getSupportedSubmissionLocales();;
|
||||
$primaryLocale = $context->getPrimaryLocale();
|
||||
|
||||
$validator = ValidatorFactory::make(
|
||||
$props,
|
||||
$this->schemaService->getValidationRules($this->dao->schema, $allowedLocales)
|
||||
);
|
||||
|
||||
// Check required fields
|
||||
ValidatorFactory::required(
|
||||
$validator,
|
||||
$object,
|
||||
$this->schemaService->getRequiredProps($this->dao->schema),
|
||||
$this->schemaService->getMultilingualProps($this->dao->schema),
|
||||
$allowedLocales,
|
||||
$primaryLocale
|
||||
);
|
||||
|
||||
// Check for input from disallowed locales
|
||||
ValidatorFactory::allowedLocales($validator, $this->schemaService->getMultilingualProps($this->dao->schema), $allowedLocales);
|
||||
|
||||
$errors = [];
|
||||
|
||||
if ($validator->fails()) {
|
||||
$errors = $this->schemaService->formatValidationErrors($validator->errors());
|
||||
}
|
||||
|
||||
Hook::call('EventLog::validate', [&$errors, $object, $props, $allowedLocales, $primaryLocale]);
|
||||
|
||||
return $errors;
|
||||
}
|
||||
|
||||
/** @copydoc DAO::insert() */
|
||||
public function add(EventLogEntry $logEntry): int
|
||||
{
|
||||
$id = $this->dao->insert($logEntry);
|
||||
Hook::call('EventLog::add', [$logEntry]);
|
||||
|
||||
// Stamp the submission status modification date without triggering edit event
|
||||
if ($logEntry->getData('assocType') === PKPApplication::ASSOC_TYPE_SUBMISSION) {
|
||||
$submission = Repo::submission()->get($logEntry->getData('assocId'));
|
||||
$submission->stampLastActivity();
|
||||
Repo::submission()->dao->update($submission);
|
||||
}
|
||||
|
||||
return $id;
|
||||
}
|
||||
|
||||
/** @copydoc DAO::delete() */
|
||||
public function delete(EventLogEntry $logEntry)
|
||||
{
|
||||
Hook::call('EventLog::delete::before', [$logEntry]);
|
||||
$this->dao->delete($logEntry);
|
||||
Hook::call('EventLog::delete', [$logEntry]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete a collection of categories
|
||||
*/
|
||||
public function deleteMany(Collector $collector)
|
||||
{
|
||||
foreach ($collector->getMany() as $logEntry) {
|
||||
/** @var EventLogEntry $logEntry */
|
||||
$this->delete($logEntry);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @file classes/log/event/SubmissionFileEventLogEntry.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 SubmissionFileEventLogEntry
|
||||
*
|
||||
* @ingroup log
|
||||
*
|
||||
* @brief Describes an entry in the submission file history log.
|
||||
*/
|
||||
|
||||
namespace PKP\log\event;
|
||||
|
||||
class SubmissionFileEventLogEntry extends EventLogEntry
|
||||
{
|
||||
// File upload/delete event types.
|
||||
public const SUBMISSION_LOG_FILE_UPLOAD = 0x50000001;
|
||||
public const SUBMISSION_LOG_FILE_DELETE = 0x50000002;
|
||||
public const SUBMISSION_LOG_FILE_REVISION_UPLOAD = 0x50000008;
|
||||
public const SUBMISSION_LOG_FILE_EDIT = 0x50000010;
|
||||
|
||||
// Audit events
|
||||
public const SUBMISSION_LOG_FILE_AUDITOR_ASSIGN = 0x50000004;
|
||||
public const SUBMISSION_LOG_FILE_AUDITOR_CLEAR = 0x50000005;
|
||||
public const SUBMISSION_LOG_FILE_AUDIT_UPLOAD = 0x50000006;
|
||||
public const SUBMISSION_LOG_FILE_SIGNOFF_SIGNOFF = 0x50000007;
|
||||
|
||||
// Deprecated events. Preserve for historical logs
|
||||
public const SUBMISSION_LOG_FILE_REVISION_DELETE = 0x50000009; // uses submission.event.revisionDeleted
|
||||
}
|
||||
|
||||
if (!PKP_STRICT_MODE) {
|
||||
class_alias('\PKP\log\event\SubmissionFileEventLogEntry', '\SubmissionFileEventLogEntry');
|
||||
foreach ([
|
||||
'SUBMISSION_LOG_FILE_UPLOAD',
|
||||
'SUBMISSION_LOG_FILE_DELETE',
|
||||
'SUBMISSION_LOG_FILE_REVISION_UPLOAD',
|
||||
'SUBMISSION_LOG_FILE_EDIT',
|
||||
'SUBMISSION_LOG_FILE_AUDITOR_ASSIGN',
|
||||
'SUBMISSION_LOG_FILE_AUDITOR_CLEAR',
|
||||
'SUBMISSION_LOG_FILE_AUDIT_UPLOAD',
|
||||
'SUBMISSION_LOG_FILE_SIGNOFF_SIGNOFF',
|
||||
'SUBMISSION_LOG_FILE_REVISION_DELETE',
|
||||
] as $constantName) {
|
||||
define($constantName, constant('\SubmissionFileEventLogEntry::' . $constantName));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,89 @@
|
||||
<?php
|
||||
/**
|
||||
* @file classes/log/event/maps/Schema.php
|
||||
*
|
||||
* Copyright (c) 2014-2023 Simon Fraser University
|
||||
* Copyright (c) 2000-2023 John Willinsky
|
||||
* Distributed under the GNU GPL v3. For full terms see the file docs/COPYING.
|
||||
*
|
||||
* @class Schema
|
||||
*
|
||||
* @brief Map event log entries to the properties defined in the event log schema
|
||||
*/
|
||||
|
||||
namespace PKP\log\event\maps;
|
||||
|
||||
use Illuminate\Support\Enumerable;
|
||||
use PKP\log\event\EventLogEntry;
|
||||
use PKP\services\PKPSchemaService;
|
||||
|
||||
class Schema extends \PKP\core\maps\Schema
|
||||
{
|
||||
public Enumerable $collection;
|
||||
|
||||
public string $schema = PKPSchemaService::SCHEMA_EVENT_LOG;
|
||||
|
||||
/**
|
||||
* Map an event log
|
||||
*
|
||||
* Includes all properties in the event log entry schema.
|
||||
*/
|
||||
public function map(EventLogEntry $item): array
|
||||
{
|
||||
return $this->mapByProperties($this->getProps(), $item);
|
||||
}
|
||||
|
||||
/**
|
||||
* Summarize an event log
|
||||
*
|
||||
* Includes properties with the apiSummary flag in the event log entry schema.
|
||||
*/
|
||||
public function summarize(EventLogEntry $entry): array
|
||||
{
|
||||
return $this->mapByProperties($this->getSummaryProps(), $entry);
|
||||
}
|
||||
|
||||
/**
|
||||
* Map a collection of event log entries
|
||||
*
|
||||
* @see self::map
|
||||
*/
|
||||
public function mapMany(Enumerable $collection): Enumerable
|
||||
{
|
||||
$this->collection = $collection;
|
||||
return $collection->map(function ($category) {
|
||||
return $this->map($category);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Summarize a collection of event log entries
|
||||
*
|
||||
* @see self::summarize
|
||||
*/
|
||||
public function summarizeMany(Enumerable $collection): Enumerable
|
||||
{
|
||||
$this->collection = $collection;
|
||||
return $collection->map(function ($category) {
|
||||
return $this->summarize($category);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Map schema properties of an event log entry to an assoc array
|
||||
*/
|
||||
protected function mapByProperties(array $props, EventLogEntry $entry): array
|
||||
{
|
||||
$output = [];
|
||||
|
||||
foreach ($props as $prop) {
|
||||
switch ($prop) {
|
||||
default:
|
||||
$output[$prop] = $entry->getData($prop);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return $output;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user