Skip to content

Commit

Permalink
feat: define & resolve
Browse files Browse the repository at this point in the history
  • Loading branch information
azuradara committed Feb 21, 2024
1 parent 96948e7 commit 43de7d6
Show file tree
Hide file tree
Showing 14 changed files with 201 additions and 86 deletions.
50 changes: 0 additions & 50 deletions .github/workflows/formats.yml

This file was deleted.

2 changes: 0 additions & 2 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -41,11 +41,9 @@
"scripts": {
"refactor": "rector",
"test:refactor": "rector --dry-run",
"test:types": "phpstan analyse --ansi",
"test:unit": "pest --colors=always",
"test": [
"@test:refactor",
"@test:types",
"@test:unit"
]
},
Expand Down
8 changes: 8 additions & 0 deletions config/foggle.php
Original file line number Diff line number Diff line change
@@ -1,5 +1,13 @@
<?php

return [
'default' => env('FOGGLE_STORE', 'array'),

'stores' => [

'array' => [
'driver' => 'array',
],

],
];
6 changes: 0 additions & 6 deletions phpstan.neon.dist

This file was deleted.

11 changes: 8 additions & 3 deletions src/Contracts/Driver.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,21 @@

interface Driver
{
/**
* @return array<string>
*/
public function defined(): array;

/**
* @param mixed $context
*
* @return mixed
*/
public function get(string $feature, $context);
public function get(string $name, $context);

/**
* @param string $feature
* @param string|class-string $name
* @param (callable(mixed $context): mixed) $resolver
*/
public function define(string $feature, callable $resolver): void;
public function define(string $name, callable $resolver): void;
}
49 changes: 49 additions & 0 deletions src/Drivers/ArrayDriver.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
<?php

namespace YouCanShop\Foggle\Drivers;

use Illuminate\Contracts\Events\Dispatcher;
use YouCanShop\Foggle\Contracts\Driver;

class ArrayDriver implements Driver
{
/** @var Dispatcher */
protected Dispatcher $dispatcher;

/** @var array<string, (callable(mixed $context): mixed)> */
protected array $resolvers;

/**
* @param Dispatcher $dispatcher
* @param array<string, (callable(mixed $context): mixed)> $resolvers
*/
public function __construct(Dispatcher $dispatcher, array $resolvers)
{
$this->dispatcher = $dispatcher;
$this->resolvers = $resolvers;
}

/**
* @inheritDoc
*/
public function defined(): array
{
return array_keys($this->resolvers);
}

/**
* @inheritDoc
*/
public function get(string $name, $context)
{
return $this->resolvers[$name]($context);
}

/**
* @inheritDoc
*/
public function define(string $name, callable $resolver): void
{
$this->resolvers[$name] = $resolver;
}
}
59 changes: 44 additions & 15 deletions src/Drivers/Decorator.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,10 @@

namespace YouCanShop\Foggle\Drivers;

use Closure;
use Illuminate\Contracts\Container\BindingResolutionException;
use Illuminate\Contracts\Container\Container;
use Illuminate\Support\Str;
use stdClass;
use Symfony\Component\Finder\Finder;
use YouCanShop\Foggle\Contracts\Driver;
use YouCanShop\Foggle\Lazily;
Expand All @@ -18,21 +18,19 @@ class Decorator implements Driver

private Container $container;

/** @var callable */
private $resolver;

public function __construct(
string $name,
Driver $driver,
callable $resolver,
Container $container
) {
$this->name = $name;
$this->driver = $driver;
$this->resolver = $resolver;
$this->container = $container;
}

