Skip to content

Commit

Permalink
Remove Doctrine DBAL from SchemaManager
Browse files Browse the repository at this point in the history
  • Loading branch information
bobbyiliev committed Sep 23, 2024
1 parent b42d57a commit 984fd41
Show file tree
Hide file tree
Showing 11 changed files with 129 additions and 108 deletions.
2 changes: 1 addition & 1 deletion docs/bread/formfields/date-time.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,4 @@
}
```

The date & timestamp input field is where you can input a date. In the JSON above you can specify the `format` value of the output of the date. It allows you to display a formatted `date` in browse and read views, using Carbon's `formatLocalized()` method
The date & timestamp input field is where you can input a date. In the JSON above you can specify the `format` value of the output of the date. It allows you to display a formatted `date` in browse and read views, using Carbon's `format()` method
2 changes: 1 addition & 1 deletion migrations/2017_11_26_015000_create_user_roles_table.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ class CreateUserRolesTable extends Migration
public function up()
{
Schema::create('user_roles', function (Blueprint $table) {
$type = DB::connection()->getDoctrineColumn(DB::getTablePrefix().'users', 'id')->getType()->getName();
$type = DB::connection()->getSchemaBuilder()->getColumnType('users', 'id');
if ($type == 'bigint') {
$table->bigInteger('user_id')->unsigned()->index();
} else {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,6 @@ class AlterPostNullableFieldsTable extends Migration
*/
public function up()
{
$platform = \DB::getDoctrineSchemaManager()->getDatabasePlatform();
$platform->registerDoctrineTypeMapping('enum', 'string');

Schema::table('posts', function (Blueprint $table) {
$table->text('excerpt')->nullable()->change();
$table->text('meta_description')->nullable()->change();
Expand All @@ -31,9 +28,9 @@ public function up()
public function down()
{
Schema::table('posts', function (Blueprint $table) {
$table->text('excerpt')->change();
$table->text('meta_description')->change();
$table->text('meta_keywords')->change();
$table->text('excerpt')->nullable(false)->change();
$table->text('meta_description')->nullable(false)->change();
$table->text('meta_keywords')->nullable(false)->change();
});
}
}
2 changes: 1 addition & 1 deletion resources/views/bread/browse.blade.php
Original file line number Diff line number Diff line change
Expand Up @@ -163,7 +163,7 @@

@elseif($row->type == 'date' || $row->type == 'timestamp')
@if ( property_exists($row->details, 'format') && !is_null($data->{$row->field}) )
{{ \Carbon\Carbon::parse($data->{$row->field})->formatLocalized($row->details->format) }}
{{ \Carbon\Carbon::parse($data->{$row->field})->format('Y-m-d H:i:s') }}
@else
{{ $data->{$row->field} }}
@endif
Expand Down
2 changes: 1 addition & 1 deletion resources/views/bread/read.blade.php
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@
@endif
@elseif($row->type == 'date' || $row->type == 'timestamp')
@if ( property_exists($row->details, 'format') && !is_null($dataTypeContent->{$row->field}) )
{{ \Carbon\Carbon::parse($dataTypeContent->{$row->field})->formatLocalized($row->details->format) }}
{{ \Carbon\Carbon::parse($dataTypeContent->{$row->field})->format('Y-m-d H:i:s') }}
@else
{{ $dataTypeContent->{$row->field} }}
@endif
Expand Down
161 changes: 88 additions & 73 deletions src/Database/Schema/SchemaManager.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,28 +2,26 @@

namespace TCG\Voyager\Database\Schema;

use Doctrine\DBAL\Schema\SchemaException;
use Doctrine\DBAL\Schema\Table as DoctrineTable;
use Illuminate\Support\Facades\DB;
use TCG\Voyager\Database\Types\Type;
use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Collection;

abstract class SchemaManager
{
// todo: trim parameters

public static function __callStatic($method, $args)
{
return static::manager()->$method(...$args);
}

public static function manager()
{
return DB::connection()->getDoctrineSchemaManager();
return DB::connection();
}

public static function getDatabaseConnection()
{
return DB::connection()->getDoctrineConnection();
return DB::connection();
}

public static function tableExists($table)
Expand All @@ -32,112 +30,129 @@ public static function tableExists($table)
$table = [$table];
}

return static::manager()->tablesExist($table);
return Schema::hasTable($table[0]);
}

public static function listTables()
{
$tables = [];
$tableNames = Schema::getConnection()->getSchemaBuilder()->getTables();

foreach (static::manager()->listTableNames() as $tableName) {
foreach ($tableNames as $tableName) {
$tables[$tableName] = static::listTableDetails($tableName);
}

return $tables;
}

/**
* @param string $tableName
*
* @return \TCG\Voyager\Database\Schema\Table
*/
public static function listTableDetails($tableName)
{
$columns = static::manager()->listTableColumns($tableName);

$foreignKeys = [];
if (static::manager()->getDatabasePlatform()->supportsForeignKeyConstraints()) {
$foreignKeys = static::manager()->listTableForeignKeys($tableName);
}
$columns = Schema::getColumnListing($tableName);
$columnDetails = collect($columns)->mapWithKeys(function ($column) use ($tableName) {
return [$column => static::getColumnDetails($tableName, $column)];
});

$indexes = static::manager()->listTableIndexes($tableName);
$indexes = static::getTableIndexes($tableName);
$foreignKeys = static::getTableForeignKeys($tableName);

return new Table($tableName, $columns, $indexes, [], $foreignKeys, []);
return new Table($tableName, $columnDetails->toArray(), $indexes, [], $foreignKeys, []);
}

/**
* Describes given table.
*
* @param string $tableName
*
* @return \Illuminate\Support\Collection
*/
public static function describeTable($tableName)
{
Type::registerCustomPlatformTypes();

$table = static::listTableDetails($tableName);

return collect($table->columns)->map(function ($column) use ($table) {
$columnArr = Column::toArray($column);
$columns = Schema::getColumnListing($tableName);

return collect($columns)->map(function ($column) use ($tableName) {
$columnDetails = static::getColumnDetails($tableName, $column);
$indexes = static::getColumnIndexes($tableName, $column);

return [
'field' => $column,
'type' => $columnDetails['type'],
'null' => $columnDetails['nullable'],
'key' => $indexes ? substr($indexes[0]['type'], 0, 3) : null,
'default' => $columnDetails['default'],
'extra' => $columnDetails['auto_increment'] ? 'auto_increment' : '',
'indexes' => $indexes,
];
});
}

$columnArr['field'] = $columnArr['name'];
$columnArr['type'] = $columnArr['type']['name'];
public static function listTableColumnNames($tableName)
{
return Schema::getColumnListing($tableName);
}

// Set the indexes and key
$columnArr['indexes'] = [];
$columnArr['key'] = null;
if ($columnArr['indexes'] = $table->getColumnsIndexes($columnArr['name'], true)) {
// Convert indexes to Array
foreach ($columnArr['indexes'] as $name => $index) {
$columnArr['indexes'][$name] = Index::toArray($index);
public static function createTable($table)
{
if ($table instanceof Blueprint) {
Schema::create($table->getTable(), function (Blueprint $blueprint) use ($table) {
foreach ($table->getColumns() as $column) {
$blueprint->addColumn(
$column->getType()->getName(),
$column->getName(),
$column->toArray()
);
}

// If there are multiple indexes for the column
// the Key will be one with highest priority
$indexType = array_values($columnArr['indexes'])[0]['type'];
$columnArr['key'] = substr($indexType, 0, 3);
}

return $columnArr;
});
});
} else {
throw new \InvalidArgumentException('Table must be an instance of Blueprint');
}
}

public static function listTableColumnNames($tableName)
protected static function getColumnDetails($table, $column)
{
Type::registerCustomPlatformTypes();
$schema = Schema::getConnection()->getSchemaBuilder();
$columnType = $schema->getColumnType($table, $column);
$columnDefinition = $schema->getColumns($table);

$columnNames = [];
$columnInfo = collect($columnDefinition)->firstWhere('name', $column);

foreach (static::manager()->listTableColumns($tableName) as $column) {
$columnNames[] = $column->getName();
if (!$columnInfo) {
throw new \InvalidArgumentException("Column '$column' not found in table '$table'.");
}

return $columnNames;
return [
'type' => $columnType,
'nullable' => !($columnInfo['nullable'] ?? false),
'default' => $columnInfo['default'] ?? null,
'auto_increment' => ($columnInfo['auto_increment'] ?? false),
];
}

public static function createTable($table)
protected static function getTableIndexes($table)
{
if (!($table instanceof DoctrineTable)) {
$table = Table::make($table);
}
return DB::getSchemaBuilder()->getIndexes($table);
}

static::manager()->createTable($table);
protected static function getColumnIndexes($table, $column)
{
$tableIndexes = static::getTableIndexes($table);
return collect($tableIndexes)->filter(function ($index) use ($column) {
return in_array($column, $index['columns']);
})->toArray();
}

protected static function getTableForeignKeys($table)
{
return DB::getSchemaBuilder()->getForeignKeys($table);
}

public static function getDoctrineTable($table)
public static function listTableNames()
{
$table = trim($table);
$connection = Schema::getConnection();

if (!static::tableExists($table)) {
throw SchemaException::tableDoesNotExist($table);
// Check if the connection supports the getTables method
if (method_exists($connection->getSchemaBuilder(), 'getTables')) {
$tables = $connection->getSchemaBuilder()->getTables();
return collect($tables)->pluck('name')->values()->all();
}

return static::manager()->listTableDetails($table);
}
// Fallback method if getTables is not available
$tables = $connection->getDoctrineSchemaManager()->listTableNames();

public static function getDoctrineColumn($table, $column)
{
return static::getDoctrineTable($table)->getColumn($column);
// Filter out tables that should be excluded (like migrations)
$excludedTables = ['migrations', 'failed_jobs', 'password_resets'];
return array_values(array_diff($tables, $excludedTables));
}
}
31 changes: 15 additions & 16 deletions src/Database/Types/Type.php
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ abstract class Type extends DoctrineType
protected static $platformTypes = [];
protected static $customTypeOptions = [];
protected static $typeCategories = [];
protected static $registeredTypes = [];

public const NAME = 'UNDEFINED_TYPE_NAME';
public const NOT_SUPPORTED = 'notSupported';
Expand Down Expand Up @@ -48,15 +49,15 @@ public static function getPlatformTypes()
static::registerCustomPlatformTypes();
}

$platform = SchemaManager::getDatabasePlatform();
$platform = SchemaManager::getDatabaseConnection()->getDriverName();

static::$platformTypes = Platform::getPlatformTypes(
$platform->getName(),
static::getPlatformTypeMapping($platform)
$platform,
static::getPlatformTypeMapping()
);

static::$platformTypes = static::$platformTypes->map(function ($type) {
return static::toArray(static::getType($type));
return static::toArray(new $type());
})->groupBy('category');

return static::$platformTypes;
Expand All @@ -81,8 +82,8 @@ public static function registerCustomPlatformTypes($force = false)
return;
}

$platform = SchemaManager::getDatabasePlatform();
$platformName = ucfirst($platform->getName());
$platform = SchemaManager::getDatabaseConnection()->getDriverName();
$platformName = ucfirst($platform);

$customTypes = array_merge(
static::getPlatformCustomTypes('Common'),
Expand All @@ -91,16 +92,9 @@ public static function registerCustomPlatformTypes($force = false)

foreach ($customTypes as $type) {
$name = $type::NAME;

if (static::hasType($name)) {
static::overrideType($name, $type);
} else {
static::addType($name, $type);
}

$dbType = defined("{$type}::DBTYPE") ? $type::DBTYPE : $name;

$platform->registerDoctrineTypeMapping($dbType, $name);
// Instead of overriding or adding Doctrine types,
// you might want to register these types in your own type registry
static::registerType($name, $type);
}

static::addCustomTypeOptions($platformName);
Expand Down Expand Up @@ -330,4 +324,9 @@ public static function getTypeCategories()

return static::$typeCategories;
}

public static function registerType($name, $typeClass)
{
static::$registeredTypes[$name] = $typeClass;
}
}
2 changes: 1 addition & 1 deletion src/Http/Controllers/VoyagerDatabaseController.php
Original file line number Diff line number Diff line change
Expand Up @@ -190,7 +190,7 @@ protected function prepareDbManager($action, $table = '')
$db->oldTable = $oldTable ? $oldTable : json_encode(null);
$db->action = $action;
$db->identifierRegex = Identifier::REGEX;
$db->platform = SchemaManager::getDatabasePlatform()->getName();
$db->platform = DB::connection()->getDriverName();

return $db;
}
Expand Down
12 changes: 10 additions & 2 deletions tests/TestCase.php
Original file line number Diff line number Diff line change
Expand Up @@ -53,9 +53,17 @@ protected function getPackageProviders($app)

public function tearDown(): void
{
//parent::tearDown();
// Restore default exception handler
$this->app->forgetInstance(ExceptionHandler::class);

//$this->artisan('migrate:reset');
// Restore PHP's default error and exception handlers
restore_error_handler();
restore_exception_handler();

parent::tearDown();

// Uncomment if you want to reset the database after each test
// $this->artisan('migrate:reset');
}

/**
Expand Down
Loading

0 comments on commit 984fd41

Please sign in to comment.