Skip to content

Commit

Permalink
Merge pull request #35 from aydinfatih/master
Browse files Browse the repository at this point in the history
Added Custom Caster Feature
  • Loading branch information
aydinfatih authored May 2, 2024
2 parents a838b67 + eb92eaa commit e311bff
Show file tree
Hide file tree
Showing 4 changed files with 121 additions and 23 deletions.
11 changes: 11 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -180,6 +180,17 @@ delete_config('key');
read_nested('foo.bar');
```

### Custom Casters
You can also custom casters:

```php
$config = factory(Config::class)->create([
'name' => 'custom-cast-config-name',
'val' => [ConfigDataType::DATE],
'type' => AsEnumCollection::class.':'.ConfigDataType::class,
]);
```

### Testing

``` bash
Expand Down
69 changes: 60 additions & 9 deletions src/Casts/ConfigValueCast.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,26 +3,77 @@
namespace TarfinLabs\LaravelConfig\Casts;

use Carbon\Carbon;
use Illuminate\Contracts\Database\Eloquent\Castable;
use Illuminate\Contracts\Database\Eloquent\CastsAttributes;
use Illuminate\Contracts\Database\Eloquent\CastsInboundAttributes;
use Illuminate\Database\Eloquent\Model;
use TarfinLabs\LaravelConfig\Enums\ConfigDataType;

