xref: /plugin/combo/action/pageprotection.php (revision 04fd306c7c155fa133ebb3669986875d65988276)
15f891b7eSNickeau<?php
25f891b7eSNickeau
3c3437056SNickeaurequire_once(__DIR__ . '/../ComboStrap/PluginUtility.php');
45f891b7eSNickeau
5*04fd306cSNickeauuse ComboStrap\ExecutionContext;
6*04fd306cSNickeauuse ComboStrap\FileSystems;
7*04fd306cSNickeauuse ComboStrap\WikiPath;
8c3437056SNickeauuse ComboStrap\Identity;
95f891b7eSNickeauuse ComboStrap\LowQualityPage;
10*04fd306cSNickeauuse ComboStrap\MarkupPath;
115f891b7eSNickeauuse ComboStrap\PageProtection;
12c3437056SNickeauuse ComboStrap\PagePublicationDate;
135f891b7eSNickeau
14c3437056SNickeau
155f891b7eSNickeau/**
165f891b7eSNickeau *
175f891b7eSNickeau */
185f891b7eSNickeauclass action_plugin_combo_pageprotection extends DokuWiki_Action_Plugin
195f891b7eSNickeau{
205f891b7eSNickeau
215f891b7eSNickeau
225f891b7eSNickeau    public function register(Doku_Event_Handler $controller)
235f891b7eSNickeau    {
245f891b7eSNickeau
255f891b7eSNickeau
265f891b7eSNickeau        /**
275f891b7eSNickeau         * https://www.dokuwiki.org/devel:event:pageutils_id_hidepage
285f891b7eSNickeau         */
295f891b7eSNickeau        $controller->register_hook('PAGEUTILS_ID_HIDEPAGE', 'BEFORE', $this, 'handleHiddenCheck', array());
3085e82846SNickeau
315f891b7eSNickeau        /**
325f891b7eSNickeau         * https://www.dokuwiki.org/devel:event:auth_acl_check
335f891b7eSNickeau         */
345f891b7eSNickeau        $controller->register_hook('AUTH_ACL_CHECK', 'AFTER', $this, 'handleAclCheck', array());
3585e82846SNickeau
3685e82846SNickeau        /**
3785e82846SNickeau         * https://www.dokuwiki.org/devel:event:sitemap_generate
3885e82846SNickeau         */
3985e82846SNickeau        $controller->register_hook('SITEMAP_GENERATE', 'BEFORE', $this, 'handleSiteMapGenerate', array());
405f891b7eSNickeau
415f891b7eSNickeau        /**
425f891b7eSNickeau         * https://www.dokuwiki.org/devel:event:search_query_pagelookup
435f891b7eSNickeau         */
445f891b7eSNickeau        $controller->register_hook('SEARCH_QUERY_PAGELOOKUP', 'AFTER', $this, 'handleSearchPageLookup', array());
455f891b7eSNickeau
465f891b7eSNickeau        /**
475f891b7eSNickeau         * https://www.dokuwiki.org/devel:event:search_query_fullpage
485f891b7eSNickeau         */
495f891b7eSNickeau        $controller->register_hook('SEARCH_QUERY_FULLPAGE', 'AFTER', $this, 'handleSearchFullPage', array());
5085e82846SNickeau
515f891b7eSNickeau        /**
525f891b7eSNickeau         * https://www.dokuwiki.org/devel:event:feed_data_process
535f891b7eSNickeau         */
5485e82846SNickeau        $controller->register_hook('FEED_DATA_PROCESS', 'BEFORE', $this, 'handleRssFeed', array());
555f891b7eSNickeau
565f891b7eSNickeau
5785e82846SNickeau        /**
5885e82846SNickeau         * Robots meta
5985e82846SNickeau         * https://www.dokuwiki.org/devel:event:tpl_metaheader_output
6085e82846SNickeau         */
6185e82846SNickeau        $controller->register_hook('TPL_METAHEADER_OUTPUT', 'BEFORE', $this, 'handleRobotsMeta', array());
6285e82846SNickeau
635f891b7eSNickeau
645f891b7eSNickeau    }
655f891b7eSNickeau
665f891b7eSNickeau    /**
6785e82846SNickeau     * Set page has hidden
685f891b7eSNickeau     * @param $event
695f891b7eSNickeau     * @param $param
705f891b7eSNickeau     */
715f891b7eSNickeau    function handleHiddenCheck(&$event, $param)
725f891b7eSNickeau    {
735f891b7eSNickeau
7485e82846SNickeau        /**
7585e82846SNickeau         * Only for public
7685e82846SNickeau         */
7785e82846SNickeau        if (Identity::isLoggedIn()) {
7885e82846SNickeau            return;
7985e82846SNickeau        }
805f891b7eSNickeau
8185e82846SNickeau        $id = $event->data['id'];
8285e82846SNickeau        if ($id == null) {
8385e82846SNickeau            /**
8485e82846SNickeau             * Happens in test when rendering
8585e82846SNickeau             * with instructions only
8685e82846SNickeau             */
8785e82846SNickeau            return;
8885e82846SNickeau        }
89*04fd306cSNickeau        $page = MarkupPath::createMarkupFromId($id);
9085e82846SNickeau
9185e82846SNickeau        if ($page->isLowQualityPage()) {
9285e82846SNickeau            if (LowQualityPage::getLowQualityProtectionMode() == PageProtection::CONF_VALUE_HIDDEN) {
9385e82846SNickeau                $event->data['hidden'] = true;
9485e82846SNickeau                return;
9585e82846SNickeau            }
9685e82846SNickeau        }
9785e82846SNickeau        if ($page->isLatePublication()) {
98c3437056SNickeau            if (PagePublicationDate::getLatePublicationProtectionMode() == PageProtection::CONF_VALUE_HIDDEN) {
995f891b7eSNickeau                $event->data['hidden'] = true;
1005f891b7eSNickeau            }
1015f891b7eSNickeau
1025f891b7eSNickeau        }
1035f891b7eSNickeau
10485e82846SNickeau    }
10585e82846SNickeau
1065f891b7eSNickeau    /**
10785e82846SNickeau     *
10885e82846SNickeau     * https://www.dokuwiki.org/devel:event:auth_acl_check
1095f891b7eSNickeau     * @param $event
1105f891b7eSNickeau     * @param $param
1115f891b7eSNickeau     */
1125f891b7eSNickeau    function handleAclCheck(&$event, $param)
1135f891b7eSNickeau    {
11485e82846SNickeau        /**
11585e82846SNickeau         * Only for public
11685e82846SNickeau         *
11785e82846SNickeau         * Note: user is also
11885e82846SNickeau         * to be found at
11985e82846SNickeau         * $user = $event->data['user'];
12085e82846SNickeau         */
12185e82846SNickeau        if (Identity::isLoggedIn()) {
12285e82846SNickeau            return;
12385e82846SNickeau        }
1245f891b7eSNickeau
12532b85071SNickeau        /**
12621913ab3SNickeau         * Are we on a page script
12732b85071SNickeau         */
12821913ab3SNickeau        $imageScript = ["/lib/exe/mediamanager.php", "/lib/exe/detail.php"];
12921913ab3SNickeau        if (in_array($_SERVER['SCRIPT_NAME'], $imageScript)) {
13021913ab3SNickeau            // id may be null or end with a star
13121913ab3SNickeau            // this is not a image
1325f891b7eSNickeau            return;
13321913ab3SNickeau        }
13432b85071SNickeau
13521913ab3SNickeau        $id = $event->data['id'];
136*04fd306cSNickeau        if ($id == null) {
137*04fd306cSNickeau            /**
138*04fd306cSNickeau             * Happens in test when rendering
139*04fd306cSNickeau             * with instructions only
140*04fd306cSNickeau             */
141*04fd306cSNickeau            return;
142*04fd306cSNickeau        }
14332b85071SNickeau
144*04fd306cSNickeau        $dokuPath = WikiPath::createFromUnknownRoot($id);
14521913ab3SNickeau        if ($dokuPath->isPage()) {
14685e82846SNickeau
14721913ab3SNickeau            /**
14821913ab3SNickeau             * It should be only a page
14921913ab3SNickeau             * https://www.dokuwiki.org/devel:event:auth_acl_check
15021913ab3SNickeau             */
151*04fd306cSNickeau            $page = MarkupPath::createMarkupFromId($id);
15285e82846SNickeau
15385e82846SNickeau            if ($page->isLowQualityPage()) {
15485e82846SNickeau                if ($this->getConf(LowQualityPage::CONF_LOW_QUALITY_PAGE_PROTECTION_ENABLE, true)) {
15585e82846SNickeau                    $securityConf = $this->getConf(LowQualityPage::CONF_LOW_QUALITY_PAGE_PROTECTION_MODE, PageProtection::CONF_VALUE_ACL);
15685e82846SNickeau                    if ($securityConf == PageProtection::CONF_VALUE_ACL) {
1575f891b7eSNickeau                        $event->result = AUTH_NONE;
15885e82846SNickeau                        return;
15985e82846SNickeau                    }
16085e82846SNickeau                }
16185e82846SNickeau            }
16285e82846SNickeau            if ($page->isLatePublication()) {
163c3437056SNickeau                if ($this->getConf(PagePublicationDate::CONF_LATE_PUBLICATION_PROTECTION_ENABLE, true)) {
164c3437056SNickeau                    $securityConf = $this->getConf(PagePublicationDate::CONF_LATE_PUBLICATION_PROTECTION_MODE, PageProtection::CONF_VALUE_ACL);
16585e82846SNickeau                    if ($securityConf == PageProtection::CONF_VALUE_ACL) {
16685e82846SNickeau                        $event->result = AUTH_NONE;
16785e82846SNickeau                        return;
16885e82846SNickeau                    }
16985e82846SNickeau                }
17085e82846SNickeau            }
17185e82846SNickeau
17285e82846SNickeau        }
17385e82846SNickeau
17485e82846SNickeau    }
17585e82846SNickeau
17685e82846SNickeau    function handleSiteMapGenerate(&$event, $param)
17785e82846SNickeau    {
17885e82846SNickeau        $pageItems = $event->data["items"];
17985e82846SNickeau        foreach ($pageItems as $key => $pageItem) {
18085e82846SNickeau            $url = $pageItem->url;
181*04fd306cSNickeau            $dokuPath = WikiPath::createFromUrl($url);
182*04fd306cSNickeau            $page = MarkupPath::createMarkupFromId($dokuPath->getWikiId());
18385e82846SNickeau            if ($page->isLowQualityPage() && LowQualityPage::isProtectionEnabled()) {
18485e82846SNickeau
18585e82846SNickeau                unset($event->data["items"][$key]);
18685e82846SNickeau                continue;
18785e82846SNickeau
18885e82846SNickeau            }
189c3437056SNickeau            if ($page->isLatePublication() && PagePublicationDate::isLatePublicationProtectionEnabled()) {
19085e82846SNickeau                unset($event->data["items"][$key]);
1915f891b7eSNickeau            }
1925f891b7eSNickeau        }
1935f891b7eSNickeau
1945f891b7eSNickeau    }
1955f891b7eSNickeau
1965f891b7eSNickeau    /**
1975f891b7eSNickeau     * @param $event
1985f891b7eSNickeau     * @param $param
1995f891b7eSNickeau     * The autocomplete do a search on page name
2005f891b7eSNickeau     */
2015f891b7eSNickeau    function handleSearchPageLookup(&$event, $param)
2025f891b7eSNickeau    {
2035f891b7eSNickeau        $this->excludePageFromSearch($event);
2045f891b7eSNickeau    }
2055f891b7eSNickeau
2065f891b7eSNickeau    /**
2075f891b7eSNickeau     * @param $event
2085f891b7eSNickeau     * @param $param
2095f891b7eSNickeau     * The search page do a search on page name
2105f891b7eSNickeau     */
2115f891b7eSNickeau    function handleSearchFullPage(&$event, $param)
2125f891b7eSNickeau    {
2135f891b7eSNickeau
2145f891b7eSNickeau        $this->excludePageFromSearch($event);
2155f891b7eSNickeau    }
2165f891b7eSNickeau
2175f891b7eSNickeau    /**
2185f891b7eSNickeau     *
2195f891b7eSNickeau     * @param $event
2205f891b7eSNickeau     * @param $param
2215f891b7eSNickeau     * The Rss
2225f891b7eSNickeau     * https://www.dokuwiki.org/syndication
2235f891b7eSNickeau     * Example
2245f891b7eSNickeau     * https://example.com/feed.php?type=rss2&num=5
2255f891b7eSNickeau     */
2265f891b7eSNickeau    function handleRssFeed(&$event, $param)
2275f891b7eSNickeau    {
22885e82846SNickeau        $isLowQualityProtectionEnabled = LowQualityPage::isProtectionEnabled();
229c3437056SNickeau        $isLatePublicationProtectionEnabled = PagePublicationDate::isLatePublicationProtectionEnabled();
23085e82846SNickeau        if (!$isLatePublicationProtectionEnabled && !$isLowQualityProtectionEnabled) {
23185e82846SNickeau            return;
23285e82846SNickeau        }
23385e82846SNickeau
23485e82846SNickeau        $pagesToBeAdded = &$event->data["data"];
23585e82846SNickeau        foreach ($pagesToBeAdded as $key => $data) {
23685e82846SNickeau
237e8b2ff59SNickeau            // To prevent an Illegal string offset 'id'
238e8b2ff59SNickeau            if (isset($data["id"])) {
239e8b2ff59SNickeau
240*04fd306cSNickeau                $page = MarkupPath::createMarkupFromId($data["id"]);
24185e82846SNickeau
24285e82846SNickeau                if ($page->isLowQualityPage() && $isLowQualityProtectionEnabled) {
24385e82846SNickeau                    $protectionMode = LowQualityPage::getLowQualityProtectionMode();
24485e82846SNickeau                    if ($protectionMode != PageProtection::CONF_VALUE_ROBOT) {
24585e82846SNickeau                        unset($pagesToBeAdded[$key]);
24685e82846SNickeau                    }
24785e82846SNickeau                }
24885e82846SNickeau
24985e82846SNickeau                if ($page->isLatePublication() && $isLatePublicationProtectionEnabled) {
250c3437056SNickeau                    $protectionMode = PagePublicationDate::getLatePublicationProtectionMode();
25185e82846SNickeau                    if ($protectionMode != PageProtection::CONF_VALUE_ROBOT) {
25285e82846SNickeau                        unset($pagesToBeAdded[$key]);
25385e82846SNickeau                    }
25485e82846SNickeau                }
255e8b2ff59SNickeau
256e8b2ff59SNickeau            }
25785e82846SNickeau        }
25885e82846SNickeau
2595f891b7eSNickeau    }
2605f891b7eSNickeau
2615f891b7eSNickeau    /**
2625f891b7eSNickeau     * @param $event
26385e82846SNickeau     * @param array $protectionModes
2645f891b7eSNickeau     */
2655f891b7eSNickeau    private
26685e82846SNickeau    function excludePageFromSearch(&$event, $protectionModes = [PageProtection::CONF_VALUE_ACL, PageProtection::CONF_VALUE_HIDDEN])
2675f891b7eSNickeau    {
2685f891b7eSNickeau
2695f891b7eSNickeau        /**
2705f891b7eSNickeau         * The value is always an array
2715f891b7eSNickeau         * but as we got this error:
2725f891b7eSNickeau         * ```
2735f891b7eSNickeau         * array_keys() expects parameter 1 to be array
2745f891b7eSNickeau         * ```
275e8b2ff59SNickeau         * The result is a list of page id
2765f891b7eSNickeau         */
277e8b2ff59SNickeau        if (is_array($event->result)) {
278e8b2ff59SNickeau            foreach (array_keys($event->result) as $idx) {
279*04fd306cSNickeau                $page = MarkupPath::createMarkupFromId($idx);
28085e82846SNickeau                if ($page->isLowQualityPage()) {
28185e82846SNickeau                    $securityConf = $this->getConf(LowQualityPage::CONF_LOW_QUALITY_PAGE_PROTECTION_MODE);
28285e82846SNickeau                    if (in_array($securityConf, $protectionModes)) {
283e8b2ff59SNickeau                        unset($event->result[$idx]);
28485e82846SNickeau                        return;
28585e82846SNickeau                    }
28685e82846SNickeau                }
28785e82846SNickeau                if ($page->isLatePublication()) {
288c3437056SNickeau                    $securityConf = $this->getConf(PagePublicationDate::CONF_LATE_PUBLICATION_PROTECTION_MODE);
28985e82846SNickeau                    if (in_array($securityConf, [PageProtection::CONF_VALUE_ACL, PageProtection::CONF_VALUE_HIDDEN])) {
290e8b2ff59SNickeau                        unset($event->result[$idx]);
29185e82846SNickeau                        return;
29285e82846SNickeau                    }
2935f891b7eSNickeau                }
2945f891b7eSNickeau            }
2955f891b7eSNickeau        }
2965f891b7eSNickeau
2975f891b7eSNickeau    }
2985f891b7eSNickeau
2995f891b7eSNickeau
30085e82846SNickeau    /**
30185e82846SNickeau     * Handle the meta robots
30285e82846SNickeau     * https://www.dokuwiki.org/devel:event:tpl_metaheader_output
30385e82846SNickeau     * @param $event
30485e82846SNickeau     * @param $param
30585e82846SNickeau     */
30685e82846SNickeau    function handleRobotsMeta(&$event, $param)
30785e82846SNickeau    {
30885e82846SNickeau
309*04fd306cSNickeau        $requestedPath = ExecutionContext::getActualOrCreateFromEnv()->getRequestedPath();
310*04fd306cSNickeau
311*04fd306cSNickeau        if (!FileSystems::exists($requestedPath)) {
31285e82846SNickeau            return;
31385e82846SNickeau        }
31485e82846SNickeau
315*04fd306cSNickeau        $page = MarkupPath::createPageFromPathObject($requestedPath);
31685e82846SNickeau
31785e82846SNickeau        /**
31885e82846SNickeau         * No management for slot page
31985e82846SNickeau         */
320*04fd306cSNickeau        if ($page->isSlot()) {
32185e82846SNickeau            return;
32285e82846SNickeau        }
32385e82846SNickeau
32485e82846SNickeau        $protected = false;
32585e82846SNickeau        $follow = "nofollow";
32685e82846SNickeau        if ($page->isLowQualityPage() && LowQualityPage::isProtectionEnabled()) {
32785e82846SNickeau            $protected = true;
32885e82846SNickeau            if (LowQualityPage::getLowQualityProtectionMode() == PageProtection::CONF_VALUE_ACL) {
32985e82846SNickeau                $follow = "nofollow";
33085e82846SNickeau            } else {
33185e82846SNickeau                $follow = "follow";
33285e82846SNickeau            }
33385e82846SNickeau        }
334c3437056SNickeau        if ($page->isLatePublication() && PagePublicationDate::isLatePublicationProtectionEnabled()) {
33585e82846SNickeau            $protected = true;
336c3437056SNickeau            if (PagePublicationDate::getLatePublicationProtectionMode() == PageProtection::CONF_VALUE_ACL) {
33785e82846SNickeau                $follow = "nofollow";
33885e82846SNickeau            } else {
33985e82846SNickeau                $follow = "follow";
34085e82846SNickeau            }
34185e82846SNickeau        }
34285e82846SNickeau        if ($protected) {
34385e82846SNickeau            foreach ($event->data['meta'] as $key => $meta) {
34485e82846SNickeau                if (array_key_exists("name", $meta)) {
34585e82846SNickeau                    /**
34685e82846SNickeau                     * We may have several properties
34785e82846SNickeau                     */
34885e82846SNickeau                    if ($meta["name"] == "robots") {
34985e82846SNickeau                        $event->data['meta'][$key]["content"] = "noindex,$follow";
35085e82846SNickeau                    }
35185e82846SNickeau                }
35285e82846SNickeau            }
35385e82846SNickeau        }
35485e82846SNickeau    }
35585e82846SNickeau
3565f891b7eSNickeau}
357