Skip to content

Commit

Permalink
Merge pull request #5457 from Laravel-Backpack/l11
Browse files Browse the repository at this point in the history
Add Laravel 11 support
  • Loading branch information
pxpm authored Mar 14, 2024
2 parents cf8535a + 8f4d4f5 commit d81b4d7
Show file tree
Hide file tree
Showing 12 changed files with 220 additions and 60 deletions.
19 changes: 14 additions & 5 deletions .github/workflows/testing.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,16 @@ jobs:
# run all combinations of the following, to make sure they're working together
matrix:
# os: [ubuntu-latest, macos-latest, windows-latest]
php: [8.1, 8.2, 8.3]
php: ['8.1', '8.2', '8.3']
laravel: [^10.0, ^11.0]
dbal: [^3.0]
laravel: [10.*]
phpunit: [10.*]
dependency-version: [stable] # to add: lowest

dependency-version: [stable] # to add: lowest
exclude:
- laravel: "^11.0"
php: "8.1"
dbal: "^3.0"


name: PHP ${{ matrix.php }}, Laravel ${{ matrix.laravel }}, PHPUnit ${{ matrix.phpunit }}, DBAL ${{ matrix.dbal }} --prefer-${{ matrix.dependency-version }}

Expand All @@ -49,7 +53,12 @@ jobs:
key: dependencies-${{ matrix.dependency-version }}-laravel-${{ matrix.laravel }}-php-${{ matrix.php }}-phpunit-${{ matrix.phpunit }}-composer-${{ hashFiles('composer.json') }}
- name: Install dependencies
run: |
composer require "laravel/framework:${{ matrix.laravel }}" "phpunit/phpunit:${{ matrix.phpunit }}" "doctrine/dbal:${{ matrix.dbal }}" --no-interaction --no-update
composer require "laravel/framework:${{ matrix.laravel }}" "phpunit/phpunit:${{ matrix.phpunit }}" --no-interaction --no-update
composer update --prefer-${{ matrix.dependency-version }} --prefer-dist --no-interaction
- name: "Install dbal"
if: ${{ matrix.laravel }} == 10
run: composer require "doctrine/dbal:${{ matrix.dbal }}" --no-interaction --no-update
- name: "Update dependencies"
run: composer update --prefer-${{ matrix.dependency-version }} --prefer-dist --no-interaction
- name: Execute tests
run: composer test
11 changes: 5 additions & 6 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -35,17 +35,16 @@
}
],
"require": {
"laravel/framework": "^10.0",
"laravel/framework": "^10.0|^11.0",
"prologue/alerts": "^1.0",
"backpack/basset": "^1.1.1",
"backpack/basset": "^1.1.1|^1.3",
"creativeorange/gravatar": "~1.0",
"doctrine/dbal": "^3.0",
"doctrine/dbal": "^3.0|^4.0",
"guzzlehttp/guzzle": "^7.0"
},
"require-dev": {
"phpunit/phpunit": "~10.0|~9.0",
"scrutinizer/ocular": "~1.7",
"orchestra/testbench": "^8.0",
"phpunit/phpunit": "^10.0|^9.0",
"orchestra/testbench": "^8.0|^9.0|^10.0",
"spatie/laravel-translatable": "^6.0"
},
"autoload": {
Expand Down
8 changes: 3 additions & 5 deletions src/app/Library/CrudPanel/Traits/AutoSet.php
Original file line number Diff line number Diff line change
Expand Up @@ -53,8 +53,9 @@ public function getDbColumnTypes()
if (! $this->driverIsSql()) {
return $dbColumnTypes;
}
$dbColumns = $this->getDbTableColumns();

foreach ($this->getDbTableColumns() as $key => $column) {
foreach ($dbColumns as $key => $column) {
$column_type = $column->getType()->getName();
$dbColumnTypes[$column->getName()]['type'] = trim(preg_replace('/\(\d+\)(.*)/i', '', $column_type));
$dbColumnTypes[$column->getName()]['default'] = $column->getDefault();
Expand Down Expand Up @@ -87,7 +88,6 @@ public function getDbTableColumns()
if (isset($this->autoset['table_columns']) && $this->autoset['table_columns']) {
return $this->autoset['table_columns'];
}

$this->autoset['table_columns'] = $this->model::getDbTableSchema()->getColumns();

return $this->autoset['table_columns'];
Expand Down Expand Up @@ -137,10 +137,8 @@ protected function inferFieldTypeFromDbColumnType($fieldName)
// break;

case 'boolean':
return 'boolean';

case 'tinyint':
return 'active';
return 'boolean';

case 'text':
case 'mediumtext':
Expand Down
7 changes: 7 additions & 0 deletions src/app/Library/CrudPanel/Traits/Create.php
Original file line number Diff line number Diff line change
Expand Up @@ -284,6 +284,13 @@ private function handleManyRelationItemRemoval($modelInstance, $removedEntries,
// get the default that could be set at database level.
$dbColumnDefault = $modelInstance->getDbColumnDefault($relationForeignKey);

// check if the relation foreign key is in casts, and cast it to the correct type
if ($modelInstance->hasCast($relationForeignKey)) {
$dbColumnDefault = match ($modelInstance->getCasts()[$relationForeignKey]) {
'int', 'integer' => $dbColumnDefault = (int) $dbColumnDefault,
default => $dbColumnDefault = $dbColumnDefault
};
}
// if column is not nullable in database, and there is no column default (null),
// we will delete the entry from the database, otherwise it will throw and ugly DB error.
if (! $relationColumnIsNullable && $dbColumnDefault === null) {
Expand Down
82 changes: 68 additions & 14 deletions src/app/Library/Database/DatabaseSchema.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,24 @@ final class DatabaseSchema
*
* @param string $connection
* @param string $table
* @return array
*/
public static function getForTable(string $connection, string $table)
{
self::generateDatabaseSchema($connection, $table);

return self::$schema[$connection][$table] ?? [];
return self::$schema[$connection][$table] ?? null;
}

public function listTableColumnsNames(string $connection, string $table)
{
$table = self::getForTable($connection, $table);

return array_keys($table->getColumns());
}

public function listTableIndexes(string $connection, string $table)
{
return self::getIndexColumnNames($connection, $table);
}

/**
Expand All @@ -32,27 +43,70 @@ public static function getForTable(string $connection, string $table)
*/
private static function generateDatabaseSchema(string $connection, string $table)
{
if (! isset(self::$schema[$connection])) {
$rawTables = DB::connection($connection)->getDoctrineSchemaManager()->createSchema();
self::$schema[$connection] = self::mapTables($rawTables);
} else {
// check for a specific table in case it was created after schema had been generated.
if (! isset(self::$schema[$connection][$table])) {
self::$schema[$connection][$table] = DB::connection($connection)->getDoctrineSchemaManager()->listTableDetails($table);
}
if (! isset(self::$schema[$connection]) || ! isset(self::$schema[$connection][$table])) {
self::$schema[$connection] = self::mapTables($connection);
}
}

/**
* Map the tables from raw db values into an usable array.
*
* @param Doctrine\DBAL\Schema\Schema $rawTables
* @param string $connection
* @return array
*/
private static function mapTables($rawTables)
private static function mapTables(string $connection)
{
return LazyCollection::make($rawTables->getTables())->mapWithKeys(function ($table, $key) {
return [$table->getName() => $table];
return LazyCollection::make(self::getCreateSchema($connection)->getTables())->mapWithKeys(function ($table, $key) use ($connection) {
$tableName = is_array($table) ? $table['name'] : $table->getName();

if (self::$schema[$connection][$tableName] ?? false) {
return [$tableName => self::$schema[$connection][$tableName]];
}

if (is_array($table)) {
$table = new Table(self::mapTableColumns($connection, $tableName));
}

return [$tableName => $table];
})->toArray();
}

private static function getIndexColumnNames(string $connection, string $table)
{
$schemaManager = self::getSchemaManager($connection);
$indexes = method_exists($schemaManager, 'listTableIndexes') ? $schemaManager->listTableIndexes($table) : $schemaManager->getIndexes($table);

$indexes = array_map(function ($index) {
return is_array($index) ? $index['columns'] : $index->getColumns();
}, $indexes);

$indexes = \Illuminate\Support\Arr::flatten($indexes);

return array_unique($indexes);
}

private static function mapTableColumns(string $connection, string $table)
{
$indexedColumns = self::getIndexColumnNames($connection, $table);

return LazyCollection::make(self::getSchemaManager($connection)->getColumns($table))->mapWithKeys(function ($column, $key) use ($indexedColumns) {
$column['index'] = array_key_exists($column['name'], $indexedColumns) ? true : false;

return [$column['name'] => $column];
})->toArray();
}

private static function getCreateSchema(string $connection)
{
$schemaManager = self::getSchemaManager($connection);

return method_exists($schemaManager, 'createSchema') ? $schemaManager->createSchema() : $schemaManager;
}

private static function getSchemaManager(string $connection)
{
$connection = DB::connection($connection);

return method_exists($connection, 'getDoctrineSchemaManager') ? $connection->getDoctrineSchemaManager() : $connection->getSchemaBuilder();
}
}
65 changes: 65 additions & 0 deletions src/app/Library/Database/Table.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
<?php

namespace Backpack\CRUD\app\Library\Database;

final class Table
{
private array $columns;

public function __construct(array $columns = [])
{
foreach ($columns as $column) {
$this->columns[$column['name']] = new class($column)
{
public function __construct(private array $column)
{
}

public function getName()
{
return $this->column['name'];
}

public function getNotnull()
{
return ! $this->column['nullable'];
}

public function getDefault()
{
return $this->column['default'];
}

public function getType()
{
return new class($this->column)
{
public function __construct(private array $column)
{
}

public function getName()
{
return $this->column['type_name'];
}
};
}
};
}
}

public function getColumns()
{
return $this->columns;
}

public function hasColumn(string $columnName)
{
return isset($this->columns[$columnName]);
}

public function getColumn(string $columnName)
{
return $this->columns[$columnName];
}
}
2 changes: 1 addition & 1 deletion src/app/Library/Database/TableSchema.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

class TableSchema
{
/** @var Doctrine\DBAL\Schema\Table */
/** @var Doctrine\DBAL\Schema\Table|Backpack\CRUD\app\Library\Database\Table */
public $schema;

public function __construct(string $connection, string $table)
Expand Down
Loading

0 comments on commit d81b4d7

Please sign in to comment.