Completed
Push — master ( 879e11...10930c )
by Lukas
20:02 queued 06:34
created

SaveAccountsTableData::runStep()   B

Complexity

Conditions 5
Paths 8

Size

Total Lines 33
Code Lines 22

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 5
eloc 22
nc 8
nop 1
dl 0
loc 33
rs 8.439
c 0
b 0
f 0
1
<?php
2
/**
3
 * @copyright Copyright (c) 2017 Joas Schilling <[email protected]>
4
 *
5
 * @author Joas Schilling <[email protected]>
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
24
namespace OC\Repair\Owncloud;
25
26
use Doctrine\DBAL\Exception\InvalidFieldNameException;
27
use OCP\DB\QueryBuilder\IQueryBuilder;
28
use OCP\IConfig;
29
use OCP\IDBConnection;
30
use OCP\Migration\IOutput;
31
use OCP\Migration\IRepairStep;
32
use OCP\PreConditionNotMetException;
33
34
/**
35
 * Copies the email address from the accounts table to the preference table,
36
 * before the data structure is changed and the information is gone
37
 */
38
class SaveAccountsTableData implements IRepairStep {
39
40
	const BATCH_SIZE = 75;
41
42
	/** @var IDBConnection */
43
	protected $db;
44
45
	/** @var IConfig */
46
	protected $config;
47
48
	/**
49
	 * @param IDBConnection $db
50
	 * @param IConfig $config
51
	 */
52
	public function __construct(IDBConnection $db, IConfig $config) {
53
		$this->db = $db;
54
		$this->config = $config;
55
	}
56
57
	/**
58
	 * @return string
59
	 */
60
	public function getName() {
61
		return 'Copy data from accounts table when migrating from ownCloud';
62
	}
63
64
	/**
65
	 * @param IOutput $output
66
	 */
67
	public function run(IOutput $output) {
68
		if (!$this->shouldRun()) {
69
			return;
70
		}
71
72
		$offset = 0;
73
		$numUsers = $this->runStep($offset);
74
75
		while ($numUsers === self::BATCH_SIZE) {
76
			$offset += $numUsers;
77
			$numUsers = $this->runStep($offset);
78
		}
79
80
		// Remove the table
81
		$this->db->dropTable('accounts');
82
	}
83
84
	/**
85
	 * @return bool
86
	 */
87
	protected function shouldRun() {
88
		$query = $this->db->getQueryBuilder();
89
		$query->select('*')
90
			->from('accounts')
91
			->where($query->expr()->isNotNull('user_id'))
92
			->setMaxResults(1);
93
94
		try {
95
			$query->execute();
96
			return true;
97
		} catch (InvalidFieldNameException $e) {
0 ignored issues
show
Bug introduced by
The class Doctrine\DBAL\Exception\InvalidFieldNameException does not exist. Did you forget a USE statement, or did you not list all dependencies?

Scrutinizer analyzes your composer.json/composer.lock file if available to determine the classes, and functions that are defined by your dependencies.

It seems like the listed class was neither found in your dependencies, nor was it found in the analyzed files in your repository. If you are using some other form of dependency management, you might want to disable this analysis.

Loading history...
98
			return false;
99
		}
100
	}
101
102
	/**
103
	 * @param int $offset
104
	 * @return int Number of copied users
105
	 */
106
	protected function runStep($offset) {
107
		$query = $this->db->getQueryBuilder();
108
		$query->select('*')
109
			->from('accounts')
110
			->orderBy('id')
111
			->setMaxResults(self::BATCH_SIZE);
112
113
		if ($offset > 0) {
114
			$query->setFirstResult($offset);
115
		}
116
117
		$result = $query->execute();
118
119
		$update = $this->db->getQueryBuilder();
120
		$update->update('users')
121
			->set('displayname', $update->createParameter('displayname'))
122
			->where($update->expr()->eq('uid', $update->createParameter('userid')));
123
124
		$updatedUsers = 0;
125
		while ($row = $result->fetch()) {
126
			try {
127
				$this->migrateUserInfo($update, $row);
128
			} catch (PreConditionNotMetException $e) {
129
				// Ignore and continue
130
			} catch (\UnexpectedValueException $e) {
131
				// Ignore and continue
132
			}
133
			$updatedUsers++;
134
		}
135
		$result->closeCursor();
136
137
		return $updatedUsers;
138
	}
139
140
	/**
141
	 * @param IQueryBuilder $update
142
	 * @param array $userdata
143
	 * @throws PreConditionNotMetException
144
	 * @throws \UnexpectedValueException
145
	 */
146
	protected function migrateUserInfo(IQueryBuilder $update, $userdata) {
147
		$state = (int) $userdata['state'];
148
		if ($state === 3) {
149
			// Deleted user, ignore
150
			return;
151
		}
152
153
		if ($userdata['email'] !== null) {
154
			$this->config->setUserValue($userdata['user_id'], 'settings', 'email', $userdata['email']);
155
		}
156
		if ($userdata['quota'] !== null) {
157
			$this->config->setUserValue($userdata['user_id'], 'files', 'quota', $userdata['quota']);
158
		}
159
		if ($userdata['last_login'] !== null) {
160
			$this->config->setUserValue($userdata['user_id'], 'login', 'lastLogin', $userdata['last_login']);
161
		}
162
		if ($state === 1) {
163
			$this->config->setUserValue($userdata['user_id'], 'core', 'enabled', 'true');
164
		} else if ($state === 2) {
165
			$this->config->setUserValue($userdata['user_id'], 'core', 'enabled', 'false');
166
		}
167
168
		if ($userdata['display_name'] !== null) {
169
			$update->setParameter('displayname', $userdata['display_name'])
170
				->setParameter('userid', $userdata['user_id']);
171
			$update->execute();
172
		}
173
174
	}
175
}
176
177