347 lines
12 KiB
PHP
347 lines
12 KiB
PHP
<?php
|
|
|
|
/**
|
|
* @file plugins/generic/htmlArticleGalley/HtmlArticleGalleyPlugin.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 HtmlArticleGalleyPlugin
|
|
*
|
|
* @brief Class for HtmlArticleGalley plugin
|
|
*/
|
|
|
|
namespace APP\plugins\generic\htmlArticleGalley;
|
|
|
|
use APP\core\Application;
|
|
use APP\core\Services;
|
|
use APP\facades\Repo;
|
|
use APP\file\PublicFileManager;
|
|
use APP\observers\events\UsageEvent;
|
|
use APP\publication\Publication;
|
|
use APP\template\TemplateManager;
|
|
use PKP\plugins\Hook;
|
|
use PKP\submissionFile\SubmissionFile;
|
|
|
|
class HtmlArticleGalleyPlugin extends \PKP\plugins\GenericPlugin
|
|
{
|
|
/**
|
|
* @see Plugin::register()
|
|
*
|
|
* @param null|mixed $mainContextId
|
|
*/
|
|
public function register($category, $path, $mainContextId = null)
|
|
{
|
|
if (!parent::register($category, $path, $mainContextId)) {
|
|
return false;
|
|
}
|
|
if ($this->getEnabled($mainContextId)) {
|
|
Hook::add('ArticleHandler::view::galley', [$this, 'articleViewCallback'], Hook::SEQUENCE_LATE);
|
|
Hook::add('ArticleHandler::download', [$this, 'articleDownloadCallback'], Hook::SEQUENCE_LATE);
|
|
}
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* Install default settings on journal creation.
|
|
*
|
|
* @return string
|
|
*/
|
|
public function getContextSpecificPluginSettingsFile()
|
|
{
|
|
return $this->getPluginPath() . '/settings.xml';
|
|
}
|
|
|
|
/**
|
|
* Get the display name of this plugin.
|
|
*
|
|
* @return string
|
|
*/
|
|
public function getDisplayName()
|
|
{
|
|
return __('plugins.generic.htmlArticleGalley.displayName');
|
|
}
|
|
|
|
/**
|
|
* Get a description of the plugin.
|
|
*/
|
|
public function getDescription()
|
|
{
|
|
return __('plugins.generic.htmlArticleGalley.description');
|
|
}
|
|
|
|
/**
|
|
* Present the article wrapper page.
|
|
*
|
|
* @param string $hookName
|
|
* @param array $args
|
|
*/
|
|
public function articleViewCallback($hookName, $args)
|
|
{
|
|
$request = & $args[0];
|
|
$issue = & $args[1];
|
|
$galley = & $args[2];
|
|
$article = & $args[3];
|
|
|
|
if (!$galley) {
|
|
return false;
|
|
}
|
|
|
|
$submissionFile = $galley->getFile();
|
|
/** @var ?Publication */
|
|
$galleyPublication = null;
|
|
if ($submissionFile->getData('mimetype') === 'text/html') {
|
|
/** @var ?Publication */
|
|
$galleyPublication = null;
|
|
foreach ($article->getData('publications') as $publication) {
|
|
if ($publication->getId() === $galley->getData('publicationId')) {
|
|
$galleyPublication = $publication;
|
|
break;
|
|
}
|
|
}
|
|
$templateMgr = TemplateManager::getManager($request);
|
|
$templateMgr->assign([
|
|
'issue' => $issue,
|
|
'article' => $article,
|
|
'galley' => $galley,
|
|
'isLatestPublication' => $article->getData('currentPublicationId') === $galley->getData('publicationId'),
|
|
'galleyPublication' => $galleyPublication,
|
|
'submissionFile' => $submissionFile,
|
|
]);
|
|
$templateMgr->display($this->getTemplateResource('display.tpl'));
|
|
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
/**
|
|
* Present rewritten article HTML.
|
|
*
|
|
* @param string $hookName
|
|
* @param array $args
|
|
*/
|
|
public function articleDownloadCallback($hookName, $args)
|
|
{
|
|
$article = & $args[0];
|
|
$galley = & $args[1];
|
|
$fileId = & $args[2];
|
|
$request = Application::get()->getRequest();
|
|
|
|
if (!$galley) {
|
|
return false;
|
|
}
|
|
|
|
$submissionFile = $galley->getFile();
|
|
if ($galley->getData('submissionFileId') == $fileId && $submissionFile->getData('mimetype') === 'text/html' && $galley->getData('submissionFileId') == $submissionFile->getId()) {
|
|
if (!Hook::call('HtmlArticleGalleyPlugin::articleDownload', [$article, &$galley, &$fileId])) {
|
|
echo $this->_getHTMLContents($request, $galley);
|
|
$returner = true;
|
|
Hook::call('HtmlArticleGalleyPlugin::articleDownloadFinished', [&$returner]);
|
|
$publication = Repo::publication()->get($galley->getData('publicationId'));
|
|
// This part is the same as in ArticleHandler::initialize():
|
|
if ($publication->getData('issueId')) {
|
|
// TODO: Previously fetched issue from cache. Reimplement when caching added.
|
|
$issue = Repo::issue()->get($publication->getData('issueId'));
|
|
$issue = $issue->getJournalId() == $article->getData('contextId') ? $issue : null;
|
|
}
|
|
event(new UsageEvent(Application::ASSOC_TYPE_SUBMISSION_FILE, $request->getContext(), $article, $galley, $submissionFile, $issue));
|
|
}
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
/**
|
|
* Return string containing the contents of the HTML file.
|
|
* This function performs any necessary filtering, like image URL replacement.
|
|
*
|
|
* @param \APP\core\Request $request
|
|
* @param \PKP\galley\Galley $galley
|
|
*
|
|
* @return string
|
|
*/
|
|
protected function _getHTMLContents($request, $galley)
|
|
{
|
|
$submissionFile = $galley->getFile();
|
|
$submissionId = $submissionFile->getData('submissionId');
|
|
$contents = Services::get('file')->fs->read($submissionFile->getData('path'));
|
|
|
|
// Replace media file references
|
|
$embeddableFiles = Repo::submissionFile()
|
|
->getCollector()
|
|
->filterByAssoc(
|
|
Application::ASSOC_TYPE_SUBMISSION_FILE,
|
|
[$submissionFile->getId()]
|
|
)
|
|
->filterByFileStages([SubmissionFile::SUBMISSION_FILE_DEPENDENT])
|
|
->includeDependentFiles()
|
|
->getMany();
|
|
|
|
$referredArticle = null;
|
|
foreach ($embeddableFiles as $embeddableFile) {
|
|
$params = [];
|
|
|
|
if ($embeddableFile->getData('mimetype') == 'text/plain' || $embeddableFile->getData('mimetype') == 'text/css') {
|
|
$params['inline'] = 'true';
|
|
}
|
|
|
|
// Ensure that the $referredArticle object refers to the article we want
|
|
if (!$referredArticle || $referredArticle->getId() != $submissionId) {
|
|
$referredArticle = Repo::submission()->get($submissionId);
|
|
}
|
|
$fileUrl = $request->url(null, 'article', 'download', [$referredArticle->getBestId(), 'version', $galley->getData('publicationId'), $galley->getBestGalleyId(), $embeddableFile->getId(), $embeddableFile->getLocalizedData('name')], $params);
|
|
$pattern = preg_quote(rawurlencode($embeddableFile->getLocalizedData('name')), '/');
|
|
|
|
$contents = preg_replace(
|
|
'/([Ss][Rr][Cc]|[Hh][Rr][Ee][Ff]|[Dd][Aa][Tt][Aa])\s*=\s*"([^"]*' . $pattern . ')"/',
|
|
'\1="' . $fileUrl . '"',
|
|
$contents
|
|
);
|
|
if ($contents === null) {
|
|
error_log('PREG error in ' . __FILE__ . ' line ' . __LINE__ . ': ' . preg_last_error());
|
|
}
|
|
|
|
// Replacement for Flowplayer or other Javascript
|
|
$contents = preg_replace(
|
|
'/[Uu][Rr][Ll]\s*\:\s*\'(' . $pattern . ')\'/',
|
|
'url:\'' . $fileUrl . '\'',
|
|
$contents
|
|
);
|
|
if ($contents === null) {
|
|
error_log('PREG error in ' . __FILE__ . ' line ' . __LINE__ . ': ' . preg_last_error());
|
|
}
|
|
|
|
// Replacement for CSS url(...)
|
|
$contents = preg_replace(
|
|
'/[Uu][Rr][Ll]\(' . $pattern . '\)/',
|
|
'url(' . $fileUrl . ')',
|
|
$contents
|
|
);
|
|
if ($contents === null) {
|
|
error_log('PREG error in ' . __FILE__ . ' line ' . __LINE__ . ': ' . preg_last_error());
|
|
}
|
|
|
|
// Replacement for other players (tested with odeo; yahoo and google player won't work w/ OJS URLs, might work for others)
|
|
$contents = preg_replace(
|
|
'/[Uu][Rr][Ll]=([^"]*' . $pattern . ')/',
|
|
'url=' . $fileUrl,
|
|
$contents
|
|
);
|
|
if ($contents === null) {
|
|
error_log('PREG error in ' . __FILE__ . ' line ' . __LINE__ . ': ' . preg_last_error());
|
|
}
|
|
}
|
|
|
|
// Perform replacement for ojs://... URLs
|
|
$contents = preg_replace_callback(
|
|
'/(<[^<>]*")[Oo][Jj][Ss]:\/\/([^"]+)("[^<>]*>)/',
|
|
[$this, '_handleOjsUrl'],
|
|
$contents
|
|
);
|
|
if ($contents === null) {
|
|
error_log('PREG error in ' . __FILE__ . ' line ' . __LINE__ . ': ' . preg_last_error());
|
|
}
|
|
|
|
$templateMgr = TemplateManager::getManager($request);
|
|
$contents = $templateMgr->loadHtmlGalleyStyles($contents, $embeddableFiles->toArray());
|
|
|
|
// Perform variable replacement for journal, issue, site info
|
|
$issue = Repo::issue()->getBySubmissionId($submissionId);
|
|
|
|
$journal = $request->getContext();
|
|
$site = $request->getSite();
|
|
|
|
$paramArray = [
|
|
'issueTitle' => $issue ? $issue->getIssueIdentification() : __('editor.article.scheduleForPublication.toBeAssigned'),
|
|
'journalTitle' => $journal->getLocalizedName(),
|
|
'siteTitle' => $site->getLocalizedTitle(),
|
|
'currentUrl' => $request->getRequestUrl()
|
|
];
|
|
|
|
foreach ($paramArray as $key => $value) {
|
|
$contents = str_replace('{$' . $key . '}', $value, $contents);
|
|
}
|
|
|
|
return $contents;
|
|
}
|
|
|
|
public function _handleOjsUrl($matchArray)
|
|
{
|
|
$request = Application::get()->getRequest();
|
|
$url = $matchArray[2];
|
|
$anchor = null;
|
|
if (($i = strpos($url, '#')) !== false) {
|
|
$anchor = substr($url, $i + 1);
|
|
$url = substr($url, 0, $i);
|
|
}
|
|
$urlParts = explode('/', $url);
|
|
if (isset($urlParts[0])) {
|
|
switch (strtolower_codesafe($urlParts[0])) {
|
|
case 'journal':
|
|
$url = $request->url(
|
|
$urlParts[1] ?? $request->getRouter()->getRequestedContextPath($request),
|
|
null,
|
|
null,
|
|
null,
|
|
null,
|
|
$anchor
|
|
);
|
|
break;
|
|
case 'article':
|
|
if (isset($urlParts[1])) {
|
|
$url = $request->url(
|
|
null,
|
|
'article',
|
|
'view',
|
|
$urlParts[1],
|
|
null,
|
|
$anchor
|
|
);
|
|
}
|
|
break;
|
|
case 'issue':
|
|
if (isset($urlParts[1])) {
|
|
$url = $request->url(
|
|
null,
|
|
'issue',
|
|
'view',
|
|
$urlParts[1],
|
|
null,
|
|
$anchor
|
|
);
|
|
} else {
|
|
$url = $request->url(
|
|
null,
|
|
'issue',
|
|
'current',
|
|
null,
|
|
null,
|
|
$anchor
|
|
);
|
|
}
|
|
break;
|
|
case 'sitepublic':
|
|
array_shift($urlParts);
|
|
$publicFileManager = new PublicFileManager();
|
|
$url = $request->getBaseUrl() . '/' . $publicFileManager->getSiteFilesPath() . '/' . implode('/', $urlParts) . ($anchor ? '#' . $anchor : '');
|
|
break;
|
|
case 'public':
|
|
array_shift($urlParts);
|
|
$journal = $request->getJournal();
|
|
$publicFileManager = new PublicFileManager();
|
|
$url = $request->getBaseUrl() . '/' . $publicFileManager->getContextFilesPath($journal->getId()) . '/' . implode('/', $urlParts) . ($anchor ? '#' . $anchor : '');
|
|
break;
|
|
}
|
|
}
|
|
return $matchArray[1] . $url . $matchArray[3];
|
|
}
|
|
}
|
|
|
|
if (!PKP_STRICT_MODE) {
|
|
class_alias('\APP\plugins\generic\htmlArticleGalley\HtmlArticleGalleyPlugin', '\HtmlArticleGalleyPlugin');
|
|
}
|