Completed
Push — master ( c57b95...1d3e11 )
by Maxence
30s queued 14s
created

Version0019Date20200603080001::copyTableCircles()   A

Complexity

Conditions 5
Paths 5

Size

Total Lines 24

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 24
rs 9.2248
c 0
b 0
f 0
cc 5
nc 5
nop 2
1
<?php
2
/**
3
 * Circles - Bring cloud-users closer together.
4
 *
5
 * This file is licensed under the Affero General Public License version 3 or
6
 * later. See the COPYING file.
7
 *
8
 * @author Maxence Lange <[email protected]>
9
 * @copyright 2019
10
 * @license GNU AGPL version 3 or any later version
11
 *
12
 * This program is free software: you can redistribute it and/or modify
13
 * it under the terms of the GNU Affero General Public License as
14
 * published by the Free Software Foundation, either version 3 of the
15
 * License, or (at your option) any later version.
16
 *
17
 * This program is distributed in the hope that it will be useful,
18
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20
 * GNU Affero General Public License for more details.
21
 *
22
 * You should have received a copy of the GNU Affero General Public License
23
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
24
 *
25
 */
26
27
declare(strict_types=1);
28
29
namespace OCA\Circles\Migration;
30
31
use Closure;
32
use Doctrine\DBAL\Schema\SchemaException;
33
use Doctrine\DBAL\Types\Types;
34
use OCP\DB\ISchemaWrapper;
35
use OCP\IDBConnection;
36
use OCP\Migration\IOutput;
37
use OCP\Migration\SimpleMigrationStep;
38
39
/**
40
 * Auto-generated migration step: Please modify to your needs!
41
 */
