mirror of
https://github.com/danog/psalm-plugin-laravel.git
synced 2025-01-22 05:11:18 +01:00
Add new ideas
This commit is contained in:
parent
44b045f975
commit
4265b7d00b
@ -46,41 +46,11 @@ abstract class AbstractPlugin implements PluginEntryPointInterface
|
||||
|
||||
$view_factory = $this->getViewFactory($app, $fake_filesystem);
|
||||
|
||||
$stubs_generator_command = new \Barryvdh\LaravelIdeHelper\Console\GeneratorCommand(
|
||||
$app['config'],
|
||||
$fake_filesystem,
|
||||
$view_factory
|
||||
);
|
||||
|
||||
$stubs_generator_command->setLaravel($app);
|
||||
|
||||
$cache_dir = __DIR__ . DIRECTORY_SEPARATOR . 'cache' . DIRECTORY_SEPARATOR;
|
||||
|
||||
$fake_filesystem->setDestination($cache_dir . 'stubs.php');
|
||||
|
||||
$stubs_generator_command->run(
|
||||
new \Symfony\Component\Console\Input\ArrayInput([]),
|
||||
new \Symfony\Component\Console\Output\NullOutput()
|
||||
);
|
||||
|
||||
/** @psalm-suppress InvalidArgument */
|
||||
$meta_generator_command = new FakeMetaCommand(
|
||||
$fake_filesystem,
|
||||
$view_factory,
|
||||
$app['config']
|
||||
);
|
||||
|
||||
$meta_generator_command->setLaravel($app);
|
||||
|
||||
$fake_filesystem->setDestination($cache_dir . 'meta.php');
|
||||
|
||||
$meta_generator_command->run(
|
||||
new \Symfony\Component\Console\Input\ArrayInput([]),
|
||||
new \Symfony\Component\Console\Output\NullOutput()
|
||||
);
|
||||
|
||||
$registration->addStubFile($cache_dir . 'stubs.php');
|
||||
$registration->addStubFile($cache_dir . 'meta.php');
|
||||
$this->ingestFacadeStubs($registration, $app, $fake_filesystem, $view_factory, $cache_dir);
|
||||
$this->ingestMetaStubs($registration, $app, $fake_filesystem, $view_factory, $cache_dir);
|
||||
$this->ingestModelStubs($registration, $app, $fake_filesystem, $cache_dir);
|
||||
|
||||
require_once 'ReturnTypeProvider/AuthReturnTypeProvider.php';
|
||||
$registration->registerHooksFromClass(ReturnTypeProvider\AuthReturnTypeProvider::class);
|
||||
@ -92,6 +62,117 @@ abstract class AbstractPlugin implements PluginEntryPointInterface
|
||||
$registration->registerHooksFromClass(AppInterfaceProvider::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param \Illuminate\Contracts\Container\Container $app
|
||||
* @param \Illuminate\View\Factory $view_factory
|
||||
*/
|
||||
private function ingestFacadeStubs(
|
||||
RegistrationInterface $registration,
|
||||
$app,
|
||||
\Illuminate\Filesystem\Filesystem $fake_filesystem,
|
||||
$view_factory,
|
||||
string $cache_dir
|
||||
) {
|
||||
$stubs_generator_command = new \Barryvdh\LaravelIdeHelper\Console\GeneratorCommand(
|
||||
$app['config'],
|
||||
$fake_filesystem,
|
||||
$view_factory
|
||||
);
|
||||
|
||||
$stubs_generator_command->setLaravel($app);
|
||||
|
||||
@unlink($cache_dir . 'stubs.php');
|
||||
|
||||
$fake_filesystem->setDestination($cache_dir . 'stubs.php');
|
||||
|
||||
$stubs_generator_command->run(
|
||||
new \Symfony\Component\Console\Input\ArrayInput([]),
|
||||
new \Symfony\Component\Console\Output\NullOutput()
|
||||
);
|
||||
|
||||
$registration->addStubFile($cache_dir . 'stubs.php');
|
||||
|
||||
unlink($cache_dir . 'stubs.php');
|
||||
}
|
||||
|
||||
/**
|
||||
* @param \Illuminate\Contracts\Container\Container $app
|
||||
* @param \Illuminate\View\Factory $view_factory
|
||||
*/
|
||||
private function ingestMetaStubs(
|
||||
RegistrationInterface $registration,
|
||||
$app,
|
||||
\Illuminate\Filesystem\Filesystem $fake_filesystem,
|
||||
$view_factory,
|
||||
string $cache_dir
|
||||
) {
|
||||
/** @psalm-suppress InvalidArgument */
|
||||
$meta_generator_command = new FakeMetaCommand(
|
||||
$fake_filesystem,
|
||||
$view_factory,
|
||||
$app['config']
|
||||
);
|
||||
|
||||
$meta_generator_command->setLaravel($app);
|
||||
|
||||
@unlink($cache_dir . 'meta.php');
|
||||
|
||||
$fake_filesystem->setDestination($cache_dir . 'meta.php');
|
||||
|
||||
$meta_generator_command->run(
|
||||
new \Symfony\Component\Console\Input\ArrayInput([]),
|
||||
new \Symfony\Component\Console\Output\NullOutput()
|
||||
);
|
||||
|
||||
$registration->addStubFile($cache_dir . 'meta.php');
|
||||
|
||||
unlink($cache_dir . 'meta.php');
|
||||
}
|
||||
|
||||
/**
|
||||
* @param \Illuminate\Contracts\Container\Container $app
|
||||
*/
|
||||
private function ingestModelStubs(
|
||||
RegistrationInterface $registration,
|
||||
$app,
|
||||
\Illuminate\Filesystem\Filesystem $fake_filesystem,
|
||||
string $cache_dir
|
||||
) {
|
||||
$migrations_folder = dirname(__DIR__, 4) . '/database/migrations/';
|
||||
|
||||
$project_analyzer = \Psalm\Internal\Analyzer\ProjectAnalyzer::getInstance();
|
||||
$codebase = $project_analyzer->getCodebase();
|
||||
|
||||
$schema_aggregator = new SchemaAggregator();
|
||||
|
||||
foreach (glob($migrations_folder . '*.php') as $file) {
|
||||
//echo $file . "\n";
|
||||
$schema_aggregator->addStatements($codebase->getStatementsForFile($file));
|
||||
}
|
||||
|
||||
$models_generator_command = new FakeModelsCommand(
|
||||
$fake_filesystem,
|
||||
$schema_aggregator
|
||||
);
|
||||
|
||||
$models_generator_command->setLaravel($app);
|
||||
|
||||
@unlink($cache_dir . 'models.php');
|
||||
|
||||
$fake_filesystem->setDestination($cache_dir . 'models.php');
|
||||
|
||||
$models_generator_command->run(
|
||||
new \Symfony\Component\Console\Input\ArrayInput([
|
||||
'--nowrite' => true
|
||||
]),
|
||||
new \Symfony\Component\Console\Output\NullOutput()
|
||||
);
|
||||
|
||||
$registration->addStubFile($cache_dir . 'models.php');
|
||||
|
||||
unlink($cache_dir . 'models.php');
|
||||
}
|
||||
|
||||
/**
|
||||
* Undocumented function
|
||||
*
|
||||
|
110
src/FakeModelsCommand.php
Normal file
110
src/FakeModelsCommand.php
Normal file
@ -0,0 +1,110 @@
|
||||
<?php
|
||||
namespace Psalm\LaravelPlugin;
|
||||
|
||||
use Composer\Autoload\ClassMapGenerator;
|
||||
use Illuminate\Console\Command;
|
||||
use Illuminate\Database\Eloquent\Relations\Relation;
|
||||
use Illuminate\Support\Str;
|
||||
use Illuminate\Filesystem\Filesystem;
|
||||
use ReflectionClass;
|
||||
use Symfony\Component\Console\Input\InputOption;
|
||||
use Symfony\Component\Console\Input\InputArgument;
|
||||
use Symfony\Component\Console\Output\OutputInterface;
|
||||
use Barryvdh\Reflection\DocBlock;
|
||||
use Barryvdh\Reflection\DocBlock\Context;
|
||||
use Barryvdh\Reflection\DocBlock\Tag;
|
||||
use Barryvdh\Reflection\DocBlock\Serializer as DocBlockSerializer;
|
||||
|
||||
class FakeModelsCommand extends \Barryvdh\LaravelIdeHelper\Console\ModelsCommand
|
||||
{
|
||||
/** @var SchemaAggregator */
|
||||
private $schema;
|
||||
|
||||
/**
|
||||
* @param Filesystem $files
|
||||
*/
|
||||
public function __construct(Filesystem $files, SchemaAggregator $schema)
|
||||
{
|
||||
parent::__construct($files);
|
||||
$this->schema = $schema;
|
||||
}
|
||||
|
||||
/**
|
||||
* Load the properties from the database table.
|
||||
*
|
||||
* @param \Illuminate\Database\Eloquent\Model $model
|
||||
*/
|
||||
protected function getPropertiesFromTable($model) : void
|
||||
{
|
||||
$table_name = $model->getTable();
|
||||
|
||||
if (!isset($this->schema->tables[$table_name])) {
|
||||
return;
|
||||
}
|
||||
|
||||
$columns = $this->schema->tables[$table_name]->columns;
|
||||
|
||||
foreach ($columns as $column) {
|
||||
$name = $column->name;
|
||||
|
||||
if (in_array($name, $model->getDates())) {
|
||||
$type = '\Illuminate\Support\Carbon';
|
||||
} else {
|
||||
switch ($column->type) {
|
||||
case 'string':
|
||||
case 'int':
|
||||
case 'float':
|
||||
$type = $column->type;
|
||||
break;
|
||||
|
||||
case 'bool':
|
||||
switch (config('database.default')) {
|
||||
case 'sqlite':
|
||||
case 'mysql':
|
||||
$type = 'int';
|
||||
break;
|
||||
default:
|
||||
$type = 'bool';
|
||||
break;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case 'enum':
|
||||
if (!$column->options) {
|
||||
$type = 'string';
|
||||
} else {
|
||||
$type = '\'' . implode('\'|\'', $column->options) . '\'';
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
$type = 'mixed';
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if ($column->nullable) {
|
||||
$this->nullableColumns[$name] = true;
|
||||
}
|
||||
|
||||
$this->setProperty($name, $type, true, true, '', $column->nullable);
|
||||
if ($this->write_model_magic_where) {
|
||||
$this->setMethod(
|
||||
Str::camel("where_" . $name),
|
||||
'\Illuminate\Database\Eloquent\Builder|\\' . get_class($model),
|
||||
array('$value')
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param \Illuminate\Database\Eloquent\Model $model
|
||||
*/
|
||||
protected function getPropertiesFromMethods($model)
|
||||
{
|
||||
// do nothing here
|
||||
}
|
||||
}
|
546
src/SchemaAggregator.php
Normal file
546
src/SchemaAggregator.php
Normal file
@ -0,0 +1,546 @@
|
||||
<?php
|
||||
namespace Psalm\LaravelPlugin;
|
||||
|
||||
use PhpParser;
|
||||
|
||||
class SchemaAggregator
|
||||
{
|
||||
/** @var array<string, SchemaTable> */
|
||||
public $tables = [];
|
||||
|
||||
/**
|
||||
* @param array<int, PhpParser\Node\Stmt> $statements
|
||||
*/
|
||||
public function addStatements(array $stmts) : void
|
||||
{
|
||||
foreach ($stmts as $stmt) {
|
||||
if ($stmt instanceof PhpParser\Node\Stmt\Class_) {
|
||||
$this->addClassStatements($stmt->stmts);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array<int, PhpParser\Node\Stmt> $statements
|
||||
*/
|
||||
private function addClassStatements(array $stmts) : void
|
||||
{
|
||||
foreach ($stmts as $stmt) {
|
||||
if ($stmt instanceof PhpParser\Node\Stmt\ClassMethod
|
||||
&& $stmt->name->name === 'up'
|
||||
) {
|
||||
$this->addUpMethodStatements($stmt->stmts);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array<int, PhpParser\Node\Stmt> $statements
|
||||
*/
|
||||
private function addUpMethodStatements(array $stmts) : void
|
||||
{
|
||||
foreach ($stmts as $stmt) {
|
||||
if ($stmt instanceof PhpParser\Node\Stmt\Expression
|
||||
&& $stmt->expr instanceof PhpParser\Node\Expr\StaticCall
|
||||
&& $stmt->expr->class instanceof PhpParser\Node\Name
|
||||
&& $stmt->expr->name instanceof PhpParser\Node\Identifier
|
||||
&& $stmt->expr->class->getAttribute('resolvedName') === \Illuminate\Support\Facades\Schema::class
|
||||
) {
|
||||
switch ($stmt->expr->name->name) {
|
||||
case 'create':
|
||||
$this->alterTable($stmt->expr, true);
|
||||
break;
|
||||
|
||||
case 'table':
|
||||
$this->alterTable($stmt->expr, false);
|
||||
break;
|
||||
|
||||
case 'drop':
|
||||
case 'dropIfExists':
|
||||
$this->dropTable($stmt->expr);
|
||||
break;
|
||||
|
||||
case 'rename':
|
||||
$this->renameTable($stmt->expr);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private function alterTable(PhpParser\Node\Expr\StaticCall $call, bool $creating) : void
|
||||
{
|
||||
if (!isset($call->args[0])
|
||||
|| !$call->args[0]->value instanceof PhpParser\Node\Scalar\String_
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
$table_name = $call->args[0]->value->value;
|
||||
|
||||
if ($creating) {
|
||||
$this->tables[$table_name] = new SchemaTable($table_name);
|
||||
}
|
||||
|
||||
if (!isset($call->args[1])
|
||||
|| !$call->args[1]->value instanceof PhpParser\Node\Expr\Closure
|
||||
|| count($call->args[1]->value->params) < 1
|
||||
|| ($call->args[1]->value->params[0]->type instanceof PhpParser\Node\Name
|
||||
&& $call->args[1]->value->params[0]->type->getAttribute('resolvedName')
|
||||
!== \Illuminate\Database\Schema\Blueprint::class)
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
$update_closure = $call->args[1]->value;
|
||||
|
||||
$call_arg_name = $call->args[1]->value->params[0]->var->name;
|
||||
|
||||
$this->processColumnUpdates($table_name, $call_arg_name, $update_closure->stmts);
|
||||
}
|
||||
|
||||
private function dropTable(PhpParser\Node\Expr\StaticCall $call)
|
||||
{
|
||||
if (!isset($call->args[0])
|
||||
|| !$call->args[0]->value instanceof PhpParser\Node\Scalar\String_
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
$table_name = $call->args[0]->value->value;
|
||||
|
||||
unset($this->tables[$table_name]);
|
||||
}
|
||||
|
||||
private function renameTable(PhpParser\Node\Expr\StaticCall $call)
|
||||
{
|
||||
if (!isset($call->args[0])
|
||||
|| !$call->args[0]->value instanceof PhpParser\Node\Scalar\String_
|
||||
|| !isset($call->args[1])
|
||||
|| !$call->args[1]->value instanceof PhpParser\Node\Scalar\String_
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
$old_table_name = $call->args[0]->value->value;
|
||||
$new_table_name = $call->args[1]->value->value;
|
||||
|
||||
if (!isset($this->tables[$old_table_name])) {
|
||||
return;
|
||||
}
|
||||
|
||||
$table = $this->tables[$old_table_name];
|
||||
|
||||
unset($this->tables[$old_table_name]);
|
||||
|
||||
$table->name = $new_table_name;
|
||||
|
||||
$this->tables[$new_table_name] = $table;
|
||||
}
|
||||
|
||||
private function processColumnUpdates(string $table_name, string $call_arg_name, array $stmts) : void
|
||||
{
|
||||
if (!isset($this->tables[$table_name])) {
|
||||
return;
|
||||
}
|
||||
|
||||
$table = $this->tables[$table_name];
|
||||
|
||||
foreach ($stmts as $stmt) {
|
||||
if ($stmt instanceof PhpParser\Node\Stmt\Expression
|
||||
&& $stmt->expr instanceof PhpParser\Node\Expr\MethodCall
|
||||
&& $stmt->expr->name instanceof PhpParser\Node\Identifier
|
||||
) {
|
||||
$root_var = $stmt->expr;
|
||||
|
||||
$first_method_call = $root_var;
|
||||
|
||||
$additional_method_calls = [];
|
||||
|
||||
$nullable = false;
|
||||
|
||||
while ($root_var instanceof PhpParser\Node\Expr\MethodCall) {
|
||||
if ($root_var->name instanceof PhpParser\Node\Identifier
|
||||
&& $root_var->name->name === 'nullable'
|
||||
) {
|
||||
$nullable = true;
|
||||
}
|
||||
|
||||
$first_method_call = $root_var;
|
||||
$root_var = $root_var->var;
|
||||
}
|
||||
|
||||
if ($root_var instanceof PhpParser\Node\Expr\Variable
|
||||
&& $root_var->name === $call_arg_name
|
||||
) {
|
||||
$first_arg = $first_method_call->args[0]->value ?? null;
|
||||
$second_arg = $first_method_call->args[1]->value ?? null;
|
||||
|
||||
if (!$first_arg instanceof PhpParser\Node\Scalar\String_) {
|
||||
if ($first_method_call->name->name === 'timestamps'
|
||||
|| $first_method_call->name->name === 'timestampsTz'
|
||||
|| $first_method_call->name->name === 'nullableTimestamps'
|
||||
|| $first_method_call->name->name === 'nullableTimestampsTz'
|
||||
|| $first_method_call->name->name === 'rememberToken'
|
||||
) {
|
||||
$column_name = null;
|
||||
} elseif ($first_method_call->name->name === 'softDeletes'
|
||||
|| $first_method_call->name->name === 'softDeletesTz'
|
||||
|| $first_method_call->name->name === 'dropSoftDeletes'
|
||||
|| $first_method_call->name->name === 'dropSoftDeletesTz'
|
||||
) {
|
||||
$column_name = 'deleted_at';
|
||||
} else {
|
||||
continue;
|
||||
}
|
||||
} else {
|
||||
$column_name = $first_arg->value;
|
||||
}
|
||||
|
||||
$second_arg_array = null;
|
||||
|
||||
if ($second_arg instanceof PhpParser\Node\Expr\Array_) {
|
||||
$second_arg_array = [];
|
||||
|
||||
foreach ($second_arg->items as $array_item) {
|
||||
if ($array_item->value instanceof PhpParser\Node\Scalar\String_) {
|
||||
$second_arg_array[] = $array_item->value->value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
switch ($first_method_call->name->name) {
|
||||
case 'bigIncrements':
|
||||
$table->setColumn(new SchemaColumn($column_name, 'int', $nullable));
|
||||
break;
|
||||
|
||||
case 'bigInteger':
|
||||
$table->setColumn(new SchemaColumn($column_name, 'int', $nullable));
|
||||
break;
|
||||
|
||||
case 'binary':
|
||||
$table->setColumn(new SchemaColumn($column_name, 'string', $nullable));
|
||||
break;
|
||||
|
||||
case 'boolean':
|
||||
$table->setColumn(new SchemaColumn($column_name, 'bool', $nullable));
|
||||
break;
|
||||
|
||||
case 'char':
|
||||
$table->setColumn(new SchemaColumn($column_name, 'string', $nullable));
|
||||
break;
|
||||
|
||||
case 'computed':
|
||||
$table->setColumn(new SchemaColumn($column_name, 'mixed', $nullable));
|
||||
break;
|
||||
|
||||
case 'date':
|
||||
$table->setColumn(new SchemaColumn($column_name, 'string', $nullable));
|
||||
break;
|
||||
|
||||
case 'dateTime':
|
||||
$table->setColumn(new SchemaColumn($column_name, 'string', $nullable));
|
||||
break;
|
||||
|
||||
case 'dateTimeTz':
|
||||
$table->setColumn(new SchemaColumn($column_name, 'string', $nullable));
|
||||
break;
|
||||
|
||||
case 'decimal':
|
||||
$table->setColumn(new SchemaColumn($column_name, 'float', $nullable));
|
||||
break;
|
||||
|
||||
case 'double':
|
||||
$table->setColumn(new SchemaColumn($column_name, 'float', $nullable));
|
||||
break;
|
||||
|
||||
case 'drop':
|
||||
$table->dropColumn($column_name);
|
||||
break;
|
||||
|
||||
case 'dropColumn':
|
||||
$table->dropColumn($column_name);
|
||||
break;
|
||||
|
||||
case 'dropForeign':
|
||||
case 'dropIndex':
|
||||
case 'dropPrimary':
|
||||
case 'dropUnique':
|
||||
case 'dropSpatialIndex':
|
||||
break;
|
||||
|
||||
case 'dropIfExists':
|
||||
$table->dropColumn($column_name);
|
||||
break;
|
||||
|
||||
case 'dropMorphs':
|
||||
$table->dropColumn($column_name . '_type');
|
||||
$table->dropColumn($column_name . '_id');
|
||||
break;
|
||||
|
||||
case 'dropRememberToken':
|
||||
$table->dropColumn('remember_token');
|
||||
break;
|
||||
|
||||
case 'dropSoftDeletes':
|
||||
$table->dropColumn($column_name);
|
||||
break;
|
||||
|
||||
case 'dropSoftDeletesTz':
|
||||
$table->dropColumn($column_name);
|
||||
break;
|
||||
|
||||
case 'dropTimestamps':
|
||||
case 'dropTimestampsTz':
|
||||
$table->dropColumn('created_at');
|
||||
$table->dropColumn('updated_at');
|
||||
break;
|
||||
|
||||
case 'enum':
|
||||
$table->setColumn(new SchemaColumn($column_name, 'enum', $nullable, $second_arg_array));
|
||||
break;
|
||||
|
||||
case 'float':
|
||||
$table->setColumn(new SchemaColumn($column_name, 'float', $nullable));
|
||||
break;
|
||||
|
||||
case 'foreign':
|
||||
break;
|
||||
|
||||
case 'geometry':
|
||||
$table->setColumn(new SchemaColumn($column_name, 'mixed', $nullable));
|
||||
break;
|
||||
|
||||
case 'geometryCollection':
|
||||
$table->setColumn(new SchemaColumn($column_name, 'mixed', $nullable));
|
||||
break;
|
||||
|
||||
case 'increments':
|
||||
break;
|
||||
|
||||
case 'index':
|
||||
break;
|
||||
|
||||
case 'integer':
|
||||
$table->setColumn(new SchemaColumn($column_name, 'int', $nullable));
|
||||
break;
|
||||
|
||||
case 'integerIncrements':
|
||||
$table->setColumn(new SchemaColumn($column_name, 'int', $nullable));
|
||||
break;
|
||||
|
||||
case 'ipAddress':
|
||||
$table->setColumn(new SchemaColumn($column_name, 'string', $nullable));
|
||||
break;
|
||||
|
||||
case 'json':
|
||||
$table->setColumn(new SchemaColumn($column_name, 'string', $nullable));
|
||||
break;
|
||||
|
||||
case 'jsonb':
|
||||
$table->setColumn(new SchemaColumn($column_name, 'string', $nullable));
|
||||
break;
|
||||
|
||||
case 'lineString':
|
||||
$table->setColumn(new SchemaColumn($column_name, 'string', $nullable));
|
||||
break;
|
||||
|
||||
case 'longText':
|
||||
$table->setColumn(new SchemaColumn($column_name, 'string', $nullable));
|
||||
break;
|
||||
|
||||
case 'macAddress':
|
||||
$table->setColumn(new SchemaColumn($column_name, 'string', $nullable));
|
||||
break;
|
||||
|
||||
case 'mediumIncrements':
|
||||
$table->setColumn(new SchemaColumn($column_name, 'int', $nullable));
|
||||
break;
|
||||
|
||||
case 'mediumInteger':
|
||||
$table->setColumn(new SchemaColumn($column_name, 'int', $nullable));
|
||||
break;
|
||||
|
||||
case 'mediumText':
|
||||
$table->setColumn(new SchemaColumn($column_name, 'string', $nullable));
|
||||
break;
|
||||
|
||||
case 'morphs':
|
||||
$table->setColumn(new SchemaColumn($column_name . '_type', 'string', $nullable));
|
||||
$table->setColumn(new SchemaColumn($column_name . '_id', 'int', $nullable));
|
||||
break;
|
||||
|
||||
case 'multiLineString':
|
||||
$table->setColumn(new SchemaColumn($column_name, 'string', $nullable));
|
||||
break;
|
||||
|
||||
case 'multiPoint':
|
||||
$table->setColumn(new SchemaColumn($column_name, 'mixed', $nullable));
|
||||
break;
|
||||
|
||||
case 'multiPolygon':
|
||||
$table->setColumn(new SchemaColumn($column_name, 'mixed', $nullable));
|
||||
break;
|
||||
|
||||
case 'multiPolygonZ':
|
||||
$table->setColumn(new SchemaColumn($column_name, 'mixed', $nullable));
|
||||
break;
|
||||
|
||||
case 'nullableMorphs':
|
||||
$table->setColumn(new SchemaColumn($column_name . '_type', 'string', true));
|
||||
$table->setColumn(new SchemaColumn($column_name . '_id', 'int', true));
|
||||
break;
|
||||
|
||||
case 'nullableTimestamps':
|
||||
$table->setColumn(new SchemaColumn('created_at', 'string', true));
|
||||
$table->setColumn(new SchemaColumn('updated_at', 'string', true));
|
||||
break;
|
||||
|
||||
case 'nullableUuidMorphs':
|
||||
$table->setColumn(new SchemaColumn($column_name . '_type', 'string', true));
|
||||
$table->setColumn(new SchemaColumn($column_name . '_id', 'string', true));
|
||||
break;
|
||||
|
||||
case 'point':
|
||||
$table->setColumn(new SchemaColumn($column_name, 'mixed', $nullable));
|
||||
break;
|
||||
|
||||
case 'polygon':
|
||||
$table->setColumn(new SchemaColumn($column_name, 'mixed', $nullable));
|
||||
break;
|
||||
|
||||
case 'primary':
|
||||
break;
|
||||
|
||||
case 'rememberToken':
|
||||
$table->setColumn(new SchemaColumn('remember_token', 'string', $nullable));
|
||||
break;
|
||||
|
||||
case 'removeColumn':
|
||||
$table->dropColumn($column_name);
|
||||
break;
|
||||
|
||||
case 'rename':
|
||||
if ($second_arg instanceof PhpParser\Node\Scalar\String_) {
|
||||
$table->renameColumn($column_name, $second_arg->value);
|
||||
}
|
||||
break;
|
||||
|
||||
case 'renameColumn':
|
||||
break;
|
||||
|
||||
case 'renameIndex':
|
||||
break;
|
||||
|
||||
case 'set':
|
||||
$table->setColumn(new SchemaColumn($column_name, 'set', $nullable, $second_arg_array));
|
||||
break;
|
||||
|
||||
case 'smallIncrements':
|
||||
$table->setColumn(new SchemaColumn($column_name, 'int', $nullable));
|
||||
break;
|
||||
|
||||
case 'smallInteger':
|
||||
$table->setColumn(new SchemaColumn($column_name, 'int', $nullable));
|
||||
break;
|
||||
|
||||
case 'softDeletes':
|
||||
$table->setColumn(new SchemaColumn($column_name, 'string', true));
|
||||
break;
|
||||
|
||||
case 'softDeletesTz':
|
||||
$table->setColumn(new SchemaColumn($column_name, 'string', true));
|
||||
break;
|
||||
|
||||
case 'spatialIndex':
|
||||
break;
|
||||
|
||||
case 'string':
|
||||
$table->setColumn(new SchemaColumn($column_name, 'string', $nullable));
|
||||
break;
|
||||
|
||||
case 'text':
|
||||
$table->setColumn(new SchemaColumn($column_name, 'string', $nullable));
|
||||
break;
|
||||
|
||||
case 'time':
|
||||
$table->setColumn(new SchemaColumn($column_name, 'string', $nullable));
|
||||
break;
|
||||
|
||||
case 'timestamp':
|
||||
$table->setColumn(new SchemaColumn($column_name, 'string', $nullable));
|
||||
break;
|
||||
|
||||
case 'timestamps':
|
||||
$table->setColumn(new SchemaColumn('created_at', 'string', true));
|
||||
$table->setColumn(new SchemaColumn('updated_at', 'string', true));
|
||||
break;
|
||||
|
||||
case 'timestampsTz':
|
||||
$table->setColumn(new SchemaColumn('created_at', 'string', true));
|
||||
$table->setColumn(new SchemaColumn('updated_at', 'string', true));
|
||||
break;
|
||||
|
||||
case 'timestampTz':
|
||||
$table->setColumn(new SchemaColumn($column_name, 'string', true));
|
||||
break;
|
||||
|
||||
case 'timeTz':
|
||||
$table->setColumn(new SchemaColumn($column_name, 'string', true));
|
||||
break;
|
||||
|
||||
case 'tinyIncrements':
|
||||
$table->setColumn(new SchemaColumn($column_name, 'int', $nullable));
|
||||
break;
|
||||
|
||||
case 'tinyInteger':
|
||||
$table->setColumn(new SchemaColumn($column_name, 'int', $nullable));
|
||||
break;
|
||||
|
||||
case 'unique':
|
||||
break;
|
||||
|
||||
case 'unsignedBigInteger':
|
||||
$table->setColumn(new SchemaColumn($column_name, 'int', $nullable));
|
||||
break;
|
||||
|
||||
case 'unsignedDecimal':
|
||||
$table->setColumn(new SchemaColumn($column_name, 'float', $nullable));
|
||||
break;
|
||||
|
||||
case 'unsignedInteger':
|
||||
$table->setColumn(new SchemaColumn($column_name, 'int', $nullable));
|
||||
break;
|
||||
|
||||
case 'unsignedMediumInteger':
|
||||
$table->setColumn(new SchemaColumn($column_name, 'int', $nullable));
|
||||
break;
|
||||
|
||||
case 'unsignedSmallInteger':
|
||||
$table->setColumn(new SchemaColumn($column_name, 'int', $nullable));
|
||||
break;
|
||||
|
||||
case 'unsignedTinyInteger':
|
||||
$table->setColumn(new SchemaColumn($column_name, 'int', $nullable));
|
||||
break;
|
||||
|
||||
case 'uuid':
|
||||
$table->setColumn(new SchemaColumn($column_name, 'string', $nullable));
|
||||
break;
|
||||
|
||||
case 'uuidMorphs':
|
||||
$table->setColumn(new SchemaColumn($column_name . '_type', 'string', $nullable));
|
||||
$table->setColumn(new SchemaColumn($column_name . '_id', 'string', $nullable));
|
||||
break;
|
||||
|
||||
case 'year':
|
||||
$table->setColumn(new SchemaColumn($column_name, 'string', true));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
29
src/SchemaColumn.php
Normal file
29
src/SchemaColumn.php
Normal file
@ -0,0 +1,29 @@
|
||||
<?php
|
||||
namespace Psalm\LaravelPlugin;
|
||||
|
||||
class SchemaColumn
|
||||
{
|
||||
/** @var string */
|
||||
public $name;
|
||||
|
||||
/** @var string */
|
||||
public $type;
|
||||
|
||||
/** @var bool */
|
||||
public $nullable;
|
||||
|
||||
/** @var ?array<int, string> */
|
||||
public $options;
|
||||
|
||||
public function __construct(
|
||||
string $name,
|
||||
string $type,
|
||||
bool $nullable = false,
|
||||
?array $options = null
|
||||
) {
|
||||
$this->name = $name;
|
||||
$this->type = $type;
|
||||
$this->nullable = $nullable;
|
||||
$this->options = $options;
|
||||
}
|
||||
}
|
41
src/SchemaTable.php
Normal file
41
src/SchemaTable.php
Normal file
@ -0,0 +1,41 @@
|
||||
<?php
|
||||
namespace Psalm\LaravelPlugin;
|
||||
|
||||
class SchemaTable
|
||||
{
|
||||
/** @var string */
|
||||
public $name;
|
||||
|
||||
/** @var array<string, SchemaColumn> */
|
||||
public $columns = [];
|
||||
|
||||
public function __construct(string $name)
|
||||
{
|
||||
$this->name = $name;
|
||||
}
|
||||
|
||||
public function setColumn(SchemaColumn $column) : void
|
||||
{
|
||||
$this->columns[$column->name] = $column;
|
||||
}
|
||||
|
||||
public function renameColumn(string $old_name, string $new_name) : void
|
||||
{
|
||||
if (!isset($this->columns[$column->name])) {
|
||||
return;
|
||||
}
|
||||
|
||||
$old_column = $this->columns[$old_name];
|
||||
|
||||
unset($this->columns[$old_name]);
|
||||
|
||||
$old_column->name = $new_name;
|
||||
|
||||
$this->columns[$new_name] = $old_column;
|
||||
}
|
||||
|
||||
public function dropColumn(string $column_name) : void
|
||||
{
|
||||
unset($this->columns[$column_name]);
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user