Completed
Branch Gutenberg/master (b3a823)
by
unknown
73:52 queued 60:28
created

ClassInterfaceCache   A

Complexity

Total Complexity 21

Size/Duplication

Total Lines 160
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 0

Importance

Changes 1
Bugs 1 Features 0
Metric Value
c 1
b 1
f 0
dl 0
loc 160
rs 10
wmc 21
lcom 1
cbo 0

8 Methods

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