Version0010Date20191227063812::resolveOptions()   A
last analyzed

Complexity

Conditions 2
Paths 2

Size

Total Lines 5
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 6

Importance

Changes 0
Metric Value
eloc 3
c 0
b 0
f 0
dl 0
loc 5
rs 10
ccs 0
cts 4
cp 0
cc 2
nc 2
nop 1
crap 6
1
<?php
2
/**
3
 * @copyright Copyright (c) 2017 René Gieling <[email protected]>
4
 *
5
 * @author René Gieling <[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 OCA\Polls\Migration;
25
26
use OCP\DB\ISchemaWrapper;
27
use OCP\IConfig;
28
use OCP\IDBConnection;
29
use OCP\Migration\SimpleMigrationStep;
30
use OCP\Migration\IOutput;
31
use OCP\Security\ISecureRandom;
32
33
class Version0010Date20191227063812 extends SimpleMigrationStep {
34
35
	/** @var IDBConnection */
36
	protected $connection;
37
38
	/** @var IConfig */
39
	protected $config;
40
41
	public function __construct(IDBConnection $connection, IConfig $config) {
42
		$this->connection = $connection;
43
		$this->config = $config;
44
	}
45
46
	/**
47
	 * $schemaClosure The `\Closure` returns a `ISchemaWrapper`
48
	 */
49
	public function changeSchema(IOutput $output, \Closure $schemaClosure, array $options) {
50
		/** @var ISchemaWrapper $schema */
51
		$schema = $schemaClosure();
52
53
		if ($schema->hasTable('polls_comments')) {
54
			$table = $schema->getTable('polls_comments');
55
			if (!$table->hasColumn('timestamp')) {
56
				$table->addColumn('timestamp', 'integer', [
57
					'length' => 11,
58
					'notnull' => true,
59
					'default' => 0
60
				]);
61
			}
62
		}
63
64
		if (!$schema->hasTable('polls_polls')) {
65
			$table = $schema->createTable('polls_polls');
66
			$table->addColumn('id', 'integer', [
67
				'autoincrement' => true,
68
				'length' => 11,
69
				'notnull' => true
70
			]);
71
			$table->addColumn('type', 'string', [
72
				'length' => 64,
73
				'notnull' => true,
74
				'default' => 'datePoll'
75
			]);
76
			$table->addColumn('title', 'string', [
77
				'length' => 128,
78
				'notnull' => true
79
			]);
80
			$table->addColumn('description', 'string', [
81
				'length' => 1024,
82
				'notnull' => true
83
			]);
84
			$table->addColumn('owner', 'string', [
85
				'length' => 64,
86
				'notnull' => true
87
			]);
88
			$table->addColumn('created', 'integer', [
89
				'length' => 11,
90
				'notnull' => true,
91
				'default' => 0
92
			]);
93
			$table->addColumn('expire', 'integer', [
94
				'length' => 11,
95
				'notnull' => true,
96
				'default' => 0
97
			]);
98
			$table->addColumn('deleted', 'integer', [
99
				'length' => 11,
100
				'notnull' => true,
101
				'default' => 0
102
			]);
103
			$table->addColumn('access', 'string', [
104
				'notnull' => true,
105
				'length' => 1024,
106
				'default' => 'hidden'
107
			]);
108
			$table->addColumn('anonymous', 'integer', [
109
				'length' => 8,
110
				'notnull' => true,
111
				'default' => 0
112
			]);
113
			$table->addColumn('full_anonymous', 'integer', [
114
				'notnull' => true,
115
				'default' => 0,
116
			]);
117
			$table->addColumn('allow_maybe', 'integer', [
118
				'notnull' => true,
119
				'default' => 1
120
			]);
121
			$table->addColumn('options', 'text', [
122
				'notnull' => true,
123
				'default' => ''
124
			]);
125
			$table->addColumn('settings', 'text', [
126
				'notnull' => true,
127
				'default' => ''
128
			]);
129
			$table->addColumn('vote_limit', 'integer', [
130
				'length' => 11,
131
				'notnull' => true,
132
				'default' => 0
133
			]);
134
			$table->addColumn('show_results', 'string', [
135
				'length' => 64,
136
				'notnull' => true,
137
				'default' => 'always'
138
			]);
139
			$table->addColumn('admin_access', 'integer', [
140
				'length' => 8,
141
				'notnull' => true,
142
				'default' => 0
143
			]);
144
145
			$table->setPrimaryKey(['id']);
146
		}
147
148
		if (!$schema->hasTable('polls_share')) {
149
			$table = $schema->createTable('polls_share');
150
			$table->addColumn('id', 'integer', [
151
				'autoincrement' => true,
152
				'notnull' => true,
153
			]);
154
			$table->addColumn('token', 'string', [
155
				'notnull' => true,
156
				'length' => 64,
157
			]);
158
			$table->addColumn('type', 'string', [
159
				'notnull' => true,
160
				'length' => 64
161
			]);
162
			$table->addColumn('poll_id', 'integer', [
163
				'notnull' => true
164
			]);
165
			$table->addColumn('user_id', 'string', [
166
				'notnull' => false,
167
				'length' => 64
168
			]);
169
			$table->addColumn('user_email', 'string', [
170
				'notnull' => false,
171
				'length' => 254
172
			]);
173
			$table->addColumn('user', 'text', [
174
				'notnull' => true,
175
				'default' => ''
176
			]);
177
			$table->setPrimaryKey(['id']);
178
		}
179
180
		if (!$schema->hasTable('polls_log')) {
181
			$table = $schema->createTable('polls_log');
182
			$table->addColumn('id', 'integer', [
183
				'autoincrement' => true,
184
				'notnull' => true
185
			]);
186
			$table->addColumn('created', 'integer', [
187
				'notnull' => true,
188
				'length' => 11,
189
				'default' => 0
190
			]);
191
			$table->addColumn('processed', 'integer', [
192
				'notnull' => true,
193
				'length' => 11,
194
				'default' => 0
195
			]);
196
			$table->addColumn('poll_id', 'integer', [
197
				'notnull' => true
198
			]);
199
			$table->addColumn('user_id', 'string', [
200
				'notnull' => false,
201
				'length' => 1024
202
			]);
203
			$table->addColumn('display_name', 'string', [
204
				'notnull' => false,
205
				'length' => 64
206
			]);
207
			$table->addColumn('message_id', 'string', [
208
				'notnull' => false,
209
				'length' => 64
210
			]);
211
			$table->addColumn('message', 'string', [
212
				'notnull' => false,
213
				'length' => 1024
214
			]);
215
			$table->setPrimaryKey(['id']);
216
		}
217
218
		return $schema;
219
	}