42
class Version0019Date20200603080001 extends SimpleMigrationStep {
43
44
45
	/** @var IDBConnection */
46
	private $connection;
47
48
49
	/**
50
	 * @param IDBConnection $connection
51
	 */
52
	public function __construct(IDBConnection $connection) {
53
		$this->connection = $connection;
54
	}
55
56
57
	/**
58
	 * @param IOutput $output
59
	 * @param Closure $schemaClosure The `\Closure` returns a `ISchemaWrapper`
60
	 * @param array $options
61
	 *
62
	 * @return null|ISchemaWrapper
63
	 * @throws SchemaException
64
	 */
65
	public function changeSchema(IOutput $output, Closure $schemaClosure, array $options) {
66
		/** @var ISchemaWrapper $schema */
67
		$schema = $schemaClosure();
68
69
		if (!$schema->hasTable('circle_circles')) {
70
			$table = $schema->createTable('circle_circles');
71
			$table->addColumn(
72
				'id', 'integer', [
73
						'autoincrement' => true,
74
						'notnull'       => true,
75
						'length'        => 4,
76
						'unsigned'      => true,
77
					]
78
			);
79
			$table->addColumn(
80
				'unique_id', 'string', [
81
							   'notnull' => true,
82
							   'length'  => 15,
83
						   ]
84
			);
85
			$table->addColumn(
86
				'long_id', 'string', [
87
							 'notnull' => true,
88
							 'length'  => 64,
89
						 ]
90
			);
91
			$table->addColumn(
92
				'name', 'string', [
93
						  'notnull' => true,
94
						  'length'  => 127,
95
					  ]
96
			);
97
			$table->addColumn(
98
				'alt_name', 'string', [
99
							  'notnull' => false,
100
							  'length'  => 127,
101
							  'default' => ''
102
						  ]
103
			);
104
			$table->addColumn(
105
				'description', 'text', [
106
								 'notnull' => false
107
							 ]
108
			);
109
			$table->addColumn(
110
				'settings', 'text', [
111
							  'notnull' => false
112
						  ]
113
			);
114
			$table->addColumn(
115
				'type', 'smallint', [
116
						  'notnull' => true,
117
						  'length'  => 2,
118
					  ]
119
			);
120
			$table->addColumn(
121
				'creation', 'datetime', [
122
							  'notnull' => false,
123
						  ]
124
			);
125
			$table->addColumn(
126
				'contact_addressbook', 'integer', [
127
										 'notnull'  => false,
128
										 'unsigned' => true,
129
										 'length'   => 7,
130
									 ]
131
			);
132
			$table->addColumn(
133
				'contact_groupname', 'string', [
134
									   'notnull' => false,
135
									   'length'  => 127,
136
								   ]
137
			);
138
			$table->setPrimaryKey(['id']);
139
			$table->addUniqueIndex(['unique_id']);
140
			$table->addUniqueIndex(['long_id']);
141
			$table->addIndex(['type']);
142
		}
143
144
//
145
//		if (!$schema->hasTable('circle_clouds')) {
146
//			$table = $schema->createTable('circle_clouds');
147
//			$table->addColumn(
148
//				'cloud_id', 'string', [
149
//							  'notnull' => true,
150
//							  'length'  => 64,
151
//						  ]
152
//			);
153
//			$table->addColumn(
154
//				'address', 'string', [
155
//							 'notnull' => true,
156
//							 'length'  => 255,
157
//						 ]
158
//			);
159
//			$table->addColumn(
160
//				'status', 'smallint', [
161
//							'notnull' => true,
162
//							'length'  => 1,
163
//						]
164
//			);
165
//			$table->addColumn(
166
//				'note', 'text', [
167
//						  'notnull' => false
168
//					  ]
169
//			);
170
//			$table->addColumn(
171
//				'created', 'datetime', [
172
//							 'notnull' => false,
173
//						 ]
174
//			);
175
//			$table->setPrimaryKey(['cloud_id']);
176
//		}
177
178
179 View Code Duplication
		if (!$schema->hasTable('circle_groups')) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
180
			$table = $schema->createTable('circle_groups');
181
			$table->addColumn(
182
				'circle_id', 'string', [
183
							   'notnull' => true,
184
							   'length'  => 15,
185
						   ]
186
			);
187
			$table->addColumn(
188
				'group_id', 'string', [
189
							  'notnull' => true,
190
							  'length'  => 64,
191
						  ]
192
			);
193
			$table->addColumn(
194
				'level', 'smallint', [
195
						   'notnull' => true,
196
						   'length'  => 1,
197
					   ]
198
			);
199
			$table->addColumn(
200
				'note', 'text', [
201
						  'notnull' => false
202
					  ]
203
			);
204
			$table->addColumn(
205
				'joined', 'datetime', [
206
							'notnull' => false,
207
						]
208
			);
209
			$table->setPrimaryKey(['circle_id', 'group_id']);
210
		}
211
212
213
		if (!$schema->hasTable('circle_gsevents')) {
214
			$table = $schema->createTable('circle_gsevents');
215
			$table->addColumn(
216
				'token', 'string', [
217
						   'notnull' => false,
218
						   'length'  => 63,
219
					   ]
220
			);
221
			$table->addColumn(
222
				'event', 'text', [
223
						   'notnull' => false
224
					   ]
225
			);
226
			$table->addColumn(
227
				'instance', 'string', [
228
							  'length'  => 255,
229
							  'notnull' => false
230
						  ]
231
			);
232
			$table->addColumn(
233
				'severity', 'integer', [
234
							  'length'  => 3,
235
							  'notnull' => false
236
						  ]
237
			);
238
			$table->addColumn(
239
				'status', 'integer', [
240
							'length'  => 3,
241
							'notnull' => false
242
						]
243
			);
244
			$table->addColumn(
245
				'creation', 'bigint', [
246
							  'length'  => 14,
247
							  'notnull' => false
248
						  ]
249
			);
250
			$table->addUniqueIndex(['token', 'instance']);
251
		}
252
253
254 View Code Duplication
		if (!$schema->hasTable('circle_gsshares')) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
255
			$table = $schema->createTable('circle_gsshares');
256
			$table->addColumn(
257
				'id', 'integer', [
258
						'notnull'       => false,
259
						'length'        => 11,
260
						'autoincrement' => true,
261
						'unsigned'      => true
262
					]
263
			);
264
			$table->addColumn(
265
				'circle_id', 'string', [
266
							   'length'  => 15,
267
							   'notnull' => false
268
						   ]
269
			);
270
			$table->addColumn(
271
				'owner', 'string', [
272
						   'length'  => 15,
273
						   'notnull' => false
274
					   ]
275
			);
276
			$table->addColumn(
277
				'instance', 'string', [
278
							  'length'  => 255,
279
							  'notnull' => false
280
						  ]
281
			);
282
			$table->addColumn(
283
				'token', 'string', [
284
						   'notnull' => false,
285
						   'length'  => 63
286
					   ]
287
			);
288
			$table->addColumn(
289
				'parent', 'integer', [
290
							'notnull' => false,
291
							'length'  => 11,
292
						]
293
			);
294
			$table->addColumn(
295
				'mountpoint', 'text', [
296
								'notnull' => false
297
							]
298
			);
299
			$table->addColumn(
300
				'mountpoint_hash', 'string', [
301
									 'length'  => 64,
302
									 'notnull' => false
303
								 ]
304
			);
305
			$table->setPrimaryKey(['id']);
306
			$table->addUniqueIndex(['circle_id', 'mountpoint_hash']);
307
		}
