BrowseForeigners.php 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346
  1. <?php
  2. /* vim: set expandtab sw=4 ts=4 sts=4: */
  3. /**
  4. * Contains functions used by browse_foreigners.php
  5. *
  6. * @package PhpMyAdmin
  7. */
  8. namespace PhpMyAdmin;
  9. use PhpMyAdmin\Template;
  10. use PhpMyAdmin\Url;
  11. use PhpMyAdmin\Util;
  12. /**
  13. * PhpMyAdmin\BrowseForeigners class
  14. *
  15. * @package PhpMyAdmin
  16. */
  17. class BrowseForeigners
  18. {
  19. private $limitChars;
  20. private $maxRows;
  21. private $repeatCells;
  22. private $showAll;
  23. private $themeImage;
  24. /**
  25. * Constructor
  26. *
  27. * @param int $limitChars Maximum number of characters to show
  28. * @param int $maxRows Number of rows to display
  29. * @param int $repeatCells Repeat the headers every X cells, or 0 to deactivate
  30. * @param boolean $showAll Shows the 'Show all' button or not
  31. * @param string $themeImage Theme image path
  32. */
  33. public function __construct(
  34. $limitChars,
  35. $maxRows,
  36. $repeatCells,
  37. $showAll,
  38. $themeImage
  39. ) {
  40. $this->limitChars = (int) $limitChars;
  41. $this->maxRows = (int) $maxRows;
  42. $this->repeatCells = (int) $repeatCells;
  43. $this->showAll = (bool) $showAll;
  44. $this->themeImage = $themeImage;
  45. }
  46. /**
  47. * Function to get html for one relational key
  48. *
  49. * @param integer $horizontal_count the current horizontal count
  50. * @param string $header table header
  51. * @param array $keys all the keys
  52. * @param integer $indexByKeyname index by keyname
  53. * @param array $descriptions descriptions
  54. * @param integer $indexByDescription index by description
  55. * @param string $current_value current value on the edit form
  56. *
  57. * @return string $html the generated html
  58. */
  59. private function getHtmlForOneKey(
  60. $horizontal_count,
  61. $header,
  62. array $keys,
  63. $indexByKeyname,
  64. array $descriptions,
  65. $indexByDescription,
  66. $current_value
  67. ) {
  68. $horizontal_count++;
  69. $output = '';
  70. // whether the key name corresponds to the selected value in the form
  71. $rightKeynameIsSelected = false;
  72. $leftKeynameIsSelected = false;
  73. if ($this->repeatCells > 0 && $horizontal_count > $this->repeatCells) {
  74. $output .= $header;
  75. $horizontal_count = 0;
  76. }
  77. // key names and descriptions for the left section,
  78. // sorted by key names
  79. $leftKeyname = $keys[$indexByKeyname];
  80. list(
  81. $leftDescription,
  82. $leftDescriptionTitle
  83. ) = $this->getDescriptionAndTitle($descriptions[$indexByKeyname]);
  84. // key names and descriptions for the right section,
  85. // sorted by descriptions
  86. $rightKeyname = $keys[$indexByDescription];
  87. list(
  88. $rightDescription,
  89. $rightDescriptionTitle
  90. ) = $this->getDescriptionAndTitle($descriptions[$indexByDescription]);
  91. $indexByDescription++;
  92. if (! empty($current_value)) {
  93. $rightKeynameIsSelected = $rightKeyname == $current_value;
  94. $leftKeynameIsSelected = $leftKeyname == $current_value;
  95. }
  96. $output .= '<tr class="noclick">';
  97. $output .= Template::get('table/browse_foreigners/column_element')->render([
  98. 'keyname' => $leftKeyname,
  99. 'description' => $leftDescription,
  100. 'title' => $leftDescriptionTitle,
  101. 'is_selected' => $leftKeynameIsSelected,
  102. 'nowrap' => true,
  103. ]);
  104. $output .= Template::get('table/browse_foreigners/column_element')->render([
  105. 'keyname' => $leftKeyname,
  106. 'description' => $leftDescription,
  107. 'title' => $leftDescriptionTitle,
  108. 'is_selected' => $leftKeynameIsSelected,
  109. 'nowrap' => false,
  110. ]);
  111. $output .= '<td width="20%">'
  112. . '<img src="' . $this->themeImage . 'spacer.png" alt=""'
  113. . ' width="1" height="1" /></td>';
  114. $output .= Template::get('table/browse_foreigners/column_element')->render([
  115. 'keyname' => $rightKeyname,
  116. 'description' => $rightDescription,
  117. 'title' => $rightDescriptionTitle,
  118. 'is_selected' => $rightKeynameIsSelected,
  119. 'nowrap' => false,
  120. ]);
  121. $output .= Template::get('table/browse_foreigners/column_element')->render([
  122. 'keyname' => $rightKeyname,
  123. 'description' => $rightDescription,
  124. 'title' => $rightDescriptionTitle,
  125. 'is_selected' => $rightKeynameIsSelected,
  126. 'nowrap' => true,
  127. ]);
  128. $output .= '</tr>';
  129. return array($output, $horizontal_count, $indexByDescription);
  130. }
  131. /**
  132. * Function to get html for relational field selection
  133. *
  134. * @param string $db current database
  135. * @param string $table current table
  136. * @param string $field field
  137. * @param array $foreignData foreign column data
  138. * @param string $fieldkey field key
  139. * @param string $current_value current columns's value
  140. *
  141. * @return string
  142. */
  143. public function getHtmlForRelationalFieldSelection(
  144. $db,
  145. $table,
  146. $field,
  147. array $foreignData,
  148. $fieldkey,
  149. $current_value
  150. ) {
  151. $gotopage = $this->getHtmlForGotoPage($foreignData);
  152. $foreignShowAll = Template::get('table/browse_foreigners/show_all')->render([
  153. 'foreign_data' => $foreignData,
  154. 'show_all' => $this->showAll,
  155. 'max_rows' => $this->maxRows,
  156. ]);
  157. $output = '<form class="ajax" '
  158. . 'id="browse_foreign_form" name="browse_foreign_from" '
  159. . 'action="browse_foreigners.php" method="post">'
  160. . '<fieldset>'
  161. . Url::getHiddenInputs($db, $table)
  162. . '<input type="hidden" name="field" value="' . htmlspecialchars($field)
  163. . '" />'
  164. . '<input type="hidden" name="fieldkey" value="'
  165. . (isset($fieldkey) ? htmlspecialchars($fieldkey) : '') . '" />';
  166. if (isset($_POST['rownumber'])) {
  167. $output .= '<input type="hidden" name="rownumber" value="'
  168. . htmlspecialchars($_POST['rownumber']) . '" />';
  169. }
  170. $filter_value = (isset($_POST['foreign_filter'])
  171. ? htmlspecialchars($_POST['foreign_filter'])
  172. : '');
  173. $output .= '<span class="formelement">'
  174. . '<label for="input_foreign_filter">' . __('Search:') . '</label>'
  175. . '<input type="text" name="foreign_filter" '
  176. . 'id="input_foreign_filter" '
  177. . 'value="' . $filter_value . '" data-old="' . $filter_value . '" '
  178. . '/>'
  179. . '<input type="submit" name="submit_foreign_filter" value="'
  180. . __('Go') . '" />'
  181. . '</span>'
  182. . '<span class="formelement">' . $gotopage . '</span>'
  183. . '<span class="formelement">' . $foreignShowAll . '</span>'
  184. . '</fieldset>'
  185. . '</form>';
  186. $output .= '<table width="100%" id="browse_foreign_table">';
  187. if (!is_array($foreignData['disp_row'])) {
  188. $output .= '</tbody>'
  189. . '</table>';
  190. return $output;
  191. }
  192. $header = '<tr>
  193. <th>' . __('Keyname') . '</th>
  194. <th>' . __('Description') . '</th>
  195. <td width="20%"></td>
  196. <th>' . __('Description') . '</th>
  197. <th>' . __('Keyname') . '</th>
  198. </tr>';
  199. $output .= '<thead>' . $header . '</thead>' . "\n"
  200. . '<tfoot>' . $header . '</tfoot>' . "\n"
  201. . '<tbody>' . "\n";
  202. $descriptions = array();
  203. $keys = array();
  204. foreach ($foreignData['disp_row'] as $relrow) {
  205. if ($foreignData['foreign_display'] != false) {
  206. $descriptions[] = $relrow[$foreignData['foreign_display']];
  207. } else {
  208. $descriptions[] = '';
  209. }
  210. $keys[] = $relrow[$foreignData['foreign_field']];
  211. }
  212. asort($keys);
  213. $horizontal_count = 0;
  214. $indexByDescription = 0;
  215. foreach ($keys as $indexByKeyname => $value) {
  216. list(
  217. $html,
  218. $horizontal_count,
  219. $indexByDescription
  220. ) = $this->getHtmlForOneKey(
  221. $horizontal_count,
  222. $header,
  223. $keys,
  224. $indexByKeyname,
  225. $descriptions,
  226. $indexByDescription,
  227. $current_value
  228. );
  229. $output .= $html;
  230. }
  231. $output .= '</tbody>'
  232. . '</table>';
  233. return $output;
  234. }
  235. /**
  236. * Get the description (possibly truncated) and the title
  237. *
  238. * @param string $description the key name's description
  239. *
  240. * @return array the new description and title
  241. */
  242. private function getDescriptionAndTitle($description)
  243. {
  244. if (mb_strlen($description) <= $this->limitChars) {
  245. $description = htmlspecialchars(
  246. $description
  247. );
  248. $descriptionTitle = '';
  249. } else {
  250. $descriptionTitle = htmlspecialchars(
  251. $description
  252. );
  253. $description = htmlspecialchars(
  254. mb_substr(
  255. $description, 0, $this->limitChars
  256. )
  257. . '...'
  258. );
  259. }
  260. return array($description, $descriptionTitle);
  261. }
  262. /**
  263. * Function to get html for the goto page option
  264. *
  265. * @param array|null $foreignData foreign data
  266. *
  267. * @return string
  268. */
  269. private function getHtmlForGotoPage($foreignData)
  270. {
  271. $gotopage = '';
  272. isset($_POST['pos']) ? $pos = $_POST['pos'] : $pos = 0;
  273. if ($foreignData === null || ! is_array($foreignData['disp_row'])) {
  274. return $gotopage;
  275. }
  276. $pageNow = @floor($pos / $this->maxRows) + 1;
  277. $nbTotalPage = @ceil($foreignData['the_total'] / $this->maxRows);
  278. if ($foreignData['the_total'] > $this->maxRows) {
  279. $gotopage = Util::pageselector(
  280. 'pos',
  281. $this->maxRows,
  282. $pageNow,
  283. $nbTotalPage,
  284. 200,
  285. 5,
  286. 5,
  287. 20,
  288. 10,
  289. __('Page number:')
  290. );
  291. }
  292. return $gotopage;
  293. }
  294. /**
  295. * Function to get foreign limit
  296. *
  297. * @param string $foreignShowAll foreign navigation
  298. *
  299. * @return string
  300. */
  301. public function getForeignLimit($foreignShowAll)
  302. {
  303. if (isset($foreignShowAll) && $foreignShowAll == __('Show all')) {
  304. return null;
  305. }
  306. isset($_POST['pos']) ? $pos = $_POST['pos'] : $pos = 0;
  307. return 'LIMIT ' . $pos . ', ' . $this->maxRows . ' ';
  308. }
  309. }