1df3d88adSMichael Klier<?php 2fe957bb7Sgithub-actions[bot] 3fe957bb7Sgithub-actions[bot]use dokuwiki\Extension\SyntaxPlugin; 4*c271718aSMark Prinsuse dokuwiki\Logger; 5fe957bb7Sgithub-actions[bot] 6df3d88adSMichael Klier/** 752fa4f27SMark Prins * DokuWiki Syntax Plugin Backlinks. 8df3d88adSMichael Klier * 9e70bf163SMichael Klier * Shows a list of pages that link back to a given page. 10e70bf163SMichael Klier * 1152fa4f27SMark Prins * Syntax: {{backlinks>[pagename][#filterNS|!#filterNS]}} 12e70bf163SMichael Klier * 1352fa4f27SMark Prins * [pagename] - a valid wiki pagename or a . for the current page 1439718802SMark Prins * [filterNS] - a valid,absolute namespace name, optionally prepended with ! to exclude 15e70bf163SMichael Klier * 16df3d88adSMichael Klier * @license GPL 2 (http://www.gnu.org/licenses/gpl.html) 17df3d88adSMichael Klier * @author Michael Klier <chi@chimeric.de> 182287a730SMark Prins * @author Mark C. Prins <mprins@users.sf.net> 19df3d88adSMichael Klier */ 20*c271718aSMark Prins 21df3d88adSMichael Klier/** 22df3d88adSMichael Klier * All DokuWiki plugins to extend the parser/rendering mechanism 23d2570a6cSMark Prins * need to inherit from this class. 24df3d88adSMichael Klier */ 25fe957bb7Sgithub-actions[bot]class syntax_plugin_backlinks extends SyntaxPlugin 26fe957bb7Sgithub-actions[bot]{ 27df3d88adSMichael Klier /** 282287a730SMark Prins * Syntax Type. 29df3d88adSMichael Klier * 30d2570a6cSMark Prins * Needs to return one of the mode types defined in $PARSER_MODES in parser.php. 31d2570a6cSMark Prins * 322287a730SMark Prins * @see DokuWiki_Syntax_Plugin::getType() 33df3d88adSMichael Klier */ 34*c271718aSMark Prins public function getType(): string 35fe957bb7Sgithub-actions[bot] { 36d2570a6cSMark Prins return 'substition'; 37d2570a6cSMark Prins } 382287a730SMark Prins 392287a730SMark Prins /** 402287a730SMark Prins * @see DokuWiki_Syntax_Plugin::getPType() 412287a730SMark Prins */ 42*c271718aSMark Prins public function getPType(): string 43fe957bb7Sgithub-actions[bot] { 44d2570a6cSMark Prins return 'block'; 45d2570a6cSMark Prins } 462287a730SMark Prins 472287a730SMark Prins /** 482287a730SMark Prins * @see Doku_Parser_Mode::getSort() 492287a730SMark Prins */ 50*c271718aSMark Prins public function getSort(): int 51fe957bb7Sgithub-actions[bot] { 52d2570a6cSMark Prins return 304; 53d2570a6cSMark Prins } 54df3d88adSMichael Klier 55df3d88adSMichael Klier /** 562287a730SMark Prins * Connect pattern to lexer. 57d2570a6cSMark Prins * 582287a730SMark Prins * @see Doku_Parser_Mode::connectTo() 59df3d88adSMichael Klier */ 60*c271718aSMark Prins public function connectTo($mode): void 61fe957bb7Sgithub-actions[bot] { 62df3d88adSMichael Klier $this->Lexer->addSpecialPattern('\{\{backlinks>.+?\}\}', $mode, 'plugin_backlinks'); 63df3d88adSMichael Klier } 64df3d88adSMichael Klier 65df3d88adSMichael Klier /** 662287a730SMark Prins * Handler to prepare matched data for the rendering process. 67d2570a6cSMark Prins * 682287a730SMark Prins * @see DokuWiki_Syntax_Plugin::handle() 69df3d88adSMichael Klier */ 70*c271718aSMark Prins public function handle($match, $state, $pos, Doku_Handler $handler): array 71fe957bb7Sgithub-actions[bot] { 72b3014541SMark Prins // strip {{backlinks> from start and }} from end 73b3014541SMark Prins $match = substr($match, 12, -2); 7439718802SMark Prins 75d2570a6cSMark Prins $includeNS = ''; 7639718802SMark Prins if (strstr($match, "#")) { 771ed0f63eSMark Prins $includeNS = substr(strstr($match, "#", false), 1); 781ed0f63eSMark Prins $match = strstr($match, "#", true); 7939718802SMark Prins } 8039718802SMark Prins 81fe957bb7Sgithub-actions[bot] return ([$match, $includeNS]); 82df3d88adSMichael Klier } 83df3d88adSMichael Klier 84df3d88adSMichael Klier /** 85df3d88adSMichael Klier * Handles the actual output creation. 86d2570a6cSMark Prins * 872287a730SMark Prins * @see DokuWiki_Syntax_Plugin::render() 88df3d88adSMichael Klier */ 89*c271718aSMark Prins public function render($format, Doku_Renderer $renderer, $data): bool 90fe957bb7Sgithub-actions[bot] { 91154ef50cSMichael Klier global $lang; 927a3c4628SDirk Melchers global $INFO; 937a3c4628SDirk Melchers global $ID; 947a3c4628SDirk Melchers 957a3c4628SDirk Melchers $id = $ID; 967a3c4628SDirk Melchers // If it's a sidebar, get the original id. 977a3c4628SDirk Melchers if ($INFO != null) { 987a3c4628SDirk Melchers $id = $INFO['id']; 997a3c4628SDirk Melchers } 1007a3c4628SDirk Melchers $match = $data[0]; 1017a3c4628SDirk Melchers $match = ($match == '.') ? $id : $match; 1027a3c4628SDirk Melchers if (strstr($match, ".:")) { 1037a3c4628SDirk Melchers resolve_pageid(getNS($id), $match, $exists); 1047a3c4628SDirk Melchers } 105df3d88adSMichael Klier 106d5c4cf25SMark Prins if ($format == 'xhtml') { 107df3d88adSMichael Klier $renderer->info['cache'] = false; 108df3d88adSMichael Klier 1097a3c4628SDirk Melchers $backlinks = ft_backlinks($match); 110af390d34SMichael Klier 111*c271718aSMark Prins Logger::debug("backlinks: all backlinks to: $match", $backlinks); 11252fa4f27SMark Prins 113d2570a6cSMark Prins $renderer->doc .= '<div id="plugin__backlinks">' . "\n"; 114154ef50cSMichael Klier 11539718802SMark Prins $filterNS = $data[1]; 11639718802SMark Prins if (!empty($backlinks) && !empty($filterNS)) { 11739718802SMark Prins if (stripos($filterNS, "!", 0) === 0) { 11839718802SMark Prins $filterNS = substr($filterNS, 1); 119*c271718aSMark Prins Logger::debug("backlinks: excluding all of namespace: $filterNS"); 1201ed0f63eSMark Prins $backlinks = array_filter( 121fe957bb7Sgithub-actions[bot] $backlinks, 122fe957bb7Sgithub-actions[bot] static fn($ns) => stripos($ns, $filterNS, 0) !== 0 1231ed0f63eSMark Prins ); 12439718802SMark Prins } else { 125*c271718aSMark Prins Logger::debug("backlinks: including namespace: $filterNS only"); 1261ed0f63eSMark Prins $backlinks = array_filter( 127fe957bb7Sgithub-actions[bot] $backlinks, 128fe957bb7Sgithub-actions[bot] static fn($ns) => stripos($ns, (string) $filterNS, 0) === 0 1291ed0f63eSMark Prins ); 13039718802SMark Prins } 13139718802SMark Prins } 13239718802SMark Prins 133*c271718aSMark Prins Logger::debug("backlinks: all backlinks to be rendered", $backlinks); 13452fa4f27SMark Prins 135df3d88adSMichael Klier if (!empty($backlinks)) { 136df3d88adSMichael Klier $renderer->doc .= '<ul class="idx">'; 137df3d88adSMichael Klier 138df3d88adSMichael Klier foreach ($backlinks as $backlink) { 139cef58d31SMichael Klier $name = p_get_metadata($backlink, 'title'); 1407ce29d5aSScrutinizer Auto-Fixer if (empty($name)) { 1417ce29d5aSScrutinizer Auto-Fixer $name = $backlink; 1427ce29d5aSScrutinizer Auto-Fixer } 143df3d88adSMichael Klier $renderer->doc .= '<li><div class="li">'; 144b3014541SMark Prins $renderer->doc .= html_wikilink(':' . $backlink, $name); 145d2570a6cSMark Prins $renderer->doc .= '</div></li>' . "\n"; 146df3d88adSMichael Klier } 147df3d88adSMichael Klier 148d2570a6cSMark Prins $renderer->doc .= '</ul>' . "\n"; 149154ef50cSMichael Klier } else { 150d2570a6cSMark Prins $renderer->doc .= "<strong>Plugin Backlinks: " . $lang['nothingfound'] . "</strong>" . "\n"; 151df3d88adSMichael Klier } 152df3d88adSMichael Klier 153d2570a6cSMark Prins $renderer->doc .= '</div>' . "\n"; 154154ef50cSMichael Klier 155df3d88adSMichael Klier return true; 156df3d88adSMichael Klier } 157df3d88adSMichael Klier return false; 158df3d88adSMichael Klier } 159df3d88adSMichael Klier} 160