<?php
/**
* @file classes/services/ContextService.php
*
* Copyright (c) 2014-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 ContextService
*
* @ingroup services
*
* @brief Extends the base context service class with app-specific
* requirements.
*/
namespace APP\services;
use APP\article\ArticleTombstoneManager;
use APP\core\Application;
use APP\facades\Repo;
use APP\file\PublicFileManager;
use APP\subscription\IndividualSubscriptionDAO;
use APP\subscription\InstitutionalSubscriptionDAO;
use APP\subscription\SubscriptionTypeDAO;
use PKP\config\Config;
use PKP\db\DAORegistry;
use PKP\file\TemporaryFileManager;
use PKP\plugins\Hook;
use PKP\submission\GenreDAO;
class ContextService extends \PKP\services\PKPContextService
{
/** @copydoc \PKP\services\PKPContextService::$contextsFileDirName */
public $contextsFileDirName = 'journals';
/**
* Initialize hooks for extending PKPContextService
*/
public function __construct()
{
$this->installFileDirs = [
Config::getVar('files', 'files_dir') . '/%s/%d',
Config::getVar('files', 'files_dir') . '/%s/%d/articles',
Config::getVar('files', 'files_dir') . '/%s/%d/issues',
Config::getVar('files', 'public_files_dir') . '/%s/%d',
];
Hook::add('Context::add', [$this, 'afterAddContext']);
Hook::add('Context::edit', [$this, 'afterEditContext']);
Hook::add('Context::delete::before', [$this, 'beforeDeleteContext']);
Hook::add('Context::delete', [$this, 'afterDeleteContext']);
Hook::add('Context::validate', [$this, 'validateContext']);
}
/**
* Take additional actions after a new context has been added
*
* @param string $hookName
* @param array $args [
*
* @option Journal The new context
* @option Request
* ]
*/
public function afterAddContext($hookName, $args)
{
$context = $args[0];
// Create a default section
$section = Repo::section()->newDataObject();
$section->setTitle(__('section.default.title'), $context->getPrimaryLocale());
$section->setAbbrev(__('section.default.abbrev'), $context->getPrimaryLocale());
$section->setMetaIndexed(true);
$section->setMetaReviewed(true);
$section->setPolicy(__('section.default.policy'), $context->getPrimaryLocale());
$section->setEditorRestricted(false);
$section->setHideTitle(false);
$section->setContextId($context->getId());
Repo::section()->add($section);
}
/**
* Update journal-specific settings when a context is edited
*
* @param string $hookName
* @param array $args [
*
* @option Journal The new context
* @option Journal The current context
* @option array The params to edit
* @option Request
* ]
*/
public function afterEditContext($hookName, $args)
{
$newContext = $args[0];
$currentContext = $args[1];
$params = $args[2];
$request = $args[3];
// Move an uploaded journal thumbnail and set the updated data
if (!empty($params['journalThumbnail'])) {
$supportedLocales = $newContext->getSupportedFormLocales();
foreach ($supportedLocales as $localeKey) {
if (!array_key_exists($localeKey, $params['journalThumbnail'])) {
continue;
}
$localeValue = $this->_saveFileParam(
$newContext,
$params['journalThumbnail'][$localeKey],
'journalThumbnail',
$request->getUser()->getId(),
$localeKey,
true
);
$newContext->setData('journalThumbnail', $localeValue, $localeKey);
}
}
// If the context is enabled or disabled, create or delete
// tombstones for all published submissions
if ($newContext->getData('enabled') !== $currentContext->getData('enabled')) {
$articleTombstoneManager = new ArticleTombstoneManager();
if ($newContext->getData('enabled')) {
$articleTombstoneManager->deleteTombstonesByContextId($newContext->getId());
} else {
$articleTombstoneManager->insertTombstonesByContext($newContext);
}
}
}
/**
* Perform actions before a context has been deleted
*
* This should only be used in cases where you need the context to still exist
* in the database to complete the actions. Otherwise, use
* ContextService::afterDeleteContext().
*
* @param string $hookName
* @param array $args [
*
* @option Context The new context
* @option Request
* ]
*/
public function beforeDeleteContext($hookName, $args)
{
$context = $args[0];
// Create tombstones for all published submissions
$articleTombstoneManager = new ArticleTombstoneManager();
$articleTombstoneManager->insertTombstonesByContext($context);
/** @var GenreDAO */
$genreDao = DAORegistry::getDAO('GenreDAO');
$genreDao->deleteByContextId($context->getId());
}
/**
* Take additional actions after a context has been deleted
*
* @param string $hookName
* @param array $args [
*
* @option Journal The new context
* @option Request
* ]
*/
public function afterDeleteContext($hookName, $args)
{
$context = $args[0];
Repo::section()->deleteByContextId($context->getId());
Repo::issue()->deleteByContextId($context->getId());
/** @var IndividualSubscriptionDAO */
$subscriptionDao = DAORegistry::getDAO('IndividualSubscriptionDAO');
$subscriptionDao->deleteByJournalId($context->getId());
/** @var InstitutionalSubscriptionDAO */
$subscriptionDao = DAORegistry::getDAO('InstitutionalSubscriptionDAO');
$subscriptionDao->deleteByJournalId($context->getId());
/** @var SubscriptionTypeDAO */
$subscriptionTypeDao = DAORegistry::getDAO('SubscriptionTypeDAO');
$subscriptionTypeDao->deleteByJournal($context->getId());
Repo::submission()->deleteByContextId($context->getId());
$publicFileManager = new PublicFileManager();
$publicFileManager->rmtree($publicFileManager->getContextFilesPath($context->getId()));
}
/**
* Make additional validation checks
*
* @param string $hookName
* @param array $args [
*
* @option Journal The new context
* @option Request
* ]
*/
public function validateContext($hookName, $args)
{
$errors = & $args[0];
$props = $args[2];
$allowedLocales = $args[3];
if (!isset($props['journalThumbnail'])) {
return;
}
// If a journal thumbnail is passed, check that the temporary file exists
// and the current user owns it
$user = Application::get()->getRequest()->getUser();
$userId = $user ? $user->getId() : null;
$temporaryFileManager = new TemporaryFileManager();
if (isset($props['journalThumbnail']) && empty($errors['journalThumbnail'])) {
foreach ($allowedLocales as $localeKey) {
if (empty($props['journalThumbnail'][$localeKey]) || empty($props['journalThumbnail'][$localeKey]['temporaryFileId'])) {
continue;
}
if (!$temporaryFileManager->getFile($props['journalThumbnail'][$localeKey]['temporaryFileId'], $userId)) {
if (!is_array($errors['journalThumbnail'])) {
$errors['journalThumbnail'] = [];
}
$errors['journalThumbnail'][$localeKey] = [__('common.noTemporaryFile')];
}
}
}
}
}
|