250 lines
9.4 KiB
PHP
250 lines
9.4 KiB
PHP
|
<?php
|
||
|
/**
|
||
|
* Plugin hidden: Enable to hide details
|
||
|
* v2.4
|
||
|
* @license GPL 2 (http://www.gnu.org/licenses/gpl.html)
|
||
|
* @author Guillaume Turri <guillaume.turri@gmail.com>
|
||
|
*/
|
||
|
|
||
|
if(!defined('DOKU_INC')) define('DOKU_INC',realpath(dirname(__FILE__).'/../../').'/');
|
||
|
if(!defined('DOKU_PLUGIN')) define('DOKU_PLUGIN',DOKU_INC.'lib/plugins/');
|
||
|
require_once(DOKU_INC.'inc/parserutils.php');
|
||
|
require_once(DOKU_PLUGIN.'syntax.php');
|
||
|
|
||
|
/**
|
||
|
* All DokuWiki plugins to extend the parser/rendering mechanism
|
||
|
* need to inherit from this class
|
||
|
*/
|
||
|
class syntax_plugin_hidden extends DokuWiki_Syntax_Plugin {
|
||
|
|
||
|
function getType(){ return 'container'; }
|
||
|
function getPType(){ return 'stack'; }
|
||
|
function getAllowedTypes() {
|
||
|
return array('container', 'baseonly', 'substition','protected','disabled','formatting','paragraphs');
|
||
|
}
|
||
|
function getSort(){
|
||
|
//make sure it's greater than hiddenSwitch plugin's one in order to avoid a confusion between "<hidden.*" and "<hiddenSwitch.*"
|
||
|
return 189;
|
||
|
}
|
||
|
|
||
|
// override default accepts() method to allow nesting
|
||
|
// - ie, to get the plugin accepts its own entry syntax
|
||
|
function accepts($mode) {
|
||
|
if ($mode == substr(get_class($this), 7)) return true;
|
||
|
return parent::accepts($mode);
|
||
|
}
|
||
|
|
||
|
function connectTo($mode) {
|
||
|
$this->Lexer->addEntryPattern('<hidden\b.*?>(?=.*?</hidden>)', $mode,'plugin_hidden');
|
||
|
$this->Lexer->addSpecialPattern('<hiddenSwitch[^>]*>', $mode,'plugin_hidden');
|
||
|
}
|
||
|
function postConnect() {
|
||
|
$this->Lexer->addExitPattern('</hidden>','plugin_hidden');
|
||
|
}
|
||
|
|
||
|
function handle($match, $state, $pos, Doku_Handler $handler) {
|
||
|
switch ($state) {
|
||
|
case DOKU_LEXER_SPECIAL:
|
||
|
//hiddenSwitch
|
||
|
$return = array('text' => $this->getLang('switch.default'), 'type' => 'switch');
|
||
|
$match = trim(utf8_substr($match, 14, -1)); //14 = strlen("<hiddenSwitch ")
|
||
|
if ( $match !== '' ){
|
||
|
$return['text'] = $match;
|
||
|
}
|
||
|
$return['text'] = htmlspecialchars($return['text']);
|
||
|
return $return;
|
||
|
|
||
|
case DOKU_LEXER_ENTER :
|
||
|
$return = array(
|
||
|
'active' => 'true',
|
||
|
'element'=>Array(),
|
||
|
'onHidden'=>'',
|
||
|
'onVisible'=>'',
|
||
|
'initialState'=>'hidden',
|
||
|
'state'=>$state,
|
||
|
'printHead' => true,
|
||
|
'bytepos_start' => $pos,
|
||
|
'edit' => false,
|
||
|
'editText' => $this->getLang('edit'),
|
||
|
'onExportPdf' => ''
|
||
|
);
|
||
|
$match = substr($match, 7, -1); //7 = strlen("<hidden")
|
||
|
|
||
|
//Looking for the initial state
|
||
|
preg_match("/initialState *= *\"([^\"]*)\" ?/i", $match, $initialState);
|
||
|
if ( count($initialState) != 0) {
|
||
|
$match = str_replace($initialState[0], '', $match);
|
||
|
$initialState = strtolower(trim($initialState[1]));
|
||
|
if ( $initialState == 'visible'
|
||
|
|| $initialState == 'true'
|
||
|
|| $initialState == 'expand' ) {
|
||
|
$return['initialState'] = 'visible';
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//Looking for the -noPrint option
|
||
|
if ( preg_match('/-noprint/i', $match, $found) ){
|
||
|
$return['printHead'] = false;
|
||
|
$match = str_replace($found[0], '', $match);
|
||
|
}
|
||
|
|
||
|
//Looking for the -editable option
|
||
|
if ( preg_match('/-edit(able)?( *= *"([^"]*)")?/i', $match, $found) ){
|
||
|
if ( count($found) > 1 ){
|
||
|
$return['editText'] = end($found);
|
||
|
}
|
||
|
$return['edit'] = true;
|
||
|
$match = str_replace($found[0], '', $match);
|
||
|
}
|
||
|
|
||
|
//Looking if this block is active
|
||
|
preg_match("/active *= *\"([^\"]*)\" ?/i", $match, $active);
|
||
|
if( count($active) != 0 ){
|
||
|
$match = str_replace($active[0], '', $match);
|
||
|
$active = strtolower(trim($active[1]));
|
||
|
if($active=='false' || $active=='f' || $active=='0' || $active=='n'){
|
||
|
$return['active'] = false;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//Looking for the element(s) of the block (ie: which switches may activate this element)
|
||
|
preg_match("/element *= *\"([^\"]*)\" ?/i", $match, $element);
|
||
|
if( count($element) != 0 ){
|
||
|
$match = str_replace($element[0], '', $match);
|
||
|
$element[1] = htmlspecialchars($element[1]);
|
||
|
$return['element'] = explode(' ', $element[1]);
|
||
|
}
|
||
|
|
||
|
//Looking for the texts to display
|
||
|
$this->_grepOption($return, 'onHidden', $match);
|
||
|
$this->_grepOption($return, 'onVisible', $match);
|
||
|
$this->_grepOption($return, 'onExportPdf', $match);
|
||
|
|
||
|
//If there were neither onHidden nor onVisible, take what's left
|
||
|
if( $return['onHidden']=='' && $return['onVisible']=='' ){
|
||
|
$text = trim($match);
|
||
|
if($text != ''){
|
||
|
$return['onHidden'] = $text;
|
||
|
$return['onVisible'] = $text;
|
||
|
} else { //if there's nothing left, take the default texts
|
||
|
$return['onHidden'] = $this->getConf('default_text_when_hidden');
|
||
|
$return['onVisible'] = $this->getConf('default_text_when_displayed');
|
||
|
}
|
||
|
} else { //if one string is specified but not the other, take the defaul text
|
||
|
$return['onHidden'] = ($return['onHidden']!='') ? $return['onHidden'] : $this->getConf('default_text_when_hidden');
|
||
|
$return['onVisible'] = ($return['onVisible']!='') ? $return['onVisible'] : $this->getConf('default_text_when_displayed');
|
||
|
}
|
||
|
|
||
|
//If we don't have an exportPdf text, take the onVisible one, since the block will be exported unfolded
|
||
|
if ( $return['onExportPdf'] == '' ){
|
||
|
$return['onExportPdf'] = $return['onVisible'];
|
||
|
}
|
||
|
|
||
|
//for security
|
||
|
$return['onHidden'] = htmlspecialchars($return['onHidden']);
|
||
|
$return['onVisible'] = htmlspecialchars($return['onVisible']);
|
||
|
$return['onExportPdf'] = htmlspecialchars($return['onExportPdf']); //FIXME: is it always the kind of escpaing we want?
|
||
|
|
||
|
return $return;
|
||
|
|
||
|
case DOKU_LEXER_UNMATCHED :
|
||
|
return array('state'=>$state, 'text'=>$match);
|
||
|
|
||
|
default:
|
||
|
return array('state'=>$state, 'bytepos_end' => $pos + strlen($match));
|
||
|
}
|
||
|
} // handle()
|
||
|
|
||
|
private function _grepOption(&$options, $tag, &$match){
|
||
|
preg_match("/$tag *= *\"([^\"]*)\" ?/i", $match, $text);
|
||
|
if ( count($text) != 0 ){
|
||
|
$match = str_replace($text[0], '', $match);
|
||
|
$options[$tag] = $text[1];
|
||
|
}
|
||
|
}
|
||
|
|
||
|
function render($mode, Doku_Renderer $renderer, $data) {
|
||
|
if ( $this->_exportingPDF() ){
|
||
|
$data['onVisible'] = $data['onExportPdf'];
|
||
|
}
|
||
|
|
||
|
if($mode == 'xhtml' && $data['type'] == 'switch') {
|
||
|
$renderer->doc .= '<button class="button hiddenSwitch">'.$data['text'].'</button>';
|
||
|
return true;
|
||
|
}
|
||
|
if($mode == 'xhtml'){
|
||
|
switch ($data['state']) {
|
||
|
case DOKU_LEXER_ENTER :
|
||
|
$this->editableBlocks[] = $data['edit'];
|
||
|
$classEdit = ($data['edit'] ? $renderer->startSectionEdit($data['bytepos_start'], 'section', $data['editText']) : '');
|
||
|
$tab = array();
|
||
|
$onVisible = p_render('xhtml', p_get_instructions($data['onVisible']), $tab);
|
||
|
$onHidden = p_render('xhtml', p_get_instructions($data['onHidden']), $tab);
|
||
|
|
||
|
// "\n" are inside tags to avoid whitespaces in the DOM with FF
|
||
|
$renderer->doc .= '<div class="hiddenGlobal '.$classEdit;
|
||
|
$renderer->doc .= $data['active'] ? ' hiddenActive' : '';
|
||
|
$renderer->doc .= '">';
|
||
|
|
||
|
|
||
|
|
||
|
$renderer->doc .= '<div class="hiddenElements">';
|
||
|
foreach($data['element'] as $element){
|
||
|
$renderer->doc .= ' '.$element;
|
||
|
}
|
||
|
$renderer->doc .= "</div>";
|
||
|
|
||
|
$renderer->doc .= '<div class="hiddenHead ';
|
||
|
$renderer->doc .= $data['printHead'] ? '' : 'hiddenNoPrint';
|
||
|
$renderer->doc .= ($data['initialState'] == 'hidden') ? ' hiddenSinceBeginning' : '';
|
||
|
$renderer->doc .= '">';
|
||
|
$renderer->doc .= '<div class="hiddenOnHidden">'.$onHidden."</div>"; //text displayed when hidden
|
||
|
$renderer->doc .= '<div class="hiddenOnVisible">'.$onVisible."</div>"; //text displayed when expanded
|
||
|
$renderer->doc .= '</div> <!-- .hiddenHead -->';
|
||
|
|
||
|
$renderer->doc .= '<div class="hiddenBody">';
|
||
|
break;
|
||
|
|
||
|
case DOKU_LEXER_UNMATCHED :
|
||
|
$text = $renderer->_xmlEntities($data['text']);
|
||
|
if ( preg_match("/^[ \t]*={2,}[^\n]+={2,}[ \t]*$/", $text, $match) ){
|
||
|
$title = trim($match[0]);
|
||
|
$level = 7 - strspn($title,'=');
|
||
|
if($level < 1) $level = 1;
|
||
|
$title = trim($title,'=');
|
||
|
$title = trim($title);
|
||
|
$renderer->header($title, $level, 0);
|
||
|
} else {
|
||
|
$renderer->doc .= $text;
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
case DOKU_LEXER_EXIT :
|
||
|
$renderer->doc .= "</div></div>"; //close hiddenBody and hiddenGlobal
|
||
|
if ( array_pop($this->editableBlocks) ){
|
||
|
$renderer->finishSectionEdit($data['bytepos_end']);
|
||
|
}
|
||
|
break;
|
||
|
}
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
if ($mode == 'odt') {
|
||
|
if ($data['state'] == DOKU_LEXER_UNMATCHED && $data['type'] != 'switch') {
|
||
|
$renderer->doc .= $renderer->_xmlEntities($data['text']);
|
||
|
}
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
return false;
|
||
|
} // render()
|
||
|
|
||
|
private function _exportingPDF(){
|
||
|
global $ACT;
|
||
|
return ($ACT == 'export_pdf' || $ACT == 'export_pdfbook' || $ACT == 'export_odt');
|
||
|
}
|
||
|
|
||
|
var $editableBlocks = array();
|
||
|
|
||
|
} // class syntax_plugin_nspages
|