1<?php 2/** 3 * Embed an image gallery 4 * 5 * @license GPL 2 (http://www.gnu.org/licenses/gpl.html) 6 * @author Andreas Gohr <andi@splitbrain.org> 7 * @author Joe Lapp <joe.lapp@pobox.com> 8 * @author Dave Doyle <davedoyle.canadalawbook.ca> 9 * @author Gerry Weissbach <gerry.w@gammaproduction.de> 10 */ 11 12if(!defined('DOKU_INC')) define('DOKU_INC',realpath(dirname(__FILE__).'/../../').'/'); 13if(!defined('DOKU_PLUGIN')) define('DOKU_PLUGIN',DOKU_INC.'lib/plugins/'); 14require_once(DOKU_PLUGIN.'syntax.php'); 15require_once(DOKU_INC.'inc/search.php'); 16require_once(DOKU_INC.'inc/JpegMeta.php'); 17 18class syntax_plugin_gallery extends DokuWiki_Syntax_Plugin { 19 /** 20 * return some info 21 */ 22 function getInfo(){ 23 return array( 24 'author' => 'Andreas Gohr', 25 'email' => 'andi@splitbrain.org', 26 'date' => '2007-11-06', 27 'name' => 'Gallery Plugin', 28 'desc' => 'Creates a gallery of images from a namespace', 29 'url' => 'http://wiki.splitbrain.org/plugin:gallery', 30 ); 31 } 32 33 /** 34 * What kind of syntax are we? 35 */ 36 function getType(){ 37 return 'substition'; 38 } 39 40 /** 41 * What about paragraphs? 42 */ 43 function getPType(){ 44 return 'block'; 45 } 46 47 /** 48 * Where to sort in? 49 */ 50 function getSort(){ 51 return 301; 52 } 53 54 55 /** 56 * Connect pattern to lexer 57 */ 58 function connectTo($mode) { 59 $this->Lexer->addSpecialPattern('\{\{gallery>[^}]*\}\}',$mode,'plugin_gallery'); 60 } 61 62 63 /** 64 * Parse option 65 */ 66 function parseOpt($params, $name) { 67 if(preg_match('/\b'.$name.'\b/i',$params,$match)) { 68 return true; 69 }else if(preg_match('/\bno'.$name.'\b/i',$params,$match)) { 70 return false; 71 }else{ 72 return $this->getConf($name); 73 } 74 } 75 76 /** 77 * Handle the match 78 */ 79 function handle($match, $state, $pos, &$handler){ 80 $match = substr($match,10,-2); //strip markup from start and end 81 82 $data = array(); 83 84 //handle params 85 list($ns,$params) = explode('?',$match,2); 86 87 if ( substr($ns, 0, 1) == ' ' ) 88 $data['float']="right"; 89 else if ( substr($ns, -1) == ' ' ) 90 $data['float']="left"; 91 else 92 $data['float'] = null; 93 94 //namespace 95 $data['ns'] = $ns; 96 97 //max thumb dimensions 98 if(preg_match('/\b(\d+)x(\d+)\b/',$params,$match)){ 99 $data['w'] = $match[1]; 100 $data['h'] = $match[2]; 101 }else{ 102 $data['w'] = $this->getConf('thumbnail_width'); 103 $data['h'] = $this->getConf('thumbnail_height'); 104 } 105 106 //max lightbox dimensions 107 if(preg_match('/\b(\d+)X(\d+)\b/',$params,$match)){ 108 $data['w_lightbox'] = $match[1]; 109 $data['h_lightbox'] = $match[2]; 110 }else{ 111 $data['w_lightbox'] = $this->getConf('image_width'); 112 $data['h_lightbox'] = $this->getConf('image_height'); 113 } 114 115 //number of images per row 116 if(preg_match('/\b(\d+)\b/i',$params,$match)){ 117 $data['cols'] = $match[1]; 118 }else{ 119 $data['cols'] = $this->getConf('cols'); 120 } 121 122 //show the filename 123 $data['showname'] = $this->parseOpt($params, 'showname'); 124 125 //lightbox style? 126 $data['lightbox'] = $this->parseOpt($params, 'lightbox'); 127 128 //direct linking? 129 if($data['lightbox']) { 130 $data['direct'] = true; //implicit direct linking 131 }else{ 132 $data['direct'] = $this->parseOpt($params, 'direct'); 133 } 134 135 //reverse sort? 136 $data['reverse'] = $this->parseOpt($params, 'reverse'); 137 138 //resize thing? 139 if(preg_match('/\bnoresize\b/i',$params,$match)) { 140 $data['noresize'] = true; 141 }else{ 142 $data['noresize'] = false; 143 } 144 145 //Layout thing? 146 if(preg_match('/\bmagazine\b/i',$params,$match)) { 147 $data['magazine'] = true; 148 }else{ 149 $data['magazine'] = false; 150 } 151 152 //Layout thing? 153 if(preg_match('/\bdiashow\b/i',$params,$match)) { 154 $data['diashow'] = true; 155 }else{ 156 $data['diashow'] = false; 157 } 158 159 //Layout thing? 160 if(preg_match('/\bpageAmount=(\d+)\b/i',$params,$match)) { 161 $data['pageAmount'] = $match[1]; 162 }else{ 163 $data['pageAmount'] = -1; 164 } 165 166 return $data; 167 } 168 169 /** 170 * Create output 171 */ 172 function render($mode, &$renderer, $data) { 173 if ( $data['pageAmount'] > 0 ) $renderer->info['cache'] = FALSE; 174 175 if($mode == 'xhtml'){ 176 $renderer->doc .= $this->_gallery($data); 177 return true; 178 } 179 return false; 180 } 181 182 /** 183 * Does the gallery formatting 184 */ 185 function _gallery($data){ 186 global $conf; 187 global $lang; 188 $ret = ''; 189 190 //use the search to get all files 191 $ns = cleanID($data['ns']); 192 $dir = utf8_encodeFN(str_replace(':','/',$ns)); 193 $files = array(); 194 search($files,$conf['mediadir'],'search_media',array(),$dir); 195 196 //anything found? 197 if(!count($files)){ 198 $ret .= '<div class="nothing">'.$lang['nothingfound'].'</div>'; 199 return $ret; 200 } 201 202 //reverse if wanted 203 if($data['reverse']) rsort($files); 204 205 //startPoint of Pages 206 $startPoint = intval($_REQUEST['startPoint']); 207 208 209 // build magazine 210 if ($data['magazine']) 211 { 212 require_once(realpath(dirname(__FILE__)).'/inc/magazinelayout.class.php'); 213 214 $template = '<img src="/lib/plugins/gallery/inc/image.php?size=[size]&file=[image]" alt="" />'; 215 $mag = new magazinelayout($data['w'], $data['h']!=120?$data['h']:5, $template); 216 $cols = $data['cols']; 217 $cols = $cols > 8 ? 8 : $cols; 218 219// $content = '<div class="gallery">'; 220 221 $amount = 0; 222 foreach($files as $img){ 223 if(!$img['isimg']) continue; 224 $amount ++; 225 if ( $amount < $startPoint ) continue; 226 if ( $data['pageAmount'] > 0 && $amount-$startPoint >= $data['pageAmount'] ) break; 227 228 $img['lightbox'] = $data['lightbox']; 229 $img['h_lightbox'] = $data['h_lightbox']; 230 $img['w_lightbox'] = $data['w_lightbox']; 231 $img['direct'] = $data['direct']; 232 $img['float'] = $data['float']; 233 234 $mag->addImage($img); 235 236 $cols --; 237 if ($cols <= 0 ) 238 { 239 $content .= $mag->getHtml(); 240 $mag = new magazinelayout($data['w'], $data['h']!=120?$data['h']:5, $template); 241 $cols = $data['cols']; 242 } 243 244 } 245 246 if ($mag->_numimages > 0) $content .= $mag->getHtml(); 247 248// $content .= '<br style="clear:both" /></div></div></div>'; 249 250 $content .= $this->_pageSelect(count($files), $data['pageAmount'], $startPoint); 251 return $content; 252 } 253 254 255 // build gallery 256 if($data['cols'] > 0){ // format as table 257 $ret .= '<table class="gallery"' . (!empty($data['float']) ? ' style="float: '.$data['float'].';"' : '') . '>'; 258 $i = 0; 259 $amount = 0; 260 foreach($files as $img){ 261 if(!$img['isimg']) continue; 262 $amount ++; 263 if ( $amount < $startPoint ) continue; 264 if ( $data['pageAmount'] > 0 && $amount-$startPoint >= $data['pageAmount'] ) break; 265 266 if($i == 0){ 267 $ret .= '<tr>'; 268 } 269 270 $ret .= '<td>'; 271 $ret .= $this->_image($img,$data); 272 $ret .= $this->_showname($img,$data); 273 $ret .= '</td>'; 274 275 $i++; 276 277 $close_tr = true; 278 if($i == $data['cols']){ 279 $ret .= '</tr>'; 280 $close_tr = false; 281 $i = 0; 282 } 283 } 284 285 if ($close_tr){ 286 // add remaining empty cells 287 for(;$i < $data['cols']; $i++){ 288 $ret .= '<td></td>'; 289 } 290 $ret .= '</tr>'; 291 } 292 293 $ret .= '</table>'; 294 }else{ // format as div sequence 295 $ret .= '<div class="gallery"' . (!empty($data['float']) ? ' style="float: '.$data['float'].';"' : '') . '>'; 296 297 $amount = 0; 298 foreach($files as $img){ 299 if(!$img['isimg']) continue; 300 $amount ++; 301 if ( $amount < $startPoint ) continue; 302 if ( $data['pageAmount'] > 0 && $amount-$startPoint >= $data['pageAmount'] ) break; 303 304 $ret .= '<div>'; 305 $ret .= $this->_image($img,$data); 306 $ret .= $this->_showname($img,$data); 307 $ret .= '</div> '; 308 } 309 310 $ret .= '<br style="clear:both" /></div>'; 311 } 312 313 $ret .= $this->_pageSelect(count($files), $data['pageAmount'], $startPoint); 314 return $ret; 315 } 316 317 /** 318 * Defines how a thumbnail should look like 319 */ 320 function _image($img,$data){ 321 global $ID; 322 323 $w = $img['meta']->getField('File.Width'); 324 $h = $img['meta']->getField('File.Height'); 325 $dim = array(); 326 327 if ( $data['noresize']) 328 { 329 $w = $data['w']; 330 $h = $data['h']; 331 } 332 else if($w > $data['w'] || $h > $data['h']){ 333 $ratio = $img['meta']->getResizeRatio($data['w'],$data['h']); 334 $w = floor($w * $ratio); 335 $h = floor($h * $ratio); 336 $dim = array('w'=>$w,'h'=>$h); 337 } 338 339 //prepare img attributes 340 $i = array(); 341 $i['width'] = $w; 342 $i['height'] = $h; 343 $i['border'] = 0; 344 $i['alt'] = $img['meta']->getField('Simple.Title'); 345 $i['class'] = 'tn'; 346 $iatt = buildAttributes($i); 347 $src = ml($img['id'],$dim); 348 349 // prepare lightbox dimensions 350 $w_lightbox = $img['meta']->getField('File.Width'); 351 $h_lightbox = $img['meta']->getField('File.Height'); 352 $dim_lightbox = array(); 353 if($w_lightbox > $data['w_lightbox'] || $h_lightbox > $data['h_lightbox']){ 354 $ratio = $img['meta']->getResizeRatio($data['w_lightbox'],$data['h_lightbox']); 355 $w_lightbox = floor($w_lightbox * $ratio); 356 $h_lightbox = floor($h_lightbox * $ratio); 357 $dim_lightbox = array('w'=>$w_lightbox,'h'=>$h_lightbox); 358 } 359 360 //prepare link attributes 361 $a = array(); 362 $a['title'] = $img['meta']->getField('Simple.Title'); 363 if($data['lightbox']){ 364 $href = ml($img['id'],$dim_lightbox); 365 $a['class'] = "lightbox JSnocheck"; 366 $a['rel'] = "lightbox"; 367 }else{ 368 $href = ml($img['id'],array('id'=>$ID),$data['direct']); 369 } 370 $aatt = buildAttributes($a); 371 372 // prepare output 373 $ret = ''; 374 $ret .= '<a href="'.$href.'" '.$aatt.'>'; 375 $ret .= '<img src="'.$src.'" '.$iatt.' />'; 376 $ret .= '</a>'; 377 return $ret; 378 } 379 380 381 /** 382 * Defines how a filename + link should look 383 */ 384 function _showname($img,$data){ 385 global $ID; 386 387 if(!$data['showname']) { return ''; } 388 389 //prepare link 390 $lnk = ml($img['id'],array('id'=>$ID),false); 391 392 // prepare output 393 $ret = ''; 394 $ret .= '<br /><a href="'.$lnk.'">'; 395 $ret .= $img['file']; // see fix posted on the wiki 396 $ret .= '</a>'; 397 return $ret; 398 } 399 400 function _pageSelect($fileCount, $showCount, $startPoint) 401 { 402 global $ID; 403 $content = '<div id="pageSelect">'; 404 405 $pages = ceil($fileCount / $showCount); 406 if ( $pages <= 1 ) return ""; 407 408 for ($i=0; $i<$pages; $i++) 409 { 410 $lnk = wl($ID, array('startPoint'=>$i*$showCount)); 411 $content .= '<a href="' . $lnk . '">'; 412 $content .= $i+1; 413 $content .= '</a>'; 414 415 if ( $i < $pages -1 ) 416 $content .= ' - '; 417 } 418 419 $content .= '</div>'; 420 return $content; 421 } 422} 423 424//Setup VIM: ex: et ts=4 enc=utf-8 : 425