1<?php
2
3if(!defined('DOKU_INC')) define('DOKU_INC',realpath(dirname(__FILE__).'/../../').'/');
4if(!defined('DOKU_PLUGIN')) define('DOKU_PLUGIN',DOKU_INC.'lib/plugins/');
5require_once(DOKU_PLUGIN.'syntax.php');
6
7/**
8 * All DokuWiki plugins to extend the parser/rendering mechanism
9 * need to inherit from this class
10 */
11class syntax_plugin_revealjs_theme extends DokuWiki_Syntax_Plugin {
12
13    public function getType() { return 'substition'; }
14    public function getSort() { return 32; }
15    public function getPType() { return 'block'; }
16
17
18    /**
19     * Connect lookup pattern to lexer.
20     *
21     * @param $aMode String The desired rendermode.
22     * @return none
23     * @public
24     * @see render()
25     */
26    public function connectTo($mode) {
27         $this->Lexer->addSpecialPattern('~~REVEAL[^~]*~~',$mode,'plugin_revealjs_theme');
28    }
29
30
31
32    /**
33     * Handler to prepare matched data for the rendering process.
34     *
35     * @param $aMatch String The text matched by the patterns.
36     * @param $aState Integer The lexer state for the match.
37     * @param $aPos Integer The character position of the matched text.
38     * @param $aHandler Object Reference to the Doku_Handler object.
39     * @return Integer The current lexer state for the match.
40     * @public
41     * @see render()
42     * @static
43     */
44    public function handle($match, $state, $pos, Doku_Handler $handler) {
45        $data = array();
46        /* Merge options from URL params into conf. URL params should not be
47        overwritten here, we want to be able to change parameters in the
48        URL. This is the reason to distinguish between the presentation
49        renderer and the page renderer. */
50        if ($_GET['do'] === 'export_revealjs') {
51            // pass -> merge itself is done in the renderer.php in earlier stage, because needed there
52        }
53        /* Merge options from page into conf */
54        else {
55            // parse options
56            if ($match !== '~~REVEAL~~') {
57                $options = trim(substr($match,8,-2));
58                // ensure that only whitespaces do not result in "theme="
59                if ($options != '') {
60                    // parse multiple options (example: theme=moon&controls=1&build_all_lists=1)
61                    if (strpos($options, '=') !== false) {
62                        parse_str($options, $data);
63                    }
64                    // if only one option this must be the theme (backward compatibility)
65                    else {
66                        $data['theme'] = $options;
67                    }
68                }
69            }
70            // merge options (needed in parsing phase for other syntax modules)
71            $this->_merge_options_into_conf($data);
72        }
73        return $data;
74    }
75
76    /**
77     * Handle the actual output creation.
78     *
79     * @param $aFormat String The output format to generate.
80     * @param $aRenderer Object A reference to the renderer object.
81     * @param $aData Array The data created by the <tt>handle()</tt>
82     * method.
83     * @return Boolean <tt>TRUE</tt> if rendered successfully, or
84     * <tt>FALSE</tt> otherwise.
85     * @public
86     * @see handle()
87     */
88    public function render($mode, Doku_Renderer $renderer, $data) {
89        global $ID, $conf;
90        if($mode == 'xhtml'){
91            if (is_a($renderer, 'renderer_plugin_revealjs')){
92                // pass
93            }
94            else {
95                /* Merge options again (needed in rendering phase for other syntax modules). Because of
96                DokuWikis caching we have no guarantee that the options merge from the parsing phase
97                will take place, so we do it here again. */
98                $this->_merge_options_into_conf($data);
99                // create button to start the presentation
100                $target = $this->getConf('open_in_new_window') ? '_blank' : '_self';
101                // hide senseless options for the url params to shorten the link
102                unset($data['open_in_new_window']);
103                unset($data['show_slide_details']);
104                unset($data['start_button']);
105
106                $exportData = $data;
107                if(isset($exportData['controls'])) $exportData['controls'] = $exportData['controls'] ? 'true' : 'false';
108                if(isset($exportData['loop'])) $exportData['loop'] = $exportData['loop'] ? 'true' : 'false';
109
110                // create the link
111                $renderer->doc .= '<div class="slide-export-link"><a target="'.$target.'" href="'.
112                    exportlink($ID,'revealjs',count($exportData)?$exportData:null).'" title="'.
113                    $this->getLang('view_presentation').'"><img src="'.DOKU_BASE.'lib/plugins/revealjs/'.
114                    $this->getConf('start_button').'" align="right" alt="'.
115                    $this->getLang('view_presentation').'"/></a>'.
116                    ($this->getConf('user_can_edit') ?
117                        '<br><nobr><a target="'.$target.'" href="'.exportlink($ID,'revealjs',count($exportData)?$exportData:null).
118                        '&print-pdf" title="'.$this->getLang('print_pdf').'">Print PDF</a></nobr>' :
119                        '').
120                    '</div>';
121                /* Prepare vars for own header handling since the needed ones
122                are protected and array types - both reasons wy this is not working
123                from within a plugin. See also /inc/parser/xhtml.php line 37 */
124                $renderer->wikipage_unique_headers = '';
125                $renderer->wikipage_slide_edit_section_open = false;
126                $renderer->wikipage_slide_indicator_headers = true;
127                $renderer->wikipage_slide_background_defined = false;
128                $renderer->wikipage_slide_number = 0;
129                $renderer->wikipage_next_slide_no_footer = false;
130                $renderer->wikipage_next_slide_no_footer_position = 0;
131            }
132            return true;
133        }
134        return false;
135    }
136
137    /**
138     * Merge options from page into plugin conf
139     */
140    private function _merge_options_into_conf($data) {
141        global $ID, $conf;
142        // merge options
143        if (!array_key_exists('plugin', $conf)) {
144            $conf['plugin'] = array('revealjs' => $data);
145        }
146        elseif (!array_key_exists('revealjs', $conf['plugin'])) {
147            $conf['plugin']['revealjs'] = $data;
148        }
149        else {
150            $conf['plugin']['revealjs'] = array_merge($conf['plugin']['revealjs'], $data);
151        }
152        /* Set state for revealjs and user edit right - needed in other syntax modules and also
153        in action plugin for section editing. Sadly this is needed on parse and on render time,
154        so we merge the options twice here in the theme.php. */
155        $conf['plugin']['revealjs']['revealjs_active'] = true;
156        $conf['plugin']['revealjs']['user_can_edit'] = auth_quickaclcheck($ID) >= AUTH_EDIT;
157    }
158}
159