3 * Contains functions used by browse foreigners
6 declare(strict_types
=1);
10 use PhpMyAdmin\Config\Settings
;
11 use PhpMyAdmin\ConfigStorage\ForeignData
;
12 use PhpMyAdmin\Theme\ThemeManager
;
15 use function array_keys
;
19 use function htmlspecialchars
;
20 use function mb_strlen
;
21 use function mb_substr
;
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();
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(
54 int $indexByDescription,
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
) {
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];
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,
98 $output .= $this->template
->render('table/browse_foreigners/column_element', [
99 'keyname' => $leftKeyname,
100 'description' => $leftDescription,
101 'title' => $leftDescriptionTitle,
102 'is_selected' => $leftKeynameIsSelected,
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,
117 $output .= $this->template
->render('table/browse_foreigners/column_element', [
118 'keyname' => $rightKeyname,
119 'description' => $rightDescription,
120 'title' => $rightDescriptionTitle,
121 'is_selected' => $rightKeynameIsSelected,
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 $fieldKey field key
137 * @param string $currentValue current columns's value
139 public function getHtmlForRelationalFieldSelection(
143 ForeignData
$foreignData,
145 string $currentValue,
147 string $foreignFilter,
148 string|
null $rownumber,
150 $gotoPage = $this->getHtmlForGotoPage($foreignData, $pos);
151 $foreignShowAll = '';
153 $foreignData->dispRow
!== null &&
154 $this->settings
->showAll
&& $foreignData->theTotal
> $this->settings
->maxRows
156 $foreignShowAll = $this->template
->render('table/browse_foreigners/show_all');
159 $output = '<form class="ajax" '
160 . 'id="browse_foreign_form" name="browse_foreign_from" action="'
161 . Url
::getFromRoute('/browse-foreigners')
162 . '" method="post"><fieldset class="row g-3 align-items-center mb-3">' . "\n"
163 . Url
::getHiddenInputs($db, $table) . "\n"
164 . '<input type="hidden" name="field" value="' . htmlspecialchars($field) . '">' . "\n"
165 . '<input type="hidden" name="fieldkey" value="'
166 . htmlspecialchars($fieldKey) . '">' . "\n";
168 if ($rownumber !== null) {
169 $output .= '<input type="hidden" name="rownumber" value="' . htmlspecialchars($rownumber) . '">';
172 $filterValue = htmlspecialchars($foreignFilter);
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="'
182 . '<div class="col-auto">' . $gotoPage . '</div>'
183 . '<div class="col-auto">' . $foreignShowAll . '</div>'
187 $output .= '<table class="table table-striped table-hover" id="browse_foreign_table">' . "\n";
189 if ($foreignData->dispRow
=== null) {
190 return $output . '</tbody>'
195 <th>' . __('Keyname') . '</th>
196 <th>' . __('Description') . '</th>
197 <td width="20%"></td>
198 <th>' . __('Description') . '</th>
199 <th>' . __('Keyname') . '</th>
202 $output .= '<thead>' . $header . '</thead>' . "\n"
203 . '<tfoot>' . $header . '</tfoot>' . "\n"
208 foreach ($foreignData->dispRow
as $relrow) {
209 $descriptions[] = $relrow[$foreignData->foreignDisplay
] ??
'';
210 $keys[] = $relrow[$foreignData->foreignField
];
215 $horizontalCount = 0;
216 $indexByDescription = 0;
218 foreach (array_keys($keys) as $indexByKeyname) {
219 [$html, $horizontalCount, $indexByDescription] = $this->getHtmlForOneKey(
228 $output .= $html . "\n";
231 $output .= '</tbody></table>';
237 * Get the description (possibly truncated) and the title
239 * @param string $description the key name's description
241 * @return array{string, string} the new description and title
243 private function getDescriptionAndTitle(string $description): array
245 if (mb_strlen($description) <= $this->settings
->limitChars
) {
246 $descriptionTitle = '';
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, int $pos): string
260 if ($foreignData->dispRow
=== null) {
264 $pageNow = (int) floor($pos / $this->settings
->maxRows
) +
1;
265 $nbTotalPage = (int) ceil($foreignData->theTotal
/ $this->settings
->maxRows
);
267 if ($foreignData->theTotal
> $this->settings
->maxRows
) {
268 return Util
::pageselector(
270 $this->settings
->maxRows
,
285 public function getForeignLimit(string|
null $foreignShowAll, int $pos): string
287 if ($foreignShowAll === __('Show all')) {
291 return 'LIMIT ' . $pos . ', ' . $this->settings
->maxRows
. ' ';