220
221
	/**
222
	 * @return void
223
	 */
224
	public function postSchemaChange(IOutput $output, \Closure $schemaClosure, array $options) {
225
		/** @var ISchemaWrapper $schema */
226
		$schema = $schemaClosure();
227
228
		if ($schema->hasTable('polls_polls') &&
229
			$schema->hasTable('polls_events')) {
230
			$this->migrateEvents();
231
		}
232
233
		if ($schema->hasTable('polls_share') &&
234
			$schema->hasTable('polls_events')) {
235
			$this->copyTokens();
236
		}
237
	}
238
239
240
	private function resolveAccess(string $access): string {
241
		if ($access === 'public') {
242
			return 'public';
243
		}
244
		return 'hidden';
245
	}
246
247
	/**
248
	 * @return string
249
	 */
250
	private function resolveOptions(bool $maybe) {
251
		if ($maybe) {
252
			return json_encode(['yes', 'no', 'maybe']);
253
		}
254
		return json_encode(['yes', 'no']);
255
	}
256
257
	private function resolveType($type): string {
258
		if ($type) {
259
			return 'textPoll';
260
		}
261
		return 'datePoll';
262
	}
263
264
	protected function migrateEvents(): void {
265
		$insert = $this->connection->getQueryBuilder();
266
		$insert
267
			->insert('polls_polls')
268
			->values([
269
				'id' => $insert->createParameter('id'),
270
				'type' => $insert->createParameter('type'),
271
				'title' => $insert->createParameter('title'),
272
				'description' => $insert->createParameter('description'),
273
				'owner' => $insert->createParameter('owner'),
274
				'created' => $insert->createParameter('created'),
275
				'expire' => $insert->createParameter('expire'),
276
				'deleted' => $insert->createParameter('deleted'),
277
				'access' => $insert->createParameter('access'),
278
				'anonymous' => $insert->createParameter('anonymous'),
279
				'full_anonymous' => $insert->createParameter('full_anonymous'),
280
				'allow_maybe' => $insert->createParameter('allow_maybe'),
281
				'options' => $insert->createParameter('options'),
282
				'settings' => $insert->createParameter('settings'),
283
				'vote_limit' => $insert->createParameter('vote_limit'),
284
				'show_results' => $insert->createParameter('show_results'),
285
				'admin_access' => $insert->createParameter('admin_access')
286
			]);
287
		$query = $this->connection->getQueryBuilder();
288
		$query->select('*')->from('polls_events');
289
		$result = $query->execute();
290
291
		while ($row = $result->fetch()) {
292
			$insert
293
			->setParameter('id', $row['id'])
294
			->setParameter('type', $this->resolveType($row['type']))
295
			->setParameter('title', $row['title'])
296
			->setParameter('description', $row['description'])
297
			->setParameter('owner', $row['owner'])
298
			->setParameter('created', intval(strtotime($row['created'])))
299
			->setParameter('expire', intval(strtotime($row['expire'])))
300
			->setParameter('deleted', 0)
301
			->setParameter('access', $this->resolveAccess($row['access']))
302
			->setParameter('anonymous', intval($row['full_anonymous']) * 2 + intval($row['is_anonymous']))
303
			->setParameter('full_anonymous', $row['full_anonymous'])
304
			->setParameter('allow_maybe', $row['allow_maybe'])
305
			->setParameter('options', $this->resolveOptions($row['allow_maybe']))
306
			->setParameter('settings', '')
307
			->setParameter('vote_limit', 0)
308
			->setParameter('show_results', 'always')
309
			->setParameter('admin_access', 0);
310
			$insert->execute();
311
		}
312
313
		$result->closeCursor();
314
	}
