Completed
Pull Request — master (#431)
by Maxence
01:53
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\Type;
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'  => 64,
95
					  ]
96
			);
97
			$table->addColumn(
98
				'description', 'text', [
99
								 'notnull' => false
100
							 ]
101
			);
102
			$table->addColumn(
103
				'settings', 'text', [
104
							  'notnull' => false
105
						  ]
106
			);
107
			$table->addColumn(
108
				'type', 'smallint', [
109
						  'notnull' => true,
110
						  'length'  => 2,
111
					  ]
112
			);
113
			$table->addColumn(
114
				'creation', 'datetime', [
115
							  'notnull' => false,
116
						  ]
117
			);
118
			$table->addColumn(
119
				'contact_addressbook', 'integer', [
120
										 'notnull'  => false,
121
										 'unsigned' => true,
122
										 'length'   => 7,
123
									 ]
124
			);
125
			$table->addColumn(
126
				'contact_groupname', 'string', [
127
									   'notnull' => false,
128
									   'length'  => 127,
129
								   ]
130
			);
131
			$table->setPrimaryKey(['id']);
132
			$table->addUniqueIndex(['unique_id']);
133
			$table->addUniqueIndex(['long_id']);
134
			$table->addIndex(['type']);
135
		}
136
137
138 View Code Duplication
		if (!$schema->hasTable('circle_clouds')) {
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...
139
			$table = $schema->createTable('circle_clouds');
140
			$table->addColumn(
141
				'cloud_id', 'string', [
142
							  'notnull' => true,
143
							  'length'  => 64,
144
						  ]
145
			);
146
			$table->addColumn(
147
				'address', 'string', [
148
							 'notnull' => true,
149
							 'length'  => 255,
150
						 ]
151
			);
152
			$table->addColumn(
153
				'status', 'smallint', [
154
							'notnull' => true,
155
							'length'  => 1,
156
						]
157
			);
158
			$table->addColumn(
159
				'note', 'text', [
160
						  'notnull' => false
161
					  ]
162
			);
163
			$table->addColumn(
164
				'created', 'datetime', [
165
							 'notnull' => false,
166
						 ]
167
			);
168
			$table->setPrimaryKey(['cloud_id']);
169
		}
170
171
172 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...
173
			$table = $schema->createTable('circle_groups');
174
			$table->addColumn(
175
				'circle_id', 'string', [
176
							   'notnull' => true,
177
							   'length'  => 15,
178
						   ]
179
			);
180
			$table->addColumn(
181
				'group_id', 'string', [
182
							  'notnull' => true,
183
							  'length'  => 64,
184
						  ]
185
			);
186
			$table->addColumn(
187
				'level', 'smallint', [
188
						   'notnull' => true,
189
						   'length'  => 1,
190
					   ]
191
			);
192
			$table->addColumn(
193
				'note', 'text', [
194
						  'notnull' => false
195
					  ]
196
			);
197
			$table->addColumn(
198
				'joined', 'datetime', [
199
							'notnull' => false,
200
						]
201
			);
202
			$table->setPrimaryKey(['circle_id', 'group_id']);
203
		}
204
205
206
		if (!$schema->hasTable('circle_gsevents')) {
207
			$table = $schema->createTable('circle_gsevents');
208
			$table->addColumn(
209
				'token', 'string', [
210
						   'notnull' => false,
211
						   'length'  => 63,
212
					   ]
213
			);
214
			$table->addColumn(
215
				'event', 'text', [
216
						   'notnull' => false
217
					   ]
218
			);
219
			$table->addColumn(
220
				'instance', 'string', [
221
							  'length'  => 255,
222
							  'notnull' => false
223
						  ]
224
			);
225
			$table->addColumn(
226
				'severity', 'integer', [
227
							  'length'  => 3,
228
							  'notnull' => false
229
						  ]
230
			);
231
			$table->addColumn(
232
				'status', 'integer', [
233
							'length'  => 3,
234
							'notnull' => false
235
						]
236
			);
237
			$table->addColumn(
238
				'creation', 'bigint', [
239
							  'length'  => 14,
240
							  'notnull' => false
241
						  ]
242
			);
243
			$table->addUniqueIndex(['token', 'instance']);
244
		}
