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