1<?php
2
3namespace ComboStrap\Web;
4
5use ComboStrap\DokuWikiId;
6use ComboStrap\ExceptionNotFound;
7use ComboStrap\ExecutionContext;
8use ComboStrap\LogUtility;
9use ComboStrap\MarkupPath;
10use ComboStrap\MediaMarkup;
11use ComboStrap\PageUrlPath;
12use ComboStrap\Site;
13use ComboStrap\WikiPath;
14
15/**
16 * Dokuwiki Rewrite
17 */
18class UrlRewrite
19{
20
21    public const CONF_KEY = 'userewrite';
22
23    public const NO_REWRITE_DOKU_VALUE = 0;
24    public const NO_REWRITE = "no_rewrite";
25    public const WEB_SERVER_REWRITE_DOKU_VALUE = 1;
26    public const WEB_SERVER_REWRITE = "web_server";
27    public const DOKU_REWRITE_DOKU_VALUE = 2;
28    /**
29     * Doku Rewrite is value 2
30     * https://www.dokuwiki.org/rewrite#further_details_for_the_technically_savvy
31     */
32    public const VALUE_DOKU_REWRITE = "doku_rewrite";
33
34
35    const EXPORT_DO_PREFIX = "export_";
36    const CANONICAL = "url_rewrite";
37    const MEDIA_PREFIX = "/_media";
38    const EXPORT_PATH_PREFIX = "/_export";
39
40
41    /**
42     * Apply all rewrite URL logic (from relative to absolute
43     * passing by web server url rewrite)
44     *
45     * Note that an URL may already have been rewritten
46     *
47     */
48    public static function rewrite(Url $url)
49    {
50
51        try {
52            $scheme = $url->getScheme();
53        } catch (ExceptionNotFound $e) {
54            /**
55             * we don't set, we just tell that that this is a http scheme
56             * the conditional {@link Url::toAbsoluteUrlString()}
57             * will set it
58             */
59            $scheme = "http";
60        }
61        switch ($scheme) {
62            case "https":
63            case "http":
64                self::pathRewrite($url);
65                self::baseRewrite($url);
66                if (Site::shouldEndpointUrlBeAbsolute()) {
67                    $url->toAbsoluteUrl();
68                }
69                break;
70        }
71
72
73    }
74
75    /**
76     * Rewrite the path
77     *
78     * Doc: https://www.dokuwiki.org/rewrite
79     * https://www.dokuwiki.org/config:userewrite
80     * @param Url $url
81     * @return void
82     */
83    private static function pathRewrite(Url $url)
84    {
85
86        try {
87            $path = $url->getPath();
88        } catch (ExceptionNotFound $e) {
89            // no path, no rewrite
90            return;
91        }
92
93        $rewrite = Site::getUrlRewrite();
94        switch ($path) {
95            case UrlEndpoint::LIB_EXE_FETCH_PHP:
96                if ($rewrite !== self::WEB_SERVER_REWRITE) {
97                    return;
98                }
99                try {
100                    $dokuwikiId = $url->getQueryPropertyValueAndRemoveIfPresent(MediaMarkup::$MEDIA_QUERY_PARAMETER);
101                } catch (ExceptionNotFound $e) {
102                    LogUtility::internalError("The media query should be present for a fetch. No Url rewrite could be done.");
103                    return;
104                }
105                $webUrlPath = str_replace(WikiPath::NAMESPACE_SEPARATOR_DOUBLE_POINT, "/", $dokuwikiId);
106                $url->setPath(self::MEDIA_PREFIX . "/$webUrlPath");
107                return;
108            case UrlEndpoint::LIB_EXE_DETAIL_PHP:
109                if ($rewrite !== self::WEB_SERVER_REWRITE) {
110                    return;
111                }
112                try {
113                    $dokuwikiId = $url->getQueryPropertyValueAndRemoveIfPresent(MediaMarkup::$MEDIA_QUERY_PARAMETER);
114                } catch (ExceptionNotFound $e) {
115                    LogUtility::internalError("The media query should be present for a detail page fetch. No Url rewrite could be done.");
116                    return;
117                }
118                $webUrlPath = str_replace(WikiPath::NAMESPACE_SEPARATOR_DOUBLE_POINT, "/", $dokuwikiId);
119                $url->setPath("/_detail/$webUrlPath");
120                return;
121            case UrlEndpoint::DOKU_PHP:
122                try {
123                    $dokuwikiId = $url->getQueryPropertyValueAndRemoveIfPresent(DokuWikiId::DOKUWIKI_ID_ATTRIBUTE);
124                } catch (ExceptionNotFound $e) {
125                    // no id (case of action such as login, ...)
126                    return;
127                }
128
129                /**
130                 * Permanent Id Rewrite
131                 * The page url path will return the original dokuwiki id
132                 * if there is no configuration
133                 */
134                $urlId = PageUrlPath::createForPage(MarkupPath::createMarkupFromId($dokuwikiId))->getValueOrDefaultAsWikiId();
135
136                /**
137                 * Rewrite Processing
138                 */
139                switch ($rewrite) {
140                    case self::WEB_SERVER_REWRITE:
141                        try {
142                            $do = $url->getQueryPropertyValue(ExecutionContext::DO_ATTRIBUTE);
143                            if (strpos($do, self::EXPORT_DO_PREFIX) === 0) {
144                                $exportFormat = substr($do, strlen(self::EXPORT_DO_PREFIX));
145                                $webUrlPath = str_replace(WikiPath::NAMESPACE_SEPARATOR_DOUBLE_POINT, "/", $urlId);
146                                $url->setPath(self::EXPORT_PATH_PREFIX . "/$exportFormat/$webUrlPath");
147                                $url->deleteQueryParameter(ExecutionContext::DO_ATTRIBUTE);
148                                return;
149                            }
150                            if ($do == ExecutionContext::SHOW_ACTION) {
151                                $url->deleteQueryParameter(ExecutionContext::DO_ATTRIBUTE);
152                            }
153                        } catch (ExceptionNotFound $e) {
154                            // no do
155                        }
156                        $webUrlPath = str_replace(WikiPath::NAMESPACE_SEPARATOR_DOUBLE_POINT, "/", $urlId);
157                        $url->setPath($webUrlPath);
158                        return;
159                    case self::VALUE_DOKU_REWRITE:
160                        $url->setPath("$path/$urlId");
161                        return;
162                    default:
163                        $url->setQueryParameter(DokuWikiId::DOKUWIKI_ID_ATTRIBUTE, $urlId);
164                        return;
165                }
166
167        }
168
169    }
170
171    private
172    static function baseRewrite(Url $url)
173    {
174        try {
175            $urlPathBaseDir = Site::getUrlPathBaseDir();
176        } catch (ExceptionNotFound $e) {
177            // ok, no base dir
178            return;
179        }
180        try {
181            $path = $url->getPath();
182        } catch (ExceptionNotFound $e) {
183            return;
184        }
185        if (strpos($path, $urlPathBaseDir) === 0) {
186            /**
187             * The base dir is already present
188             */
189            return;
190        }
191        if ($urlPathBaseDir[strlen($urlPathBaseDir) - 1] === "/") {
192            $url->setPath("$urlPathBaseDir$path");
193        } else {
194            $url->setPath("$urlPathBaseDir/$path");
195        }
196
197    }
198
199    public static function sendErrorMessage()
200    {
201        $rewriteOption2 = "https://www.dokuwiki.org/rewrite#option_2dokuwiki";
202        $rewriteOption1 = "https://www.dokuwiki.org/rewrite#option_1web_server";
203        $hrefPermanentFunctionality = "https://combostrap.com/page/canonical-url-4kxbb9fd#permanent";
204        $hrefNiceUrl = "https://combostrap.com/admin/nice-url-noln5keo";
205        LogUtility::error("Combostrap does not support the <a href=\"$rewriteOption2\">Url Dokuwiki Rewriting (Option 2)</a> because of the <a href=\"$hrefPermanentFunctionality\"> permanent Url functionality</a>. You should disable it and use the <a href=\"$rewriteOption1\">Web Server Option (Option 1)</a> if you want <a href=\"$hrefNiceUrl\">nice URL</a>.", self::CANONICAL);
206    }
207
208}
209