xref: /template/strap/action/pageprotection.php (revision 04fd306c7c155fa133ebb3669986875d65988276)
1<?php
2
3require_once(__DIR__ . '/../ComboStrap/PluginUtility.php');
4
5use ComboStrap\ExecutionContext;
6use ComboStrap\FileSystems;
7use ComboStrap\WikiPath;
8use ComboStrap\Identity;
9use ComboStrap\LowQualityPage;
10use ComboStrap\MarkupPath;
11use ComboStrap\PageProtection;
12use ComboStrap\PagePublicationDate;
13
14
15/**
16 *
17 */
18class action_plugin_combo_pageprotection extends DokuWiki_Action_Plugin
19{
20
21
22    public function register(Doku_Event_Handler $controller)
23    {
24
25
26        /**
27         * https://www.dokuwiki.org/devel:event:pageutils_id_hidepage
28         */
29        $controller->register_hook('PAGEUTILS_ID_HIDEPAGE', 'BEFORE', $this, 'handleHiddenCheck', array());
30
31        /**
32         * https://www.dokuwiki.org/devel:event:auth_acl_check
33         */
34        $controller->register_hook('AUTH_ACL_CHECK', 'AFTER', $this, 'handleAclCheck', array());
35
36        /**
37         * https://www.dokuwiki.org/devel:event:sitemap_generate
38         */
39        $controller->register_hook('SITEMAP_GENERATE', 'BEFORE', $this, 'handleSiteMapGenerate', array());
40
41        /**
42         * https://www.dokuwiki.org/devel:event:search_query_pagelookup
43         */
44        $controller->register_hook('SEARCH_QUERY_PAGELOOKUP', 'AFTER', $this, 'handleSearchPageLookup', array());
45
46        /**
47         * https://www.dokuwiki.org/devel:event:search_query_fullpage
48         */
49        $controller->register_hook('SEARCH_QUERY_FULLPAGE', 'AFTER', $this, 'handleSearchFullPage', array());
50
51        /**
52         * https://www.dokuwiki.org/devel:event:feed_data_process
53         */
54        $controller->register_hook('FEED_DATA_PROCESS', 'BEFORE', $this, 'handleRssFeed', array());
55
56
57        /**
58         * Robots meta
59         * https://www.dokuwiki.org/devel:event:tpl_metaheader_output
60         */
61        $controller->register_hook('TPL_METAHEADER_OUTPUT', 'BEFORE', $this, 'handleRobotsMeta', array());
62
63
64    }
65
66    /**
67     * Set page has hidden
68     * @param $event
69     * @param $param
70     */
71    function handleHiddenCheck(&$event, $param)
72    {
73
74        /**
75         * Only for public
76         */
77        if (Identity::isLoggedIn()) {
78            return;
79        }
80
81        $id = $event->data['id'];
82        if ($id == null) {
83            /**
84             * Happens in test when rendering
85             * with instructions only
86             */
87            return;
88        }
89        $page = MarkupPath::createMarkupFromId($id);
90
91        if ($page->isLowQualityPage()) {
92            if (LowQualityPage::getLowQualityProtectionMode() == PageProtection::CONF_VALUE_HIDDEN) {
93                $event->data['hidden'] = true;
94                return;
95            }
96        }
97        if ($page->isLatePublication()) {
98            if (PagePublicationDate::getLatePublicationProtectionMode() == PageProtection::CONF_VALUE_HIDDEN) {
99                $event->data['hidden'] = true;
100            }
101
102        }
103
104    }
105
106    /**
107     *
108     * https://www.dokuwiki.org/devel:event:auth_acl_check
109     * @param $event
110     * @param $param
111     */
112    function handleAclCheck(&$event, $param)
113    {
114        /**
115         * Only for public
116         *
117         * Note: user is also
118         * to be found at
119         * $user = $event->data['user'];
120         */
121        if (Identity::isLoggedIn()) {
122            return;
123        }
124
125        /**
126         * Are we on a page script
127         */
128        $imageScript = ["/lib/exe/mediamanager.php", "/lib/exe/detail.php"];
129        if (in_array($_SERVER['SCRIPT_NAME'], $imageScript)) {
130            // id may be null or end with a star
131            // this is not a image
132            return;
133        }
134
135        $id = $event->data['id'];
136        if ($id == null) {
137            /**
138             * Happens in test when rendering
139             * with instructions only
140             */
141            return;
142        }
143
144        $dokuPath = WikiPath::createFromUnknownRoot($id);
145        if ($dokuPath->isPage()) {
146
147            /**
148             * It should be only a page
149             * https://www.dokuwiki.org/devel:event:auth_acl_check
150             */
151            $page = MarkupPath::createMarkupFromId($id);
152
153            if ($page->isLowQualityPage()) {
154                if ($this->getConf(LowQualityPage::CONF_LOW_QUALITY_PAGE_PROTECTION_ENABLE, true)) {
155                    $securityConf = $this->getConf(LowQualityPage::CONF_LOW_QUALITY_PAGE_PROTECTION_MODE, PageProtection::CONF_VALUE_ACL);
156                    if ($securityConf == PageProtection::CONF_VALUE_ACL) {
157                        $event->result = AUTH_NONE;
158                        return;
159                    }
160                }
161            }
162            if ($page->isLatePublication()) {
163                if ($this->getConf(PagePublicationDate::CONF_LATE_PUBLICATION_PROTECTION_ENABLE, true)) {
164                    $securityConf = $this->getConf(PagePublicationDate::CONF_LATE_PUBLICATION_PROTECTION_MODE, PageProtection::CONF_VALUE_ACL);
165                    if ($securityConf == PageProtection::CONF_VALUE_ACL) {
166                        $event->result = AUTH_NONE;
167                        return;
168                    }
169                }
170            }
171
172        }
173
174    }
175
176    function handleSiteMapGenerate(&$event, $param)
177    {
178        $pageItems = $event->data["items"];
179        foreach ($pageItems as $key => $pageItem) {
180            $url = $pageItem->url;
181            $dokuPath = WikiPath::createFromUrl($url);
182            $page = MarkupPath::createMarkupFromId($dokuPath->getWikiId());
183            if ($page->isLowQualityPage() && LowQualityPage::isProtectionEnabled()) {
184
185                unset($event->data["items"][$key]);
186                continue;
187
188            }
189            if ($page->isLatePublication() && PagePublicationDate::isLatePublicationProtectionEnabled()) {
190                unset($event->data["items"][$key]);
191            }
192        }
193
194    }
195
196    /**
197     * @param $event
198     * @param $param
199     * The autocomplete do a search on page name
200     */
201    function handleSearchPageLookup(&$event, $param)
202    {
203        $this->excludePageFromSearch($event);
204    }
205
206    /**
207     * @param $event
208     * @param $param
209     * The search page do a search on page name
210     */
211    function handleSearchFullPage(&$event, $param)
212    {
213
214        $this->excludePageFromSearch($event);
215    }
216
217    /**
218     *
219     * @param $event
220     * @param $param
221     * The Rss
222     * https://www.dokuwiki.org/syndication
223     * Example
224     * https://example.com/feed.php?type=rss2&num=5
225     */
226    function handleRssFeed(&$event, $param)
227    {
228        $isLowQualityProtectionEnabled = LowQualityPage::isProtectionEnabled();
229        $isLatePublicationProtectionEnabled = PagePublicationDate::isLatePublicationProtectionEnabled();
230        if (!$isLatePublicationProtectionEnabled && !$isLowQualityProtectionEnabled) {
231            return;
232        }
233
234        $pagesToBeAdded = &$event->data["data"];
235        foreach ($pagesToBeAdded as $key => $data) {
236
237            // To prevent an Illegal string offset 'id'
238            if (isset($data["id"])) {
239
240                $page = MarkupPath::createMarkupFromId($data["id"]);
241
242                if ($page->isLowQualityPage() && $isLowQualityProtectionEnabled) {
243                    $protectionMode = LowQualityPage::getLowQualityProtectionMode();
244                    if ($protectionMode != PageProtection::CONF_VALUE_ROBOT) {
245                        unset($pagesToBeAdded[$key]);
246                    }
247                }
248
249                if ($page->isLatePublication() && $isLatePublicationProtectionEnabled) {
250                    $protectionMode = PagePublicationDate::getLatePublicationProtectionMode();
251                    if ($protectionMode != PageProtection::CONF_VALUE_ROBOT) {
252                        unset($pagesToBeAdded[$key]);
253                    }
254                }
255
256            }
257        }
258
259    }
260
261    /**
262     * @param $event
263     * @param array $protectionModes
264     */
265    private
266    function excludePageFromSearch(&$event, $protectionModes = [PageProtection::CONF_VALUE_ACL, PageProtection::CONF_VALUE_HIDDEN])
267    {
268
269        /**
270         * The value is always an array
271         * but as we got this error:
272         * ```
273         * array_keys() expects parameter 1 to be array
274         * ```
275         * The result is a list of page id
276         */
277        if (is_array($event->result)) {
278            foreach (array_keys($event->result) as $idx) {
279                $page = MarkupPath::createMarkupFromId($idx);
280                if ($page->isLowQualityPage()) {
281                    $securityConf = $this->getConf(LowQualityPage::CONF_LOW_QUALITY_PAGE_PROTECTION_MODE);
282                    if (in_array($securityConf, $protectionModes)) {
283                        unset($event->result[$idx]);
284                        return;
285                    }
286                }
287                if ($page->isLatePublication()) {
288                    $securityConf = $this->getConf(PagePublicationDate::CONF_LATE_PUBLICATION_PROTECTION_MODE);
289                    if (in_array($securityConf, [PageProtection::CONF_VALUE_ACL, PageProtection::CONF_VALUE_HIDDEN])) {
290                        unset($event->result[$idx]);
291                        return;
292                    }
293                }
294            }
295        }
296
297    }
298
299
300    /**
301     * Handle the meta robots
302     * https://www.dokuwiki.org/devel:event:tpl_metaheader_output
303     * @param $event
304     * @param $param
305     */
306    function handleRobotsMeta(&$event, $param)
307    {
308
309        $requestedPath = ExecutionContext::getActualOrCreateFromEnv()->getRequestedPath();
310
311        if (!FileSystems::exists($requestedPath)) {
312            return;
313        }
314
315        $page = MarkupPath::createPageFromPathObject($requestedPath);
316
317        /**
318         * No management for slot page
319         */
320        if ($page->isSlot()) {
321            return;
322        }
323
324        $protected = false;
325        $follow = "nofollow";
326        if ($page->isLowQualityPage() && LowQualityPage::isProtectionEnabled()) {
327            $protected = true;
328            if (LowQualityPage::getLowQualityProtectionMode() == PageProtection::CONF_VALUE_ACL) {
329                $follow = "nofollow";
330            } else {
331                $follow = "follow";
332            }
333        }
334        if ($page->isLatePublication() && PagePublicationDate::isLatePublicationProtectionEnabled()) {
335            $protected = true;
336            if (PagePublicationDate::getLatePublicationProtectionMode() == PageProtection::CONF_VALUE_ACL) {
337                $follow = "nofollow";
338            } else {
339                $follow = "follow";
340            }
341        }
342        if ($protected) {
343            foreach ($event->data['meta'] as $key => $meta) {
344                if (array_key_exists("name", $meta)) {
345                    /**
346                     * We may have several properties
347                     */
348                    if ($meta["name"] == "robots") {
349                        $event->data['meta'][$key]["content"] = "noindex,$follow";
350                    }
351                }
352            }
353        }
354    }
355
356}
357