1<?php 2 3use ComboStrap\DisqusIdentifier; 4use ComboStrap\ExceptionNotExists; 5use ComboStrap\LogUtility; 6use ComboStrap\Meta\Store\MetadataDokuWikiStore; 7use ComboStrap\MarkupPath; 8use ComboStrap\PluginUtility; 9 10 11/** 12 * Disqus integration 13 * https://combostrap.com/disqus 14 */ 15class syntax_plugin_combo_disqus extends DokuWiki_Syntax_Plugin 16{ 17 18 const CONF_DEFAULT_ATTRIBUTES = 'disqusDefaultAttributes'; 19 20 const ATTRIBUTE_SHORTNAME = "shortname"; 21 const ATTRIBUTE_IDENTIFIER = 'id'; 22 const ATTRIBUTE_TITLE = 'title'; 23 const ATTRIBUTE_URL = 'url'; 24 25 const TAG = 'disqus'; 26 27 const ATTRIBUTE_CATEGORY = "category"; 28 29 /** 30 * Syntax Type. 31 * 32 * Needs to return one of the mode types defined in $PARSER_MODES in parser.php 33 * @see https://www.dokuwiki.org/devel:syntax_plugins#syntax_types 34 */ 35 function getType() 36 { 37 return 'substition'; 38 } 39 40 /** 41 * Syntax Type. 42 * 43 * Needs to return one of the mode types defined in $PARSER_MODES in parser.php 44 * @see DokuWiki_Syntax_Plugin::getType() 45 */ 46 function getPType() 47 { 48 return 'block'; 49 } 50 51 /** 52 * Plugin priority 53 * 54 * @see Doku_Parser_Mode::getSort() 55 * 56 * the mode with the lowest sort number will win out 57 */ 58 function getSort() 59 { 60 return 160; 61 } 62 63 /** 64 * Create a pattern that will called this plugin 65 * 66 * @param string $mode 67 * @see Doku_Parser_Mode::connectTo() 68 */ 69 function connectTo($mode) 70 { 71 $pattern = PluginUtility::getEmptyTagPattern(self::TAG); 72 $this->Lexer->addSpecialPattern($pattern, $mode, PluginUtility::getModeFromTag($this->getPluginComponent())); 73 } 74 75 /** 76 * 77 * The handle function goal is to parse the matched syntax through the pattern function 78 * and to return the result for use in the renderer 79 * This result is always cached until the page is modified. 80 * @param string $match 81 * @param int $state 82 * @param int $pos 83 * @param Doku_Handler $handler 84 * @return array|bool 85 * @see DokuWiki_Syntax_Plugin::handle() 86 * 87 */ 88 function handle($match, $state, $pos, Doku_Handler $handler) 89 { 90 91 92 $attributes = PluginUtility::getTagAttributes($match); 93 return array($attributes); 94 95 96 } 97 98 /** 99 * Render the output 100 * @param string $format 101 * @param Doku_Renderer $renderer 102 * @param array $data - what the function handle() return'ed 103 * @return boolean - rendered correctly? (however, returned value is not used at the moment) 104 * @see DokuWiki_Syntax_Plugin::render() 105 * 106 */ 107 function render($format, Doku_Renderer $renderer, $data): bool 108 { 109 110 switch ($format) { 111 112 case 'xhtml': 113 114 list($attributes) = $data; 115 /** @var Doku_Renderer_xhtml $renderer */ 116 117 $page = MarkupPath::createFromRequestedPage(); 118 119 /** 120 * Disqus configuration 121 * https://help.disqus.com/en/articles/1717084-javascript-configuration-variables 122 */ 123 $default = PluginUtility::getTagAttributes($this->getConf(self::CONF_DEFAULT_ATTRIBUTES)); 124 $attributes = PluginUtility::mergeAttributes($attributes, $default); 125 $forumShortName = $attributes[self::ATTRIBUTE_SHORTNAME]; 126 if (empty($forumShortName)) { 127 LogUtility::msg("The disqus forum shortName should not be empty", LogUtility::LVL_MSG_ERROR, self::TAG); 128 return false; 129 } 130 $forumShortName = hsc($forumShortName); 131 132 /** 133 * @deprecated the page id is used 134 */ 135 $disqusIdentifier = MetadataDokuWikiStore::getOrCreateFromResource($page) 136 ->getFromName(DisqusIdentifier::PROPERTY_NAME); 137 if (empty($disqusIdentifier)) { 138 139 $disqusIdentifier = $attributes[self::ATTRIBUTE_IDENTIFIER]; 140 if (empty($disqusIdentifier)) { 141 try { 142 $disqusIdentifier = $page->getPageId(); 143 } catch (ExceptionNotExists $e) { 144 // the page does not exists 145 return false; 146 } 147 } 148 149 } 150 $disqusConfig = "this.page.identifier = \"$disqusIdentifier\";"; 151 152 $url = $attributes[self::ATTRIBUTE_URL]; 153 if (empty($url)) { 154 $url = $page->getCanonicalUrl(); 155 } 156 $disqusConfig .= "this.page.url = $url;"; 157 158 159 $title = $attributes[self::ATTRIBUTE_TITLE]; 160 if (empty($title)) { 161 $title = action_plugin_combo_metatitle::getHtmlTitle(); 162 if (!empty($title)) { 163 $disqusConfig .= "this.page.title = $title;"; 164 } 165 } 166 167 $category = $attributes[self::ATTRIBUTE_CATEGORY]; 168 if (empty($category)) { 169 $disqusConfig .= "this.page.category_id = $category;"; 170 } 171 172 173 /** 174 * The javascript 175 */ 176 $renderer->doc .= <<<EOD 177<script charset="utf-8" type="text/javascript"> 178 179 // Configuration 180 181 // The disqus_config should be a var to give it the global scope 182 // Otherwise, disqus will see no config 183 // noinspection ES6ConvertVarToLetConst 184 var disqus_config = function () { 185 $disqusConfig 186 }; 187 188 // Embed the library 189 (function() { 190 const d = document, s = d.createElement('script'); 191 s.src = 'https://$forumShortName.disqus.com/embed.js'; 192 s.setAttribute('data-timestamp', (+new Date()).toString()); 193 (d.head || d.body).appendChild(s); 194 })(); 195 196</script> 197<noscript><a href="https://disqus.com/home/discussion/$forumShortName/$disqusIdentifier/">View the discussion thread.</a></noscript> 198EOD; 199 // The tag 200 $renderer->doc .= '<div id="disqus_thread"></div>'; 201 202 return true; 203 204 case 'metadata': 205 206 } 207 return false; 208 209 } 210 211 212} 213 214