Skip to content

Commit

Permalink
feat: repository configuration
Browse files Browse the repository at this point in the history
  • Loading branch information
Mohammad-Alavi committed Jan 26, 2025
1 parent 603d86a commit 143a50f
Show file tree
Hide file tree
Showing 10 changed files with 238 additions and 97 deletions.
2 changes: 1 addition & 1 deletion src/Abstract/Models/BaseModel.php
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ abstract class BaseModel extends LaravelEloquentModel implements Resource

protected static function newFactory()
{
$factoryName = apiato()->factoryDiscovery()
$factoryName = apiato()->factory()
->resolveFactoryName(static::class);

if (is_string($factoryName)) {
Expand Down
67 changes: 59 additions & 8 deletions src/Foundation/Apiato.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,9 @@
namespace Apiato\Foundation;

use Apiato\Foundation\Configuration\ApplicationBuilder;
use Apiato\Foundation\Configuration\FactoryDiscovery;
use Apiato\Foundation\Configuration\Factory;
use Apiato\Foundation\Configuration\Localization;
use Apiato\Foundation\Configuration\Repository;
use Apiato\Foundation\Configuration\Routing;
use Apiato\Foundation\Configuration\Seeding;
use Apiato\Foundation\Configuration\View;
Expand Down Expand Up @@ -33,7 +34,8 @@ final class Apiato
private Localization $localization;
private View $view;
private Seeding $seeding;
private FactoryDiscovery $factoryDiscovery;
private Factory $factory;
private Repository $repository;

private function __construct(
private readonly string $basePath,
Expand Down Expand Up @@ -111,10 +113,21 @@ public function withRouting(callable|null $callback = null): self

public function withFactories(callable|null $callback = null): self
{
$this->factoryDiscovery ??= new FactoryDiscovery();
$this->factory ??= new Factory();

if (!is_null($callback)) {
$callback($this->factoryDiscovery);
$callback($this->factory);
}

return $this;
}

public function withRepositories(callable|null $callback = null): self
{
$this->repository ??= new Repository();

if (!is_null($callback)) {
$callback($this->repository);
}

return $this;
Expand Down Expand Up @@ -203,7 +216,7 @@ public function providers(): array
}

/*
* Get the configuration files to be loaded.
* Get the config files.
*
* @return string[]
*/
Expand All @@ -215,7 +228,7 @@ public function configs(): array
}

/*
* Get the helper files to be loaded.
* Get the helper files.
*
* @return string[]
*/
Expand All @@ -226,51 +239,89 @@ public function helpers(): array
)->toArray();
}

/**
* Get the migration paths.
*/
public function migrations(): array
{
return $this->migrationPaths;
}

/**
* Get the event paths.
*/
public function events(): array
{
return $this->eventDiscoveryPaths;
}

/**
* Get the command paths.
*/
public function commands(): array
{
return $this->commandPaths;
}

/**
* Register the API routes.
*/
public function registerApiRoutes(): void
{
$this->routing->registerApiRoutes();
}

/**
* Get Web routes.
*/
public function webRoutes(): array
{
return $this->routing->webRoutes();
}

/**
* Get the seeding configuration.
*/
public function seeding(): Seeding
{
return $this->seeding;
}

/**
* Get the routing configuration.
*/
public function routing(): Routing
{
return $this->routing;
}

public function factoryDiscovery(): FactoryDiscovery
/**
* Get the factory configuration.
*/
public function factory(): Factory
{
return $this->factory;
}

/**
* Get the repository configuration.
*/
public function repository(): Repository
{
return $this->factoryDiscovery;
return $this->repository;
}

/**
* Get the localization configuration.
*/
public function localization(): Localization
{
return $this->localization;
}

/**
* Get the view configuration.
*/
public function view(): View
{
return $this->view;
Expand Down
10 changes: 9 additions & 1 deletion src/Foundation/Configuration/ApplicationBuilder.php
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,15 @@ private function withDefaults(string $basePath): void
)->loadWebRoutesFrom(
...$this->getDirs($this->joinPaths($basePath, 'app/Containers/*/*/UI/WEB/Routes')),
);
})->withFactories();
})->withFactories()
->withRepositories();
}

