1<?php 2 3// implementation of 4// https://developer.mozilla.org/en-US/docs/Web/HTML/Element/cite 5 6// must be run within Dokuwiki 7use ComboStrap\LinkUtility; 8use ComboStrap\StringUtility; 9use ComboStrap\Tag; 10use ComboStrap\PluginUtility; 11 12require_once(__DIR__ . '/../class/StringUtility.php'); 13 14if (!defined('DOKU_INC')) die(); 15 16 17class syntax_plugin_combo_cite extends DokuWiki_Syntax_Plugin 18{ 19 const TAG = "cite"; 20 21 22 function getType() 23 { 24 return 'container'; 25 } 26 27 /** 28 * How Dokuwiki will add P element 29 * 30 * * 'normal' - The plugin can be used inside paragraphs 31 * * 'block' - Open paragraphs need to be closed before plugin output - block should not be inside paragraphs 32 * * 'stack' - Special case. Plugin wraps other paragraphs. - Stacks can contain paragraphs 33 * 34 * @see DokuWiki_Syntax_Plugin::getPType() 35 */ 36 function getPType() 37 { 38 return 'normal'; 39 } 40 41 /** 42 * @return array 43 * Allow which kind of plugin inside 44 * 45 * No one of array('baseonly','container', 'formatting', 'substition', 'protected', 'disabled', 'paragraphs') 46 * because we manage self the content and we call self the parser 47 * 48 * Return an array of one or more of the mode types {@link $PARSER_MODES} in Parser.php 49 */ 50 function getAllowedTypes() 51 { 52 return array('baseonly', 'container', 'formatting', 'substition', 'protected', 'disabled', 'paragraphs'); 53 } 54 55 function getSort() 56 { 57 /** 58 * Should be less than the cite syntax plugin 59 **/ 60 return 200; 61 } 62 63 64 function connectTo($mode) 65 { 66 67 $pattern = PluginUtility::getContainerTagPattern(self::TAG); 68 $this->Lexer->addEntryPattern($pattern, $mode, PluginUtility::getModeForComponent($this->getPluginComponent())); 69 70 } 71 72 73 function postConnect() 74 { 75 76 $this->Lexer->addExitPattern('</' . syntax_plugin_combo_cite::TAG . '>', PluginUtility::getModeForComponent($this->getPluginComponent())); 77 78 } 79 80 /** 81 * 82 * The handle function goal is to parse the matched syntax through the pattern function 83 * and to return the result for use in the renderer 84 * This result is always cached until the page is modified. 85 * @param string $match 86 * @param int $state 87 * @param int $pos - byte position in the original source file 88 * @param Doku_Handler $handler 89 * @return array|bool 90 * @see DokuWiki_Syntax_Plugin::handle() 91 * 92 */ 93 function handle($match, $state, $pos, Doku_Handler $handler) 94 { 95 96 switch ($state) { 97 98 case DOKU_LEXER_ENTER : 99 $tagAttributes = PluginUtility::getTagAttributes($match); 100 $node = new Tag(self::TAG, $tagAttributes, $state, $handler); 101 $parent = ""; 102 if ($node->hasParent()) { 103 $parent = $node->getParent()->getName(); 104 } 105 return array( 106 PluginUtility::STATE => $state, 107 PluginUtility::ATTRIBUTES => $tagAttributes, 108 PluginUtility::CONTEXT => $parent); 109 110 case DOKU_LEXER_UNMATCHED : 111 return PluginUtility::handleAndReturnUnmatchedData(self::TAG, $match, $handler); 112 113 case DOKU_LEXER_EXIT : 114 // Important otherwise we don't get an exit in the render 115 $node = new Tag(self::TAG, array(), $state, $handler); 116 $context = ""; 117 if ($node->hasParent()) { 118 $parent = $node->getParent(); 119 $context = $parent->getName(); 120 if ($context == syntax_plugin_combo_blockquote::TAG) { 121 $link = $node->getOpeningTag()->getDescendant(syntax_plugin_combo_link::TAG); 122 if (!empty($link)) { 123 $ref = $link->getAttribute(LinkUtility::ATTRIBUTE_REF); 124 if (StringUtility::match($ref, "https:\/\/twitter.com\/[^\/]*\/status\/.*")) { 125 $context = syntax_plugin_combo_blockquote::TWEET; 126 $parent->setType($context); 127 $parent->setContext($context); 128 $node->getOpeningTag()->setContext($context); 129 } 130 } 131 } 132 } 133 return array( 134 PluginUtility::STATE => $state, 135 PluginUtility::CONTEXT => $context); 136 137 138 } 139 return array(); 140 141 } 142 143 /** 144 * Render the output 145 * @param string $format 146 * @param Doku_Renderer $renderer 147 * @param array $data - what the function handle() return'ed 148 * @return boolean - rendered correctly? (however, returned value is not used at the moment) 149 * @see DokuWiki_Syntax_Plugin::render() 150 * 151 * 152 */ 153 function render($format, Doku_Renderer $renderer, $data) 154 { 155 156 if ($format == 'xhtml') { 157 158 /** @var Doku_Renderer_xhtml $renderer */ 159 $state = $data [PluginUtility::STATE]; 160 switch ($state) { 161 case DOKU_LEXER_ENTER : 162 163 $attributes = $data[PluginUtility::ATTRIBUTES]; 164 $context = $data[PluginUtility::CONTEXT]; 165 switch ($context) { 166 167 case syntax_plugin_combo_blockquote::TAG: 168 StringUtility::addEolCharacterIfNotPresent($renderer->doc); 169 $renderer->doc .= "<footer class=\"blockquote-footer\"><cite"; 170 if (sizeof($attributes) > 0) { 171 $inlineAttributes = PluginUtility::array2HTMLAttributes($attributes); 172 $renderer->doc .= " $inlineAttributes>"; 173 } else { 174 $renderer->doc .= '>'; 175 } 176 break; 177 case syntax_plugin_combo_blockquote::TWEET: 178 $renderer->doc .= '</p>'; 179 break; 180 default: 181 $renderer->doc .= "<cite"; 182 if (sizeof($attributes) > 0) { 183 $inlineAttributes = PluginUtility::array2HTMLAttributes($attributes); 184 $renderer->doc .= " $inlineAttributes"; 185 } 186 $renderer->doc .= ">"; 187 } 188 break; 189 190 case DOKU_LEXER_UNMATCHED : 191 $renderer->doc .= PluginUtility::renderUnmatched($data); 192 break; 193 194 case DOKU_LEXER_EXIT : 195 196 $context = $data[PluginUtility::CONTEXT]; 197 switch ($context) { 198 case syntax_plugin_combo_card::TAG: 199 case syntax_plugin_combo_blockquote::TAG: 200 $renderer->doc .= '</cite>'; 201 $renderer->doc .= '</footer>' . DOKU_LF; 202 break; 203 case syntax_plugin_combo_blockquote::TWEET: 204 // There is no element 205 break; 206 default: 207 $renderer->doc .= '</cite>' . DOKU_LF; 208 209 } 210 break; 211 212 } 213 return true; 214 } 215 216 // unsupported $mode 217 return false; 218 } 219 220 221} 222 223