1<?php
2/* Copyright (c) 1998-2013 ILIAS open source, Extended GPL, see docs/LICENSE */
3
4require_once './Services/PDFGeneration/classes/factory/class.ilHtmlToPdfTransformerFactory.php';
5require_once './Services/PDFGeneration/classes/class.ilPDFGeneratorUtils.php';
6
7/**
8 * Class ilTestPDFGenerator
9 *
10 * Class that handles PDF generation for test and assessment.
11 *
12 * @author Maximilian Becker <mbecker@databay.de>
13 * @version $Id$
14 *
15 */
16class ilTestPDFGenerator
17{
18    const PDF_OUTPUT_DOWNLOAD = 'D';
19    const PDF_OUTPUT_INLINE = 'I';
20    const PDF_OUTPUT_FILE = 'F';
21
22    const service = "Test";
23
24    private static function buildHtmlDocument($contentHtml, $styleHtml)
25    {
26        return "
27			<html>
28				<head>
29					<meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\" />
30 					$styleHtml
31 				</head>
32				<body>$contentHtml</body>
33			</html>
34		";
35    }
36
37    /**
38     * @param $html
39     * @return string
40     */
41    private static function makeHtmlDocument($contentHtml, $styleHtml)
42    {
43        if (!is_string($contentHtml) || !strlen(trim($contentHtml))) {
44            return $contentHtml;
45        }
46
47        $html = self::buildHtmlDocument($contentHtml, $styleHtml);
48
49        $dom = new DOMDocument("1.0", "utf-8");
50        if (!@$dom->loadHTML($html)) {
51            return $html;
52        }
53
54        $invalid_elements = array();
55
56        $script_elements = $dom->getElementsByTagName('script');
57        foreach ($script_elements as $elm) {
58            $invalid_elements[] = $elm;
59        }
60
61        foreach ($invalid_elements as $elm) {
62            $elm->parentNode->removeChild($elm);
63        }
64
65        // remove noprint elems as tcpdf will make empty pdf when hidden by css rules
66        $domX = new DomXPath($dom);
67        foreach ($domX->query("//*[contains(@class, 'noprint')]") as $node) {
68            $node->parentNode->removeChild($node);
69        }
70
71        $dom->encoding = 'UTF-8';
72
73        $img_src_map = array();
74        foreach ($dom->getElementsByTagName('img') as $elm) {
75            /** @var $elm DOMElement $uid */
76            $uid = 'img_src_' . uniqid();
77            $src = $elm->getAttribute('src');
78
79            $elm->setAttribute('src', $uid);
80
81            $img_src_map[$uid] = $src;
82        }
83
84        $cleaned_html = $dom->saveHTML();
85
86        foreach ($img_src_map as $uid => $src) {
87            $cleaned_html = str_replace($uid, $src, $cleaned_html);
88        }
89
90        if (!$cleaned_html) {
91            return $html;
92        }
93
94        return $cleaned_html;
95    }
96
97    public static function generatePDF($pdf_output, $output_mode, $filename = null, $purpose = null)
98    {
99        $pdf_output = self::preprocessHTML($pdf_output);
100
101        if (substr($filename, strlen($filename) - 4, 4) != '.pdf') {
102            $filename .= '.pdf';
103        }
104        $pdf_factory = new ilHtmlToPdfTransformerFactory();
105        return $pdf_factory->deliverPDFFromHTMLString($pdf_output, $filename, $output_mode, self::service, $purpose);
106    }
107
108    public static function preprocessHTML($html)
109    {
110        $html = self::makeHtmlDocument($html, '<style>' . self::getCssContent() . '</style>');
111
112        return $html;
113    }
114
115    protected static function getTemplatePath($a_filename, $module_path = 'Modules/Test/')
116    {
117        // use ilStyleDefinition instead of account to get the current skin
118        include_once "Services/Style/System/classes/class.ilStyleDefinition.php";
119        if (ilStyleDefinition::getCurrentSkin() != "default") {
120            $fname = "./Customizing/global/skin/" .
121                    ilStyleDefinition::getCurrentSkin() . "/" . $module_path . basename($a_filename);
122        }
123
124        if ($fname == "" || !file_exists($fname)) {
125            $fname = "./" . $module_path . "templates/default/" . basename($a_filename);
126        }
127        return $fname;
128    }
129
130    protected static function getCssContent()
131    {
132        $cssContent = file_get_contents(self::getTemplatePath('delos.css', ''));
133        $cssContent .= file_get_contents(self::getTemplatePath('test_pdf.css'));
134
135        return $cssContent;
136    }
137}
138