1<?php 2/** 3 * CSV Plugin: displays a cvs formatted file or inline data as a table 4 * 5 * @license GPL 2 (http://www.gnu.org/licenses/gpl.html) 6 * @author Steven Danz <steven-danz@kc.rr.com> 7 * @author Gert 8 * @author Andreas Gohr <gohr@cosmocode.de> 9 * @author Jerry G. Geiger <JerryGeiger@web.de> 10 */ 11 12/** 13 * Display CSV data as table 14 */ 15class syntax_plugin_csv_table extends DokuWiki_Syntax_Plugin 16{ 17 18 /** @inheritdoc */ 19 public function getType() 20 { 21 return 'substition'; 22 } 23 24 /** @inheritdoc */ 25 public function getSort() 26 { 27 return 155; 28 } 29 30 /** @inheritdoc */ 31 public function getPType() 32 { 33 return 'block'; 34 } 35 36 /** @inheritdoc */ 37 public function connectTo($mode) 38 { 39 $this->Lexer->addSpecialPattern('<csv[^>]*>.*?(?:<\/csv>)', $mode, 'plugin_csv_table'); 40 } 41 42 /** @inheritdoc */ 43 public function handle($match, $state, $pos, Doku_Handler $handler) 44 { 45 $match = substr($match, 4, -6); // <csv ... </csv> 46 47 list($optstr, $content) = explode('>', $match, 2); 48 $opt = helper_plugin_csv::parseOptions($optstr); 49 $opt['content'] = $content; 50 51 return $opt; 52 } 53 54 /** @inheritdoc */ 55 public function render($mode, Doku_Renderer $renderer, $opt) 56 { 57 if ($mode == 'metadata') return false; 58 59 // load file data 60 if ($opt['file']) { 61 try { 62 $opt['content'] = helper_plugin_csv::loadContent($opt['file']); 63 if (!media_ispublic($opt['file'])) $renderer->info['cache'] = false; 64 } catch (\Exception $e) { 65 $renderer->cdata($e->getMessage()); 66 return true; 67 } 68 } 69 70 // check if there is content 71 $content =& $opt['content']; 72 $content = trim($content); 73 if ($content === '') { 74 $renderer->cdata('No csv data found'); 75 return true; 76 } 77 78 $data = helper_plugin_csv::prepareData($content, $opt); 79 80 if (empty($data)) { 81 $message = $this->getLang('no_result'); 82 $renderer->cdata($message); 83 return true; 84 } 85 86 $maxcol = count($data[0]); 87 $line = 0; 88 89 // render 90 $renderer->table_open($maxcol, count($data)); 91 // Open thead or tbody 92 ($opt['hdr_rows']) ? $renderer->tablethead_open() : $renderer->tabletbody_open(); 93 foreach ($data as $row) { 94 // close thead yet? 95 if ($line > 0 && $line == $opt['hdr_rows']) { 96 $renderer->tablethead_close(); 97 $renderer->tabletbody_open(); 98 } 99 $renderer->tablerow_open(); 100 for ($i = 0; $i < $maxcol;) { 101 $span = 1; 102 // lookahead to find spanning cells 103 if ($opt['span_empty_cols']) { 104 for ($j = $i + 1; $j < $maxcol; $j++) { 105 if ($row[$j] === '') { 106 $span++; 107 } else { 108 break; 109 } 110 } 111 } 112 113 // open cell 114 if ($line < $opt['hdr_rows'] || $i < $opt['hdr_cols']) { 115 $renderer->tableheader_open($span); 116 } else { 117 $renderer->tablecell_open($span); 118 } 119 120 // print cell content, call linebreak() for newlines 121 $lines = explode("\n", $row[$i]); 122 $cnt = count($lines); 123 for ($k = 0; $k < $cnt; $k++) { 124 $renderer->cdata($lines[$k]); 125 if ($k < $cnt - 1) $renderer->linebreak(); 126 } 127 128 // close cell 129 if ($line < $opt['hdr_rows'] || $i < $opt['hdr_cols']) { 130 $renderer->tableheader_close(); 131 } else { 132 $renderer->tablecell_close(); 133 } 134 135 $i += $span; 136 } 137 $renderer->tablerow_close(); 138 $line++; 139 } 140 // if there was a tbody, close it 141 if ($opt['hdr_rows'] < $line) $renderer->tabletbody_close(); 142 $renderer->table_close(); 143 144 return true; 145 } 146 147} 148