Completed
Pull Request — master (#148)
by
unknown
05:52
created

MigrateGenerateCommand::getExcludedTables()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 10
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 10
rs 9.4285
c 0
b 0
f 0
cc 2
eloc 6
nc 2
nop 0
1
<?php namespace Xethron\MigrationsGenerator;
2
3
use File;
4
use Illuminate\Support\Collection;
5
use Way\Generators\Commands\GeneratorCommand;
6
use Symfony\Component\Console\Input\InputOption;
7
use Symfony\Component\Console\Input\InputArgument;
8
9
use Way\Generators\Generator;
10
use Way\Generators\Filesystem\Filesystem;
11
use Way\Generators\Compilers\TemplateCompiler;
12
use Illuminate\Database\Migrations\MigrationRepositoryInterface;
13
14
use Xethron\MigrationsGenerator\Generators\SchemaGenerator;
15
use Xethron\MigrationsGenerator\Syntax\AddToTable;
16
use Xethron\MigrationsGenerator\Syntax\DroppedTable;
17
use Xethron\MigrationsGenerator\Syntax\AddForeignKeysToTable;
18
use Xethron\MigrationsGenerator\Syntax\RemoveForeignKeysFromTable;
19
20
use Illuminate\Contracts\Config\Repository as Config;
21
22
class MigrateGenerateCommand extends GeneratorCommand {
23
24
	/**
25
	 * The console command name.
26
	 * @var string
27
	 */
28
	protected $name = 'migrate:generate';
29
30
	/**
31
	 * The console command description.
32
	 * @var string
33
	 */
34
	protected $description = 'Generate a migration from an existing table structure.';
35
36
	/**
37
	 * @var \Way\Generators\Filesystem\Filesystem
38
	 */
39
	protected $file;
40
41
	/**
42
	 * @var \Way\Generators\Compilers\TemplateCompiler
43
	 */
44
	protected $compiler;
45
46
	/**
47
	 * @var \Illuminate\Database\Migrations\MigrationRepositoryInterface  $repository
48
	 */
49
	protected $repository;
50
51
	/**
52
	 * @var \Illuminate\Config\Repository  $config
53
	 */
54
	protected $config;
55
56
	/**
57
	 * @var \Xethron\MigrationsGenerator\Generators\SchemaGenerator
58
	 */
59
	protected $schemaGenerator;
60
61
	/**
62
	 * Array of Fields to create in a new Migration
63
	 * Namely: Columns, Indexes and Foreign Keys
64
	 * @var array
65
	 */
66
	protected $fields = array();
67
68
	/**
69
	 * List of Migrations that has been done
70
	 * @var array
71
	 */
72
	protected $migrations = array();
73
74
	/**
75
	 * @var bool
76
	 */
77
	protected $log = false;
78
79
	/**
80
	 * @var int
81
	 */
82
	protected $batch;
83
84
	/**
85
	 * Filename date prefix (Y_m_d_His)
86
	 * @var string
87
	 */
88
	protected $datePrefix;
89
90
	/**
91
	 * @var string
92
	 */
93
	protected $migrationName;
94
95
	/**
96
	 * @var string
97
	 */
98
	protected $method;
99
100
	/**
101
	 * @var string
102
	 */
103
	protected $table;
104
105
    /**
106
     * @var string|null
107
     */
108
    protected $connection = null;
109
110
    /**
111
     * For create migrations so they all do not have the same date
112
     * @var int
113
     */
114
    protected $secondCount = 1;
115
116
    /**
117
     * Array of ForeignKeys to create in a new Migration
118
     * Namely: Foreign Keys
119
     * @var array
120
     */
121
    protected $foreignKeys = array();
122
123
    /** @var bool // separate or combine the foreign keys to the table create */
124
    protected $separateForeignKeysCreation = true;
125
126
    /** @var bool // empty the existing migrations */
127
    protected $clearAllExistingMigrations = false;
128
129
    /** @var bool // should we check for table dependencies via foreign keys */
130
    protected $checkForTableDependencies = false;
131
132
    /**
133
	 * @param \Way\Generators\Generator  $generator
134
	 * @param \Way\Generators\Filesystem\Filesystem  $file
135
	 * @param \Way\Generators\Compilers\TemplateCompiler  $compiler
136
	 * @param \Illuminate\Database\Migrations\MigrationRepositoryInterface  $repository
137
	 * @param \Illuminate\Config\Repository  $config
138
	 */
139
	public function __construct(
140
		Generator $generator,
141
		Filesystem $file,
142
		TemplateCompiler $compiler,
143
		MigrationRepositoryInterface $repository,
144
		Config $config
145
	)
146
	{
147
		$this->file = $file;
148
		$this->compiler = $compiler;
149
		$this->repository = $repository;
150
		$this->config = $config;
0 ignored issues
show
Documentation Bug introduced by
It seems like $config of type object<Illuminate\Contracts\Config\Repository> is incompatible with the declared type object<Illuminate\Config\Repository> of property $config.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
151
152
		parent::__construct( $generator );
153
	}
154
155
	/**
156
	 * Execute the console command. Added for Laravel 5.5
157
	 *
158
	 * @return void
159
	 */
160
	public function handle()
161
	{
162
		$this->fire();
163
	}
164
165
    /**
166
	 * Execute the console command.
167
	 *
168
	 * @return void
169
	 */
170
	public function fire()
171
	{
172
		$this->info( 'Using connection: '. $this->option( 'connection' ) ."\n" );
173
        if ($this->option('connection') !== $this->config->get('database.default')) {
174
            $this->connection = $this->option('connection');
0 ignored issues
show
Documentation Bug introduced by
It seems like $this->option('connection') can also be of type array. However, the property $connection is declared as type string|null. Maybe add an additional type check?

Our type inference engine has found a suspicous assignment of a value to a property. This check raises an issue when a value that can be of a mixed type is assigned to a property that is type hinted more strictly.

For example, imagine you have a variable $accountId that can either hold an Id object or false (if there is no account id yet). Your code now assigns that value to the id property of an instance of the Account class. This class holds a proper account, so the id value must no longer be false.

Either this assignment is in error or a type check should be added for that assignment.

class Id
{
    public $id;

    public function __construct($id)
    {
        $this->id = $id;
    }

}

class Account
{
    /** @var  Id $id */
    public $id;
}

$account_id = false;

if (starsAreRight()) {
    $account_id = new Id(42);
}

$account = new Account();
if ($account instanceof Id)
{
    $account->id = $account_id;
}
Loading history...
175
        }
176
		$this->schemaGenerator = new SchemaGenerator(
177
			$this->option('connection'),
178
			$this->option('defaultIndexNames'),
179
			$this->option('defaultFKNames')
180
		);
181
182
		if ( $this->argument( 'tables' ) ) {
183
			$tables = explode( ',', $this->argument( 'tables' ) );
184
		} elseif ( $this->option('tables') ) {
185
			$tables = explode( ',', $this->option( 'tables' ) );
186
		} else {
187
			$tables = $this->schemaGenerator->getTables();
188
		}
189
190
		$tables = $this->removeExcludedTables($tables);
191
		$this->info( 'Generating migrations for: '. implode( ', ', $tables ) );
192
193
		if (!$this->option( 'no-interaction' )) {
194
			$this->log = $this->askYn('Do you want to log these migrations in the migrations table?');
195
            $this->checkForTableDependencies = $this->askYn('Do you want to load tables by table dependencies?');
196
            $this->separateForeignKeysCreation = $this->askYn('Do you want to separate the foreign keys creation into their own migrations?');
197
            $this->clearAllExistingMigrations = $this->askYn('Do you want to clear all existing migrations?');
198
		}
199
200
		if ( $this->log ) {
201
			$this->repository->setSource( $this->option( 'connection' ) );
202
			if ( ! $this->repository->repositoryExists() ) {
203
				$options = array('--database' => $this->option( 'connection' ) );
204
				$this->call('migrate:install', $options);
205
			}
206
			$batch = $this->repository->getNextBatchNumber();
207
			$this->batch = $this->askNumeric( 'Next Batch Number is: '. $batch .'. We recommend using Batch Number 0 so that it becomes the "first" migration', 0 );
0 ignored issues
show
Documentation Bug introduced by
It seems like $this->askNumeric('Next ... "first" migration', 0) can also be of type double or string. However, the property $batch is declared as type integer. Maybe add an additional type check?

Our type inference engine has found a suspicous assignment of a value to a property. This check raises an issue when a value that can be of a mixed type is assigned to a property that is type hinted more strictly.

For example, imagine you have a variable $accountId that can either hold an Id object or false (if there is no account id yet). Your code now assigns that value to the id property of an instance of the Account class. This class holds a proper account, so the id value must no longer be false.

Either this assignment is in error or a type check should be added for that assignment.

class Id
{
    public $id;

    public function __construct($id)
    {
        $this->id = $id;
    }

}

class Account
{
    /** @var  Id $id */
    public $id;
}

$account_id = false;

if (starsAreRight()) {
    $account_id = new Id(42);
}

$account = new Account();
if ($account instanceof Id)
{
    $account->id = $account_id;
}
Loading history...
208
		}
209
210
        $this->clearAllMigrations();
211
        $this->info( $this->separateForeignKeysCreation ? "Setting up Tables and Index Migrations" : "Setting up Tables, Index, and Foreign Key Migrations");
212
        $this->datePrefix = date( 'Y_m_d_His' );
213
        $this->generateTablesAndIndices( $tables );
214
215
        if ($this->separateForeignKeysCreation) {
216
            $this->info( "Setting up Foreign Key Migrations" );
217
            $this->generateForeignKeys( $tables );
218
        }
219
220
        $this->info( "\nFinished!\n" );
221
	}
222
223
    /**
224
     * Make sure the migration date string is always different and sequential
225
     * @return false|string
226
     */
227
    protected function getDatePrefix()
228
    {
229
        $this->secondCount++;
230
        return date( 'Y_m_d_His', strtotime( "+{$this->secondCount} second" ) );
231
    }
232
233
    /**
234
     * Check if we should clear all existing migrations, and if so, remove them
235
     */
236
    protected function clearAllMigrations()
237
    {
238
        if ($this->clearAllExistingMigrations) {
239
            $directory = base_path() . '/database/migrations/';
240
            File::cleanDirectory($directory);
241
        }
242
    }
243
244
	/**
245
	 * Ask for user input: Yes/No
246
	 * @param  string $question Question to ask
247
	 * @return boolean          Answer from user
248
	 */
249
	protected function askYn( $question ) {
250
		$answer = $this->ask( $question .' [Y/n] ');
251
		while ( ! in_array( strtolower( $answer ), [ 'y', 'n', 'yes', 'no' ] ) ) {
252
			$answer = $this->ask('Please choose either yes or no. ');
253
		}
254
		return in_array( strtolower( $answer ), [ 'y', 'yes' ] );
255
	}
256
257
	/**
258
	 * Ask user for a Numeric Value, or blank for default
259
	 * @param  string    $question Question to ask
260
	 * @param  int|float $default  Default Value (optional)
261
	 * @return int|float           Answer
262
	 */
263
	protected function askNumeric( $question, $default = null ) {
264
		$ask = 'Your answer needs to be a numeric value';
265
266
		if ( ! is_null( $default ) ) {
267
			$question .= ' [Default: '. $default .'] ';
268
			$ask .= ' or blank for default';
269
		}
270
271
		$answer = $this->ask( $question );
272
273
		while ( ! is_numeric( $answer ) and ! ( $answer == '' and ! is_null( $default ) ) ) {
274
			$answer = $this->ask( $ask .'. ');
275
		}
276
		if ( $answer == '' ) {
277
			$answer = $default;
278
		}
279
		return $answer;
280
	}
281
282
	/**
283
	 * Generate tables and index migrations.
284
	 *
285
	 * @param  array $tables List of tables to create migrations for
286
	 * @return void
287
	 */
288
	protected function generateTablesAndIndices( array $tables )
289
	{
290
        if ($this->checkForTableDependencies) {
291
            $this->generateTablesAndIndicesLookingForTableDependencies($tables);
292
        } else {
293
            $this->method = 'create';
294
295
            foreach ( $tables as $table ) {
296
                $this->table = $table;
297
                $this->migrationName = 'create_'. $this->table .'_table';
298
                $this->fields = $this->schemaGenerator->getFields( $this->table );
0 ignored issues
show
Documentation Bug introduced by
It seems like $this->schemaGenerator->getFields($this->table) can also be of type false. However, the property $fields is declared as type array. Maybe add an additional type check?

Our type inference engine has found a suspicous assignment of a value to a property. This check raises an issue when a value that can be of a mixed type is assigned to a property that is type hinted more strictly.

For example, imagine you have a variable $accountId that can either hold an Id object or false (if there is no account id yet). Your code now assigns that value to the id property of an instance of the Account class. This class holds a proper account, so the id value must no longer be false.

Either this assignment is in error or a type check should be added for that assignment.

class Id
{
    public $id;

    public function __construct($id)
    {
        $this->id = $id;
    }

}

class Account
{
    /** @var  Id $id */
    public $id;
}

$account_id = false;

if (starsAreRight()) {
    $account_id = new Id(42);
}

$account = new Account();
if ($account instanceof Id)
{
    $account->id = $account_id;
}
Loading history...
299
300
                $this->generate();
301
            }
302
        }
303
	}
304
305
    /**
306
     * Generate tables and index migrations while checking for table dependencies via foreign keys
307
     *
308
     * @param array $tables
309
     */
310
    protected function generateTablesAndIndicesLookingForTableDependencies( array $tables )
311
    {
312
        $this->method = 'create';
313
314
        $tables = collect($tables);
315
        $tablesWithFields = new Collection();
316
317
        foreach ($tables as $table) {
318
            $this->getDependencyTable($table, $tablesWithFields);
319
        }
320
321
        foreach ( $tablesWithFields as $table => $fields) {
322
            $this->table = $table;
0 ignored issues
show
Documentation Bug introduced by
It seems like $table can also be of type integer. However, the property $table is declared as type string. Maybe add an additional type check?

Our type inference engine has found a suspicous assignment of a value to a property. This check raises an issue when a value that can be of a mixed type is assigned to a property that is type hinted more strictly.

For example, imagine you have a variable $accountId that can either hold an Id object or false (if there is no account id yet). Your code now assigns that value to the id property of an instance of the Account class. This class holds a proper account, so the id value must no longer be false.

Either this assignment is in error or a type check should be added for that assignment.

class Id
{
    public $id;

    public function __construct($id)
    {
        $this->id = $id;
    }

}

class Account
{
    /** @var  Id $id */
    public $id;
}

$account_id = false;

if (starsAreRight()) {
    $account_id = new Id(42);
}

$account = new Account();
if ($account instanceof Id)
{
    $account->id = $account_id;
}
Loading history...
323
            $this->migrationName = 'create_'. $this->table .'_table';
324
            $this->fields = $fields;
325
326
            if (!$this->separateForeignKeysCreation) {
327
                $this->foreignKeys = $this->schemaGenerator->getForeignKeyConstraints($this->table);
328
            }
329
330
            $this->generate();
331
        }
332
    }
333
334
    /**
335
     * @param $table
336
     * @param Collection $tableWithFields
337
     */
338
    protected function getDependencyTable($table, Collection &$tableWithFields)
339
    {
340
        if (!$tableWithFields->has($table)) {
341
            $fields = $this->schemaGenerator->getFields($table) ?: [];
342
343
            foreach ($fields as $field => $info) {
344
                if (substr($field, -3) === '_id') {
345
                    $tableName = str_plural(substr($field, 0, -3));
346
                    $this->getDependencyTable($tableName, $tableWithFields);
347
                }
348
            }
349
350
            $tableWithFields->put($table, $fields);
351
        }
352
    }
353
354
	/**
355
	 * Generate foreign key migrations.
356
	 *
357
	 * @param  array $tables List of tables to create migrations for
358
	 * @return void
359
	 */
360
	protected function generateForeignKeys( array $tables )
361
	{
362
		$this->method = 'table';
363
364
		foreach ( $tables as $table ) {
365
			$this->table = $table;
366
			$this->migrationName = 'add_foreign_keys_to_'. $this->table .'_table';
367
			$this->fields = $this->schemaGenerator->getForeignKeyConstraints( $this->table );
368
369
			$this->generate();
370
		}
371
	}
372
373
	/**
374
	 * Generate Migration for the current table.
375
	 *
376
	 * @return void
377
	 */
378
	protected function generate()
379
	{
380
		if ( $this->fields ) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $this->fields of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using ! empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
381
			parent::fire();
0 ignored issues
show
Comprehensibility Bug introduced by
It seems like you call parent on a different method (fire() instead of generate()). Are you sure this is correct? If so, you might want to change this to $this->fire().

This check looks for a call to a parent method whose name is different than the method from which it is called.

Consider the following code:

class Daddy
{
    protected function getFirstName()
    {
        return "Eidur";
    }

    protected function getSurName()
    {
        return "Gudjohnsen";
    }
}

class Son
{
    public function getFirstName()
    {
        return parent::getSurname();
    }
}

The getFirstName() method in the Son calls the wrong method in the parent class.

Loading history...
382
383
			if ( $this->log ) {
384
				$file = $this->getDatePrefix() . '_' . $this->migrationName;
385
				$this->repository->log($file, $this->batch);
386
			}
387
		}
388
	}
389
390
	/**
391
	 * The path where the file will be created
392
	 *
393
	 * @return string
394
	 */
395
	protected function getFileGenerationPath()
396
	{
397
		$path = $this->getPathByOptionOrConfig( 'path', 'migration_target_path' );
398
		$migrationName = str_replace('/', '_', $this->migrationName);
399
		$fileName = $this->getDatePrefix() . '_' . $migrationName . '.php';
400
401
		return "{$path}/{$fileName}";
402
	}
403
404
	/**
405
	 * Fetch the template data
406
	 *
407
	 * @return array
408
	 */
409
	protected function getTemplateData()
410
	{
411
        if (!$this->separateForeignKeysCreation) {
412
            return $this->combineTableAndForeignKeys();
413
        }
414
415
        return $this->separateTableAndForeignKeys();
416
	}
417
418
    /**
419
     * Separate the foreign keys from create migrations
420
     *
421
     * @return array
422
     */
423
    protected function separateTableAndForeignKeys()
424
    {
425
        $up = '';
426
        $down = '';
427
428
        if ( $this->method == 'create' ) {
429
            $up = (new AddToTable($this->file, $this->compiler))->run($this->fields, $this->table, $this->connection, 'create');
0 ignored issues
show
Bug introduced by
It seems like $this->connection can also be of type string; however, Xethron\MigrationsGenerator\Syntax\Table::run() does only seem to accept null, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
430
            $down = (new DroppedTable)->drop($this->table, $this->connection);
0 ignored issues
show
Bug introduced by
It seems like $this->connection can also be of type string; however, Xethron\MigrationsGenera...ax\DroppedTable::drop() does only seem to accept null, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
431
        }
432
433
        if ( $this->method == 'table' ) {
434
            $up = (new AddForeignKeysToTable($this->file, $this->compiler))->run($this->fields, $this->table, $this->connection);
0 ignored issues
show
Bug introduced by
It seems like $this->connection can also be of type string; however, Xethron\MigrationsGenerator\Syntax\Table::run() does only seem to accept null, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
435
            $down = (new RemoveForeignKeysFromTable($this->file, $this->compiler))->run($this->fields, $this->table, $this->connection);
0 ignored issues
show
Bug introduced by
It seems like $this->connection can also be of type string; however, Xethron\MigrationsGenerator\Syntax\Table::run() does only seem to accept null, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
436
        }
437
438
        return [
439
            'CLASS' => ucwords(camel_case($this->migrationName)),
440
            'UP'    => $up,
441
            'DOWN'  => $down
442
        ];
443
    }
444
445
    /**
446
     * Combine the table migrations and foreign key creations
447
     *
448
     * @return array
449
     */
450
    protected function combineTableAndForeignKeys()
451
    {
452
        $up = '';
453
        $down = '';
454
455
        if ( $this->method == 'create' ) {
456
            $up .= (new AddToTable($this->file, $this->compiler))->run($this->fields, $this->table, $this->connection, 'create');
0 ignored issues
show
Bug introduced by
It seems like $this->connection can also be of type string; however, Xethron\MigrationsGenerator\Syntax\Table::run() does only seem to accept null, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
457
            $up .= $this->foreignKeys ? PHP_EOL . PHP_EOL . "\t\t" . (new AddForeignKeysToTable($this->file, $this->compiler))->run($this->foreignKeys, $this->table, $this->connection) : '';
0 ignored issues
show
Bug introduced by
It seems like $this->connection can also be of type string; however, Xethron\MigrationsGenerator\Syntax\Table::run() does only seem to accept null, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
458
            $down .= $this->foreignKeys ? (new RemoveForeignKeysFromTable($this->file, $this->compiler))->run($this->foreignKeys, $this->table, $this->connection) . PHP_EOL . PHP_EOL . "\t\t" : '';
0 ignored issues
show
Bug introduced by
It seems like $this->connection can also be of type string; however, Xethron\MigrationsGenerator\Syntax\Table::run() does only seem to accept null, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
459
            $down .= (new DroppedTable)->drop($this->table, $this->connection);
0 ignored issues
show
Bug introduced by
It seems like $this->connection can also be of type string; however, Xethron\MigrationsGenera...ax\DroppedTable::drop() does only seem to accept null, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
460
        }
461
462
        return [
463
            'CLASS' => ucwords(camel_case($this->migrationName)),
464
            'UP'    => $up,
465
            'DOWN'  => $down
466
        ];
467
    }
468
469
	/**
470
	 * Get path to template for generator
471
	 *
472
	 * @return string
473
	 */
474
	protected function getTemplatePath()
475
	{
476
		return $this->getPathByOptionOrConfig( 'templatePath', 'migration_template_path' );
477
	}
478
479
	/**
480
	 * Get the console command arguments.
481
	 *
482
	 * @return array
483
	 */
484
	protected function getArguments()
485
	{
486
		return [
487
			['tables', InputArgument::OPTIONAL, 'A list of Tables you wish to Generate Migrations for separated by a comma: users,posts,comments'],
488
		];
489
	}
490
491
	/**
492
	 * Get the console command options.
493
	 *
494
	 * @return array
495
	 */
496
	protected function getOptions()
497
	{
498
		return [
0 ignored issues
show
Bug Best Practice introduced by
The return type of return array(array('conn...ames for migrations')); (array<string|null>[]) is incompatible with the return type of the parent method Way\Generators\Commands\...atorCommand::getOptions of type array<string|null>[].

If you return a value from a function or method, it should be a sub-type of the type that is given by the parent type f.e. an interface, or abstract method. This is more formally defined by the Lizkov substitution principle, and guarantees that classes that depend on the parent type can use any instance of a child type interchangably. This principle also belongs to the SOLID principles for object oriented design.

Let’s take a look at an example:

class Author {
    private $name;

    public function __construct($name) {
        $this->name = $name;
    }

    public function getName() {
        return $this->name;
    }
}

abstract class Post {
    public function getAuthor() {
        return 'Johannes';
    }
}

class BlogPost extends Post {
    public function getAuthor() {
        return new Author('Johannes');
    }
}

class ForumPost extends Post { /* ... */ }

function my_function(Post $post) {
    echo strtoupper($post->getAuthor());
}

Our function my_function expects a Post object, and outputs the author of the post. The base class Post returns a simple string and outputting a simple string will work just fine. However, the child class BlogPost which is a sub-type of Post instead decided to return an object, and is therefore violating the SOLID principles. If a BlogPost were passed to my_function, PHP would not complain, but ultimately fail when executing the strtoupper call in its body.

Loading history...
499
			['connection', 'c', InputOption::VALUE_OPTIONAL, 'The database connection to use.', $this->config->get( 'database.default' )],
500
			['tables', 't', InputOption::VALUE_OPTIONAL, 'A list of Tables you wish to Generate Migrations for separated by a comma: users,posts,comments'],
501
			['ignore', 'i', InputOption::VALUE_OPTIONAL, 'A list of Tables you wish to ignore, separated by a comma: users,posts,comments' ],
502
			['path', 'p', InputOption::VALUE_OPTIONAL, 'Where should the file be created?'],
503
			['templatePath', 'tp', InputOption::VALUE_OPTIONAL, 'The location of the template for this generator'],
504
			['defaultIndexNames', null, InputOption::VALUE_NONE, 'Don\'t use db index names for migrations'],
505
			['defaultFKNames', null, InputOption::VALUE_NONE, 'Don\'t use db foreign key names for migrations'],
506
		];
507
	}
508
509
	/**
510
	 * Remove all the tables to exclude from the array of tables
511
	 *
512
	 * @param array $tables
513
	 *
514
	 * @return array
515
	 */
516
	protected function removeExcludedTables( array $tables )
517
	{
518
		$excludes = $this->getExcludedTables();
519
		$tables = array_diff($tables, $excludes);
520
521
		return $tables;
522
	}
523
524
	/**
525
	 * Get a list of tables to exclude
526
	 *
527
	 * @return array
528
	 */
529
	protected function getExcludedTables()
530
	{
531
		$excludes = ['migrations'];
532
		$ignore = $this->option('ignore');
533
		if ( ! empty($ignore)) {
534
			return array_merge($excludes, explode(',', $ignore));
535
		}
536
537
		return $excludes;
538
	}
539
540
}
541