* @license PHP License * @package wb * @subpackage Markup */ WBClass::load('WBMarkup_Converter'); /** * Tag converter * * Convert node to node * * @version 0.9.1 * @package wb * @subpackage Markup */ class WBMarkup_Converter_Wb_Vfsfile extends WBMarkup_Converter { /** * associative array to configure converter * @param array */ protected $config = array( 'defaultwidth' => 200, 'defaultheight' => 200, 'blockwidth' => 600, 'blockheight' => 600, 'maxwidth' => 400, 'maxheight' => 400, 'previewwidth' => 600, 'previewheight' => 600 ); /** * Associative array of convert options * @var array */ protected $option = array( 'datauri' => 'auto' ); /** * List of processed files * * @var array */ private $files = array(); /** * Preset * * Clean list of processed files * @param WBMarkup_Handler $handler * @param string $content */ public function preset($handler, &$content) { $this->files = array(); return parent::preset($handler, $content); } /** * Get List of Processed Files * * @return array */ public function getFileList() { return $this->files; } /** * transform Xinha Tags to XML * * @param array $node to be modified document node * @return bool true on success */ public function toXml(&$node) { $xml = array( 'ns' => 'wb', 'tag' => 'vfsfile', 'attributes' => array(), 'isEmpty' => true, 'cData' => array() ); if (!empty($node['cData'])) { $xml['isEmpty'] = false; $xml['cData'] = $node['cData']; } $size = array( intval($this->config['defaultwidth']), intval($this->config['defaultheight']) ); if (isset($node['attributes']['width'])) { $width = intval($node['attributes']['width']); $width = min($width, intval($this->config['maxwidth'])); $size[0] = $width; } if (isset($node['attributes']['height'])) { $height = intval($node['attributes']['height']); $height = min($height, intval($this->config['maxheight'])); $size[1] = $height; } $atts = array( 'obscureid' => $node['attributes']['wb:value'], 'size' => implode('x',$size), 'position' => 'block', ); if (isset($node['attributes']['position'])) { $atts['position'] = $node['attributes']['position']; } $xml['attributes'] = $atts; $node = $xml; return true; } /** * transform Xml to Wxml (html) tags * * @param array $node to be modified document node * @return bool true on success */ public function toWxml(&$node) { $wxml = array( 'ns' => '', 'tag' => 'img', 'attributes' => array(), 'isEmpty' => true, 'cData' => array() ); $size = intval($this->config['defaultwidth']) . 'x' . intval($this->config['defaultheight']); if (isset($node['attributes']['size'])) { $size = $node['attributes']['size']; } $src = '[[SERVICE_FILE]]' . $node['attributes']['obscureid'] . '/image' . '?size=' . $size; $size = explode('x', $size); $style = array(); $atts = array( 'wb:dialog' => 'Vfsfile', 'wb:value' => $node['attributes']['obscureid'], 'position' => $node['attributes']['position'], 'style' => '', 'alt' => $node['attributes']['obscureid'], ); switch ($node['attributes']['position']) { case 'reference': $wxml['tag'] = 'span'; $wxml['isEmpty'] = false; $wxml['cData'] = $node['cData']; $atts['class'] = 'vfsfile vfsfile-reference'; break; case 'download': $wxml['tag'] = 'span'; $wxml['isEmpty'] = false; $wxml['cData'] = $node['cData']; $atts['class'] = 'vfsfile vfsfile-download'; break; case 'left': $atts['src'] = $src; $atts['width'] = $size[0]; $atts['height'] = $size[1]; $style['display'] = 'block'; $style['float'] = 'left'; break; case 'right': $atts['src'] = $src; $atts['width'] = $size[0]; $atts['height'] = $size[1]; $style['display'] = 'block'; $style['float'] = 'right'; break; default: case 'block': $atts['src'] = $src; $atts['width'] = $size[0]; $atts['height'] = $size[1]; $style['display'] = 'block'; break; } $atts = array_merge($this->getDefaultAttributes(WBMarkup_Converter::TARGET_WXML), $atts); if (isset($node['attributes']['class'])) { $atts['class'] .= ' ' . $node['attributes']['class']; } $node = $wxml; $node['attributes'] = $atts; return true; } /** * transform XML to Html * * @param array $node to be modified document node * @return bool true on success */ public function toHtml(&$node) { $oid = $node['attributes']['obscureid']; // load file $loader = WBClass::create('WBVFS_File'); /** @var $loader WBVFS_File */ $file = $loader->loadByObscureId($oid); if (!$file->isOk()) { $this->toHtmlBrokenFile($file, $node); return true; } $this->files[$file->getId()] = $file->getMime(WBVFS_FILE::MIME_MAJOR); switch ($node['attributes']['position']) { case 'download': return $this->toHtmlAsDownload($file, $node); break; case 'reference': return $this->toHtmlAsReference($file, $node); break; default: break; } switch ($file->getMime(WBVFS_File::MIME_MAJOR)) { case 'video': $this->toHtmlVideo($file, $node); break; case 'image': $this->toHtmlImage($file, $node); break; default: $this->toHtmlAsDownload($file, $node); break; } return true; } /** * display broken file * * In case file is bloken, display something at least * * @param WBVFS_File $file * @param array $node */ private function toHtmlAsReference($file, &$node) { $html = array( 'ns' => null, 'tag' => 'a', 'attributes' => array(), 'isEmpty' => false, 'cData' => array() ); $atts = array( 'href' => '#vfsfile' . $file->getObscureid(), 'title' => $file->getDescription() ); $html['attributes'] = $atts; $html['cData'] = $node['cData']; $node = $html; return true; } /** * display broken file * * In case file is bloken, display something at least * * @param WBVFS_File $file * @param array $node */ private function toHtmlAsDownload($file, &$node) { if (empty($node['cData'])) { $node['cData'] = array($file->getName()); } if (!$this->loadTemplates('download')) { $html = array( 'ns' => null, 'tag' => 'a', 'attributes' => array(), 'isEmpty' => false, 'cData' => array() ); $atts = array( 'name' => 'vfsfile' . $file->getObscureid(), 'href' => $file->getUrl('application', true), 'title' => $file->getDescription() ); $html['attributes'] = $atts; $html['cData'] = $node['cData']; $node = $html; return true; } $data = $this->prefillPlaceholder($file, $node, 'download'); $data['url'] = $file->getUrl('application', true); $this->template2HtmlNode($node, $data); } /** * display broken file * * In case file is bloken, display something at least * * @param WBVFS_File $file * @param array $node */ protected function toHtmlBrokenFile($file, &$node) { $this->toHtmlAsDownload($file, $node); } /** * file to download link * * Download file * * @param WBVFS_File $file * @param array $node * @deprecated */ protected function toHtmlDownload($file, &$node) { if (!$this->loadTemplates('download')) { return $this->toHtmlDownloadString($file, $node); } $data = $this->prefillPlaceholder($file, $node, 'download'); $data['url'] = $file->getUrl('application', true); $data['img_url'] = $file->getUrl('image', true); $size = intval($this->config['defaultwidth']) . 'x' . intval($this->config['defaultheight']); if (isset($node['attributes']['size'])) { $size = $node['attributes']['size']; } $get = array('size' => $size); $data['img_src'] = $this->getImageSrc($file, $get); $this->template2HtmlNode($node, $data); } /** * display image * * Show image and use lightbox to display "big" picture * * @param WBVFS_File $file * @param array $node * @return unknown_type */ protected function toHtmlImage($file, &$node) { if (!$this->loadTemplates('image')) { return $this->toHtmlImageString($file, $node); } $url = $file->getUrl('image', true); $size = intval($this->config['defaultwidth']) . 'x' . intval($this->config['defaultheight']); if (isset($node['attributes']['size'])) { $size = $node['attributes']['size']; } if (!empty($node['attributes']['position'])) { switch ($node['attributes']['position']) { case 'block': // auto block size for small width $tmp = explode('x', $size); if ($tmp[0] < (intval($this->config['blockwidth']) / 2)) { $node['attributes']['position'] = 'block-auto'; break; } $size = intval($this->config['blockwidth']) . 'x' . intval($this->config['blockheight']); break; default: break; } } $data = $this->prefillPlaceholder($file, $node, 'image'); $get = array('size' => $size); $data['src'] = $this->getImageSrc($file, $get); $data['url'] = $url; $data['get'] = http_build_query($get); $size = explode('x', $size); $data['size_width'] = $size[0]; $data['size_height'] = $size[1]; $data['size_previewwidth'] = $this->config['previewwidth']; $data['size_previewheight'] = $this->config['previewheight']; $data['alt'] = $file->getName(); $data['title'] = $file->getDescription(); if (empty($data['title'])) { $data['title'] = $data['alt']; } $this->template2HtmlNode($node, $data); } /** * display video * * Start Flash video player * * @param WBVFS_File $file * @param array $node */ protected function toHtmlVideo($file, &$node) { if (!$this->loadTemplates('video')) { return $this->toHtmlVideoString($file, $node); } $data = $this->prefillPlaceholder($file, $node, 'video'); $data['url'] = $file->getUrl('image', true); $size = intval($this->config['defaultwidth']) . 'x' . intval($this->config['defaultheight']); if (isset($node['attributes']['size'])) { $size = $node['attributes']['size']; } $size = explode('x', $size); $data['widthfull'] = 0; $data['widthplayer'] = $size[0]; if ($size[0] > $this->config['previewwidth']) { $data['widthfull'] = 1; $data['widthplayer'] = 0; } $this->template2HtmlNode($node, $data); } /** * transform position to style attribute * * Play with display and float * * @param array $node * @return string $style */ protected function position2Style($node, $inline = false) { if (!isset($node['attributes']['position'])) { return ''; } $style = 'display:block;'; if ($inline) { $style = 'display:inline-block'; } switch ($node['attributes']['position']) { case 'left': $style = 'float:left;'; break; case 'right': $style = 'float:right;'; break; default: case 'block': break; } return $style; } /** * prefill placeholders with file information * * Convenience method to prepare template data * * @param WBVFS_File $file * @param array $node * @param string $class additional class name * @return array $data */ private function prefillPlaceholder($file, &$node, $class) { // default position if (!isset($node['attributes']['position'])) { $node['attributes']['position'] = ''; } $data = array( 'checksum' => $this->md5, 'class' => 'vfsfile ' . $class, 'position' => $node['attributes']['position'], 'id' => $file->getId(), 'obscureid' => $file->getObscureId(), 'name' => $file->getName(), 'description' => $file->getDescription(), 'title' => $file->getName(), 'server' => $file->getServer(), 'cdata' => implode(' ', $node['cData']), 'mimemajor' => $file->getMime(WBVFS_File::MIME_MAJOR), 'mimeminor' => $file->getMime(WBVFS_File::MIME_MINOR), 'alt' => str_replace("\n", ' ', trim(htmlentities($file->getDescription()))) ); if (empty($data['title'])) { $data['title'] = $data['name']; } $data['name_url'] = urlencode($data['name']); return $data; } /** * file to download link * * Download file * Fallback method without templates * * @param WBVFS_File $file * @param array $node */ protected function toHtmlDownloadString($file, &$node) { $html = array( 'ns' => null, 'tag' => 'a', 'attributes' => array(), 'isEmpty' => false, 'cData' => array() ); $atts = array( 'class' => sprintf('vfsfile download %s %s', $file->getMime(WBVFS_File::MIME_MAJOR), $file->getMime(WBVFS_File::MIME_MINOR)), 'href' => $file->getUrl('application', true), 'style' => $this->position2Style($node), 'title' => $file->getName(), 'name' => 'vfsfile' . $file->getObscureid() ); $html['attributes'] = $atts; $html['cData'][] = $file->getName(); $node = $html; } /** * display image * * Show image and use lightbox to display "big" picture. * Fallback method without templates * * @param WBVFS_File $file * @param array $node * @return unknown_type */ protected function toHtmlImageString($file, &$node) { $html = array( 'ns' => null, 'tag' => 'a', 'attributes' => array(), 'isEmpty' => false, 'cData' => array() ); $size = intval($this->config['defaultwidth']) . 'x' . intval($this->config['defaultheight']); if (!empty($node['attributes']['position'])) { switch ($node['attributes']['position']) { case 'block': $size = intval($this->config['blockwidth']) . 'x' . intval($this->config['blockheight']); break; default: if (isset($node['attributes']['size'])) { $size = $node['attributes']['size']; } break; } } $src = $file->getUrl('image', true) . '?size='; $class = array('wb-vfsfile', 'wb-vfsfile-image'); if (!empty($node['attribute']['position'])) { $class[] = 'wb-vfsfile-' . $node['attribute']['position']; } if (!empty($node['attribute']['class'])) { $class[] = $node['attribute']['class']; } $atts = array( 'class' => implode(' ', $class), 'href' => $src . intval($this->config['previewwidth']) . 'x' . intval($this->config['previewheight']), 'style' => $this->position2Style($node, true), 'rel' => sprintf('lightbox[%s]', $this->md5), 'name' => 'vfsfile' . $file->getObscureid() ); $alt = $file->getName(); $atts['title'] = $file->getDescription(); if (empty($atts['title'])) { $atts['title'] = $alt; } // pass reference to just created html node $get = array('size' => $size); $html['cData'][] = sprintf('%s', $this->getImageSrc($file, $get), $alt); $html['attributes'] = $atts; $node = $html; } /** * display video * * Start Flash video player * Fallback method without templates * * @param WBVFS_File $file * @param array $node */ protected function toHtmlVideoString($file, &$node) { $oid = $file->getObscureId(); $html = array( 'ns' => null, 'tag' => 'span', 'attributes' => array(), 'isEmpty' => false, 'cData' => array() ); $atts = array( 'class' => 'vfsfile video', 'style' => $this->position2Style($node), ); $urlDl = $file->getUrl('application', true); $server = $file->getServer(); $innerHtml = << WBVFSFile-playVideo-%1\$s-%2\$s-WBVFSFile %4\$s EOT; $html['cData'][] = sprintf($innerHtml , $this->md5 , $file->getObscureid() , urlencode($file->getName()) , addslashes($file->getName()) , addslashes($urlDl) , addslashes($server) ); $html['attributes'] = $atts; $node = $html; } /** * Get image source * * Either get image source as URL or as data URI. * * @param WBVFS_File $file * @param array $get * @todo refactor this method and merge with WBVFS_Mime_Image */ private function getImageSrc($file, &$get) { $src = $file->getUrl('image', true); if (!empty($get)) { $src .= '?' . http_build_query($get); } switch ($this->option['datauri']) { case 'none': return $src; break; case 'force': break; default: case 'auto': // well, just don't do anything... if (!WBParam::get('wb/html/datauri/use', false)) { return $src; } // image size if (!isset($get['size'])) { return $src; } // only for small images $size = explode('x', $get['size']); if (201 < max($size)) { return $src; } break; } $req = WBClass::create('WBRequest', array('module' => 'Fake')); $req->import($get); $res = WBClass::create('WBResponse'); $mimeMinor = null; $redirect = array(); $mimeHdl = WBClass::create('WBVFS_Mime_Image'); /** @var $mimeHdl VFS_Mime_Image */ $mimeHdl->setVirtualFile($file); $path = $mimeHdl->getRequestedFile($req, $res, $redirect, $mimeMinor); // do it again but with different GET parameters if (!empty($redirect)) { $get = $redirect['get']; $req->import($get); $redirect = array(); $path = $mimeHdl->getRequestedFile($req, $res, $redirect, $mimeMinor); } $mimeMinor = $mimeHdl->getMime(WBVFS_File::MIME_MINOR); $fmt = 'data:image/%s;base64,%s'; return sprintf($fmt, $mimeMinor, base64_encode(file_get_contents($path))); } }