Translated using Weblate (Portuguese)
[phpmyadmin.git] / src / BrowseForeigners.php
blob1ba9387303c931cd1691ed82383a3b871be12ea4
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\Theme\ThemeManager;
13 use function __;
14 use function array_keys;
15 use function asort;
16 use function ceil;
17 use function floor;
18 use function htmlspecialchars;
19 use function is_array;
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 mixed[] $foreignData foreign column data
137 * @param string|null $fieldKey field key
138 * @param string $currentValue current columns's value
140 public function getHtmlForRelationalFieldSelection(
141 string $db,
142 string $table,
143 string $field,
144 array $foreignData,
145 string|null $fieldKey,
146 string $currentValue,
147 ): string {
148 $gotoPage = $this->getHtmlForGotoPage($foreignData);
149 $foreignShowAll = $this->template->render('table/browse_foreigners/show_all', [
150 'foreign_data' => $foreignData,
151 'show_all' => $this->settings->showAll,
152 'max_rows' => $this->settings->maxRows,
155 $output = '<form class="ajax" '
156 . 'id="browse_foreign_form" name="browse_foreign_from" action="'
157 . Url::getFromRoute('/browse-foreigners')
158 . '" method="post"><fieldset class="row g-3 align-items-center mb-3">' . "\n"
159 . Url::getHiddenInputs($db, $table) . "\n"
160 . '<input type="hidden" name="field" value="' . htmlspecialchars($field) . '">' . "\n"
161 . '<input type="hidden" name="fieldkey" value="'
162 . (isset($fieldKey) ? htmlspecialchars($fieldKey) : '') . '">' . "\n";
164 if (isset($_POST['rownumber'])) {
165 $output .= '<input type="hidden" name="rownumber" value="'
166 . htmlspecialchars((string) $_POST['rownumber']) . '">';
169 $filterValue = isset($_POST['foreign_filter'])
170 ? htmlspecialchars($_POST['foreign_filter'])
171 : '';
172 $output .= '<div class="col-auto">'
173 . '<label class="form-label" for="input_foreign_filter">' . __('Search:') . '</label></div>' . "\n"
174 . '<div class="col-auto"><input class="form-control" type="text" name="foreign_filter" '
175 . 'id="input_foreign_filter" '
176 . 'value="' . $filterValue . '" data-old="' . $filterValue . '">' . "\n"
177 . '</div><div class="col-auto">'
178 . '<input class="btn btn-primary" type="submit" name="submit_foreign_filter" value="'
179 . __('Go') . '">'
180 . '</div>' . "\n"
181 . '<div class="col-auto">' . $gotoPage . '</div>'
182 . '<div class="col-auto">' . $foreignShowAll . '</div>'
183 . '</fieldset>'
184 . '</form>' . "\n";
186 $output .= '<table class="table table-striped table-hover" id="browse_foreign_table">' . "\n";
188 if (! is_array($foreignData['disp_row'])) {
189 return $output . '</tbody>'
190 . '</table>';
193 $header = '<tr>
194 <th>' . __('Keyname') . '</th>
195 <th>' . __('Description') . '</th>
196 <td width="20%"></td>
197 <th>' . __('Description') . '</th>
198 <th>' . __('Keyname') . '</th>
199 </tr>' . "\n";
201 $output .= '<thead>' . $header . '</thead>' . "\n"
202 . '<tfoot>' . $header . '</tfoot>' . "\n"
203 . '<tbody>' . "\n";
205 $descriptions = [];
206 $keys = [];
207 foreach ($foreignData['disp_row'] as $relrow) {
208 if ($foreignData['foreign_display'] != false) {
209 $descriptions[] = $relrow[$foreignData['foreign_display']] ?? '';
210 } else {
211 $descriptions[] = '';
214 $keys[] = $relrow[$foreignData['foreign_field']];
217 asort($keys);
219 $horizontalCount = 0;
220 $indexByDescription = 0;
222 foreach (array_keys($keys) as $indexByKeyname) {
223 [$html, $horizontalCount, $indexByDescription] = $this->getHtmlForOneKey(
224 $horizontalCount,
225 $header,
226 $keys,
227 $indexByKeyname,
228 $descriptions,
229 $indexByDescription,
230 $currentValue,
232 $output .= $html . "\n";
235 $output .= '</tbody></table>';
237 return $output;
241 * Get the description (possibly truncated) and the title
243 * @param string $description the key name's description
245 * @return array<int,string> the new description and title
247 private function getDescriptionAndTitle(string $description): array
249 if (mb_strlen($description) <= $this->settings->limitChars) {
250 $descriptionTitle = '';
251 } else {
252 $descriptionTitle = $description;
253 $description = mb_substr($description, 0, $this->settings->limitChars) . '...';
256 return [$description, $descriptionTitle];
260 * Function to get html for the goto page option
262 * @param mixed[]|null $foreignData foreign data
264 private function getHtmlForGotoPage(array|null $foreignData): string
266 isset($_POST['pos']) ? $pos = $_POST['pos'] : $pos = 0;
267 if ($foreignData === null || ! is_array($foreignData['disp_row'])) {
268 return '';
271 $pageNow = (int) floor($pos / $this->settings->maxRows) + 1;
272 $nbTotalPage = (int) ceil($foreignData['the_total'] / $this->settings->maxRows);
274 if ($foreignData['the_total'] > $this->settings->maxRows) {
275 return Util::pageselector(
276 'pos',
277 $this->settings->maxRows,
278 $pageNow,
279 $nbTotalPage,
280 200,
285 __('Page number:'),
289 return '';
293 * Function to get foreign limit
295 * @param string|null $foreignShowAll foreign navigation
297 public function getForeignLimit(string|null $foreignShowAll): string|null
299 if ($foreignShowAll === __('Show all')) {
300 return null;
303 isset($_POST['pos']) ? $pos = $_POST['pos'] : $pos = 0;
305 return 'LIMIT ' . $pos . ', ' . $this->settings->maxRows . ' ';