1<?php
2/**
3 * Latexport Plugin: Exports to latex
4 *
5 * @license    GPL 2 (http://www.gnu.org/licenses/gpl.html)
6 * @author Jean-Michel Gonet <jmgonet@yahoo.com>
7 */
8
9// must be run within Dokuwiki
10if(!defined('DOKU_INC')) die();
11
12require_once DOKU_PLUGIN . 'latexport/helpers/archive_helper_zip.php';
13require_once DOKU_PLUGIN . 'latexport/implementation/decorator_persister.php';
14require_once DOKU_PLUGIN . 'latexport/implementation/decorator_includer.php';
15require_once DOKU_PLUGIN . 'latexport/implementation/decorator_math.php';
16require_once DOKU_PLUGIN . 'latexport/implementation/decorator_tables.php';
17require_once DOKU_PLUGIN . 'latexport/implementation/decorator_headings.php';
18require_once DOKU_PLUGIN . 'latexport/implementation/decorator_images.php';
19
20/**
21 * A façade between doku wiki and the actual tex renderer.
22 * Actual renderer is decorator.php or one of its extensions.
23 */
24class renderer_plugin_latexport_tex extends Decorator {
25	const GRAPHICSPATH = 'images/';
26
27	/**
28	 * To create a compressed archive with all TeX resources needed
29	 * to download together.
30	 */
31	private $archive;
32
33	/**
34	 * Keeps track of the recursion level.
35	 * Root page has a recursion level 0. Children pages have a level of 1,
36	 * grand-children have a level of 2, etc.
37	 */
38	private $recursionLevel;
39
40	/**
41	 * Keeps track of heading level.
42	 */
43	private $headingLevel;
44
45	/**
46	 * List of includes yet to process.
47	 */
48	private $includes;
49
50	/**
51	 * Current page ID.
52	 */
53	private $currentPageId;
54
55	/**
56	 * Class constructor.
57	 */
58	function __construct() {
59		$this->archive = new ArchiveHelperZip();
60		$this->includes = new SplQueue();
61		$this->recursionLevel = 0;
62		$this->headingLevel = 0;
63
64		parent::__construct(
65			new DecoratorHeadings(
66				new DecoratorIncluder($this->includes,
67					new DecoratorMath(
68						new DecoratorTables(
69							new DecoratorImages(
70								new DecoratorPersister($this->archive)))))));
71	}
72
73	/**
74	 * Returns the mode name produced by this renderer.
75	 */
76	function getFormat(){
77		return "latexport";
78	}
79
80	/**
81	 * Do not make multiple instances of this class
82	 */
83	function isSingleton(){
84		return true;
85	}
86
87	/**
88	 * Initializes the rendering.
89	 */
90	function document_start($doNotCareAboutProviedPageId = null, $doNotCareAboutProvidedRecursionLevel = 0) {
91		global $ID;
92
93		$this->nocache();
94
95		if (!$this->currentPageId) {
96			$this->currentPageId = $ID;
97		}
98
99		$fileName = $this->texifyPageId($this->currentPageId);
100
101		if ($this->recursionLevel == 0) {
102			// Create HTTP headers
103			$output_filename = $this->texifyPageId($this->currentPageId, 'zip');
104			$headers = array(
105					'Content-Type' => $this->archive->getContentType(),
106					'Content-Disposition' => 'attachment; filename="'.$output_filename.'";',
107					);
108
109			// store the content type headers in metadata
110			p_set_metadata($this->currentPageId,array('format' => array('latexport_tex' => $headers) ));
111
112			// Starts the archive:
113			$this->archive->startArchive();
114
115			// The root page has always the same file name:
116			$fileName = "aaa.tex";
117		}
118
119		// Starts the document:
120		$this->archive->startFile($fileName);
121		$this->decorator->document_start($this->currentPageId, $this->recursionLevel);
122		$this->recursionLevel++;
123	}
124
125	/**
126	 * Propagates the heading level corrected with base heading level retrieved
127	 * from the include link.
128	 */
129	function header($text, $level, $pos) {
130		$this->decorator->header($text, $level + $this->headingLevel, $pos);
131	}
132
133	/**
134	 * Closes the document and processes the gathered includes.
135	 */
136	function document_end($doNotCareAboutProvidedRecursionLevel = 0){
137		$this->decorator->document_end($this->recursionLevel - 1);
138
139		$this->archive->closeFile();
140
141		$this->processIncludes();
142
143		$this->recursionLevel--;
144		if ($this->recursionLevel == 0) {
145			$this->doc = $this->archive->closeArchive();
146		}
147	}
148
149	function processIncludes() {
150		while (!$this->includes->isEmpty()) {
151			$include = $this->includes->pop();
152			$file = wikiFN($include->getLink());
153			$this->currentPageId = $include->getLink();
154			$this->headingLevel = $include->getHeadingLevel();
155			p_cached_output($file, 'latexport_tex');
156		}
157	}
158}
159