245
246
247
		if (!$schema->hasTable('circle_gsshares')) {
248
			$table = $schema->createTable('circle_gsshares');
249
			$table->addColumn(
250
				'id', 'integer', [
251
						'notnull'       => false,
252
						'length'        => 11,
253
						'autoincrement' => true,
254
						'unsigned'      => true
255
					]
256
			);
257
			$table->addColumn(
258
				'circle_id', 'string', [
259
							   'length'  => 15,
260
							   'notnull' => false
261
						   ]
262
			);
263
			$table->addColumn(
264
				'owner', 'string', [
265
						   'length'  => 15,
266
						   'notnull' => false
267
					   ]
268
			);
269
			$table->addColumn(
270
				'instance', 'string', [
271
							  'length'  => 255,
272
							  'notnull' => false
273
						  ]
274
			);
275
			$table->addColumn(
276
				'token', 'string', [
277
						   'notnull' => false,
278
						   'length'  => 63
279
					   ]
280
			);
281
			$table->addColumn(
282
				'parent', 'integer', [
283
							'notnull' => false,
284
							'length'  => 11,
285
						]
286
			);
287
			$table->addColumn(
288
				'mountpoint', 'text', [
289
								'notnull' => false
290
							]
291
			);
292
			$table->addColumn(
293
				'mountpoint_hash', 'string', [
294
									 'length'  => 64,
295
									 'notnull' => false
296
								 ]
297
			);
298
			$table->setPrimaryKey(['id']);
299
			$table->addUniqueIndex(['circle_id', 'mountpoint_hash']);
300
		}
301
302
303 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...
304
			$table = $schema->createTable('circle_gsshares_mp');
305
			$table->addColumn(
306
				'share_id', 'integer', [
307
							  'length'  => 11,
308
							  'notnull' => false
309
						  ]
310
			);
311
			$table->addColumn(
312
				'user_id', 'string', [
313
							 'length'  => 127,
314
							 'notnull' => false
315
						 ]
316
			);
317
			$table->addColumn(
318
				'mountpoint', 'text', [
319
								'notnull' => false
320
							]
321
			);
322
			$table->addColumn(
323
				'mountpoint_hash', 'string', [
324
									 'length'  => 64,
325
									 'notnull' => false
326
								 ]
327
			);
328
			$table->setPrimaryKey(['share_id', 'user_id']);
329
			$table->addUniqueIndex(['share_id', 'mountpoint_hash']);
330
		}
331
332
333
		if (!$schema->hasTable('circle_links')) {
334
			$table = $schema->createTable('circle_links');
335
			$table->addColumn(
336
				'id', 'smallint', [
337
						'autoincrement' => true,
338
						'notnull'       => true,
339
						'length'        => 3,
340
						'unsigned'      => true,
341
					]
342
			);
343
			$table->addColumn(
344
				'status', 'smallint', [
345
							'notnull' => true,
346
							'length'  => 1,
347
						]
348
			);
349
			$table->addColumn(
350
				'circle_id', 'string', [
351
							   'notnull' => true,
352
							   'length'  => 64,
353
						   ]
354
			);
355
			$table->addColumn(
356
				'unique_id', 'string', [
357
							   'notnull' => false,
358
							   'length'  => 64,
359
						   ]
360
			);
361
			$table->addColumn(
362
				'address', 'string', [
363
							 'notnull' => true,
364
							 'length'  => 128,
365
						 ]
366
			);
367
			$table->addColumn(
368
				'token', 'string', [
369
						   'notnull' => true,
370
						   'length'  => 64,
371
					   ]
372
			);
373
			$table->addColumn(
374
				'key', 'string', [
375
						 'notnull' => true,
376
						 'length'  => 64,
377
					 ]
378
			);
379
			$table->addColumn(
380
				'creation', 'datetime', [
381
							  'notnull' => false,
382
						  ]
383
			);
384
			$table->setPrimaryKey(['id']);
385
		}
