Skip to content
Merged
Show file tree
Hide file tree
Changes from 8 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .github/workflows/build-ci-atlas.yml
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ jobs:
- "8.4"
laravel:
- "11.*"
- "12.*"

steps:
- uses: "actions/checkout@v4"
Expand Down
7 changes: 3 additions & 4 deletions .github/workflows/build-ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -28,19 +28,18 @@ jobs:
laravel:
- "10.*"
- "11.*"
- "12.*"
include:
- php: "8.1"
laravel: "10.*"
mongodb: "5.0"
mode: "low-deps"
os: "ubuntu-latest"
- php: "8.4"
laravel: "11.*"
mongodb: "7.0"
os: "ubuntu-latest"
Comment on lines -37 to -40
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This was duplicating an existing case.

exclude:
- php: "8.1"
laravel: "11.*"
- php: "8.1"
laravel: "12.*"

steps:
- uses: "actions/checkout@v4"
Expand Down
14 changes: 7 additions & 7 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -25,11 +25,11 @@
"php": "^8.1",
"ext-mongodb": "^1.15",
"composer-runtime-api": "^2.0.0",
"illuminate/cache": "^10.36|^11",
"illuminate/container": "^10.0|^11",
"illuminate/database": "^10.30|^11",
"illuminate/events": "^10.0|^11",
"illuminate/support": "^10.0|^11",
"illuminate/cache": "^10.36|^11|^12",
"illuminate/container": "^10.0|^11|^12",
"illuminate/database": "^10.30|^11|^12",
"illuminate/events": "^10.0|^11|^12",
"illuminate/support": "^10.0|^11|^12",
"mongodb/mongodb": "^1.21",
"symfony/http-foundation": "^6.4|^7"
},
Expand All @@ -38,8 +38,8 @@
"league/flysystem-gridfs": "^3.28",
"league/flysystem-read-only": "^3.0",
"phpunit/phpunit": "^10.3|^11.5.3",
"orchestra/testbench": "^8.0|^9.0",
"mockery/mockery": "^1.4.4@stable",
"orchestra/testbench": "^8.0|^9.0|^10.0",
"mockery/mockery": "^1.4.4",
"doctrine/coding-standard": "12.0.x-dev",
"spatie/laravel-query-builder": "^5.6|^6",
"phpstan/phpstan": "^1.10",
Expand Down
10 changes: 10 additions & 0 deletions phpstan-baseline.neon
Original file line number Diff line number Diff line change
@@ -1,5 +1,15 @@
parameters:
ignoreErrors:
-
message: "#^Class MongoDB\\\\Laravel\\\\Query\\\\Grammar does not have a constructor and must be instantiated without any parameters\\.$#"
count: 1
path: src/Connection.php

-
message: "#^Class MongoDB\\\\Laravel\\\\Schema\\\\Grammar does not have a constructor and must be instantiated without any parameters\\.$#"
count: 1
path: src/Connection.php

Comment on lines +3 to +12
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It tried using the @phpstan-ignore new.noConstructor in the code, but that triggers an other error ignore.unmatchedIdentifier on Laravel 12, where the constructor has this parameter.

-
message: "#^Access to an undefined property Illuminate\\\\Container\\\\Container\\:\\:\\$config\\.$#"
count: 3
Expand Down
6 changes: 4 additions & 2 deletions src/Connection.php
Original file line number Diff line number Diff line change
Expand Up @@ -355,13 +355,15 @@ protected function getDefaultPostProcessor()
/** @inheritdoc */
protected function getDefaultQueryGrammar()
{
return new Query\Grammar();
// Argument added in Laravel 12
return new Query\Grammar($this);
}

/** @inheritdoc */
protected function getDefaultSchemaGrammar()
{
return new Schema\Grammar();
// Argument added in Laravel 12
return new Schema\Grammar($this);
Comment on lines +358 to +366
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

}

