first commit
This commit is contained in:
@@ -0,0 +1,58 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @file pages/about/AboutHandler.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 AboutHandler
|
||||
*
|
||||
* @ingroup pages_about
|
||||
*
|
||||
* @brief Handle requests for journal about functions.
|
||||
*/
|
||||
|
||||
namespace APP\pages\about;
|
||||
|
||||
use APP\core\Application;
|
||||
use APP\subscription\SubscriptionTypeDAO;
|
||||
use APP\template\TemplateManager;
|
||||
use PKP\db\DAORegistry;
|
||||
|
||||
class AboutHandler extends \PKP\pages\about\AboutContextHandler
|
||||
{
|
||||
/**
|
||||
* Display about subscriptions page.
|
||||
*
|
||||
* @param array $args
|
||||
* @param \APP\core\Request $request
|
||||
*/
|
||||
public function subscriptions($args, $request)
|
||||
{
|
||||
$templateMgr = TemplateManager::getManager($request);
|
||||
$this->setupTemplate($request);
|
||||
$journal = $request->getJournal();
|
||||
/** @var SubscriptionTypeDAO */
|
||||
$subscriptionTypeDao = DAORegistry::getDAO('SubscriptionTypeDAO');
|
||||
|
||||
if ($journal) {
|
||||
$paymentManager = Application::getPaymentManager($journal);
|
||||
if (!($journal->getData('paymentsEnabled') && $paymentManager->isConfigured())) {
|
||||
$request->redirect(null, 'index');
|
||||
}
|
||||
}
|
||||
|
||||
$templateMgr->assign([
|
||||
'subscriptionAdditionalInformation' => $journal->getLocalizedData('subscriptionAdditionalInformation'),
|
||||
'subscriptionMailingAddress' => $journal->getData('subscriptionMailingAddress'),
|
||||
'subscriptionName' => $journal->getData('subscriptionName'),
|
||||
'subscriptionPhone' => $journal->getData('subscriptionPhone'),
|
||||
'subscriptionEmail' => $journal->getData('subscriptionEmail'),
|
||||
'individualSubscriptionTypes' => $subscriptionTypeDao->getByInstitutional($journal->getId(), false, false)->toArray(),
|
||||
'institutionalSubscriptionTypes' => $subscriptionTypeDao->getByInstitutional($journal->getId(), true, false)->toArray(),
|
||||
]);
|
||||
$templateMgr->display('frontend/pages/subscriptions.tpl');
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @defgroup pages_about About page
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file pages/about/index.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.
|
||||
*
|
||||
* @ingroup pages_about
|
||||
*
|
||||
* @brief Handle requests for about the journal functions.
|
||||
*
|
||||
*/
|
||||
|
||||
switch ($op) {
|
||||
case 'subscriptions':
|
||||
return new APP\pages\about\AboutHandler();
|
||||
default:
|
||||
// Fall back on pkp-lib implementation
|
||||
return require_once('lib/pkp/pages/about/index.php');
|
||||
}
|
||||
@@ -0,0 +1,610 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @file pages/article/ArticleHandler.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 ArticleHandler
|
||||
*
|
||||
* @ingroup pages_article
|
||||
*
|
||||
* @brief Handle requests for article functions.
|
||||
*
|
||||
*/
|
||||
|
||||
namespace APP\pages\article;
|
||||
|
||||
use APP\core\Application;
|
||||
use APP\core\Services;
|
||||
use APP\facades\Repo;
|
||||
use APP\handler\Handler;
|
||||
use APP\issue\IssueAction;
|
||||
use APP\observers\events\UsageEvent;
|
||||
use APP\payment\ojs\OJSCompletedPaymentDAO;
|
||||
use APP\payment\ojs\OJSPaymentManager;
|
||||
use APP\security\authorization\OjsJournalMustPublishPolicy;
|
||||
use APP\submission\Submission;
|
||||
use APP\template\TemplateManager;
|
||||
use Firebase\JWT\JWT;
|
||||
use PKP\citation\CitationDAO;
|
||||
use PKP\config\Config;
|
||||
use PKP\core\PKPApplication;
|
||||
use PKP\db\DAORegistry;
|
||||
use PKP\plugins\Hook;
|
||||
use PKP\plugins\PluginRegistry;
|
||||
use PKP\security\authorization\ContextRequiredPolicy;
|
||||
use PKP\security\Validation;
|
||||
use PKP\submission\Genre;
|
||||
use PKP\submission\GenreDAO;
|
||||
use PKP\submission\PKPSubmission;
|
||||
use PKP\submissionFile\SubmissionFile;
|
||||
|
||||
class ArticleHandler extends Handler
|
||||
{
|
||||
/** @var \APP\journal\Journal Context associated with the request */
|
||||
public $context;
|
||||
|
||||
/** @var ?\APP\issue\Issue Issue associated with the request */
|
||||
public $issue;
|
||||
|
||||
/** @var \APP\submission\Submission Submission associated with the request */
|
||||
public $article;
|
||||
|
||||
/** @var \PKP\category\Category Category associated with the request */
|
||||
public $categories;
|
||||
|
||||
/** @var \APP\publication\Publication Publication associated with the request */
|
||||
public $publication;
|
||||
|
||||
/** @var \PKP\galley\Galley galley associated with the request */
|
||||
public $galley;
|
||||
|
||||
/** @var int submissionFileId associated with the request */
|
||||
public $submissionFileId;
|
||||
|
||||
|
||||
/**
|
||||
* @copydoc PKPHandler::authorize()
|
||||
*/
|
||||
public function authorize($request, &$args, $roleAssignments)
|
||||
{
|
||||
// Permit the use of the Authorization header and an API key for access to unpublished/subscription content
|
||||
if ($header = array_search('Authorization', array_flip(getallheaders()))) {
|
||||
[$bearer, $jwt] = explode(' ', $header);
|
||||
if (strcasecmp($bearer, 'Bearer') == 0 && !empty($jwt)) {
|
||||
$secret = Config::getVar('security', 'api_key_secret', '');
|
||||
if (!$secret) {
|
||||
$templateMgr = TemplateManager::getManager($request);
|
||||
$templateMgr->assign('message', 'api.500.apiSecretKeyMissing');
|
||||
return $templateMgr->display('frontend/pages/message.tpl');
|
||||
}
|
||||
try {
|
||||
$apiToken = JWT::decode($jwt, $secret, ['HS256']);
|
||||
// Compatibility with old API keys
|
||||
// https://github.com/pkp/pkp-lib/issues/6462
|
||||
if (substr($apiToken, 0, 2) === '""') {
|
||||
$apiToken = json_decode($apiToken);
|
||||
}
|
||||
$this->setApiToken($apiToken);
|
||||
} catch (\Exception $e) {
|
||||
$templateMgr = TemplateManager::getManager($request);
|
||||
$templateMgr->assign('message', 'api.400.invalidApiToken');
|
||||
return $templateMgr->display('frontend/pages/message.tpl');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$this->addPolicy(new ContextRequiredPolicy($request));
|
||||
|
||||
$this->addPolicy(new OjsJournalMustPublishPolicy($request));
|
||||
|
||||
return parent::authorize($request, $args, $roleAssignments);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see PKPHandler::initialize()
|
||||
*
|
||||
* @param \APP\core\Request $request
|
||||
* @param array $args Arguments list
|
||||
*/
|
||||
public function initialize($request, $args = [])
|
||||
{
|
||||
$urlPath = empty($args) ? 0 : array_shift($args);
|
||||
|
||||
// Get the submission that matches the requested urlPath
|
||||
$submission = ctype_digit((string) $urlPath)
|
||||
? Repo::submission()->get((int) $urlPath, $request->getContext()->getId())
|
||||
: Repo::submission()->getByUrlPath($urlPath, $request->getContext()->getId());
|
||||
|
||||
$user = $request->getUser();
|
||||
|
||||
// Serve 404 if no submission available OR submission is unpublished and no user is logged in OR submission is unpublished and we have a user logged in but the user does not have access to preview
|
||||
if (!$submission || ($submission->getData('status') !== PKPSubmission::STATUS_PUBLISHED && !$user) || ($submission->getData('status') !== PKPSubmission::STATUS_PUBLISHED && $user && !Repo::submission()->canPreview($user, $submission))) {
|
||||
$request->getDispatcher()->handle404();
|
||||
}
|
||||
|
||||
// If the urlPath does not match the urlPath of the current
|
||||
// publication, redirect to the current URL
|
||||
$currentUrlPath = $submission->getBestId();
|
||||
if ($currentUrlPath && $currentUrlPath != $urlPath) {
|
||||
$newArgs = array_merge([$currentUrlPath], $args);
|
||||
$request->redirect(null, $request->getRequestedPage(), $request->getRequestedOp(), $newArgs);
|
||||
}
|
||||
|
||||
$this->article = $submission;
|
||||
// Get the requested publication or if none requested get the current publication
|
||||
$subPath = empty($args) ? 0 : array_shift($args);
|
||||
if ($subPath === 'version') {
|
||||
$publicationId = (int) array_shift($args);
|
||||
$galleyId = empty($args) ? 0 : array_shift($args);
|
||||
foreach ($this->article->getData('publications') as $publication) {
|
||||
if ($publication->getId() === $publicationId) {
|
||||
$this->publication = $publication;
|
||||
}
|
||||
}
|
||||
if (!$this->publication) {
|
||||
$request->getDispatcher()->handle404();
|
||||
}
|
||||
} else {
|
||||
$this->publication = $this->article->getCurrentPublication();
|
||||
$galleyId = $subPath;
|
||||
}
|
||||
|
||||
if ($this->publication->getData('status') !== PKPSubmission::STATUS_PUBLISHED && !Repo::submission()->canPreview($user, $submission)) {
|
||||
$request->getDispatcher()->handle404();
|
||||
}
|
||||
|
||||
if ($galleyId && in_array($request->getRequestedOp(), ['view', 'download'])) {
|
||||
$galleys = $this->publication->getData('galleys');
|
||||
foreach ($galleys as $galley) {
|
||||
if ($galley->getBestGalleyId() == $galleyId) {
|
||||
$this->galley = $galley;
|
||||
break;
|
||||
|
||||
// In some cases, a URL to a galley may use the ID when it should use
|
||||
// the urlPath. Redirect to the galley's correct URL.
|
||||
} elseif (ctype_digit($galleyId) && $galley->getId() == $galleyId) {
|
||||
$request->redirect(null, $request->getRequestedPage(), $request->getRequestedOp(), [$submission->getBestId(), $galley->getBestGalleyId()]);
|
||||
}
|
||||
}
|
||||
// Redirect to the most recent version of the submission if the request
|
||||
// points to an outdated galley but doesn't use the specific versioned
|
||||
// URL. This can happen when a galley's urlPath is changed between versions.
|
||||
if (!$this->galley) {
|
||||
$publications = $submission->getPublishedPublications();
|
||||
foreach ($publications as $publication) {
|
||||
foreach ($publication->getData('galleys') as $galley) {
|
||||
if ($galley->getBestGalleyId() == $galleyId) {
|
||||
$request->redirect(null, $request->getRequestedPage(), $request->getRequestedOp(), [$submission->getBestId()]);
|
||||
}
|
||||
}
|
||||
}
|
||||
$request->getDispatcher()->handle404();
|
||||
}
|
||||
|
||||
// Store the file id if it exists
|
||||
if (!empty($args)) {
|
||||
$this->submissionFileId = array_shift($args);
|
||||
}
|
||||
}
|
||||
|
||||
if ($this->publication->getData('issueId')) {
|
||||
// TODO: Previously fetched issue from cache. Reimplement when caching added.
|
||||
$issue = Repo::issue()->get($this->publication->getData('issueId'));
|
||||
$issue = $issue->getJournalId() == $submission->getData('contextId') ? $issue : null;
|
||||
$this->issue = $issue;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* View Article. (Either article landing page or galley view.)
|
||||
*
|
||||
* @param array $args
|
||||
* @param \APP\core\Request $request
|
||||
*/
|
||||
public function view($args, $request)
|
||||
{
|
||||
$context = $request->getContext();
|
||||
$user = $request->getUser();
|
||||
$issue = $this->issue;
|
||||
$article = $this->article;
|
||||
$publication = $this->publication;
|
||||
$templateMgr = TemplateManager::getManager($request);
|
||||
$templateMgr->assign([
|
||||
'issue' => $issue,
|
||||
'article' => $article,
|
||||
'publication' => $publication,
|
||||
'currentPublication' => $article->getCurrentPublication(),
|
||||
'galley' => $this->galley,
|
||||
'fileId' => $this->submissionFileId, // DEPRECATED in 3.4.0: https://github.com/pkp/pkp-lib/issues/6545
|
||||
'submissionFileId' => $this->submissionFileId,
|
||||
]);
|
||||
$this->setupTemplate($request);
|
||||
|
||||
// Get the earliest published publication
|
||||
$firstPublication = $article->getData('publications')->reduce(function ($a, $b) {
|
||||
return empty($a) || strtotime((string) $b->getData('datePublished')) < strtotime((string) $a->getData('datePublished')) ? $b : $a;
|
||||
}, 0);
|
||||
$templateMgr->assign([
|
||||
'firstPublication' => $firstPublication,
|
||||
]);
|
||||
|
||||
$templateMgr->assign([
|
||||
'ccLicenseBadge' => Application::get()->getCCLicenseBadge($publication->getData('licenseUrl')),
|
||||
'publication' => $publication,
|
||||
'section' => Repo::section()->get($publication->getData('sectionId')),
|
||||
]);
|
||||
|
||||
if ($this->galley && !$this->userCanViewGalley($request, $article->getId(), $this->galley->getId())) {
|
||||
fatalError('Cannot view galley.');
|
||||
}
|
||||
|
||||
$templateMgr->assign([
|
||||
'categories' => Repo::category()->getCollector()
|
||||
->filterByPublicationIds([$publication->getId()])
|
||||
->getMany()
|
||||
->toArray()
|
||||
]);
|
||||
|
||||
// Get galleys sorted into primary and supplementary groups
|
||||
$galleys = $publication->getData('galleys');
|
||||
|
||||
$primaryGalleys = [];
|
||||
$supplementaryGalleys = [];
|
||||
if ($galleys) {
|
||||
$genreDao = DAORegistry::getDAO('GenreDAO'); /** @var GenreDAO $genreDao */
|
||||
$primaryGenres = $genreDao->getPrimaryByContextId($context->getId())->toArray();
|
||||
$primaryGenreIds = array_map(function ($genre) {
|
||||
return $genre->getId();
|
||||
}, $primaryGenres);
|
||||
$supplementaryGenres = $genreDao->getBySupplementaryAndContextId(true, $context->getId())->toArray();
|
||||
$supplementaryGenreIds = array_map(function ($genre) {
|
||||
return $genre->getId();
|
||||
}, $supplementaryGenres);
|
||||
|
||||
foreach ($galleys as $galley) {
|
||||
$remoteUrl = $galley->getRemoteURL();
|
||||
$file = Repo::submissionFile()->get((int) $galley->getData('submissionFileId'));
|
||||
if (!$remoteUrl && !$file) {
|
||||
continue;
|
||||
}
|
||||
if ($remoteUrl || in_array($file->getGenreId(), $primaryGenreIds)) {
|
||||
$primaryGalleys[] = $galley;
|
||||
} elseif (in_array($file->getGenreId(), $supplementaryGenreIds)) {
|
||||
$supplementaryGalleys[] = $galley;
|
||||
}
|
||||
}
|
||||
}
|
||||
$templateMgr->assign([
|
||||
'primaryGalleys' => $primaryGalleys,
|
||||
'supplementaryGalleys' => $supplementaryGalleys,
|
||||
'userGroupsById' => Repo::userGroup()->getCollector()->filterByPublicationIds([$this->publication->getId()])->getMany()->toArray()
|
||||
]);
|
||||
|
||||
// Citations
|
||||
if ($publication->getData('citationsRaw')) {
|
||||
$citationDao = DAORegistry::getDAO('CitationDAO'); /** @var CitationDAO $citationDao */
|
||||
$parsedCitations = $citationDao->getByPublicationId($publication->getId());
|
||||
$templateMgr->assign([
|
||||
'parsedCitations' => $parsedCitations->toArray(),
|
||||
]);
|
||||
}
|
||||
|
||||
// Assign deprecated values to the template manager for
|
||||
// compatibility with older themes
|
||||
$templateMgr->assign([
|
||||
'licenseTerms' => $context->getLocalizedData('licenseTerms'),
|
||||
'licenseUrl' => $publication->getData('licenseUrl'),
|
||||
'copyrightHolder' => $publication->getLocalizedData('copyrightHolder'),
|
||||
'copyrightYear' => $publication->getData('copyrightYear'),
|
||||
'pubIdPlugins' => PluginRegistry::loadCategory('pubIds', true),
|
||||
'keywords' => $publication->getData('keywords'),
|
||||
]);
|
||||
|
||||
// Fetch and assign the galley to the template
|
||||
if ($this->galley && $this->galley->getRemoteURL()) {
|
||||
$request->redirectUrl($this->galley->getRemoteURL());
|
||||
}
|
||||
|
||||
if (empty($this->galley)) {
|
||||
// No galley: Prepare the article landing page.
|
||||
|
||||
// Ask robots not to index outdated versions and point to the canonical url for the latest version
|
||||
if ($publication->getId() !== $article->getCurrentPublication()->getId()) {
|
||||
$templateMgr->addHeader('noindex', '<meta name="robots" content="noindex">');
|
||||
$url = $request->getDispatcher()->url($request, PKPApplication::ROUTE_PAGE, null, 'article', 'view', $article->getBestId());
|
||||
$templateMgr->addHeader('canonical', '<link rel="canonical" href="' . $url . '">');
|
||||
}
|
||||
|
||||
// Get the subscription status if displaying the abstract;
|
||||
// if access is open, we can display links to the full text.
|
||||
|
||||
// The issue may not exist, if this is an editorial user
|
||||
// and scheduling hasn't been completed yet for the article.
|
||||
$issueAction = new IssueAction();
|
||||
$subscriptionRequired = false;
|
||||
if ($issue) {
|
||||
$subscriptionRequired = $issueAction->subscriptionRequired($issue, $context);
|
||||
}
|
||||
|
||||
$subscribedUser = $issueAction->subscribedUser($user, $context, isset($issue) ? $issue->getId() : null, isset($article) ? $article->getId() : null);
|
||||
$subscribedDomain = $issueAction->subscribedDomain($request, $context, isset($issue) ? $issue->getId() : null, isset($article) ? $article->getId() : null);
|
||||
|
||||
$completedPaymentDao = DAORegistry::getDAO('OJSCompletedPaymentDAO'); /** @var OJSCompletedPaymentDAO $completedPaymentDao */
|
||||
$templateMgr->assign(
|
||||
'hasAccess',
|
||||
!$subscriptionRequired ||
|
||||
$publication->getData('accessStatus') == Submission::ARTICLE_ACCESS_OPEN ||
|
||||
$subscribedUser || $subscribedDomain ||
|
||||
($user && $issue && $completedPaymentDao->hasPaidPurchaseIssue($user->getId(), $issue->getId())) ||
|
||||
($user && $completedPaymentDao->hasPaidPurchaseArticle($user->getId(), $article->getId()))
|
||||
);
|
||||
|
||||
$paymentManager = Application::get()->getPaymentManager($context);
|
||||
if ($paymentManager->onlyPdfEnabled()) {
|
||||
$templateMgr->assign('restrictOnlyPdf', true);
|
||||
}
|
||||
if ($paymentManager->purchaseArticleEnabled()) {
|
||||
$templateMgr->assign('purchaseArticleEnabled', true);
|
||||
}
|
||||
|
||||
if (!Hook::call('ArticleHandler::view', [&$request, &$issue, &$article, $publication])) {
|
||||
$templateMgr->display('frontend/pages/article.tpl');
|
||||
event(new UsageEvent(Application::ASSOC_TYPE_SUBMISSION, $context, $article, null, null, $this->issue));
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
// Ask robots not to index outdated versions
|
||||
if ($publication->getId() !== $article->getCurrentPublication()->getId()) {
|
||||
$templateMgr->addHeader('noindex', '<meta name="robots" content="noindex">');
|
||||
}
|
||||
|
||||
// Galley: Prepare the galley file download.
|
||||
if (!Hook::call('ArticleHandler::view::galley', [&$request, &$issue, &$this->galley, &$article, $publication])) {
|
||||
if ($this->publication->getId() !== $this->article->getCurrentPublication()->getId()) {
|
||||
$redirectPath = [
|
||||
$article->getBestId(),
|
||||
'version',
|
||||
$publication->getId(),
|
||||
$this->galley->getBestGalleyId()
|
||||
];
|
||||
} else {
|
||||
$redirectPath = [
|
||||
$article->getBestId(),
|
||||
$this->galley->getBestGalleyId()
|
||||
];
|
||||
}
|
||||
$request->redirect(null, null, 'download', $redirectPath);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Download an article file
|
||||
* For deprecated OJS 2.x URLs; see https://github.com/pkp/pkp-lib/issues/1541
|
||||
*
|
||||
* @param array $args
|
||||
* @param \APP\core\Request $request
|
||||
*/
|
||||
public function viewFile($args, $request)
|
||||
{
|
||||
$articleId = $args[0] ?? 0;
|
||||
$galleyId = $args[1] ?? 0;
|
||||
$submissionFileId = isset($args[2]) ? (int) $args[2] : 0;
|
||||
header('HTTP/1.1 301 Moved Permanently');
|
||||
$request->redirect(null, null, 'download', [$articleId, $galleyId, $submissionFileId]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Download a supplementary file.
|
||||
* For deprecated OJS 2.x URLs; see https://github.com/pkp/pkp-lib/issues/1541
|
||||
*
|
||||
* @param array $args
|
||||
* @param \APP\core\Request $request
|
||||
*/
|
||||
public function downloadSuppFile($args, $request)
|
||||
{
|
||||
$articleId = $args[0] ?? 0;
|
||||
$article = Repo::submission()->get($articleId);
|
||||
if (!$article) {
|
||||
$dispatcher = $request->getDispatcher();
|
||||
$dispatcher->handle404();
|
||||
}
|
||||
$suppId = $args[1] ?? 0;
|
||||
|
||||
$submissionFiles = Repo::submissionFile()
|
||||
->getCollector()
|
||||
->filterBySubmissionIds([$article->getId()])
|
||||
->getMany();
|
||||
|
||||
foreach ($submissionFiles as $submissionFile) {
|
||||
if ($submissionFile->getData('old-supp-id') == $suppId) {
|
||||
$articleGalleys = Repo::galley()->getCollector()
|
||||
->filterByPublicationIds([$article->getCurrentPublication()->getId()])
|
||||
->getMany();
|
||||
|
||||
foreach ($articleGalleys as $articleGalley) {
|
||||
$galleyFile = Repo::submissionFile()->get($articleGalley->getData('submissionFileId'));
|
||||
if ($galleyFile && $galleyFile->getData('submissionFileId') == $submissionFile->getId()) {
|
||||
header('HTTP/1.1 301 Moved Permanently');
|
||||
$request->redirect(null, null, 'download', [$articleId, $articleGalley->getId(), $submissionFile->getId()]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
$dispatcher = $request->getDispatcher();
|
||||
$dispatcher->handle404();
|
||||
}
|
||||
|
||||
/**
|
||||
* Download an article file
|
||||
*
|
||||
* @param array $args
|
||||
* @param \APP\core\Request $request
|
||||
*/
|
||||
public function download($args, $request)
|
||||
{
|
||||
if (!isset($this->galley)) {
|
||||
$request->getDispatcher()->handle404();
|
||||
}
|
||||
if ($this->galley->getRemoteURL()) {
|
||||
$request->redirectUrl($this->galley->getRemoteURL());
|
||||
} elseif ($this->userCanViewGalley($request, $this->article->getId(), $this->galley->getId())) {
|
||||
if (!$this->submissionFileId) {
|
||||
$this->submissionFileId = $this->galley->getData('submissionFileId');
|
||||
}
|
||||
|
||||
// If no file ID could be determined, treat it as a 404.
|
||||
if (!$this->submissionFileId) {
|
||||
$request->getDispatcher()->handle404();
|
||||
}
|
||||
|
||||
// If the file ID is not the galley's file ID, ensure it is a dependent file, or else 404.
|
||||
if ($this->submissionFileId != $this->galley->getData('submissionFileId')) {
|
||||
$dependentFileIds = Repo::submissionFile()
|
||||
->getCollector()
|
||||
->filterByAssoc(
|
||||
Application::ASSOC_TYPE_SUBMISSION_FILE,
|
||||
[$this->galley->getData('submissionFileId')]
|
||||
)
|
||||
->filterByFileStages([SubmissionFile::SUBMISSION_FILE_DEPENDENT])
|
||||
->includeDependentFiles()
|
||||
->getIds()
|
||||
->toArray();
|
||||
|
||||
if (!in_array($this->submissionFileId, $dependentFileIds)) {
|
||||
$request->getDispatcher()->handle404();
|
||||
}
|
||||
}
|
||||
|
||||
if (!Hook::call('ArticleHandler::download', [$this->article, &$this->galley, &$this->submissionFileId])) {
|
||||
$submissionFile = Repo::submissionFile()->get($this->submissionFileId);
|
||||
|
||||
if (!Services::get('file')->fs->has($submissionFile->getData('path'))) {
|
||||
$request->getDispatcher()->handle404();
|
||||
}
|
||||
|
||||
$filename = Services::get('file')->formatFilename($submissionFile->getData('path'), $submissionFile->getLocalizedData('name'));
|
||||
|
||||
// if the file is a galley file (i.e. not a dependent file e.g. CSS or images), fire an usage event.
|
||||
if ($this->galley->getData('submissionFileId') == $this->submissionFileId) {
|
||||
$assocType = Application::ASSOC_TYPE_SUBMISSION_FILE;
|
||||
/** @var GenreDAO */
|
||||
$genreDao = DAORegistry::getDAO('GenreDAO');
|
||||
$genre = $genreDao->getById($submissionFile->getData('genreId'));
|
||||
// TO-DO: is this correct ?
|
||||
if ($genre->getCategory() != Genre::GENRE_CATEGORY_DOCUMENT || $genre->getSupplementary() || $genre->getDependent()) {
|
||||
$assocType = Application::ASSOC_TYPE_SUBMISSION_FILE_COUNTER_OTHER;
|
||||
}
|
||||
event(new UsageEvent($assocType, $request->getContext(), $this->article, $this->galley, $submissionFile, $this->issue));
|
||||
}
|
||||
$returner = true;
|
||||
Hook::call('FileManager::downloadFileFinished', [&$returner]);
|
||||
Services::get('file')->download($submissionFile->getData('fileId'), $filename);
|
||||
}
|
||||
} else {
|
||||
header('HTTP/1.0 403 Forbidden');
|
||||
echo '403 Forbidden<br>';
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines whether a user can view this article galley or not.
|
||||
*
|
||||
* @param \APP\core\Request $request
|
||||
* @param string $articleId
|
||||
* @param int|string $galleyId
|
||||
*/
|
||||
public function userCanViewGalley($request, $articleId, $galleyId = null)
|
||||
{
|
||||
$issueAction = new IssueAction();
|
||||
|
||||
$context = $request->getContext();
|
||||
$submission = $this->article;
|
||||
$issue = $this->issue;
|
||||
$contextId = $context->getId();
|
||||
$user = $request->getUser();
|
||||
$userId = $user ? $user->getId() : 0;
|
||||
|
||||
// If this is an editorial user who can view unpublished/unscheduled
|
||||
// articles, bypass further validation. Likewise for its author.
|
||||
if ($submission && $user && Repo::submission()->canPreview($user, $submission)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Make sure the reader has rights to view the article/issue.
|
||||
if ($issue && $issue->getPublished() && $submission->getStatus() == PKPSubmission::STATUS_PUBLISHED) {
|
||||
$subscriptionRequired = $issueAction->subscriptionRequired($issue, $context);
|
||||
$isSubscribedDomain = $issueAction->subscribedDomain($request, $context, $issue->getId(), $submission->getId());
|
||||
|
||||
// Check if login is required for viewing.
|
||||
if (!$isSubscribedDomain && !Validation::isLoggedIn() && $context->getData('restrictArticleAccess') && isset($galleyId) && $galleyId) {
|
||||
Validation::redirectLogin();
|
||||
}
|
||||
|
||||
// bypass all validation if subscription based on domain or ip is valid
|
||||
// or if the user is just requesting the abstract
|
||||
if ((!$isSubscribedDomain && $subscriptionRequired) && (isset($galleyId) && $galleyId)) {
|
||||
// Subscription Access
|
||||
$subscribedUser = $issueAction->subscribedUser($user, $context, $issue->getId(), $submission->getId());
|
||||
|
||||
$paymentManager = Application::get()->getPaymentManager($context);
|
||||
|
||||
$purchasedIssue = false;
|
||||
if (!$subscribedUser && $paymentManager->purchaseIssueEnabled()) {
|
||||
$completedPaymentDao = DAORegistry::getDAO('OJSCompletedPaymentDAO'); /** @var OJSCompletedPaymentDAO $completedPaymentDao */
|
||||
$purchasedIssue = $completedPaymentDao->hasPaidPurchaseIssue($userId, $issue->getId());
|
||||
}
|
||||
|
||||
if (!(!$subscriptionRequired || $submission->getCurrentPublication()->getData('accessStatus') == Submission::ARTICLE_ACCESS_OPEN || $subscribedUser || $purchasedIssue)) {
|
||||
if ($paymentManager->purchaseArticleEnabled() || $paymentManager->membershipEnabled()) {
|
||||
/* if only pdf files are being restricted, then approve all non-pdf galleys
|
||||
* and continue checking if it is a pdf galley */
|
||||
if ($paymentManager->onlyPdfEnabled()) {
|
||||
if ($this->galley && !$this->galley->isPdfGalley()) {
|
||||
$this->issue = $issue;
|
||||
$this->article = $submission;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
if (!Validation::isLoggedIn()) {
|
||||
Validation::redirectLogin('payment.loginRequired.forArticle');
|
||||
}
|
||||
|
||||
/* if the article has been paid for then forget about everything else
|
||||
* and just let them access the article */
|
||||
$completedPaymentDao = DAORegistry::getDAO('OJSCompletedPaymentDAO'); /** @var OJSCompletedPaymentDAO $completedPaymentDao */
|
||||
$dateEndMembership = $user->getData('dateEndMembership', 0);
|
||||
if ($completedPaymentDao->hasPaidPurchaseArticle($userId, $submission->getId())
|
||||
|| (!is_null($dateEndMembership) && $dateEndMembership > time())) {
|
||||
$this->issue = $issue;
|
||||
$this->article = $submission;
|
||||
return true;
|
||||
} elseif ($paymentManager->purchaseArticleEnabled()) {
|
||||
$queuedPayment = $paymentManager->createQueuedPayment($request, OJSPaymentManager::PAYMENT_TYPE_PURCHASE_ARTICLE, $user->getId(), $submission->getId(), $context->getData('purchaseArticleFee'));
|
||||
$paymentManager->queuePayment($queuedPayment);
|
||||
|
||||
$paymentForm = $paymentManager->getPaymentForm($queuedPayment);
|
||||
$paymentForm->display($request);
|
||||
exit;
|
||||
}
|
||||
}
|
||||
|
||||
if (!isset($galleyId) || $galleyId) {
|
||||
if (!Validation::isLoggedIn()) {
|
||||
Validation::redirectLogin('reader.subscriptionRequiredLoginText');
|
||||
}
|
||||
$request->redirect(null, 'about', 'subscriptions');
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
$request->redirect(null, 'search');
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @defgroup pages_article Article Pages
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file pages/article/index.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.
|
||||
*
|
||||
* @ingroup pages_article
|
||||
*
|
||||
* @brief Handle requests for article functions.
|
||||
*
|
||||
*/
|
||||
|
||||
switch ($op) {
|
||||
case 'viewFile': // Old URLs; see https://github.com/pkp/pkp-lib/issues/1541
|
||||
case 'downloadSuppFile': // Old URLs; see https://github.com/pkp/pkp-lib/issues/1541
|
||||
case 'view':
|
||||
case 'download':
|
||||
define('HANDLER_CLASS', 'APP\pages\article\ArticleHandler');
|
||||
break;
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @file pages/authorDashboard/AuthorDashboardHandler.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 AuthorDashboardHandler
|
||||
*
|
||||
* @ingroup pages_authorDashboard
|
||||
*
|
||||
* @brief Handle requests for the author dashboard.
|
||||
*/
|
||||
|
||||
namespace APP\pages\authorDashboard;
|
||||
|
||||
use APP\facades\Repo;
|
||||
use APP\publication\Publication;
|
||||
use PKP\components\forms\publication\TitleAbstractForm;
|
||||
use PKP\context\Context;
|
||||
use PKP\core\PKPApplication;
|
||||
use PKP\pages\authorDashboard\PKPAuthorDashboardHandler;
|
||||
|
||||
class AuthorDashboardHandler extends PKPAuthorDashboardHandler
|
||||
{
|
||||
protected function _getRepresentationsGridUrl($request, $submission)
|
||||
{
|
||||
return $request->getDispatcher()->url(
|
||||
$request,
|
||||
PKPApplication::ROUTE_COMPONENT,
|
||||
null,
|
||||
'grid.articleGalleys.ArticleGalleyGridHandler',
|
||||
'fetchGrid',
|
||||
null,
|
||||
[
|
||||
'submissionId' => $submission->getId(),
|
||||
'publicationId' => '__publicationId__',
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
protected function getTitleAbstractForm(string $latestPublicationApiUrl, array $locales, Publication $latestPublication, Context $context): TitleAbstractForm
|
||||
{
|
||||
$section = Repo::section()->get($latestPublication->getData('sectionId'), $context->getId());
|
||||
return new TitleAbstractForm(
|
||||
$latestPublicationApiUrl,
|
||||
$locales,
|
||||
$latestPublication,
|
||||
(int) $section->getData('wordCount'),
|
||||
!$section->getData('abstractsNotRequired')
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @defgroup pages_authorDashboard Author Dashboard Pages
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file pages/authorDashboard/index.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.
|
||||
*
|
||||
* @ingroup pages_authorDashboard
|
||||
*
|
||||
* @brief Handle requests for the author dashboard.
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
switch ($op) {
|
||||
//
|
||||
// Author Dashboard
|
||||
//
|
||||
case 'submission':
|
||||
case 'readSubmissionEmail':
|
||||
case 'reviewRoundInfo':
|
||||
define('HANDLER_CLASS', 'APP\pages\authorDashboard\AuthorDashboardHandler');
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @defgroup pages_catalog Catalog page
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file pages/catalog/index.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.
|
||||
*
|
||||
* @ingroup pages_catalog
|
||||
*
|
||||
* @brief Handle requests for the public catalog view.
|
||||
*
|
||||
*/
|
||||
|
||||
switch ($op) {
|
||||
case 'category':
|
||||
case 'fullSize':
|
||||
case 'thumbnail':
|
||||
define('HANDLER_CLASS', 'PKP\pages\catalog\PKPCatalogHandler');
|
||||
break;
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @defgroup pages_decision Editorial decision pages
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file pages/decision/index.php
|
||||
*
|
||||
* Copyright (c) 2014-2022 Simon Fraser University
|
||||
* Copyright (c) 2003-2022 John Willinsky
|
||||
* Distributed under the GNU GPL v3. For full terms see the file docs/COPYING.
|
||||
*
|
||||
* @ingroup pages_decision
|
||||
*
|
||||
* @brief Handle requests to take an editorial decision
|
||||
*
|
||||
*/
|
||||
|
||||
define('HANDLER_CLASS', 'PKP\pages\decision\DecisionHandler');
|
||||
@@ -0,0 +1,91 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @file /pages/dois/DoiManagementHandler.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 DoisHandler
|
||||
*
|
||||
* @ingroup pages_doi
|
||||
*
|
||||
* @brief Handle requests for DOI management functions.
|
||||
*/
|
||||
|
||||
namespace APP\pages\dois;
|
||||
|
||||
use APP\components\listPanels\DoiListPanel;
|
||||
use APP\facades\Repo;
|
||||
use PKP\core\PKPApplication;
|
||||
use PKP\pages\dois\PKPDoisHandler;
|
||||
|
||||
class DoisHandler extends PKPDoisHandler
|
||||
{
|
||||
/**
|
||||
* Set app-specific state components to appear on DOI management page
|
||||
*/
|
||||
protected function getAppStateComponents(\APP\core\Request $request, array $enabledDoiTypes, array $commonArgs): array
|
||||
{
|
||||
$context = $request->getContext();
|
||||
|
||||
$stateComponents = [];
|
||||
|
||||
// Publication and Galley DOIs
|
||||
if (count(array_intersect($enabledDoiTypes, [Repo::doi()::TYPE_PUBLICATION, Repo::doi()::TYPE_REPRESENTATION])) > 0) {
|
||||
$submissionDoiListPanel = new DoiListPanel(
|
||||
'submissionDoiListPanel',
|
||||
__('doi.manager.submissionDois'),
|
||||
array_merge(
|
||||
$commonArgs,
|
||||
[
|
||||
'apiUrl' => $request->getDispatcher()->url($request, PKPApplication::ROUTE_API, $context->getPath(), 'submissions'),
|
||||
'getParams' => [
|
||||
'stageIds' => [WORKFLOW_STAGE_ID_EDITING, WORKFLOW_STAGE_ID_PRODUCTION],
|
||||
],
|
||||
'isSubmission' => true,
|
||||
'includeIssuesFilter' => true,
|
||||
'itemType' => 'submission'
|
||||
]
|
||||
)
|
||||
);
|
||||
$stateComponents[$submissionDoiListPanel->id] = $submissionDoiListPanel->getConfig();
|
||||
}
|
||||
|
||||
// Issues DOIs
|
||||
if (in_array(Repo::doi()::TYPE_ISSUE, $enabledDoiTypes)) {
|
||||
$issueDoiListPanel = new DoiListPanel(
|
||||
'issueDoiListPanel',
|
||||
__('doi.manager.issueDois'),
|
||||
array_merge(
|
||||
$commonArgs,
|
||||
[
|
||||
'apiUrl' => $request->getDispatcher()->url($request, PKPApplication::ROUTE_API, $context->getPath(), 'issues'),
|
||||
'getParams' => [],
|
||||
'isSubmission' => false,
|
||||
'includeIssuesFilter' => false,
|
||||
'itemType' => 'issue',
|
||||
]
|
||||
)
|
||||
);
|
||||
$stateComponents[$issueDoiListPanel->id] = $issueDoiListPanel->getConfig();
|
||||
}
|
||||
return $stateComponents;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set Smarty template variables. Which tabs to display are set by the APP.
|
||||
*/
|
||||
protected function getTemplateVariables(array $enabledDoiTypes): array
|
||||
{
|
||||
$templateVariables = parent::getTemplateVariables($enabledDoiTypes);
|
||||
return array_merge(
|
||||
$templateVariables,
|
||||
[
|
||||
'displaySubmissionsTab' => count(array_intersect($enabledDoiTypes, [Repo::doi()::TYPE_PUBLICATION, Repo::doi()::TYPE_REPRESENTATION])) > 0,
|
||||
'displayIssuesTab' => in_array(Repo::doi()::TYPE_ISSUE, $enabledDoiTypes),
|
||||
]
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
<?php
|
||||
/**
|
||||
* @defgroup pages_doiManagement DOI Management Pages
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file pages/doiManagement/index.php
|
||||
*
|
||||
* Copyright (c) 2014-2020 Simon Fraser University
|
||||
* Copyright (c) 2003-2020 John Willinsky
|
||||
* Distributed under the GNU GPL v3. For full terms see the file docs/COPYING.
|
||||
*
|
||||
* @ingroup pages_doiManagement
|
||||
*
|
||||
* @brief Handle requests for DOI management functions.
|
||||
*
|
||||
*/
|
||||
|
||||
switch ($op) {
|
||||
case 'index':
|
||||
define('HANDLER_CLASS', 'APP\pages\dois\DoisHandler');
|
||||
break;
|
||||
}
|
||||
@@ -0,0 +1,246 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @file pages/gateway/GatewayHandler.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 GatewayHandler
|
||||
*
|
||||
* @ingroup pages_gateway
|
||||
*
|
||||
* @brief Handle external gateway requests.
|
||||
*/
|
||||
|
||||
namespace APP\pages\gateway;
|
||||
|
||||
use APP\core\PageRouter;
|
||||
use APP\facades\Repo;
|
||||
use APP\handler\Handler;
|
||||
use APP\journal\JournalDAO;
|
||||
use APP\template\TemplateManager;
|
||||
use Illuminate\Support\LazyCollection;
|
||||
use PKP\db\DAORegistry;
|
||||
use PKP\facades\Locale;
|
||||
use PKP\plugins\PluginRegistry;
|
||||
|
||||
class GatewayHandler extends Handler
|
||||
{
|
||||
public $plugin;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param \APP\core\Request $request
|
||||
*/
|
||||
public function __construct($request)
|
||||
{
|
||||
parent::__construct();
|
||||
/** @var PageRouter */
|
||||
$router = $request->getRouter();
|
||||
$op = $router->getRequestedOp($request);
|
||||
if ($op == 'plugin') {
|
||||
$args = $router->getRequestedArgs($request);
|
||||
$pluginName = array_shift($args);
|
||||
$plugins = PluginRegistry::loadCategory('gateways');
|
||||
if (!isset($plugins[$pluginName])) {
|
||||
$request->getDispatcher()->handle404();
|
||||
}
|
||||
$this->plugin = $plugins[$pluginName];
|
||||
foreach ($this->plugin->getPolicies($request) as $policy) {
|
||||
$this->addPolicy($policy);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Index handler.
|
||||
*
|
||||
* @param array $args
|
||||
* @param \APP\core\Request $request
|
||||
*/
|
||||
public function index($args, $request)
|
||||
{
|
||||
$request->redirect(null, 'index');
|
||||
}
|
||||
|
||||
/**
|
||||
* Display the LOCKSS manifest.
|
||||
*
|
||||
* @param array $args
|
||||
* @param \APP\core\Request $request
|
||||
*/
|
||||
public function lockss($args, $request)
|
||||
{
|
||||
$this->validate();
|
||||
$this->setupTemplate($request);
|
||||
|
||||
$journal = $request->getContext();
|
||||
$templateMgr = TemplateManager::getManager($request);
|
||||
|
||||
if ($journal != null) {
|
||||
if (!$journal->getData('enableLockss')) {
|
||||
$request->redirect(null, 'index');
|
||||
}
|
||||
$yearsIssuesPublished = Repo::issue()->getYearsIssuesPublished($journal->getId())->values();
|
||||
|
||||
// FIXME Should probably go in IssueDAO or a subclass
|
||||
$year = $yearsIssuesPublished->contains((int) $request->getUserVar('year'))
|
||||
? (int) $request->getUserVar('year')
|
||||
: null;
|
||||
|
||||
if (!isset($year)) {
|
||||
$year = $yearsIssuesPublished->max();
|
||||
$templateMgr->assign('showInfo', true);
|
||||
}
|
||||
|
||||
$prevYear = $nextYear = null;
|
||||
if (isset($year)) {
|
||||
$key = $yearsIssuesPublished->search(function ($i) use ($year) {
|
||||
return $i === $year;
|
||||
});
|
||||
if (isset($key)) {
|
||||
$prevYear = $yearsIssuesPublished->get($key - 1);
|
||||
$nextYear = $yearsIssuesPublished->get($key + 1);
|
||||
}
|
||||
}
|
||||
|
||||
$issues = $this->getPublishedIssuesByNumber($journal->getId(), null, null, $year);
|
||||
$templateMgr->assign([
|
||||
'journal' => $journal,
|
||||
'year' => $year,
|
||||
'prevYear' => $prevYear,
|
||||
'nextYear' => $nextYear,
|
||||
'issues' => $issues->toArray(),
|
||||
]);
|
||||
|
||||
$locales = $journal->getSupportedLocaleNames();
|
||||
if (!isset($locales) || empty($locales)) {
|
||||
$primaryLocale = Locale::getPrimaryLocale();
|
||||
$locales = [$primaryLocale => Locale::getMetadata($primaryLocale)->getDisplayName()];
|
||||
}
|
||||
$templateMgr->assign('locales', $locales);
|
||||
} else {
|
||||
$journalDao = DAORegistry::getDAO('JournalDAO'); /** @var JournalDAO $journalDao */
|
||||
$journals = $journalDao->getAll(true);
|
||||
$templateMgr->assign('journals', $journals);
|
||||
}
|
||||
|
||||
$templateMgr->display('gateway/lockss.tpl');
|
||||
}
|
||||
|
||||
/**
|
||||
* Display the CLOCKSS manifest.
|
||||
*
|
||||
* @param array $args
|
||||
* @param \APP\core\Request $request
|
||||
*/
|
||||
public function clockss($args, $request)
|
||||
{
|
||||
$this->validate();
|
||||
$this->setupTemplate($request);
|
||||
|
||||
$journal = $request->getContext();
|
||||
$templateMgr = TemplateManager::getManager($request);
|
||||
|
||||
if ($journal != null) {
|
||||
if (!$journal->getData('enableClockss')) {
|
||||
$request->redirect(null, 'index');
|
||||
}
|
||||
|
||||
$yearsIssuesPublished = Repo::issue()->getYearsIssuesPublished($journal->getId())->values();
|
||||
|
||||
// FIXME Should probably go in Issue DAO or a subclass
|
||||
$year = $yearsIssuesPublished->contains((int) $request->getUserVar('year'))
|
||||
? (int) $request->getUserVar('year')
|
||||
: null;
|
||||
|
||||
|
||||
if (!isset($year)) {
|
||||
$year = $yearsIssuesPublished->max();
|
||||
$issues = $this->getPublishedIssuesByNumber($journal->getId(), null, null, $year);
|
||||
$templateMgr->assign([
|
||||
'issues' => $issues->toArray(),
|
||||
'showInfo' => true,
|
||||
]);
|
||||
}
|
||||
|
||||
$prevYear = $nextYear = null;
|
||||
if (isset($year)) {
|
||||
$key = $yearsIssuesPublished->search(function ($i) use ($year) {
|
||||
return $i === $year;
|
||||
});
|
||||
if (isset($key)) {
|
||||
$prevYear = $yearsIssuesPublished->get($key - 1);
|
||||
$nextYear = $yearsIssuesPublished->get($key + 1);
|
||||
}
|
||||
}
|
||||
|
||||
$issues = $this->getPublishedIssuesByNumber($journal->getId(), null, null, $year);
|
||||
$templateMgr->assign([
|
||||
'journal' => $journal,
|
||||
'year' => $year,
|
||||
'prevYear' => $prevYear,
|
||||
'nextYear' => $nextYear,
|
||||
'issues' => $issues->toArray(),
|
||||
]);
|
||||
|
||||
$locales = $journal->getSupportedLocaleNames();
|
||||
if (!isset($locales) || empty($locales)) {
|
||||
$primaryLocale = Locale::getPrimaryLocale();
|
||||
$locales = [$primaryLocale => Locale::getMetadata($primaryLocale)->getDisplayName()];
|
||||
}
|
||||
$templateMgr->assign('locales', $locales);
|
||||
} else {
|
||||
$journalDao = DAORegistry::getDAO('JournalDAO'); /** @var JournalDAO $journalDao */
|
||||
$journals = $journalDao->getAll(true);
|
||||
$templateMgr->assign('journals', $journals);
|
||||
}
|
||||
|
||||
$templateMgr->display('gateway/clockss.tpl');
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle requests for gateway plugins.
|
||||
*
|
||||
* @param array $args
|
||||
* @param \APP\core\Request $request
|
||||
*/
|
||||
public function plugin($args, $request)
|
||||
{
|
||||
$this->validate();
|
||||
if (isset($this->plugin)) {
|
||||
if (!$this->plugin->fetch(array_slice($args, 1), $request)) {
|
||||
$request->redirect(null, 'index');
|
||||
}
|
||||
} else {
|
||||
$request->redirect(null, 'index');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve Issue by some combination of volume, number, and year
|
||||
*
|
||||
*/
|
||||
protected function getPublishedIssuesByNumber(int $contextId, ?int $volume = null, ?int $number = null, ?int $year = null): LazyCollection
|
||||
{
|
||||
$collector = Repo::issue()->getCollector()
|
||||
->filterByContextIds([$contextId]);
|
||||
|
||||
if ($volume !== null) {
|
||||
$collector->filterByVolumes([$volume]);
|
||||
}
|
||||
|
||||
if ($number !== null) {
|
||||
$collector->filterByNumbers([$number]);
|
||||
}
|
||||
|
||||
if ($year !== null) {
|
||||
$collector->filterByYears([$year]);
|
||||
}
|
||||
|
||||
return $collector->getMany();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @defgroup pages_gateway Gateway Pages
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file pages/gateway/index.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.
|
||||
*
|
||||
* @ingroup pages_gateway
|
||||
*
|
||||
* @brief Handle gateway interaction requests.
|
||||
*
|
||||
*/
|
||||
|
||||
switch ($op) {
|
||||
case 'index':
|
||||
case 'lockss':
|
||||
case 'clockss':
|
||||
case 'plugin':
|
||||
define('HANDLER_CLASS', 'APP\pages\gateway\GatewayHandler');
|
||||
break;
|
||||
}
|
||||
@@ -0,0 +1,105 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @file pages/index/IndexHandler.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 IndexHandler
|
||||
*
|
||||
* @ingroup pages_index
|
||||
*
|
||||
* @brief Handle site index requests.
|
||||
*/
|
||||
|
||||
namespace APP\pages\index;
|
||||
|
||||
use APP\core\Application;
|
||||
use APP\facades\Repo;
|
||||
use APP\journal\JournalDAO;
|
||||
use APP\observers\events\UsageEvent;
|
||||
use APP\pages\issue\IssueHandler;
|
||||
use APP\template\TemplateManager;
|
||||
use PKP\config\Config;
|
||||
use PKP\db\DAORegistry;
|
||||
use PKP\pages\index\PKPIndexHandler;
|
||||
use PKP\security\Validation;
|
||||
|
||||
class IndexHandler extends PKPIndexHandler
|
||||
{
|
||||
//
|
||||
// Public handler operations
|
||||
//
|
||||
/**
|
||||
* If no journal is selected, display list of journals.
|
||||
* Otherwise, display the index page for the selected journal.
|
||||
*
|
||||
* @param array $args
|
||||
* @param \APP\core\Request $request
|
||||
*/
|
||||
public function index($args, $request)
|
||||
{
|
||||
$this->validate(null, $request);
|
||||
$journal = $request->getJournal();
|
||||
|
||||
if (!$journal) {
|
||||
$hasNoContexts = null; // Avoid scrutinizer warnings
|
||||
$journal = $this->getTargetContext($request, $hasNoContexts);
|
||||
if ($journal) {
|
||||
// There's a target context but no journal in the current request. Redirect.
|
||||
$request->redirect($journal->getPath());
|
||||
}
|
||||
if ($hasNoContexts && Validation::isSiteAdmin()) {
|
||||
// No contexts created, and this is the admin.
|
||||
$request->redirect(null, 'admin', 'contexts');
|
||||
}
|
||||
}
|
||||
|
||||
$this->setupTemplate($request);
|
||||
$router = $request->getRouter();
|
||||
$templateMgr = TemplateManager::getManager($request);
|
||||
$templateMgr->assign([
|
||||
'highlights' => $this->getHighlights($journal),
|
||||
]);
|
||||
|
||||
$this->_setupAnnouncements($journal ?? $request->getSite(), $templateMgr);
|
||||
if ($journal) {
|
||||
// Assign header and content for home page
|
||||
$templateMgr->assign([
|
||||
'additionalHomeContent' => $journal->getLocalizedData('additionalHomeContent'),
|
||||
'homepageImage' => $journal->getLocalizedData('homepageImage'),
|
||||
'homepageImageAltText' => $journal->getLocalizedData('homepageImageAltText'),
|
||||
'journalDescription' => $journal->getLocalizedData('description'),
|
||||
]);
|
||||
|
||||
$issue = Repo::issue()->getCurrent($journal->getId(), true);
|
||||
if (isset($issue) && $journal->getData('publishingMode') != \APP\journal\Journal::PUBLISHING_MODE_NONE) {
|
||||
// The current issue TOC/cover page should be displayed below the custom home page.
|
||||
IssueHandler::_setupIssueTemplate($request, $issue);
|
||||
}
|
||||
|
||||
$templateMgr->display('frontend/pages/indexJournal.tpl');
|
||||
event(new UsageEvent(Application::ASSOC_TYPE_JOURNAL, $journal));
|
||||
return;
|
||||
} else {
|
||||
$journalDao = DAORegistry::getDAO('JournalDAO'); /** @var JournalDAO $journalDao */
|
||||
$site = $request->getSite();
|
||||
|
||||
if ($site->getRedirect() && ($journal = $journalDao->getById($site->getRedirect())) != null) {
|
||||
$request->redirect($journal->getPath());
|
||||
}
|
||||
|
||||
$templateMgr->assign([
|
||||
'pageTitleTranslated' => $site->getLocalizedTitle(),
|
||||
'about' => $site->getLocalizedAbout(),
|
||||
'journalFilesPath' => $request->getBaseUrl() . '/' . Config::getVar('files', 'public_files_dir') . '/journals/',
|
||||
'journals' => $journalDao->getAll(true)->toArray(),
|
||||
'site' => $site,
|
||||
]);
|
||||
$templateMgr->setCacheability(TemplateManager::CACHEABILITY_PUBLIC);
|
||||
$templateMgr->display('frontend/pages/indexSite.tpl');
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @defgroup pages_index Index Pages
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file pages/index/index.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.
|
||||
*
|
||||
* @ingroup pages_index
|
||||
*
|
||||
* @brief Handle site index requests.
|
||||
*
|
||||
*/
|
||||
|
||||
switch ($op) {
|
||||
case 'index':
|
||||
define('HANDLER_CLASS', 'APP\pages\index\IndexHandler');
|
||||
break;
|
||||
}
|
||||
@@ -0,0 +1,121 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @file pages/information/InformationHandler.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 InformationHandler
|
||||
*
|
||||
* @ingroup pages_information
|
||||
*
|
||||
* @brief Display journal information.
|
||||
*/
|
||||
|
||||
namespace APP\pages\information;
|
||||
|
||||
use APP\handler\Handler;
|
||||
use APP\template\TemplateManager;
|
||||
use PKP\security\authorization\ContextRequiredPolicy;
|
||||
|
||||
class InformationHandler extends Handler
|
||||
{
|
||||
/**
|
||||
* @see PKPHandler::authorize()
|
||||
*/
|
||||
public function authorize($request, &$args, $roleAssignments)
|
||||
{
|
||||
$context = $request->getContext();
|
||||
if (!$context || !$context->getSetting('restrictSiteAccess')) {
|
||||
$templateMgr = TemplateManager::getManager($request);
|
||||
$templateMgr->setCacheability(TemplateManager::CACHEABILITY_PUBLIC);
|
||||
}
|
||||
|
||||
$this->addPolicy(new ContextRequiredPolicy($request));
|
||||
return parent::authorize($request, $args, $roleAssignments);
|
||||
}
|
||||
|
||||
/**
|
||||
* Display the information page for the journal.
|
||||
*
|
||||
* @param array $args
|
||||
* @param \APP\core\Request $request
|
||||
*/
|
||||
public function index($args, $request)
|
||||
{
|
||||
$this->setupTemplate($request);
|
||||
$this->validate(null, $request);
|
||||
$journal = $request->getJournal();
|
||||
|
||||
switch (array_shift($args)) {
|
||||
case 'readers':
|
||||
$content = $journal->getLocalizedData('readerInformation');
|
||||
$pageTitle = 'navigation.infoForReaders.long';
|
||||
break;
|
||||
case 'authors':
|
||||
$content = $journal->getLocalizedData('authorInformation');
|
||||
$pageTitle = 'navigation.infoForAuthors.long';
|
||||
break;
|
||||
case 'librarians':
|
||||
$content = $journal->getLocalizedData('librarianInformation');
|
||||
$pageTitle = 'navigation.infoForLibrarians.long';
|
||||
break;
|
||||
case 'competingInterestGuidelines':
|
||||
$content = $journal->getLocalizedData('competingInterestsPolicy');
|
||||
$pageTitle = 'navigation.competingInterestGuidelines';
|
||||
break;
|
||||
case 'sampleCopyrightWording':
|
||||
$content = __('manager.setup.copyrightNotice.sample');
|
||||
$pageTitle = 'manager.setup.copyrightNotice';
|
||||
break;
|
||||
default:
|
||||
return $request->redirect($journal->getPath());
|
||||
}
|
||||
|
||||
$templateMgr = TemplateManager::getManager($request);
|
||||
$templateMgr->assign('pageTitle', $pageTitle);
|
||||
$templateMgr->assign('content', $content);
|
||||
$templateMgr->display('frontend/pages/information.tpl');
|
||||
}
|
||||
|
||||
public function readers($args, $request)
|
||||
{
|
||||
$this->index(['readers'], $request);
|
||||
}
|
||||
|
||||
public function authors($args, $request)
|
||||
{
|
||||
$this->index(['authors'], $request);
|
||||
}
|
||||
|
||||
public function librarians($args, $request)
|
||||
{
|
||||
$this->index(['librarians'], $request);
|
||||
}
|
||||
|
||||
public function competingInterestGuidelines($args, $request)
|
||||
{
|
||||
$this->index(['competingInterestGuidelines'], $request);
|
||||
}
|
||||
|
||||
public function sampleCopyrightWording($args, $request)
|
||||
{
|
||||
$this->index(['sampleCopyrightWording'], $request);
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize the template.
|
||||
*
|
||||
* @param \APP\core\Request $request
|
||||
*/
|
||||
public function setupTemplate($request)
|
||||
{
|
||||
parent::setupTemplate($request);
|
||||
if (!$request->getJournal()->getData('restrictSiteAccess')) {
|
||||
$templateMgr = TemplateManager::getManager($request);
|
||||
$templateMgr->setCacheability(TemplateManager::CACHEABILITY_PUBLIC);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @defgroup pages_information Information Pages
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file pages/information/index.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.
|
||||
*
|
||||
* @ingroup pages_information
|
||||
*
|
||||
* @brief Handle information requests.
|
||||
*
|
||||
*/
|
||||
|
||||
switch ($op) {
|
||||
case 'index':
|
||||
case 'readers':
|
||||
case 'authors':
|
||||
case 'librarians':
|
||||
case 'competingInterestGuidelines':
|
||||
case 'sampleCopyrightWording':
|
||||
define('HANDLER_CLASS', 'APP\pages\information\InformationHandler');
|
||||
break;
|
||||
}
|
||||
@@ -0,0 +1,430 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @file pages/issue/IssueHandler.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 IssueHandler
|
||||
*
|
||||
* @ingroup pages_issue
|
||||
*
|
||||
* @brief Handle requests for issue functions.
|
||||
*/
|
||||
|
||||
namespace APP\pages\issue;
|
||||
|
||||
use APP\core\Application;
|
||||
use APP\facades\Repo;
|
||||
use APP\file\IssueFileManager;
|
||||
use APP\handler\Handler;
|
||||
use APP\issue\Collector;
|
||||
use APP\issue\IssueAction;
|
||||
use APP\issue\IssueGalleyDAO;
|
||||
use APP\observers\events\UsageEvent;
|
||||
use APP\payment\ojs\OJSCompletedPaymentDAO;
|
||||
use APP\payment\ojs\OJSPaymentManager;
|
||||
use APP\security\authorization\OjsIssueRequiredPolicy;
|
||||
use APP\security\authorization\OjsJournalMustPublishPolicy;
|
||||
use APP\template\TemplateManager;
|
||||
use PKP\config\Config;
|
||||
use PKP\db\DAORegistry;
|
||||
use PKP\facades\Locale;
|
||||
use PKP\plugins\Hook;
|
||||
use PKP\plugins\PluginRegistry;
|
||||
use PKP\security\authorization\ContextRequiredPolicy;
|
||||
use PKP\security\Validation;
|
||||
use PKP\submission\GenreDAO;
|
||||
use PKP\submission\PKPSubmission;
|
||||
|
||||
class IssueHandler extends Handler
|
||||
{
|
||||
/** @var \APP\issue\IssueGalley retrieved issue galley */
|
||||
public $_galley = null;
|
||||
|
||||
|
||||
/**
|
||||
* @copydoc PKPHandler::authorize()
|
||||
*/
|
||||
public function authorize($request, &$args, $roleAssignments)
|
||||
{
|
||||
$this->addPolicy(new ContextRequiredPolicy($request));
|
||||
$this->addPolicy(new OjsJournalMustPublishPolicy($request));
|
||||
|
||||
// the 'archives' op does not need this policy so it is left out of the operations array.
|
||||
$this->addPolicy(new OjsIssueRequiredPolicy($request, $args, ['view', 'download']));
|
||||
|
||||
return parent::authorize($request, $args, $roleAssignments);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see PKPHandler::initialize()
|
||||
*
|
||||
* @param array $args Arguments list
|
||||
*/
|
||||
public function initialize($request, $args = [])
|
||||
{
|
||||
// Get the issue galley
|
||||
$galleyId = $args[1] ?? 0;
|
||||
if ($galleyId) {
|
||||
$issue = $this->getAuthorizedContextObject(Application::ASSOC_TYPE_ISSUE);
|
||||
$galleyDao = DAORegistry::getDAO('IssueGalleyDAO'); /** @var IssueGalleyDAO $galleyDao */
|
||||
$journal = $request->getJournal();
|
||||
$galley = $galleyDao->getByBestId($galleyId, $issue->getId());
|
||||
|
||||
// Invalid galley id, redirect to issue page
|
||||
if (!$galley) {
|
||||
$request->redirect(null, null, 'view', $issue->getId());
|
||||
}
|
||||
|
||||
$this->setGalley($galley);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Display about index page.
|
||||
*/
|
||||
public function index($args, $request)
|
||||
{
|
||||
$this->current($args, $request);
|
||||
}
|
||||
|
||||
/**
|
||||
* Display current issue page.
|
||||
*/
|
||||
public function current($args, $request)
|
||||
{
|
||||
$journal = $request->getJournal();
|
||||
$issue = Repo::issue()->getCurrent($journal->getId(), true);
|
||||
|
||||
if ($issue != null) {
|
||||
$request->redirect(null, 'issue', 'view', $issue->getBestIssueId());
|
||||
}
|
||||
|
||||
$this->setupTemplate($request);
|
||||
$templateMgr = TemplateManager::getManager($request);
|
||||
// consider public identifiers
|
||||
$pubIdPlugins = PluginRegistry::loadCategory('pubIds', true);
|
||||
$templateMgr->assign('pubIdPlugins', $pubIdPlugins);
|
||||
$templateMgr->display('frontend/pages/issue.tpl');
|
||||
}
|
||||
|
||||
/**
|
||||
* View an issue.
|
||||
*
|
||||
* @param array $args
|
||||
* @param \APP\core\Request $request
|
||||
*/
|
||||
public function view($args, $request)
|
||||
{
|
||||
$issue = $this->getAuthorizedContextObject(Application::ASSOC_TYPE_ISSUE);
|
||||
$this->setupTemplate($request);
|
||||
$templateMgr = TemplateManager::getManager($request);
|
||||
$journal = $request->getJournal();
|
||||
|
||||
if (($galley = $this->getGalley()) && $this->userCanViewGalley($request)) {
|
||||
if (!Hook::call('IssueHandler::view::galley', [&$request, &$issue, &$galley])) {
|
||||
$request->redirect(null, null, 'download', [$issue->getBestIssueId($journal), $galley->getBestGalleyId()]);
|
||||
}
|
||||
} else {
|
||||
self::_setupIssueTemplate($request, $issue, $request->getUserVar('showToc') ? true : false);
|
||||
$templateMgr->assign('issueId', $issue->getBestIssueId());
|
||||
|
||||
// consider public identifiers
|
||||
$pubIdPlugins = PluginRegistry::loadCategory('pubIds', true);
|
||||
$templateMgr->assign('pubIdPlugins', $pubIdPlugins);
|
||||
$templateMgr->display('frontend/pages/issue.tpl');
|
||||
event(new UsageEvent(Application::ASSOC_TYPE_ISSUE, $journal, null, null, null, $issue));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Display the issue archive listings
|
||||
*
|
||||
* @param array $args
|
||||
* @param \APP\core\Request $request
|
||||
*/
|
||||
public function archive($args, $request)
|
||||
{
|
||||
$this->setupTemplate($request);
|
||||
$page = isset($args[0]) ? (int) $args[0] : 1;
|
||||
$templateMgr = TemplateManager::getManager($request);
|
||||
$context = $request->getContext();
|
||||
|
||||
$count = $context->getData('itemsPerPage') ? $context->getData('itemsPerPage') : Config::getVar('interface', 'items_per_page');
|
||||
$offset = $page > 1 ? ($page - 1) * $count : 0;
|
||||
|
||||
$collector = Repo::issue()->getCollector()
|
||||
->limit($count)
|
||||
->offset($offset)
|
||||
->filterByContextIds([$context->getId()])
|
||||
->orderBy(Collector::ORDERBY_SEQUENCE)
|
||||
->filterByPublished(true);
|
||||
|
||||
$issues = $collector->getMany()->toArray();
|
||||
$total = $collector->limit(null)->offset(null)->getCount();
|
||||
|
||||
$showingStart = $offset + 1;
|
||||
$showingEnd = min($offset + $count, $offset + count($issues));
|
||||
$nextPage = $total > $showingEnd ? $page + 1 : null;
|
||||
$prevPage = $showingStart > 1 ? $page - 1 : null;
|
||||
|
||||
$templateMgr->assign([
|
||||
'issues' => $issues,
|
||||
'showingStart' => $showingStart,
|
||||
'showingEnd' => $showingEnd,
|
||||
'total' => $total,
|
||||
'nextPage' => $nextPage,
|
||||
'prevPage' => $prevPage,
|
||||
]);
|
||||
|
||||
$templateMgr->display('frontend/pages/issueArchive.tpl');
|
||||
}
|
||||
|
||||
/**
|
||||
* Downloads an issue galley file
|
||||
*
|
||||
* @param array $args ($issueId, $galleyId)
|
||||
* @param \APP\core\Request $request
|
||||
*/
|
||||
public function download($args, $request)
|
||||
{
|
||||
if ($this->userCanViewGalley($request)) {
|
||||
$issue = $this->getAuthorizedContextObject(Application::ASSOC_TYPE_ISSUE);
|
||||
$galley = $this->getGalley();
|
||||
|
||||
if (!Hook::call('IssueHandler::download', [&$issue, &$galley])) {
|
||||
$issueFileManager = new IssueFileManager($issue->getId());
|
||||
if ($issueFileManager->downloadById($galley->getFileId(), $request->getUserVar('inline') ? true : false)) {
|
||||
event(new UsageEvent(Application::ASSOC_TYPE_ISSUE_GALLEY, $request->getContext(), null, null, null, $issue, $galley));
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the retrieved issue galley
|
||||
*
|
||||
* @return \APP\issue\IssueGalley
|
||||
*/
|
||||
public function getGalley()
|
||||
{
|
||||
return $this->_galley;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a retrieved issue galley
|
||||
*
|
||||
* @param \APP\issue\IssueGalley $galley
|
||||
*/
|
||||
public function setGalley($galley)
|
||||
{
|
||||
$this->_galley = $galley;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines whether or not a user can view an issue galley.
|
||||
*
|
||||
* @param \APP\core\Request $request
|
||||
*/
|
||||
public function userCanViewGalley($request)
|
||||
{
|
||||
$issueAction = new IssueAction();
|
||||
|
||||
$journal = $request->getJournal();
|
||||
$user = $request->getUser();
|
||||
$userId = $user ? $user->getId() : 0;
|
||||
$issue = $this->getAuthorizedContextObject(Application::ASSOC_TYPE_ISSUE);
|
||||
$galley = $this->getGalley();
|
||||
|
||||
// If this is an editorial user who can view unpublished issue galleys,
|
||||
// bypass further validation
|
||||
if ($issueAction->allowedIssuePrePublicationAccess($journal, $user)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Ensure reader has rights to view the issue galley
|
||||
if ($issue->getPublished()) {
|
||||
$subscriptionRequired = $issueAction->subscriptionRequired($issue, $journal);
|
||||
$isSubscribedDomain = $issueAction->subscribedDomain($request, $journal, $issue->getId());
|
||||
|
||||
// Check if login is required for viewing.
|
||||
if (!$isSubscribedDomain && !Validation::isLoggedIn() && $journal->getData('restrictArticleAccess')) {
|
||||
Validation::redirectLogin();
|
||||
}
|
||||
|
||||
// If no domain/ip subscription, check if user has a valid subscription
|
||||
// or if the user has previously purchased the issue
|
||||
if (!$isSubscribedDomain && $subscriptionRequired) {
|
||||
// Check if user has a valid subscription
|
||||
$subscribedUser = $issueAction->subscribedUser($user, $journal, $issue->getId());
|
||||
if (!$subscribedUser) {
|
||||
// Check if payments are enabled,
|
||||
$paymentManager = Application::getPaymentManager($journal);
|
||||
|
||||
if ($paymentManager->purchaseIssueEnabled() || $paymentManager->membershipEnabled()) {
|
||||
// If only pdf files are being restricted, then approve all non-pdf galleys
|
||||
// and continue checking if it is a pdf galley
|
||||
if ($paymentManager->onlyPdfEnabled() && !$galley->isPdfGalley()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!Validation::isLoggedIn()) {
|
||||
Validation::redirectLogin('payment.loginRequired.forIssue');
|
||||
}
|
||||
|
||||
// If the issue galley has been purchased, then allow reader access
|
||||
$completedPaymentDao = DAORegistry::getDAO('OJSCompletedPaymentDAO'); /** @var OJSCompletedPaymentDAO $completedPaymentDao */
|
||||
$dateEndMembership = $user->getSetting('dateEndMembership', 0);
|
||||
if ($completedPaymentDao->hasPaidPurchaseIssue($userId, $issue->getId()) || (!is_null($dateEndMembership) && $dateEndMembership > time())) {
|
||||
return true;
|
||||
} else {
|
||||
// Otherwise queue an issue purchase payment and display payment form
|
||||
$queuedPayment = $paymentManager->createQueuedPayment($request, OJSPaymentManager::PAYMENT_TYPE_PURCHASE_ISSUE, $userId, $issue->getId(), $journal->getData('purchaseIssueFee'));
|
||||
$paymentManager->queuePayment($queuedPayment);
|
||||
|
||||
$paymentForm = $paymentManager->getPaymentForm($queuedPayment);
|
||||
$paymentForm->display($request);
|
||||
exit;
|
||||
}
|
||||
}
|
||||
|
||||
if (!Validation::isLoggedIn()) {
|
||||
Validation::redirectLogin('reader.subscriptionRequiredLoginText');
|
||||
}
|
||||
$request->redirect(null, 'about', 'subscriptions');
|
||||
}
|
||||
}
|
||||
} else {
|
||||
$request->redirect(null, 'index');
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Given an issue, set up the template with all the required variables for
|
||||
* frontend/objects/issue_toc.tpl to function properly (i.e. current issue
|
||||
* and view issue).
|
||||
*
|
||||
* @param object $issue The issue to display
|
||||
* @param bool $showToc iff false and a custom cover page exists,
|
||||
* the cover page will be displayed. Otherwise table of contents
|
||||
* will be displayed.
|
||||
*/
|
||||
public static function _setupIssueTemplate($request, $issue, $showToc = false)
|
||||
{
|
||||
$journal = $request->getJournal();
|
||||
$user = $request->getUser();
|
||||
$templateMgr = TemplateManager::getManager($request);
|
||||
|
||||
// Determine pre-publication access
|
||||
// FIXME: Do that. (Bug #8278)
|
||||
|
||||
$templateMgr->assign([
|
||||
'issueIdentification' => $issue->getIssueIdentification(),
|
||||
'issueTitle' => $issue->getLocalizedTitle(),
|
||||
'issueSeries' => $issue->getIssueIdentification(['showTitle' => false]),
|
||||
]);
|
||||
|
||||
$locale = Locale::getLocale();
|
||||
|
||||
$templateMgr->assign([
|
||||
'locale' => $locale,
|
||||
]);
|
||||
|
||||
$issueGalleyDao = DAORegistry::getDAO('IssueGalleyDAO'); /** @var IssueGalleyDAO $issueGalleyDao */
|
||||
|
||||
$genreDao = DAORegistry::getDAO('GenreDAO'); /** @var GenreDAO $genreDao */
|
||||
$primaryGenres = $genreDao->getPrimaryByContextId($journal->getId())->toArray();
|
||||
$primaryGenreIds = array_map(function ($genre) {
|
||||
return $genre->getId();
|
||||
}, $primaryGenres);
|
||||
|
||||
// Show scheduled submissions if this is a preview
|
||||
$allowedStatuses = [PKPSubmission::STATUS_PUBLISHED];
|
||||
if (!$issue->getPublished()) {
|
||||
$allowedStatuses[] = PKPSubmission::STATUS_SCHEDULED;
|
||||
}
|
||||
|
||||
$issueSubmissions = Repo::submission()->getCollector()
|
||||
->filterByContextIds([$issue->getJournalId()])
|
||||
->filterByIssueIds([$issue->getId()])
|
||||
->filterByStatus($allowedStatuses)
|
||||
->orderBy(\APP\submission\Collector::ORDERBY_SEQUENCE, \APP\submission\Collector::ORDER_DIR_ASC)
|
||||
->getMany();
|
||||
|
||||
$sections = Repo::section()->getByIssueId($issue->getId());
|
||||
$issueSubmissionsInSection = [];
|
||||
foreach ($sections as $section) {
|
||||
$issueSubmissionsInSection[$section->getId()] = [
|
||||
'title' => $section->getHideTitle() ? null : $section->getLocalizedTitle(),
|
||||
'hideAuthor' => $section->getHideAuthor(),
|
||||
'articles' => [],
|
||||
];
|
||||
}
|
||||
foreach ($issueSubmissions as $submission) {
|
||||
if (!$sectionId = $submission->getCurrentPublication()->getData('sectionId')) {
|
||||
continue;
|
||||
}
|
||||
$issueSubmissionsInSection[$sectionId]['articles'][] = $submission;
|
||||
}
|
||||
|
||||
$authorUserGroups = Repo::userGroup()->getCollector()->filterByRoleIds([\PKP\security\Role::ROLE_ID_AUTHOR])->filterByContextIds([$journal->getId()])->getMany()->remember();
|
||||
$templateMgr->assign([
|
||||
'issue' => $issue,
|
||||
'issueGalleys' => $issueGalleyDao->getByIssueId($issue->getId()),
|
||||
'publishedSubmissions' => $issueSubmissionsInSection,
|
||||
'primaryGenreIds' => $primaryGenreIds,
|
||||
'authorUserGroups' => $authorUserGroups,
|
||||
]);
|
||||
|
||||
// Subscription Access
|
||||
$issueAction = new IssueAction();
|
||||
$subscriptionRequired = $issueAction->subscriptionRequired($issue, $journal);
|
||||
$subscribedUser = $issueAction->subscribedUser($user, $journal);
|
||||
$subscribedDomain = $issueAction->subscribedDomain($request, $journal);
|
||||
|
||||
if ($subscriptionRequired && !$subscribedUser && !$subscribedDomain) {
|
||||
$templateMgr->assign('subscriptionExpiryPartial', true);
|
||||
|
||||
// Partial subscription expiry for issue
|
||||
$partial = $issueAction->subscribedUser($user, $journal, $issue->getId());
|
||||
if (!$partial) {
|
||||
$issueAction->subscribedDomain($request, $journal, $issue->getId());
|
||||
}
|
||||
$templateMgr->assign('issueExpiryPartial', $partial);
|
||||
|
||||
// Partial subscription expiry for articles
|
||||
$articleExpiryPartial = [];
|
||||
foreach ($issueSubmissions as $issueSubmission) {
|
||||
$partial = $issueAction->subscribedUser($user, $journal, $issue->getId(), $issueSubmission->getId());
|
||||
if (!$partial) {
|
||||
$issueAction->subscribedDomain($request, $journal, $issue->getId(), $issueSubmission->getId());
|
||||
}
|
||||
$articleExpiryPartial[$issueSubmission->getId()] = $partial;
|
||||
}
|
||||
$templateMgr->assign('articleExpiryPartial', $articleExpiryPartial);
|
||||
}
|
||||
|
||||
$completedPaymentDao = DAORegistry::getDAO('OJSCompletedPaymentDAO'); /** @var OJSCompletedPaymentDAO $completedPaymentDao */
|
||||
$templateMgr->assign([
|
||||
'hasAccess' => !$subscriptionRequired ||
|
||||
$issue->getAccessStatus() == \APP\issue\Issue::ISSUE_ACCESS_OPEN ||
|
||||
$subscribedUser || $subscribedDomain ||
|
||||
($user && $completedPaymentDao->hasPaidPurchaseIssue($user->getId(), $issue->getId()))
|
||||
]);
|
||||
|
||||
$paymentManager = Application::getPaymentManager($journal);
|
||||
if ($paymentManager->onlyPdfEnabled()) {
|
||||
$templateMgr->assign('restrictOnlyPdf', true);
|
||||
}
|
||||
if ($paymentManager->purchaseArticleEnabled()) {
|
||||
$templateMgr->assign('purchaseArticleEnabled', true);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @defgroup pages_issue Issue Pages
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file pages/issue/index.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.
|
||||
*
|
||||
* @ingroup pages_issue
|
||||
*
|
||||
* @brief Handle requests for issue functions.
|
||||
*
|
||||
*/
|
||||
switch ($op) {
|
||||
case 'index':
|
||||
case 'current':
|
||||
case 'archive':
|
||||
case 'view':
|
||||
case 'download':
|
||||
define('HANDLER_CLASS', 'APP\pages\issue\IssueHandler');
|
||||
break;
|
||||
}
|
||||
@@ -0,0 +1,71 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @file pages/manageIssues/ManageIssuesHandler.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 ManageIssuesHandler
|
||||
*
|
||||
* @ingroup pages_editor
|
||||
*
|
||||
* @brief Handle requests for issue management in publishing.
|
||||
*/
|
||||
|
||||
namespace APP\pages\manageIssues;
|
||||
|
||||
use APP\handler\Handler;
|
||||
use APP\template\TemplateManager;
|
||||
use PKP\security\authorization\PKPSiteAccessPolicy;
|
||||
use PKP\security\Role;
|
||||
|
||||
class ManageIssuesHandler extends Handler
|
||||
{
|
||||
/** @var \APP\issue\Issue Issue associated with the request */
|
||||
public $issue;
|
||||
|
||||
/** @copydoc PKPHandler::_isBackendPage */
|
||||
public $_isBackendPage = true;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct();
|
||||
$this->addRoleAssignment(
|
||||
[Role::ROLE_ID_MANAGER, Role::ROLE_ID_SITE_ADMIN],
|
||||
[
|
||||
'index',
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @copydoc PKPHandler::authorize()
|
||||
*/
|
||||
public function authorize($request, &$args, $roleAssignments)
|
||||
{
|
||||
$this->addPolicy(new PKPSiteAccessPolicy($request, null, $roleAssignments));
|
||||
return parent::authorize($request, $args, $roleAssignments);
|
||||
}
|
||||
|
||||
/**
|
||||
* Displays the issue listings in a tabbed interface.
|
||||
*
|
||||
* @param array $args
|
||||
* @param \APP\core\Request $request
|
||||
*/
|
||||
public function index($args, $request)
|
||||
{
|
||||
$this->setupTemplate($request);
|
||||
|
||||
$templateMgr = TemplateManager::getManager($request);
|
||||
$templateMgr->assign([
|
||||
'pageTitle' => __('editor.navigation.issues')
|
||||
]);
|
||||
return $templateMgr->display('manageIssues/issues.tpl');
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @defgroup pages_manageIssues Issue Management Pages
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file pages/manageIssues/index.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.
|
||||
*
|
||||
* @ingroup pages_editor
|
||||
*
|
||||
* @brief Handle requests for issue management functions.
|
||||
*
|
||||
*/
|
||||
|
||||
switch ($op) {
|
||||
//
|
||||
// Issue
|
||||
//
|
||||
case 'index':
|
||||
case 'issuesTabs':
|
||||
define('HANDLER_CLASS', 'APP\pages\manageIssues\ManageIssuesHandler');
|
||||
break;
|
||||
}
|
||||
@@ -0,0 +1,175 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @file pages/management/SettingsHandler.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 SettingsHandler
|
||||
*
|
||||
* @ingroup pages_management
|
||||
*
|
||||
* @brief Handle requests for settings pages.
|
||||
*/
|
||||
|
||||
namespace APP\pages\management;
|
||||
|
||||
use APP\template\TemplateManager;
|
||||
use PKP\core\PKPApplication;
|
||||
use PKP\pages\management\ManagementHandler;
|
||||
use PKP\plugins\Hook;
|
||||
use PKP\plugins\PluginRegistry;
|
||||
use PKP\security\Role;
|
||||
|
||||
class SettingsHandler extends ManagementHandler
|
||||
{
|
||||
/**
|
||||
* Constructor.
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct();
|
||||
$this->addRoleAssignment(
|
||||
[Role::ROLE_ID_SITE_ADMIN],
|
||||
[
|
||||
'access', 'settings',
|
||||
]
|
||||
);
|
||||
$this->addRoleAssignment(
|
||||
Role::ROLE_ID_MANAGER,
|
||||
[
|
||||
'settings',
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add the workflow settings page
|
||||
*
|
||||
* @param array $args
|
||||
* @param \APP\core\Request $request
|
||||
*/
|
||||
public function workflow($args, $request)
|
||||
{
|
||||
parent::workflow($args, $request);
|
||||
|
||||
$this->addReviewFormWorkflowSupport($request);
|
||||
|
||||
TemplateManager::getManager($request)->display('management/workflow.tpl');
|
||||
}
|
||||
|
||||
/**
|
||||
* Add the archive and payments tabs to the distribution settings page
|
||||
*
|
||||
* @param array $args
|
||||
* @param \APP\core\Request $request
|
||||
*/
|
||||
public function distribution($args, $request)
|
||||
{
|
||||
parent::distribution($args, $request);
|
||||
|
||||
$templateMgr = TemplateManager::getManager($request);
|
||||
$context = $request->getContext();
|
||||
$router = $request->getRouter();
|
||||
$dispatcher = $request->getDispatcher();
|
||||
|
||||
$apiUrl = $this->getContextApiUrl($request);
|
||||
$lockssUrl = $router->url($request, $context->getPath(), 'gateway', 'lockss');
|
||||
$clockssUrl = $router->url($request, $context->getPath(), 'gateway', 'clockss');
|
||||
|
||||
$locales = $this->getSupportedFormLocales($context);
|
||||
|
||||
$accessForm = new \APP\components\forms\context\AccessForm($apiUrl, $locales, $context);
|
||||
$archivingLockssForm = new \APP\components\forms\context\ArchivingLockssForm($apiUrl, $locales, $context, $lockssUrl, $clockssUrl);
|
||||
|
||||
// Create a dummy "form" for the PKP Preservation Network settings. This
|
||||
// form loads a single field which enables/disables the plugin, and does
|
||||
// not need to be submitted. It's a dirty hack, but we can change this once
|
||||
// an API is in place for plugins and plugin settings.
|
||||
$plnPlugin = PluginRegistry::getPlugin('generic', 'plnplugin');
|
||||
$archivePnForm = new \PKP\components\forms\FormComponent('archivePn', 'PUT', 'dummy', $locales);
|
||||
$archivePnForm->addPage([
|
||||
'id' => 'default',
|
||||
'submitButton' => null,
|
||||
])
|
||||
->addGroup([
|
||||
'id' => 'default',
|
||||
'pageId' => 'default',
|
||||
]);
|
||||
|
||||
if ($plnPlugin) {
|
||||
$plnPlugin = PluginRegistry::getPlugin('generic', 'plnplugin');
|
||||
$pnEnablePluginUrl = $dispatcher->url($request, PKPApplication::ROUTE_COMPONENT, null, 'grid.settings.plugins.SettingsPluginGridHandler', 'enable', null, ['plugin' => 'plnplugin', 'category' => 'generic']);
|
||||
$pnDisablePluginUrl = $dispatcher->url($request, PKPApplication::ROUTE_COMPONENT, null, 'grid.settings.plugins.SettingsPluginGridHandler', 'disable', null, ['plugin' => 'plnplugin', 'category' => 'generic']);
|
||||
$pnSettingsUrl = $dispatcher->url($request, PKPApplication::ROUTE_COMPONENT, null, 'grid.settings.plugins.SettingsPluginGridHandler', 'manage', null, ['verb' => 'settings', 'plugin' => 'plnplugin', 'category' => 'generic']);
|
||||
|
||||
$archivePnForm->addField(new \APP\components\forms\FieldArchivingPn('pn', [
|
||||
'label' => __('manager.setup.plnPluginArchiving'),
|
||||
'description' => __('manager.setup.plnDescription'),
|
||||
'terms' => __('manager.setup.plnSettingsDescription'),
|
||||
'options' => [
|
||||
[
|
||||
'value' => true,
|
||||
'label' => __('manager.setup.plnPluginEnable'),
|
||||
],
|
||||
],
|
||||
'value' => (bool) $plnPlugin,
|
||||
'enablePluginUrl' => $pnEnablePluginUrl,
|
||||
'disablePluginUrl' => $pnDisablePluginUrl,
|
||||
'settingsUrl' => $pnSettingsUrl,
|
||||
'csrfToken' => $request->getSession()->getCSRFToken(),
|
||||
'groupId' => 'default',
|
||||
'enablePluginSuccess' => __('common.pluginEnabled', ['pluginName' => __('manager.setup.plnPluginArchiving')]),
|
||||
'disablePluginSuccess' => __('common.pluginDisabled', ['pluginName' => __('manager.setup.plnPluginArchiving')]),
|
||||
]));
|
||||
} else {
|
||||
$archivePnForm->addField(new \PKP\components\forms\FieldHTML('pn', [
|
||||
'label' => __('manager.setup.plnPluginArchiving'),
|
||||
'description' => __('manager.setup.plnPluginNotInstalled'),
|
||||
'groupId' => 'default',
|
||||
]));
|
||||
}
|
||||
|
||||
// Add forms to the existing settings data
|
||||
$components = $templateMgr->getState('components');
|
||||
$components[$accessForm->id] = $accessForm->getConfig();
|
||||
$components[$archivingLockssForm->id] = $archivingLockssForm->getConfig();
|
||||
$components[$archivePnForm->id] = $archivePnForm->getConfig();
|
||||
$templateMgr->setState(['components' => $components]);
|
||||
|
||||
// Add a payments link to be added/removed when payments form submitted
|
||||
$templateMgr->setState([
|
||||
'paymentsNavLink' => [
|
||||
'name' => __('common.payments'),
|
||||
'url' => $router->url($request, null, 'payments'),
|
||||
'isCurrent' => false,
|
||||
],
|
||||
]);
|
||||
|
||||
// Hook into the settings templates to add the appropriate tabs
|
||||
Hook::add('Template::Settings::distribution', function ($hookName, $args) {
|
||||
$templateMgr = $args[1];
|
||||
$output = &$args[2];
|
||||
$output .= $templateMgr->fetch('management/additionalDistributionTabs.tpl');
|
||||
return false;
|
||||
});
|
||||
|
||||
$templateMgr->display('management/distribution.tpl');
|
||||
}
|
||||
|
||||
protected function getEmailFromFilters(): array
|
||||
{
|
||||
$filters = parent::getEmailFromFilters();
|
||||
$filters[Role::ROLE_ID_SUBSCRIPTION_MANAGER] = __('user.role.subscriptionManager');
|
||||
return $filters;
|
||||
}
|
||||
|
||||
protected function getEmailToFilters(): array
|
||||
{
|
||||
$filters = parent::getEmailToFilters();
|
||||
$filters[Role::ROLE_ID_SUBSCRIPTION_MANAGER] = __('user.role.subscriptionManager');
|
||||
return $filters;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @defgroup pages_management Management Pages
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file pages/management/index.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.
|
||||
*
|
||||
* @ingroup pages_management
|
||||
*
|
||||
* @brief Handle requests for settings pages.
|
||||
*
|
||||
*/
|
||||
|
||||
switch ($op) {
|
||||
//
|
||||
// Settings
|
||||
//
|
||||
case 'index':
|
||||
case 'settings':
|
||||
case 'access':
|
||||
define('HANDLER_CLASS', 'APP\pages\management\SettingsHandler');
|
||||
break;
|
||||
case 'tools':
|
||||
case 'importexport':
|
||||
case 'statistics':
|
||||
case 'permissions':
|
||||
case 'resetPermissions':
|
||||
define('HANDLER_CLASS', 'PKP\pages\management\PKPToolsHandler');
|
||||
break;
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @defgroup pages_manager Manager Pages
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file pages/manager/index.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.
|
||||
*
|
||||
* @ingroup pages_manager
|
||||
*
|
||||
* @brief Handle requests for journal management functions.
|
||||
*
|
||||
*/
|
||||
|
||||
switch ($op) {
|
||||
//
|
||||
// Subscription Policies
|
||||
//
|
||||
case 'subscriptionPolicies':
|
||||
case 'saveSubscriptionPolicies':
|
||||
//
|
||||
// Subscription Types
|
||||
//
|
||||
case 'subscriptionTypes':
|
||||
case 'deleteSubscriptionType':
|
||||
case 'createSubscriptionType':
|
||||
case 'selectSubscriber':
|
||||
case 'editSubscriptionType':
|
||||
case 'updateSubscriptionType':
|
||||
case 'moveSubscriptionType':
|
||||
//
|
||||
// Subscriptions
|
||||
//
|
||||
case 'subscriptions':
|
||||
case 'subscriptionsSummary':
|
||||
case 'deleteSubscription':
|
||||
case 'renewSubscription':
|
||||
case 'createSubscription':
|
||||
case 'editSubscription':
|
||||
case 'updateSubscription':
|
||||
define('HANDLER_CLASS', 'APP\manager\SubscriptionHandler');
|
||||
break;
|
||||
//
|
||||
// Payment
|
||||
//
|
||||
case 'payments':
|
||||
case 'savePaymentSettings':
|
||||
case 'viewPayments':
|
||||
case 'viewPayment':
|
||||
define('HANDLER_CLASS', 'APP\manager\ManagerPaymentHandler');
|
||||
break;
|
||||
}
|
||||
@@ -0,0 +1,87 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @file pages/oai/OAIHandler.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 OAIHandler
|
||||
*
|
||||
* @ingroup pages_oai
|
||||
*
|
||||
* @brief Handle OAI protocol requests.
|
||||
*/
|
||||
|
||||
namespace APP\pages\oai;
|
||||
|
||||
use APP\handler\Handler;
|
||||
use APP\oai\ojs\JournalOAI;
|
||||
use Firebase\JWT\JWT;
|
||||
use PKP\config\Config;
|
||||
use PKP\oai\OAIConfig;
|
||||
use PKP\plugins\PluginRegistry;
|
||||
use PKP\session\SessionManager;
|
||||
|
||||
// Disable initializing the session
|
||||
SessionManager::disable();
|
||||
|
||||
class OAIHandler extends Handler
|
||||
{
|
||||
/**
|
||||
* @param array $args
|
||||
* @param \APP\core\Request $request
|
||||
*/
|
||||
public function index($args, $request)
|
||||
{
|
||||
$this->validate(null, $request);
|
||||
|
||||
PluginRegistry::loadCategory('oaiMetadataFormats', true);
|
||||
|
||||
$oai = new JournalOAI(new OAIConfig($request->url(null, 'oai'), Config::getVar('oai', 'repository_id')));
|
||||
if (!$request->getJournal() && $request->getRouter()->getRequestedContextPath($request) != 'index') {
|
||||
$dispatcher = $request->getDispatcher();
|
||||
return $dispatcher->handle404();
|
||||
}
|
||||
$oai->execute();
|
||||
}
|
||||
|
||||
/**
|
||||
* @copydoc PKPHandler::validate()
|
||||
*
|
||||
* @param null|mixed $requiredContexts
|
||||
* @param null|mixed $request
|
||||
*/
|
||||
public function validate($requiredContexts = null, $request = null)
|
||||
{
|
||||
// Site validation checks not applicable
|
||||
//parent::validate($requiredContexts, $request);
|
||||
|
||||
if (!Config::getVar('oai', 'oai')) {
|
||||
$request->redirect(null, 'index');
|
||||
}
|
||||
|
||||
// Permit the use of the Authorization header and an API key for access to unpublished content (article URLs)
|
||||
if ($header = array_search('Authorization', array_flip(getallheaders()))) {
|
||||
[$bearer, $jwt] = explode(' ', $header);
|
||||
if (strcasecmp($bearer, 'Bearer') == 0) {
|
||||
$apiToken = JWT::decode($jwt, Config::getVar('security', 'api_key_secret', ''), ['HS256']);
|
||||
// Compatibility with old API keys
|
||||
// https://github.com/pkp/pkp-lib/issues/6462
|
||||
if (substr($apiToken, 0, 2) === '""') {
|
||||
$apiToken = json_decode($apiToken);
|
||||
}
|
||||
$this->setApiToken($apiToken);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @see PKPHandler::requireSSL()
|
||||
*/
|
||||
public function requireSSL()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @defgroup pages_oai OAI Pages
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file pages/oai/index.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.
|
||||
*
|
||||
* @ingroup pages_oai
|
||||
*
|
||||
* @brief Handle Open Archives Initiative protocol interaction requests.
|
||||
*
|
||||
*/
|
||||
|
||||
switch ($op) {
|
||||
case 'index':
|
||||
define('HANDLER_CLASS', 'APP\pages\oai\OAIHandler');
|
||||
break;
|
||||
}
|
||||
@@ -0,0 +1,79 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @file pages/payment/PaymentHandler.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 PaymentHandler
|
||||
*
|
||||
* @ingroup pages_payment
|
||||
*
|
||||
* @brief Handle requests for payment functions.
|
||||
*/
|
||||
|
||||
namespace APP\pages\payment;
|
||||
|
||||
use APP\core\Application;
|
||||
use APP\handler\Handler;
|
||||
use APP\template\TemplateManager;
|
||||
use PKP\db\DAORegistry;
|
||||
use PKP\payment\QueuedPaymentDAO;
|
||||
use PKP\plugins\PluginRegistry;
|
||||
use PKP\security\Validation;
|
||||
|
||||
class PaymentHandler extends Handler
|
||||
{
|
||||
/**
|
||||
* Pass request to plugin.
|
||||
*
|
||||
* @param array $args
|
||||
* @param \APP\core\Request $request
|
||||
*/
|
||||
public function plugin($args, $request)
|
||||
{
|
||||
$paymentMethodPlugins = PluginRegistry::loadCategory('paymethod');
|
||||
$paymentMethodPluginName = array_shift($args);
|
||||
if (empty($paymentMethodPluginName) || !isset($paymentMethodPlugins[$paymentMethodPluginName])) {
|
||||
$request->redirect(null, null, 'index');
|
||||
}
|
||||
|
||||
$paymentMethodPlugin = & $paymentMethodPlugins[$paymentMethodPluginName];
|
||||
if (!$paymentMethodPlugin->isConfigured($request->getContext())) {
|
||||
$request->redirect(null, null, 'index');
|
||||
}
|
||||
|
||||
$paymentMethodPlugin->handle($args, $request);
|
||||
}
|
||||
|
||||
/**
|
||||
* Present a landing page from which to fulfill a payment.
|
||||
*
|
||||
* @param array $args
|
||||
* @param \APP\core\Request $request
|
||||
*/
|
||||
public function pay($args, $request)
|
||||
{
|
||||
if (!Validation::isLoggedIn()) {
|
||||
Validation::redirectLogin();
|
||||
}
|
||||
|
||||
$paymentManager = Application::getPaymentManager($request->getContext());
|
||||
$templateMgr = TemplateManager::getManager($request);
|
||||
$queuedPaymentDao = DAORegistry::getDAO('QueuedPaymentDAO'); /** @var QueuedPaymentDAO $queuedPaymentDao */
|
||||
$queuedPayment = $queuedPaymentDao->getById($queuedPaymentId = array_shift($args));
|
||||
if (!$queuedPayment) {
|
||||
$templateMgr->assign([
|
||||
'pageTitle' => 'common.payment',
|
||||
'message' => 'payment.notFound',
|
||||
]);
|
||||
$templateMgr->display('frontend/pages/message.tpl');
|
||||
return;
|
||||
}
|
||||
|
||||
$paymentForm = $paymentManager->getPaymentForm($queuedPayment);
|
||||
$paymentForm->display($request);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @defgroup pages_payment Payment Pages
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file pages/payment/index.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.
|
||||
*
|
||||
* @ingroup pages_payment
|
||||
*
|
||||
* @brief Handle requests for interactions between the payment system and external
|
||||
* sites/systems.
|
||||
*/
|
||||
|
||||
switch ($op) {
|
||||
case 'plugin':
|
||||
case 'pay':
|
||||
define('HANDLER_CLASS', 'APP\pages\payment\PaymentHandler');
|
||||
break;
|
||||
}
|
||||
@@ -0,0 +1,241 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @file pages/payments/PaymentsHandler.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 PaymentsHandler
|
||||
*
|
||||
* @ingroup pages_payments
|
||||
*
|
||||
* @brief Handle requests for payment management.
|
||||
*/
|
||||
|
||||
namespace APP\pages\payments;
|
||||
|
||||
use APP\core\Application;
|
||||
use APP\handler\Handler;
|
||||
use APP\notification\NotificationManager;
|
||||
use APP\subscription\form\PaymentTypesForm;
|
||||
use APP\subscription\form\SubscriptionPolicyForm;
|
||||
use APP\template\TemplateManager;
|
||||
use PKP\config\Config;
|
||||
use PKP\core\JSONMessage;
|
||||
use PKP\core\PKPApplication;
|
||||
use PKP\security\authorization\PKPSiteAccessPolicy;
|
||||
use PKP\security\Role;
|
||||
|
||||
class PaymentsHandler extends Handler
|
||||
{
|
||||
/** @copydoc PKPHandler::_isBackendPage */
|
||||
public $_isBackendPage = true;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct();
|
||||
$this->addRoleAssignment(
|
||||
[Role::ROLE_ID_MANAGER, Role::ROLE_ID_SITE_ADMIN, Role::ROLE_ID_SUBSCRIPTION_MANAGER],
|
||||
['index', 'subscriptions', 'subscriptionTypes', 'subscriptionPolicies', 'saveSubscriptionPolicies', 'paymentTypes', 'savePaymentTypes', 'payments']
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Display a list of payment tabs for the current journal.
|
||||
*
|
||||
* @param array $args
|
||||
* @param \APP\core\Request $request
|
||||
*/
|
||||
public function index($args, $request)
|
||||
{
|
||||
$this->setupTemplate($request);
|
||||
$templateMgr = TemplateManager::getManager($request);
|
||||
$templateMgr->assign([
|
||||
'pageTitle' => __('manager.subscriptions'),
|
||||
]);
|
||||
$templateMgr->display('payments/index.tpl');
|
||||
}
|
||||
|
||||
/**
|
||||
* @copydoc PKPHandler::authorize()
|
||||
*/
|
||||
public function authorize($request, &$args, $roleAssignments)
|
||||
{
|
||||
$this->addPolicy(new PKPSiteAccessPolicy($request, null, $roleAssignments));
|
||||
return parent::authorize($request, $args, $roleAssignments);
|
||||
}
|
||||
|
||||
/**
|
||||
* Display a list of subscriptions for the current journal.
|
||||
*
|
||||
* @param array $args
|
||||
* @param \APP\core\Request $request
|
||||
*/
|
||||
public function subscriptions($args, $request)
|
||||
{
|
||||
$templateMgr = TemplateManager::getManager($request);
|
||||
$dispatcher = $request->getDispatcher();
|
||||
switch (array_shift($args)) {
|
||||
case 'institutional':
|
||||
return $templateMgr->fetchAjax(
|
||||
'institutionalSubscriptionsGridContainer',
|
||||
$dispatcher->url(
|
||||
$request,
|
||||
PKPApplication::ROUTE_COMPONENT,
|
||||
null,
|
||||
'grid.subscriptions.InstitutionalSubscriptionsGridHandler',
|
||||
'fetchGrid'
|
||||
)
|
||||
);
|
||||
case 'individual':
|
||||
return $templateMgr->fetchAjax(
|
||||
'individualSubscriptionsGridContainer',
|
||||
$dispatcher->url(
|
||||
$request,
|
||||
PKPApplication::ROUTE_COMPONENT,
|
||||
null,
|
||||
'grid.subscriptions.IndividualSubscriptionsGridHandler',
|
||||
'fetchGrid'
|
||||
)
|
||||
);
|
||||
}
|
||||
$dispatcher->handle404();
|
||||
}
|
||||
|
||||
/**
|
||||
* Display a list of subscription types for the current journal.
|
||||
*
|
||||
* @param array $args
|
||||
* @param \APP\core\Request $request
|
||||
*/
|
||||
public function subscriptionTypes($args, $request)
|
||||
{
|
||||
$templateMgr = TemplateManager::getManager($request);
|
||||
$dispatcher = $request->getDispatcher();
|
||||
return $templateMgr->fetchAjax(
|
||||
'subscriptionTypesGridContainer',
|
||||
$dispatcher->url(
|
||||
$request,
|
||||
PKPApplication::ROUTE_COMPONENT,
|
||||
null,
|
||||
'grid.subscriptions.SubscriptionTypesGridHandler',
|
||||
'fetchGrid'
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Display subscription policies for the current journal.
|
||||
*
|
||||
* @param array $args
|
||||
* @param \APP\core\Request $request
|
||||
*/
|
||||
public function subscriptionPolicies($args, $request)
|
||||
{
|
||||
$this->validate();
|
||||
$this->setupTemplate($request);
|
||||
|
||||
$templateMgr = TemplateManager::getManager($request);
|
||||
|
||||
if (Config::getVar('general', 'scheduled_tasks')) {
|
||||
$templateMgr->assign('scheduledTasksEnabled', true);
|
||||
}
|
||||
|
||||
$paymentManager = Application::getPaymentManager($request->getJournal());
|
||||
$templateMgr->assign('acceptSubscriptionPayments', $paymentManager->isConfigured());
|
||||
|
||||
$subscriptionPolicyForm = new SubscriptionPolicyForm();
|
||||
$subscriptionPolicyForm->initData();
|
||||
return new JSONMessage(true, $subscriptionPolicyForm->fetch($request));
|
||||
}
|
||||
|
||||
/**
|
||||
* Save subscription policies for the current journal.
|
||||
*
|
||||
* @param array $args
|
||||
* @param \APP\core\Request $request
|
||||
*/
|
||||
public function saveSubscriptionPolicies($args, $request)
|
||||
{
|
||||
$this->validate();
|
||||
$this->setupTemplate($request);
|
||||
|
||||
$subscriptionPolicyForm = new SubscriptionPolicyForm();
|
||||
$subscriptionPolicyForm->readInputData();
|
||||
if ($subscriptionPolicyForm->validate()) {
|
||||
$subscriptionPolicyForm->execute();
|
||||
$notificationManager = new NotificationManager();
|
||||
$user = $request->getUser();
|
||||
$notificationManager->createTrivialNotification($user->getId());
|
||||
return new JSONMessage(true);
|
||||
}
|
||||
return new JSONMessage(true, $subscriptionPolicyForm->fetch($request));
|
||||
}
|
||||
|
||||
/**
|
||||
* Display payment types for the current journal.
|
||||
*
|
||||
* @param array $args
|
||||
* @param \APP\core\Request $request
|
||||
*/
|
||||
public function paymentTypes($args, $request)
|
||||
{
|
||||
$this->validate();
|
||||
$this->setupTemplate($request);
|
||||
|
||||
|
||||
$paymentTypesForm = new PaymentTypesForm();
|
||||
$paymentTypesForm->initData();
|
||||
return new JSONMessage(true, $paymentTypesForm->fetch($request));
|
||||
}
|
||||
|
||||
/**
|
||||
* Save payment types for the current journal.
|
||||
*
|
||||
* @param array $args
|
||||
* @param \APP\core\Request $request
|
||||
*/
|
||||
public function savePaymentTypes($args, $request)
|
||||
{
|
||||
$this->validate();
|
||||
$this->setupTemplate($request);
|
||||
|
||||
$paymentTypesForm = new PaymentTypesForm();
|
||||
$paymentTypesForm->readInputData();
|
||||
if ($paymentTypesForm->validate()) {
|
||||
$paymentTypesForm->execute();
|
||||
$notificationManager = new NotificationManager();
|
||||
$user = $request->getUser();
|
||||
$notificationManager->createTrivialNotification($user->getId());
|
||||
return new JSONMessage(true);
|
||||
}
|
||||
return new JSONMessage(true, $paymentTypesForm->fetch($request));
|
||||
}
|
||||
|
||||
/**
|
||||
* Display a list of payments for the current journal.
|
||||
*
|
||||
* @param array $args
|
||||
* @param \APP\core\Request $request
|
||||
*/
|
||||
public function payments($args, $request)
|
||||
{
|
||||
$templateMgr = TemplateManager::getManager($request);
|
||||
$dispatcher = $request->getDispatcher();
|
||||
return $templateMgr->fetchAjax(
|
||||
'paymentsGridContainer',
|
||||
$dispatcher->url(
|
||||
$request,
|
||||
PKPApplication::ROUTE_COMPONENT,
|
||||
null,
|
||||
'grid.subscriptions.PaymentsGridHandler',
|
||||
'fetchGrid'
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @defgroup pages_payments Payment Management Pages
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file pages/payments/index.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.
|
||||
*
|
||||
* @ingroup pages_subscriptions
|
||||
*
|
||||
* @brief Handle requests for payment management functions.
|
||||
*
|
||||
*/
|
||||
|
||||
switch ($op) {
|
||||
//
|
||||
// Issue
|
||||
//
|
||||
case 'index':
|
||||
case 'subscriptions':
|
||||
case 'subscriptionTypes':
|
||||
case 'subscriptionPolicies':
|
||||
case 'saveSubscriptionPolicies':
|
||||
case 'paymentTypes':
|
||||
case 'savePaymentTypes':
|
||||
case 'payments':
|
||||
define('HANDLER_CLASS', 'APP\pages\payments\PaymentsHandler');
|
||||
break;
|
||||
}
|
||||
@@ -0,0 +1,154 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @file pages/reviewer/ReviewerHandler.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 ReviewerHandler
|
||||
*
|
||||
* @ingroup pages_reviewer
|
||||
*
|
||||
* @brief Handle requests for reviewer functions.
|
||||
*/
|
||||
|
||||
namespace APP\pages\reviewer;
|
||||
|
||||
use APP\core\Request;
|
||||
use APP\facades\Repo;
|
||||
use APP\submission\reviewer\form\ReviewerReviewStep3Form;
|
||||
use APP\submission\Submission;
|
||||
use PKP\core\PKPRequest;
|
||||
use PKP\db\DAORegistry;
|
||||
use PKP\pages\reviewer\PKPReviewerHandler;
|
||||
use PKP\security\AccessKeyManager;
|
||||
use PKP\security\authorization\SubmissionAccessPolicy;
|
||||
use PKP\security\Role;
|
||||
use PKP\security\Validation;
|
||||
use PKP\session\SessionManager;
|
||||
use PKP\submission\reviewAssignment\ReviewAssignment;
|
||||
use PKP\submission\reviewAssignment\ReviewAssignmentDAO;
|
||||
use PKP\submission\reviewer\form\ReviewerReviewForm;
|
||||
use PKP\user\User;
|
||||
|
||||
class ReviewerHandler extends PKPReviewerHandler
|
||||
{
|
||||
/** @var Submission */
|
||||
public $submission;
|
||||
|
||||
/** @var User */
|
||||
public $user;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct();
|
||||
$this->addRoleAssignment(
|
||||
Role::ROLE_ID_REVIEWER,
|
||||
[
|
||||
'submission', 'step', 'saveStep',
|
||||
'showDeclineReview', 'saveDeclineReview', 'downloadFile'
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @copydoc PKPHandler::authorize()
|
||||
*/
|
||||
public function authorize($request, &$args, $roleAssignments)
|
||||
{
|
||||
$context = $request->getContext();
|
||||
if ($context->getData('reviewerAccessKeysEnabled')) {
|
||||
$this->_validateAccessKey($request);
|
||||
}
|
||||
|
||||
$router = $request->getRouter();
|
||||
$this->addPolicy(new SubmissionAccessPolicy(
|
||||
$request,
|
||||
$args,
|
||||
$roleAssignments
|
||||
));
|
||||
|
||||
|
||||
return parent::authorize($request, $args, $roleAssignments);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests if the request contains a valid access token. If this is the case
|
||||
* the regular login process will be skipped
|
||||
*
|
||||
* @param Request $request
|
||||
*/
|
||||
protected function _validateAccessKey($request)
|
||||
{
|
||||
$accessKeyCode = $request->getUserVar('key');
|
||||
$reviewId = $request->getUserVar('reviewId');
|
||||
if (!($accessKeyCode && $reviewId)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Check if the user is already logged in
|
||||
$sessionManager = SessionManager::getManager();
|
||||
$session = $sessionManager->getUserSession();
|
||||
if ($session->getUserId()) {
|
||||
return;
|
||||
}
|
||||
|
||||
$reviewAssignmentDao = DAORegistry::getDAO('ReviewAssignmentDAO'); /** @var ReviewAssignmentDAO $reviewAssignmentDao */
|
||||
$reviewAssignment = $reviewAssignmentDao->getById($reviewId);
|
||||
if (!$reviewAssignment) {
|
||||
return;
|
||||
} // e.g. deleted review assignment
|
||||
|
||||
$reviewSubmission = Repo::submission()->get($reviewAssignment->getSubmissionId());
|
||||
if (!$reviewSubmission || ($reviewSubmission->getId() != $reviewAssignment->getSubmissionId())) {
|
||||
return;
|
||||
} // e.g. deleted review assignment
|
||||
|
||||
// Validate the access key
|
||||
$context = $request->getContext();
|
||||
$accessKeyManager = new AccessKeyManager();
|
||||
$accessKeyHash = $accessKeyManager->generateKeyHash($accessKeyCode);
|
||||
$accessKey = $accessKeyManager->validateKey(
|
||||
$context->getId(),
|
||||
$reviewAssignment->getReviewerId(),
|
||||
$accessKeyHash
|
||||
);
|
||||
if (!$accessKey) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Get the reviewer user object
|
||||
$user = Repo::user()->get($accessKey->getUserId());
|
||||
if (!$user) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Register the user object in the session
|
||||
$reason = null;
|
||||
if (Validation::registerUserSession($user, $reason)) {
|
||||
$this->submission = $reviewSubmission;
|
||||
$this->user = $user;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @copydoc PKPReviewerHandler::getReviewForm()
|
||||
*/
|
||||
public function getReviewForm(
|
||||
int $step,
|
||||
PKPRequest $request,
|
||||
Submission $reviewSubmission,
|
||||
ReviewAssignment $reviewAssignment
|
||||
): ReviewerReviewForm {
|
||||
switch ($step) {
|
||||
case 3:
|
||||
return new ReviewerReviewStep3Form($request, $reviewSubmission, $reviewAssignment);
|
||||
}
|
||||
return parent::getReviewForm($step, $request, $reviewSubmission, $reviewAssignment);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @defgroup pages_reviewer Reviewer Pages
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file pages/reviewer/index.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.
|
||||
*
|
||||
* @ingroup pages_reviewer
|
||||
*
|
||||
* @brief Handle requests for reviewer functions.
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
switch ($op) {
|
||||
//
|
||||
// Submission Tracking
|
||||
//
|
||||
case 'submission':
|
||||
case 'step':
|
||||
case 'saveStep':
|
||||
case 'showDeclineReview':
|
||||
case 'saveDeclineReview':
|
||||
define('HANDLER_CLASS', 'APP\pages\reviewer\ReviewerHandler');
|
||||
break;
|
||||
}
|
||||
@@ -0,0 +1,244 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @file pages/search/SearchHandler.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 SearchHandler
|
||||
*
|
||||
* @ingroup pages_search
|
||||
*
|
||||
* @brief Handle site index requests.
|
||||
*/
|
||||
|
||||
namespace APP\pages\search;
|
||||
|
||||
use APP\core\Services;
|
||||
use APP\facades\Repo;
|
||||
use APP\handler\Handler;
|
||||
use APP\search\ArticleSearch;
|
||||
use APP\security\authorization\OjsJournalMustPublishPolicy;
|
||||
use APP\template\TemplateManager;
|
||||
|
||||
class SearchHandler extends Handler
|
||||
{
|
||||
/**
|
||||
* @copydoc PKPHandler::authorize()
|
||||
*
|
||||
* @param mixed $request
|
||||
* @param mixed $args
|
||||
* @param mixed $roleAssignments
|
||||
*/
|
||||
public function authorize($request, &$args, $roleAssignments)
|
||||
{
|
||||
if ($request->getContext()) {
|
||||
$this->addPolicy(new OjsJournalMustPublishPolicy($request));
|
||||
}
|
||||
|
||||
return parent::authorize($request, $args, $roleAssignments);
|
||||
}
|
||||
|
||||
/**
|
||||
* Show the search form
|
||||
*
|
||||
* @param array $args
|
||||
* @param \APP\core\Request $request
|
||||
*/
|
||||
public function index($args, $request)
|
||||
{
|
||||
$this->validate(null, $request);
|
||||
$this->search($args, $request);
|
||||
}
|
||||
|
||||
/**
|
||||
* Private function to transmit current filter values
|
||||
* to the template.
|
||||
*
|
||||
* @param \APP\core\Request $request
|
||||
* @param TemplateManager $templateMgr
|
||||
* @param array $searchFilters
|
||||
*/
|
||||
public function _assignSearchFilters($request, &$templateMgr, $searchFilters)
|
||||
{
|
||||
// Get the journal id (if any).
|
||||
$journal = & $searchFilters['searchJournal'];
|
||||
$journalId = ($journal ? $journal->getId() : null);
|
||||
$searchFilters['searchJournal'] = $journalId;
|
||||
|
||||
// Assign all filters except for dates which need special treatment.
|
||||
$templateSearchFilters = [];
|
||||
foreach ($searchFilters as $filterName => $filterValue) {
|
||||
if (in_array($filterName, ['fromDate', 'toDate'])) {
|
||||
continue;
|
||||
}
|
||||
$templateSearchFilters[$filterName] = $filterValue;
|
||||
}
|
||||
|
||||
// Assign the filters to the template.
|
||||
$templateMgr->assign($templateSearchFilters);
|
||||
|
||||
// Special case: publication date filters.
|
||||
foreach (['From', 'To'] as $fromTo) {
|
||||
$month = $request->getUserVar("date{$fromTo}Month");
|
||||
$day = $request->getUserVar("date{$fromTo}Day");
|
||||
$year = $request->getUserVar("date{$fromTo}Year");
|
||||
if (empty($year)) {
|
||||
$date = null;
|
||||
$hasEmptyFilters = true;
|
||||
} else {
|
||||
$defaultMonth = ($fromTo == 'From' ? 1 : 12);
|
||||
$defaultDay = ($fromTo == 'From' ? 1 : 31);
|
||||
$date = date(
|
||||
'Y-m-d H:i:s',
|
||||
mktime(
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
empty($month) ? $defaultMonth : $month,
|
||||
empty($day) ? $defaultDay : $day,
|
||||
$year
|
||||
)
|
||||
);
|
||||
$hasActiveFilters = true;
|
||||
}
|
||||
$templateMgr->assign([
|
||||
"date{$fromTo}Month" => $month,
|
||||
"date{$fromTo}Day" => $day,
|
||||
"date{$fromTo}Year" => $year,
|
||||
"date{$fromTo}" => $date
|
||||
]);
|
||||
}
|
||||
|
||||
// Assign the year range.
|
||||
$collector = Repo::publication()->getCollector();
|
||||
if ($journalId) {
|
||||
$collector->filterByContextIds([(int) $journalId]);
|
||||
}
|
||||
$yearRange = Repo::publication()->getDateBoundaries($collector);
|
||||
$yearStart = substr($yearRange->min_date_published, 0, 4);
|
||||
$yearEnd = substr($yearRange->max_date_published, 0, 4);
|
||||
$templateMgr->assign([
|
||||
'yearStart' => $yearStart,
|
||||
'yearEnd' => $yearEnd,
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Show the search form
|
||||
*
|
||||
* @param array $args
|
||||
* @param \APP\core\Request $request
|
||||
*/
|
||||
public function search($args, $request)
|
||||
{
|
||||
$this->validate(null, $request);
|
||||
|
||||
// Get and transform active filters.
|
||||
$articleSearch = new ArticleSearch();
|
||||
$searchFilters = $articleSearch->getSearchFilters($request);
|
||||
$keywords = $articleSearch->getKeywordsFromSearchFilters($searchFilters);
|
||||
|
||||
// Get the range info.
|
||||
$rangeInfo = $this->getRangeInfo($request, 'search');
|
||||
|
||||
// Retrieve results.
|
||||
$error = '';
|
||||
$results = $articleSearch->retrieveResults(
|
||||
$request,
|
||||
$searchFilters['searchJournal'],
|
||||
$keywords,
|
||||
$error,
|
||||
$searchFilters['fromDate'],
|
||||
$searchFilters['toDate'],
|
||||
$rangeInfo
|
||||
);
|
||||
|
||||
$this->setupTemplate($request);
|
||||
|
||||
$templateMgr = TemplateManager::getManager($request);
|
||||
$templateMgr->setCacheability(TemplateManager::CACHEABILITY_NO_STORE);
|
||||
|
||||
$this->_assignSearchFilters($request, $templateMgr, $searchFilters);
|
||||
[$orderBy, $orderDir] = $articleSearch->getResultSetOrdering($request);
|
||||
|
||||
$templateMgr->assign([
|
||||
'orderBy' => $orderBy,
|
||||
'orderDir' => $orderDir,
|
||||
'simDocsEnabled' => true,
|
||||
'results' => $results,
|
||||
'error' => $error,
|
||||
'authorUserGroups' => Repo::userGroup()->getCollector()
|
||||
->filterByRoleIds([\PKP\security\Role::ROLE_ID_AUTHOR])
|
||||
->filterByContextIds($searchFilters['searchJournal'] ? [$searchFilters['searchJournal']->getId()] : null)
|
||||
->getMany()->remember(),
|
||||
'searchResultOrderOptions' => $articleSearch->getResultSetOrderingOptions($request),
|
||||
'searchResultOrderDirOptions' => $articleSearch->getResultSetOrderingDirectionOptions(),
|
||||
]);
|
||||
|
||||
if (!$request->getContext()) {
|
||||
$templateMgr->assign([
|
||||
'searchableContexts' => $this->getSearchableContexts(),
|
||||
]);
|
||||
}
|
||||
|
||||
$templateMgr->display('frontend/pages/search.tpl');
|
||||
}
|
||||
|
||||
/**
|
||||
* Redirect to a search query that shows documents
|
||||
* similar to the one identified by an article id in the
|
||||
* request.
|
||||
*
|
||||
* @param array $args
|
||||
* @param \APP\core\Request $request
|
||||
*/
|
||||
public function similarDocuments($args, &$request)
|
||||
{
|
||||
$this->validate(null, $request);
|
||||
|
||||
// Retrieve the (mandatory) ID of the article that
|
||||
// we want similar documents for.
|
||||
$articleId = $request->getUserVar('articleId');
|
||||
if (!is_numeric($articleId)) {
|
||||
$request->redirect(null, 'search');
|
||||
}
|
||||
|
||||
// Check whether a search plugin provides terms for a similarity search.
|
||||
$articleSearch = new ArticleSearch();
|
||||
$searchTerms = $articleSearch->getSimilarityTerms($articleId);
|
||||
|
||||
// Redirect to a search query with the identified search terms (if any).
|
||||
if (empty($searchTerms)) {
|
||||
$searchParams = null;
|
||||
} else {
|
||||
$searchParams = ['query' => implode(' ', $searchTerms)];
|
||||
}
|
||||
$request->redirect(null, 'search', null, null, $searchParams);
|
||||
}
|
||||
|
||||
/**
|
||||
* Setup common template variables.
|
||||
*
|
||||
* @param \APP\core\Request $request
|
||||
*/
|
||||
public function setupTemplate($request)
|
||||
{
|
||||
parent::setupTemplate($request);
|
||||
$templateMgr = TemplateManager::getManager($request);
|
||||
$journal = $request->getJournal();
|
||||
if (!$journal || !$journal->getData('restrictSiteAccess')) {
|
||||
$templateMgr->setCacheability(TemplateManager::CACHEABILITY_PUBLIC);
|
||||
}
|
||||
}
|
||||
|
||||
protected function getSearchableContexts(): array
|
||||
{
|
||||
$contextService = Services::get('context');
|
||||
return $contextService->getManySummary([
|
||||
'isEnabled' => true,
|
||||
]);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @defgroup pages_search Search Pages
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file pages/search/index.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.
|
||||
*
|
||||
* @ingroup pages_search
|
||||
*
|
||||
* @brief Handle search requests.
|
||||
*
|
||||
*/
|
||||
|
||||
switch ($op) {
|
||||
case 'index':
|
||||
case 'search':
|
||||
case 'similarDocuments':
|
||||
define('HANDLER_CLASS', 'APP\pages\search\SearchHandler');
|
||||
break;
|
||||
}
|
||||
@@ -0,0 +1,82 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @file pages/sitemap/SitemapHandler.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 SitemapHandler
|
||||
*
|
||||
* @ingroup pages_sitemap
|
||||
*
|
||||
* @brief Produce a sitemap in XML format for submitting to search engines.
|
||||
*/
|
||||
|
||||
namespace APP\pages\sitemap;
|
||||
|
||||
use APP\facades\Repo;
|
||||
use APP\issue\Collector;
|
||||
use APP\submission\Submission;
|
||||
use PKP\pages\sitemap\PKPSitemapHandler;
|
||||
use PKP\plugins\Hook;
|
||||
|
||||
class SitemapHandler extends PKPSitemapHandler
|
||||
{
|
||||
/**
|
||||
* @copydoc PKPSitemapHandler_createContextSitemap()
|
||||
*/
|
||||
public function _createContextSitemap($request)
|
||||
{
|
||||
$doc = parent::_createContextSitemap($request);
|
||||
$root = $doc->documentElement;
|
||||
|
||||
$journal = $request->getJournal();
|
||||
$journalId = $journal->getId();
|
||||
|
||||
// Search
|
||||
$root->appendChild($this->_createUrlTree($doc, $request->url($journal->getPath(), 'search')));
|
||||
// Issues
|
||||
if ($journal->getData('publishingMode') != \APP\journal\Journal::PUBLISHING_MODE_NONE) {
|
||||
$root->appendChild($this->_createUrlTree($doc, $request->url($journal->getPath(), 'issue', 'current')));
|
||||
$root->appendChild($this->_createUrlTree($doc, $request->url($journal->getPath(), 'issue', 'archive')));
|
||||
$publishedIssues = Repo::issue()->getCollector()
|
||||
->filterByContextIds([$journalId])
|
||||
->filterByPublished(true)
|
||||
->orderBy(Collector::ORDERBY_PUBLISHED_ISSUES)
|
||||
->getMany();
|
||||
foreach ($publishedIssues as $issue) {
|
||||
$root->appendChild($this->_createUrlTree($doc, $request->url($journal->getPath(), 'issue', 'view', $issue->getId())));
|
||||
// Articles for issue
|
||||
$submissions = Repo::submission()
|
||||
->getCollector()
|
||||
->filterByContextIds([$journal->getId()])
|
||||
->filterByIssueIds([$issue->getId()])
|
||||
->filterByStatus([Submission::STATUS_PUBLISHED])
|
||||
->getMany();
|
||||
|
||||
foreach ($submissions as $submission) {
|
||||
// Abstract
|
||||
$root->appendChild($this->_createUrlTree($doc, $request->url($journal->getPath(), 'article', 'view', [$submission->getBestId()])));
|
||||
// Galley files
|
||||
$galleys = Repo::galley()
|
||||
->getCollector()
|
||||
->filterByPublicationIds([($submission->getCurrentPublication()->getId())])
|
||||
->getMany();
|
||||
|
||||
foreach ($galleys as $galley) {
|
||||
$root->appendChild($this->_createUrlTree($doc, $request->url($journal->getPath(), 'article', 'view', [$submission->getBestId(), $galley->getBestGalleyId()])));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$doc->appendChild($root);
|
||||
|
||||
// Enable plugins to change the sitemap
|
||||
Hook::call('SitemapHandler::createJournalSitemap', [&$doc]);
|
||||
|
||||
return $doc;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @defgroup pages_sitemap Site Map Pages
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file pages/sitemap/index.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.
|
||||
*
|
||||
* @ingroup pages_sitemap
|
||||
*
|
||||
* @brief Produce a sitemap in XML format for submitting to search engines.
|
||||
*
|
||||
*/
|
||||
|
||||
switch ($op) {
|
||||
case 'index':
|
||||
define('HANDLER_CLASS', 'APP\pages\sitemap\SitemapHandler');
|
||||
break;
|
||||
}
|
||||
@@ -0,0 +1,194 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @file pages/stats/StatsHandler.php
|
||||
*
|
||||
* Copyright (c) 2013-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 StatsHandler
|
||||
*
|
||||
* @ingroup pages_stats
|
||||
*
|
||||
* @brief Handle requests for statistics pages.
|
||||
*/
|
||||
|
||||
namespace APP\pages\stats;
|
||||
|
||||
use APP\core\Application;
|
||||
use APP\core\Request;
|
||||
use APP\core\Services;
|
||||
use APP\facades\Repo;
|
||||
use APP\template\TemplateManager;
|
||||
use PKP\core\PKPApplication;
|
||||
use PKP\pages\stats\PKPStatsHandler;
|
||||
use PKP\plugins\Hook;
|
||||
use PKP\security\Role;
|
||||
use PKP\statistics\PKPStatisticsHelper;
|
||||
|
||||
class StatsHandler extends PKPStatsHandler
|
||||
{
|
||||
/**
|
||||
* Constructor.
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct();
|
||||
$this->addRoleAssignment(
|
||||
[Role::ROLE_ID_SITE_ADMIN, Role::ROLE_ID_MANAGER, Role::ROLE_ID_SUB_EDITOR],
|
||||
['issues']
|
||||
);
|
||||
Hook::add('TemplateManager::display', [$this, 'addSectionFilters']);
|
||||
}
|
||||
|
||||
/**
|
||||
* Display issues stats
|
||||
*
|
||||
*/
|
||||
public function issues(array $args, Request $request): void
|
||||
{
|
||||
$dispatcher = $request->getDispatcher();
|
||||
$context = $request->getContext();
|
||||
|
||||
if (!$context) {
|
||||
$dispatcher->handle404();
|
||||
}
|
||||
|
||||
$templateMgr = TemplateManager::getManager($request);
|
||||
$this->setupTemplate($request);
|
||||
|
||||
$dateStart = date('Y-m-d', strtotime('-31 days'));
|
||||
$dateEnd = date('Y-m-d', strtotime('yesterday'));
|
||||
$count = 30;
|
||||
|
||||
$timeline = Services::get('issueStats')->getTimeline(PKPStatisticsHelper::STATISTICS_DIMENSION_DAY, [
|
||||
'assocTypes' => [Application::ASSOC_TYPE_ISSUE],
|
||||
'contextIds' => [$context->getId()],
|
||||
'count' => $count,
|
||||
'dateStart' => $dateStart,
|
||||
'dateEnd' => $dateEnd,
|
||||
]);
|
||||
|
||||
$statsComponent = new \APP\components\StatsIssuePage(
|
||||
$dispatcher->url($request, PKPApplication::ROUTE_API, $context->getPath(), 'stats/issues'),
|
||||
[
|
||||
'timeline' => $timeline,
|
||||
'timelineInterval' => PKPStatisticsHelper::STATISTICS_DIMENSION_DAY,
|
||||
'timelineType' => 'toc',
|
||||
'tableColumns' => [
|
||||
[
|
||||
'name' => 'title',
|
||||
'label' => __('issue.issue'),
|
||||
],
|
||||
[
|
||||
'name' => 'tocViews',
|
||||
'label' => __('stats.views'),
|
||||
'value' => 'tocViews',
|
||||
],
|
||||
[
|
||||
'name' => 'issueGalleyViews',
|
||||
'label' => __('stats.downloads'),
|
||||
'value' => 'issueGalleyViews',
|
||||
],
|
||||
[
|
||||
'name' => 'total',
|
||||
'label' => __('stats.total'),
|
||||
'value' => 'totalViews',
|
||||
'orderBy' => 'totalViews',
|
||||
'initialOrderDirection' => true,
|
||||
],
|
||||
],
|
||||
'count' => $count,
|
||||
'dateStart' => $dateStart,
|
||||
'dateEnd' => $dateEnd,
|
||||
'dateRangeOptions' => [
|
||||
[
|
||||
'dateStart' => $dateStart,
|
||||
'dateEnd' => $dateEnd,
|
||||
'label' => __('stats.dateRange.last30Days'),
|
||||
],
|
||||
[
|
||||
'dateStart' => date('Y-m-d', strtotime('-91 days')),
|
||||
'dateEnd' => $dateEnd,
|
||||
'label' => __('stats.dateRange.last90Days'),
|
||||
],
|
||||
[
|
||||
'dateStart' => date('Y-m-d', strtotime('-12 months')),
|
||||
'dateEnd' => $dateEnd,
|
||||
'label' => __('stats.dateRange.last12Months'),
|
||||
],
|
||||
[
|
||||
'dateStart' => '',
|
||||
'dateEnd' => '',
|
||||
'label' => __('stats.dateRange.allDates'),
|
||||
],
|
||||
],
|
||||
'orderBy' => 'total',
|
||||
'orderDirection' => true,
|
||||
]
|
||||
);
|
||||
$templateMgr->setState($statsComponent->getConfig());
|
||||
$templateMgr->assign([
|
||||
'pageComponent' => 'StatsIssuesPage',
|
||||
'pageTitle' => __('stats.issueStats'),
|
||||
'pageWidth' => TemplateManager::PAGE_WIDTH_WIDE
|
||||
]);
|
||||
|
||||
$templateMgr->display('stats/issues.tpl');
|
||||
}
|
||||
|
||||
/**
|
||||
* Add OJS-specific configuration options to the stats component data
|
||||
*
|
||||
* Fired when the `TemplateManager::display` hook is called.
|
||||
*
|
||||
* @param array $args [$templateMgr, $template, $sendContentType, $charset, $output]
|
||||
*/
|
||||
public function addSectionFilters($hookName, $args)
|
||||
{
|
||||
$templateMgr = $args[0];
|
||||
$template = $args[1];
|
||||
|
||||
if (!in_array($template, ['stats/publications.tpl', 'stats/editorial.tpl'])) {
|
||||
return;
|
||||
}
|
||||
|
||||
$context = Application::get()->getRequest()->getContext();
|
||||
|
||||
$filters = $templateMgr->getState('filters');
|
||||
if (is_null($filters)) {
|
||||
$filters = [];
|
||||
}
|
||||
$sections = Repo::section()->getSectionList($context->getId());
|
||||
$filters[] = [
|
||||
'heading' => __('section.sections'),
|
||||
'filters' => array_map(function ($section) {
|
||||
return [
|
||||
'param' => 'sectionIds',
|
||||
'value' => (int) $section['id'],
|
||||
'title' => $section['title'],
|
||||
];
|
||||
}, $sections),
|
||||
];
|
||||
if ($template == 'stats/publications.tpl') {
|
||||
$issues = Repo::issue()->getCollector()
|
||||
->filterByContextIds([$context->getId()])
|
||||
->filterByPublished(true)
|
||||
->getMany();
|
||||
$filters[] = [
|
||||
'heading' => __('issue.issues'),
|
||||
'filters' => $issues->map(function ($issue, $key) {
|
||||
return [
|
||||
'param' => 'issueIds',
|
||||
'value' => (int) $issue->getId(),
|
||||
'title' => $issue->getIssueIdentification(),
|
||||
];
|
||||
})->toArray(),
|
||||
];
|
||||
}
|
||||
$templateMgr->setState([
|
||||
'filters' => $filters
|
||||
]);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @defgroup pages_stats Statistics Pages
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file pages/stats/index.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.
|
||||
*
|
||||
* @ingroup pages_stats
|
||||
*
|
||||
* @brief Handle requests for statistics pages.
|
||||
*
|
||||
*/
|
||||
|
||||
define('HANDLER_CLASS', 'APP\pages\stats\StatsHandler');
|
||||
@@ -0,0 +1,171 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @file pages/submission/SubmissionHandler.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 SubmissionHandler
|
||||
*
|
||||
* @ingroup pages_submission
|
||||
*
|
||||
* @brief Handles page requests to the submission wizard
|
||||
*/
|
||||
|
||||
namespace APP\pages\submission;
|
||||
|
||||
use APP\components\forms\submission\ReconfigureSubmission;
|
||||
use APP\components\forms\submission\StartSubmission;
|
||||
use APP\core\Application;
|
||||
use APP\core\Request;
|
||||
use APP\publication\Publication;
|
||||
use APP\section\Section;
|
||||
use APP\submission\Submission;
|
||||
use APP\template\TemplateManager;
|
||||
use Illuminate\Support\LazyCollection;
|
||||
use PKP\components\forms\FormComponent;
|
||||
use PKP\components\forms\publication\Details;
|
||||
use PKP\components\forms\publication\TitleAbstractForm;
|
||||
use PKP\components\forms\submission\ForTheEditors;
|
||||
use PKP\context\Context;
|
||||
use PKP\facades\Locale;
|
||||
use PKP\pages\submission\PKPSubmissionHandler;
|
||||
|
||||
class SubmissionHandler extends PKPSubmissionHandler
|
||||
{
|
||||
/**
|
||||
* Display the screen to start a new submission
|
||||
*/
|
||||
protected function start(array $args, Request $request): void
|
||||
{
|
||||
$context = $request->getContext();
|
||||
$userGroups = $this->getSubmitUserGroups($context, $request->getUser());
|
||||
if (!$userGroups->count()) {
|
||||
$this->showErrorPage(
|
||||
'submission.wizard.notAllowed',
|
||||
__('submission.wizard.notAllowed.description', [
|
||||
'email' => $context->getData('contactEmail'),
|
||||
'name' => $context->getData('contactName'),
|
||||
])
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
$sections = $this->getSubmitSections($context);
|
||||
if (empty($sections)) {
|
||||
$this->showErrorPage(
|
||||
'submission.wizard.notAllowed',
|
||||
__('submission.wizard.noSectionAllowed.description', [
|
||||
'email' => $context->getData('contactEmail'),
|
||||
'name' => $context->getData('contactName'),
|
||||
])
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
$apiUrl = $request->getDispatcher()->url(
|
||||
$request,
|
||||
Application::ROUTE_API,
|
||||
$context->getPath(),
|
||||
'submissions'
|
||||
);
|
||||
|
||||
$form = new StartSubmission($apiUrl, $context, $userGroups, $sections);
|
||||
|
||||
$templateMgr = TemplateManager::getManager($request);
|
||||
|
||||
$templateMgr->setState([
|
||||
'form' => $form->getConfig(),
|
||||
]);
|
||||
|
||||
parent::start($args, $request);
|
||||
}
|
||||
|
||||
protected function getSubmittingTo(Context $context, Submission $submission, array $sections, LazyCollection $categories): string
|
||||
{
|
||||
$languageCount = count($context->getSupportedSubmissionLocales()) > 1;
|
||||
$sectionCount = count($sections) > 1;
|
||||
$section = collect($sections)->first(fn ($section) => $section->getId() === $submission->getCurrentPublication()->getData('sectionId'));
|
||||
|
||||
if ($sectionCount && $languageCount) {
|
||||
return __(
|
||||
'submission.wizard.submittingToSectionInLanguage',
|
||||
[
|
||||
'section' => $section->getLocalizedTitle(),
|
||||
'language' => Locale::getMetadata($submission->getData('locale'))->getDisplayName(),
|
||||
]
|
||||
);
|
||||
} elseif ($sectionCount) {
|
||||
return __(
|
||||
'submission.wizard.submittingToSection',
|
||||
[
|
||||
'section' => $section->getLocalizedTitle(),
|
||||
]
|
||||
);
|
||||
} elseif ($languageCount) {
|
||||
return __(
|
||||
'submission.wizard.submittingInLanguage',
|
||||
[
|
||||
'language' => Locale::getMetadata($submission->getData('locale'))->getDisplayName(),
|
||||
]
|
||||
);
|
||||
}
|
||||
return '';
|
||||
}
|
||||
|
||||
protected function getReconfigureForm(Context $context, Submission $submission, Publication $publication, array $sections, LazyCollection $categories): ReconfigureSubmission
|
||||
{
|
||||
return new ReconfigureSubmission(
|
||||
FormComponent::ACTION_EMIT,
|
||||
$submission,
|
||||
$publication,
|
||||
$context,
|
||||
$sections
|
||||
);
|
||||
}
|
||||
|
||||
protected function getDetailsForm(string $publicationApiUrl, array $locales, Publication $publication, Context $context, array $sections, string $suggestionUrlBase): TitleAbstractForm
|
||||
{
|
||||
/** @var Section $section */
|
||||
$section = collect($sections)->first(fn ($section) => $section->getId() === $publication->getData('sectionId'));
|
||||
|
||||
return new Details(
|
||||
$publicationApiUrl,
|
||||
$locales,
|
||||
$publication,
|
||||
$context,
|
||||
$suggestionUrlBase,
|
||||
(int) $section->getData('wordCount'),
|
||||
!$section->getData('abstractsNotRequired')
|
||||
);
|
||||
}
|
||||
|
||||
protected function getForTheEditorsForm(string $publicationApiUrl, array $locales, Publication $publication, Submission $submission, Context $context, string $suggestionUrlBase, LazyCollection $categories): ForTheEditors
|
||||
{
|
||||
return new ForTheEditors(
|
||||
$publicationApiUrl,
|
||||
$locales,
|
||||
$publication,
|
||||
$submission,
|
||||
$context,
|
||||
$suggestionUrlBase,
|
||||
$categories
|
||||
);
|
||||
}
|
||||
|
||||
protected function getReconfigurePublicationProps(): array
|
||||
{
|
||||
return [
|
||||
'sectionId',
|
||||
];
|
||||
}
|
||||
|
||||
protected function getReconfigureSubmissionProps(): array
|
||||
{
|
||||
return [
|
||||
'locale',
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @file pages/submission/index.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.
|
||||
*
|
||||
* @ingroup pages_submission
|
||||
*
|
||||
* @brief Handle requests for the submission wizard.
|
||||
*
|
||||
*/
|
||||
|
||||
switch ($op) {
|
||||
case 'index':
|
||||
case 'saved':
|
||||
case 'wizard': // Deprecated
|
||||
define('HANDLER_CLASS', 'APP\pages\submission\SubmissionHandler');
|
||||
break;
|
||||
}
|
||||
@@ -0,0 +1,440 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @file pages/user/UserHandler.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 UserHandler
|
||||
*
|
||||
* @ingroup pages_user
|
||||
*
|
||||
* @brief Handle requests for user functions.
|
||||
*/
|
||||
|
||||
namespace APP\pages\user;
|
||||
|
||||
use APP\core\Application;
|
||||
use APP\facades\Repo;
|
||||
use APP\journal\Journal;
|
||||
use APP\payment\ojs\OJSPaymentManager;
|
||||
use APP\subscription\form\UserIndividualSubscriptionForm;
|
||||
use APP\subscription\form\UserInstitutionalSubscriptionForm;
|
||||
use APP\subscription\IndividualSubscriptionDAO;
|
||||
use APP\subscription\InstitutionalSubscriptionDAO;
|
||||
use APP\subscription\Subscription;
|
||||
use APP\subscription\SubscriptionTypeDAO;
|
||||
use APP\template\TemplateManager;
|
||||
use PKP\db\DAORegistry;
|
||||
use PKP\pages\user\PKPUserHandler;
|
||||
|
||||
class UserHandler extends PKPUserHandler
|
||||
{
|
||||
/**
|
||||
* Display subscriptions page
|
||||
*
|
||||
* @param array $args
|
||||
* @param \APP\core\Request $request
|
||||
*/
|
||||
public function subscriptions($args, $request)
|
||||
{
|
||||
$this->validate(null, $request);
|
||||
|
||||
$journal = $request->getJournal();
|
||||
$user = $request->getUser();
|
||||
$templateMgr = TemplateManager::getManager($request);
|
||||
if (!$journal || !$user || $journal->getData('publishingMode') != Journal::PUBLISHING_MODE_SUBSCRIPTION) {
|
||||
$request->redirect(null, 'index');
|
||||
}
|
||||
|
||||
$subscriptionTypeDao = DAORegistry::getDAO('SubscriptionTypeDAO'); /** @var SubscriptionTypeDAO $subscriptionTypeDao */
|
||||
$individualSubscriptionTypesExist = $subscriptionTypeDao->subscriptionTypesExistByInstitutional($journal->getId(), false);
|
||||
$institutionalSubscriptionTypesExist = $subscriptionTypeDao->subscriptionTypesExistByInstitutional($journal->getId(), true);
|
||||
if (!$individualSubscriptionTypesExist && !$institutionalSubscriptionTypesExist) {
|
||||
$request->redirect(null, 'index');
|
||||
}
|
||||
|
||||
// Subscriptions contact and additional information
|
||||
// Get subscriptions and options for current journal
|
||||
if ($individualSubscriptionTypesExist) {
|
||||
$subscriptionDao = DAORegistry::getDAO('IndividualSubscriptionDAO'); /** @var IndividualSubscriptionDAO $subscriptionDao */
|
||||
$userIndividualSubscription = $subscriptionDao->getByUserIdForJournal($user->getId(), $journal->getId());
|
||||
$templateMgr->assign('userIndividualSubscription', $userIndividualSubscription);
|
||||
}
|
||||
|
||||
if ($institutionalSubscriptionTypesExist) {
|
||||
/** @var InstitutionalSubscriptionDAO $subscriptionDao */
|
||||
$subscriptionDao = DAORegistry::getDAO('InstitutionalSubscriptionDAO');
|
||||
$userInstitutionalSubscriptions = $subscriptionDao->getByUserIdForJournal($user->getId(), $journal->getId())->toArray();
|
||||
$templateMgr->assign('userInstitutionalSubscriptions', $userInstitutionalSubscriptions);
|
||||
$institutions = [];
|
||||
foreach ($userInstitutionalSubscriptions as $userInstitutionalSubscription) {
|
||||
$institution = Repo::institution()->get($userInstitutionalSubscription->getInstitutionId());
|
||||
$institutions[$userInstitutionalSubscription->getId()] = $institution;
|
||||
}
|
||||
$templateMgr->assign('institutions', $institutions);
|
||||
}
|
||||
|
||||
$paymentManager = Application::getPaymentManager($journal);
|
||||
|
||||
$this->setupTemplate($request);
|
||||
|
||||
$templateMgr->assign([
|
||||
'subscriptionName' => $journal->getData('subscriptionName'),
|
||||
'subscriptionEmail' => $journal->getData('subscriptionEmail'),
|
||||
'subscriptionPhone' => $journal->getData('subscriptionPhone'),
|
||||
'subscriptionMailingAddress' => $journal->getData('subscriptionMailingAddress'),
|
||||
'subscriptionAdditionalInformation' => $journal->getLocalizedData('subscriptionAdditionalInformation'),
|
||||
'journalTitle' => $journal->getLocalizedName(),
|
||||
'journalPath' => $journal->getPath(),
|
||||
'individualSubscriptionTypesExist' => $individualSubscriptionTypesExist,
|
||||
'institutionalSubscriptionTypesExist' => $institutionalSubscriptionTypesExist,
|
||||
'paymentsEnabled' => $paymentManager->isConfigured(),
|
||||
]);
|
||||
$templateMgr->display('frontend/pages/userSubscriptions.tpl');
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if the journal's setup has been sufficiently completed.
|
||||
*
|
||||
* @param object $journal
|
||||
*
|
||||
* @return bool True iff setup is incomplete
|
||||
*/
|
||||
public function _checkIncompleteSetup($journal)
|
||||
{
|
||||
if ($journal->getLocalizedAcronym() == '' || $journal->getData('contactEmail') == '' ||
|
||||
$journal->getData('contactName') == '' || $journal->getLocalizedData('abbreviation') == '') {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// Payments
|
||||
//
|
||||
/**
|
||||
* Purchase a subscription.
|
||||
*
|
||||
* @param array $args
|
||||
* @param \APP\core\Request $request
|
||||
*/
|
||||
public function purchaseSubscription($args, $request)
|
||||
{
|
||||
$this->validate(null, $request);
|
||||
$journal = $request->getContext();
|
||||
if (empty($args) || !$journal || $journal->getData('publishingMode') != Journal::PUBLISHING_MODE_SUBSCRIPTION) {
|
||||
$request->redirect(null, 'index');
|
||||
}
|
||||
|
||||
$paymentManager = Application::getPaymentManager($journal);
|
||||
$acceptSubscriptionPayments = $paymentManager->isConfigured();
|
||||
if (!$acceptSubscriptionPayments) {
|
||||
$request->redirect(null, 'index');
|
||||
}
|
||||
|
||||
$this->setupTemplate($request);
|
||||
$user = $request->getUser();
|
||||
|
||||
$institutional = array_shift($args);
|
||||
if (!empty($args)) {
|
||||
$subscriptionId = (int) array_shift($args);
|
||||
}
|
||||
|
||||
if ($institutional == 'institutional') {
|
||||
$institutional = true;
|
||||
$subscriptionDao = DAORegistry::getDAO('InstitutionalSubscriptionDAO'); /** @var InstitutionalSubscriptionDAO $subscriptionDao */
|
||||
} else {
|
||||
$institutional = false;
|
||||
$subscriptionDao = DAORegistry::getDAO('IndividualSubscriptionDAO'); /** @var IndividualSubscriptionDAO $subscriptionDao */
|
||||
}
|
||||
|
||||
if (isset($subscriptionId)) {
|
||||
// Ensure subscription to be updated is for this user
|
||||
if (!$subscriptionDao->subscriptionExistsByUser($subscriptionId, $user->getId())) {
|
||||
$request->redirect(null, 'index');
|
||||
}
|
||||
|
||||
// Ensure subscription can be updated
|
||||
$subscription = $subscriptionDao->getById($subscriptionId);
|
||||
$subscriptionStatus = $subscription->getStatus();
|
||||
$validStatus = [
|
||||
Subscription::SUBSCRIPTION_STATUS_ACTIVE,
|
||||
Subscription::SUBSCRIPTION_STATUS_AWAITING_ONLINE_PAYMENT,
|
||||
Subscription::SUBSCRIPTION_STATUS_AWAITING_MANUAL_PAYMENT
|
||||
];
|
||||
|
||||
if (!in_array($subscriptionStatus, $validStatus)) {
|
||||
$request->redirect(null, 'index');
|
||||
}
|
||||
|
||||
if ($institutional) {
|
||||
$subscriptionForm = new UserInstitutionalSubscriptionForm($request, $user->getId(), $subscriptionId);
|
||||
} else {
|
||||
$subscriptionForm = new UserIndividualSubscriptionForm($request, $user->getId(), $subscriptionId);
|
||||
}
|
||||
} else {
|
||||
if ($institutional) {
|
||||
$subscriptionForm = new UserInstitutionalSubscriptionForm($request, $user->getId());
|
||||
} else {
|
||||
// Ensure user does not already have an individual subscription
|
||||
if ($subscriptionDao->subscriptionExistsByUserForJournal($user->getId(), $journal->getId())) {
|
||||
$request->redirect(null, 'index');
|
||||
}
|
||||
$subscriptionForm = new UserIndividualSubscriptionForm($request, $user->getId());
|
||||
}
|
||||
}
|
||||
|
||||
$subscriptionForm->initData();
|
||||
$subscriptionForm->display();
|
||||
}
|
||||
|
||||
/**
|
||||
* Pay for a subscription purchase.
|
||||
*
|
||||
* @param array $args
|
||||
* @param \APP\core\Request $request
|
||||
*/
|
||||
public function payPurchaseSubscription($args, $request)
|
||||
{
|
||||
$this->validate(null, $request);
|
||||
|
||||
if (empty($args)) {
|
||||
$request->redirect(null, 'index');
|
||||
}
|
||||
|
||||
$journal = $request->getContext();
|
||||
if (!$journal) {
|
||||
$request->redirect(null, 'index');
|
||||
}
|
||||
if ($journal->getData('publishingMode') != Journal::PUBLISHING_MODE_SUBSCRIPTION) {
|
||||
$request->redirect(null, 'index');
|
||||
}
|
||||
|
||||
$paymentManager = Application::getPaymentManager($journal);
|
||||
$acceptSubscriptionPayments = $paymentManager->isConfigured();
|
||||
if (!$acceptSubscriptionPayments) {
|
||||
$request->redirect(null, 'index');
|
||||
}
|
||||
|
||||
$this->setupTemplate($request);
|
||||
$user = $request->getUser();
|
||||
|
||||
$institutional = array_shift($args);
|
||||
if (!empty($args)) {
|
||||
$subscriptionId = (int) array_shift($args);
|
||||
}
|
||||
|
||||
if ($institutional == 'institutional') {
|
||||
$institutional = true;
|
||||
$subscriptionDao = DAORegistry::getDAO('InstitutionalSubscriptionDAO'); /** @var InstitutionalSubscriptionDAO $subscriptionDao */
|
||||
} else {
|
||||
$institutional = false;
|
||||
$subscriptionDao = DAORegistry::getDAO('IndividualSubscriptionDAO'); /** @var IndividualSubscriptionDAO $subscriptionDao */
|
||||
}
|
||||
|
||||
if (isset($subscriptionId)) {
|
||||
// Ensure subscription to be updated is for this user
|
||||
if (!$subscriptionDao->subscriptionExistsByUser($subscriptionId, $user->getId())) {
|
||||
$request->redirect(null, 'index');
|
||||
}
|
||||
|
||||
// Ensure subscription can be updated
|
||||
$subscription = $subscriptionDao->getById($subscriptionId);
|
||||
$subscriptionStatus = $subscription->getStatus();
|
||||
$validStatus = [
|
||||
Subscription::SUBSCRIPTION_STATUS_ACTIVE,
|
||||
Subscription::SUBSCRIPTION_STATUS_AWAITING_ONLINE_PAYMENT,
|
||||
Subscription::SUBSCRIPTION_STATUS_AWAITING_MANUAL_PAYMENT
|
||||
];
|
||||
|
||||
if (!in_array($subscriptionStatus, $validStatus)) {
|
||||
$request->redirect(null, 'index');
|
||||
}
|
||||
|
||||
if ($institutional) {
|
||||
$subscriptionForm = new UserInstitutionalSubscriptionForm($request, $user->getId(), $subscriptionId);
|
||||
} else {
|
||||
$subscriptionForm = new UserIndividualSubscriptionForm($request, $user->getId(), $subscriptionId);
|
||||
}
|
||||
} else {
|
||||
if ($institutional) {
|
||||
$subscriptionForm = new UserInstitutionalSubscriptionForm($request, $user->getId());
|
||||
} else {
|
||||
// Ensure user does not already have an individual subscription
|
||||
if ($subscriptionDao->subscriptionExistsByUserForJournal($user->getId(), $journal->getId())) {
|
||||
$request->redirect(null, 'index');
|
||||
}
|
||||
$subscriptionForm = new UserIndividualSubscriptionForm($request, $user->getId());
|
||||
}
|
||||
}
|
||||
|
||||
$subscriptionForm->readInputData();
|
||||
|
||||
// Check for any special cases before trying to save
|
||||
if ($request->getUserVar('addIpRange')) {
|
||||
$editData = true;
|
||||
$ipRanges = $subscriptionForm->getData('ipRanges');
|
||||
$ipRanges[] = '';
|
||||
$subscriptionForm->setData('ipRanges', $ipRanges);
|
||||
} elseif (($delIpRange = $request->getUserVar('delIpRange')) && count($delIpRange) == 1) {
|
||||
$editData = true;
|
||||
[$delIpRange] = array_keys($delIpRange);
|
||||
$delIpRange = (int) $delIpRange;
|
||||
$ipRanges = $subscriptionForm->getData('ipRanges');
|
||||
array_splice($ipRanges, $delIpRange, 1);
|
||||
$subscriptionForm->setData('ipRanges', $ipRanges);
|
||||
}
|
||||
|
||||
if (isset($editData)) {
|
||||
$subscriptionForm->display();
|
||||
} else {
|
||||
if ($subscriptionForm->validate()) {
|
||||
$subscriptionForm->execute();
|
||||
} else {
|
||||
$subscriptionForm->display();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Complete the purchase subscription process.
|
||||
*
|
||||
* @param array $args
|
||||
* @param \APP\core\Request $request
|
||||
*/
|
||||
public function completePurchaseSubscription($args, $request)
|
||||
{
|
||||
$this->validate(null, $request);
|
||||
$journal = $request->getContext();
|
||||
if (!$journal || count($args) != 2 || $journal->getData('publishingMode') != Journal::PUBLISHING_MODE_SUBSCRIPTION) {
|
||||
$request->redirect(null, 'index');
|
||||
}
|
||||
|
||||
$paymentManager = Application::getPaymentManager($journal);
|
||||
$acceptSubscriptionPayments = $paymentManager->isConfigured();
|
||||
if (!$acceptSubscriptionPayments) {
|
||||
$request->redirect(null, 'index');
|
||||
}
|
||||
|
||||
$this->setupTemplate($request);
|
||||
$user = $request->getUser();
|
||||
$institutional = array_shift($args);
|
||||
$subscriptionId = (int) array_shift($args);
|
||||
|
||||
if ($institutional == 'institutional') {
|
||||
$subscriptionDao = DAORegistry::getDAO('InstitutionalSubscriptionDAO'); /** @var InstitutionalSubscriptionDAO $subscriptionDao */
|
||||
} else {
|
||||
$subscriptionDao = DAORegistry::getDAO('IndividualSubscriptionDAO'); /** @var IndividualSubscriptionDAO $subscriptionDao */
|
||||
}
|
||||
|
||||
if (!$subscriptionDao->subscriptionExistsByUser($subscriptionId, $user->getId())) {
|
||||
$request->redirect(null, 'index');
|
||||
}
|
||||
|
||||
$subscription = $subscriptionDao->getById($subscriptionId);
|
||||
$subscriptionStatus = $subscription->getStatus();
|
||||
$validStatus = [Subscription::SUBSCRIPTION_STATUS_ACTIVE, Subscription::SUBSCRIPTION_STATUS_AWAITING_ONLINE_PAYMENT];
|
||||
|
||||
if (!in_array($subscriptionStatus, $validStatus)) {
|
||||
$request->redirect(null, 'index');
|
||||
}
|
||||
|
||||
$subscriptionTypeDao = DAORegistry::getDAO('SubscriptionTypeDAO'); /** @var SubscriptionTypeDAO $subscriptionTypeDao */
|
||||
$subscriptionType = $subscriptionTypeDao->getById($subscription->getTypeId());
|
||||
|
||||
$queuedPayment = $paymentManager->createQueuedPayment($request, OJSPaymentManager::PAYMENT_TYPE_PURCHASE_SUBSCRIPTION, $user->getId(), $subscriptionId, $subscriptionType->getCost(), $subscriptionType->getCurrencyCodeAlpha());
|
||||
$paymentManager->queuePayment($queuedPayment);
|
||||
|
||||
$paymentForm = $paymentManager->getPaymentForm($queuedPayment);
|
||||
$paymentForm->display($request);
|
||||
}
|
||||
|
||||
/**
|
||||
* Pay the "renew subscription" fee.
|
||||
*
|
||||
* @param array $args
|
||||
* @param \APP\core\Request $request
|
||||
*/
|
||||
public function payRenewSubscription($args, $request)
|
||||
{
|
||||
$this->validate(null, $request);
|
||||
$journal = $request->getContext();
|
||||
if (count($args) != 2 || !$journal || $journal->getData('publishingMode') != Journal::PUBLISHING_MODE_SUBSCRIPTION) {
|
||||
$request->redirect(null, 'index');
|
||||
}
|
||||
|
||||
$paymentManager = Application::getPaymentManager($journal);
|
||||
$acceptSubscriptionPayments = $paymentManager->isConfigured();
|
||||
if (!$acceptSubscriptionPayments) {
|
||||
$request->redirect(null, 'index');
|
||||
}
|
||||
|
||||
$this->setupTemplate($request);
|
||||
$user = $request->getUser();
|
||||
$institutional = array_shift($args);
|
||||
$subscriptionId = (int) array_shift($args);
|
||||
|
||||
if ($institutional == 'institutional') {
|
||||
$subscriptionDao = DAORegistry::getDAO('InstitutionalSubscriptionDAO'); /** @var InstitutionalSubscriptionDAO $subscriptionDao */
|
||||
} else {
|
||||
$subscriptionDao = DAORegistry::getDAO('IndividualSubscriptionDAO'); /** @var IndividualSubscriptionDAO $subscriptionDao */
|
||||
}
|
||||
|
||||
if (!$subscriptionDao->subscriptionExistsByUser($subscriptionId, $user->getId())) {
|
||||
$request->redirect(null, 'index');
|
||||
}
|
||||
|
||||
$subscription = $subscriptionDao->getById($subscriptionId);
|
||||
|
||||
if ($subscription->isNonExpiring()) {
|
||||
$request->redirect(null, 'index');
|
||||
}
|
||||
|
||||
$subscriptionStatus = $subscription->getStatus();
|
||||
$validStatus = [
|
||||
Subscription::SUBSCRIPTION_STATUS_ACTIVE,
|
||||
Subscription::SUBSCRIPTION_STATUS_AWAITING_ONLINE_PAYMENT,
|
||||
Subscription::SUBSCRIPTION_STATUS_AWAITING_MANUAL_PAYMENT
|
||||
];
|
||||
|
||||
if (!in_array($subscriptionStatus, $validStatus)) {
|
||||
$request->redirect(null, 'index');
|
||||
}
|
||||
|
||||
$subscriptionTypeDao = DAORegistry::getDAO('SubscriptionTypeDAO'); /** @var SubscriptionTypeDAO $subscriptionTypeDao */
|
||||
$subscriptionType = $subscriptionTypeDao->getById($subscription->getTypeId());
|
||||
|
||||
$queuedPayment = $paymentManager->createQueuedPayment($request, OJSPaymentManager::PAYMENT_TYPE_RENEW_SUBSCRIPTION, $user->getId(), $subscriptionId, $subscriptionType->getCost(), $subscriptionType->getCurrencyCodeAlpha());
|
||||
$paymentManager->queuePayment($queuedPayment);
|
||||
|
||||
$paymentForm = $paymentManager->getPaymentForm($queuedPayment);
|
||||
$paymentForm->display($request);
|
||||
}
|
||||
|
||||
/**
|
||||
* Pay for a membership.
|
||||
*
|
||||
* @param array $args
|
||||
* @param \APP\core\Request $request
|
||||
*/
|
||||
public function payMembership($args, $request)
|
||||
{
|
||||
$this->validate(null, $request);
|
||||
$this->setupTemplate($request);
|
||||
$journal = $request->getContext();
|
||||
$user = $request->getUser();
|
||||
|
||||
$paymentManager = Application::getPaymentManager($journal);
|
||||
|
||||
$queuedPayment = $paymentManager->createQueuedPayment($request, OJSPaymentManager::PAYMENT_TYPE_MEMBERSHIP, $user->getId(), null, $journal->getData('membershipFee'));
|
||||
$paymentManager->queuePayment($queuedPayment);
|
||||
|
||||
$paymentForm = $paymentManager->getPaymentForm($queuedPayment);
|
||||
$paymentForm->display($request);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @defgroup pages_user User Pages
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file pages/user/index.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.
|
||||
*
|
||||
* @ingroup pages_user
|
||||
*
|
||||
* @brief Handle requests for user functions.
|
||||
*
|
||||
*/
|
||||
|
||||
switch ($op) {
|
||||
//
|
||||
// Misc.
|
||||
//
|
||||
case 'index':
|
||||
case 'subscriptions':
|
||||
case 'setLocale':
|
||||
case 'authorizationDenied':
|
||||
case 'purchaseSubscription':
|
||||
case 'payPurchaseSubscription':
|
||||
case 'completePurchaseSubscription':
|
||||
case 'payRenewSubscription':
|
||||
case 'payMembership':
|
||||
case 'getInterests':
|
||||
define('HANDLER_CLASS', 'APP\pages\user\UserHandler');
|
||||
break;
|
||||
default:
|
||||
require_once('lib/pkp/pages/user/index.php');
|
||||
}
|
||||
@@ -0,0 +1,317 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @file pages/workflow/WorkflowHandler.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 WorkflowHandler
|
||||
*
|
||||
* @ingroup pages_reviewer
|
||||
*
|
||||
* @brief Handle requests for the submission workflow.
|
||||
*/
|
||||
|
||||
namespace APP\pages\workflow;
|
||||
|
||||
use APP\core\Application;
|
||||
use APP\core\Services;
|
||||
use APP\decision\types\Accept;
|
||||
use APP\decision\types\SkipExternalReview;
|
||||
use APP\facades\Repo;
|
||||
use APP\file\PublicFileManager;
|
||||
use APP\publication\Publication;
|
||||
use APP\submission\Submission;
|
||||
use APP\template\TemplateManager;
|
||||
use PKP\components\forms\publication\TitleAbstractForm;
|
||||
use PKP\context\Context;
|
||||
use PKP\decision\types\BackFromCopyediting;
|
||||
use PKP\decision\types\BackFromProduction;
|
||||
use PKP\decision\types\CancelReviewRound;
|
||||
use PKP\decision\types\Decline;
|
||||
use PKP\decision\types\InitialDecline;
|
||||
use PKP\decision\types\RecommendAccept;
|
||||
use PKP\decision\types\RecommendDecline;
|
||||
use PKP\decision\types\RecommendRevisions;
|
||||
use PKP\decision\types\RequestRevisions;
|
||||
use PKP\decision\types\RevertDecline;
|
||||
use PKP\decision\types\RevertInitialDecline;
|
||||
use PKP\decision\types\SendExternalReview;
|
||||
use PKP\decision\types\SendToProduction;
|
||||
use PKP\notification\PKPNotification;
|
||||
use PKP\pages\workflow\PKPWorkflowHandler;
|
||||
use PKP\plugins\Hook;
|
||||
use PKP\security\Role;
|
||||
|
||||
class WorkflowHandler extends PKPWorkflowHandler
|
||||
{
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct();
|
||||
|
||||
$this->addRoleAssignment(
|
||||
[Role::ROLE_ID_SUB_EDITOR, Role::ROLE_ID_MANAGER, Role::ROLE_ID_SITE_ADMIN, Role::ROLE_ID_ASSISTANT],
|
||||
[
|
||||
'access', 'index', 'submission',
|
||||
'editorDecisionActions', // Submission & review
|
||||
'externalReview', // review
|
||||
'editorial',
|
||||
'production',
|
||||
'submissionHeader',
|
||||
'submissionProgressBar',
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Setup variables for the template
|
||||
*
|
||||
* @param \APP\core\Request $request
|
||||
*/
|
||||
public function setupIndex($request)
|
||||
{
|
||||
parent::setupIndex($request);
|
||||
|
||||
$templateMgr = TemplateManager::getManager($request);
|
||||
$submission = $this->getAuthorizedContextObject(Application::ASSOC_TYPE_SUBMISSION);
|
||||
|
||||
$submissionContext = $request->getContext();
|
||||
if ($submission->getContextId() !== $submissionContext->getId()) {
|
||||
$submissionContext = Services::get('context')->get($submission->getContextId());
|
||||
}
|
||||
|
||||
$locales = $submissionContext->getSupportedSubmissionLocaleNames();
|
||||
$locales = array_map(fn (string $locale, string $name) => ['key' => $locale, 'label' => $name], array_keys($locales), $locales);
|
||||
|
||||
$latestPublication = $submission->getLatestPublication();
|
||||
|
||||
$latestPublicationApiUrl = $request->getDispatcher()->url($request, Application::ROUTE_API, $submissionContext->getPath(), 'submissions/' . $submission->getId() . '/publications/' . $latestPublication->getId());
|
||||
$temporaryFileApiUrl = $request->getDispatcher()->url($request, Application::ROUTE_API, $submissionContext->getPath(), 'temporaryFiles');
|
||||
$issueApiUrl = $request->getDispatcher()->url($request, Application::ROUTE_API, $submissionContext->getData('urlPath'), 'issues/__issueId__');
|
||||
|
||||
$publicFileManager = new PublicFileManager();
|
||||
$baseUrl = $request->getBaseUrl() . '/' . $publicFileManager->getContextFilesPath($submissionContext->getId());
|
||||
|
||||
$issueEntryForm = new \APP\components\forms\publication\IssueEntryForm($latestPublicationApiUrl, $locales, $latestPublication, $submissionContext, $baseUrl, $temporaryFileApiUrl);
|
||||
|
||||
$sectionWordLimits = [];
|
||||
$sections = Repo::section()->getCollector()->filterByContextIds([$submissionContext->getId()])->getMany();
|
||||
foreach ($sections as $section) {
|
||||
$sectionWordLimits[$section->getId()] = (int) $section->getAbstractWordCount() ?? 0;
|
||||
}
|
||||
|
||||
class_exists(\APP\components\forms\publication\AssignToIssueForm::class); // Force define of FORM_ASSIGN_TO_ISSUE
|
||||
$templateMgr->setConstants([
|
||||
'FORM_ASSIGN_TO_ISSUE' => FORM_ASSIGN_TO_ISSUE,
|
||||
'FORM_ISSUE_ENTRY' => FORM_ISSUE_ENTRY,
|
||||
'FORM_PUBLISH' => FORM_PUBLISH,
|
||||
]);
|
||||
|
||||
$components = $templateMgr->getState('components');
|
||||
$components[FORM_ISSUE_ENTRY] = $issueEntryForm->getConfig();
|
||||
|
||||
// Add payments form if enabled
|
||||
$paymentManager = Application::getPaymentManager($submissionContext);
|
||||
$templateMgr->assign([
|
||||
'submissionPaymentsEnabled' => $paymentManager->publicationEnabled(),
|
||||
]);
|
||||
if ($paymentManager->publicationEnabled()) {
|
||||
$submissionPaymentsForm = new \APP\components\forms\publication\SubmissionPaymentsForm(
|
||||
$request->getDispatcher()->url($request, Application::ROUTE_API, $submissionContext->getPath(), '_submissions/' . $submission->getId() . '/payment'),
|
||||
$submission,
|
||||
$request->getContext()
|
||||
);
|
||||
$components[FORM_SUBMISSION_PAYMENTS] = $submissionPaymentsForm->getConfig();
|
||||
$templateMgr->setConstants([
|
||||
'FORM_SUBMISSION_PAYMENTS' => FORM_SUBMISSION_PAYMENTS,
|
||||
]);
|
||||
}
|
||||
|
||||
// Add the word limit to the existing title/abstract form
|
||||
if (!empty($components[FORM_TITLE_ABSTRACT]) &&
|
||||
array_key_exists($submission->getLatestPublication()->getData('sectionId'), $sectionWordLimits)) {
|
||||
$limit = (int) $sectionWordLimits[$submission->getLatestPublication()->getData('sectionId')];
|
||||
foreach ($components[FORM_TITLE_ABSTRACT]['fields'] as $key => $field) {
|
||||
if ($field['name'] === 'abstract') {
|
||||
$components[FORM_TITLE_ABSTRACT]['fields'][$key]['wordLimit'] = $limit;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$assignToIssueUrl = $request->getDispatcher()->url(
|
||||
$request,
|
||||
Application::ROUTE_COMPONENT,
|
||||
null,
|
||||
'modals.publish.AssignToIssueHandler',
|
||||
'assign',
|
||||
null,
|
||||
[
|
||||
'submissionId' => $submission->getId(),
|
||||
'publicationId' => '__publicationId__',
|
||||
]
|
||||
);
|
||||
|
||||
$publicationFormIds = $templateMgr->getState('publicationFormIds');
|
||||
$publicationFormIds[] = FORM_ISSUE_ENTRY;
|
||||
|
||||
$templateMgr->setState([
|
||||
'assignToIssueUrl' => $assignToIssueUrl,
|
||||
'components' => $components,
|
||||
'publicationFormIds' => $publicationFormIds,
|
||||
'issueApiUrl' => $issueApiUrl,
|
||||
'sectionWordLimits' => $sectionWordLimits,
|
||||
'selectIssueLabel' => __('publication.selectIssue'),
|
||||
]);
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// Protected helper methods
|
||||
//
|
||||
/**
|
||||
* Return the editor assignment notification type based on stage id.
|
||||
*
|
||||
* @param int $stageId
|
||||
*
|
||||
* @return ?int
|
||||
*/
|
||||
protected function getEditorAssignmentNotificationTypeByStageId($stageId)
|
||||
{
|
||||
switch ($stageId) {
|
||||
case WORKFLOW_STAGE_ID_SUBMISSION:
|
||||
return PKPNotification::NOTIFICATION_TYPE_EDITOR_ASSIGNMENT_SUBMISSION;
|
||||
case WORKFLOW_STAGE_ID_EXTERNAL_REVIEW:
|
||||
return PKPNotification::NOTIFICATION_TYPE_EDITOR_ASSIGNMENT_EXTERNAL_REVIEW;
|
||||
case WORKFLOW_STAGE_ID_EDITING:
|
||||
return PKPNotification::NOTIFICATION_TYPE_EDITOR_ASSIGNMENT_EDITING;
|
||||
case WORKFLOW_STAGE_ID_PRODUCTION:
|
||||
return PKPNotification::NOTIFICATION_TYPE_EDITOR_ASSIGNMENT_PRODUCTION;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
protected function _getRepresentationsGridUrl($request, $submission)
|
||||
{
|
||||
return $request->getDispatcher()->url(
|
||||
$request,
|
||||
Application::ROUTE_COMPONENT,
|
||||
null,
|
||||
'grid.articleGalleys.ArticleGalleyGridHandler',
|
||||
'fetchGrid',
|
||||
null,
|
||||
[
|
||||
'submissionId' => $submission->getId(),
|
||||
'publicationId' => '__publicationId__',
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
protected function getStageDecisionTypes(int $stageId): array
|
||||
{
|
||||
$submission = $this->getAuthorizedContextObject(Application::ASSOC_TYPE_SUBMISSION);
|
||||
$request = Application::get()->getRequest();
|
||||
$reviewRoundId = (int) $request->getUserVar('reviewRoundId');
|
||||
|
||||
switch ($stageId) {
|
||||
case WORKFLOW_STAGE_ID_SUBMISSION:
|
||||
$decisionTypes = [
|
||||
new SendExternalReview(),
|
||||
new SkipExternalReview(),
|
||||
];
|
||||
if ($submission->getData('status') === Submission::STATUS_DECLINED) {
|
||||
$decisionTypes[] = new RevertInitialDecline();
|
||||
} elseif ($submission->getData('status') === Submission::STATUS_QUEUED) {
|
||||
$decisionTypes[] = new InitialDecline();
|
||||
}
|
||||
break;
|
||||
case WORKFLOW_STAGE_ID_EXTERNAL_REVIEW:
|
||||
$decisionTypes = [
|
||||
new RequestRevisions(),
|
||||
new Accept(),
|
||||
];
|
||||
$cancelReviewRound = new CancelReviewRound();
|
||||
if ($cancelReviewRound->canRetract($submission, $reviewRoundId)) {
|
||||
$decisionTypes[] = $cancelReviewRound;
|
||||
}
|
||||
if ($submission->getData('status') === Submission::STATUS_DECLINED) {
|
||||
$decisionTypes[] = new RevertDecline();
|
||||
} elseif ($submission->getData('status') === Submission::STATUS_QUEUED) {
|
||||
$decisionTypes[] = new Decline();
|
||||
}
|
||||
break;
|
||||
case WORKFLOW_STAGE_ID_EDITING:
|
||||
$decisionTypes = [
|
||||
new SendToProduction(),
|
||||
new BackFromCopyediting(),
|
||||
];
|
||||
break;
|
||||
case WORKFLOW_STAGE_ID_PRODUCTION:
|
||||
$decisionTypes = [
|
||||
new BackFromProduction(),
|
||||
];
|
||||
break;
|
||||
}
|
||||
|
||||
Hook::call('Workflow::Decisions', [&$decisionTypes, $stageId]);
|
||||
|
||||
return $decisionTypes;
|
||||
}
|
||||
|
||||
protected function getStageRecommendationTypes(int $stageId): array
|
||||
{
|
||||
switch ($stageId) {
|
||||
case WORKFLOW_STAGE_ID_EXTERNAL_REVIEW:
|
||||
$decisionTypes = [
|
||||
new RecommendRevisions(),
|
||||
new RecommendAccept(),
|
||||
new RecommendDecline(),
|
||||
];
|
||||
break;
|
||||
default:
|
||||
$decisionTypes = [];
|
||||
}
|
||||
|
||||
|
||||
Hook::call('Workflow::Recommendations', [$decisionTypes, $stageId]);
|
||||
|
||||
return $decisionTypes;
|
||||
}
|
||||
|
||||
protected function getPrimaryDecisionTypes(): array
|
||||
{
|
||||
return [
|
||||
SendExternalReview::class,
|
||||
Accept::class,
|
||||
SendToProduction::class,
|
||||
];
|
||||
}
|
||||
|
||||
protected function getWarnableDecisionTypes(): array
|
||||
{
|
||||
return [
|
||||
InitialDecline::class,
|
||||
Decline::class,
|
||||
CancelReviewRound::class,
|
||||
BackFromCopyediting::class,
|
||||
BackFromProduction::class,
|
||||
];
|
||||
}
|
||||
|
||||
protected function getTitleAbstractForm(string $latestPublicationApiUrl, array $locales, Publication $latestPublication, Context $context): TitleAbstractForm
|
||||
{
|
||||
$section = Repo::section()->get($latestPublication->getData('sectionId'), $context->getId());
|
||||
return new TitleAbstractForm(
|
||||
$latestPublicationApiUrl,
|
||||
$locales,
|
||||
$latestPublication,
|
||||
(int) $section->getData('wordCount'),
|
||||
!$section->getData('abstractsNotRequired')
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @defgroup pages_workflow Workflow Pages
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file pages/workflow/index.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.
|
||||
*
|
||||
* @ingroup pages_workflow
|
||||
*
|
||||
* @brief Handle requests for workflow functions.
|
||||
*
|
||||
*/
|
||||
|
||||
switch ($op) {
|
||||
case 'access':
|
||||
case 'index':
|
||||
case 'submission':
|
||||
case 'externalReview':
|
||||
case 'editorial':
|
||||
case 'production':
|
||||
case 'editorDecisionActions':
|
||||
case 'submissionProgressBar':
|
||||
define('HANDLER_CLASS', 'APP\pages\workflow\WorkflowHandler');
|
||||
break;
|
||||
}
|
||||
Reference in New Issue
Block a user