FavoriteTableController.php 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190
  1. <?php
  2. declare(strict_types=1);
  3. namespace PhpMyAdmin\Controllers\Database\Structure;
  4. use PhpMyAdmin\ConfigStorage\Relation;
  5. use PhpMyAdmin\Controllers\Database\AbstractController;
  6. use PhpMyAdmin\RecentFavoriteTable;
  7. use PhpMyAdmin\ResponseRenderer;
  8. use PhpMyAdmin\Template;
  9. use PhpMyAdmin\Url;
  10. use PhpMyAdmin\Util;
  11. use function __;
  12. use function count;
  13. use function is_array;
  14. use function json_decode;
  15. use function json_encode;
  16. use function md5;
  17. use function sha1;
  18. final class FavoriteTableController extends AbstractController
  19. {
  20. /** @var Relation */
  21. private $relation;
  22. public function __construct(ResponseRenderer $response, Template $template, string $db, Relation $relation)
  23. {
  24. parent::__construct($response, $template, $db);
  25. $this->relation = $relation;
  26. }
  27. public function __invoke(): void
  28. {
  29. global $cfg, $db, $errorUrl;
  30. $parameters = [
  31. 'favorite_table' => $_REQUEST['favorite_table'] ?? null,
  32. 'favoriteTables' => $_REQUEST['favoriteTables'] ?? null,
  33. 'sync_favorite_tables' => $_REQUEST['sync_favorite_tables'] ?? null,
  34. ];
  35. Util::checkParameters(['db']);
  36. $errorUrl = Util::getScriptNameForOption($cfg['DefaultTabDatabase'], 'database');
  37. $errorUrl .= Url::getCommon(['db' => $db], '&');
  38. if (! $this->response->isAjax()) {
  39. return;
  40. }
  41. $favoriteInstance = RecentFavoriteTable::getInstance('favorite');
  42. if (isset($parameters['favoriteTables'])) {
  43. $favoriteTables = json_decode($parameters['favoriteTables'], true);
  44. if (! is_array($favoriteTables)) {
  45. $favoriteTables = [];
  46. }
  47. } else {
  48. $favoriteTables = [];
  49. }
  50. // Required to keep each user's preferences separate.
  51. $user = sha1($cfg['Server']['user']);
  52. // Request for Synchronization of favorite tables.
  53. if (isset($parameters['sync_favorite_tables'])) {
  54. $relationParameters = $this->relation->getRelationParameters();
  55. if ($relationParameters->favoriteTablesFeature !== null) {
  56. $this->response->addJSON($this->synchronizeFavoriteTables(
  57. $favoriteInstance,
  58. $user,
  59. $favoriteTables
  60. ));
  61. }
  62. return;
  63. }
  64. if (! $this->hasDatabase()) {
  65. return;
  66. }
  67. $changes = true;
  68. $favoriteTable = $parameters['favorite_table'] ?? '';
  69. $alreadyFavorite = $this->checkFavoriteTable($favoriteTable);
  70. if (isset($_REQUEST['remove_favorite'])) {
  71. if ($alreadyFavorite) {
  72. // If already in favorite list, remove it.
  73. $favoriteInstance->remove($this->db, $favoriteTable);
  74. $alreadyFavorite = false; // for favorite_anchor template
  75. }
  76. } elseif (isset($_REQUEST['add_favorite'])) {
  77. if (! $alreadyFavorite) {
  78. $numTables = count($favoriteInstance->getTables());
  79. if ($numTables == $cfg['NumFavoriteTables']) {
  80. $changes = false;
  81. } else {
  82. // Otherwise add to favorite list.
  83. $favoriteInstance->add($this->db, $favoriteTable);
  84. $alreadyFavorite = true; // for favorite_anchor template
  85. }
  86. }
  87. }
  88. $favoriteTables[$user] = $favoriteInstance->getTables();
  89. $json = [];
  90. $json['changes'] = $changes;
  91. if (! $changes) {
  92. $json['message'] = $this->template->render('components/error_message', [
  93. 'msg' => __('Favorite List is full!'),
  94. ]);
  95. $this->response->addJSON($json);
  96. return;
  97. }
  98. // Check if current table is already in favorite list.
  99. $favoriteParams = [
  100. 'db' => $this->db,
  101. 'ajax_request' => true,
  102. 'favorite_table' => $favoriteTable,
  103. ($alreadyFavorite ? 'remove' : 'add') . '_favorite' => true,
  104. ];
  105. $json['user'] = $user;
  106. $json['favoriteTables'] = json_encode($favoriteTables);
  107. $json['list'] = $favoriteInstance->getHtmlList();
  108. $json['anchor'] = $this->template->render('database/structure/favorite_anchor', [
  109. 'table_name_hash' => md5($favoriteTable),
  110. 'db_table_name_hash' => md5($this->db . '.' . $favoriteTable),
  111. 'fav_params' => $favoriteParams,
  112. 'already_favorite' => $alreadyFavorite,
  113. ]);
  114. $this->response->addJSON($json);
  115. }
  116. /**
  117. * Synchronize favorite tables
  118. *
  119. * @param RecentFavoriteTable $favoriteInstance Instance of this class
  120. * @param string $user The user hash
  121. * @param array $favoriteTables Existing favorites
  122. *
  123. * @return array
  124. */
  125. private function synchronizeFavoriteTables(
  126. RecentFavoriteTable $favoriteInstance,
  127. string $user,
  128. array $favoriteTables
  129. ): array {
  130. $favoriteInstanceTables = $favoriteInstance->getTables();
  131. if (empty($favoriteInstanceTables) && isset($favoriteTables[$user])) {
  132. foreach ($favoriteTables[$user] as $value) {
  133. $favoriteInstance->add($value['db'], $value['table']);
  134. }
  135. }
  136. $favoriteTables[$user] = $favoriteInstance->getTables();
  137. // Set flag when localStorage and pmadb(if present) are in sync.
  138. $_SESSION['tmpval']['favorites_synced'][$GLOBALS['server']] = true;
  139. return [
  140. 'favoriteTables' => json_encode($favoriteTables),
  141. 'list' => $favoriteInstance->getHtmlList(),
  142. ];
  143. }
  144. /**
  145. * Function to check if a table is already in favorite list.
  146. *
  147. * @param string $currentTable current table
  148. */
  149. private function checkFavoriteTable(string $currentTable): bool
  150. {
  151. $recentFavoriteTables = RecentFavoriteTable::getInstance('favorite');
  152. foreach ($recentFavoriteTables->getTables() as $value) {
  153. if ($value['db'] == $this->db && $value['table'] == $currentTable) {
  154. return true;
  155. }
  156. }
  157. return false;
  158. }
  159. }