xref: /plugin/combo/action/docustom.php (revision 49b8fb2440a8b019e2a082c98b66ddbf7fc707db)
104fd306cSNickeau<?php
204fd306cSNickeau
304fd306cSNickeauuse ComboStrap\DokuwikiId;
404fd306cSNickeauuse ComboStrap\ExceptionNotFound;
504fd306cSNickeauuse ComboStrap\ExceptionReporter;
604fd306cSNickeauuse ComboStrap\ExecutionContext;
704fd306cSNickeauuse ComboStrap\FetcherAppPages;
804fd306cSNickeauuse ComboStrap\FetcherPage;
9*49b8fb24Sgerardnicouse ComboStrap\FetcherRailBar;
1004fd306cSNickeauuse ComboStrap\FileSystems;
1104fd306cSNickeauuse ComboStrap\HttpResponseStatus;
12*49b8fb24Sgerardnicouse ComboStrap\Identity;
1304fd306cSNickeauuse ComboStrap\IFetcher;
1404fd306cSNickeauuse ComboStrap\LogUtility;
1504fd306cSNickeauuse ComboStrap\MarkupPath;
1604fd306cSNickeauuse ComboStrap\Mime;
1704fd306cSNickeauuse ComboStrap\PluginUtility;
1854743e42Sgerardnicouse ComboStrap\Site;
1904fd306cSNickeauuse ComboStrap\SiteConfig;
2004fd306cSNickeauuse ComboStrap\Web\Url;
2154743e42Sgerardnicouse ComboStrap\Web\UrlRewrite;
2204fd306cSNickeau
2304fd306cSNickeau/**
2404fd306cSNickeau * Implementation of custom do (ie ACT) to output {@link \ComboStrap\IFetcherString}
2504fd306cSNickeau *
2604fd306cSNickeau *
2704fd306cSNickeau *
2804fd306cSNickeau */
2904fd306cSNickeauclass action_plugin_combo_docustom extends DokuWiki_Action_Plugin
3004fd306cSNickeau{
3104fd306cSNickeau
3204fd306cSNickeau    const DO_PREFIX = "combo_";
3304fd306cSNickeau
3404fd306cSNickeau    const TEMPLATE_CANONICAL = "template";
3504fd306cSNickeau
3604fd306cSNickeau    /**
3704fd306cSNickeau     * @var bool to avoid recursion that may happen using {@link tpl_content()}
3804fd306cSNickeau     */
3904fd306cSNickeau    private bool $doCustomActuallyExecuting = false;
4004fd306cSNickeau
4104fd306cSNickeau    /**
4204fd306cSNickeau     * @return bool
4304fd306cSNickeau     */
4404fd306cSNickeau    public static function isThemeSystemEnabled(): bool
4504fd306cSNickeau    {
4604fd306cSNickeau        $confValue = SiteConfig::getConfValue(SiteConfig::CONF_ENABLE_THEME_SYSTEM, SiteConfig::CONF_ENABLE_THEME_SYSTEM_DEFAULT);
4704fd306cSNickeau        return $confValue === 1;
4804fd306cSNickeau    }
4904fd306cSNickeau
5004fd306cSNickeau    public static function getDoParameterValue(string $fetcherName): string
5104fd306cSNickeau    {
5204fd306cSNickeau        return self::DO_PREFIX . $fetcherName;
5304fd306cSNickeau    }
5404fd306cSNickeau
5504fd306cSNickeau    /**
5604fd306cSNickeau     *
5704fd306cSNickeau     * @param Doku_Event_Handler $controller
5804fd306cSNickeau     * @return void
5904fd306cSNickeau     */
6004fd306cSNickeau
6104fd306cSNickeau    public function register(\Doku_Event_Handler $controller)
6204fd306cSNickeau    {
6304fd306cSNickeau        /**
6404fd306cSNickeau         * Execute the combo action via an ACTION_ACT_PREPROCESS
6504fd306cSNickeau         *
6604fd306cSNickeau         * Not via the [TPL_ACT_UNKNOWN](https://www.dokuwiki.org/devel:event:tpl_act_unknown)
6704fd306cSNickeau         * because it would otherwise put the content in the middle of the page
6804fd306cSNickeau         * as an admin page.
6904fd306cSNickeau         *
7004fd306cSNickeau         * Not really useful if you want your own layout or do an export
7104fd306cSNickeau         */
7204fd306cSNickeau        $controller->register_hook('ACTION_ACT_PREPROCESS', 'BEFORE', $this, 'executeComboDoAction');
7304fd306cSNickeau
7404fd306cSNickeau    }
7504fd306cSNickeau
7604fd306cSNickeau    /**
7704fd306cSNickeau     * @param Doku_Event $event
7804fd306cSNickeau     * @param $param
7904fd306cSNickeau     * @return void
8004fd306cSNickeau     *
8104fd306cSNickeau     */
8204fd306cSNickeau    public function executeComboDoAction(Doku_Event $event, $param)
8304fd306cSNickeau    {
8404fd306cSNickeau
8504fd306cSNickeau        if ($this->doCustomActuallyExecuting) {
8604fd306cSNickeau            return;
8704fd306cSNickeau        }
8804fd306cSNickeau
8904fd306cSNickeau        /**
9004fd306cSNickeau         * The router may have done a redirection
9104fd306cSNickeau         * (The Dokuwiki testRequest does not stop unfortunately)
9204fd306cSNickeau         */
9304fd306cSNickeau        $executionContext = ExecutionContext::getActualOrCreateFromEnv();
9404fd306cSNickeau        $hasEnded = $executionContext
9504fd306cSNickeau            ->response()
9604fd306cSNickeau            ->hasEnded();
9704fd306cSNickeau        if ($hasEnded) {
9804fd306cSNickeau            if ($executionContext->isTestRun()) {
9904fd306cSNickeau                /**
10004fd306cSNickeau                 * This info helps the developer to see
10104fd306cSNickeau                 * why nothing happens when it sends two dokuwiki {@link TestRequest}
10204fd306cSNickeau                 *
10304fd306cSNickeau                 * And not two {@link \ComboStrap\HttpResponse}
10404fd306cSNickeau                 * that reinitialize the global scope
10504fd306cSNickeau                 */
10604fd306cSNickeau                LogUtility::info("ExecuteDoAction: The response has already be send (ended).");
10704fd306cSNickeau            }
10804fd306cSNickeau            return;
10904fd306cSNickeau        }
11004fd306cSNickeau
11154743e42Sgerardnico        $urlRewrite = Site::getUrlRewrite();
11254743e42Sgerardnico        if ($urlRewrite == UrlRewrite::VALUE_DOKU_REWRITE) {
11354743e42Sgerardnico            UrlRewrite::sendErrorMessage();
11454743e42Sgerardnico            return;
11554743e42Sgerardnico        }
11654743e42Sgerardnico
11704fd306cSNickeau        $action = $event->data;
11804fd306cSNickeau
119*49b8fb24Sgerardnico        $privateRailbar = $executionContext->getConfig()->getBooleanValue(FetcherRailBar::CONF_PRIVATE_RAIL_BAR, FetcherRailBar::CONF_PRIVATE_RAIL_BAR_DEFAULT);
120*49b8fb24Sgerardnico        $isAnonymous = Identity::isAnonymous();
121*49b8fb24Sgerardnico        if ($privateRailbar && $isAnonymous) {
122*49b8fb24Sgerardnico            /**
123*49b8fb24Sgerardnico             * To avoid the google console error: `Excluded by ‘noindex’ tag`
124*49b8fb24Sgerardnico             * Example of URL
125*49b8fb24Sgerardnico             * https://example.com/dat/bobj/central_management_server?tab_files=upload&do=media&tab_details=history&image=db:hana:hdb_thread_stat_systemdb.png&ns=web/resource
126*49b8fb24Sgerardnico             */
127*49b8fb24Sgerardnico            $privateAction = [ExecutionContext::MEDIA_ACTION, ExecutionContext::DIFF_ACTION, ExecutionContext::RECENT_ACTION];
128*49b8fb24Sgerardnico            if (in_array($action, $privateAction)) {
129*49b8fb24Sgerardnico                $executionContext->response()
130*49b8fb24Sgerardnico                    ->setStatus(HttpResponseStatus::NOT_AUTHORIZED)
131*49b8fb24Sgerardnico                    ->end();
132*49b8fb24Sgerardnico                return;
133*49b8fb24Sgerardnico            }
134*49b8fb24Sgerardnico        }
135*49b8fb24Sgerardnico
13604fd306cSNickeau        if (self::isThemeSystemEnabled()) {
13704fd306cSNickeau            switch ($action) {
138*49b8fb24Sgerardnico                case ExecutionContext::SHOW_ACTION:
13904fd306cSNickeau                    try {
14004fd306cSNickeau                        $id = Url::createFromGetOrPostGlobalVariable()->getPropertyValue(DokuwikiId::DOKUWIKI_ID_ATTRIBUTE);
14104fd306cSNickeau                    } catch (ExceptionNotFound $e) {
14204fd306cSNickeau                        // should not happen but yeah
14304fd306cSNickeau                        return;
14404fd306cSNickeau                    }
14504fd306cSNickeau                    $path = MarkupPath::createMarkupFromId($id);
14604fd306cSNickeau                    if (!FileSystems::exists($path)) {
14704fd306cSNickeau                        return;
14804fd306cSNickeau                    }
14904fd306cSNickeau                    $action = self::getDoParameterValue(FetcherPage::NAME);
15004fd306cSNickeau                    break;
15104fd306cSNickeau                case ExecutionContext::LOGIN_ACTION:
15204fd306cSNickeau                case ExecutionContext::REGISTER_ACTION:
15304fd306cSNickeau                case ExecutionContext::RESEND_PWD_ACTION:
15404fd306cSNickeau                case ExecutionContext::PROFILE_ACTION:
15504fd306cSNickeau                case ExecutionContext::EDIT_ACTION:
15604fd306cSNickeau                case ExecutionContext::PREVIEW_ACTION:
15704fd306cSNickeau                case ExecutionContext::SEARCH_ACTION:
15804fd306cSNickeau                case ExecutionContext::INDEX_ACTION:
15904fd306cSNickeau                    //case ExecutionContext::REVISIONS_ACTION:
16004fd306cSNickeau                    //case ExecutionContext::DIFF_ACTION: needs styling
16104fd306cSNickeau                    $action = self::getDoParameterValue(FetcherAppPages::NAME);
16204fd306cSNickeau                    break;
16304fd306cSNickeau            }
16404fd306cSNickeau        }
16504fd306cSNickeau
166*49b8fb24Sgerardnico
16704fd306cSNickeau        if (!$this->isComboDoAction($action)) return;
16804fd306cSNickeau
16904fd306cSNickeau        /**
17004fd306cSNickeau         * To avoid recursion
17104fd306cSNickeau         */
17204fd306cSNickeau        $this->doCustomActuallyExecuting = true;
17304fd306cSNickeau
17404fd306cSNickeau
17504fd306cSNickeau        try {
17604fd306cSNickeau            $fetcherName = $this->getFetcherNameFromAction($action);
17704fd306cSNickeau            $url = Url::createFromGetOrPostGlobalVariable()
17804fd306cSNickeau                ->addQueryParameter(IFetcher::FETCHER_KEY, $fetcherName);
17904fd306cSNickeau            $fetcher = $executionContext->createStringMainFetcherFromRequestedUrl($url);
18004fd306cSNickeau            $body = $fetcher->getFetchString();
18104fd306cSNickeau            $mime = $fetcher->getMime();
18204fd306cSNickeau            $executionContext->response()
18304fd306cSNickeau                ->setStatus(HttpResponseStatus::ALL_GOOD)
18404fd306cSNickeau                ->setBody($body, $mime)
18504fd306cSNickeau                ->end();
18604fd306cSNickeau        } catch (\Exception $e) {
18704fd306cSNickeau
18804fd306cSNickeau
18904fd306cSNickeau            $reporterMessage = "An error has occurred during the execution of the action ($action)";
19004fd306cSNickeau            $html = ExceptionReporter::createForException($e)
19104fd306cSNickeau                ->getHtmlPage($reporterMessage);
19204fd306cSNickeau            if (PluginUtility::isDevOrTest()) {
19304fd306cSNickeau                // Permits to throw the error to get the stack trace
19404fd306cSNickeau                LogUtility::warning($reporterMessage, self::TEMPLATE_CANONICAL, $e);
19504fd306cSNickeau            }
19604fd306cSNickeau            $executionContext->response()
19704fd306cSNickeau                ->setException($e)
19804fd306cSNickeau                ->setBody($html, Mime::getHtml())
19904fd306cSNickeau                ->end();
20004fd306cSNickeau
20104fd306cSNickeau        } finally {
20204fd306cSNickeau            $this->doCustomActuallyExecuting = false;
20304fd306cSNickeau        }
20404fd306cSNickeau
20504fd306cSNickeau    }
20604fd306cSNickeau
20704fd306cSNickeau
20804fd306cSNickeau    private function isComboDoAction($actionName): bool
20904fd306cSNickeau    {
21004fd306cSNickeau        return strpos($actionName, self::DO_PREFIX) === 0;
21104fd306cSNickeau    }
21204fd306cSNickeau
21304fd306cSNickeau    private function getFetcherNameFromAction($actionName)
21404fd306cSNickeau    {
21504fd306cSNickeau        return substr($actionName, strlen(self::DO_PREFIX));
21604fd306cSNickeau    }
21704fd306cSNickeau
21804fd306cSNickeau
21904fd306cSNickeau}
220