PluginProbe
404 Solution / 4.3.3
404 Solution v4.3.3
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 / view / View_ListTableChrome.php

View_ListTableChrome.php in 404 Solution 4.3.3, at includes/view/View_ListTableChrome.php

183 lines 8.4 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 * Admin list-table chrome shared by the Page Redirects and Captured 404 URLs
9 * admin tables. Owns the widgets that surround the data rows: subsubsub filter
10 * row, per-page selector, score-range filter, bulk-action form URL/options,
11 * empty-trash form, and the i18n strings for the pagination auto-refresh
12 * indicator. Pagination itself is rendered by ABJ_404_Solution_AdminPaginationLinks
13 * (single source of truth) and reaches the page over the same AJAX warmup channel.
14 */
15 class ABJ_404_Solution_View_ListTableChrome extends ABJ_404_Solution_ViewComponent {
16
17 /** Load a template file from includes/html/ and trim its trailing newline. */
18 private function tpl(string $name): string {
19 $raw = ABJ_404_Solution_FileSystemService::readFileContents(dirname(__DIR__) . '/html/' . $name, false);
20 return rtrim((string)$raw, "\n");
21 }
22
23 /**
24 * Load a template and substitute an associative array of placeholders.
25 * @param array<string,string> $vars
26 */
27 private function fillTpl(string $name, array $vars): string {
28 return (string)$this->f->str_replace(array_keys($vars), array_values($vars), $this->tpl($name));
29 }
30
31 /**
32 * Build the rows-per-page <option> list HTML.
33 *
34 * @param int|string $currentPerPage
35 */
36 public function buildPerpageOptions($currentPerPage): string {
37 $optionTpl = $this->tpl('viewRedirectsTablePerpageOption.html');
38 $html = '';
39 foreach (array(10, 25, 50, 100, 200) as $opt) {
40 $selected = ($currentPerPage == $opt) ? ' selected' : '';
41 $html .= $this->f->str_replace(
42 array('{value}', '{selected_attr}'),
43 array((string)$opt, $selected),
44 $optionTpl
45 ) . "\n";
46 }
47 return $html;
48 }
49
50 /** Build a bulk-action button (the type that posts to the bulk form). */
51 public function buildBulkButton(string $value, string $label): string {
52 return $this->f->str_replace(
53 array('{value}', '{label}'),
54 array(esc_attr($value), $label),
55 $this->tpl('viewRedirectsTableBulkButton.html')
56 ) . "\n";
57 }
58
59 /**
60 * Build the i18n string for the pagination "Refresh available" pill
61 * data-* attr. The pill is the only background-refresh surface: the table
62 * always renders live from the denorm read, so there is no "refreshing /
63 * data refreshed" progress toast (and no started/finished strings).
64 *
65 * @return array{available:string}
66 */
67 public function paginationRefreshStrings(): array {
68 $available = __('Refresh available', '404-solution');
69 return array('available' => $available);
70 }
71
72 /** Build the Confidence-filter <option> list for the Redirects table. */
73 public function buildScoreRangeOptions(string $currentScoreRange): string {
74 $opts = array(
75 'all' => __('All', '404-solution'),
76 // allow-em-dash: pre-existing translation string with U+2265 in published .po files
77 'high' => __('High (≥80%)', '404-solution'),
78 // allow-em-dash: pre-existing translation string with U+2013 in published .po files
79 'medium' => __('Medium (50–79%)', '404-solution'),
80 'low' => __('Low (<50%)', '404-solution'),
81 'manual' => __('Manual (no score)', '404-solution'),
82 );
83 $tpl = $this->tpl('viewRedirectsTableScoreRangeOption.html');
84 $html = '';
85 foreach ($opts as $val => $label) {
86 $html .= $this->f->str_replace(
87 array('{value}', '{selected_attr}', '{label}'),
88 array(esc_attr($val), ($currentScoreRange === $val) ? ' selected' : '', esc_html($label)),
89 $tpl
90 ) . "\n";
91 }
92 return $html;
93 }
94
95 /**
96 * Build the bulk-action <option> list for the Redirects table.
97 * @param mixed $currentFilter
98 */
99 public function buildRedirectsBulkActionOptions($currentFilter): string {
100 $tpl = $this->tpl('viewRedirectsTableBulkActionOption.html');
101 $opts = array();
102 if ($currentFilter != ABJ404_STATUS_AUTO) { $opts[] = array('editRedirect', esc_html__('Edit Redirects', '404-solution')); }
103 if ($currentFilter != ABJ404_TRASH_FILTER) { $opts[] = array('bulktrash', esc_html__('Move to Trash', '404-solution')); }
104 if ($currentFilter == ABJ404_TRASH_FILTER) {
105 $opts[] = array('bulk_trash_restore', esc_html__('Restore Redirects', '404-solution'));
106 $opts[] = array('bulk_trash_delete_permanently', esc_html__('Delete Permanently', '404-solution'));
107 }
108 $html = '';
109 foreach ($opts as $o) {
110 $html .= $this->f->str_replace(array('{value}', '{label}'), $o, $tpl) . "\n";
111 }
112 return $html;
113 }
114
115 /** Build the standalone Empty-Trash form shown below the redirects table when viewing the Trash filter. */
116 public function buildEmptyTrashForm(string $sub): string {
117 $eturl = wp_nonce_url("?page=" . ABJ404_PP . "&filter=" . ABJ404_TRASH_FILTER . "&subpage=" . $sub, "abj404_bulkProcess");
118 return $this->fillTpl('viewRedirectsTableEmptyTrashForm.html', array(
119 '{action_url}' => esc_url($eturl),
120 '{confirm_js}' => esc_js(__('Are you sure you want to permanently delete all items in the trash?', '404-solution')),
121 '{label}' => esc_html__('Empty Trash', '404-solution'),
122 ));
123 }
124
125 /**
126 * Build the native-WordPress subsubsub filter row for a list-table page.
127 *
128 * Counts are emitted as a placeholder character; the real numbers are
129 * populated by the pagination AJAX response (see view_updater_pagination.js).
130 *
131 * @param string $sub Subpage key (abj404_redirects, abj404_captured).
132 * @param array<int, array{0:int|string, 1:string}> $items One [filterValue, label] pair per link.
133 * @param array<string, mixed> $tableOptions Current table options (for active-link detection).
134 */
135 public function buildSubsubsubFilters(string $sub, array $items, array $tableOptions): string {
136 $currentFilter = isset($tableOptions['filter']) ? $tableOptions['filter'] : 0;
137 $itemTpl = ABJ_404_Solution_FileSystemService::readFileContents(dirname(__DIR__) . "/html/listTableSubsubsubItem.html");
138 $itemsHtml = '';
139 $lastIndex = count($items) - 1;
140 foreach ($items as $i => $pair) {
141 list($filter, $label) = $pair;
142 $url = "?page=" . ABJ404_PP . "&subpage=" . $sub;
143 if ($filter != 0) {
144 $url .= "&filter=" . $filter;
145 }
146 $isCurrent = ($currentFilter == $filter);
147 $classAttr = $isCurrent ? ' class="current"' : '';
148 $separator = ($i < $lastIndex) ? ' |' : '';
149
150 $row = $itemTpl;
151 $row = str_replace('{url}', esc_url($url), $row);
152 $row = str_replace('{classAttr}', $classAttr, $row);
153 $row = str_replace('{filter}', esc_attr((string)$filter), $row);
154 $row = str_replace('{label}', esc_html($label), $row);
155 $row = str_replace('{count}', '&hellip;', $row);
156 $row = str_replace('{separator}', $separator, $row);
157 $itemsHtml .= $row;
158 }
159
160 $outer = ABJ_404_Solution_FileSystemService::readFileContents(dirname(__DIR__) . "/html/listTableSubsubsub.html");
161 return str_replace('{items}', $itemsHtml, $outer);
162 }
163
164 /**
165 * @param array<string, mixed> $tableOptions
166 */
167 public function getBulkOperationsFormURL(string $sub, array $tableOptions): string {
168 $url = "?page=" . ABJ404_PP . "&subpage=" . $sub;
169 $filter = array_key_exists('filter', $tableOptions) && is_scalar($tableOptions['filter']) ? $tableOptions['filter'] : 0;
170 if ($filter != 0) {
171 $url .= "&filter=" . $filter;
172 }
173 $orderby = array_key_exists('orderby', $tableOptions) && is_string($tableOptions['orderby']) ? $tableOptions['orderby'] : 'url';
174 $order = array_key_exists('order', $tableOptions) && is_string($tableOptions['order']) ? $tableOptions['order'] : 'ASC';
175 if (!($orderby == "url" && $order == "ASC")) {
176 $url .= "&orderby=" . sanitize_text_field($orderby) . "&order=" . sanitize_text_field($order);
177 }
178 $url = wp_nonce_url($url, 'abj404_bulkProcess');
179 return $url;
180 }
181
182 }
183