1<?php 2/** 3 * DokuWiki Plugin directorylist (Syntax Component) 4 * 5 * @author alexwenzel <alexander.wenzel.berlin@gmail.com> 6 */ 7 8// must be run within Dokuwiki 9if (!defined('DOKU_INC')) die(); 10 11class Syntax_Plugin_Directorylist_Directorylist extends DokuWiki_Syntax_Plugin 12{ 13 /** 14 * Doku_Renderer 15 * @var Doku_Renderer 16 */ 17 private $renderer; 18 19 /** 20 * @return string Syntax mode type 21 */ 22 public function getType() 23 { 24 return 'disabled'; 25 } 26 27 /** 28 * @return string Paragraph type 29 */ 30 public function getPType() 31 { 32 return 'stack'; 33 } 34 35 /** 36 * @return int Sort order - Low numbers go before high numbers 37 */ 38 public function getSort() 39 { 40 return 10; 41 } 42 43 /** 44 * Connect lookup pattern to lexer 45 * @param string $mode Parser mode 46 * @return void 47 */ 48 public function connectTo($mode) 49 { 50 $this->Lexer->addSpecialPattern('<directorylist.+?>',$mode,'plugin_directorylist_directorylist'); 51 } 52 53 /** 54 * Handle matches of the directorylist syntax 55 * @param string $match The match of the syntax 56 * @param int $state The state of the handler 57 * @param int $pos The position in the document 58 * @param Doku_Handler $handler The handler 59 * @return array Data for the renderer 60 */ 61 public function handle($match, $state, $pos, Doku_Handler $handler) 62 { 63 // default value 64 $parameters = array(); 65 66 // regex 67 preg_match_all('#(\w+)\s*=\s*"(.*?)"#', $match, $return); 68 69 if (is_array($return) && isset($return[1]) && is_array($return[1])) 70 foreach($return[1] as $index => $name) 71 { 72 $parameters[$name] = $return[2][$index]; 73 } 74 75 return $parameters; 76 } 77 78 /** 79 * Render xhtml output or metadata 80 * @param string $mode Renderer mode (supported modes: xhtml) 81 * @param Doku_Renderer $renderer The renderer 82 * @param array $data The data from the handler() function 83 * @return bool If rendering was successful. 84 */ 85 public function render($mode, Doku_Renderer $renderer, $data) 86 { 87 // do not render if not in xhtml mode 88 if($mode != 'xhtml') return false; 89 90 // safe reference 91 $this->renderer = $renderer; 92 93 try { 94 95 // check and set default: recursive argument 96 if ( ! isset($data['recursive']) || empty($data['recursive']) ) 97 $data['recursive'] = true; 98 99 // check and set default: ignore argument 100 if ( ! isset($data['ignore']) || empty($data['ignore']) ) 101 $data['ignore'] = ''; 102 103 // check and set default: fileorder argument 104 if ( ! isset($data['fileorder']) || empty($data['fileorder']) ) 105 $data['fileorder'] = 'asc'; 106 107 // check and set default: type argument 108 if ( ! isset($data['type']) || empty($data['type']) ) 109 $data['type'] = 'download'; 110 111 // check: path argument 112 if ( ! isset($data['path']) || empty($data['path']) ) 113 throw new Exception("A path is missing!"); 114 115 // get all directories and files 116 require_once "SplFileArray.php"; 117 $fs = new SplFileArray($data['path'], (bool)$data['recursive'], $data['fileorder']); 118 119 // get files 120 $files = $fs->get(); 121 122 123 // start walking down 124 $this->renderer->doc .= '<ul class="directorylist">'; 125 $this->walkDirArray( $files , $data); 126 $this->renderer->doc .= '</ul>'; 127 128 } catch (Exception $e) { 129 130 $this->renderer->doc .= '<strong>directorylist error:</strong> '; 131 $this->renderer->doc .= $e->getMessage(); 132 } 133 134 // finished 135 return true; 136 } 137 138 /** 139 * Walks down the directory array 140 * @param array $dirArray 141 * @return void 142 */ 143 private function walkDirArray(array $dirArray, array $data) 144 { 145 foreach ($dirArray as $key => $value) { 146 147 // check if is ignored 148 if ( ! $this->isIgnored($data['ignored'], $key) ) { 149 150 // check if is directory 151 if ( is_array($value) ) { 152 153 // this is the start of a new sub directory 154 $this->renderer->doc .= '<li class="folder">'.$key.'<ul>'; 155 $this->walkDirArray($value, $data); 156 $this->renderer->doc .= '</ul></li>'; 157 } 158 else if ( $value instanceof SplFileInfo ) { 159 160 // not directory, but file 161 $this->renderer->doc .= '<li class="file">'.$this->formatLink($value,$data).$this->formatBytes($value).'</li>'; 162 } 163 } 164 } 165 } 166 167 /** 168 * Returns, whether the file is ignored or not 169 * @see http://www.php.net/manual/en/function.fnmatch.php 170 * @param string $ignorePattern 171 * @param string $name 172 * @return bool 173 */ 174 private function isIgnored($ignorePattern, $name) 175 { 176 // not ignored if emtpy 177 if ( empty($ignorePattern) ) 178 return false; 179 180 // explode the ignore argument 181 $patternArray = explode(',', $ignorePattern); 182 183 // iterate through all given patterns 184 foreach ($patternArray as $pattern) { 185 186 // is there a match 187 if ( fnmatch($pattern, $name) ) 188 return true; 189 } 190 191 return false; 192 } 193 194 /** 195 * Returns the filesize for a given file 196 * @param SplFileInfo $file 197 * @param integer $precision 198 * @return string 199 */ 200 private function formatBytes(SplFileInfo $file, $precision = 2) 201 { 202 $base = log($file->getSize()) / log(1024); 203 $suffixes = array('B', 'kB', 'MB', 'GB', 'TB'); 204 205 $return = round(pow(1024, $base - floor($base)), $precision) .' '. $suffixes[floor($base)]; 206 207 return '<span class="size">'.$return.'</span>'; 208 } 209 210 211 212 213 /** 214 * Returns the link tag for a given file 215 * @param string $filepath 216 * @return string 217 */ 218 private function formatLink(SplFileInfo $file, array $data) 219 { 220 global $conf; 221 222 $link = '<a href="'; 223 if( $data['type']=='download' ) { 224 $link .= '?do=download&file='.rawurlencode($file->getRealPath()); 225 } else if( $data['type']=='direct' ) { 226 $link .= 'file://'.$file->getRealPath(); 227 } else if ($data['type']=='link'){ 228 $startpos = strpos( $file->getRealPath(), $conf['basedir'] ); 229 $link .= $conf['baseurl'].substr( $file->getRealPath(), $startpos); 230 } else { 231 $link .= ''; 232 } 233 $link .= '"'; 234 if( $data['type']=='download' ) { 235 $link .= ' target="_blank"'; 236 } 237 $link .= ' title="'.$file->getFilename().'"'; 238 $link .= '>'; 239 $link .= utf8_encode($file->getFilename()); 240 $link .= '</a>'; 241 242 return $link; 243 } 244} 245 246// vim:ts=4:sw=4:et: 247