Skip to content

Commit

Permalink
Merge 8430d25 into 13d5f7c
Browse files Browse the repository at this point in the history
  • Loading branch information
feryardiant committed Jul 9, 2020
2 parents 13d5f7c + 8430d25 commit 09c0a6d
Show file tree
Hide file tree
Showing 14 changed files with 85 additions and 70 deletions.
6 changes: 3 additions & 3 deletions .github/wiki/Home.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ This tiny library aims to provide dead simple PSR-11 implementation with flexibl

## Requirements

- PHP 7.1+
- PHP 7.1+ and tested up-to PHP 8.0-alpha

## Installation

Expand Down Expand Up @@ -90,7 +90,7 @@ Means it has `get($serviceId)` and `has($serviceId)` method as required by [PSR-

## Extra Flexibilities

In-case you like the way to accessing a service instance using array, yes you can by registering `ArrayContainer` as a service
In-case you'd like to accessing a service instance using array, yes you can by registering `ArrayContainer` as a service

```php
use Projek\Container\ArrayContainer;
Expand Down Expand Up @@ -118,4 +118,4 @@ $container->set('myService', function (PropertyContainer $container) {
$container->{Psr\Log\LoggerInterface::class} // Not convenient indeed, but yes you could 😅
);
});
```
```
46 changes: 34 additions & 12 deletions .github/wiki/Registering-an-instance.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,35 +9,57 @@ $container->set($abstract, $concrete)
| `$abstract` | `string` | Name of the service |
| `$concrete` | `callable`, `object` | Instance of the service |

You have few ways registering your services to the container. Example above you can use `Closure`, you also has the options to:
There's few ways to register your services to the container as follow:

## Use any [`callable`](https://www.php.net/manual/en/language.types.callable.php)
### 1. Use any [`callable`](https://www.php.net/manual/en/language.types.callable.php)

```php
// callable string of a function name
$container->set('myService', 'aFunctionName');

// callable string of a static method of a class
$container->set('myService', 'MyServiceProvider::staticMethodName');
// callable string of a class::method pair
$container->set('myService', 'SomeClass::methodName');

// callable array as a method of class instance
$container->set('myService', [$myObj, 'methodName']);
// callable array as an object of class and method pair
$container->set('myService', [$classInstance, 'methodName']);

// callable array as a static method of class
$container->set('myService', [MyServiceProvider::class, 'staticMethodName']);
// callable array as a string of class name and method pair
$container->set('myService', [SomeClass::class, 'methodName']);
```

## Use object of class instance
If registering a class-method pair (whether it's a `string` or `array`) it would work regardless the method is a static or not. Let say we have the following

```php
$container->set('myService', new MyService);
class SomeClass implements CertainInterface
{
public static function staticMethod() {
// some codes
}

public function nonStaticMethod() {
// some codes
}
}

$container->set(CertainInterface::class, 'SomeClass::staticMethod'); // OR
$container->set(CertainInterface::class, 'SomeClass::nonStaticMethod'); // OR
$container->set(CertainInterface::class, [SomeClass::class, 'staticMethod']); // OR
$container->set(CertainInterface::class, [SomeClass::class, 'nonStaticMethod']); // OR
$container->set(CertainInterface::class, [new SomeClass, 'staticMethod']); // OR
$container->set(CertainInterface::class, [new SomeClass, 'nonStaticMethod']);
```

### 2. Use object of class instance

```php
$container->set('myService', new SomeClass);
```

## Use string of a class name
### 3. Use string of a class name

```php
// callable string of a class name
$container->set('myService', MyServiceProvider::class);
$container->set('myService', SomeFactoryClass::class);
```

By registering a service as class name you have the option to resolve and inject the dependencies either for its `__construct()` and `__invoke()` method, if any. See [#2](https://github.com/projek-xyz/container/pull/2)
Expand Down
12 changes: 6 additions & 6 deletions src/Container.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

namespace Projek;

use Projek\Container\{ContainerInterface, InvalidArgumentException, NotFoundException, RangeException, Resolver};
use Projek\Container\{ContainerInterface, Exception, Resolver};
use Psr\Container\ContainerInterface as PsrContainerInterface;

class Container implements ContainerInterface
Expand Down Expand Up @@ -62,7 +62,7 @@ public function __clone()
public function get($id)
{
if (! $this->has($id)) {
throw new NotFoundException($id);
throw new Exception\NotFoundException($id);
}

if (isset($this->resolved[$id])) {
Expand Down Expand Up @@ -135,17 +135,17 @@ private function assertParams(int $count, array $params = []): array
{
if (2 === $count) {
if (! is_array($params[0])) {
throw new InvalidArgumentException(2, ['array'], gettype($params[0]));
throw new Exception\InvalidArgumentException(2, ['array'], gettype($params[0]));
} elseif (! ($params[1] instanceof \Closure) && null !== $params[1]) {
throw new InvalidArgumentException(3, ['Closure'], gettype($params[1]));
throw new Exception\InvalidArgumentException(3, ['Closure'], gettype($params[1]));
}

return [$params[0], $params[1]];
}

if (1 === $count) {
if (! is_array($params[0]) && ! ($params[0] instanceof \Closure)) {
throw new InvalidArgumentException(2, ['array', 'Closure'], gettype($params[0]));
throw new Exception\InvalidArgumentException(2, ['array', 'Closure'], gettype($params[0]));
}

$arguments = is_array($params[0]) ? $params[0] : [];
Expand All @@ -154,6 +154,6 @@ private function assertParams(int $count, array $params = []): array
return [$arguments, $condition];
}

throw new RangeException(3, $count + 1);
throw new Exception\RangeException(3, $count + 1);
}
}
2 changes: 1 addition & 1 deletion src/Container/ArrayContainer.php
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ public function offsetGet($name)
{
try {
return $this->getContainer($name);
} catch (NotFoundException $e) {
} catch (Exception\NotFoundException $e) {
return null;
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

declare(strict_types=1);

namespace Projek\Container;
namespace Projek\Container\Exception;

use Psr\Container\ContainerExceptionInterface;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

declare(strict_types=1);

namespace Projek\Container;
namespace Projek\Container\Exception;

use Psr\Container\NotFoundExceptionInterface;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

declare(strict_types=1);

namespace Projek\Container;
namespace Projek\Container\Exception;

use Psr\Container\ContainerExceptionInterface;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@

declare(strict_types=1);

namespace Projek\Container;
namespace Projek\Container\Exception;

use Projek\Container\Exception;

class UnresolvableException extends Exception
{
Expand Down
2 changes: 1 addition & 1 deletion src/Container/PropertyContainer.php
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ public function __get(string $name)
{
try {
return $this->getContainer($name);
} catch (NotFoundException $e) {
} catch (Exception\NotFoundException $e) {
return null;
}
}
Expand Down
12 changes: 6 additions & 6 deletions src/Container/Resolver.php
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ public function handle($instance, array $args = [])
*
* @param string|object|callable|Closure $toResolve
* @return object|callable
* @throws UnresolvableException
* @throws Exception\UnresolvableException
*/
public function resolve($toResolve)
{
Expand All @@ -72,11 +72,11 @@ public function resolve($toResolve)
if ($this->assertCallable($toResolve)) {
return $toResolve;
}
} catch (UnresolvableException $err) {
} catch (Exception\UnresolvableException $err) {
// do nothing
}

throw new UnresolvableException($toResolve);
throw new Exception\UnresolvableException($toResolve);
}

/**
Expand All @@ -95,7 +95,7 @@ protected function createInstance(string $className)
try {
$reflector = new ReflectionClass($className);
} catch (ReflectionException $err) {
throw new UnresolvableException($className, $err);
throw new Exception\UnresolvableException($className, $err);
}

if (! $reflector->isInstantiable()) {
Expand Down Expand Up @@ -129,7 +129,7 @@ protected function resolveArgs($reflection, array $args = []): array
$args[$position] = $this->getContainer(
($type && ! $type->isBuiltin() ? $type : $param)->getName()
);
} catch (NotFoundException $e) {
} catch (Exception\NotFoundException $e) {
if (! $param->isOptional()) {
throw $e;
}
Expand Down Expand Up @@ -163,7 +163,7 @@ private function assertCallable(&$instance): bool
}

if (! method_exists(...$instance)) {
throw new UnresolvableException([get_class($instance[0]), $instance[1]]);
throw new Exception\UnresolvableException([get_class($instance[0]), $instance[1]]);
}
}

Expand Down
10 changes: 5 additions & 5 deletions test/spec/ArrayContainer.spec.php
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
<?php

use Projek\Container;
use Projek\Container\{ArrayContainer, Exception, UnresolvableException};
use Projek\Container\{ArrayContainer, Exception};
use Stubs\AbstractFoo;
use function Kahlan\describe;
use function Kahlan\expect;

// use function Kahlan\{describe, expect};

describe(ArrayContainer::class, function () {
beforeEach(function () {
Expand All @@ -29,10 +29,10 @@

expect(function () {
$this->c['foo'] = ['foo', 'bar'];
})->toThrow(new UnresolvableException(['foo', 'bar']));
})->toThrow(new Exception\UnresolvableException(['foo', 'bar']));

expect(function () {
$this->c['foo'] = null;
})->toThrow(new UnresolvableException(null));
})->toThrow(new Exception\UnresolvableException(null));
});
});
31 changes: 14 additions & 17 deletions test/spec/Container.spec.php
Original file line number Diff line number Diff line change
@@ -1,14 +1,11 @@
<?php

use Projek\Container;
use Projek\Container\{ContainerInterface, Exception, InvalidArgumentException, NotFoundException, RangeException, UnresolvableException};
use Projek\Container\{ContainerInterface, Exception};
use Psr\Container\ContainerInterface as PsrContainer;
use Stubs\{Dummy, AbstractFoo, CallableClass, ConcreteBar, PrivateFactory, ServiceProvider, SomeClass};
use Stubs\{Dummy, AbstractFoo, CallableClass, ConcreteBar, ServiceProvider, SomeClass};

use function Kahlan\beforeEach;
use function Kahlan\context;
use function Kahlan\describe;
use function Kahlan\expect;
// use function Kahlan\{beforeEach, context, describe, expect};

describe(Container::class, function () {
beforeEach(function () {
Expand Down Expand Up @@ -56,7 +53,7 @@

expect(function () {
return $this->c->get('dummy');
})->toThrow(new NotFoundException('dummy'));
})->toThrow(new Exception\NotFoundException('dummy'));
});

it('Should not overwrite existing', function () {
Expand All @@ -72,7 +69,7 @@
});
expect(function () {
return $this->c->get('stds');
})->toThrow(new NotFoundException('foo'));
})->toThrow(new Exception\NotFoundException('foo'));
});

it('Should cache resolved instances', function () {
Expand Down Expand Up @@ -170,15 +167,15 @@

expect(function () {
$this->c->set('foo', 'NotExistsClass');
})->toThrow(new UnresolvableException('NotExistsClass'));
})->toThrow(new Exception\UnresolvableException('NotExistsClass'));

expect(function () {
$this->c->set('foo', ['foo', 'bar']);
})->toThrow(new UnresolvableException(['foo', 'bar']));
})->toThrow(new Exception\UnresolvableException(['foo', 'bar']));

expect(function () {
$this->c->set('foo', null);
})->toThrow(new UnresolvableException(null));
})->toThrow(new Exception\UnresolvableException(null));
});
});

Expand Down Expand Up @@ -320,7 +317,7 @@ function func() {

return null;
});
})->toThrow(new UnresolvableException([Stubs\SomeClass::class, 'notExists']));
})->toThrow(new Exception\UnresolvableException([Stubs\SomeClass::class, 'notExists']));
});

it('Should pass second parameter as argument for the handler', function () {
Expand Down Expand Up @@ -349,31 +346,31 @@ function func() {
it('Should throw exception if second parameter were invalid', function () {
expect(function () {
$this->c->make(Stubs\SomeClass::class, 'string');
})->toThrow(new InvalidArgumentException(2, ['array', 'Closure'], 'string'));
})->toThrow(new Exception\InvalidArgumentException(2, ['array', 'Closure'], 'string'));

// Ignore falsy param
expect(function () {
$this->c->make(Stubs\SomeClass::class, 'string', null);
})->toThrow(new InvalidArgumentException(2, ['array', 'Closure'], 'string'));
})->toThrow(new Exception\InvalidArgumentException(2, ['array', 'Closure'], 'string'));

expect(function () {
// Correct condition with incorrect argument
$this->c->make(Stubs\SomeClass::class, 'string', function ($instance) {
return [$instance, 'shouldCalled'];
});
})->toThrow(new InvalidArgumentException(2, ['array'], 'string'));
})->toThrow(new Exception\InvalidArgumentException(2, ['array'], 'string'));
});

it('Should throw exception if third parameter were invalid', function () {
expect(function () {
$this->c->make(Stubs\SomeClass::class, ['string'], 'condition');
})->toThrow(new InvalidArgumentException(3, ['Closure'], 'string'));
})->toThrow(new Exception\InvalidArgumentException(3, ['Closure'], 'string'));
});

it('Should throw exception if have more than 3 parameters', function () {
expect(function () {
$this->c->make(Stubs\SomeClass::class, ['string'], 'condition', 'more');
})->toThrow(new RangeException(3, 4));
})->toThrow(new Exception\RangeException(3, 4));
});

it('Should ignore the optional arguments if falsy ', function () {
Expand Down

0 comments on commit 09c0a6d

Please sign in to comment.