Skip to content

Commit 8ec7617

Browse files
committed
Implement ArrayContainer + BDD tests
1 parent c8facd9 commit 8ec7617

File tree

3 files changed

+229
-0
lines changed

3 files changed

+229
-0
lines changed

specs/array-container.spec.php

Lines changed: 118 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,118 @@
1+
<?php
2+
3+
use Psr\Container\ContainerInterface;
4+
use Psr\Container\NotFoundExceptionInterface;
5+
use Technically\ArrayContainer\Exceptions\ServiceNotFound;
6+
use Technically\ArrayContainer\ArrayContainer;
7+
8+
describe('ArrayContainer', function() {
9+
10+
it('should instantiate a new instance', function() {
11+
$container = new ArrayContainer();
12+
assert($container instanceof ArrayContainer);
13+
});
14+
15+
it('should implement PSR container interface', function() {
16+
$container = new ArrayContainer();
17+
assert($container instanceof ContainerInterface);
18+
});
19+
20+
it('should instantiate a new instance with array of entries', function() {
21+
$container = new ArrayContainer([
22+
'a' => 'A',
23+
'b' => 'B',
24+
]);
25+
assert($container->has('a'));
26+
assert($container->has('b'));
27+
assert($container->toArray() === [
28+
'a' => 'A',
29+
'b' => 'B',
30+
]);
31+
});
32+
33+
describe('->has()', function() {
34+
it('should return true for defined entries', function () {
35+
$container = new ArrayContainer([
36+
'a' => 'A',
37+
'b' => 'B',
38+
]);
39+
40+
assert($container->has('a') === true);
41+
assert($container->has('b') === true);
42+
});
43+
it('should return false for entries not defined', function () {
44+
$container = new ArrayContainer([
45+
'a' => 'A',
46+
'b' => 'B',
47+
]);
48+
49+
assert($container->has('A') === false);
50+
assert($container->has('B') === false);
51+
});
52+
});
53+
54+
describe('->get()', function() {
55+
it('should return entries by identifier', function () {
56+
$now = new DateTime('now');
57+
$container = new ArrayContainer([
58+
'greeting' => 'Hello',
59+
'date' => $now,
60+
]);
61+
62+
assert($container->get('greeting') === 'Hello');
63+
assert($container->get('date') === $now);
64+
});
65+
66+
it('should throw ServiceNotFound exception for entries not defined', function () {
67+
$container = new ArrayContainer(['a' => 'A']);
68+
69+
assert($container->has('b') === false);
70+
71+
try {
72+
$container->get('b');
73+
} catch (ServiceNotFound $exception) {
74+
// passthru
75+
}
76+
77+
assert(isset($exception));
78+
assert($exception instanceof ServiceNotFound);
79+
assert($exception instanceof NotFoundExceptionInterface);
80+
});
81+
});
82+
83+
describe('->set()', function() {
84+
it('should set entries for identifier', function () {
85+
$now = new DateTime('now');
86+
$container = new ArrayContainer();
87+
88+
assert($container->has('date') === false);
89+
90+
$container->set('date', $now);
91+
92+
assert($container->has('date') === true);
93+
assert($container->get('date') === $now);
94+
});
95+
96+
it('should overwrite previously defined entries for the same identifier', function () {
97+
$container = new ArrayContainer(['a' => 'A']);
98+
99+
assert($container->get('a') === 'A');
100+
101+
$container->set('a', 'B');
102+
103+
assert($container->get('a') === 'B');
104+
});
105+
});
106+
107+
describe('->toArray()', function() {
108+
it('should return all container entries in array', function () {
109+
$container = new ArrayContainer(['a' => 'A']);
110+
111+
assert($container->toArray() === ['a' => 'A']);
112+
113+
$container->set('b', 'B');
114+
115+
assert($container->toArray() === ['a' => 'A', 'b' => 'B']);
116+
});
117+
});
118+
});

src/ArrayContainer.php

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
<?php
2+
3+
namespace Technically\ArrayContainer;
4+
5+
use Psr\Container\ContainerInterface;
6+
use Technically\ArrayContainer\Exceptions\ServiceNotFound;
7+
8+
final class ArrayContainer implements ContainerInterface
9+
{
10+
/**
11+
* @var mixed[]
12+
*/
13+
private $services;
14+
15+
/**
16+
* @param mixed[] $services
17+
*/
18+
public function __construct(array $services = [])
19+
{
20+
$this->services = $services;
21+
}
22+
23+
/**
24+
* Returns true if the container can return an entry for the given identifier.
25+
* Returns false otherwise.
26+
*
27+
* `has($id)` returning true does not mean that `get($id)` will not throw an exception.
28+
* It does however mean that `get($id)` will not throw a `NotFoundExceptionInterface`.
29+
*
30+
* @param string $id Identifier of the entry to look for.
31+
*
32+
* @return bool
33+
*/
34+
public function has($id)
35+
{
36+
return array_key_exists($id, $this->services);
37+
}
38+
39+
/**
40+
* Finds an entry of the container by its identifier and returns it.
41+
*
42+
* @param string $id Identifier of the entry to look for.
43+
*
44+
* @throws ServiceNotFound No entry was found for **this** identifier.
45+
*
46+
* @return mixed Entry.
47+
*/
48+
public function get($id)
49+
{
50+
if (array_key_exists($id, $this->services)) {
51+
return $this->services[$id];
52+
}
53+
54+
throw new ServiceNotFound($id);
55+
}
56+
57+
/**
58+
* Sets a container entry for the given identifier.
59+
*
60+
* @param string $id Identifier of the entry to set.
61+
* @param mixed $entry Entry.
62+
*
63+
* @return void
64+
*/
65+
public function set($id, $entry)
66+
{
67+
$this->services[$id] = $entry;
68+
}
69+
70+
/**
71+
* Return an associative array of all container entries.
72+
*
73+
* @return mixed[]
74+
*/
75+
public function toArray(): array
76+
{
77+
return $this->services;
78+
}
79+
}

src/Exceptions/ServiceNotFound.php

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
<?php
2+
3+
namespace Technically\ArrayContainer\Exceptions;
4+
5+
use Psr\Container\NotFoundExceptionInterface;
6+
use RuntimeException;
7+
8+
final class ServiceNotFound extends RuntimeException implements NotFoundExceptionInterface
9+
{
10+
/**
11+
* @var string
12+
*/
13+
private $serviceName;
14+
15+
/**
16+
* @param string $serviceName
17+
*/
18+
public function __construct(string $serviceName)
19+
{
20+
$this->serviceName = $serviceName;
21+
22+
parent::__construct("Could not resolve service (`{$serviceName}`).");
23+
}
24+
25+
/**
26+
* @return string
27+
*/
28+
public function getServiceName(): string
29+
{
30+
return $this->serviceName;
31+
}
32+
}

0 commit comments

Comments
 (0)