1<?php
2
3namespace ComboStrap;
4
5
6use ComboStrap\Meta\Field\PageTemplateName;
7use ComboStrap\Web\Url;
8use ComboStrap\Web\UrlEndpoint;
9use dokuwiki\Action\Exception\FatalException;
10use dokuwiki\ActionRouter;
11use dokuwiki\Ui\PageView;
12
13/**
14 * No Cache for the idenity forms
15 * as if there is a cache problems,
16 * We can't login anymore for instance
17 */
18class FetcherAppPages extends IFetcherAbs implements IFetcherString
19{
20
21    const NAME = "page-app";
22    const CANONICAL = "page-app";
23
24    use FetcherTraitWikiPath;
25
26    private string $requestedLayout;
27    private bool $build = false;
28
29
30    private TemplateForWebPage $pageTemplate;
31
32
33    /**
34     * @param Url|null $url
35     * @return Url
36     *
37     * Note: The fetch url is the {@link FetcherCache keyCache}
38     */
39    function getFetchUrl(Url $url = null): Url
40    {
41        /**
42         * Overwrite default fetcher endpoint
43         * that is {@link UrlEndpoint::createFetchUrl()}
44         */
45        $url = UrlEndpoint::createDokuUrl();
46        try {
47            $url->addQueryParameter(PageTemplateName::PROPERTY_NAME, $this->getRequestedLayout());
48        } catch (ExceptionNotFound $e) {
49            // no requested layout
50        }
51        return parent::getFetchUrl($url)
52            ->addQueryParameter("do", self::NAME);
53    }
54
55
56    /**
57     * @return string
58     */
59    public function getFetchString(): string
60    {
61
62        $contextPath = $this->getSourcePath();
63        if ($contextPath->hasRevision()) {
64            /**
65             * In the diff {@link ExecutionContext::DIFF_ACTION},
66             * the `rev` property is passed in the URL and we get a bad context
67             */
68            $contextPath = WikiPath::createMarkupPathFromId($contextPath->getWikiId());
69        }
70
71
72        if (!$this->build) {
73
74            $this->build = true;
75            $pageLang = Site::getLangObject();
76            $title = $this->getLabel();
77
78            $this->pageTemplate = TemplateForWebPage::create()
79                ->setRequestedTemplateName($this->getRequestedTemplateOrDefault())
80                ->setRequestedLang($pageLang)
81                ->setRequestedEnableTaskRunner(false) // no page id
82                ->setRequestedTitle($title)
83                ->setRequestedContextPath($contextPath);
84
85        }
86
87
88        /**
89         * The content
90         *
91         * Adapted from {@link tpl_content()}
92         *
93         * As this is only for identifier forms,
94         * the buffer should not be a problem
95         *
96         * Because all admin action are using the php buffer
97         * We can then have an overflow
98         */
99        global $ACT;
100        ob_start();
101        $actionName = FetcherAppPages::class . "::tpl_content_core";
102        \dokuwiki\Extension\Event::createAndTrigger('TPL_ACT_RENDER', $ACT, $actionName);
103        $mainHtml = ob_get_clean();
104
105
106        /**
107         * Add css
108         */
109        switch ($ACT) {
110            case ExecutionContext::PREVIEW_ACTION:
111            case ExecutionContext::EDIT_ACTION:
112                $markupPath = MarkupPath::createPageFromPathObject($contextPath);
113                if ($ACT === ExecutionContext::PREVIEW_ACTION && $markupPath->isSlot()) {
114                    try {
115                        SlotSystem::sendContextPathMessage(SlotSystem::getContextPath());
116                    } catch (ExceptionNotFound $e) {
117                        // no history (ie no cookie or new installation)
118                    }
119                }
120        }
121
122
123        /**
124         * Generate the whole html page via the layout
125         */
126        return $this->pageTemplate
127            ->setMainContent($mainHtml)
128            ->render();
129
130    }
131
132
133    /**
134     *
135     */
136    function getBuster(): string
137    {
138        return "";
139    }
140
141    public function getMime(): Mime
142    {
143        return Mime::create(Mime::HTML);
144    }
145
146    public function getFetcherName(): string
147    {
148        return self::NAME;
149    }
150
151    /**
152     * We take over the {@link tpl_content_core()} of Dokuwiki
153     * because the instance of the router is not reinit.
154     * We get then problem on test because of the private global static {@link ActionRouter::$instance) variable
155     * @return bool
156     * @noinspection PhpUnused - is a callback to the event TPL_ACT_RENDER called in this class
157     */
158    static public function tpl_content_core(): bool
159    {
160
161        /**
162         * $INFO['prependTOC'] = ''; // php8 Undefined array key "prependTOC"
163         * at {@link PageView}
164         */
165        global $INFO;
166        if (!array_key_exists('prependTOC', $INFO)) {
167            $INFO['prependTOC'] = false;
168        }
169
170        /**
171         * Was false, is true
172         */
173        $router = ActionRouter::getInstance(true);
174        try {
175            $router->getAction()->tplContent();
176        } catch (FatalException $e) {
177            // there was no content for the action
178            msg(hsc($e->getMessage()), -1);
179            return false;
180        }
181        return true;
182    }
183
184    /**
185     * @throws ExceptionNotFound
186     */
187    private function getRequestedLayout(): string
188    {
189        if (!isset($this->requestedLayout)) {
190            throw new ExceptionNotFound("No requested layout");
191        }
192        return $this->requestedLayout;
193    }
194
195
196    /**
197     *
198     */
199    public function close(): FetcherAppPages
200    {
201        // nothing to do
202        return $this;
203    }
204
205
206    private function getRequestedTemplateOrDefault(): string
207    {
208        try {
209            return $this->getRequestedLayout();
210        } catch (ExceptionNotFound $e) {
211            global $ACT;
212            switch ($ACT) {
213                case ExecutionContext::EDIT_ACTION:
214                case ExecutionContext::PREVIEW_ACTION:
215                    return PageTemplateName::APP_EDIT;
216                case ExecutionContext::LOGIN_ACTION:
217                    return PageTemplateName::APP_LOGIN;
218                case ExecutionContext::REGISTER_ACTION:
219                    return PageTemplateName::APP_REGISTER;
220                case ExecutionContext::RESEND_PWD_ACTION:
221                    return PageTemplateName::APP_RESEND_PWD;
222                case ExecutionContext::REVISIONS_ACTION:
223                    return PageTemplateName::APP_REVISIONS;
224                case ExecutionContext::DIFF_ACTION:
225                    return PageTemplateName::APP_DIFF;
226                case ExecutionContext::INDEX_ACTION:
227                    return PageTemplateName::APP_INDEX;
228                case ExecutionContext::PROFILE_ACTION:
229                    return PageTemplateName::APP_PROFILE;
230                default:
231                case ExecutionContext::SEARCH_ACTION:
232                    return PageTemplateName::APP_SEARCH;
233            }
234
235        }
236    }
237
238
239    public function getLabel(): string
240    {
241        global $ACT;
242        $label = "App Pages";
243        switch ($ACT) {
244            case ExecutionContext::RESEND_PWD_ACTION:
245                $label = "Resend Password";
246                break;
247            case ExecutionContext::LOGIN_ACTION:
248                $label = "Login";
249                break;
250            case ExecutionContext::REGISTER_ACTION:
251                $label = "Register";
252                break;
253            case ExecutionContext::EDIT_ACTION:
254            case ExecutionContext::PREVIEW_ACTION:
255                $label = "Editor";
256                break;
257            case ExecutionContext::DIFF_ACTION:
258                $label = "Diff";
259                break;
260            case ExecutionContext::REVISIONS_ACTION:
261                $label = "Log";
262                break;
263        }
264        return $label;
265    }
266
267
268    /**
269     * @throws ExceptionBadArgument
270     * @throws ExceptionBadSyntax
271     * @throws ExceptionNotExists
272     * @throws ExceptionNotFound
273     */
274    public function buildFromTagAttributes(TagAttributes $tagAttributes): IFetcher
275    {
276        parent::buildFromTagAttributes($tagAttributes);
277        $this->buildOriginalPathFromTagAttributes($tagAttributes);
278        return $this;
279    }
280}
281