xref: /plugin/combo/ComboStrap/Web/UrlRewrite.php (revision c597a3bf5597b4bbe46319179f7f7d03627bcd6b)
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                                return;
148                            }
149                            if ($do == ExecutionContext::SHOW_ACTION) {
150                                $url->deleteQueryParameter(ExecutionContext::DO_ATTRIBUTE);
151                            }
152                        } catch (ExceptionNotFound $e) {
153                            // no do
154                        }
155                        $webUrlPath = str_replace(WikiPath::NAMESPACE_SEPARATOR_DOUBLE_POINT, "/", $urlId);
156                        $url->setPath($webUrlPath);
157                        return;
158                    case self::VALUE_DOKU_REWRITE:
159                        $url->setPath("$path/$urlId");
160                        return;
161                    default:
162                        $url->setQueryParameter(DokuWikiId::DOKUWIKI_ID_ATTRIBUTE, $urlId);
163                        return;
164                }
165
166        }
167
168    }
169
170    private
171    static function baseRewrite(Url $url)
172    {
173        try {
174            $urlPathBaseDir = Site::getUrlPathBaseDir();
175        } catch (ExceptionNotFound $e) {
176            // ok, no base dir
177            return;
178        }
179        try {
180            $path = $url->getPath();
181        } catch (ExceptionNotFound $e) {
182            return;
183        }
184        if (strpos($path, $urlPathBaseDir) === 0) {
185            /**
186             * The base dir is already present
187             */
188            return;
189        }
190        if ($urlPathBaseDir[strlen($urlPathBaseDir) - 1] === "/") {
191            $url->setPath("$urlPathBaseDir$path");
192        } else {
193            $url->setPath("$urlPathBaseDir/$path");
194        }
195
196    }
197
198    public static function sendErrorMessage()
199    {
200        $rewriteOption2 = "https://www.dokuwiki.org/rewrite#option_2dokuwiki";
201        $rewriteOption1 = "https://www.dokuwiki.org/rewrite#option_1web_server";
202        $hrefPermanentFunctionality = "https://combostrap.com/page/canonical-url-4kxbb9fd#permanent";
203        $hrefNiceUrl = "https://combostrap.com/admin/nice-url-noln5keo";
204        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);
205    }
206
207}
208