386
387
388
		if (!$schema->hasTable('circle_members')) {
389
			$table = $schema->createTable('circle_members');
390
			$table->addColumn(
391
				'circle_id', 'string', [
392
							   'notnull' => true,
393
							   'length'  => 15,
394
						   ]
395
			);
396
			$table->addColumn(
397
				'member_id', Type::STRING, [
398
							   'notnull' => false,
399
							   'length'  => 15,
400
						   ]
401
			);
402
			$table->addColumn(
403
				'contact_id', 'string', [
404
								'notnull' => false,
405
								'length'  => 127,
406
							]
407
			);
408
			$table->addColumn(
409
				'user_type', 'smallint', [
410
							   'notnull' => true,
411
							   'length'  => 1,
412
							   'default' => 1,
413
						   ]
414
			);
415
			$table->addColumn(
416
				'user_id', 'string', [
417
							 'notnull' => true,
418
							 'length'  => 127,
419
						 ]
420
			);
421
			$table->addColumn(
422
				'instance', 'string', [
423
							  'default' => '',
424
							  'length'  => 255
425
						  ]
426
			);
427
			$table->addColumn(
428
				'level', 'smallint', [
429
						   'notnull' => true,
430
						   'length'  => 1,
431
					   ]
432
			);
433
			$table->addColumn(
434
				'status', 'string', [
435
							'notnull' => false,
436
							'length'  => 15,
437
						]
438
			);
439
			$table->addColumn(
440
				'note', 'text', [
441
						  'notnull' => false
442
					  ]
443
			);
444
			$table->addColumn(
445
				'joined', 'datetime', [
446
							'notnull' => false,
447
						]
448
			);
449
			$table->addColumn(
450
				'contact_meta', 'text', [
451
								  'notnull' => false
452
							  ]
453
			);
454
			$table->addColumn(
455
				'contact_checked', Type::SMALLINT, [
456
									 'notnull' => false,
457
									 'length'  => 1,
458
								 ]
459
			);
460
461
			$table->setPrimaryKey(['circle_id', 'user_id', 'user_type', 'contact_id', 'instance']);
462
		}
463
464
465
		if (!$schema->hasTable('circle_shares')) {
466
			$table = $schema->createTable('circle_shares');
467
			$table->addColumn(
468
				'id', 'integer', [
469
						'autoincrement' => true,
470
						'notnull'       => true,
471
						'length'        => 4,
472
						'unsigned'      => true,
473
					]
474
			);
475
			$table->addColumn(
476
				'unique_id', 'string', [
477
							   'notnull' => false,
478
							   'length'  => 32,
479
						   ]
480
			);
481
			$table->addColumn(
482
				'circle_id', 'string', [
483
							   'notnull' => true,
484
							   'length'  => 15,
485
						   ]
486
			);
487
			$table->addColumn(
488
				'source', 'string', [
489
							'notnull' => true,
490
							'length'  => 15,
491
						]
492
			);
493
			$table->addColumn(
494
				'type', 'string', [
495
						  'notnull' => true,
496
						  'length'  => 15,
497
					  ]
498
			);
499
			$table->addColumn(
500
				'author', 'string', [
501
							'notnull' => true,
502
							'length'  => 127,
503
						]
504
			);
505
			$table->addColumn(
506
				'cloud_id', 'string', [
507
							  'notnull' => false,
508
							  'length'  => 254,
509
							  'default' => 'null',
510
						  ]
511
			);
512
			$table->addColumn(
513
				'headers', 'text', [
514
							 'notnull' => false
515
						 ]
516
			);
517
			$table->addColumn(
518
				'payload', 'text', [
519
							 'notnull' => true
520
						 ]
521
			);
522
			$table->addColumn(
523
				'creation', 'datetime', [
524
							  'notnull' => false,
525
						  ]
526
			);
527
			$table->setPrimaryKey(['id']);
528
		}
