Completed
Branch FET/11450/reserved-instance-in... (cfa977)
by
unknown
69:04 queued 55:58
created

ClassInterfaceCache::addAlias()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 12
Code Lines 8

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 3
eloc 8
nc 3
nop 3
dl 0
loc 12
rs 9.4285
c 0
b 0
f 0
1
<?php
2
3
namespace EventEspresso\core\services\loaders;
4
5
use EventEspresso\core\domain\values\FullyQualifiedName;
6
7
defined('EVENT_ESPRESSO_VERSION') || exit;
8
9
10
11
/**
12
 * Class ClassInterfaceCache
13
 * Tracks and caches the interfaces and their aliases implemented by classes
14
 * so that we are not continuously and/or repeatedly looking up that information
15
 *
16
 * @package EventEspresso\core\services\loaders
17
 * @author  Brent Christensen
18
 * @since   $VID:$
19
 */
20
class ClassInterfaceCache
21
{
22
23
    /**
24
     * array of interfaces indexed by FQCNs where values are arrays of interface FQNs
25
     *
26
     * @var string[][] $interfaces
27
     */
28
    private $interfaces = array();
29
30
    /**
31
     * @type string[][] $aliases
32
     */
33
    protected $aliases = array();
34
35
36
37
    /**
38
     * @param string $fqn
39
     * @return string
40
     */
41
    public function getFqn($fqn)
42
    {
43
        return $fqn instanceof FullyQualifiedName ? $fqn->string() : $fqn;
44
    }
45
46
47
48
    /**
49
     * @param string $fqn
50
     * @return array
51
     */
52
    public function getInterfaces($fqn)
53
    {
54
        $fqn = $this->getFqn($fqn);
55
        // have we already seen this FQCN ?
56
        if (! array_key_exists($fqn, $this->interfaces)) {
57
            $this->interfaces[ $fqn ] = array();
58
            if (class_exists($fqn)) {
59
                $this->interfaces[ $fqn ] = class_implements($fqn, false);
60
                $this->interfaces[ $fqn ] = $this->interfaces[ $fqn ] !== false
61
                    ? $this->interfaces[ $fqn ]
62
                    : array();
63
            }
64
        }
65
        return $this->interfaces[ $fqn ];
66
    }
67
68
69
    /**
70
     * @param string $fqn
71
     * @param string $interface
72
     * @return bool
73
     */
74
    public function hasInterface($fqn, $interface)
75
    {
76
        $fqn = $this->getFqn($fqn);
77
        $interfaces = $this->getInterfaces($fqn);
78
        return in_array($interface, $interfaces, true);
79
    }
80
81
82
    /**
83
     * adds an alias for a classname
84
     *
85
     * @param string $fqn       the class name that should be used (concrete class to replace interface)
86
     * @param string $alias     the class name that would be type hinted for (abstract parent or interface)
87
     * @param string $for_class the class that has the dependency (is type hinting for the interface)
88
     */
89
    public function addAlias($fqn, $alias, $for_class = '')
90
    {
91
        $fqn = $this->getFqn($fqn);
92
        $alias = $this->getFqn($alias);
93
        if ($for_class !== '') {
94
            if (! isset($this->aliases[ $for_class ])) {
95
                $this->aliases[ $for_class ] = array();
96
            }
97
            $this->aliases[ $for_class ][ $alias ] = $fqn;
98
        }
99
        $this->aliases[ $alias ] = $fqn;
100
    }
101
102
103
    /**
104
     * returns TRUE if the provided FQN is an alias
105
     *
106
     * @param string $fqn
107
     * @param string $for_class
108
     * @return bool
109
     */
110
    public function isAlias($fqn = '', $for_class = '')
111
    {
112
        $fqn = $this->getFqn($fqn);
113
        if ($this->isAliasForClass($fqn, $for_class)) {
114
            return true;
115
        }
116
        if($this->isDirectAlias($fqn)) {
117
            return true;
118
        }
119
        return false;
120
    }
121
122
123
    /**
124
     * returns TRUE if the provided FQN is an alias
125
     *
126
     * @param string $fqn
127
     * @return bool
128
     */
129
    protected function isDirectAlias($fqn = '')
130
    {
131
        return isset($this->aliases[ (string) $fqn ]);
132
    }
133
134
135
    /**
136
     * returns TRUE if the provided FQN is an alias for the specified class
137
     *
138
     * @param string $fqn
139
     * @param string $for_class
140
     * @return bool
141
     */
142
    protected function isAliasForClass($fqn = '', $for_class = '')
143
    {
144
        return (
145
            $for_class !== ''
146
            && isset($this->aliases[ (string) $for_class ][ (string) $fqn ])
147
        );
148
    }
149
150
151
    /**
152
     * returns FQN for provided alias if one exists, otherwise returns the original FQN
153
     * functions recursively, so that multiple aliases can be used to drill down to a FQN
154
     *  for example:
155
     *      if the following two entries were added to the aliases array:
156
     *          array(
157
     *              'interface_alias'           => 'some\namespace\interface'
158
     *              'some\namespace\interface'  => 'some\namespace\classname'
159
     *          )
160
     *      then one could use Loader::getNew( 'interface_alias' )
161
     *      to load an instance of 'some\namespace\classname'
162
     *
163
     * @param string $alias
164
     * @param string $for_class
165
     * @return string
166
     */
167
    public function getFqnForAlias($alias = '', $for_class = '')
168
    {
169
        $alias = $this->getFqn($alias);
170
        if ($this->isAliasForClass($alias, $for_class)) {
171
            return $this->getFqnForAlias($this->aliases[ (string) $for_class ][ (string) $alias ], $for_class);
172
        }
173
        if ($this->isDirectAlias($alias)) {
174
            return $this->getFqnForAlias($this->aliases[ (string) $alias ], '');
175
        }
176
        return $alias;
177
    }
178
}
179