dokuwiki-hidden-plugin – Blame information for rev 1

Subversion Repositories:
Rev:
Rev Author Line No. Line
1 office 1 <?php
2 /**
3 * Plugin hidden: Enable to hide details
4 * v2.4
5 * @license GPL 2 (http://www.gnu.org/licenses/gpl.html)
6 * @author Guillaume Turri <guillaume.turri@gmail.com>
7 */
8  
9 if(!defined('DOKU_INC')) define('DOKU_INC',realpath(dirname(__FILE__).'/../../').'/');
10 if(!defined('DOKU_PLUGIN')) define('DOKU_PLUGIN',DOKU_INC.'lib/plugins/');
11 require_once(DOKU_INC.'inc/parserutils.php');
12 require_once(DOKU_PLUGIN.'syntax.php');
13  
14 /**
15 * All DokuWiki plugins to extend the parser/rendering mechanism
16 * need to inherit from this class
17 */
18 class syntax_plugin_hidden extends DokuWiki_Syntax_Plugin {
19  
20 function getType(){ return 'container'; }
21 function getPType(){ return 'stack'; }
22 function getAllowedTypes() {
23 return array('container', 'baseonly', 'substition','protected','disabled','formatting','paragraphs');
24 }
25 function getSort(){
26 //make sure it's greater than hiddenSwitch plugin's one in order to avoid a confusion between "<hidden.*" and "<hiddenSwitch.*"
27 return 189;
28 }
29  
30 // override default accepts() method to allow nesting
31 // - ie, to get the plugin accepts its own entry syntax
32 function accepts($mode) {
33 if ($mode == substr(get_class($this), 7)) return true;
34 return parent::accepts($mode);
35 }
36  
37 function connectTo($mode) {
38 $this->Lexer->addEntryPattern('<hidden\b.*?>(?=.*?</hidden>)', $mode,'plugin_hidden');
39 $this->Lexer->addSpecialPattern('<hiddenSwitch[^>]*>', $mode,'plugin_hidden');
40 }
41 function postConnect() {
42 $this->Lexer->addExitPattern('</hidden>','plugin_hidden');
43 }
44  
45 function handle($match, $state, $pos, Doku_Handler $handler) {
46 switch ($state) {
47 case DOKU_LEXER_SPECIAL:
48 //hiddenSwitch
49 $return = array('text' => $this->getLang('switch.default'), 'type' => 'switch');
50 $match = trim(utf8_substr($match, 14, -1)); //14 = strlen("<hiddenSwitch ")
51 if ( $match !== '' ){
52 $return['text'] = $match;
53 }
54 $return['text'] = htmlspecialchars($return['text']);
55 return $return;
56  
57 case DOKU_LEXER_ENTER :
58 $return = array(
59 'active' => 'true',
60 'element'=>Array(),
61 'onHidden'=>'',
62 'onVisible'=>'',
63 'initialState'=>'hidden',
64 'state'=>$state,
65 'printHead' => true,
66 'bytepos_start' => $pos,
67 'edit' => false,
68 'editText' => $this->getLang('edit'),
69 'onExportPdf' => ''
70 );
71 $match = substr($match, 7, -1); //7 = strlen("<hidden")
72  
73 //Looking for the initial state
74 preg_match("/initialState *= *\"([^\"]*)\" ?/i", $match, $initialState);
75 if ( count($initialState) != 0) {
76 $match = str_replace($initialState[0], '', $match);
77 $initialState = strtolower(trim($initialState[1]));
78 if ( $initialState == 'visible'
79 || $initialState == 'true'
80 || $initialState == 'expand' ) {
81 $return['initialState'] = 'visible';
82 }
83 }
84  
85 //Looking for the -noPrint option
86 if ( preg_match('/-noprint/i', $match, $found) ){
87 $return['printHead'] = false;
88 $match = str_replace($found[0], '', $match);
89 }
90  
91 //Looking for the -editable option
92 if ( preg_match('/-edit(able)?( *= *"([^"]*)")?/i', $match, $found) ){
93 if ( count($found) > 1 ){
94 $return['editText'] = end($found);
95 }
96 $return['edit'] = true;
97 $match = str_replace($found[0], '', $match);
98 }
99  
100 //Looking if this block is active
101 preg_match("/active *= *\"([^\"]*)\" ?/i", $match, $active);
102 if( count($active) != 0 ){
103 $match = str_replace($active[0], '', $match);
104 $active = strtolower(trim($active[1]));
105 if($active=='false' || $active=='f' || $active=='0' || $active=='n'){
106 $return['active'] = false;
107 }
108 }
109  
110 //Looking for the element(s) of the block (ie: which switches may activate this element)
111 preg_match("/element *= *\"([^\"]*)\" ?/i", $match, $element);
112 if( count($element) != 0 ){
113 $match = str_replace($element[0], '', $match);
114 $element[1] = htmlspecialchars($element[1]);
115 $return['element'] = explode(' ', $element[1]);
116 }
117  
118 //Looking for the texts to display
119 $this->_grepOption($return, 'onHidden', $match);
120 $this->_grepOption($return, 'onVisible', $match);
121 $this->_grepOption($return, 'onExportPdf', $match);
122  
123 //If there were neither onHidden nor onVisible, take what's left
124 if( $return['onHidden']=='' && $return['onVisible']=='' ){
125 $text = trim($match);
126 if($text != ''){
127 $return['onHidden'] = $text;
128 $return['onVisible'] = $text;
129 } else { //if there's nothing left, take the default texts
130 $return['onHidden'] = $this->getConf('default_text_when_hidden');
131 $return['onVisible'] = $this->getConf('default_text_when_displayed');
132 }
133 } else { //if one string is specified but not the other, take the defaul text
134 $return['onHidden'] = ($return['onHidden']!='') ? $return['onHidden'] : $this->getConf('default_text_when_hidden');
135 $return['onVisible'] = ($return['onVisible']!='') ? $return['onVisible'] : $this->getConf('default_text_when_displayed');
136 }
137  
138 //If we don't have an exportPdf text, take the onVisible one, since the block will be exported unfolded
139 if ( $return['onExportPdf'] == '' ){
140 $return['onExportPdf'] = $return['onVisible'];
141 }
142  
143 //for security
144 $return['onHidden'] = htmlspecialchars($return['onHidden']);
145 $return['onVisible'] = htmlspecialchars($return['onVisible']);
146 $return['onExportPdf'] = htmlspecialchars($return['onExportPdf']); //FIXME: is it always the kind of escpaing we want?
147  
148 return $return;
149  
150 case DOKU_LEXER_UNMATCHED :
151 return array('state'=>$state, 'text'=>$match);
152  
153 default:
154 return array('state'=>$state, 'bytepos_end' => $pos + strlen($match));
155 }
156 } // handle()
157  
158 private function _grepOption(&$options, $tag, &$match){
159 preg_match("/$tag *= *\"([^\"]*)\" ?/i", $match, $text);
160 if ( count($text) != 0 ){
161 $match = str_replace($text[0], '', $match);
162 $options[$tag] = $text[1];
163 }
164 }
165  
166 function render($mode, Doku_Renderer $renderer, $data) {
167 if ( $this->_exportingPDF() ){
168 $data['onVisible'] = $data['onExportPdf'];
169 }
170  
171 if($mode == 'xhtml' && $data['type'] == 'switch') {
172 $renderer->doc .= '<button class="button hiddenSwitch">'.$data['text'].'</button>';
173 return true;
174 }
175 if($mode == 'xhtml'){
176 switch ($data['state']) {
177 case DOKU_LEXER_ENTER :
178 $this->editableBlocks[] = $data['edit'];
179 $classEdit = ($data['edit'] ? $renderer->startSectionEdit($data['bytepos_start'], 'section', $data['editText']) : '');
180 $tab = array();
181 $onVisible = p_render('xhtml', p_get_instructions($data['onVisible']), $tab);
182 $onHidden = p_render('xhtml', p_get_instructions($data['onHidden']), $tab);
183  
184 // "\n" are inside tags to avoid whitespaces in the DOM with FF
185 $renderer->doc .= '<div class="hiddenGlobal '.$classEdit;
186 $renderer->doc .= $data['active'] ? ' hiddenActive' : '';
187 $renderer->doc .= '">';
188  
189  
190  
191 $renderer->doc .= '<div class="hiddenElements">';
192 foreach($data['element'] as $element){
193 $renderer->doc .= ' '.$element;
194 }
195 $renderer->doc .= "</div>";
196  
197 $renderer->doc .= '<div class="hiddenHead ';
198 $renderer->doc .= $data['printHead'] ? '' : 'hiddenNoPrint';
199 $renderer->doc .= ($data['initialState'] == 'hidden') ? ' hiddenSinceBeginning' : '';
200 $renderer->doc .= '">';
201 $renderer->doc .= '<div class="hiddenOnHidden">'.$onHidden."</div>"; //text displayed when hidden
202 $renderer->doc .= '<div class="hiddenOnVisible">'.$onVisible."</div>"; //text displayed when expanded
203 $renderer->doc .= '</div> <!-- .hiddenHead -->';
204  
205 $renderer->doc .= '<div class="hiddenBody">';
206 break;
207  
208 case DOKU_LEXER_UNMATCHED :
209 $text = $renderer->_xmlEntities($data['text']);
210 if ( preg_match("/^[ \t]*={2,}[^\n]+={2,}[ \t]*$/", $text, $match) ){
211 $title = trim($match[0]);
212 $level = 7 - strspn($title,'=');
213 if($level < 1) $level = 1;
214 $title = trim($title,'=');
215 $title = trim($title);
216 $renderer->header($title, $level, 0);
217 } else {
218 $renderer->doc .= $text;
219 }
220 break;
221  
222 case DOKU_LEXER_EXIT :
223 $renderer->doc .= "</div></div>"; //close hiddenBody and hiddenGlobal
224 if ( array_pop($this->editableBlocks) ){
225 $renderer->finishSectionEdit($data['bytepos_end']);
226 }
227 break;
228 }
229 return true;
230 }
231  
232 if ($mode == 'odt') {
233 if ($data['state'] == DOKU_LEXER_UNMATCHED && $data['type'] != 'switch') {
234 $renderer->doc .= $renderer->_xmlEntities($data['text']);
235 }
236 return true;
237 }
238  
239 return false;
240 } // render()
241  
242 private function _exportingPDF(){
243 global $ACT;
244 return ($ACT == 'export_pdf' || $ACT == 'export_pdfbook' || $ACT == 'export_odt');
245 }
246  
247 var $editableBlocks = array();
248  
249 } // class syntax_plugin_nspages