syntax.php 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231
  1. <?php
  2. /**
  3. * @file progrecss/syntax.php
  4. * @brief DokuWiki Progress bars using CSS.
  5. * @license GPL 2 (http://www.gnu.org/licenses/gpl.html)
  6. * @author Luis Machuca Bezzaza <luis [dot] machuca [at] gulix [dot] cl>
  7. * @version 1.9 (Mar 2018)
  8. * @date 2018-03-27
  9. *
  10. * For a live demo check the instructions on the plugin's wiki page.
  11. *
  12. * Greetings.
  13. * - Luis Machuca Bezzaza.
  14. */
  15. if(!defined('DW_LF')) define('DW_LF',"\n");
  16. if(!defined('DOKU_INC'))
  17. define('DOKU_INC',realpath(dirname(__FILE__).'/../../').'/');
  18. if(!defined('DOKU_PLUGIN'))
  19. define('DOKU_PLUGIN',DOKU_INC.'lib/plugins/');
  20. require_once(DOKU_PLUGIN.'syntax.php');
  21. /**
  22. * All DokuWiki plugins to extend the parser/rendering mechanism
  23. * need to inherit from this class
  24. */
  25. class syntax_plugin_progrecss extends DokuWiki_Syntax_Plugin {
  26. function getType(){
  27. return 'formatting';
  28. }
  29. function getAllowedTypes() {
  30. return array('substition', 'formatting', 'disabled');
  31. }
  32. function getSort(){
  33. return 550;
  34. }
  35. function getPType(){
  36. return 'normal';
  37. }
  38. function connectTo($mode) {
  39. $p_param= ".*?";
  40. // option 1: a percentage (eg.: "45%")
  41. $this->Lexer->addSpecialPattern (
  42. "<progrecss (?:[0-9]{1,2}|100)% $p_param/>",
  43. $mode, 'plugin_progrecss');
  44. // option 2: a fraction (eg.: "13/57")
  45. $this->Lexer->addSpecialPattern (
  46. "<progrecss (?:\d+/\d+) $p_param/>",
  47. $mode, 'plugin_progrecss');
  48. }
  49. /**
  50. * Handle the match
  51. */
  52. function handle($match, $state, $pos, Doku_Handler $handler) {
  53. // function handle($match, $state, $pos, &$handler){
  54. /* The syntax is expected as follows:
  55. ppp% [param1=value1; [param2=value2; [...]]]
  56. */
  57. $data= array();
  58. static $progrecss_count= 0;
  59. static $expected_params= array(
  60. "caption", /* caption: can contain formatting wikitext, or be empty. */
  61. "style", /* style: must be empty or a value defined as a user style. */
  62. "width", /* width: must be a valid CSS expression for width, except in pt. */
  63. "order", /* order: the percentage value appears before, inside (default) or after the bar */
  64. "marker", /* reserved for future use */
  65. "pdisplay" /* pdisplay: sprintf() format for the percentage value */
  66. );
  67. /* OK, so let's strip the markup, taking first the precentage%
  68. value which is _mandatory_. */
  69. $match = substr($match,11,-2); // Strip markup
  70. $match= explode(' ', $match, 2);
  71. /* That already done, let's split all other elements, which are
  72. expected to be in the 'param=value;' format. We must
  73. take into consideration 'escaped' semicolons. */
  74. $elems= preg_split('/(?<!\\\\);/', $match[1]);
  75. foreach ($elems as $pair) {
  76. list($key,$value)= explode('=', $pair, 2);
  77. trim($key); trim($value);
  78. /* we check if the param is valid (exists in 'expected_params'),
  79. otherwise we just choose to ignore it.
  80. (yes, something better could've been done) */
  81. if (in_array($key, $expected_params) ) { //accept parameter
  82. $data[$key]= $value;
  83. } else { //refuse parameter
  84. }
  85. }
  86. /* Sanitize the 'order' parameter */
  87. if (!preg_match('/(before|inside|after)/', $data['order'] ) )
  88. $data['order'] = 'inside';
  89. /* At this point, if any of the available parameters was
  90. not found, let's apply some sane default. */
  91. //if (empty($data['caption']) ) $data['caption']= "";
  92. if (empty($data['style']) ) $data['style']= "default";
  93. if (empty($data['width']) ) $data['width']= "100px";
  94. if (empty($data['pdisplay'])) $data['pdisplay']= $this->getConf('percent_format');
  95. $data['style']= "progrecss_". $data['style'];
  96. /* If 'p' is of the form 'x/y', convert it to an approximate percentage
  97. */
  98. $p= $match[0];
  99. if (preg_match('/\d+\/\d+/', $p) ) {
  100. $plist= explode('/', $p, 2);
  101. // if fraction is too large, we just consider it 100%
  102. $p[0] = min($p[0], $p[1]);
  103. $p = intval($plist[0]*100/$plist[1]);
  104. $data['f'] = $plist[0]. $this->getConf('fraction_divisor'). $plist[1];
  105. }
  106. else {
  107. $data['f'] = sprintf($data['pdisplay'].'%%', intval($p));
  108. }
  109. $data['p']= intval($p);
  110. // Else p should be in the form '\d+' as required by the regex
  111. /* In order to somewhat uniquely IDfy each p-bar,
  112. let's use a counter...
  113. Why didn't I think of that before? */
  114. $IDnum= sprintf("progrecss_id_%03d",
  115. $progrecss_count);
  116. /* Did I mention that this generates correlative IDs */
  117. $data['id']= $IDnum;
  118. $progrecss_count= $progrecss_count+1;
  119. /* Are we ready yet? */
  120. return $data;
  121. }
  122. /**
  123. * Create output
  124. */
  125. function render($mode, Doku_Renderer $renderer, $data) {
  126. //function render($mode, &$renderer, $data) {
  127. static $counter= 0;
  128. $percentage= intval($data['p']);
  129. $fmted_p = $data['f'];
  130. $id= $data['id'];
  131. $fullwidth= $data['width'];
  132. $caption= $data['caption'];
  133. $style= $data['style'];
  134. $where= $data['order'];
  135. if($mode == 'xhtml'){
  136. /* each progrecssbar is enclosed in a SPAN package,
  137. classed according to "style" parameter,
  138. and IDed in a somewhat-unique manner using both caption
  139. and random binary toughts. */
  140. $renderer->doc .= $this->_create_block_header(
  141. $id, $style, $fullwidth);
  142. $renderer->doc .= '<span class="border" style="width: '.
  143. $fullwidth. ';">';
  144. /* The next function contains the actual "intelligence" behind
  145. the plugin. The rest is simply "ability".*/
  146. $renderer->doc .= $this->_place_percentage($percentage, $fmted_p, $where);
  147. $renderer->doc .= DW_LF;
  148. /* See? A PHP+CSS is as powerful as... */
  149. $renderer->doc .= '&nbsp;</span>'. DW_LF;
  150. if (!empty($caption)) $renderer->doc .= $this->_render_caption($caption);
  151. $renderer->doc .= $this->_create_block_footer($id);
  152. return true;
  153. }
  154. if($mode == 'text'){
  155. // simply output the percentage in a text renderer
  156. $renderer->doc .= ' ['. $fmted_p;
  157. if (!empty ($caption) ) {
  158. $renderer->doc .= ' | '. $caption;
  159. }
  160. $renderer->doc.= ' ]'. DW_LF;
  161. return true;
  162. } // done with the text renderer
  163. return false;
  164. }
  165. /*
  166. * From this point on, all are local functions
  167. */
  168. function _create_block_header($id, $style, $fullwidth) {
  169. $wt = DW_LF. '<!-- begin: progrecss bar \''. $id. '\'. -->'. DW_LF;
  170. $wt = '<span id="'. $id. '" class="'. $style. '" >';
  171. return $wt;
  172. }
  173. function _create_block_footer($id) {
  174. $wt = '</span>';
  175. $wt .= DW_LF. '<!-- end of progrecss bar \''. $id. '\'. -->'. DW_LF;
  176. return $wt;
  177. }
  178. function _render_caption($caption) {
  179. $wt = '<span class="caption">';
  180. $wt .= p_render('xhtml', p_get_instructions($caption), $info);
  181. $wt = str_replace('<p>', '', $wt);
  182. $wt = str_replace('</p>', '', $wt);
  183. $wt = trim($wt);
  184. $wt .= '</span>';
  185. return $wt;
  186. }
  187. /*
  188. not used yet.
  189. percentage position:
  190. before --> [20% | ]
  191. inside --> [ 25% | ]
  192. after --> [ | 30%]
  193. */
  194. function _place_percentage ($pv, $p, $where) {
  195. if ($where==='before') $wt.= $p;
  196. $wt.= ' <span class="bar '. $where. '" style="width: '.$pv. '%;">';
  197. if ($where==='inside') $wt.= $p;
  198. $wt.= '</span> ';
  199. if ($where==='after') $wt.= $p;
  200. return $wt;
  201. }
  202. }
  203. // end, we are happy now