1<?php 2 3namespace dokuwiki\plugin\filelist; 4 5class Output 6{ 7 /** @var \Doku_Renderer */ 8 protected $renderer; 9 10 /** @var string */ 11 protected $basedir; 12 13 /** @var string */ 14 protected $webdir; 15 16 /** @var array */ 17 protected $files; 18 19 20 public function __construct(\Doku_Renderer $renderer, $basedir, $webdir, $files) 21 { 22 $this->renderer = $renderer; 23 $this->basedir = $basedir; 24 $this->webdir = $webdir; 25 $this->files = $files; 26 } 27 28 public function renderAsList($params) 29 { 30 if ($this->renderer instanceof \Doku_Renderer_xhtml) { 31 $this->renderer->doc .= '<div class="filelist-plugin">'; 32 } 33 34 $this->renderListItems($this->files, $params); 35 36 if ($this->renderer instanceof \Doku_Renderer_xhtml) { 37 $this->renderer->doc .= '</div>'; 38 } 39 } 40 41 /** 42 * Renders the files as a table, including details if configured that way. 43 * 44 * @param array $params the parameters of the filelist call 45 */ 46 public function renderAsTable($params) 47 { 48 if ($this->renderer instanceof \Doku_Renderer_xhtml) { 49 $this->renderer->doc .= '<div class="filelist-plugin">'; 50 } 51 52 $items = $this->flattenResultTree($this->files); 53 $this->renderTableItems($items, $params); 54 55 if ($this->renderer instanceof \Doku_Renderer_xhtml) { 56 $this->renderer->doc .= '</div>'; 57 } 58 } 59 60 61 /** 62 * Renders the files as a table, including details if configured that way. 63 * 64 * @param array $params the parameters of the filelist call 65 */ 66 protected function renderTableItems($items, $params) 67 { 68 69 $renderer = $this->renderer; 70 71 72 // count the columns 73 $columns = 1; 74 if ($params['showsize']) { 75 $columns++; 76 } 77 if ($params['showdate']) { 78 $columns++; 79 } 80 81 $renderer->table_open($columns); 82 83 if ($params['tableheader']) { 84 $renderer->tablethead_open(); 85 $renderer->tablerow_open(); 86 87 $renderer->tableheader_open(); 88 $renderer->cdata($this->getLang('filename')); 89 $renderer->tableheader_close(); 90 91 if ($params['showsize']) { 92 $renderer->tableheader_open(); 93 $renderer->cdata($this->getLang('filesize')); 94 $renderer->tableheader_close(); 95 } 96 97 if ($params['showdate']) { 98 $renderer->tableheader_open(); 99 $renderer->cdata($this->getLang('lastmodified')); 100 $renderer->tableheader_close(); 101 } 102 103 $renderer->tablerow_close(); 104 $renderer->tablethead_close(); 105 } 106 107 $renderer->tabletbody_open(); 108 foreach ($items as $item) { 109 $renderer->tablerow_open(); 110 $renderer->tablecell_open(); 111 $this->renderItemLink($item, $params['randlinks']); 112 $renderer->tablecell_close(); 113 114 if ($params['showsize']) { 115 $renderer->tablecell_open(1, 'right'); 116 $renderer->cdata(filesize_h($item['size'])); 117 $renderer->tablecell_close(); 118 } 119 120 if ($params['showdate']) { 121 $renderer->tablecell_open(); 122 $renderer->cdata(dformat($item['mtime'])); 123 $renderer->tablecell_close(); 124 } 125 126 $renderer->tablerow_close(); 127 } 128 $renderer->tabletbody_close(); 129 $renderer->table_close(); 130 } 131 132 133 /** 134 * Recursively renders a tree of files as list items. 135 * 136 * @param array $items the files to render 137 * @param array $params the parameters of the filelist call 138 * @param int $level the level to render 139 * @return void 140 */ 141 protected function renderListItems($items, $params, $level = 1) 142 { 143 if ($params['style'] == 'olist') { 144 $this->renderer->listo_open(); 145 } else { 146 $this->renderer->listu_open(); 147 } 148 149 foreach ($items as $file) { 150 if ($file['children'] === false && $file['treesize'] === 0) continue; // empty directory 151 152 $this->renderer->listitem_open($level); 153 $this->renderer->listcontent_open(); 154 155 if ($file['children'] !== false && $file['treesize'] > 0) { 156 // render the directory and its subtree 157 $this->renderer->cdata($file['name']); 158 $this->renderListItems($file['children'], $params, $level + 1); 159 } elseif ($file['children'] === false) { 160 // render the file link 161 $this->renderItemLink($file, $params['randlinks']); 162 163 // render filesize 164 if ($params['showsize']) { 165 $this->renderer->cdata($params['listsep'] . filesize_h($file['size'])); 166 } 167 // render lastmodified 168 if ($params['showdate']) { 169 $this->renderer->cdata($params['listsep'] . dformat($file['mtime'])); 170 } 171 } 172 173 $this->renderer->listcontent_close(); 174 $this->renderer->listitem_close(); 175 } 176 177 if ($params['style'] == 'olist') { 178 $this->renderer->listo_close(); 179 } else { 180 $this->renderer->listu_close(); 181 } 182 } 183 184 protected function renderItemLink($item, $cachebuster = false) 185 { 186 if ($this->renderer instanceof \Doku_Renderer_xhtml) { 187 $this->renderItemLinkXHTML($item, $cachebuster); 188 } else { 189 $this->renderItemLinkAny($item, $cachebuster); 190 } 191 } 192 193 /** 194 * Render a file link on the XHTML renderer 195 */ 196 protected function renderItemLinkXHTML($item, $cachebuster = false) 197 { 198 global $conf; 199 /** @var \Doku_Renderer_xhtml $renderer */ 200 $renderer = $this->renderer; 201 202 //prepare for formating 203 $link['target'] = $conf['target']['extern']; 204 $link['style'] = ''; 205 $link['pre'] = ''; 206 $link['suf'] = ''; 207 $link['more'] = ''; 208 $link['url'] = $this->itemWebUrl($item, $cachebuster); 209 $link['name'] = $item['name']; 210 $link['title'] = $renderer->_xmlEntities($link['url']); 211 if ($conf['relnofollow']) $link['more'] .= ' rel="nofollow"'; 212 [$ext,] = mimetype(basename($item['local'])); 213 $link['class'] = 'media mediafile mf_' . $ext; 214 $renderer->doc .= $renderer->_formatLink($link); 215 } 216 217 /** 218 * Render a file link on any Renderer 219 * @param array $item 220 * @param bool $cachebuster 221 * @return void 222 */ 223 protected function renderItemLinkAny($item, $cachebuster = false) 224 { 225 $this->renderer->externalmedialink($this->itemWebUrl($item, $cachebuster), $item['name']); 226 } 227 228 /** 229 * Construct the Web URL for a given item 230 * 231 * @param array $item The item data as returned by the Crawler 232 * @param bool $cachbuster add a cachebuster to the URL? 233 * @return string 234 */ 235 protected function itemWebUrl($item, $cachbuster = false) 236 { 237 if (str_ends_with($this->webdir, '=')) { 238 $url = $this->webdir . rawurlencode($item['local']); 239 } else { 240 $url = $this->webdir . $item['local']; 241 } 242 243 if ($cachbuster) { 244 if (strpos($url, '?') === false) { 245 $url .= '?t=' . $item['mtime']; 246 } else { 247 $url .= '&t=' . $item['mtime']; 248 } 249 } 250 return $url; 251 } 252 253 /** 254 * Flattens the filelist by recursively walking through all subtrees and 255 * merging them with a prefix attached to the filenames. 256 * 257 * @param array $items the tree to flatten 258 * @param string $prefix the prefix to attach to all processed nodes 259 * @return array a flattened representation of the tree 260 */ 261 protected function flattenResultTree($items, $prefix = '') 262 { 263 $result = []; 264 foreach ($items as $file) { 265 if ($file['children'] !== false) { 266 $result = array_merge( 267 $result, 268 $this->flattenResultTree($file['children'], $prefix . $file['name'] . '/') 269 ); 270 } else { 271 $file['name'] = $prefix . $file['name']; 272 $result[] = $file; 273 } 274 } 275 return $result; 276 } 277 278 protected function getLang($key) 279 { 280 $syntax = plugin_load('syntax', 'filelist'); 281 return $syntax->getLang($key); 282 } 283} 284