Completed
Push — master ( 4d7d0c...65bf09 )
by Mathieu
02:04
created

MapFactory::is_resolvable()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 16
Code Lines 9

Duplication

Lines 0
Ratio 0 %

Importance

Changes 2
Bugs 0 Features 0
Metric Value
c 2
b 0
f 0
dl 0
loc 16
rs 9.4286
cc 3
eloc 9
nc 3
nop 1
1
<?php
2
3
namespace Charcoal\Factory;
4
5
// Dependencies from `PHP`
6
use \InvalidArgumentException;
7
8
// Local namespace dependencies
9
use \Charcoal\Factory\AbstractFactory;
10
11
/**
12
 * The map Factory resolves the **class name** from an associative array with the **type** key.
13
 *
14
 */
15
class MapFactory extends AbstractFactory
16
{
17
    /**
18
     * The class map array holds available types, in `[$type => $className]` format.
19
     * @var array $map
20
     */
21
    private $map = [];
22
23
    /**
24
     * Add a class name to the available types _map_.
25
     *
26
     * @param string $type      The type (class ident).
27
     * @param string $className The FQN of the class.
28
     * @throws InvalidArgumentException If the $type parameter is not a striing or the $className class does not exist.
29
     * @return FactoryInterface Chainable
30
     */
31
    public function addClass($type, $className)
32
    {
33
        if (!is_string($type)) {
34
            throw new InvalidArgumentException(
35
                'Type (class key) must be a string'
36
            );
37
        }
38
        if (!class_exists($className)) {
39
            throw new InvalidArgumentException(
40
                sprintf('Class "%s" is not a valid class name.', $className)
41
            );
42
        }
43
44
        $this->map[$type] = $className;
45
        return $this;
46
    }
47
48
    /**
49
     * Add multiple types, in a an array of `type` => `className`.
50
     *
51
     * @param array $map The map (key=>classname) to use.
52
     * @return FactoryInterface Chainable
53
     */
54
    public function setMap(array $map)
55
    {
56
        // Resets (overwrites) map.
57
        $this->map = [];
58
        foreach ($map as $type => $className) {
59
            $this->addClass($type, $className);
60
        }
61
        return $this;
62
    }
63
64
    /**
65
     * Get the map of all types in `[$type => $class]` format.
66
     *
67
     * @return array
68
     */
69
    public function map()
70
    {
71
        return $this->map;
72
    }
73
74
    /**
75
     * The "Map Factory" implements `AbstractFactory`'s `resolve()` abstract method
76
     * by fetching the class ident from the `map` member array.
77
     *
78
     * If the object's `type` is not defined in the class map, an exception will be thrown.
79
     *
80
     * @param string $type The "type" of object to resolve (the object ident).
81
     * @throws InvalidArgumentException If the type parameter is not a string.
82
     * @return string
83
     */
84
    public function resolve($type)
85
    {
86
        if (!is_string($type)) {
87
            throw new InvalidArgumentException(
88
                'Can not resolve class ident: type must be a string'
89
            );
90
        }
91
92
        $map = $this->map();
93
        if (!isset($map[$type])) {
94
            throw new InvalidArgumentException(
95
                'Invalid type (not defined in class map)'
96
            );
97
        }
98
        return $map[$type];
99
    }
100
101
    /**
102
     * The "Map Factory" implements `AbstractFactory`'s `is_resolvable()` abstract method
103
     * by ensuring the class ident is defined in the class map and is a validd class.
104
     *
105
     * @param string $type The "type" of object to resolve (the object ident).
106
     * @throws InvalidArgumentException If the type parameter is not a string.
107
     * @return boolean
108
     */
109
    public function isResolvable($type)
110
    {
111
        if (!is_string($type)) {
112
            throw new InvalidArgumentException(
113
                'Can not check resolvable: type must be a string'
114
            );
115
        }
116
117
        $map = $this->map();
118
        if (!isset($map[$type])) {
119
            return false;
120
        }
121
122
        $className = $map[$type];
123
        return !!class_exists($className);
124
    }
125
}
126