1<?php 2/** 3 * Plugin tcycle: tiny cycle 4 * 5 * @license GPL 2 (http://www.gnu.org/licenses/gpl.html) 6 * @author Reinhard Kaeferboeck <rfk@kaeferboeck.info> 7 * @author Trailjeep <trailjeep@gmail.com> 8 */ 9 10// must be run within Dokuwiki 11if(!defined('DOKU_INC')) die(); 12 13if(!defined('DOKU_PLUGIN')) define('DOKU_PLUGIN',DOKU_INC.'lib/plugins/'); 14 15/** 16 * All DokuWiki plugins to extend the parser/rendering mechanism 17 * need to inherit from this class 18 */ 19class syntax_plugin_tcycle extends DokuWiki_Syntax_Plugin { 20 function getType(){ return 'formatting';} 21 function getPType(){ return 'normal';} 22 function getAllowedTypes() { return array('container','substition','protected','disabled','formatting','paragraphs'); } 23 function getSort(){ return 195; } 24 function connectTo($mode) { 25 $this->Lexer->addEntryPattern('<tcycle.*?>(?=.*?</tcycle>)',$mode,'plugin_tcycle'); 26 $this->Lexer->addPattern('\{\{.*\}\}','plugin_tcycle'); 27 } 28 function postConnect() { $this->Lexer->addExitPattern('</tcycle>','plugin_tcycle'); } 29 30 /** 31 * Handle the match 32 */ 33 function handle($match, $state, $pos, Doku_Handler $handler) { 34 switch($state) { 35 case DOKU_LEXER_ENTER: 36 $attributes = strtolower(substr($match, 5, -1)); 37 $dataspeed = $this->_getAttribute($attributes, "data-speed", $this->getConf('data-speed')); 38 $datafx = $this->_getAttribute($attributes, "data-fx", $this->getConf('data-fx')); 39 if (!in_array($datafx, array('scroll', 'fade'))) { $datafx = $this->getConf('data-fx'); } 40 $datatimeout = $this->_getAttribute($attributes, "data-timeout", $this->getConf('data-timeout')); 41 $width = $this->_getAttribute($attributes, "width", $this->getConf('width')); 42 $height = $this->_getAttribute($attributes, "height", $this->getConf('height')); 43 $namespace = $this->_getAttribute($attributes, "namespace", $this->getConf('namespace')); 44 if ($namespace === 1) { 45 $namespace = str_replace(':', '/', getNS(cleanID(getID()))); 46 } elseif ($namespace !== 0) { 47 $namespace = str_replace(':', '/', $namespace); 48 } 49 $metadata = $this->_getAttribute($attributes, "metadata", $this->getConf('metadata')); 50 $objectfit = $this->_getAttribute($attributes, "fit", $this->getConf('fit')); 51 if (!in_array($objectfit, array('fill','contain','cover','scale-down','none'))) { $objectfit = $this->getConf('fit'); } 52 return array($state, array($dataspeed, $datafx, $datatimeout, $width, $height, $namespace, $metadata, $objectfit)); 53 case DOKU_LEXER_MATCHED: 54 global $conf; 55 $addimgs = trim($match); 56 $addimgs = preg_replace('/\{\{ ?:?/', $conf['mediadir'].'/', $addimgs); 57 $addimgs = preg_replace('/\?.*\}\}/', '', $addimgs); 58 $addimgs = preg_replace('/\| ?.*?\}\}/', '', $addimgs); 59 $addimgs = str_replace(':', '/', $addimgs); 60 $addimgs = preg_split('/\s+/', $addimgs); 61 return array($state, array($addimgs)); 62 case DOKU_LEXER_UNMATCHED: 63 return array($state, $match); 64 case DOKU_LEXER_EXIT: 65 return array($state, ''); 66 } 67 return array(); 68 } 69 70 /** 71 * Create output 72 */ 73 function render($mode, Doku_Renderer $renderer, $data) { 74 if($mode == 'xhtml'){ 75 list($state,$match) = $data; 76 switch ($state) { 77 case DOKU_LEXER_ENTER : 78 list($this->dataspeed, $this->datafx, $this->datatimeout, $this->width, $this->height, $this->namespace, $this->metadata, $this->objectfit) = $match; 79 $renderer->doc .= '<div class="tcycle" style="width: '.$this->width.';"'; 80 $renderer->doc .= 'data-speed="'.$this->dataspeed.'" '; 81 $renderer->doc .= 'data-fx="'.$this->datafx.'" '; 82 $renderer->doc .= 'data-timeout="'.$this->datatimeout.'">'; 83 break; 84 case DOKU_LEXER_MATCHED: 85 list($this->addimgs) = $match; 86 break; 87 case DOKU_LEXER_UNMATCHED : 88 $renderer->doc .= $renderer->_xmlEntities($match); 89 break; 90 case DOKU_LEXER_EXIT : 91 $images = $this->_getImages($this->namespace, $this->addimgs); 92 $renderer->doc .= $images; 93 $renderer->doc .= '</div>'; 94 break; 95 } 96 return true; 97 } 98 return false; 99 } 100 101 function _getAttribute($attributeString, $attribute, $default){ 102 $retVal = $default; 103 $pos = strpos($attributeString, $attribute."="); 104 if ($pos === false) { 105 $pos = strpos($attributeString, $attribute." "); 106 } 107 if ($pos > 0) { 108 $pos = $pos + strlen($attribute); 109 $value = substr($attributeString,$pos); 110 111 //replace '=' and quote signs with null and trim leading spaces 112 $value = ltrim(str_replace(['=', "'", '"'], '', $value)); 113 114 //grab the text before the next space 115 $pos = strpos($value, " "); 116 if ($pos > 0) { 117 $value = substr($value,0,$pos); 118 } 119 $retVal = hsc($value); 120 } 121 return $retVal; 122 } 123 function _getImages($namespace, $addimgs) { 124 global $conf; 125 $files = array(); 126 $images = ''; 127 $target = $conf['target']['media']; 128 $relnf = ''; 129 if ($conf['relnofollow'] == 1) { $relnf = 'nofollow'; } 130 if ($namespace !== 0) { $files = glob($conf['mediadir'].'/'.$namespace."/*.{jp*g,png,gif}", GLOB_BRACE); } 131 $files = array_merge((array)$files, (array)$addimgs); 132 foreach($files as $file) { 133 if (!is_file($file)) { break; } 134 $detail = str_replace($conf['mediadir'], '/_detail', $file); 135 $media = str_replace($conf['mediadir'], '/_media', $file); 136 $meta = new JpegMeta($file); 137 $title = $meta->getField('Simple.Title'); 138 if ($title === "") { $title = " "; } 139 $alt = $meta->getField('Iptc.Caption'); 140 if ($alt === "") { $alt = " "; } 141 $images .= '<figure>'; 142 if ($this->metadata === 1) { $images .= '<figcaption>'.$title.'</figcaption>'; } 143 $images .= '<a href="'.$detail.'" target="'.$target.'" rel ="'.$relnf.' noopener">'; 144 $images .= '<img class="media" src="'.$media.'" title="'.$title.'" alt="'.$alt.'" style="object-fit: '.$this->objectfit.'; width: '.$this->width.'; height: '.$this->height.';" />'; 145 $images .= '</a>'; 146 if ( $this->metadata === 1 ) { $images .= '<figcaption>'.$alt.'</figcaption>'; } 147 $images .= '</figure>'; 148 } 149 return $images; 150 } 151} 152//Setup VIM: ex: et ts=4 enc=utf-8 : 153