diff --git a/src/Illuminate/Support/Manager.php b/src/Illuminate/Support/Manager.php index 5a1052e490d0..8aa750045e5d 100755 --- a/src/Illuminate/Support/Manager.php +++ b/src/Illuminate/Support/Manager.php @@ -50,14 +50,14 @@ public function __construct(Container $container) /** * Get the default driver name. * - * @return string|null + * @return \BackedEnum|\UnitEnum|string|null */ abstract public function getDefaultDriver(); /** * Get a driver instance. * - * @param string|null $driver + * @param \BackedEnum|\UnitEnum|string|null $driver * @return mixed * * @throws \InvalidArgumentException @@ -75,56 +75,58 @@ public function driver($driver = null) // If the given driver has not been created before, we will create the instances // here and cache it so we can return it next time very quickly. If there is // already a driver created by this name, we'll just return that instance. - return $this->drivers[$driver] ??= $this->createDriver($driver); + return $this->drivers[enum_value($driver)] ??= $this->createDriver($driver); } /** * Create a new driver instance. * - * @param string $driver + * @param \BackedEnum|\UnitEnum|string $driver * @return mixed * * @throws \InvalidArgumentException */ protected function createDriver($driver) { + $driverName = enum_value($driver); + // First, we will determine if a custom driver creator exists for the given driver and // if it does not we will check for a creator method for the driver. Custom creator // callbacks allow developers to build their own "drivers" easily using Closures. - if (isset($this->customCreators[$driver])) { + if (isset($this->customCreators[$driverName])) { return $this->callCustomCreator($driver); } - $method = 'create'.Str::studly($driver).'Driver'; + $method = 'create'.Str::studly($driverName).'Driver'; if (method_exists($this, $method)) { return $this->$method(); } - throw new InvalidArgumentException("Driver [$driver] not supported."); + throw new InvalidArgumentException("Driver [$driverName] not supported."); } /** * Call a custom driver creator. * - * @param string $driver + * @param \BackedEnum|\UnitEnum|string $driver * @return mixed */ protected function callCustomCreator($driver) { - return $this->customCreators[$driver]($this->container); + return $this->customCreators[enum_value($driver)]($this->container); } /** * Register a custom driver creator Closure. * - * @param string $driver + * @param \BackedEnum|\UnitEnum|string $driver * @param \Closure $callback * @return $this */ public function extend($driver, Closure $callback) { - $this->customCreators[$driver] = $callback; + $this->customCreators[enum_value($driver)] = $callback; return $this; } diff --git a/tests/Integration/Support/Fixtures/EnumManager.php b/tests/Integration/Support/Fixtures/EnumManager.php new file mode 100644 index 000000000000..cc4a9e75d530 --- /dev/null +++ b/tests/Integration/Support/Fixtures/EnumManager.php @@ -0,0 +1,49 @@ +defaultDriver = $default; + + return $this; + } + + /** + * Get the default driver name. + * + * @return string|null + */ + public function getDefaultDriver() + { + return $this->defaultDriver; + } + + public function createMysqlDriver() + { + return new class('@mysql') + { + public function __construct(public readonly string $name) + { + } + }; + } + + public function createMariaDbDriver() + { + return new class('@mariadb') + { + public function __construct(public readonly string $name) + { + } + }; + } +} diff --git a/tests/Integration/Support/Fixtures/EnumManager/Bar.php b/tests/Integration/Support/Fixtures/EnumManager/Bar.php new file mode 100644 index 000000000000..8ab3cdcd261b --- /dev/null +++ b/tests/Integration/Support/Fixtures/EnumManager/Bar.php @@ -0,0 +1,8 @@ +app))->driver(); } + + public function testDefaultDriverCanBeUnitEnum() + { + $driver = (new EnumManager($this->app)) + ->useAsDefault(Foo::MySql) + ->driver(); + + $this->assertEquals('@mysql', $driver->name); + } + + public function testDefaultDriverCanBeBackedEnum() + { + $driver = (new EnumManager($this->app)) + ->useAsDefault(Bar::MariaDb) + ->driver(); + + $this->assertEquals('@mariadb', $driver->name); + } + + public function testExtend() + { + $manager = (new NullableManager($this->app)) + ->extend('myDriver', static fn () => new class('@my-driver') + { + public function __construct(public readonly string $name) + { + } + }); + + $concrete = $manager->driver('myDriver'); + $this->assertEquals('@my-driver', $concrete->name); + + $manager->extend('myDriver', static fn () => new class('@my-driver-overrode') + { + public function __construct(public readonly string $name) + { + } + }); + $cachedConcrete = $manager->driver('myDriver'); + $this->assertEquals('@my-driver', $cachedConcrete->name); + + $manager->forgetDrivers(); + $concrete = $manager->driver('myDriver'); + $this->assertEquals('@my-driver-overrode', $concrete->name); + } + + public function testExtendUsingEnum() + { + $concrete = (new EnumManager($this->app)) + ->useAsDefault(Bar::MariaDb) + ->extend(Bar::MariaDb, fn () => new class('@mariadb-extended') + { + public function __construct(public readonly string $name) + { + } + }) + ->driver(); + $this->assertEquals('@mariadb-extended', $concrete->name); + + $concrete = (new EnumManager($this->app)) + ->useAsDefault(Foo::MySql) + ->extend(Foo::MySql, fn () => new class('@mysql-extended') + { + public function __construct(public readonly string $name) + { + } + }) + ->driver(); + $this->assertEquals('@mysql-extended', $concrete->name); + } + + public function testOthers() + { + $manager = (new EnumManager($this->app)) + ->useAsDefault(Bar::MariaDb); + + $default = $manager->driver(); + $this->assertEquals('@mariadb', $default->name); + + $other = $manager->driver(Foo::MySql); + $this->assertEquals('@mysql', $other->name); + } }