308
309
310 View Code Duplication
		if (!$schema->hasTable('circle_gsshares_mp')) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
311
			$table = $schema->createTable('circle_gsshares_mp');
312
			$table->addColumn(
313
				'share_id', 'integer', [
314
							  'length'  => 11,
315
							  'notnull' => false
316
						  ]
317
			);
318
			$table->addColumn(
319
				'user_id', 'string', [
320
							 'length'  => 127,
321
							 'notnull' => false
322
						 ]
323
			);
324
			$table->addColumn(
325
				'mountpoint', 'text', [
326
								'notnull' => false
327
							]
328
			);
329
			$table->addColumn(
330
				'mountpoint_hash', 'string', [
331
									 'length'  => 64,
332
									 'notnull' => false
333
								 ]
334
			);
335
			$table->setPrimaryKey(['share_id', 'user_id']);
336
			$table->addUniqueIndex(['share_id', 'mountpoint_hash']);
337
		}
338
339
340
341
342
		if (!$schema->hasTable('circle_members')) {
343
			$table = $schema->createTable('circle_members');
344
			$table->addColumn(
345
				'circle_id', 'string', [
346
							   'notnull' => true,
347
							   'length'  => 15,
348
						   ]
349
			);
350
			$table->addColumn(
351
				'member_id', Types::STRING, [
352
							   'notnull' => false,
353
							   'length'  => 15,
354
						   ]
355
			);
356
			$table->addColumn(
357
				'contact_id', 'string', [
358
								'notnull' => false,
359
								'length'  => 127,
360
							]
361
			);
362
			$table->addColumn(
363
				'user_type', 'smallint', [
364
							   'notnull' => true,
365
							   'length'  => 1,
366
							   'default' => 1,
367
						   ]
368
			);
369
			$table->addColumn(
370
				'user_id', 'string', [
371
							 'notnull' => true,
372
							 'length'  => 127,
373
						 ]
374
			);
375
			$table->addColumn(
376
				'cached_name', 'string', [
377
								 'notnull' => false,
378
								 'length'  => 255,
379
								 'default' => ''
380
							 ]
381
			);
382
			$table->addColumn(
383
				'cached_update', 'datetime', [
384
								   'notnull' => false,
385
							   ]
386
			);
387
			$table->addColumn(
388
				'instance', 'string', [
389
							  'default' => '',
390
							  'length'  => 255
391
						  ]
392
			);
393
			$table->addColumn(
394
				'level', 'smallint', [
395
						   'notnull' => true,
396
						   'length'  => 1,
397
					   ]
398
			);
399
			$table->addColumn(
400
				'status', 'string', [
401
							'notnull' => false,
402
							'length'  => 15,
403
						]
404
			);
405
			$table->addColumn(
406
				'note', 'text', [
407
						  'notnull' => false
408
					  ]
409
			);
410
			$table->addColumn(
411
				'joined', 'datetime', [
412
							'notnull' => false,
413
						]
414
			);
415
			$table->addColumn(
416
				'contact_meta', 'text', [
417
								  'notnull' => false
418
							  ]
419
			);
420
			$table->addColumn(
421
				'contact_checked', Types::SMALLINT, [
422
									 'notnull' => false,
423
									 'length'  => 1,
424
								 ]
425
			);
426
427
			$table->setPrimaryKey(['circle_id', 'user_id', 'user_type', 'contact_id', 'instance']);
428
		}
