*/
if (!defined('DOKU_INC'))
define('DOKU_INC',realpath(dirname(__FILE__).'/../../').'/');
if (!defined('DOKU_PLUGIN'))
define('DOKU_PLUGIN',DOKU_INC.'lib/plugins/');
require_once(DOKU_PLUGIN.'syntax.php');
class syntax_plugin_htmlabstract extends DokuWiki_Syntax_Plugin
{
/**
* return informations for plugins managing page
*/
function getInfo()
{
return array(
'author' => 'Vincent Feltz',
'email' => 'psycho@feltzv.fr',
'date' => '2016-11-07', //first version 2008-11-14
'name' => 'HtmlAbstract',
'desc' => 'Allows integration of remote or local DW RSS feeds using html formatted abstracts instead of choosing between html OR abstract.',
'url' => 'http://www.dokuwiki.org/plugin:htmlabstract',
);
}
/**
* return the type of syntax defined by this plugin
*/
function getType() {return 'substition';} // This is not a mispelling! ;) (http://www.dokuwiki.org/devel:syntax_plugins#fn__5)
/**
* return when to call this plugin
*/
function getSort() {return 310;} // 310 = Doku_Parser_Mode_rss (http://www.dokuwiki.org/devel:parser:getsort_list)
/**
* connect the pattern to the lexer
*/
function connectTo($mode) {$this->Lexer->addSpecialPattern('{{htmlabs>.*?}}',$mode,'plugin_htmlabstract');}
/**
* handle the pattern match
*/
function handle($match, $state, $pos, &$handler)
{
$params = $this->splitAndSortParams($match);
$elements = $this->getFeedElements($params);
if (!is_array($elements) && false !== strpos($elements, 'ERROR'))
return array($elements);
$content = $this->formatElements($elements, $params);
return array($content);
}
/**
* handle rendering output
*/
function render($mode, &$renderer, $data)
{
$renderer->doc .= $data[0];
$data[0] = "";
return TRUE;
}
/**
* determines params to be used from match and configuration
*/
function splitAndSortParams($match)
{
global $conf;
$match = trim(trim($match, '{}'));
$match = substr($match, strlen("htmlabs>"));
if (false !== strpos($match, ' '))
$params['feed_url'] = trim(substr($match, 0, strpos($match, ' ')));
else
$params['feed_url'] = trim($match);
$match = substr($match, strlen($params['feed_url']) + 1);
if (substr($params['feed_url'], 0, 7) != 'http://')
$params['feed_url'] = DOKU_URL.$params['feed_url'];
if (false !== ($pos = strpos($params['feed_url'], '?')))
{
$tmp = explode('?', $params['feed_url']);
$params['feed_url'] = $tmp[0];
$params['feed_params'] = $tmp[1];
}
else
$params['feed_params'] = '';
$params['feed_params'] .= '&content=html&type=rss2';
$opts = explode(' ', strtolower($match));
$params['author'] = !in_array('noauthor', $opts);
$params['title'] = !in_array('notitle', $opts);
$params['date'] = !in_array('nodate', $opts);
$params['textlink'] = $this->getConf('textlink') ? $this->getConf('textlink') : $this->getLang("textlink");
$params['maxlen'] = $this->getConf('maxlength');
if ($params['maxlen'] <= 0)
$params['maxlen'] = 750;
$params['trycleancut'] = $this->getConf('paragraph');
$params['bg_color'] = $this->getConf('bg_color');
$params['unknown_author'] = $this->getLang('extern_edit');
return $params;
}
/**
* get and parse elements of targeted feed
*/
function getFeedElements($params)
{
if (!($xml = @file_get_contents($params['feed_url'].'?'.$params['feed_params'])))
return 'ERROR : Cannot get content from '.$params['feed_url'].' ! Please check the feed URL.
';
$dom = new DOMDocument();
if (false === @$dom->loadXML($xml))
return 'ERROR : XML error in feed, cannot parse.
';
$elements = array();
$items = $dom->getElementsByTagName('item');
foreach ($items as $item)
{
$element = array();
$details = $item->getElementsByTagName('*');
foreach ($details as $detail)
switch ($detail->nodeName)
{
case 'title' :
case 'author' :
case 'pubDate' :
case 'link' :
case 'description' :
$element[$detail->nodeName] = $detail->nodeValue;
break;
}
if (!isset($element['author']))
$element['author'] = $params['unknown_author'];
$elements[] = $element;
}
return $elements;
}
/**
* format elements to put them in a list of coloured-background previews
*/
function formatElements($elements, $params)
{
$css = ' style="background-color:#'.$params['bg_color'].'; padding: 0px 5px 5px; overflow:auto; margin-bottom: 20px;"';
$content = '
opened by DW before plugin handling for W3C compliance (
) $content.= ' '."\n"; foreach ($elements as $element) { $item = '
'; return $content; } //TODO à refaire pour les windowsiens! /** * format feed items'dates to adapt them to local wiki config (config:dformat) */ function formatDate($date) { global $conf; if (false !== strpos($_SERVER['SERVER_SOFTWARE'], 'Win32') || false !== strpos($_SERVER['SERVER_SOFTWARE'], 'Win64')) return $date; //strptime() is not implemented on Windows platforms, sorry! $decomposed_date = strptime($date, '%a, %d %b %Y %H:%M:%S %z'); extract($decomposed_date); $date = strftime($conf['dformat'], mktime($tm_hour, $tm_min, $tm_sec, $tm_mon + 1, $tm_mday, 1900 + $tm_year)); return $date; } /** * cut abstracts to desired length, searches the cleaner cut, and close broken tags */ function formatDescription($text, $params) { $cut = $this->cutTextToLength($text, $params['maxlen']); $text = preg_replace('/<([a-z]+[^>]*) id="([^>]+)"/', '<$1 id="${2}_htmlabstract_'.microtime(true).'"', $text); //time() is used here for W3C compliance (avoid duplicated id's) if ($cut && $params['trycleancut']) { $min = ($params['maxlen'] > 400) ? (200) : ($params['maxlen'] / 2); if (FALSE !== ($pos = strrpos($text, "
")) && $pos >= $min) $text = substr($text, 0, 4 + $pos); } if ($cut) $text .= '... '; $text = $this->closeBrokenTags($text); return $text; } /** * brutally cut abstract to desired length without considering html tags */ function cutTextToLength(&$text, $maxlen) { $intag = false; $i = -1; $len = 0; $textlen = strlen($text); while (++$i < $textlen) if ('<' == $text[$i]) $intag = true; elseif ('>' == $text[$i]) $intag = false; elseif (!$intag) if ($maxlen == ++$len) { $text = substr($text, 0, $i); return true; } return false; } /** * search tags broken by brutal cut and close them */ function closeBrokenTags($text) { $tags = array(); $i = -1; $textlen = strlen($text); while (++$i < $textlen) if ($text[$i] == '<') { if ($text[$i + 1] != '/' && $text[$i + 1] != '!') //opening tag { $j = $i; while ($text[++$j] != ' ' && $text[$j] != '>'); array_push($tags, substr($text, $i + 1, $j - $i - 1)); } elseif ($text[$i + 1] == '/') //closing tag { $j = $i + 1; while ($text[++$j] != ' ' && $text[$j] != '>'); $closed_tag = substr($text, $i + 2, $j - $i - 2); while ($tags[count($tags) - 1] != $closed_tag) array_pop($tags); array_pop($tags); } } while (count($tags)) $text .= ''.array_pop($tags).'>'; return $text; } } ?>