*/
class syntax_plugin_simplenavi extends DokuWiki_Syntax_Plugin
{
private $startpages = [];
/** @inheritdoc */
public function getType()
{
return 'substition';
}
/** @inheritdoc */
public function getPType()
{
return 'block';
}
/** @inheritdoc */
public function getSort()
{
return 155;
}
/** @inheritdoc */
public function connectTo($mode)
{
$this->Lexer->addSpecialPattern('{{simplenavi>[^}]*}}', $mode, 'plugin_simplenavi');
}
/** @inheritdoc */
public function handle($match, $state, $pos, Doku_Handler $handler)
{
return explode(' ', substr($match, 13, -2));
}
/** @inheritdoc */
public function render($format, Doku_Renderer $renderer, $data)
{
if ($format != 'xhtml') return false;
global $conf;
global $INFO;
$renderer->nocache();
// first data is namespace, rest is options
$ns = array_shift($data);
if ($ns && $ns[0] === '.') {
// resolve relative to current page
$ns = getNS((new PageResolver($INFO['id']))->resolveId("$ns:xxx"));
} else {
$ns = cleanID($ns);
}
// convert to path
$ns = utf8_encodeFN(str_replace(':', '/', $ns));
$items = [];
search($items, $conf['datadir'], [$this, 'cbSearch'], ['ns' => $INFO['id']], $ns, 1, 'natural');
if ($this->getConf('sortByTitle')) {
$this->sortByTitle($items, "id");
} else {
if ($this->getConf('sort') == 'ascii') {
uksort($items, [$this, 'pathCompare']);
}
}
$class = 'plugin__simplenavi';
if (in_array('filter', $data)) $class .= ' plugin__simplenavi_filter';
$renderer->doc .= '
';
$renderer->doc .= html_buildlist($items, 'idx', [$this, 'cbList'], [$this, 'cbListItem']);
$renderer->doc .= '
';
return true;
}
/**
* Create a list openening
*
* @param array $item
* @return string
* @see html_buildlist()
*/
public function cbList($item)
{
global $INFO;
if (($item['type'] == 'd' && $item['open']) || $INFO['id'] == $item['id']) {
return '' . html_wikilink(':' . $item['id'], $this->getTitle($item['id'])) . '';
} else {
return html_wikilink(':' . $item['id'], $this->getTitle($item['id']));
}
}
/**
* Create a list item
*
* @param array $item
* @return string
* @see html_buildlist()
*/
public function cbListItem($item)
{
if ($item['type'] == "f") {
return '';
} elseif ($item['open']) {
return '';
} else {
return '';
}
}
/**
* Custom search callback
*
* @param $data
* @param $base
* @param $file
* @param $type
* @param $lvl
* @param $opts
* @return bool
*/
public function cbSearch(&$data, $base, $file, $type, $lvl, $opts)
{
global $conf;
$return = true;
$id = pathID($file);
if ($type == 'd' && !(
preg_match('#^' . $id . '(:|$)#', $opts['ns']) ||
preg_match('#^' . $id . '(:|$)#', getNS($opts['ns']))
)) {
//add but don't recurse
$return = false;
} elseif ($type == 'f' && (!empty($opts['nofiles']) || substr($file, -4) != '.txt')) {
//don't add
return false;
}
// for sneaky index, check access to the namespace's start page
if ($type == 'd' && $conf['sneaky_index']) {
$sp = (new PageResolver(''))->resolveId($id . ':');
if (auth_quickaclcheck($sp) < AUTH_READ) {
return false;
}
}
if ($type == 'd') {
// link directories to their start pages
$id = "$id:";
$id = (new PageResolver(''))->resolveId($id);
$this->startpages[$id] = 1;
} elseif (!empty($this->startpages[$id])) {
// skip already shown start pages
return false;
} elseif (noNS($id) == $conf['start']) {
// skip the main start page
return false;
}
//check hidden
if (isHiddenPage($id)) {
return false;
}
//check ACL
if ($type == 'f' && auth_quickaclcheck($id) < AUTH_READ) {
return false;
}
$data[$id] = array(
'id' => $id,
'type' => $type,
'level' => $lvl,
'open' => $return,
);
return $return;
}
/**
* Get the title for the given page ID
*
* @param string $id
* @return string
*/
protected function getTitle($id)
{
global $conf;
if (useHeading('navigation')) {
$p = p_get_first_heading($id);
}
if (!empty($p)) return $p;
$p = noNS($id);
if ($p == $conf['start'] || !$p) {
$p = noNS(getNS($id));
if (!$p) {
return $conf['start'];
}
}
return $p;
}
/**
* Custom comparator to compare IDs
*
* @param string $a
* @param string $b
* @return int
*/
public function pathCompare($a, $b)
{
global $conf;
$a = preg_replace('/' . preg_quote($conf['start'], '/') . '$/', '', $a);
$b = preg_replace('/' . preg_quote($conf['start'], '/') . '$/', '', $b);
$a = str_replace(':', '/', $a);
$b = str_replace(':', '/', $b);
return strcmp($a, $b);
}
/**
* Sort items by title
*
* @param array[] $array a list of items
* @param string $key the key that contains the page ID in each item
* @return void
*/
protected function sortByTitle(&$array, $key)
{
$sorter = [];
$ret = [];
reset($array);
foreach ($array as $ii => $va) {
$sorter[$ii] = $this->getTitle($va[$key]);
}
if ($this->getConf('sort') == 'ascii') {
uksort($sorter, [$this, 'pathCompare']);
} else {
natcasesort($sorter);
}
foreach ($sorter as $ii => $va) {
$ret[$ii] = $array[$ii];
}
$array = $ret;
}
}