529
530
531
		if (!$schema->hasTable('circle_tokens')) {
532
			$table = $schema->createTable('circle_tokens');
533
			$table->addColumn(
534
				'circle_id', 'string', [
535
							   'notnull' => true,
536
							   'length'  => 15,
537
						   ]
538
			);
539
			$table->addColumn(
540
				'member_id', Type::STRING, [
541
							   'notnull' => false,
542
							   'length'  => 15,
543
						   ]
544
			);
545
			$table->addColumn(
546
				'user_id', 'string', [
547
							 'notnull' => true,
548
							 'length'  => 255,
549
						 ]
550
			);
551
			$table->addColumn(
552
				'share_id', 'bigint', [
553
							  'notnull' => true,
554
							  'length'  => 14,
555
						  ]
556
			);
557
			$table->addColumn(
558
				'token', 'string', [
559
						   'notnull' => true,
560
						   'length'  => 31,
561
					   ]
562
			);
563
			$table->addColumn(
564
				'password', 'string', [
565
							  'notnull' => true,
566
							  'length'  => 127,
567
						  ]
568
			);
569
			$table->addColumn(
570
				'accepted', Type::SMALLINT, [
571
							  'notnull' => false,
572
							  'length'  => 1,
573
						  ]
574
			);
575
			$table->setPrimaryKey(['circle_id', 'user_id', 'share_id']);
576
		}
577
578
579
		return $schema;
580
	}
581
582
583
	/**
584
	 * @param IOutput $output
585
	 * @param Closure $schemaClosure The `\Closure` returns a `ISchemaWrapper`
586
	 * @param array $options
587
	 */
588
	public function postSchemaChange(IOutput $output, Closure $schemaClosure, array $options) {
589
590
		/** @var ISchemaWrapper $schema */
591
		$schema = $schemaClosure();
592
593
		if ($schema->hasTable('circles_tokens')) {
594
			$this->copyTable('circles_tokens', 'circle_tokens');
595
		}
596
		if ($schema->hasTable('circles_circles')) {
597
			$this->copyTableCircles('circles_circles', 'circle_circles');
598
		}
599
		if ($schema->hasTable('circles_clouds')) {
600
			$this->copyTable('circles_clouds', 'circle_clouds');
601
		}
602
		if ($schema->hasTable('circles_groups')) {
603
			$this->copyTable('circles_groups', 'circle_groups');
604
		}
605
		if ($schema->hasTable('circles_gsevents')) {
606
			$this->copyTable('circles_gsevents', 'circle_gsevents');
607
		}
608
		if ($schema->hasTable('circles_gsshares')) {
609
			$this->copyTable('circles_gsshares', 'circle_gsshares');
610
		}
611
		if ($schema->hasTable('circles_gsshares_mp')) {
612
			$this->copyTable('circles_gsshares_mp', 'circle_gsshares_mp');
613
		}
614
		if ($schema->hasTable('circles_links')) {
615
			$this->copyTable('circles_links', 'circle_links');
616
		}
617
		if ($schema->hasTable('circles_members')) {
618
			$this->copyTable('circles_members', 'circle_members', ['instance' => '', 'contact_id' => '']);
619
		}
620
		if ($schema->hasTable('circles_shares')) {
621
			$this->copyTable('circles_shares', 'circle_shares');
622
		}
623
624
		$this->updateMemberId();
625
		$this->updateTokens();
626
	}
627
628
629
	/**
630
	 * @param $orig
631
	 * @param $dest
632
	 * @param array $default
633
	 */
634
	protected function copyTable($orig, $dest, array $default = []) {
635
		$qb = $this->connection->getQueryBuilder();
636
637
		$qb->select('*')
638
		   ->from($orig);
639
640
		$result = $qb->execute();
641
		while ($row = $result->fetch()) {
642
			$copy = $this->connection->getQueryBuilder();
643
			$copy->insert($dest);
644
			$ak = array_keys($row);
645
			foreach ($ak as $k) {
646
				if ($row[$k] !== null) {
647
					$copy->setValue($k, $copy->createNamedParameter($row[$k]));
648
				} elseif (array_key_exists($k, $default)) {
649
					$copy->setValue($k, $copy->createNamedParameter($default[$k]));
650
				}
651
			}
652
653
			$ak = array_keys($default);
654
			foreach ($ak as $k) {
655
				if (!array_key_exists($k, $row)) {
656
					$copy->setValue($k, $copy->createNamedParameter($default[$k]));
657
				}
658
			}
659
660
			$copy->execute();
661
		}
662
	}
