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