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