663
664
665
	/**
666
	 * @param $orig
667
	 * @param $dest
668
	 */
669
	protected function copyTableCircles($orig, $dest) {
670
		$qb = $this->connection->getQueryBuilder();
671
672
		$qb->select('*')
673
		   ->from($orig);
674
675
		$result = $qb->execute();
676
		while ($row = $result->fetch()) {
677
			$copy = $this->connection->getQueryBuilder();
678
			$copy->insert($dest);
679
			$ak = array_keys($row);
680
			foreach ($ak as $k) {
681
				$v = $row[$k];
682
				if ($k === 'unique_id') {
683
					$copy->setValue('unique_id', $copy->createNamedParameter(substr($v, 0, 14)));
684
					$copy->setValue('long_id', $copy->createNamedParameter($v));
685
				} else if ($v !== null) {
686
					$copy->setValue($k, $copy->createNamedParameter($v));
687
				}
688
			}
689
690
			$copy->execute();
691
		}
692
	}
693
694
695
	/**
696
	 *
697
	 */
698
	private function updateMemberId() {
699
		$qb = $this->connection->getQueryBuilder();
700
		$expr = $qb->expr();
701
702
		$orX = $expr->orX();
703
		$orX->add($expr->eq('member_id', $qb->createNamedParameter('')));
704
		$orX->add($expr->isNull('member_id'));
705
706
		$qb->select('circle_id', 'user_id', 'user_type', 'instance')
707
		   ->from('circle_members')
708
		   ->where($orX);
709
710
		$result = $qb->execute();
711
		while ($row = $result->fetch()) {
712
			$uniqueId = substr(bin2hex(openssl_random_pseudo_bytes(24)), 0, 15);
713
714
			$update = $this->connection->getQueryBuilder();
715
			$expru = $update->expr();
716
			$update->update('circle_members')
717
				   ->set('member_id', $update->createNamedParameter($uniqueId))
718
				   ->where($expru->eq('circle_id', $update->createNamedParameter($row['circle_id'])))
719
				   ->andWhere($expru->eq('user_id', $update->createNamedParameter($row['user_id'])))
720
				   ->andWhere($expru->eq('user_type', $update->createNamedParameter($row['user_type'])))
721
				   ->andWhere($expru->eq('instance', $update->createNamedParameter($row['instance'])));
722
723
			$update->execute();
724
		}
725
	}
726
727
728
	/**
729
	 *
730
	 */
731
	private function updateTokens() {
732
		$qb = $this->connection->getQueryBuilder();
733
		$expr = $qb->expr();
734
		$orX = $expr->orX();
735
		$orX->add($expr->eq('member_id', $qb->createNamedParameter('')));
736
		$orX->add($expr->isNull('member_id'));
737
		$qb->select('user_id', 'circle_id')
738
		   ->from('circle_tokens')
739
		   ->where($orX);
740
741
		$result = $qb->execute();
742
		while ($row = $result->fetch()) {
743
			$qbm = $this->connection->getQueryBuilder();
744
			$exprm = $qbm->expr();
745
746
			$qbm->select('member_id')
747
				->from('circle_members')
748
				->where($exprm->eq('circle_id', $qbm->createNamedParameter($row['circle_id'])))
749
				->andWhere($exprm->eq('user_id', $qbm->createNamedParameter($row['user_id'])))
750
				->andWhere($exprm->neq('user_type', $qbm->createNamedParameter('1')));
751
752
			$resultm = $qbm->execute();
753
			$member = $resultm->fetch();
754
755
			$update = $this->connection->getQueryBuilder();
756
			$expru = $update->expr();
757
			$update->update('circle_tokens')
758
				   ->set('member_id', $update->createNamedParameter($member['member_id']))
759
				   ->where($expru->eq('circle_id', $update->createNamedParameter($row['circle_id'])))
760
				   ->andWhere($expru->eq('user_id', $update->createNamedParameter($row['user_id'])));
761
762
			$update->execute();
763
		}
764
	}
765
766
767
}
768