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