429
430
431
		if (!$schema->hasTable('circle_tokens')) {
432
			$table = $schema->createTable('circle_tokens');
433
			$table->addColumn(
434
				'circle_id', 'string', [
435
							   'notnull' => true,
436
							   'length'  => 15,
437
						   ]
438
			);
439
			$table->addColumn(
440
				'member_id', Types::STRING, [
441
							   'notnull' => false,
442
							   'length'  => 15,
443
						   ]
444
			);
445
			$table->addColumn(
446
				'user_id', 'string', [
447
							 'notnull' => true,
448
							 'length'  => 255,
449
						 ]
450
			);
451
			$table->addColumn(
452
				'share_id', 'bigint', [
453
							  'notnull' => true,
454
							  'length'  => 14,
455
						  ]
456
			);
457
			$table->addColumn(
458
				'token', 'string', [
459
						   'notnull' => true,
460
						   'length'  => 31,
461
					   ]
462
			);
463
			$table->addColumn(
464
				'password', 'string', [
465
							  'notnull' => true,
466
							  'length'  => 127,
467
						  ]
468
			);
469
			$table->addColumn(
470
				'accepted', Types::SMALLINT, [
471
							  'notnull' => false,
472
							  'length'  => 1,
473
						  ]
474
			);
475
			$table->setPrimaryKey(['circle_id', 'user_id', 'share_id']);
476
		}
477
478
479
		return $schema;
480
	}
481
482
483
	/**
484
	 * @param IOutput $output
485
	 * @param Closure $schemaClosure The `\Closure` returns a `ISchemaWrapper`
486
	 * @param array $options
487
	 */
488
	public function postSchemaChange(IOutput $output, Closure $schemaClosure, array $options) {
489
490
		/** @var ISchemaWrapper $schema */
491
		$schema = $schemaClosure();
492
493
		if ($schema->hasTable('circles_tokens')) {
494
			$this->copyTable('circles_tokens', 'circle_tokens');
495
		}
496
		if ($schema->hasTable('circles_circles')) {
497
			$this->copyTableCircles('circles_circles', 'circle_circles');
498
		}
499
//		if ($schema->hasTable('circles_clouds')) {
500
//			$this->copyTable('circles_clouds', 'circle_clouds');
501
//		}
502
		if ($schema->hasTable('circles_groups')) {
503
			$this->copyTable('circles_groups', 'circle_groups');
504
		}
505
		if ($schema->hasTable('circles_gsevents')) {
506
			$this->copyTable('circles_gsevents', 'circle_gsevents');
507
		}
508
		if ($schema->hasTable('circles_gsshares')) {
509
			$this->copyTable('circles_gsshares', 'circle_gsshares');
510
		}
511
		if ($schema->hasTable('circles_gsshares_mp')) {
512
			$this->copyTable('circles_gsshares_mp', 'circle_gsshares_mp');
513
		}
514
		if ($schema->hasTable('circles_links')) {
515
			$this->copyTable('circles_links', 'circle_links');
516
		}
517
		if ($schema->hasTable('circles_members')) {
518
			$this->copyTable('circles_members', 'circle_members', ['instance' => '', 'contact_id' => '']);
519
		}
520
		if ($schema->hasTable('circles_shares')) {
521
			$this->copyTable('circles_shares', 'circle_shares');
522
		}
523
524
		$this->updateMemberId();
525
		$this->updateTokens();
526
	}
527
528
529
	/**
530
	 * @param $orig
531
	 * @param $dest
532
	 * @param array $default
533
	 */
534
	protected function copyTable($orig, $dest, array $default = []) {
535
		$qb = $this->connection->getQueryBuilder();
536
537
		$qb->select('*')
538
		   ->from($orig);
539
540
		$result = $qb->execute();
541
		while ($row = $result->fetch()) {
542
			$copy = $this->connection->getQueryBuilder();
543
			$copy->insert($dest);
544
			$ak = array_keys($row);
545
			foreach ($ak as $k) {
546
				if ($row[$k] !== null) {
547
					$copy->setValue($k, $copy->createNamedParameter($row[$k]));
548
				} elseif (array_key_exists($k, $default)) {
549
					$copy->setValue($k, $copy->createNamedParameter($default[$k]));
550
				}
551
			}
552
553
			$ak = array_keys($default);
554
			foreach ($ak as $k) {
555
				if (!array_key_exists($k, $row)) {
556
					$copy->setValue($k, $copy->createNamedParameter($default[$k]));
557
				}
558
			}
559
560
			$copy->execute();
561
		}
562
	}
