xref: /plugin/combo/syntax/disqus.php (revision 4cadd4f8c541149bdda95f080e38a6d4e3a640ca)
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): bool
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