1<?php 2 3 4require_once(__DIR__ . "/../class/Analytics.php"); 5require_once(__DIR__ . "/../class/PluginUtility.php"); 6require_once(__DIR__ . "/../class/LinkUtility.php"); 7require_once(__DIR__ . "/../class/HtmlUtility.php"); 8 9use ComboStrap\Analytics; 10use ComboStrap\LinkUtility; 11use ComboStrap\LogUtility; 12use ComboStrap\Page; 13use ComboStrap\PluginUtility; 14use ComboStrap\LowQualityPage; 15use ComboStrap\Tag; 16 17if (!defined('DOKU_INC')) die(); 18 19/** 20 * 21 * A link pattern to take over the link of Dokuwiki 22 * and transform it as a bootstrap link 23 * 24 * The handle of the move of link is to be found in the 25 * admin action {@link action_plugin_combo_linkmove} 26 * 27 */ 28class syntax_plugin_combo_link extends DokuWiki_Syntax_Plugin 29{ 30 const TAG = 'link'; 31 32 33 /** 34 * Syntax Type. 35 * 36 * Needs to return one of the mode types defined in $PARSER_MODES in parser.php 37 * @see https://www.dokuwiki.org/devel:syntax_plugins#syntax_types 38 */ 39 function getType() 40 { 41 return 'substition'; 42 } 43 44 /** 45 * How Dokuwiki will add P element 46 * 47 * * 'normal' - The plugin can be used inside paragraphs 48 * * 'block' - Open paragraphs need to be closed before plugin output - block should not be inside paragraphs 49 * * 'stack' - Special case. Plugin wraps other paragraphs. - Stacks can contain paragraphs 50 * 51 * @see DokuWiki_Syntax_Plugin::getPType() 52 */ 53 function getPType() 54 { 55 return 'normal'; 56 } 57 58 /** 59 * @return array 60 * Allow which kind of plugin inside 61 * 62 * No one of array('container', 'baseonly', 'formatting', 'substition', 'protected', 'disabled', 'paragraphs') 63 * because we manage self the content and we call self the parser 64 */ 65 function getAllowedTypes() 66 { 67 return array('substition', 'formatting', 'disabled'); 68 } 69 70 /** 71 * @see Doku_Parser_Mode::getSort() 72 * The mode with the lowest sort number will win out 73 */ 74 function getSort() 75 { 76 return 100; 77 } 78 79 80 function connectTo($mode) 81 { 82 83 $this->Lexer->addSpecialPattern(LinkUtility::LINK_PATTERN, $mode, PluginUtility::getModeForComponent($this->getPluginComponent())); 84 85 } 86 87 88 /** 89 * The handler for an internal link 90 * based on `internallink` in {@link Doku_Handler} 91 * The handler call the good renderer in {@link Doku_Renderer_xhtml} with 92 * the parameters (ie for instance internallink) 93 * @param string $match 94 * @param int $state 95 * @param int $pos 96 * @param Doku_Handler $handler 97 * @return array|bool 98 */ 99 function handle($match, $state, $pos, Doku_Handler $handler) 100 { 101 102 /** 103 * Because we use the specialPattern, there is only one state ie DOKU_LEXER_SPECIAL 104 */ 105 $attributes = LinkUtility::getAttributes($match); 106 $tag = new Tag(self::TAG, $attributes, $state, $handler->calls); 107 $parent = $tag->getParent(); 108 $parentName = ""; 109 if ($parent != null) { 110 $parentName = $parent->getName(); 111 } 112 return array( 113 PluginUtility::ATTRIBUTES => $attributes, 114 PluginUtility::PARENT_TAG => $parentName 115 ); 116 117 118 } 119 120 /** 121 * Render the output 122 * @param string $format 123 * @param Doku_Renderer $renderer 124 * @param array $data - what the function handle() return'ed 125 * @return boolean - rendered correctly? (however, returned value is not used at the moment) 126 * @see DokuWiki_Syntax_Plugin::render() 127 * 128 * 129 */ 130 function render($format, Doku_Renderer $renderer, $data) 131 { 132 // The data 133 switch ($format) { 134 case 'xhtml': 135 136 /** @var Doku_Renderer_xhtml $renderer */ 137 138 /** 139 * Cache problem may occurs while releasing 140 */ 141 if (isset($data[PluginUtility::ATTRIBUTES])) { 142 $attributes = $data[PluginUtility::ATTRIBUTES]; 143 } else { 144 $attributes = $data; 145 } 146 147 $type = $attributes[LinkUtility::ATTRIBUTE_TYPE]; 148 $id = $attributes[LinkUtility::ATTRIBUTE_ID]; 149 150 /** 151 * Email are also link for Dokuwiki 152 * And there is no notion of page. 153 * For the low quality page functionality, 154 * we split the process of the internal link 155 */ 156 $lowLink = false; 157 if ($type == LinkUtility::TYPE_INTERNAL) { 158 /** 159 * If this is a low quality internal page, 160 * print a shallow link for the anonymous user 161 */ 162 $qualifiedPageId = LinkUtility::toQualifiedLink($id); 163 $page = new Page($qualifiedPageId); 164 if ($this->getConf(LowQualityPage::CONF_LOW_QUALITY_PAGE_PROTECTION_ENABLE) 165 && $page->isLowQualityPage()) { 166 167 $lowLink = true; 168 } 169 } 170 171 /** 172 * Render the link 173 */ 174 $htmlLink = LinkUtility::renderLinkDefault($renderer, $attributes, $lowLink); 175 176 /** 177 * Extra styling 178 */ 179 $parentClassWithoutClass = array( 180 syntax_plugin_combo_button::TAG, 181 syntax_plugin_combo_cite::TAG, 182 syntax_plugin_combo_dropdown::TAG, 183 syntax_plugin_combo_listitem::TAG, 184 syntax_plugin_combo_preformatted::TAG 185 ); 186 if (page_exists($id) && in_array($data[PluginUtility::PARENT_TAG], $parentClassWithoutClass)) { 187 $htmlLink = LinkUtility::deleteDokuWikiClass($htmlLink); 188 } 189 190 if ($data[PluginUtility::PARENT_TAG] == syntax_plugin_combo_button::TAG) { 191 // We could also apply the class ie btn-secondary ... 192 $htmlLink = LinkUtility::inheritColorFromParent($htmlLink); 193 } 194 195 /** 196 * Add it to the rendering 197 */ 198 $renderer->doc .= $htmlLink; 199 200 return true; 201 break; 202 203 case 204 'metadata': 205 206 /** 207 * Keep track of the backlinks ie meta['relation']['references'] 208 * @var Doku_Renderer_metadata $renderer 209 */ 210 if (isset($data[PluginUtility::ATTRIBUTES])) { 211 $attributes = $data[PluginUtility::ATTRIBUTES]; 212 } else { 213 $attributes = $data; 214 } 215 LinkUtility::handleMetadata($renderer, $attributes); 216 217 return true; 218 break; 219 220 case Analytics::RENDERER_FORMAT: 221 /** 222 * 223 * @var renderer_plugin_combo_analytics $renderer 224 */ 225 $attributes = $data[PluginUtility::ATTRIBUTES]; 226 LinkUtility::processLinkStats($attributes, $renderer->stats); 227 break; 228 229 } 230 // unsupported $mode 231 return false; 232 } 233 234 235} 236 237