563
564
565
	/**
566
	 * @param $orig
567
	 * @param $dest
568
	 */
569
	protected function copyTableCircles($orig, $dest) {
570
		$qb = $this->connection->getQueryBuilder();
571
572
		$qb->select('*')
573
		   ->from($orig);
574
575
		$result = $qb->execute();
576
		while ($row = $result->fetch()) {
577
			$copy = $this->connection->getQueryBuilder();
578
			$copy->insert($dest);
579
			$ak = array_keys($row);
580
			foreach ($ak as $k) {
581
				$v = $row[$k];
582
				if ($k === 'unique_id') {
583
					$copy->setValue('unique_id', $copy->createNamedParameter(substr($v, 0, 14)));
584
					$copy->setValue('long_id', $copy->createNamedParameter($v));
585
				} else if ($v !== null) {
586
					$copy->setValue($k, $copy->createNamedParameter($v));
587
				}
588
			}
589
590
			$copy->execute();
591
		}
592
	}
593
594
595
	/**
596
	 *
597
	 */
598
	private function updateMemberId() {
599
		$qb = $this->connection->getQueryBuilder();
600
		$expr = $qb->expr();
601
602
		$orX = $expr->orX();
603
		$orX->add($expr->eq('member_id', $qb->createNamedParameter('')));
604
		$orX->add($expr->isNull('member_id'));
605
606
		$qb->select('circle_id', 'user_id', 'user_type', 'instance')
607
		   ->from('circle_members')
608
		   ->where($orX);
609
610
		$result = $qb->execute();
611
		while ($row = $result->fetch()) {
612
			$uniqueId = substr(bin2hex(openssl_random_pseudo_bytes(24)), 0, 15);
613
614
			$update = $this->connection->getQueryBuilder();
615
			$expru = $update->expr();
616
			$update->update('circle_members')
617
				   ->set('member_id', $update->createNamedParameter($uniqueId))
618
				   ->where($expru->eq('circle_id', $update->createNamedParameter($row['circle_id'])))
619
				   ->andWhere($expru->eq('user_id', $update->createNamedParameter($row['user_id'])))
620
				   ->andWhere($expru->eq('user_type', $update->createNamedParameter($row['user_type'])))
621
				   ->andWhere($expru->eq('instance', $update->createNamedParameter($row['instance'])));
622
623
			$update->execute();
624
		}
625
	}
626
627
628
	/**
629
	 *
630
	 */
631
	private function updateTokens() {
632
		$qb = $this->connection->getQueryBuilder();
633
		$expr = $qb->expr();
634
		$orX = $expr->orX();
635
		$orX->add($expr->eq('member_id', $qb->createNamedParameter('')));
636
		$orX->add($expr->isNull('member_id'));
637
		$qb->select('user_id', 'circle_id')
638
		   ->from('circle_tokens')
639
		   ->where($orX);
640
641
		$result = $qb->execute();
642
		while ($row = $result->fetch()) {
643
			$qbm = $this->connection->getQueryBuilder();
644
			$exprm = $qbm->expr();
645
646
			$qbm->select('member_id')
647
				->from('circle_members')
648
				->where($exprm->eq('circle_id', $qbm->createNamedParameter($row['circle_id'])))
649
				->andWhere($exprm->eq('user_id', $qbm->createNamedParameter($row['user_id'])))
650
				->andWhere($exprm->neq('user_type', $qbm->createNamedParameter('1')));
651
652
			$resultm = $qbm->execute();
653
			$member = $resultm->fetch();
654
655
			$update = $this->connection->getQueryBuilder();
656
			$expru = $update->expr();
657
			$update->update('circle_tokens')
658
				   ->set('member_id', $update->createNamedParameter($member['member_id']))
659
				   ->where($expru->eq('circle_id', $update->createNamedParameter($row['circle_id'])))
660
				   ->andWhere($expru->eq('user_id', $update->createNamedParameter($row['user_id'])));
661
662
			$update->execute();
663
		}
664
	}
665
666
667
}
668