Skip to content
5 changes: 3 additions & 2 deletions packages/auth/src/CurrentUserInitializer.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,16 @@
use Tempest\Container\DynamicInitializer;
use Tempest\Container\Tag;
use Tempest\Reflection\ClassReflector;
use UnitEnum;

final readonly class CurrentUserInitializer implements DynamicInitializer
{
public function canInitialize(ClassReflector $class, ?string $tag): bool
public function canInitialize(ClassReflector $class, null|string|UnitEnum $tag): bool
{
return $class->implements(CanAuthenticate::class);
}

public function initialize(ClassReflector $class, ?string $tag, Container $container): object
public function initialize(ClassReflector $class, null|string|UnitEnum $tag, Container $container): object
{
$user = $container->get(Authenticator::class)->currentUser();

Expand Down
5 changes: 3 additions & 2 deletions packages/cache/src/CacheInitializer.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,19 +9,20 @@
use Tempest\Container\DynamicInitializer;
use Tempest\Container\Singleton;
use Tempest\Reflection\ClassReflector;
use UnitEnum;

use function Tempest\env;
use function Tempest\Support\str;

final readonly class CacheInitializer implements DynamicInitializer
{
public function canInitialize(ClassReflector $class, ?string $tag): bool
public function canInitialize(ClassReflector $class, null|string|UnitEnum $tag): bool
{
return $class->getType()->matches(Cache::class);
}

#[Singleton]
public function initialize(ClassReflector $class, ?string $tag, Container $container): Cache
public function initialize(ClassReflector $class, null|string|UnitEnum $tag, Container $container): Cache
{
return new GenericCache(
cacheConfig: $container->get(CacheConfig::class, $tag),
Expand Down
5 changes: 3 additions & 2 deletions packages/cache/src/Testing/RestrictedCacheInitializer.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,17 +8,18 @@
use Tempest\Container\Singleton;
use Tempest\Discovery\SkipDiscovery;
use Tempest\Reflection\ClassReflector;
use UnitEnum;

#[SkipDiscovery]
final class RestrictedCacheInitializer implements DynamicInitializer
{
public function canInitialize(ClassReflector $class, ?string $tag): bool
public function canInitialize(ClassReflector $class, null|string|UnitEnum $tag): bool
{
return $class->getType()->matches(Cache::class);
}

#[Singleton]
public function initialize(ClassReflector $class, ?string $tag, Container $container): Cache
public function initialize(ClassReflector $class, null|string|UnitEnum $tag, Container $container): Cache
{
return new RestrictedCache($tag);
}
Expand Down
7 changes: 4 additions & 3 deletions packages/container/src/Container.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,15 @@
use Tempest\Reflection\ClassReflector;
use Tempest\Reflection\FunctionReflector;
use Tempest\Reflection\MethodReflector;
use UnitEnum;

interface Container
{
public function register(string $className, callable $definition): self;

public function unregister(string $className, bool $tagged = false): self;

public function singleton(string $className, mixed $definition, ?string $tag = null): self;
public function singleton(string $className, mixed $definition, null|string|UnitEnum $tag = null): self;

public function config(object $config): self;

Expand All @@ -23,9 +24,9 @@ public function config(object $config): self;
* @param class-string<TClassName> $className
* @return null|TClassName
*/
public function get(string $className, ?string $tag = null, mixed ...$params): mixed;
public function get(string $className, null|string|UnitEnum $tag = null, mixed ...$params): mixed;

public function has(string $className, ?string $tag = null): bool;
public function has(string $className, null|string|UnitEnum $tag = null): bool;

public function invoke(ClassReflector|MethodReflector|FunctionReflector|callable|string $method, mixed ...$params): mixed;

Expand Down
5 changes: 3 additions & 2 deletions packages/container/src/DynamicInitializer.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,11 @@
namespace Tempest\Container;

use Tempest\Reflection\ClassReflector;
use UnitEnum;

interface DynamicInitializer
{
public function canInitialize(ClassReflector $class, ?string $tag): bool;
public function canInitialize(ClassReflector $class, null|string|UnitEnum $tag): bool;

public function initialize(ClassReflector $class, ?string $tag, Container $container): object;
public function initialize(ClassReflector $class, null|string|UnitEnum $tag, Container $container): object;
}
21 changes: 13 additions & 8 deletions packages/container/src/GenericContainer.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
use Tempest\Reflection\ParameterReflector;
use Tempest\Reflection\TypeReflector;
use Throwable;
use UnitEnum;

final class GenericContainer implements Container
{
Expand Down Expand Up @@ -122,12 +123,12 @@ public function unregister(string $className, bool $tagged = false): self
return $this;
}

public function has(string $className, ?string $tag = null): bool
public function has(string $className, null|string|UnitEnum $tag = null): bool
{
return isset($this->definitions[$className]) || isset($this->singletons[$this->resolveTaggedName($className, $tag)]);
}

public function singleton(string $className, mixed $definition, ?string $tag = null): self
public function singleton(string $className, mixed $definition, null|string|UnitEnum $tag = null): self
{
if ($definition instanceof HasTag) {
$tag = $definition->tag;
Expand Down Expand Up @@ -156,7 +157,7 @@ public function config(object $config): self
* @param class-string<TClassName> $className
* @return null|TClassName
*/
public function get(string $className, ?string $tag = null, mixed ...$params): ?object
public function get(string $className, null|string|UnitEnum $tag = null, mixed ...$params): ?object
{
$this->resolveChain();

Expand Down Expand Up @@ -298,7 +299,7 @@ public function removeInitializer(ClassReflector|string $initializerClass): Cont
return $this;
}

private function resolve(string $className, ?string $tag = null, mixed ...$params): ?object
private function resolve(string $className, null|string|UnitEnum $tag = null, mixed ...$params): ?object
{
$class = new ClassReflector($className);

Expand Down Expand Up @@ -361,7 +362,7 @@ private function initializerForBuiltin(TypeReflector $target, string $tag): ?Ini
return null;
}

private function initializerForClass(ClassReflector $target, ?string $tag = null): null|Initializer|DynamicInitializer
private function initializerForClass(ClassReflector $target, null|string|UnitEnum $tag = null): null|Initializer|DynamicInitializer
{
// Initializers themselves can't be initialized,
// otherwise you'd end up with infinite loops
Expand Down Expand Up @@ -454,7 +455,7 @@ private function autowireDependencies(MethodReflector|FunctionReflector $method,
return $dependencies;
}

private function autowireDependency(ParameterReflector $parameter, ?string $tag, mixed $providedValue = null): mixed
private function autowireDependency(ParameterReflector $parameter, null|string|UnitEnum $tag, mixed $providedValue = null): mixed
{
$parameterType = $parameter->getType();

Expand Down Expand Up @@ -494,7 +495,7 @@ private function autowireDependency(ParameterReflector $parameter, ?string $tag,
throw $lastThrowable ?? new CannotAutowireException($this->chain, new Dependency($parameter));
}

private function autowireObjectDependency(TypeReflector $type, ?string $tag, mixed $providedValue, bool $lazy): mixed
private function autowireObjectDependency(TypeReflector $type, null|string|UnitEnum $tag, mixed $providedValue, bool $lazy): mixed
{
// If the provided value is of the right type,
// don't waste time autowiring, return it!
Expand Down Expand Up @@ -591,8 +592,12 @@ public function __clone(): void
$this->chain = $this->chain?->clone();
}

private function resolveTaggedName(string $className, ?string $tag): string
private function resolveTaggedName(string $className, null|string|UnitEnum $tag): string
{
if ($tag instanceof UnitEnum) {
$tag = $tag->name;
}

return $tag
? "{$className}#{$tag}"
: $className;
Expand Down
21 changes: 21 additions & 0 deletions packages/container/tests/ContainerTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
use Tempest\Container\Tests\Fixtures\ContainerObjectEInitializer;
use Tempest\Container\Tests\Fixtures\DependencyWithBuiltinDependencies;
use Tempest\Container\Tests\Fixtures\DependencyWithTaggedDependency;
use Tempest\Container\Tests\Fixtures\EnumTag;
use Tempest\Container\Tests\Fixtures\HasTagObject;
use Tempest\Container\Tests\Fixtures\ImplementsInterfaceA;
use Tempest\Container\Tests\Fixtures\InjectA;
Expand Down Expand Up @@ -258,6 +259,26 @@ public function test_tagged_singleton(): void
$this->assertSame('cli', $container->get(TaggedDependency::class, 'cli')->name);
}

public function test_tagged_singleton_with_enum(): void
{
$container = new GenericContainer();

$container->singleton(
TaggedDependency::class,
new TaggedDependency('web'),
tag: EnumTag::FOO,
);

$container->singleton(
TaggedDependency::class,
new TaggedDependency('cli'),
tag: EnumTag::BAR,
);

$this->assertSame('web', $container->get(TaggedDependency::class, EnumTag::FOO)->name);
$this->assertSame('cli', $container->get(TaggedDependency::class, EnumTag::BAR)->name);
}

public function test_tagged_singleton_with_initializer(): void
{
$container = new GenericContainer();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,16 @@
use Tempest\Container\DynamicInitializer;
use Tempest\Container\Tag;
use Tempest\Reflection\ClassReflector;
use UnitEnum;

final class ContainerObjectEInitializer implements DynamicInitializer
{
public function canInitialize(ClassReflector $class, ?string $tag): bool
public function canInitialize(ClassReflector $class, null|string|UnitEnum $tag): bool
{
return $class->getName() === ContainerObjectE::class;
}

public function initialize(ClassReflector $class, ?string $tag, Container $container): object
public function initialize(ClassReflector $class, null|string|UnitEnum $tag, Container $container): object
{
return new ContainerObjectE();
}
Expand Down
9 changes: 9 additions & 0 deletions packages/container/tests/Fixtures/EnumTag.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
<?php

namespace Tempest\Container\Tests\Fixtures;

enum EnumTag
{
case FOO;
case BAR;
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
use Tempest\Database\Builder\ModelDefinition;
use Tempest\Database\Builder\TableDefinition;
use Tempest\Database\Exceptions\CannotCountDistinctWithoutSpecifyingAColumn;
use Tempest\Database\OnDatabase;
use Tempest\Database\Query;
use Tempest\Database\QueryStatements\CountStatement;
use Tempest\Database\QueryStatements\WhereStatement;
Expand All @@ -17,7 +18,7 @@
*/
final class CountQueryBuilder implements BuildsQuery
{
use HasConditions;
use HasConditions, OnDatabase;

private ?ModelDefinition $modelDefinition;

Expand Down Expand Up @@ -95,7 +96,7 @@ public function toSql(): string

public function build(mixed ...$bindings): Query
{
return new Query($this->count, [...$this->bindings, ...$bindings]);
return new Query($this->count, [...$this->bindings, ...$bindings])->onDatabase($this->onDatabase);
}

private function resolveTable(string|object $model): TableDefinition
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

use Tempest\Database\Builder\ModelDefinition;
use Tempest\Database\Builder\TableDefinition;
use Tempest\Database\OnDatabase;
use Tempest\Database\Query;
use Tempest\Database\QueryStatements\DeleteStatement;
use Tempest\Database\QueryStatements\WhereStatement;
Expand All @@ -16,7 +17,7 @@
*/
final class DeleteQueryBuilder implements BuildsQuery
{
use HasConditions;
use HasConditions, OnDatabase;

private DeleteStatement $delete;

Expand Down Expand Up @@ -68,6 +69,6 @@ public function toSql(): string

public function build(mixed ...$bindings): Query
{
return new Query($this->delete, [...$this->bindings, ...$bindings]);
return new Query($this->delete, [...$this->bindings, ...$bindings])->onDatabase($this->onDatabase);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,16 +8,20 @@
use Tempest\Database\Exceptions\CannotInsertHasManyRelation;
use Tempest\Database\Exceptions\CannotInsertHasOneRelation;
use Tempest\Database\Id;
use Tempest\Database\OnDatabase;
use Tempest\Database\Query;
use Tempest\Database\QueryStatements\InsertStatement;
use Tempest\Mapper\SerializerFactory;
use Tempest\Reflection\ClassReflector;
use Tempest\Support\Arr\ImmutableArray;
use Tempest\Support\Conditions\HasConditions;

use function Tempest\Database\model;

final class InsertQueryBuilder implements BuildsQuery
{
use HasConditions, OnDatabase;

private InsertStatement $insert;

private array $after = [];
Expand Down Expand Up @@ -70,10 +74,7 @@ public function build(mixed ...$bindings): Query
$this->insert->addEntry($data);
}

return new Query(
$this->insert,
$bindings,
);
return new Query($this->insert, $bindings)->onDatabase($this->onDatabase);
}

public function then(Closure ...$callbacks): self
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,10 @@

use Closure;
use Tempest\Database\Builder\FieldDefinition;
use Tempest\Database\Builder\ModelDefinition;
use Tempest\Database\Builder\ModelInspector;
use Tempest\Database\Id;
use Tempest\Database\Mappers\SelectModelMapper;
use Tempest\Database\OnDatabase;
use Tempest\Database\Query;
use Tempest\Database\QueryStatements\FieldStatement;
use Tempest\Database\QueryStatements\JoinStatement;
Expand All @@ -19,6 +19,7 @@
use Tempest\Database\QueryStatements\WhereStatement;
use Tempest\Support\Arr\ImmutableArray;
use Tempest\Support\Conditions\HasConditions;
use UnitEnum;

use function Tempest\Database\model;
use function Tempest\map;
Expand All @@ -28,7 +29,7 @@
*/
final class SelectQueryBuilder implements BuildsQuery
{
use HasConditions;
use HasConditions, OnDatabase;

/** @var class-string<TModelClass> $modelClass */
private readonly string $modelClass;
Expand Down Expand Up @@ -225,7 +226,7 @@ public function build(mixed ...$bindings): Query
$this->select->join[] = $relation->getJoinStatement();
}

return new Query($this->select, [...$this->bindings, ...$bindings]);
return new Query($this->select, [...$this->bindings, ...$bindings])->onDatabase($this->onDatabase);
}

private function clone(): self
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
use Tempest\Database\Exceptions\CannotUpdateHasManyRelation;
use Tempest\Database\Exceptions\CannotUpdateHasOneRelation;
use Tempest\Database\Id;
use Tempest\Database\OnDatabase;
use Tempest\Database\Query;
use Tempest\Database\QueryStatements\UpdateStatement;
use Tempest\Database\QueryStatements\WhereStatement;
Expand All @@ -18,7 +19,7 @@

final class UpdateQueryBuilder implements BuildsQuery
{
use HasConditions;
use HasConditions, OnDatabase;

private UpdateStatement $update;

Expand Down Expand Up @@ -87,7 +88,7 @@ public function build(mixed ...$bindings): Query
$bindings[] = $binding;
}

return new Query($this->update, $bindings);
return new Query($this->update, $bindings)->onDatabase($this->onDatabase);
}

private function resolveValues(): ImmutableArray
Expand Down
Loading