Container::has()   A
last analyzed

Complexity

Conditions 3
Paths 3

Size

Total Lines 13
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 7
CRAP Score 3

Importance

Changes 3
Bugs 0 Features 0
Metric Value
cc 3
eloc 7
c 3
b 0
f 0
nc 3
nop 1
dl 0
loc 13
ccs 7
cts 7
cp 1
crap 3
rs 10
1
<?php
2
3
namespace danmurf\DependencyInjection;
4
5
use danmurf\DependencyInjection\Exception\ContainerException;
6
use danmurf\DependencyInjection\Exception\NotFoundException;
7
use Psr\Container\ContainerInterface;
8
9
/**
10
 * Simple dependency injection container with configurable service
11
 * location strategies.
12
 *
13
 * @author Dan Murfitt <[email protected]>
14
 */
15
class Container implements ContainerInterface
16
{
17
    /** @var ServiceLocatorInterface */
18
    private $serviceLocator;
19
20
    /** @var array */
21
    private $instances = [];
22
23
    /** @var array */
24
    private $classMap = [];
25
26
    /**
27
     * @param ServiceLocatorInterface $serviceLocator
28
     */
29 14
    public function __construct(ServiceLocatorInterface $serviceLocator)
30
    {
31 14
        $this->serviceLocator = $serviceLocator;
32 14
    }
33
34
    /**
35
     * Get an instance of a service.
36
     *
37
     * @param string $requestedId Registered service ID or FQCN
38
     *
39
     * @throws NotFoundException
40
     */
41 5
    public function get($requestedId)
42
    {
43 5
        if (false === $registeredId = $this->getRegisteredId($requestedId)) {
44 2
            $this->register($this->serviceLocator->locate($requestedId, $this), $requestedId);
45 1
            $registeredId = $requestedId;
46
        }
47
48 4
        return $this->instances[$registeredId];
49
    }
50
51
    /**
52
     * Determine if the container can locate an instance of the specified service ID or FQCN.
53
     *
54
     * @param string $id
55
     *
56
     * @return bool
57
     */
58 3
    public function has($id): bool
59
    {
60 3
        if (false !== $this->getRegisteredId($id)) {
61 1
            return true;
62
        }
63
64
        try {
65 2
            $this->serviceLocator->locate($id, $this);
66 1
        } catch (NotFoundException $exception) {
67 1
            return false;
68
        }
69
70 1
        return true;
71
    }
72
73
    /**
74
     * Register a service with the container.
75
     *
76
     * @param mixed       $instance An instance of a service
77
     * @param string|null $id       A specified service ID (FQCN will be used in the case of `null`)
78
     */
79 6
    public function register($instance, string $id = null)
80
    {
81 6
        if (!is_object($instance)) {
82 1
            throw new ContainerException('Only objects can be registered with the container.');
83
        }
84
85 5
        $class = get_class($instance);
86
87 5
        if (null === $id) {
88 2
            $id = $class;
89
        }
90
91 5
        $this->instances[$id] = $instance;
92 5
        $this->classMap[$class] = $id;
93 5
    }
94
95
    /**
96
     * Get the registered ID for the requested service ID or FQCN.
97
     *
98
     * @param string $requestedId Service id or FQCN
99
     *
100
     * @return string|bool The registered ID, or false it's not found
101
     */
102 8
    private function getRegisteredId(string $requestedId)
103
    {
104 8
        if (isset($this->instances[$requestedId])) {
105 3
            return $requestedId;
106
        }
107
108 5
        if (isset($this->classMap[$requestedId])) {
109 1
            return $this->classMap[$requestedId];
110
        }
111
112 4
        return false;
113
    }
114
}
115