xref: /plugin/combo/action/docustom.php (revision 04fd306c7c155fa133ebb3669986875d65988276)
1*04fd306cSNickeau<?php
2*04fd306cSNickeau
3*04fd306cSNickeauuse ComboStrap\DokuwikiId;
4*04fd306cSNickeauuse ComboStrap\ExceptionNotFound;
5*04fd306cSNickeauuse ComboStrap\ExceptionReporter;
6*04fd306cSNickeauuse ComboStrap\ExecutionContext;
7*04fd306cSNickeauuse ComboStrap\FetcherAppPages;
8*04fd306cSNickeauuse ComboStrap\FetcherPage;
9*04fd306cSNickeauuse ComboStrap\FileSystems;
10*04fd306cSNickeauuse ComboStrap\HttpResponseStatus;
11*04fd306cSNickeauuse ComboStrap\IFetcher;
12*04fd306cSNickeauuse ComboStrap\LogUtility;
13*04fd306cSNickeauuse ComboStrap\MarkupPath;
14*04fd306cSNickeauuse ComboStrap\Mime;
15*04fd306cSNickeauuse ComboStrap\PluginUtility;
16*04fd306cSNickeauuse ComboStrap\SiteConfig;
17*04fd306cSNickeauuse ComboStrap\Web\Url;
18*04fd306cSNickeau
19*04fd306cSNickeau/**
20*04fd306cSNickeau * Implementation of custom do (ie ACT) to output {@link \ComboStrap\IFetcherString}
21*04fd306cSNickeau *
22*04fd306cSNickeau *
23*04fd306cSNickeau *
24*04fd306cSNickeau */
25*04fd306cSNickeauclass action_plugin_combo_docustom extends DokuWiki_Action_Plugin
26*04fd306cSNickeau{
27*04fd306cSNickeau
28*04fd306cSNickeau    const DO_PREFIX = "combo_";
29*04fd306cSNickeau
30*04fd306cSNickeau    const TEMPLATE_CANONICAL = "template";
31*04fd306cSNickeau
32*04fd306cSNickeau    /**
33*04fd306cSNickeau     * @var bool to avoid recursion that may happen using {@link tpl_content()}
34*04fd306cSNickeau     */
35*04fd306cSNickeau    private bool $doCustomActuallyExecuting = false;
36*04fd306cSNickeau
37*04fd306cSNickeau    /**
38*04fd306cSNickeau     * @return bool
39*04fd306cSNickeau     */
40*04fd306cSNickeau    public static function isThemeSystemEnabled(): bool
41*04fd306cSNickeau    {
42*04fd306cSNickeau        $confValue = SiteConfig::getConfValue(SiteConfig::CONF_ENABLE_THEME_SYSTEM, SiteConfig::CONF_ENABLE_THEME_SYSTEM_DEFAULT);
43*04fd306cSNickeau        return $confValue === 1;
44*04fd306cSNickeau    }
45*04fd306cSNickeau
46*04fd306cSNickeau    public static function getDoParameterValue(string $fetcherName): string
47*04fd306cSNickeau    {
48*04fd306cSNickeau        return self::DO_PREFIX . $fetcherName;
49*04fd306cSNickeau    }
50*04fd306cSNickeau
51*04fd306cSNickeau    /**
52*04fd306cSNickeau     *
53*04fd306cSNickeau     * @param Doku_Event_Handler $controller
54*04fd306cSNickeau     * @return void
55*04fd306cSNickeau     */
56*04fd306cSNickeau
57*04fd306cSNickeau    public function register(\Doku_Event_Handler $controller)
58*04fd306cSNickeau    {
59*04fd306cSNickeau        /**
60*04fd306cSNickeau         * Execute the combo action via an ACTION_ACT_PREPROCESS
61*04fd306cSNickeau         *
62*04fd306cSNickeau         * Not via the [TPL_ACT_UNKNOWN](https://www.dokuwiki.org/devel:event:tpl_act_unknown)
63*04fd306cSNickeau         * because it would otherwise put the content in the middle of the page
64*04fd306cSNickeau         * as an admin page.
65*04fd306cSNickeau         *
66*04fd306cSNickeau         * Not really useful if you want your own layout or do an export
67*04fd306cSNickeau         */
68*04fd306cSNickeau        $controller->register_hook('ACTION_ACT_PREPROCESS', 'BEFORE', $this, 'executeComboDoAction');
69*04fd306cSNickeau
70*04fd306cSNickeau    }
71*04fd306cSNickeau
72*04fd306cSNickeau    /**
73*04fd306cSNickeau     * @param Doku_Event $event
74*04fd306cSNickeau     * @param $param
75*04fd306cSNickeau     * @return void
76*04fd306cSNickeau     *
77*04fd306cSNickeau     */
78*04fd306cSNickeau    public function executeComboDoAction(Doku_Event $event, $param)
79*04fd306cSNickeau    {
80*04fd306cSNickeau
81*04fd306cSNickeau        if ($this->doCustomActuallyExecuting) {
82*04fd306cSNickeau            return;
83*04fd306cSNickeau        }
84*04fd306cSNickeau
85*04fd306cSNickeau        /**
86*04fd306cSNickeau         * The router may have done a redirection
87*04fd306cSNickeau         * (The Dokuwiki testRequest does not stop unfortunately)
88*04fd306cSNickeau         */
89*04fd306cSNickeau        $executionContext = ExecutionContext::getActualOrCreateFromEnv();
90*04fd306cSNickeau        $hasEnded = $executionContext
91*04fd306cSNickeau            ->response()
92*04fd306cSNickeau            ->hasEnded();
93*04fd306cSNickeau        if ($hasEnded) {
94*04fd306cSNickeau            if ($executionContext->isTestRun()) {
95*04fd306cSNickeau                /**
96*04fd306cSNickeau                 * This info helps the developer to see
97*04fd306cSNickeau                 * why nothing happens when it sends two dokuwiki {@link TestRequest}
98*04fd306cSNickeau                 *
99*04fd306cSNickeau                 * And not two {@link \ComboStrap\HttpResponse}
100*04fd306cSNickeau                 * that reinitialize the global scope
101*04fd306cSNickeau                 */
102*04fd306cSNickeau                LogUtility::info("ExecuteDoAction: The response has already be send (ended).");
103*04fd306cSNickeau            }
104*04fd306cSNickeau            return;
105*04fd306cSNickeau        }
106*04fd306cSNickeau
107*04fd306cSNickeau        $action = $event->data;
108*04fd306cSNickeau
109*04fd306cSNickeau        if (self::isThemeSystemEnabled()) {
110*04fd306cSNickeau            switch ($action) {
111*04fd306cSNickeau                case "show":
112*04fd306cSNickeau                    try {
113*04fd306cSNickeau                        $id = Url::createFromGetOrPostGlobalVariable()->getPropertyValue(DokuwikiId::DOKUWIKI_ID_ATTRIBUTE);
114*04fd306cSNickeau                    } catch (ExceptionNotFound $e) {
115*04fd306cSNickeau                        // should not happen but yeah
116*04fd306cSNickeau                        return;
117*04fd306cSNickeau                    }
118*04fd306cSNickeau                    $path = MarkupPath::createMarkupFromId($id);
119*04fd306cSNickeau                    if (!FileSystems::exists($path)) {
120*04fd306cSNickeau                        return;
121*04fd306cSNickeau                    }
122*04fd306cSNickeau                    $action = self::getDoParameterValue(FetcherPage::NAME);
123*04fd306cSNickeau                    break;
124*04fd306cSNickeau                case ExecutionContext::LOGIN_ACTION:
125*04fd306cSNickeau                case ExecutionContext::REGISTER_ACTION:
126*04fd306cSNickeau                case ExecutionContext::RESEND_PWD_ACTION:
127*04fd306cSNickeau                case ExecutionContext::PROFILE_ACTION:
128*04fd306cSNickeau                case ExecutionContext::EDIT_ACTION:
129*04fd306cSNickeau                case ExecutionContext::PREVIEW_ACTION:
130*04fd306cSNickeau                case ExecutionContext::SEARCH_ACTION:
131*04fd306cSNickeau                case ExecutionContext::INDEX_ACTION:
132*04fd306cSNickeau                    //case ExecutionContext::REVISIONS_ACTION:
133*04fd306cSNickeau                    //case ExecutionContext::DIFF_ACTION: needs styling
134*04fd306cSNickeau                    $action = self::getDoParameterValue(FetcherAppPages::NAME);
135*04fd306cSNickeau                    break;
136*04fd306cSNickeau            }
137*04fd306cSNickeau        }
138*04fd306cSNickeau
139*04fd306cSNickeau        if (!$this->isComboDoAction($action)) return;
140*04fd306cSNickeau
141*04fd306cSNickeau        /**
142*04fd306cSNickeau         * To avoid recursion
143*04fd306cSNickeau         */
144*04fd306cSNickeau        $this->doCustomActuallyExecuting = true;
145*04fd306cSNickeau
146*04fd306cSNickeau
147*04fd306cSNickeau        try {
148*04fd306cSNickeau            $fetcherName = $this->getFetcherNameFromAction($action);
149*04fd306cSNickeau            $url = Url::createFromGetOrPostGlobalVariable()
150*04fd306cSNickeau                ->addQueryParameter(IFetcher::FETCHER_KEY, $fetcherName);
151*04fd306cSNickeau            $fetcher = $executionContext->createStringMainFetcherFromRequestedUrl($url);
152*04fd306cSNickeau            $body = $fetcher->getFetchString();
153*04fd306cSNickeau            $mime = $fetcher->getMime();
154*04fd306cSNickeau            $executionContext->response()
155*04fd306cSNickeau                ->setStatus(HttpResponseStatus::ALL_GOOD)
156*04fd306cSNickeau                ->setBody($body, $mime)
157*04fd306cSNickeau                ->end();
158*04fd306cSNickeau        } catch (\Exception $e) {
159*04fd306cSNickeau
160*04fd306cSNickeau
161*04fd306cSNickeau            $reporterMessage = "An error has occurred during the execution of the action ($action)";
162*04fd306cSNickeau            $html = ExceptionReporter::createForException($e)
163*04fd306cSNickeau                ->getHtmlPage($reporterMessage);
164*04fd306cSNickeau            if (PluginUtility::isDevOrTest()) {
165*04fd306cSNickeau                // Permits to throw the error to get the stack trace
166*04fd306cSNickeau                LogUtility::warning($reporterMessage, self::TEMPLATE_CANONICAL, $e);
167*04fd306cSNickeau            }
168*04fd306cSNickeau            $executionContext->response()
169*04fd306cSNickeau                ->setException($e)
170*04fd306cSNickeau                ->setBody($html, Mime::getHtml())
171*04fd306cSNickeau                ->end();
172*04fd306cSNickeau
173*04fd306cSNickeau        } finally {
174*04fd306cSNickeau            $this->doCustomActuallyExecuting = false;
175*04fd306cSNickeau        }
176*04fd306cSNickeau
177*04fd306cSNickeau    }
178*04fd306cSNickeau
179*04fd306cSNickeau
180*04fd306cSNickeau    private function isComboDoAction($actionName): bool
181*04fd306cSNickeau    {
182*04fd306cSNickeau        return strpos($actionName, self::DO_PREFIX) === 0;
183*04fd306cSNickeau    }
184*04fd306cSNickeau
185*04fd306cSNickeau    private function getFetcherNameFromAction($actionName)
186*04fd306cSNickeau    {
187*04fd306cSNickeau        return substr($actionName, strlen(self::DO_PREFIX));
188*04fd306cSNickeau    }
189*04fd306cSNickeau
190*04fd306cSNickeau
191*04fd306cSNickeau}
192