PluginProbe
404 Solution / 4.3.0
404 Solution v4.3.0
4.3.5 4.3.4 4.3.3 4.3.2 4.3.1 4.3.0 4.2.0 4.1.19 4.1.18 4.1.17 4.1.16 4.1.15 4.1.13 4.1.12 4.1.11 4.1.10 4.1.9 4.1.8 4.1.7 4.1.6 4.1.5 4.1.4 4.1.3 trunk 2.30.0 All 109 releases
404-solution / includes / services / ShortcodeUrlBarUpdater.php

ShortcodeUrlBarUpdater.php in 404 Solution 4.3.0, at includes/services/ShortcodeUrlBarUpdater.php

182 lines 7.9 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 if (!defined('ABSPATH')) {
4 exit;
5 }
6
7 /**
8 * Restores the browser URL while rendering suggestions on a custom 404 page.
9 */
10 class ABJ_404_Solution_ShortcodeUrlBarUpdater {
11
12 /**
13 * @return void
14 */
15 public function updateIfNecessary(): void {
16 $logging = abj_service('logging');
17 $debugMessage = '';
18 $options = abj_service('options_repository')->getOptions();
19
20 $requestedURLForRestore = $this->requestedUrlForRestore();
21 $shouldUpdateURL = $this->shouldUpdateURL($options, $requestedURLForRestore, $debugMessage);
22
23 if ($shouldUpdateURL) {
24 $userFriendlyURL = $this->userFriendlyURL($requestedURLForRestore);
25 echo $this->renderUrlReplaceScript($userFriendlyURL);
26
27 $currentReqUri = isset($_SERVER['REQUEST_URI']) && is_string($_SERVER['REQUEST_URI']) ? $_SERVER['REQUEST_URI'] : '';
28 $debugMessage .= "Updating the URL from " . $currentReqUri .
29 " to " . esc_url($userFriendlyURL) . ", ";
30 }
31
32 $debugMessage .= $this->debugOptionsSummary($options);
33 $debugMessage .= "is_single(): " . is_single() . " | " . "is_page(): " . is_page() .
34 " | is_feed(): " . is_feed() . " | is_trackback(): " . is_trackback() . " | is_preview(): " .
35 is_preview();
36
37 $logging->debugMessage("updateURLbarIfNecessary: " . $debugMessage);
38 }
39
40 /**
41 * @param array<string, mixed> $options
42 * @param string $requestedURLForRestore
43 * @param string $debugMessage
44 * @return bool
45 */
46 private function shouldUpdateURL(array $options, string $requestedURLForRestore, string &$debugMessage): bool {
47 $shouldUpdateURL = true;
48 if (!isset($options['update_suggest_url']) || $options['update_suggest_url'] != 1) {
49 $shouldUpdateURL = false;
50 $debugMessage .= "do not update (update_suggest_url is off), ";
51 }
52 if ($requestedURLForRestore === '') {
53 $shouldUpdateURL = false;
54 $debugMessage .= "do not update (no cookie found), ";
55 }
56 if (!$this->custom404ContextAllowsURLUpdate($options, $debugMessage)) {
57 $shouldUpdateURL = false;
58 }
59 return $shouldUpdateURL;
60 }
61
62 /**
63 * @param array<string, mixed> $options
64 * @param string $debugMessage
65 * @return bool
66 */
67 private function custom404ContextAllowsURLUpdate(array $options, string &$debugMessage): bool {
68 $queryParamName = ABJ404_PP . '_ref';
69 if (isset($_GET[$queryParamName]) && !empty($_GET[$queryParamName])) {
70 $debugMessage .= "ok to update (manual redirect to custom 404 page), ";
71 return true;
72 }
73
74 $dest404page = $this->dest404page($options);
75 $notFoundResponse = abj_service('not_found_response');
76 if (!is_object($notFoundResponse) || !method_exists($notFoundResponse, 'thereIsAUserSpecified404Page') ||
77 !$notFoundResponse->thereIsAUserSpecified404Page($dest404page)) {
78 $debugMessage .= "do not update (no custom 404 page specified), ";
79 return false;
80 }
81
82 return $this->currentRequestMatches404Page($dest404page, $options, $debugMessage);
83 }
84
85 /**
86 * @param string $dest404page
87 * @param array<string, mixed> $options
88 * @param string $debugMessage
89 * @return bool
90 */
91 private function currentRequestMatches404Page(string $dest404page, array $options, string &$debugMessage): bool {
92 $permalink = ABJ_404_Solution_PermalinkResolver::permalinkInfoToArray($dest404page, 0, null, $options);
93 $requestUriRaw = isset($_SERVER['REQUEST_URI']) && is_string($_SERVER['REQUEST_URI']) ? $_SERVER['REQUEST_URI'] : '';
94 $requestUriPath = parse_url($requestUriRaw, PHP_URL_PATH);
95 $permLinkStr = isset($permalink['link']) && is_string($permalink['link']) ? $permalink['link'] : '';
96 $requestUriPathStr = is_string($requestUriPath) ? $requestUriPath : '';
97 $status = isset($permalink['status']) && is_string($permalink['status']) ? $permalink['status'] : '';
98 $functions = abj_service('functions');
99 if (!is_object($functions) || !method_exists($functions, 'endsWithCaseSensitive')) {
100 $debugMessage .= "do not update (URL helper unavailable), ";
101 return false;
102 }
103
104 if (!$functions->endsWithCaseSensitive($permLinkStr, $requestUriPathStr) && $status != 'trash') {
105 $debugMessage .= "do not update (not on custom 404 page (" . $permLinkStr . ")), ";
106 return false;
107 }
108 $debugMessage .= "ok to update (displaying custom 404 page (" . $permLinkStr . ")), ";
109 return true;
110 }
111
112 /**
113 * @param array<string, mixed> $options
114 * @return string
115 */
116 private function dest404page(array $options): string {
117 $fallback = ABJ404_TYPE_404_DISPLAYED . '|' . ABJ404_TYPE_404_DISPLAYED;
118 $dest404pageRaw = isset($options['dest404page']) ? $options['dest404page'] : $fallback;
119 return is_string($dest404pageRaw) ? $dest404pageRaw : $fallback;
120 }
121
122 /**
123 * @param string $requestedURLForRestore
124 * @return string
125 */
126 private function userFriendlyURL(string $requestedURLForRestore): string {
127 $scheme = isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] === 'on' ? 'https' : 'http';
128 $host = isset($_SERVER['HTTP_HOST']) && is_string($_SERVER['HTTP_HOST']) ? $_SERVER['HTTP_HOST'] : '';
129 return $scheme . '://' . $host . esc_url($requestedURLForRestore);
130 }
131
132 /**
133 * @return string
134 */
135 private function requestedUrlForRestore(): string {
136 $updateURLCookieName = ABJ404_PP . '_REQUEST_URI_UPDATE_URL';
137 $legacyRequestKey = ABJ404_PP . '_REQUEST_URI';
138 if (isset($_REQUEST[$updateURLCookieName]) && is_string($_REQUEST[$updateURLCookieName]) &&
139 $_REQUEST[$updateURLCookieName] !== '') {
140 return $_REQUEST[$updateURLCookieName];
141 }
142 if (isset($_REQUEST[$legacyRequestKey]) && is_string($_REQUEST[$legacyRequestKey]) &&
143 $_REQUEST[$legacyRequestKey] !== '') {
144 return $_REQUEST[$legacyRequestKey];
145 }
146 return '';
147 }
148
149 /**
150 * @param string $userFriendlyURL
151 * @return string
152 */
153 private function renderUrlReplaceScript(string $userFriendlyURL): string {
154 $urlJson = wp_json_encode($userFriendlyURL);
155 $template = ABJ_404_Solution_FileSystemService::readFileContents(
156 dirname(__DIR__) . '/html/shortcodeUrlReplaceScript.html',
157 false
158 );
159 return str_replace('{url_json}', is_string($urlJson) ? $urlJson : 'null', $template) . "\n";
160 }
161
162 /**
163 * @param array<string, mixed> $options
164 * @return string
165 */
166 private function debugOptionsSummary(array $options): string {
167 $scAutoRedirects = isset($options['auto_redirects']) && is_scalar($options['auto_redirects']) ? (string)$options['auto_redirects'] : '';
168 $scAutoScore = isset($options['auto_score']) && is_scalar($options['auto_score']) ? (string)$options['auto_score'] : '';
169 $scTemplatePriority = isset($options['template_redirect_priority']) && is_scalar($options['template_redirect_priority']) ? (string)$options['template_redirect_priority'] : '';
170 $scAutoCats = isset($options['auto_cats']) && is_scalar($options['auto_cats']) ? (string)$options['auto_cats'] : '';
171 $scAutoTags = isset($options['auto_tags']) && is_scalar($options['auto_tags']) ? (string)$options['auto_tags'] : '';
172 $scDest404 = isset($options['dest404page']) && is_scalar($options['dest404page']) ? (string)$options['dest404page'] : '';
173 return "is404: " . is_404() . ", " .
174 esc_html('auto_redirects: ' . $scAutoRedirects .
175 ', auto_score: ' . $scAutoScore .
176 ', template_redirect_priority: ' . $scTemplatePriority .
177 ', auto_cats: ' . $scAutoCats .
178 ', auto_tags: ' . $scAutoTags .
179 ', dest404page: ' . $scDest404) . ", ";
180 }
181 }
182