* @license PHP License
* @package wb
* @subpackage Markup
*/
WBClass::load('WBMarkup_Converter');
/**
* Tag converter
*
* Convert node to node
*
* @version 0.6.0
* @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,
'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);
//$data['img_src'] = $data['img_url'] . '?size=' . $size;
$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);
}
$data = $this->prefillPlaceholder($file, $node, 'image');
$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['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'];
$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);
$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 (isset($node['attributes']['size'])) {
$size = $node['attributes']['size'];
}
$src = $file->getUrl('image', true)
. '?size=';
$atts = array(
'class' => 'vfsfile image',
'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('', $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
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)));
}
}