Translated using Weblate (English (United Kingdom))
[phpmyadmin.git] / src / BrowseForeigners.php
blobcd27e7708b13ade94c79e1ceb41ea09c1105c1df
1 <?php
2 /**
3 * Contains functions used by browse foreigners
4 */
6 declare(strict_types=1);
8 namespace PhpMyAdmin;
10 use PhpMyAdmin\Config\Settings;
11 use PhpMyAdmin\ConfigStorage\ForeignData;
12 use PhpMyAdmin\Theme\ThemeManager;
14 use function __;
15 use function array_keys;
16 use function asort;
17 use function ceil;
18 use function floor;
19 use function htmlspecialchars;
20 use function mb_strlen;
21 use function mb_substr;
23 /**
24 * PhpMyAdmin\BrowseForeigners class
26 class BrowseForeigners
28 private Settings $settings;
30 public function __construct(public Template $template, Config $config, private readonly ThemeManager $themeManager)
32 $this->settings = $config->getSettings();
35 /**
36 * Function to get html for one relational key
38 * @param int $horizontalCount the current horizontal count
39 * @param string $header table header
40 * @param mixed[] $keys all the keys
41 * @param int $indexByKeyname index by keyname
42 * @param mixed[] $descriptions descriptions
43 * @param int $indexByDescription index by description
44 * @param string $currentValue current value on the edit form
46 * @return array{string, int, int} the generated html
48 private function getHtmlForOneKey(
49 int $horizontalCount,
50 string $header,
51 array $keys,
52 int $indexByKeyname,
53 array $descriptions,
54 int $indexByDescription,
55 string $currentValue,
56 ): array {
57 $horizontalCount++;
58 $output = '';
60 // whether the key name corresponds to the selected value in the form
61 $rightKeynameIsSelected = false;
62 $leftKeynameIsSelected = false;
64 if ($this->settings->repeatCells > 0 && $horizontalCount > $this->settings->repeatCells) {
65 $output .= $header;
66 $horizontalCount = 0;
69 // key names and descriptions for the left section,
70 // sorted by key names
71 $leftKeyname = $keys[$indexByKeyname];
72 [$leftDescription, $leftDescriptionTitle] = $this->getDescriptionAndTitle($descriptions[$indexByKeyname]);
74 // key names and descriptions for the right section,
75 // sorted by descriptions
76 $rightKeyname = $keys[$indexByDescription];
78 $rightDescription,
79 $rightDescriptionTitle,
80 ] = $this->getDescriptionAndTitle($descriptions[$indexByDescription]);
82 $indexByDescription++;
84 if ($currentValue !== '') {
85 $rightKeynameIsSelected = $rightKeyname == $currentValue;
86 $leftKeynameIsSelected = $leftKeyname == $currentValue;
89 $output .= '<tr class="noclick">';
91 $output .= $this->template->render('table/browse_foreigners/column_element', [
92 'keyname' => $leftKeyname,
93 'description' => $leftDescription,
94 'title' => $leftDescriptionTitle,
95 'is_selected' => $leftKeynameIsSelected,
96 'nowrap' => true,
97 ]);
98 $output .= $this->template->render('table/browse_foreigners/column_element', [
99 'keyname' => $leftKeyname,
100 'description' => $leftDescription,
101 'title' => $leftDescriptionTitle,
102 'is_selected' => $leftKeynameIsSelected,
103 'nowrap' => false,
106 $output .= '<td width="20%"><img src="'
107 . $this->themeManager->theme->getImgPath('spacer.png')
108 . '" alt="" width="1" height="1"></td>';
110 $output .= $this->template->render('table/browse_foreigners/column_element', [
111 'keyname' => $rightKeyname,
112 'description' => $rightDescription,
113 'title' => $rightDescriptionTitle,
114 'is_selected' => $rightKeynameIsSelected,
115 'nowrap' => false,
117 $output .= $this->template->render('table/browse_foreigners/column_element', [
118 'keyname' => $rightKeyname,
119 'description' => $rightDescription,
120 'title' => $rightDescriptionTitle,
121 'is_selected' => $rightKeynameIsSelected,
122 'nowrap' => true,
125 $output .= '</tr>';
127 return [$output, $horizontalCount, $indexByDescription];
131 * Function to get html for relational field selection
133 * @param string $db current database
134 * @param string $table current table
135 * @param string $field field
136 * @param string|null $fieldKey field key
137 * @param string $currentValue current columns's value
139 public function getHtmlForRelationalFieldSelection(
140 string $db,
141 string $table,
142 string $field,
143 ForeignData $foreignData,
144 string|null $fieldKey,
145 string $currentValue,
146 ): string {
147 $gotoPage = $this->getHtmlForGotoPage($foreignData);
148 $foreignShowAll = '';
149 if (
150 $foreignData->dispRow !== null &&
151 $this->settings->showAll && $foreignData->theTotal > $this->settings->maxRows
153 $foreignShowAll = $this->template->render('table/browse_foreigners/show_all');
156 $output = '<form class="ajax" '
157 . 'id="browse_foreign_form" name="browse_foreign_from" action="'
158 . Url::getFromRoute('/browse-foreigners')
159 . '" method="post"><fieldset class="row g-3 align-items-center mb-3">' . "\n"
160 . Url::getHiddenInputs($db, $table) . "\n"
161 . '<input type="hidden" name="field" value="' . htmlspecialchars($field) . '">' . "\n"
162 . '<input type="hidden" name="fieldkey" value="'
163 . (isset($fieldKey) ? htmlspecialchars($fieldKey) : '') . '">' . "\n";
165 if (isset($_POST['rownumber'])) {
166 $output .= '<input type="hidden" name="rownumber" value="'
167 . htmlspecialchars((string) $_POST['rownumber']) . '">';
170 $filterValue = isset($_POST['foreign_filter'])
171 ? htmlspecialchars($_POST['foreign_filter'])
172 : '';
173 $output .= '<div class="col-auto">'
174 . '<label class="form-label" for="input_foreign_filter">' . __('Search:') . '</label></div>' . "\n"
175 . '<div class="col-auto"><input class="form-control" type="text" name="foreign_filter" '
176 . 'id="input_foreign_filter" '
177 . 'value="' . $filterValue . '" data-old="' . $filterValue . '">' . "\n"
178 . '</div><div class="col-auto">'
179 . '<input class="btn btn-primary" type="submit" name="submit_foreign_filter" value="'
180 . __('Go') . '">'
181 . '</div>' . "\n"
182 . '<div class="col-auto">' . $gotoPage . '</div>'
183 . '<div class="col-auto">' . $foreignShowAll . '</div>'
184 . '</fieldset>'
185 . '</form>' . "\n";
187 $output .= '<table class="table table-striped table-hover" id="browse_foreign_table">' . "\n";
189 if ($foreignData->dispRow === null) {
190 return $output . '</tbody>'
191 . '</table>';
194 $header = '<tr>
195 <th>' . __('Keyname') . '</th>
196 <th>' . __('Description') . '</th>
197 <td width="20%"></td>
198 <th>' . __('Description') . '</th>
199 <th>' . __('Keyname') . '</th>
200 </tr>' . "\n";
202 $output .= '<thead>' . $header . '</thead>' . "\n"
203 . '<tfoot>' . $header . '</tfoot>' . "\n"
204 . '<tbody>' . "\n";
206 $descriptions = [];
207 $keys = [];
208 foreach ($foreignData->dispRow as $relrow) {
209 $descriptions[] = $relrow[$foreignData->foreignDisplay] ?? '';
210 $keys[] = $relrow[$foreignData->foreignField];
213 asort($keys);
215 $horizontalCount = 0;
216 $indexByDescription = 0;
218 foreach (array_keys($keys) as $indexByKeyname) {
219 [$html, $horizontalCount, $indexByDescription] = $this->getHtmlForOneKey(
220 $horizontalCount,
221 $header,
222 $keys,
223 $indexByKeyname,
224 $descriptions,
225 $indexByDescription,
226 $currentValue,
228 $output .= $html . "\n";
231 $output .= '</tbody></table>';
233 return $output;
237 * Get the description (possibly truncated) and the title
239 * @param string $description the key name's description
241 * @return array<int,string> the new description and title
243 private function getDescriptionAndTitle(string $description): array
245 if (mb_strlen($description) <= $this->settings->limitChars) {
246 $descriptionTitle = '';
247 } else {
248 $descriptionTitle = $description;
249 $description = mb_substr($description, 0, $this->settings->limitChars) . '...';
252 return [$description, $descriptionTitle];
256 * Function to get html for the goto page option
258 private function getHtmlForGotoPage(ForeignData $foreignData): string
260 isset($_POST['pos']) ? $pos = $_POST['pos'] : $pos = 0;
261 if ($foreignData->dispRow === null) {
262 return '';
265 $pageNow = (int) floor($pos / $this->settings->maxRows) + 1;
266 $nbTotalPage = (int) ceil($foreignData->theTotal / $this->settings->maxRows);
268 if ($foreignData->theTotal > $this->settings->maxRows) {
269 return Util::pageselector(
270 'pos',
271 $this->settings->maxRows,
272 $pageNow,
273 $nbTotalPage,
274 200,
279 __('Page number:'),
283 return '';
287 * Function to get foreign limit
289 * @param string|null $foreignShowAll foreign navigation
291 public function getForeignLimit(string|null $foreignShowAll): string|null
293 if ($foreignShowAll === __('Show all')) {
294 return null;
297 isset($_POST['pos']) ? $pos = $_POST['pos'] : $pos = 0;
299 return 'LIMIT ' . $pos . ', ' . $this->settings->maxRows . ' ';