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 array( 112 PluginUtility::STATE => $state, 113 PluginUtility::PAYLOAD => $match 114 ); 115 116 case DOKU_LEXER_EXIT : 117 // Important otherwise we don't get an exit in the render 118 $node = new Tag(self::TAG, array(), $state, $handler); 119 $context = ""; 120 if ($node->hasParent()) { 121 $parent = $node->getParent(); 122 $context = $parent->getName(); 123 if ($context == syntax_plugin_combo_blockquote::TAG) { 124 $link = $node->getOpeningTag()->getDescendant(syntax_plugin_combo_link::TAG); 125 if (!empty($link)) { 126 $ref = $link->getAttribute(LinkUtility::ATTRIBUTE_REF); 127 if (StringUtility::match($ref, "https:\/\/twitter.com\/[^\/]*\/status\/.*")) { 128 $context = syntax_plugin_combo_blockquote::TWEET; 129 $parent->setType($context); 130 $parent->setContext($context); 131 $node->getOpeningTag()->setContext($context); 132 } 133 } 134 } 135 } 136 return array( 137 PluginUtility::STATE => $state, 138 PluginUtility::CONTEXT => $context); 139 140 141 } 142 return array(); 143 144 } 145 146 /** 147 * Render the output 148 * @param string $format 149 * @param Doku_Renderer $renderer 150 * @param array $data - what the function handle() return'ed 151 * @return boolean - rendered correctly? (however, returned value is not used at the moment) 152 * @see DokuWiki_Syntax_Plugin::render() 153 * 154 * 155 */ 156 function render($format, Doku_Renderer $renderer, $data) 157 { 158 159 if ($format == 'xhtml') { 160 161 /** @var Doku_Renderer_xhtml $renderer */ 162 $state = $data [PluginUtility::STATE]; 163 switch ($state) { 164 case DOKU_LEXER_ENTER : 165 166 $attributes = $data[PluginUtility::ATTRIBUTES]; 167 $context = $data[PluginUtility::CONTEXT]; 168 switch ($context) { 169 170 case syntax_plugin_combo_blockquote::TAG: 171 StringUtility::addEolCharacterIfNotPresent($renderer->doc); 172 $renderer->doc .= "<footer class=\"blockquote-footer\"><cite"; 173 if (sizeof($attributes) > 0) { 174 $inlineAttributes = PluginUtility::array2HTMLAttributes($attributes); 175 $renderer->doc .= " $inlineAttributes>"; 176 } else { 177 $renderer->doc .= '>'; 178 } 179 break; 180 case syntax_plugin_combo_blockquote::TWEET: 181 $renderer->doc .= '</p>'; 182 break; 183 default: 184 $renderer->doc .= "<cite"; 185 if (sizeof($attributes) > 0) { 186 $inlineAttributes = PluginUtility::array2HTMLAttributes($attributes); 187 $renderer->doc .= " $inlineAttributes"; 188 } 189 $renderer->doc .= ">"; 190 } 191 break; 192 193 case DOKU_LEXER_UNMATCHED : 194 $renderer->doc .= PluginUtility::escape($data[PluginUtility::PAYLOAD]); 195 break; 196 197 case DOKU_LEXER_EXIT : 198 199 $context = $data[PluginUtility::CONTEXT]; 200 switch($context){ 201 case syntax_plugin_combo_card::TAG: 202 case syntax_plugin_combo_blockquote::TAG: 203 $renderer->doc .= '</cite>'; 204 $renderer->doc .= '</footer>' . DOKU_LF; 205 break; 206 case syntax_plugin_combo_blockquote::TWEET: 207 // There is no element 208 break; 209 default: 210 $renderer->doc .= '</cite>'.DOKU_LF; 211 212 } 213 break; 214 215 } 216 return true; 217 } 218 219 // unsupported $mode 220 return false; 221 } 222 223 224} 225 226