first commit

This commit is contained in:
CHIEFSOFT\ameye
2024-06-08 17:09:23 -04:00
commit df3a033196
17887 changed files with 8637778 additions and 0 deletions
+58
View File
@@ -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');
}
}
+26
View File
@@ -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');
}
+610
View File
@@ -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;
}
}
+27
View File
@@ -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')
);
}
}
+29
View File
@@ -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');
}
+26
View File
@@ -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;
}
+20
View File
@@ -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');
+91
View File
@@ -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),
]
);
}
}
+23
View File
@@ -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;
}
+246
View File
@@ -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();
}
}
+27
View File
@@ -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;
}
+105
View File
@@ -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');
}
}
}
+24
View File
@@ -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;
}
+121
View File
@@ -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);
}
}
}
+29
View File
@@ -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;
}
+430
View File
@@ -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);
}
}
}
+27
View File
@@ -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');
}
}
+28
View File
@@ -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;
}
+175
View File
@@ -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;
}
}
+36
View File
@@ -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;
}
+57
View File
@@ -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;
}
+87
View File
@@ -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;
}
}
+24
View File
@@ -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;
}
+79
View File
@@ -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);
}
}
+25
View File
@@ -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;
}
+241
View File
@@ -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'
)
);
}
}
+34
View File
@@ -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;
}
+154
View File
@@ -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);
}
}
+32
View File
@@ -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;
}
+244
View File
@@ -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,
]);
}
}
+26
View File
@@ -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;
}
+82
View File
@@ -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;
}
}
+24
View File
@@ -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;
}
+194
View File
@@ -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
]);
}
}
+20
View File
@@ -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');
+171
View File
@@ -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',
];
}
}
+22
View File
@@ -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;
}
+440
View File
@@ -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);
}
}
+38
View File
@@ -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');
}
+317
View File
@@ -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')
);
}
}
+31
View File
@@ -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;
}