315
316
	/**
317
	 * Copy public tokens
318
	 */
319
	protected function copyTokens(): void {
320
		$insert = $this->connection->getQueryBuilder();
321
		$insert->insert('polls_share')
322
			->values([
323
				'token' => $insert->createParameter('token'),
324
				'type' => $insert->createParameter('type'),
325
				'poll_id' => $insert->createParameter('poll_id'),
326
				'user_id' => $insert->createParameter('user_id'),
327
				'user_email' => $insert->createParameter('user_email'),
328
				'user' => $insert->createParameter('user')
329
			]);
330
		$query = $this->connection->getQueryBuilder();
331
		$query->select('*')
332
			->from('polls_events');
333
		$result = $query->execute();
334
335
		while ($row = $result->fetch()) {
336
			if ($row['access'] === 'public') {
337
				// copy the hash to a public share
338
				$insert
339
				->setParameter('token', $row['hash'])
340
				->setParameter('type', 'public')
341
				->setParameter('poll_id', $row['id'])
342
				->setParameter('user_id', null)
343
				->setParameter('user_email', null)
344
				->setParameter('user', '');
345
				$insert->execute();
346
			} elseif ($row['access'] === 'hidden') {
347
				// copy the hash to a public share
348
				// poll stays hidden for registered users
349
				$insert
350
				->setParameter('token', $row['hash'])
351
				->setParameter('type', 'public')
352
				->setParameter('poll_id', $row['id'])
353
				->setParameter('user_id', null)
354
				->setParameter('user_email', null)
355
				->setParameter('user', '');
356
				$insert->execute();
357
			} elseif ($row['access'] === 'registered') {
358
				// copy the hash to a public share
359
				// to keep the hash
360
				$insert
361
				->setParameter('token', $row['hash'])
362
				->setParameter('type', 'public')
363
				->setParameter('poll_id', $row['id'])
364
				->setParameter('user_id', null)
365
				->setParameter('user_email', null)
366
				->setParameter('user', '');
367
			} else {
368
				// create a personal share for invitated users
369
370
				// explode the access entry to single access strings
371
				$users = explode(';', $row['access']);
372
				foreach ($users as $value) {
373
					// separate 'user' and 'group' from user names and create
374
					// a share for every entry
375
					$parts = explode('_', $value);
376
					$insert
377
					->setParameter('token', \OC::$server->getSecureRandom()->generate(
378
						16,
379
						ISecureRandom::CHAR_DIGITS .
380
						ISecureRandom::CHAR_LOWER .
381
						ISecureRandom::CHAR_UPPER
382
					))
383
					->setParameter('type', $parts[0])
384
					->setParameter('poll_id', $row['id'])
385
					->setParameter('user_id', $parts[1])
386
					->setParameter('user_email', null)
387
					->setParameter('user', '');
388
					$insert->execute();
389
				}
390
			}
391
		}
392
		$result->closeCursor();
393
	}
394
}
395