PluginProbe
404 Solution / trunk
404 Solution vtrunk
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 / admin / RedirectAddModalPresenter.php

RedirectAddModalPresenter.php in 404 Solution trunk, at includes/admin/RedirectAddModalPresenter.php

177 lines 8.3 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 * Presents the Add Manual Redirect modal on the Page Redirects admin table.
9 */
10 class ABJ_404_Solution_RedirectAddModalPresenter {
11
12 /** @var ABJ_404_Solution_Functions */
13 private $functions;
14
15 /** @var ABJ_404_Solution_View_OptionsPresenter */
16 private $optionsPresenter;
17
18 /** @var ABJ_404_Solution_View_RedirectTypeUI */
19 private $redirectTypeUI;
20
21 /** @var ABJ_404_Solution_View_RedirectConditions */
22 private $redirectConditions;
23
24 public function __construct(ABJ_404_Solution_Functions $functions, ABJ_404_Solution_View_OptionsPresenter $optionsPresenter,
25 ABJ_404_Solution_View_RedirectTypeUI $redirectTypeUI,
26 ABJ_404_Solution_View_RedirectConditions $redirectConditions) {
27 $this->functions = $functions;
28 $this->optionsPresenter = $optionsPresenter;
29 $this->redirectTypeUI = $redirectTypeUI;
30 $this->redirectConditions = $redirectConditions;
31 }
32
33 /**
34 * @param array<string, mixed> $tableOptions
35 */
36 public function render(array $tableOptions): string {
37 $options = $this->optionsPresenter->getOptionsWithDefaults();
38 $link = wp_nonce_url($this->formUrl($tableOptions), 'abj404addRedirect');
39 $urlPlaceholder = parse_url(get_home_url(), PHP_URL_PATH) . '/example';
40 $prefilledUrl = $this->prefilledUrl();
41
42 return $this->fillTpl('viewRedirectsTableAddModal.html', array(
43 '{modal_title}' => esc_html__('Add Manual Redirect', '404-solution'),
44 '{form_action}' => esc_url($link),
45 '{modal_active_class}' => $prefilledUrl === '' ? '' : ' active',
46 '{url_value}' => esc_attr($prefilledUrl),
47 '{url_label}' => esc_html__('URL', '404-solution'),
48 '{url_placeholder}' => esc_attr($urlPlaceholder),
49 '{url_help}' => esc_html__('The URL path that should be redirected (without domain)', '404-solution'),
50 '{regex_label}' => esc_html__('Treat this URL as a regular expression', '404-solution'),
51 '{explain_label}' => esc_html__('(Explain)', '404-solution'),
52 '{regex_help_1}' => esc_html__('When checked, the text is treated as a regular expression. Note that including a bad regular expression or one that takes too long will break your website. So please use caution and test them elsewhere before trying them here. If you don\'t know what you\'re doing please don\'t use this option (as it\'s not necessary for the functioning of the plugin).', '404-solution'),
53 '{example_label}' => esc_html__('Example:', '404-solution'),
54 '{regex_help_2}' => esc_html__('/events/(.+) will match any URL that begins with /events/. Use $1 in the destination to insert the captured text. Site-relative paths such as /archive/$1 and full HTTP(S) URLs are supported.', '404-solution'),
55 '{regex_help_3}' => esc_html__('First, all of the normal "exact match" URLs are checked, then all of the regular expression URLs are checked.', '404-solution'),
56 '{redirect_to_html}' => $this->redirectToHtml(),
57 '{redirect_type_grid}' => $this->redirectTypeGrid($options),
58 '{advanced_options}' => $this->advancedOptionsHtml(),
59 '{cancel_label}' => esc_html__('Cancel', '404-solution'),
60 '{add_redirect_label}' => esc_html__('Add', '404-solution'),
61 ));
62 }
63
64 /**
65 * The URL an inbound "redirect this URL" link asked us to pre-fill.
66 *
67 * The admin-only note on the front-end suggestions page links here with
68 * the path that 404'd, so the admin lands on the form with the URL
69 * already in it rather than having to retype what they were just looking
70 * at. Only a site-relative path is accepted; anything else (an absolute
71 * URL, a scheme, a stray fragment) is reduced to its path component or
72 * dropped, so the query arg cannot seed the form with an off-site value.
73 *
74 * @return string Empty when the request carries no usable path, which
75 * also leaves the modal closed.
76 */
77 private function prefilledUrl(): string {
78 $raw = ABJ_404_Solution_RequestInputNormalizer::readText(
79 $_GET, array('name' => 'abj404_add_url'));
80 if ($raw === '') {
81 return '';
82 }
83 $path = parse_url($raw, PHP_URL_PATH);
84 if (!is_string($path) || $path === '') {
85 return '';
86 }
87 return $path[0] === '/' ? $path : '/' . $path;
88 }
89
90 /**
91 * @param array<string, mixed> $tableOptions
92 */
93 private function formUrl(array $tableOptions): string {
94 $url = '?page=' . ABJ404_PP . '&subpage=abj404_redirects';
95 $orderby = array_key_exists('orderby', $tableOptions) && is_string($tableOptions['orderby']) ? $tableOptions['orderby'] : 'url';
96 $order = array_key_exists('order', $tableOptions) && is_string($tableOptions['order']) ? $tableOptions['order'] : 'ASC';
97 if (!($orderby == 'url' && $order == 'ASC')) {
98 $url .= '&orderby=' . sanitize_text_field($orderby) . '&order=' . sanitize_text_field($order);
99 }
100 $filter = array_key_exists('filter', $tableOptions) && is_scalar($tableOptions['filter']) ? $tableOptions['filter'] : 0;
101 if ($filter != 0) {
102 $url .= '&filter=' . $filter;
103 }
104 return $url;
105 }
106
107 private function redirectToHtml(): string {
108 $redirectHtml = $this->tpl('addManualRedirectPageSearchDropdown.html');
109 $redirectHtml = $this->functions->str_replace(
110 array(
111 '{redirect_to_label}',
112 '{TOOLTIP_POPUP_EXPLANATION_EMPTY}',
113 '{TOOLTIP_POPUP_EXPLANATION_PAGE}',
114 '{TOOLTIP_POPUP_EXPLANATION_CUSTOM_STRING}',
115 '{TOOLTIP_POPUP_EXPLANATION_URL}',
116 '{REDIRECT_TO_USER_FIELD_WARNING}',
117 '{redirectPageTitle}',
118 '{pageIDAndType}',
119 '{data-url}',
120 ),
121 array(
122 esc_html__('Redirect to', '404-solution') . ' *',
123 __('(Type a page name or an external URL)', '404-solution'),
124 __('(A page has been selected.)', '404-solution'),
125 __('(A custom string has been entered.)', '404-solution'),
126 __('(An external URL will be used.)', '404-solution'),
127 '',
128 '',
129 '',
130 'admin-ajax.php?action=echoRedirectToPages&includeDefault404Page=true&includeSpecial=true&nonce=' .
131 wp_create_nonce('abj404_ajax'),
132 ),
133 $redirectHtml
134 );
135 return $this->functions->doNormalReplacements($redirectHtml);
136 }
137
138 /**
139 * @param array<string, mixed> $options
140 */
141 private function redirectTypeGrid(array $options): string {
142 $rawDefault = $options['default_redirect'] ?? '301';
143 $defaultCode = is_string($rawDefault) ? $rawDefault : '301';
144 ob_start();
145 $this->redirectTypeUI->echoRedirectTypeButtonGrid($defaultCode);
146 return (string)ob_get_clean();
147 }
148
149 private function advancedOptionsHtml(): string {
150 ob_start();
151 $this->redirectConditions->echoRedirectConditionsSection();
152 $conditionsSection = (string)ob_get_clean();
153
154 return $this->fillTpl('viewRedirectsTableAdvancedOptions.html', array(
155 '{open_attr}' => '',
156 '{advanced_options_label}' => esc_html__('Advanced Options', '404-solution'),
157 '{active_from_label}' => esc_html__('Active From (optional)', '404-solution'),
158 '{start_date_value}' => '',
159 '{active_from_help}' => esc_html__('Leave blank to activate immediately', '404-solution'),
160 '{active_until_label}' => esc_html__('Active Until (optional)', '404-solution'),
161 '{end_date_value}' => '',
162 '{active_until_help}' => esc_html__('Leave blank to never expire', '404-solution'),
163 '{conditions_section}' => $conditionsSection,
164 ));
165 }
166
167 /** @param array<string, string> $vars */
168 private function fillTpl(string $name, array $vars): string {
169 return (string)$this->functions->str_replace(array_keys($vars), array_values($vars), $this->tpl($name));
170 }
171
172 private function tpl(string $name): string {
173 $raw = ABJ_404_Solution_FileSystemService::readFileContents(dirname(__DIR__) . '/html/' . $name, false);
174 return rtrim((string)$raw, "\n");
175 }
176 }
177