SaveAccountsTableData.php 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172
  1. <?php
  2. /**
  3. * @copyright Copyright (c) 2017 Joas Schilling <coding@schilljs.com>
  4. *
  5. * @author Joas Schilling <coding@schilljs.com>
  6. *
  7. * @license GNU AGPL version 3 or any later version
  8. *
  9. * This program is free software: you can redistribute it and/or modify
  10. * it under the terms of the GNU Affero General Public License as
  11. * published by the Free Software Foundation, either version 3 of the
  12. * License, or (at your option) any later version.
  13. *
  14. * This program is distributed in the hope that it will be useful,
  15. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  16. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  17. * GNU Affero General Public License for more details.
  18. *
  19. * You should have received a copy of the GNU Affero General Public License
  20. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  21. *
  22. */
  23. namespace OC\Repair\Owncloud;
  24. use OCP\DB\QueryBuilder\IQueryBuilder;
  25. use OCP\IConfig;
  26. use OCP\IDBConnection;
  27. use OCP\Migration\IOutput;
  28. use OCP\Migration\IRepairStep;
  29. use OCP\PreConditionNotMetException;
  30. /**
  31. * Copies the email address from the accounts table to the preference table,
  32. * before the data structure is changed and the information is gone
  33. */
  34. class SaveAccountsTableData implements IRepairStep {
  35. const BATCH_SIZE = 75;
  36. /** @var IDBConnection */
  37. protected $db;
  38. /** @var IConfig */
  39. protected $config;
  40. /**
  41. * @param IDBConnection $db
  42. * @param IConfig $config
  43. */
  44. public function __construct(IDBConnection $db, IConfig $config) {
  45. $this->db = $db;
  46. $this->config = $config;
  47. }
  48. /**
  49. * @return string
  50. */
  51. public function getName() {
  52. return 'Copy data from accounts table when migrating from ownCloud';
  53. }
  54. /**
  55. * @param IOutput $output
  56. */
  57. public function run(IOutput $output) {
  58. if (!$this->shouldRun()) {
  59. return;
  60. }
  61. $offset = 0;
  62. $numUsers = $this->runStep($offset);
  63. while ($numUsers === self::BATCH_SIZE) {
  64. $offset += $numUsers;
  65. $numUsers = $this->runStep($offset);
  66. }
  67. // Remove the table
  68. $this->db->dropTable('accounts');
  69. }
  70. /**
  71. * @return bool
  72. */
  73. protected function shouldRun() {
  74. $schema = $this->db->createSchema();
  75. $tableName = $this->config->getSystemValue('dbtableprefix', 'oc_') . 'accounts';
  76. if (!$schema->hasTable($tableName)) {
  77. return false;
  78. }
  79. $table = $schema->getTable($tableName);
  80. return $table->hasColumn('user_id');
  81. }
  82. /**
  83. * @param int $offset
  84. * @return int Number of copied users
  85. */
  86. protected function runStep($offset) {
  87. $query = $this->db->getQueryBuilder();
  88. $query->select('*')
  89. ->from('accounts')
  90. ->orderBy('id')
  91. ->setMaxResults(self::BATCH_SIZE);
  92. if ($offset > 0) {
  93. $query->setFirstResult($offset);
  94. }
  95. $result = $query->execute();
  96. $update = $this->db->getQueryBuilder();
  97. $update->update('users')
  98. ->set('displayname', $update->createParameter('displayname'))
  99. ->where($update->expr()->eq('uid', $update->createParameter('userid')));
  100. $updatedUsers = 0;
  101. while ($row = $result->fetch()) {
  102. try {
  103. $this->migrateUserInfo($update, $row);
  104. } catch (PreConditionNotMetException $e) {
  105. // Ignore and continue
  106. } catch (\UnexpectedValueException $e) {
  107. // Ignore and continue
  108. }
  109. $updatedUsers++;
  110. }
  111. $result->closeCursor();
  112. return $updatedUsers;
  113. }
  114. /**
  115. * @param IQueryBuilder $update
  116. * @param array $userdata
  117. * @throws PreConditionNotMetException
  118. * @throws \UnexpectedValueException
  119. */
  120. protected function migrateUserInfo(IQueryBuilder $update, $userdata) {
  121. $state = (int) $userdata['state'];
  122. if ($state === 3) {
  123. // Deleted user, ignore
  124. return;
  125. }
  126. if ($userdata['email'] !== null) {
  127. $this->config->setUserValue($userdata['user_id'], 'settings', 'email', $userdata['email']);
  128. }
  129. if ($userdata['quota'] !== null) {
  130. $this->config->setUserValue($userdata['user_id'], 'files', 'quota', $userdata['quota']);
  131. }
  132. if ($userdata['last_login'] !== null) {
  133. $this->config->setUserValue($userdata['user_id'], 'login', 'lastLogin', $userdata['last_login']);
  134. }
  135. if ($state === 1) {
  136. $this->config->setUserValue($userdata['user_id'], 'core', 'enabled', 'true');
  137. } else if ($state === 2) {
  138. $this->config->setUserValue($userdata['user_id'], 'core', 'enabled', 'false');
  139. }
  140. if ($userdata['display_name'] !== null) {
  141. $update->setParameter('displayname', $userdata['display_name'])
  142. ->setParameter('userid', $userdata['user_id']);
  143. $update->execute();
  144. }
  145. }
  146. }