1<?php 2 3/** 4 * Easily embed videos from various Video Sharing sites 5 * 6 * @license GPL 2 (http://www.gnu.org/licenses/gpl.html) 7 * @author Andreas Gohr <andi@splitbrain.org> 8 */ 9class syntax_plugin_vshare_video extends DokuWiki_Syntax_Plugin 10{ 11 protected $sites; 12 13 protected $sizes = [ 14 'small' => [255, 143], 15 'medium' => [425, 239], 16 'large' => [520, 293], 17 'full' => ['100%', ''], 18 'half' => ['50%', ''], 19 ]; 20 21 protected $alignments = [ 22 0 => 'none', 23 1 => 'right', 24 2 => 'left', 25 3 => 'center', 26 ]; 27 28 /** 29 * Constructor. 30 * Intitalizes the supported video sites 31 */ 32 public function __construct() 33 { 34 $this->sites = helper_plugin_vshare::loadSites(); 35 } 36 37 /** @inheritdoc */ 38 public function getType() 39 { 40 return 'substition'; 41 } 42 43 /** @inheritdoc */ 44 public function getPType() 45 { 46 return 'block'; 47 } 48 49 /** @inheritdoc */ 50 public function getSort() 51 { 52 return 159; 53 } 54 55 /** @inheritdoc */ 56 public function connectTo($mode) 57 { 58 $pattern = join('|', array_keys($this->sites)); 59 $this->Lexer->addSpecialPattern('\{\{\s?(?:' . $pattern . ')>[^}]*\}\}', $mode, 'plugin_vshare_video'); 60 } 61 62 /** @inheritdoc */ 63 public function handle($match, $state, $pos, Doku_Handler $handler) 64 { 65 $command = substr($match, 2, -2); 66 67 // title 68 list($command, $title) = array_pad(explode('|', $command), 2, ''); 69 $title = trim($title); 70 71 // alignment 72 $align = 0; 73 if (substr($command, 0, 1) == ' ') $align += 1; 74 if (substr($command, -1) == ' ') $align += 2; 75 $command = trim($command); 76 77 // get site and video 78 list($site, $vid) = explode('>', $command); 79 if (!$this->sites[$site]) return null; // unknown site 80 if (!$vid) return null; // no video!? 81 82 // what size? 83 list($vid, $pstr) = array_pad(explode('?', $vid, 2), 2, ''); 84 parse_str($pstr, $userparams); 85 list($width, $height) = $this->parseSize($userparams); 86 87 // get URL 88 $url = $this->insertPlaceholders($this->sites[$site]['url'], $vid, $width, $height); 89 list($url, $urlpstr) = array_pad(explode('?', $url, 2), 2, ''); 90 parse_str($urlpstr, $urlparams); 91 92 // merge parameters 93 $params = array_merge($urlparams, $userparams); 94 $url = $url . '?' . buildURLparams($params, '&'); 95 96 return array( 97 'site' => $site, 98 'domain' => parse_url($url, PHP_URL_HOST), 99 'video' => $vid, 100 'url' => $url, 101 'align' => $this->alignments[$align], 102 'width' => $width, 103 'height' => $height, 104 'title' => $title, 105 ); 106 } 107 108 /** @inheritdoc */ 109 public function render($mode, Doku_Renderer $R, $data) 110 { 111 if ($mode != 'xhtml') return false; 112 if (is_null($data)) return false; 113 114 if (is_a($R, 'renderer_plugin_dw2pdf')) { 115 $R->doc .= $this->pdf($data); 116 } else { 117 $R->doc .= $this->iframe($data, $this->getConf('gdpr') ? 'div' : 'iframe'); 118 } 119 return true; 120 } 121 122 /** 123 * Prepare the HTML for output of the embed iframe 124 * @param array $data 125 * @param string $element Can be used to not directly embed the iframe 126 * @return string 127 */ 128 public function iframe($data, $element = 'iframe') 129 { 130 return "<$element " 131 . buildAttributes(array( 132 'src' => $data['url'], 133 'width' => $data['width'], 134 'height' => $data['height'], 135 'style' => $this->sizeToStyle($data['width'], $data['height']), 136 'class' => 'vshare vshare__' . $data['align'], 137 'allowfullscreen' => '', 138 'frameborder' => 0, 139 'scrolling' => 'no', 140 'data-domain' => $data['domain'], 141 )) 142 . '><h3>' . hsc($data['title']) . "</h3></$element>"; 143 } 144 145 /** 146 * Create a style attribute for the given size 147 * 148 * @param int|string $width 149 * @param int|string $height 150 * @return string 151 */ 152 public function sizeToStyle($width, $height) 153 { 154 // no unit? use px 155 if ($width && $width == (int)$width) { 156 $width = $width . 'px'; 157 } 158 // no unit? use px 159 if ($height && $height == (int)$height) { 160 $height = $height . 'px'; 161 } 162 163 $style = ''; 164 if ($width) $style .= 'width:' . $width . ';'; 165 if ($height) $style .= 'height:' . $height . ';'; 166 return $style; 167 } 168 169 /** 170 * Prepare the HTML for output in PDF exports 171 * 172 * @param array $data 173 * @return string 174 */ 175 public function pdf($data) 176 { 177 $html = '<div class="vshare vshare__' . $data['align'] . '" 178 width="' . $data['width'] . '" 179 height="' . $data['height'] . '">'; 180 181 $html .= '<a href="' . $data['url'] . '" class="vshare">'; 182 $html .= '<img src="' . DOKU_BASE . 'lib/plugins/vshare/video.png" />'; 183 $html .= '</a>'; 184 185 $html .= '<br />'; 186 187 $html .= '<a href="' . $data['url'] . '" class="vshare">'; 188 $html .= ($data['title'] ? hsc($data['title']) : 'Video'); 189 $html .= '</a>'; 190 191 $html .= '</div>'; 192 193 return $html; 194 } 195 196 /** 197 * Fill the placeholders in the given URL 198 * 199 * @param string $url 200 * @param string $vid 201 * @param int|string $width 202 * @param int|string $height 203 * @return string 204 */ 205 public function insertPlaceholders($url, $vid, $width, $height) 206 { 207 global $INPUT; 208 $url = str_replace('@VIDEO@', rawurlencode($vid), $url); 209 $url = str_replace('@DOMAIN@', rawurlencode($INPUT->server->str('HTTP_HOST')), $url); 210 $url = str_replace('@WIDTH@', $width, $url); 211 $url = str_replace('@HEIGHT@', $height, $url); 212 213 return $url; 214 } 215 216 /** 217 * Extract the wanted size from the parameter list 218 * 219 * @param array $params 220 * @return int[] 221 */ 222 public function parseSize(&$params) 223 { 224 $known = join('|', array_keys($this->sizes)); 225 226 foreach ($params as $key => $value) { 227 if (preg_match("/^((\d+)x(\d+))|($known)\$/i", $key, $m)) { 228 unset($params[$key]); 229 if (isset($m[4])) { 230 return $this->sizes[strtolower($m[4])]; 231 } else { 232 return [$m[2], $m[3]]; 233 } 234 } 235 } 236 237 // default 238 return $this->sizes['medium']; 239 } 240} 241