1<?php 2 3use dokuwiki\Extension\SyntaxPlugin; 4 5/** 6 * DokuWiki Syntax Plugin Backlinks. 7 * 8 * Shows a list of pages that link back to a given page. 9 * 10 * Syntax: {{backlinks>[pagename][#filterNS|!#filterNS]}} 11 * 12 * [pagename] - a valid wiki pagename or a . for the current page 13 * [filterNS] - a valid,absolute namespace name, optionally prepended with ! to exclude 14 * 15 * @license GPL 2 (http://www.gnu.org/licenses/gpl.html) 16 * @author Michael Klier <chi@chimeric.de> 17 * @author Mark C. Prins <mprins@users.sf.net> 18 */ 19/** 20 * All DokuWiki plugins to extend the parser/rendering mechanism 21 * need to inherit from this class. 22 */ 23class syntax_plugin_backlinks extends SyntaxPlugin 24{ 25 /** 26 * Syntax Type. 27 * 28 * Needs to return one of the mode types defined in $PARSER_MODES in parser.php. 29 * 30 * @see DokuWiki_Syntax_Plugin::getType() 31 */ 32 public function getType() 33 { 34 return 'substition'; 35 } 36 37 /** 38 * @see DokuWiki_Syntax_Plugin::getPType() 39 */ 40 public function getPType() 41 { 42 return 'block'; 43 } 44 45 /** 46 * @see Doku_Parser_Mode::getSort() 47 */ 48 public function getSort() 49 { 50 return 304; 51 } 52 53 /** 54 * Connect pattern to lexer. 55 * 56 * @see Doku_Parser_Mode::connectTo() 57 */ 58 public function connectTo($mode) 59 { 60 $this->Lexer->addSpecialPattern('\{\{backlinks>.+?\}\}', $mode, 'plugin_backlinks'); 61 } 62 63 /** 64 * Handler to prepare matched data for the rendering process. 65 * 66 * @see DokuWiki_Syntax_Plugin::handle() 67 */ 68 public function handle($match, $state, $pos, Doku_Handler $handler) 69 { 70 // strip {{backlinks> from start and }} from end 71 $match = substr($match, 12, -2); 72 73 $includeNS = ''; 74 if (strstr($match, "#")) { 75 $includeNS = substr(strstr($match, "#", false), 1); 76 $match = strstr($match, "#", true); 77 } 78 79 return ([$match, $includeNS]); 80 } 81 82 /** 83 * Handles the actual output creation. 84 * 85 * @see DokuWiki_Syntax_Plugin::render() 86 */ 87 public function render($format, Doku_Renderer $renderer, $data) 88 { 89 global $lang; 90 global $INFO; 91 global $ID; 92 93 $id = $ID; 94 // If it's a sidebar, get the original id. 95 if ($INFO != null) { 96 $id = $INFO['id']; 97 } 98 $match = $data[0]; 99 $match = ($match == '.') ? $id : $match; 100 if (strstr($match, ".:")) { 101 resolve_pageid(getNS($id), $match, $exists); 102 } 103 104 if ($format == 'xhtml') { 105 $renderer->info['cache'] = false; 106 107 $backlinks = ft_backlinks($match); 108 109 dbglog($backlinks, "backlinks: all backlinks to: $match"); 110 111 $renderer->doc .= '<div id="plugin__backlinks">' . "\n"; 112 113 $filterNS = $data[1]; 114 if (!empty($backlinks) && !empty($filterNS)) { 115 if (stripos($filterNS, "!", 0) === 0) { 116 $filterNS = substr($filterNS, 1); 117 dbglog($filterNS, "backlinks: exluding all of namespace: $filterNS"); 118 $backlinks = array_filter( 119 $backlinks, 120 static fn($ns) => stripos($ns, $filterNS, 0) !== 0 121 ); 122 } else { 123 dbglog($filterNS, "backlinks: including namespace: $filterNS only"); 124 $backlinks = array_filter( 125 $backlinks, 126 static fn($ns) => stripos($ns, (string) $filterNS, 0) === 0 127 ); 128 } 129 } 130 131 dbglog($backlinks, "backlinks: all backlinks to be rendered"); 132 133 if (!empty($backlinks)) { 134 $renderer->doc .= '<ul class="idx">'; 135 136 foreach ($backlinks as $backlink) { 137 $name = p_get_metadata($backlink, 'title'); 138 if (empty($name)) { 139 $name = $backlink; 140 } 141 $renderer->doc .= '<li><div class="li">'; 142 $renderer->doc .= html_wikilink(':' . $backlink, $name); 143 $renderer->doc .= '</div></li>' . "\n"; 144 } 145 146 $renderer->doc .= '</ul>' . "\n"; 147 } else { 148 $renderer->doc .= "<strong>Plugin Backlinks: " . $lang['nothingfound'] . "</strong>" . "\n"; 149 } 150 151 $renderer->doc .= '</div>' . "\n"; 152 153 return true; 154 } 155 return false; 156 } 157} 158