芝麻web文件管理V1.00
编辑当前文件:/home/sditechnicalteam/public_html/vendor/nunomaduro/larastan/src/Properties/SchemaAggregator.php
*/ public array $tables = []; /** @param array
$tables */ public function __construct(array $tables = []) { $this->tables = $tables; } /** * @param array
$stmts */ public function addStatements(array $stmts): void { $nodeFinder = new NodeFinder(); /** @var PhpParser\Node\Stmt\Class_[] $classes */ $classes = $nodeFinder->findInstanceOf($stmts, PhpParser\Node\Stmt\Class_::class); foreach ($classes as $stmt) { $this->addClassStatements($stmt->stmts); } } /** * @param array
$stmts */ private function addClassStatements(array $stmts): void { foreach ($stmts as $stmt) { if ($stmt instanceof PhpParser\Node\Stmt\ClassMethod && $stmt->name->name !== 'down' && $stmt->stmts ) { $this->addUpMethodStatements($stmt->stmts); } } } /** * @param PhpParser\Node\Stmt[] $stmts */ private function addUpMethodStatements(array $stmts): void { $nodeFinder = new NodeFinder(); $methods = $nodeFinder->findInstanceOf($stmts, PhpParser\Node\Stmt\Expression::class); foreach ($methods as $stmt) { if ($stmt instanceof PhpParser\Node\Stmt\Expression && $stmt->expr instanceof PhpParser\Node\Expr\MethodCall && $stmt->expr->var instanceof PhpParser\Node\Expr\StaticCall && $stmt->expr->var->class instanceof PhpParser\Node\Name && $stmt->expr->var->name instanceof PhpParser\Node\Identifier && ($stmt->expr->var->name->toString() === 'connection' || $stmt->expr->var->name->toString() === 'setConnection') && ($stmt->expr->var->class->toCodeString() === '\Illuminate\Support\Facades\Schema' || $stmt->expr->var->class->toCodeString() === '\Schema') ) { $statement = $stmt->expr; } elseif ($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->toCodeString() === '\Illuminate\Support\Facades\Schema' || $stmt->expr->class->toCodeString() === '\Schema') ) { $statement = $stmt->expr; } else { continue; } if (! $statement->name instanceof PhpParser\Node\Identifier) { continue; } switch ($statement->name->name) { case 'create': $this->alterTable($statement, true); break; case 'table': $this->alterTable($statement, false); break; case 'drop': case 'dropIfExists': $this->dropTable($statement); break; case 'rename': $this->renameTableThroughStaticCall($statement); } } } private function alterTable(PhpParser\Node\Expr\StaticCall|PhpParser\Node\Expr\MethodCall $call, bool $creating): void { if (! isset($call->args[0]) || ! $call->getArgs()[0]->value instanceof PhpParser\Node\Scalar\String_ ) { return; } $tableName = $call->getArgs()[0]->value->value; if ($creating) { $this->tables[$tableName] = new SchemaTable($tableName); } if (! isset($call->args[1]) || ! $call->getArgs()[1]->value instanceof PhpParser\Node\Expr\Closure || count($call->getArgs()[1]->value->params) < 1 || ($call->getArgs()[1]->value->params[0]->type instanceof PhpParser\Node\Name && $call->getArgs()[1]->value->params[0]->type->toCodeString() !== '\\Illuminate\Database\Schema\Blueprint') ) { return; } $updateClosure = $call->getArgs()[1]->value; if ($call->getArgs()[1]->value->params[0]->var instanceof PhpParser\Node\Expr\Variable && is_string($call->getArgs()[1]->value->params[0]->var->name) ) { $argName = $call->getArgs()[1]->value->params[0]->var->name; $this->processColumnUpdates($tableName, $argName, $updateClosure->stmts); } } /** * @param string $tableName * @param string $argName * @param PhpParser\Node\Stmt[] $stmts * * @throws \Exception */ private function processColumnUpdates(string $tableName, string $argName, array $stmts): void { if (! isset($this->tables[$tableName])) { return; } $table = $this->tables[$tableName]; 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 ) { $rootVar = $stmt->expr; $firstMethodCall = $rootVar; $nullable = false; while ($rootVar instanceof PhpParser\Node\Expr\MethodCall) { if ($rootVar->name instanceof PhpParser\Node\Identifier && $rootVar->name->name === 'nullable' ) { $nullable = true; } $firstMethodCall = $rootVar; $rootVar = $rootVar->var; } if ($rootVar instanceof PhpParser\Node\Expr\Variable && $rootVar->name === $argName && $firstMethodCall->name instanceof PhpParser\Node\Identifier ) { $firstArg = $firstMethodCall->getArgs()[0]->value ?? null; $secondArg = $firstMethodCall->getArgs()[1]->value ?? null; if ($firstMethodCall->name->name === 'foreignIdFor') { if ($firstArg instanceof PhpParser\Node\Expr\ClassConstFetch && $firstArg->class instanceof PhpParser\Node\Name ) { $modelClass = $firstArg->class->toCodeString(); } elseif ($firstArg instanceof PhpParser\Node\Scalar\String_) { $modelClass = $firstArg->value; } else { continue; } $columnName = Str::snake(class_basename($modelClass)).'_id'; if ($secondArg instanceof PhpParser\Node\Scalar\String_) { $columnName = $secondArg->value; } $table->setColumn(new SchemaColumn($columnName, 'int', $nullable)); continue; } if (! $firstArg instanceof PhpParser\Node\Scalar\String_) { if ($firstMethodCall->name->name === 'timestamps' || $firstMethodCall->name->name === 'timestampsTz' || $firstMethodCall->name->name === 'nullableTimestamps' || $firstMethodCall->name->name === 'nullableTimestampsTz' || $firstMethodCall->name->name === 'rememberToken' ) { switch (strtolower($firstMethodCall->name->name)) { case 'droptimestamps': case 'droptimestampstz': $table->dropColumn('created_at'); $table->dropColumn('updated_at'); break; case 'remembertoken': $table->setColumn(new SchemaColumn('remember_token', 'string', $nullable)); break; case 'dropremembertoken': $table->dropColumn('remember_token'); break; case 'timestamps': case 'timestampstz': case 'nullabletimestamps': $table->setColumn(new SchemaColumn('created_at', 'string', true)); $table->setColumn(new SchemaColumn('updated_at', 'string', true)); break; } continue; } if ($firstMethodCall->name->name === 'softDeletes' || $firstMethodCall->name->name === 'softDeletesTz' || $firstMethodCall->name->name === 'dropSoftDeletes' || $firstMethodCall->name->name === 'dropSoftDeletesTz' ) { $columnName = 'deleted_at'; } else { continue; } } else { $columnName = $firstArg->value; } $secondArgArray = null; if ($secondArg instanceof PhpParser\Node\Expr\Array_) { $secondArgArray = []; foreach ($secondArg->items as $array_item) { if ($array_item !== null && $array_item->value instanceof PhpParser\Node\Scalar\String_) { $secondArgArray[] = $array_item->value->value; } } } switch (strtolower($firstMethodCall->name->name)) { case 'biginteger': case 'increments': case 'integer': case 'integerincrements': case 'mediumincrements': case 'mediuminteger': case 'smallincrements': case 'smallinteger': case 'tinyincrements': case 'tinyinteger': case 'unsignedbiginteger': case 'unsignedinteger': case 'unsignedmediuminteger': case 'unsignedsmallinteger': case 'unsignedtinyinteger': case 'bigincrements': case 'foreignid': $table->setColumn(new SchemaColumn($columnName, 'int', $nullable)); break; case 'char': case 'datetimetz': case 'date': case 'datetime': case 'ipaddress': case 'json': case 'jsonb': case 'linestring': case 'longtext': case 'macaddress': case 'mediumtext': case 'multilinestring': case 'string': case 'text': case 'time': case 'timestamp': case 'uuid': case 'binary': $table->setColumn(new SchemaColumn($columnName, 'string', $nullable)); break; case 'boolean': $table->setColumn(new SchemaColumn($columnName, 'bool', $nullable)); break; case 'geometry': case 'geometrycollection': case 'multipoint': case 'multipolygon': case 'multipolygonz': case 'point': case 'polygon': case 'computed': $table->setColumn(new SchemaColumn($columnName, 'mixed', $nullable)); break; case 'double': case 'float': case 'unsigneddecimal': case 'decimal': $table->setColumn(new SchemaColumn($columnName, 'float', $nullable)); break; case 'after': if ($secondArg instanceof PhpParser\Node\Expr\Closure && $secondArg->params[0]->var instanceof PhpParser\Node\Expr\Variable && ! ($secondArg->params[0]->var->name instanceof PhpParser\Node\Expr)) { $argName = $secondArg->params[0]->var->name; $this->processColumnUpdates($tableName, $argName, $secondArg->stmts); } break; case 'dropcolumn': case 'dropifexists': case 'dropsoftdeletes': case 'dropsoftdeletestz': case 'removecolumn': case 'drop': $table->dropColumn($columnName); break; case 'dropforeign': case 'dropindex': case 'dropprimary': case 'dropunique': case 'foreign': case 'index': case 'primary': case 'renameindex': case 'spatialIndex': case 'unique': case 'dropspatialindex': break; case 'dropmorphs': $table->dropColumn($columnName.'_type'); $table->dropColumn($columnName.'_id'); break; case 'enum': $table->setColumn(new SchemaColumn($columnName, 'enum', $nullable, $secondArgArray)); break; case 'morphs': $table->setColumn(new SchemaColumn($columnName.'_type', 'string', $nullable)); $table->setColumn(new SchemaColumn($columnName.'_id', 'int', $nullable)); break; case 'nullablemorphs': $table->setColumn(new SchemaColumn($columnName.'_type', 'string', true)); $table->setColumn(new SchemaColumn($columnName.'_id', 'int', true)); break; case 'nullableuuidmorphs': $table->setColumn(new SchemaColumn($columnName.'_type', 'string', true)); $table->setColumn(new SchemaColumn($columnName.'_id', 'string', true)); break; case 'rename': $this->renameTableThroughMethodCall($table, $stmt->expr); break; case 'renamecolumn': if ($secondArg instanceof PhpParser\Node\Scalar\String_) { $table->renameColumn($columnName, $secondArg->value); } break; case 'set': $table->setColumn(new SchemaColumn($columnName, 'set', $nullable, $secondArgArray)); break; case 'softdeletestz': case 'timestamptz': case 'timetz': case 'year': case 'softdeletes': $table->setColumn(new SchemaColumn($columnName, 'string', true)); break; case 'uuidmorphs': $table->setColumn(new SchemaColumn($columnName.'_type', 'string', $nullable)); $table->setColumn(new SchemaColumn($columnName.'_id', 'string', $nullable)); break; default: // We know a property exists with a name, we just don't know its type. $table->setColumn(new SchemaColumn($columnName, 'mixed', $nullable)); break; } } } } } private function dropTable(PhpParser\Node\Expr\StaticCall|PhpParser\Node\Expr\MethodCall $call): void { if (! isset($call->args[0]) || ! $call->getArgs()[0]->value instanceof PhpParser\Node\Scalar\String_ ) { return; } $tableName = $call->getArgs()[0]->value->value; unset($this->tables[$tableName]); } private function renameTableThroughStaticCall(PhpParser\Node\Expr\StaticCall|PhpParser\Node\Expr\MethodCall $call): void { if (! isset($call->args[0], $call->args[1]) || ! $call->getArgs()[0]->value instanceof PhpParser\Node\Scalar\String_ || ! $call->getArgs()[1]->value instanceof PhpParser\Node\Scalar\String_ ) { return; } $oldTableName = $call->getArgs()[0]->value->value; $newTableName = $call->getArgs()[1]->value->value; $this->renameTable($oldTableName, $newTableName); } private function renameTableThroughMethodCall(SchemaTable $oldTable, PhpParser\Node\Expr\MethodCall $call): void { if (! isset($call->args[0]) || ! $call->getArgs()[0]->value instanceof PhpParser\Node\Scalar\String_ ) { return; } /** @var PhpParser\Node\Scalar\String_ $methodCallArgument */ $methodCallArgument = $call->getArgs()[0]->value; $oldTableName = $oldTable->name; $newTableName = $methodCallArgument->value; $this->renameTable($oldTableName, $newTableName); } private function renameTable(string $oldTableName, string $newTableName): void { if (! isset($this->tables[$oldTableName])) { return; } $table = $this->tables[$oldTableName]; unset($this->tables[$oldTableName]); $table->name = $newTableName; $this->tables[$newTableName] = $table; } }