1<?php 2 3use ComboStrap\LogUtility; 4use ComboStrap\MetadataUtility; 5use ComboStrap\PluginUtility; 6use ComboStrap\Page; 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 $page = Page::createPageFromEnvironment(); 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 $disqusIdentifier = MetadataUtility::getMeta(self::META_DISQUS_IDENTIFIER); 133 if (empty($disqusIdentifier)) { 134 135 $disqusIdentifier = $attributes[self::ATTRIBUTE_IDENTIFIER]; 136 if (empty($disqusIdentifier)) { 137 $disqusIdentifier = $page->getId(); 138 } 139 140 $canonical = $page->getCanonical(); 141 if (!empty($canonical)) { 142 $disqusIdentifier = $canonical; 143 } 144 MetadataUtility::setMeta(self::META_DISQUS_IDENTIFIER, $disqusIdentifier); 145 } 146 $disqusConfig = "this.page.identifier = \"$disqusIdentifier\";"; 147 148 $url = $attributes[self::ATTRIBUTE_URL]; 149 if (empty($url)) { 150 $url = $page->getCanonicalUrlOrDefault(); 151 } 152 $disqusConfig .= "this.page.url = $url;"; 153 154 155 $title = $attributes[self::ATTRIBUTE_TITLE]; 156 if (empty($title)) { 157 $title = action_plugin_combo_metatitle::getTitle(); 158 if (!empty($title)) { 159 $disqusConfig .= "this.page.title = $title;"; 160 } 161 } 162 163 $category = $attributes[self::ATTRIBUTE_CATEGORY]; 164 if (empty($category)) { 165 $disqusConfig .= "this.page.category_id = $category;"; 166 } 167 168 169 /** 170 * The javascript 171 */ 172 $renderer->doc .= <<<EOD 173<script charset="utf-8" type="text/javascript"> 174 175 // Configuration 176 177 // The disqus_config should be a var to give it the global scope 178 // Otherwise, disqus will see no config 179 // noinspection ES6ConvertVarToLetConst 180 var disqus_config = function () { 181 $disqusConfig 182 }; 183 184 // Embed the library 185 (function() { 186 const d = document, s = d.createElement('script'); 187 s.src = 'https://$forumShortName.disqus.com/embed.js'; 188 s.setAttribute('data-timestamp', (+new Date()).toString()); 189 (d.head || d.body).appendChild(s); 190 })(); 191 192</script> 193<noscript><a href="https://disqus.com/home/discussion/$forumShortName/$disqusIdentifier/">View the discussion thread.</a></noscript> 194EOD; 195 // The tag 196 $renderer->doc .= '<div id="disqus_thread"></div>'; 197 198 return true; 199 break; 200 case 'metadata': 201 202 } 203 return false; 204 205 } 206 207 208} 209 210