xref: /plugin/combo/syntax/disqus.php (revision 37748cd8654635afbeca80942126742f0f4cc346)
1<?php
2
3use ComboStrap\LogUtility;
4use ComboStrap\MetadataUtility;
5use ComboStrap\PluginUtility;
6use ComboStrap\Page;
7
8require_once(__DIR__ . '/../ComboStrap/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::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::createRequestedPageFromEnvironment();
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