public function withRepositories(callable|null $callback = null): self
{
$this->apiato->withRepositories($callback);

return $this;
}

public function withFactories(callable|null $callback = null): self
Expand Down
53 changes: 53 additions & 0 deletions src/Foundation/Configuration/Factory.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
<?php

namespace Apiato\Foundation\Configuration;

use Illuminate\Database\Eloquent\Factories\Factory as AbstractFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Str;

/**
* @template TModel of Model
* @template TFactory of AbstractFactory
*/
final class Factory
{
protected static \Closure $nameResolver;

public function __construct()
{
$this->resolveFactoryNameUsing(
static function (string $modelName): string|null {
$factoryName = Str::of($modelName)->beforeLast('Models\\')
->append('Data\\Factories\\' . class_basename($modelName) . 'Factory')
->value();

if (class_exists($factoryName)) {
return $factoryName;
}

return null;
},
);
}

/**
* @param \Closure(class-string<TModel>): (class-string<TFactory>|null) $callback
*/
public function resolveFactoryNameUsing(\Closure $callback): self
{
self::$nameResolver = $callback;

return $this;
}

/**
* @param class-string<TModel> $modelName
*
* @return class-string<TFactory>|null
*/
public function resolveFactoryName(string $modelName): string|null
{
return app()->call(self::$nameResolver, ['modelName' => $modelName]);
}
}
55 changes: 0 additions & 55 deletions src/Foundation/Configuration/FactoryDiscovery.php

This file was deleted.

57 changes: 57 additions & 0 deletions src/Foundation/Configuration/Repository.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
<?php

namespace Apiato\Foundation\Configuration;

use Apiato\Abstract\Repositories\Repository as AbstractRepository;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Str;

/**
* @template TModel of Model
* @template TRepository of AbstractRepository
*/
final class Repository
{
protected static \Closure $nameResolver;

public function __construct()
{
$this->resolveModelNameUsing(
static function (string $repositoryName): string {
$modelName = Str::of($repositoryName)->beforeLast('Data\\Repositories\\')
->append('Models\\')
->append(
Str::of(class_basename($repositoryName))
->beforeLast('Repository')
->title()->value(),
)->value();

if (class_exists($modelName)) {
return $modelName;
}

throw new \RuntimeException("Model not found for repository: {$repositoryName}");
},
);
}

/**
* @param \Closure(class-string<TRepository>): (class-string<TModel>) $callback
*/
public function resolveModelNameUsing(\Closure $callback): self
{
self::$nameResolver = $callback;

return $this;
}

/**
* @param class-string<TRepository> $repositoryName
*
* @return class-string<TModel>
*/
public function resolveModelName(string $repositoryName): string
{
return app()->call(self::$nameResolver, ['repositoryName' => $repositoryName]);
}
}
7 changes: 7 additions & 0 deletions tests/Unit/Abstract/Repositories/RepositoryTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
use Pest\Expectation;
use Workbench\App\Containers\Identity\User\Data\Repositories\UserRepository;
use Workbench\App\Containers\Identity\User\Models\User;
use Workbench\App\Containers\MySection\Book\Data\Repositories\BookRepository;
use Workbench\App\Containers\MySection\Book\Models\Book;

describe(class_basename(Repository::class), function (): void {
Expand Down Expand Up @@ -119,6 +120,12 @@ public function shouldEagerLoadIncludes(): bool
});
});

it('discover its model', function (): void {
$repository = new BookRepository(app());

expect($repository->model())->toBe(Book::class);
});

it('can cache', function (): void {
config()->set('repository.cache.enabled', true);
config()->set('repository.cache.minutes', 1);
Expand Down
Loading

0 comments on commit 143a50f

Please sign in to comment.