class ConfigValueCast implements CastsAttributes
{
public function get(Model $model, string $key, mixed $value, array $attributes)
{
return match ($attributes['type']) {
ConfigDataType::BOOLEAN->value => (bool) $value,
ConfigDataType::INTEGER->value => (int) $value,
ConfigDataType::DATE->value => Carbon::createFromFormat('Y-m-d', $value),
ConfigDataType::DATE_TIME->value => Carbon::createFromFormat('Y-m-d H:i', $value),
ConfigDataType::JSON->value => json_decode($value, true),
default => $value,
};
switch ($attributes['type']) {
case ConfigDataType::BOOLEAN->value:
return (bool) $value;
case ConfigDataType::INTEGER->value:
return (int) $value;
case ConfigDataType::DATE->value:
return Carbon::createFromFormat('Y-m-d', $value);
case ConfigDataType::DATE_TIME->value:
return Carbon::createFromFormat('Y-m-d H:i', $value);
case ConfigDataType::JSON->value:
return json_decode($value, true);
default:
$parts = explode(':', $attributes['type']);
$casterClass = array_shift($parts);
if (class_exists($casterClass)) {
$caster = match (true) {
is_subclass_of($casterClass, CastsAttributes::class), is_subclass_of($casterClass, CastsInboundAttributes::class) => new $casterClass(...$parts),
is_subclass_of($casterClass, Castable::class) => $casterClass::castUsing($parts),
default => null
};

if ($caster !== null) {
return $caster->get(model: $model, key: $key, value: $value, attributes: $attributes);
}
}

return $value;
}
}

public function set(Model $model, string $key, mixed $value, array $attributes)
{
return $value;
$type = $attributes['type']?->value ?? $attributes['type'] ?? null;

switch ($type) {
case ConfigDataType::DATE->value:
return Carbon::parse($value)->format('Y-m-d');
case ConfigDataType::DATE_TIME->value:
return Carbon::parse($value)->format('Y-m-d H:i');
case ConfigDataType::JSON->value:
return match (true) {
is_string($value) => $value,
default => json_encode($value)
};
default:
$parts = explode(':', $type);
$casterClass = array_shift($parts);

if (class_exists($casterClass)) {
$caster = match (true) {
is_subclass_of($casterClass, CastsAttributes::class), is_subclass_of($casterClass, CastsInboundAttributes::class) => new $casterClass(...$parts),
is_subclass_of($casterClass, Castable::class) => $casterClass::castUsing($parts),
default => null
};

if ($caster !== null) {
return $caster->set(model: $model, key: $key, value: $value, attributes: $parts);
}
}

return $value;
}
}
}
2 changes: 1 addition & 1 deletion src/LaravelConfig.php
Original file line number Diff line number Diff line change
Expand Up @@ -159,8 +159,8 @@ public function delete(Config $config): int
private function fillColumns(Config $config, ConfigItem $configItem): Config
{
$config->name = $configItem->name;
$config->val = $configItem->val;
$config->type = $configItem->type;
$config->val = $configItem->val;
$config->description = $configItem->description;
$config->tags = $configItem->tags;

Expand Down
62 changes: 49 additions & 13 deletions tests/LaravelConfigTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@
namespace TarfinLabs\LaravelConfig\Tests;

use Carbon\Carbon;
use Illuminate\Database\Eloquent\Casts\AsCollection;
use Illuminate\Database\Eloquent\Casts\AsEnumCollection;
use Illuminate\Support\Collection;
use Illuminate\Support\Str;
use TarfinLabs\LaravelConfig\Config\Config;
use TarfinLabs\LaravelConfig\Config\ConfigFactory;
Expand All @@ -26,10 +29,10 @@ public function it_create_a_new_config_parameter(): void
{
$factory = new ConfigFactory();
$configItem = $factory->setName(Str::random(5))
->setType(ConfigDataType::BOOLEAN)
->setValue('1')
->setDescription(Str::random(50))
->get();
->setType(ConfigDataType::BOOLEAN)
->setValue('1')
->setDescription(Str::random(50))
->get();

$this->laravelConfig->create($configItem);

Expand Down Expand Up @@ -72,10 +75,10 @@ public function it_does_not_create_a_config_parameter_with_the_same_name(): void

$factory = new ConfigFactory();
$configItem = $factory->setName($config->name)
->setType(ConfigDataType::BOOLEAN)
->setValue('1')
->setDescription(Str::random(50))
->get();
->setType(ConfigDataType::BOOLEAN)
->setValue('1')
->setDescription(Str::random(50))
->get();

$response = $this->laravelConfig->create($configItem);

Expand All @@ -90,9 +93,9 @@ public function it_updates_existing_config_parameter(): void

$factory = new ConfigFactory($config);
$configItem = $factory->setType(ConfigDataType::BOOLEAN)
->setValue('0')
->setDescription('updated-description')
->get();
->setValue('0')
->setDescription('updated-description')
->get();

$this->laravelConfig->update($config, $configItem);

Expand Down Expand Up @@ -256,7 +259,7 @@ public function it_returns_date_value_for_date_type_config_parameter_if_exists()
{
$config = factory(Config::class)->create([
'name' => 'yunus.was.here',
'val' => '2024-02-29',
'val' => '2024-02-29 14:50:00',
'type' => ConfigDataType::DATE,
]);

Expand All @@ -270,7 +273,7 @@ public function it_returns_json_value_for_json_type_config_parameter_if_exists()
{
$config = factory(Config::class)->create([
'name' => 'yunus.was.here',
'val' => '{"9":[7,8,9],"2":[7,8,9],"31":[10,11,12]}',
'val' => [9 => [7, 8, 9], 2 => [7, 8, 9], 31 => [10, 11, 12]],
'type' => ConfigDataType::JSON,
]);

Expand All @@ -282,4 +285,37 @@ public function it_returns_json_value_for_json_type_config_parameter_if_exists()
$this->assertArrayHasKey(2, $response);
$this->assertArrayHasKey(31, $response);
}

/** @test */
public function it_returns_in_caster_type_if_type_is_custom_caster_with_param(): void
{
$config = factory(Config::class)->create([
'name' => 'fatih.was.here',
'val' => [ConfigDataType::DATE],
'type' => AsEnumCollection::class.':'.ConfigDataType::class,
]);

$response = $this->laravelConfig->get($config->name);

$this->assertInstanceOf(Collection::class, $response);
$this->assertCount(1, $response);

$this->assertEquals([ConfigDataType::DATE], $response->toArray());
}

/** @test */
public function it_returns_in_caster_type_if_type_is_custom_caster(): void
{
$config = factory(Config::class)->create([
'name' => 'fatih.was.here',
'val' => [ConfigDataType::DATE->value],
'type' => AsCollection::class,
]);

$response = $this->laravelConfig->get($config->name);

$this->assertInstanceOf(Collection::class, $response);
$this->assertCount(1, $response);
$this->assertEquals([ConfigDataType::DATE->value], $response->toArray());
}
}

0 comments on commit e311bff

Please sign in to comment.