1 <?php
2 /**
3  * Add Note capability to dokuwiki
4  *
5  * <note>This is note</note>
6  * <note classic>This is note</note>
7  * <note important>This is an important note</note>
8  * <note warning>This is a big warning</note>
9  * <note tip>This is a tip</note>
10  *
11  * by Olivier Cortès <olive@deep-ocean.net>
12  * under the terms of the GNU GPL v2.
13  *
14  * Originaly derived from the work of :
15  * Stephane Chamberland <stephane.chamberland@ec.gc.ca> (Side Notes PlugIn)
16  * Carl-Christian Salvesen <calle@ioslo.net> (Graphviz plugin)
17  *
18  * Contributions by Eric Hameleers <alien [at] slackware [dot] com> :
19  *   use <div> instead of <table>,
20  *   contain the images and stylesheet inside the plugin,
21  *   permit nesting of notes,
22  *
23  * Contributed by Christopher Smith <chris [at] jalakai [dot] co [dot] uk>
24  *   fix some parsing problems and a security hole.
25  *   make note types case independent
26  *   simplify code reading
27  *   modernise the plugin for changes/fixes/improvements to the underlying Dokuwiki plugin class,
28  *   improve efficiency.
29  *
30  * Contributed by Aurélien Bompard <aurelien [at] bompard [dot] org>
31  *   support for the ODT output format.
32  *
33  * @license    GNU_GPL_v2
34  * @author     Olivier Cortes <olive@deep-ocean.net>
35  */
36 
37 class syntax_plugin_note extends DokuWiki_Syntax_Plugin
38 {
39 
40     protected $notes = array(
41         'noteimportant' => array('important', 'importante'),
42         'notewarning' => array('warning', 'bloquante', 'critique'),
43         'notetip' => array('tip', 'tuyau', 'idée'),
44         'noteclassic' => array('', 'classic', 'classique')
45     );
46 
47     protected $default = 'plugin_note noteclassic';
48 
49     function getType()
50     {
51         return 'container';
52     }
53 
54     function getPType()
55     {
56         return 'block';
57     }
58 
59     function getAllowedTypes()
60     {
61         return array('container', 'substition', 'protected', 'disabled', 'formatting', 'paragraphs');
62     }
63 
64     function getSort()
65     {
66         return 195;
67     }
68 
69     // override default accepts() method to allow nesting
70     // - ie, to get the plugin accepts its own entry syntax
71     function accepts($mode)
72     {
73         if ($mode == substr(get_class($this), 7)) {
74             return true;
75         }
76         return parent::accepts($mode);
77     }
78 
79     function connectTo($mode)
80     {
81         $this->Lexer->addEntryPattern('<note.*?>(?=.*?</note>)', $mode, 'plugin_note');
82     }
83 
84     function postConnect()
85     {
86         $this->Lexer->addExitPattern('</note>', 'plugin_note');
87     }
88 
89     function handle($match, $state, $pos, Doku_Handler $handler)
90     {
91         switch ($state) {
92             case DOKU_LEXER_ENTER:
93                 $note = strtolower(trim(substr($match, 5, -1)));
94 
95                 foreach ($this->notes as $class => $names) {
96                     if (in_array($note, $names)) {
97                         return array($state, $class);
98                     }
99                 }
100                 return array($state, $this->default);
101 
102             case DOKU_LEXER_UNMATCHED:
103                 return array($state, $match);
104 
105             default:
106                 return array($state, null);
107         }
108     }
109 
110     function render($format, Doku_Renderer $renderer, $indata)
111     {
112         if ($format == 'xhtml') {
113             list($state, $data) = $indata;
114 
115             switch ($state) {
116                 case DOKU_LEXER_ENTER :
117                     $renderer->doc .= '<div class="plugin_note ' . htmlspecialchars($data) . '">';
118                     break;
119 
120                 case DOKU_LEXER_UNMATCHED :
121                     $renderer->doc .= $renderer->_xmlEntities($data);
122                     break;
123 
124                 case DOKU_LEXER_EXIT :
125                     $renderer->doc .= "\n</div>";
126                     break;
127             }
128             return true;
129         } elseif ($format == 'odt') {
130             list($state, $data) = $indata;
131 
132             $this->render_odt($renderer, $state, $data);
133             return true;
134         }
135 
136         // unsupported $mode
137         return false;
138     }
139 
140     protected function render_odt($renderer, $state, $data)
141     {
142         static $first = true;
143         static $new;
144 
145         if ($first == true) {
146             $new = method_exists($renderer, 'getODTPropertiesFromElement');
147             $first = false;
148         }
149 
150         if (!$new) {
151             // Render with older ODT plugin version.
152             $this->render_odt_old($renderer, $state, $data);
153         } else {
154             // Render with newer ODT plugin version.
155             $this->render_odt_new($renderer, $state, $data);
156         }
157     }
158 
159     protected function render_odt_old($renderer, $state, $data)
160     {
161         switch ($state) {
162             case DOKU_LEXER_ENTER:
163                 $type = substr($data, 4);
164                 if ($type == 'classic') {
165                     // The icon for classic notes is named note.png
166                     $type = 'note';
167                 }
168                 $colors = array('note' => '#eeeeff', 'warning' => '#ffdddd', 'important' => '#ffffcc', 'tip' => '#ddffdd');
169 
170                 // Content
171                 $properties = array();
172                 $properties ['width'] = '100%';
173                 $properties ['align'] = 'center';
174                 $properties ['shadow'] = '#808080 0.18cm 0.18cm';
175                 $renderer->_odtTableOpenUseProperties($properties);
176 
177                 $properties = array();
178                 $properties ['width'] = '1.5cm';
179                 $renderer->_odtTableAddColumnUseProperties($properties);
180 
181                 $properties = array();
182                 $properties ['width'] = '13.5cm';
183                 $renderer->_odtTableAddColumnUseProperties($properties);
184 
185                 $renderer->tablerow_open();
186 
187                 $properties = array();
188                 $properties ['vertical-align'] = 'middle';
189                 $properties ['text-align'] = 'center';
190                 $properties ['padding'] = '0.1cm';
191                 $properties ['border'] = '0.002cm solid #000000';
192                 $properties ['background-color'] = $colors[$type];
193                 $renderer->_odtTableCellOpenUseProperties($properties);
194 
195                 $src = DOKU_PLUGIN . 'note/images/' . $type . '.png';
196                 $renderer->_odtAddImage($src);
197 
198                 $renderer->tablecell_close();
199 
200                 $properties = array();
201                 $properties ['vertical-align'] = 'middle';
202                 $properties ['padding'] = '0.3cm';
203                 $properties ['border'] = '0.002cm solid #000000';
204                 $properties ['background-color'] = $colors[$type];
205                 $renderer->_odtTableCellOpenUseProperties($properties);
206                 break;
207 
208             case DOKU_LEXER_UNMATCHED :
209                 $renderer->cdata($data);
210                 break;
211 
212             case DOKU_LEXER_EXIT :
213                 $renderer->tablecell_close();
214                 $renderer->tablerow_close();
215                 $renderer->_odtTableClose();
216                 $renderer->p_open();
217                 break;
218         }
219     }
220 
221     /**
222      * ODT rendering for new versions of the ODT plugin.
223      *
224      * @param $renderer the renderer to use
225      * @param $state    the current state
226      * @param $data     data from handle()
227      * @author LarsDW223
228      */
229     protected function render_odt_new($renderer, $state, $data)
230     {
231         switch ($state) {
232             case DOKU_LEXER_ENTER:
233                 $css_properties = array();
234 
235                 // Get CSS properties for ODT export.
236                 $renderer->getODTPropertiesNew($css_properties, 'div', 'class="' . $data . '"', null, true);
237 
238                 // Create Content
239                 // (We only use the CSS parameters that are meaningful for creating the ODT table)
240                 $properties = array();
241                 $properties ['width'] = '100%';
242                 $properties ['align'] = 'center';
243                 $properties ['shadow'] = '#808080 0.18cm 0.18cm';
244                 $renderer->_odtTableOpenUseProperties($properties);
245 
246                 $properties = array();
247                 $properties ['width'] = '1.5cm';
248                 $renderer->_odtTableAddColumnUseProperties($properties);
249 
250                 $properties = array();
251                 $properties ['width'] = '13.5cm';
252                 $renderer->_odtTableAddColumnUseProperties($properties);
253 
254                 $renderer->tablerow_open();
255 
256                 $properties = array();
257                 $properties ['vertical-align'] = $css_properties ['vertical-align'];
258                 $properties ['text-align'] = 'center';
259                 $properties ['padding'] = '0.1cm';
260                 $properties ['border'] = '0.002cm solid #000000';
261                 $properties ['background-color'] = $css_properties ['background-color'];
262                 $renderer->_odtTableCellOpenUseProperties($properties);
263 
264                 if ($css_properties ['background-image']) {
265                     $renderer->_odtAddImage($css_properties ['background-image']);
266                 }
267 
268                 $renderer->tablecell_close();
269 
270                 $properties = array();
271                 $properties ['vertical-align'] = $css_properties ['vertical-align'];
272                 $properties ['text-align'] = $css_properties ['text-align'];
273                 $properties ['padding'] = '0.3cm';
274                 $properties ['border'] = '0.002cm solid #000000';
275                 $properties ['background-color'] = $css_properties ['background-color'];
276                 $renderer->_odtTableCellOpenUseProperties($properties);
277                 break;
278 
279             case DOKU_LEXER_UNMATCHED :
280                 $renderer->cdata($data);
281                 break;
282 
283             case DOKU_LEXER_EXIT :
284                 $renderer->tablecell_close();
285                 $renderer->tablerow_close();
286                 $renderer->_odtTableClose();
287                 $renderer->p_open();
288                 break;
289         }
290     }
291 }
292