]*>'; $this->Lexer->addSpecialPattern($pattern, $aMode, PluginUtility::getModeFromTag($this->getPluginComponent())); } function getSort() { /** * One less than the old one */ return 149; } /** * No p element please * @return string */ function getPType() { return 'block'; } function getType() { // The spelling is wrong but this is a correct value // https://www.dokuwiki.org/devel:syntax_plugins#syntax_types return 'substition'; } /** * * The handle function goal is to parse the matched syntax through the pattern function * and to return the result for use in the renderer * This result is always cached until the page is modified. * @param string $match * @param int $state * @param int $pos * @param Doku_Handler $handler * @return array|bool * @see DokuWiki_Syntax_Plugin::handle() * */ function handle($match, $state, $pos, Doku_Handler $handler) { switch ($state) { // As there is only one call to connect to in order to a add a pattern, // there is only one state entering the function // but I leave it for better understanding of the process flow case DOKU_LEXER_SPECIAL : // Parse the parameters $match = substr($match, 8, -1); //9 = strlen("getConf(self::INCLUDE_DIRECTORY_PARAMETERS); $parameters[self::SHOW_HEADER] = $this->getConf(self::SHOW_HEADER); // /i not case sensitive $attributePattern = "\\s*(\w+)\\s*=\\s*['\"]{1}([^`\"]*)['\"]{1}\\s*"; $result = preg_match_all('/' . $attributePattern . '/i', $match, $matches); if ($result != 0) { foreach ($matches[1] as $key => $parameterKey) { $parameter = strtolower($parameterKey); $value = $matches[2][$key]; if (in_array($parameter, [self::SHOW_HEADER, self::INCLUDE_DIRECTORY_PARAMETERS])) { $value = filter_var($value, FILTER_VALIDATE_BOOLEAN); } $parameters[$parameter] = $value; } } // Cache the values return array( PluginUtility::STATE => $state, PluginUtility::ATTRIBUTES => $parameters ); } return false; } function render($mode, Doku_Renderer $renderer, $data) { // The $data variable comes from the handle() function // // $mode = 'xhtml' means that we output html // There is other mode such as metadata where you can output data for the headers (Not 100% sure) if ($mode == 'xhtml') { /** @var Doku_Renderer_xhtml $renderer */ $state = $data[PluginUtility::STATE]; // As there is only one call to connect to in order to a add a pattern, // there is only one state entering the function // but I leave it for better understanding of the process flow switch ($state) { case DOKU_LEXER_SPECIAL : PluginUtility::getSnippetManager()->attachCssInternalStyleSheet(self::MINIMAP_TAG_NAME); global $ID; global $INFO; $callingId = $ID; // If mini-map is in a sidebar, we don't want the ID of the sidebar // but the ID of the page. if ($INFO != null) { $callingId = $INFO['id']; } $attributes = $data[PluginUtility::ATTRIBUTES]; $nameSpacePath = getNS($callingId); // The complete path to the directory if (array_key_exists(self::NAMESPACE_KEY_ATT, $attributes)) { $nameSpacePath = $attributes[self::NAMESPACE_KEY_ATT]; } $currentNameSpace = curNS($callingId); // The name of the container directory $includeDirectory = $attributes[self::INCLUDE_DIRECTORY_PARAMETERS]; $pagesOfNamespace = $this->getNamespaceChildren($nameSpacePath, $sort = 'natural', $listdirs = $includeDirectory); // Set the two possible home page for the namespace ie: // - the name of the containing map ($homePageWithContainingMapName) // - the start conf parameters ($homePageWithStartConf) global $conf; $parts = explode(':', $nameSpacePath); $lastContainingNameSpace = $parts[count($parts) - 1]; $homePageWithContainingMapName = $nameSpacePath . ':' . $lastContainingNameSpace; $startConf = $conf['start']; $homePageWithStartConf = $nameSpacePath . ':' . $startConf; // Build the list of page $miniMapList = ''; // End list-group // Build the panel header $miniMapHeader = ""; $startId = ""; if ($startPageFound) { $startId = $homePageWithStartConf; } else { if ($homePageFound) { $startId = $homePageWithContainingMapName; } } $panelHeaderContent = ""; if ($startId == "") { if ($attributes[self::SHOW_HEADER] == true) { $panelHeaderContent = 'No Home Page found'; } } else { $startLink = new LinkMarkup($startId); try { $panelHeaderContent = $startLink->toAttributes()->toHtmlEnterTag("a"); $panelHeaderContent .= $startLink->getDefaultLabel(); $panelHeaderContent .= ""; } catch (ExceptionCompile $e) { $panelHeaderContent = "Error: {$e->getMessage()}"; } // We are not counting the header page $pageNum--; } if ($panelHeaderContent != "") { $miniMapHeader .= '
' . $panelHeaderContent . ' ' . $pageNum . ' pages
'; } if ($attributes['debug'] ?? null) { $miniMapHeader .= '
' . 'Debug Information:
' . 'CallingId: (' . $callingId . ')
' . 'Suppress Option: (' . ($attributes['suppress'] ?? '') . ')
' . '
'; } // Header + list $renderer->doc .= '
' . $miniMapHeader . $miniMapList . '
'; break; } return true; } return false; } /** * Return all pages and/of sub-namespaces (subdirectory) of a namespace (ie directory) * Adapted from feed.php * * @param string $namespace The container of the pages * @param string $sort 'natural' to use natural order sorting (default); 'date' to sort by filemtime * @param $listdirs - Add the directory to the list of files * @return array An array of the pages for the namespace */ function getNamespaceChildren($namespace, $sort = 'natural', $listdirs = false) { require_once(DOKU_INC . 'inc/search.php'); global $conf; $ns = ':' . cleanID($namespace); // ns as a path $ns = utf8_encodeFN(str_replace(':', '/', $ns)); $data = array(); // Options of the callback function search_universal // in the search.php file $search_opts = array( 'depth' => 1, 'pagesonly' => true, 'listfiles' => true, 'listdirs' => $listdirs, 'firsthead' => true ); // search_universal is a function in inc/search.php that accepts the $search_opts parameters search($data, $conf['datadir'], 'search_universal', $search_opts, $ns, $lvl = 1, $sort); return $data; } /** * Return the id of the start page of a namespace * * @param string $id an id of a namespace (directory) * @return string the id of the home page */ function getNamespaceStartId($id) { global $conf; $id = $id . ":"; if (page_exists($id . $conf['start'])) { // start page inside namespace $homePageId = $id . $conf['start']; } elseif (page_exists($id . noNS(cleanID($id)))) { // page named like the NS inside the NS $homePageId = $id . noNS(cleanID($id)); } elseif (page_exists($id)) { // page like namespace exists $homePageId = substr($id, 0, -1); } else { // fall back to default $homePageId = $id . $conf['start']; } return $homePageId; } /** * @param $get_called_class * @return string */ public static function getTagName($get_called_class) { list(/* $t */, /* $p */, $c) = explode('_', $get_called_class, 3); return (isset($c) ? $c : ''); } /** * @return string - the tag */ public static function getTag() { return self::getTagName(get_called_class()); } }