1<?php 2 3use ComboStrap\LogUtility; 4use ComboStrap\MetadataUtility; 5use ComboStrap\PluginUtility; 6use ComboStrap\UrlCanonical; 7 8require_once(__DIR__ . '/../class/PluginUtility.php'); 9 10/** 11 * Disqus integration 12 * https://combostrap.com/disqus 13 */ 14class syntax_plugin_combo_disqus extends DokuWiki_Syntax_Plugin 15{ 16 17 const CONF_DEFAULT_ATTRIBUTES = 'disqusDefaultAttributes'; 18 19 const ATTRIBUTE_SHORTNAME = "shortname"; 20 const ATTRIBUTE_IDENTIFIER = 'id'; 21 const ATTRIBUTE_TITLE = 'title'; 22 const ATTRIBUTE_URL = 'url'; 23 24 const TAG = 'disqus'; 25 26 const META_DISQUS_IDENTIFIER = "disqus_identifier"; 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::getModeForComponent($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) 108 { 109 110 switch ($format) { 111 112 case 'xhtml': 113 114 list($attributes) = $data; 115 /** @var Doku_Renderer_xhtml $renderer */ 116 117 118 /** 119 * Disqus configuration 120 * https://help.disqus.com/en/articles/1717084-javascript-configuration-variables 121 */ 122 $default = PluginUtility::getTagAttributes($this->getConf(self::CONF_DEFAULT_ATTRIBUTES)); 123 $attributes = PluginUtility::mergeAttributes($attributes, $default); 124 $forumShortName = $attributes[self::ATTRIBUTE_SHORTNAME]; 125 if (empty($forumShortName)) { 126 LogUtility::msg("The disqus forum shortName should not be empty", LogUtility::LVL_MSG_ERROR, self::TAG); 127 return false; 128 } 129 $forumShortName = hsc($forumShortName); 130 131 $disqusIdentifier = MetadataUtility::getMeta(self::META_DISQUS_IDENTIFIER); 132 if (empty($disqusIdentifier)) { 133 134 $disqusIdentifier = $attributes[self::ATTRIBUTE_IDENTIFIER]; 135 if (empty($disqusIdentifier)) { 136 $disqusIdentifier = PluginUtility::getPageId(); 137 } 138 139 $canonical = MetadataUtility::getMeta(UrlCanonical::CANONICAL_PROPERTY); 140 if (!empty($canonical)) { 141 $disqusIdentifier = $canonical; 142 } 143 MetadataUtility::setMeta(self::META_DISQUS_IDENTIFIER, $disqusIdentifier); 144 } 145 $disqusConfig = "this.page.identifier = \"$disqusIdentifier\";"; 146 147 $url = $attributes[self::ATTRIBUTE_URL]; 148 if (empty($url)) { 149 if (!empty($canonical)) { 150 $url = UrlCanonical::getUrl($canonical); 151 } 152 } 153 154 if (!empty($url)) { 155 $disqusConfig .= "this.page.url = $url;"; 156 } 157 158 $title = $attributes[self::ATTRIBUTE_TITLE]; 159 if (empty($title)) { 160 $title = action_plugin_combo_metatitle::getTitle(); 161 if (!empty($title)){ 162 $disqusConfig .= "this.page.title = $title;"; 163 } 164 } 165 166 $category = $attributes[self::ATTRIBUTE_CATEGORY]; 167 if (empty($category)){ 168 $disqusConfig .= "this.page.category_id = $category;"; 169 } 170 171 172 /** 173 * The javascript 174 */ 175 $renderer->doc .= <<<EOD 176<script charset="utf-8" type="text/javascript"> 177 178 // Configuration 179 180 // The disqus_config should be a var to give it the global scope 181 // Otherwise, disqus will see no config 182 // noinspection ES6ConvertVarToLetConst 183 var disqus_config = function () { 184 $disqusConfig 185 }; 186 187 // Embed the library 188 (function() { 189 const d = document, s = d.createElement('script'); 190 s.src = 'https://$forumShortName.disqus.com/embed.js'; 191 s.setAttribute('data-timestamp', (+new Date()).toString()); 192 (d.head || d.body).appendChild(s); 193 })(); 194 195</script> 196<noscript><a href="https://disqus.com/home/discussion/$forumShortName/$disqusIdentifier/">View the discussion thread.</a></noscript> 197EOD; 198 // The tag 199 $renderer->doc .= '<div id="disqus_thread"></div>'; 200 201 return true; 202 break; 203 case 'metadata': 204 205 } 206 return false; 207 208 } 209 210 211} 212 213