/**
Expand Down
29 changes: 21 additions & 8 deletions src/Schema/Blueprint.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,11 @@

namespace MongoDB\Laravel\Schema;

use Closure;
use Illuminate\Database\Connection;
use Illuminate\Database\Schema\Blueprint as SchemaBlueprint;
use MongoDB\Collection;
use ReflectionMethod;

use function array_flip;
use function implode;
Expand All @@ -18,19 +20,20 @@

class Blueprint extends SchemaBlueprint
{
private static bool $hasConnectionInConstructor;

/**
* The MongoConnection object for this blueprint.
*
* @var Connection
* The MongoDB connection object for this blueprint.
*/
protected $connection;
protected Connection $connection;

/**
* The Collection object for this blueprint.
* The MongoDB collection object for this blueprint.
* Type added in Laravel 12.
*
* @var Collection
*/
protected $collection;
protected Collection $collection;

/**
* Fluent columns.
Expand All @@ -42,9 +45,19 @@ class Blueprint extends SchemaBlueprint
/**
* Create a new schema blueprint.
*/
public function __construct(Connection $connection, string $collection)
public function __construct(Connection $connection, string $collection, ?Closure $callback = null)
{
parent::__construct($collection);
// Parent constructor signature was changed in Laravel 12
// https://github.com/laravel/framework/commit/f29df4740d724f1c36385c9989569e3feb9422df#diff-68f714a9f1b751481b993414d3f1300ad55bcef12084ec0eb8f47f350033c24bR107
self::$hasConnectionInConstructor ??= (new ReflectionMethod(parent::class, '__construct'))->getParameters()[0]->getName() === 'connection';

if (self::$hasConnectionInConstructor) {
// Laravel 12 and after
parent::__construct($connection, $collection, $callback);
} else {
// Laravel 11 and before
parent::__construct($collection, $callback);
}

$this->connection = $connection;

Expand Down
37 changes: 32 additions & 5 deletions src/Schema/Builder.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
use Closure;
use MongoDB\Collection;
use MongoDB\Driver\Exception\ServerException;
use MongoDB\Laravel\Connection;
use MongoDB\Model\CollectionInfo;
use MongoDB\Model\IndexInfo;

Expand All @@ -16,18 +17,22 @@
use function array_keys;
use function array_map;
use function array_merge;
use function array_values;
use function assert;
use function count;
use function current;
use function implode;
use function in_array;
use function is_array;
use function is_string;
use function iterator_to_array;
use function sort;
use function sprintf;
use function str_ends_with;
use function substr;
use function usort;

/** @property Connection $connection */
class Builder extends \Illuminate\Database\Schema\Builder
{
/**
Expand Down Expand Up @@ -137,9 +142,10 @@ public function dropAllTables()
}
}

public function getTables()
/** @param string|null $schema Database name */
public function getTables($schema = null)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are the signature changes here also a potential BC break for Laravel 11 users, or would you not expect anyone to extend this class?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, this is a breaking change if someone extends our class... I hope nobody does. We should make more classes final.

{
$db = $this->connection->getDatabase();
$db = $this->connection->getDatabase($schema);
$collections = [];

foreach ($db->listCollectionNames() as $collectionName) {
Expand All @@ -150,7 +156,8 @@ public function getTables()

$collections[] = [
'name' => $collectionName,
'schema' => null,
'schema' => $db->getDatabaseName(),
'schema_qualified_name' => $db->getDatabaseName() . '.' . $collectionName,
'size' => $stats[0]?->storageStats?->totalSize ?? null,
'comment' => null,
'collation' => null,
Expand All @@ -165,9 +172,29 @@ public function getTables()
return $collections;
}

public function getTableListing()
/**
* @param string|null $schema
* @param bool $schemaQualified If a schema is provided, prefix the collection names with the schema name
*
* @return array
*/
public function getTableListing($schema = null, $schemaQualified = false)
{
$collections = iterator_to_array($this->connection->getDatabase()->listCollectionNames());
$collections = [];

if ($schema === null || is_string($schema)) {
$collections[$schema ?? 0] = iterator_to_array($this->connection->getDatabase($schema)->listCollectionNames());
} elseif (is_array($schema)) {
foreach ($schema as $db) {
$collections[$db] = iterator_to_array($this->connection->getDatabase($db)->listCollectionNames());
}
}

if ($schema && $schemaQualified) {
$collections = array_map(fn ($db, $collections) => array_map(static fn ($collection) => $db . '.' . $collection, $collections), array_keys($collections), $collections);
}

$collections = array_merge(...array_values($collections));
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If $schemaQualified is false and the database name is never prepended to yield full namespaces, would this statement potentially clobber collection names?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, but that's how the feature is designed.


sort($collections);

Expand Down
2 changes: 1 addition & 1 deletion tests/Query/BuilderTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -1605,7 +1605,7 @@ private static function getBuilder(): Builder
$connection = m::mock(Connection::class);
$processor = m::mock(Processor::class);
$connection->shouldReceive('getSession')->andReturn(null);
$connection->shouldReceive('getQueryGrammar')->andReturn(new Grammar());
$connection->shouldReceive('getQueryGrammar')->andReturn(new Grammar($connection));

return new Builder($connection, null, $processor);
}
Expand Down
1 change: 1 addition & 0 deletions tests/RelationsTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ public function tearDown(): void
Photo::truncate();
Label::truncate();
Skill::truncate();
Soft::truncate();
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This was a latent bug when the test suite was run in a particular order, MassPrunableTest::testPruneSoftDelete failed.


parent::tearDown();
}
Expand Down
26 changes: 26 additions & 0 deletions tests/SchemaTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -395,6 +395,7 @@ public function testGetTables()
{
DB::connection('mongodb')->table('newcollection')->insert(['test' => 'value']);
DB::connection('mongodb')->table('newcollection_two')->insert(['test' => 'value']);
$dbName = DB::connection('mongodb')->getDatabaseName();

$tables = Schema::getTables();
$this->assertIsArray($tables);
Expand All @@ -403,9 +404,13 @@ public function testGetTables()
foreach ($tables as $table) {
$this->assertArrayHasKey('name', $table);
$this->assertArrayHasKey('size', $table);
$this->assertArrayHasKey('schema', $table);
$this->assertArrayHasKey('schema_qualified_name', $table);

if ($table['name'] === 'newcollection') {
$this->assertEquals(8192, $table['size']);
$this->assertEquals($dbName, $table['schema']);
$this->assertEquals($dbName . '.newcollection', $table['schema_qualified_name']);
$found = true;
}
}
Expand All @@ -428,6 +433,27 @@ public function testGetTableListing()
$this->assertContains('newcollection_two', $tables);
}

public function testGetTableListingBySchema()
{
DB::connection('mongodb')->table('newcollection')->insert(['test' => 'value']);
DB::connection('mongodb')->table('newcollection_two')->insert(['test' => 'value']);
$dbName = DB::connection('mongodb')->getDatabaseName();

$tables = Schema::getTableListing([$dbName, 'database__that_does_not_exists'], schemaQualified: true);

$this->assertIsArray($tables);
$this->assertGreaterThanOrEqual(2, count($tables));
$this->assertContains($dbName . '.newcollection', $tables);
$this->assertContains($dbName . '.newcollection_two', $tables);

$tables = Schema::getTableListing([$dbName, 'database__that_does_not_exists'], schemaQualified: false);

$this->assertIsArray($tables);
$this->assertGreaterThanOrEqual(2, count($tables));
$this->assertContains('newcollection', $tables);
$this->assertContains('newcollection_two', $tables);
}

public function testGetColumns()
{
$collection = DB::connection('mongodb')->table('newcollection');
Expand Down
Loading