Skip to content
Snippets Groups Projects
Select Git revision
  • c1eb8fedfd82964a1ee04dd044a6e38c742cc912
  • master default protected
  • cambouis-3_3_0
  • stable-3_3_0
  • jc/zimage-with-subfile-ids
  • jc/3.4.0-4
6 results

XML2HTMLPlugin.php

Blame
  • 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;
        }
    
    }