Select Git revision
XML2HTMLPlugin.php
Jerome Chauveau authored
Code owners
Assign users and groups as approvers for specific file changes. Learn more.
XML2HTMLPlugin.php 10.76 KiB
<?php
/**
* Created by PhpStorm.
* User: dje
* Date: 04/10/22
* Time: 17:36
*/
import('lib.pkp.classes.plugins.GenericPlugin');
import('lib.pkp.classes.file.PrivateFileManager');
class XML2HTMLPlugin extends GenericPlugin
{
public function register($category, $path, $mainContextId = NULL)
{
// Register the plugin even when it is not enabled
$success = parent::register($category, $path);
if ($success && $this->getEnabled()) {
HookRegistry::register('ArticleHandler::view::galley', array($this, 'articleHandler'));
//HookRegistry::register('ArticleHandler::download', array($this, 'articleDownloadCallback'), HOOK_SEQUENCE_LATE);
HookRegistry::register('LoadHandler', array($this, 'loadImageHandler'));
HookRegistry::register('CatalogBookHandler::view', array($this, 'catalogHandler'));
}
return $success;
}
/**
* @throws Exception
*/
public function articleHandler($hookName, $params): bool
{
$galley =& $params[2];
$submission = &$params[3];
//handle only on zip galleys - supposed to be an xml archive (source + images)
$zipMode = $galley && $galley->getFileType() === 'application/zip';
if ($zipMode) {
$this->archiveView($galley->getFile()->getData('path'), $submission->getId(), $galley->getId(),'article');
return true;
} else return false;
}
public function catalogHandler($hookName, $params): bool
{
$submission = &$params[1];
$galley =& $params[2];
$submissionFile =& $params[3];
$zipMode = $submissionFile->getData('mimetype') === "application/zip";
if ($zipMode) {
$this->archiveView($submissionFile->getData('path'), $submission->getId(), $galley->getId(),'catalog');
return true;
} else
return false;
}
private function archiveView(string $filePath, int $submissionId, int $galleyId, string $op)
{
$htmlFile = XML2HTMLPlugin::getHTMLPathFromZipPath($filePath);
$html = file_get_contents($htmlFile);
//make transfo only if html does not exist
if(!$html) {
$xmlFilePath = XML2HTMLPlugin::unzipXMLArchive($filePath);
$html = $this->resolveZipImagePaths(
XML2HTMLPlugin::transform($xmlFilePath),
$submissionId,
$galleyId,
$xmlFilePath, $this->getRequest(),
$op);
//store transfo result
file_put_contents($htmlFile, $html, LOCK_EX);
}
$templateMgr = TemplateManager::getManager($this->getRequest());
$templateMgr->assign('assetsPath',$this->getPluginAssetsPath($this->getRequest()));
$templateMgr->assign('text', $html);
$templateMgr->display($this->getTemplateResource('HTMLGalleyView.tpl'));
}
/**
* get HTML file path from its zip one
* exemple : a/b/c/1234.zip -> ojs/files/dir/a/b/c/1234/1234.html
* @param $zipPath
* @return string
*/
private static function getHTMLPathFromZipPath($zipPath){
$fileMgr = new PrivateFileManager();
$filesDir = $fileMgr->getBasePath() . DIRECTORY_SEPARATOR;
$fullZipPath = $filesDir . $zipPath;
$fullPrefixPath = str_replace('.zip', '', $fullZipPath);
$pathInfo = pathinfo($fullZipPath);
$zipName = $pathInfo['filename'];
return str_replace($pathInfo['filename'], $zipName. DIRECTORY_SEPARATOR . $zipName . '.html', $fullPrefixPath);
}
/**
* Provide a name for this plugin
*
* The name will appear in the plugins list where editors can
* enable and disable plugins.
*/
public function getDisplayName()
{
return 'XML To HTML PLUGIN';
}
/**
* Provide a description for this plugin
*
* The description will appear in the plugins list where editors can
* enable and disable plugins.
*/
public function getDescription()
{
return 'This plugin transform XML articles to HTML';
}
/**
* @param $request
* @param $verb
* @return mixed
*/
public function getActions($request, $verb) {
$router = $request->getRouter();
import('lib.pkp.classes.linkAction.request.AjaxModal');
return array_merge(
$this->getEnabled()?array(
new LinkAction(
'settings',
new AjaxModal(
$router->url($request, null, null, 'manage', null, array('verb' => 'settings', 'plugin' => $this->getName(), 'category' => 'generic')),
$this->getDisplayName()
),
__('manager.plugins.settings'),
null
),
):array(),
parent::getActions($request, $verb)
);
}
/**
* Load a form when the `settings` button is clicked and
* save the form when the user saves it.
*
* @param array $args
* @param Request $request
* @return JSONMessage
*/
public function manage($args, $request)
{
switch ($request->getUserVar('verb')) {
case 'settings':
$this->import('XML2HTMLSettingsForm');
// Load the custom form
$form = new XML2HTMLSettingsForm($this);
// Fetch the form the first time it loads, before
// the user has tried to save it
if (!$request->getUserVar('save')) {
$form->initData();
return new JSONMessage(true, $form->fetch($request));
}
// Validate and save the form data
$form->readInputData();
if ($form->validate()) {
$form->execute();
return new JSONMessage(true);
}
}
return parent::manage($args, $request);
}
function getPluginAssetsPath($request) {
return $request->getBaseUrl() . '/' . $this->getPluginPath() . '/resources/';
}
static function transform(
string $xmlFilePath
)
{
////// xslt transfo
$xsltPath = dirname(__FILE__) . DIRECTORY_SEPARATOR . '2html.xsl';
// Load the XML source
$xml = new DOMDocument;
$xml->load($xmlFilePath);
$xsl = new DOMDocument;
$xsl->load($xsltPath, LIBXML_DTDATTR);
// Configure the transformer
$proc = new XSLTProcessor;
$proc->importStyleSheet($xsl); // attach the xsl rules
$locale = AppLocale::getLocale();
$proc->setParameter('', 'lang', $locale);
return $proc->transformToXML($xml);
}
static function unzipXMLArchive(string $path)
{
$fileManager = new FileManager();
$submissionFileExtension = $fileManager->parseFileExtension($path);
$fileInfo = pathinfo($path);
if ($submissionFileExtension == 'zip') {
$fileMgr = new PrivateFileManager();
$filesDir = $fileMgr->getBasePath() . DIRECTORY_SEPARATOR;
$zip = new ZipArchive;
$zipPath = $filesDir . $path;
$zipPathParts = pathinfo($zipPath);
if (file_exists($zipPathParts['dirname'] . DIRECTORY_SEPARATOR . $zipPathParts['filename'])) {
return $filesDir . $fileInfo['dirname'] . DIRECTORY_SEPARATOR . $fileInfo['filename'] . DIRECTORY_SEPARATOR . $fileInfo['filename'] . '.xml';
}
if ($zip->open($zipPath) === TRUE) {
$archiveFolderName = NULL;
if ($zip->numFiles > 0) {//gets zip top folder name
$archiveFolderName = $zip->getNameIndex(0);
} else {
throw new \Exception("Bad zip Submission file.");
}
$zip->extractTo($zipPathParts['dirname']);
rename(
$zipPathParts['dirname'] . DIRECTORY_SEPARATOR . $archiveFolderName,
$zipPathParts['dirname'] . DIRECTORY_SEPARATOR . $zipPathParts['filename']);
$zip->close();
$files = scandir($zipPathParts['dirname'] . DIRECTORY_SEPARATOR . $zipPathParts['filename']);
foreach ($files as $file) {
$extension = $fileManager->parseFileExtension($file);
if ($extension == 'xml') {
$basePath = $zipPathParts['dirname'] . DIRECTORY_SEPARATOR . $zipPathParts['filename'] . '/';
rename(
$basePath . $file,
$basePath . $zipPathParts['filename'] . '.xml'
);
return $filesDir . $fileInfo['dirname'] . DIRECTORY_SEPARATOR . $fileInfo['filename'] . DIRECTORY_SEPARATOR . $fileInfo['filename'] . '.xml';
}
}
} else {
return NULL;
}
} else return NULL;
}
/**
* @param $hookName string
* @param $args array
* @brief Handle associated files of the full-text, only images are supported
*/
function loadImageHandler($hookName, array $args)
{
$page = $args[0];
$op = $args[1];
if ($page == 'article' && (/*$op == 'image' || */$op == 'zimage')) {
define('HANDLER_CLASS', 'ArticleImageDataHandler');
import('plugins.generic.xml2html.ArticleImageDataHandler');
} else if (($page == 'catalog') && (/*$op == 'image' || */$op == 'zimage')) {
define('HANDLER_CLASS', 'BookImageDataHandler');
import('plugins.generic.xml2html.BookImageDataHandler');
}
}
static function resolveZipImagePaths(
string $htmlString,
int $submissionId,
int $galleyId,
string $xmlFilePath,
Request $request,
string $op = 'article')
{
$pathInfo = pathinfo($xmlFilePath);
$extractedZipPath = $pathInfo['dirname'];
$files = scandir($extractedZipPath);
foreach ($files as $file) {
$info = pathinfo($file);
if ($info["extension"] == 'jpg' || $info["extension"] == 'png') {
$request = $request;
$filePath = $request->url(
null, $op,
'zimage',
array(
$submissionId,
$galleyId,
$file
)
);
$pattern = preg_quote(rawurlencode($file));
$htmlString = preg_replace(
'/([Ss][Rr][Cc]|[Hh][Rr][Ee][Ff]|[Dd][Aa][Tt][Aa])\s*=\s*"([^"]*' . $pattern . ')"/',
'\1="' . $filePath . '"',
$htmlString);
}
}
return $htmlString;
}
}