/**
* @throws BindingResolutionException
*/
public function discover(string $namespace = 'App\\Features', ?string $path = null): void
{
$namespace = Str::finish($namespace, '\\');
Expand All @@ -47,24 +45,55 @@ public function discover(string $namespace = 'App\\Features', ?string $path = nu
}

/**
* @param class-string $name
* @param class-string|string $name
* @param callable|null $resolver
*
* @return void
* @throws BindingResolutionException
*/
public function define(string $name)
public function define(string $name, callable $resolver = null): void
{
/** @var stdClass $instance */
$instance = $this->container->make($name);
$feature = $instance->name ?? class_basename($name);
if ($resolver === null) {
[$name, $resolver] = [$this->container->make($name)->name ?? $name, new Lazily($name)];
}

$this->driver->define($feature, function ($context) use ($feature, $instance) {
$resolver = fn () => $instance->resolve($context);
$this->driver->define($name, function ($context) use ($name, $resolver) {
if ($resolver instanceof Lazily) {
$resolver = with(
$this->container[$resolver->feature],
fn($i) => method_exists($i, 'resolve')
? $i->resolve($context)
: $i($context)
);
}

if (!$resolver instanceof Closure) {
return $this->resolve($name, fn() => $resolver, $context);
}

return $this->resolve($name, $resolver, $context);
});
}

public function get(string $feature, $context)
/**
* @param string $name
* @param callable $resolver
* @param mixed $context
*
* @return mixed
*/
protected function resolve(string $name, callable $resolver, $context)
{
return $resolver($context);
}

public function get(string $name, $context)
{
return $this->driver->get($name, $context);
}

public function defined(): array
{
// TODO: Implement get() method.
return $this->driver->defined();
}
}
47 changes: 47 additions & 0 deletions src/Foggle.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,16 @@
use Illuminate\Contracts\Container\BindingResolutionException;
use Illuminate\Contracts\Container\Container;
use InvalidArgumentException;
use YouCanShop\Foggle\Drivers\ArrayDriver;
use YouCanShop\Foggle\Drivers\Decorator;

/**
* @mixin Decorator
*/
final class Foggle
{
private Container $container;
protected array $stores = [];

public function __construct(Container $container)
{
Expand All @@ -32,4 +38,45 @@ public function feature(string $name)

return $feature->resolve();
}

public function driver(string $name = null): Decorator
{
$name = $name ?: $this->getDefaultDriver();

return $this->stores[$name] = $this->stores[$name] ?? $this->resolve($name);
}

protected function resolve(string $name): Decorator
{
$config = $this->getDriverConfig($name);
if ($config === null) {
throw new InvalidArgumentException("Foggle store [$name] is not defined");
}

if ($name === 'array') {
$driver = new ArrayDriver($this->container['events'], []);
}

if (!isset($driver)) {
throw new InvalidArgumentException("Driver [{$config['driver']}] is not supported");
}

return new Decorator($name, $driver, $this->container);
}


protected function getDriverConfig(string $name): ?array
{
return $this->container['config']["foggle.stores.$name"];
}

public function getDefaultDriver(): string
{
return $this->container['config']->get('foggle.default') ?? 'array';
}

public function __call($name, $arguments)
{
return $this->driver()->$name(...$arguments);
}
}
13 changes: 13 additions & 0 deletions src/Lazily.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<?php

namespace YouCanShop\Foggle;

class Lazily
{
public string $feature;

public function __construct(string $feature)
{
$this->feature = $feature;
}
}
5 changes: 5 additions & 0 deletions testbench.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
providers:
- YouCanShop\Foggle\FoggleServiceProvider

workbench:
install: true
9 changes: 0 additions & 9 deletions tests/Feature/Foggle.php

This file was deleted.

25 changes: 25 additions & 0 deletions tests/Feature/FoggleTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
<?php

use function Orchestra\Testbench\workbench_path;

it('discovers features', function () {
$foggle = $this->foggle();

$foggle->discover(
'Workbench\\App\\Features',
workbench_path('app/Features')
);

expect($foggle->defined())->toBeGreaterThan(0);
});

it('retrieves a feature\'s value by name', function () {
$foggle = $this->foggle();

$foggle->discover(
'Workbench\\App\\Features',
workbench_path('app/Features')
);

expect($foggle->get('always-true', null))->toBeTrue();
});
1 change: 0 additions & 1 deletion tests/TestCase.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ abstract class TestCase extends OrchestraTestCase
{
use WithWorkbench;


public function foggle(): Foggle
{
return new Foggle($this->app);
Expand Down
2 changes: 2 additions & 0 deletions workbench/app/Features/AlwaysTrue.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@

class AlwaysTrue
{
public string $name = 'always-true';

public function resolve(): bool
{
return true;
Expand Down

0 comments on commit 43de7d6

Please sign in to comment.