Completed
Branch TASK/update-about-page (5cee29)
by
unknown
34:34 queued 26:08
created

FqcnLocator::setNamespace()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 10

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 3
nc 3
nop 2
dl 0
loc 10
rs 9.9332
c 0
b 0
f 0
1
<?php
2
3
namespace EventEspresso\core\services\locators;
4
5
use EE_Psr4AutoloaderInit;
6
use EventEspresso\core\exceptions\InvalidClassException;
7
use EventEspresso\core\exceptions\InvalidDataTypeException;
8
use EventEspresso\Core\Psr4Autoloader;
9
use FilesystemIterator;
10
11
/**
12
 * Class FqcnLocator
13
 * Description
14
 *
15
 * @package       Event Espresso
16
 * @author        Brent Christensen
17
 */
18
class FqcnLocator extends Locator
19
{
20
21
    /**
22
     * @var array $FQCNs
23
     */
24
    protected $FQCNs = array();
25
26
    /**
27
     * @var array $namespaces
28
     */
29
    protected $namespaces = array();
30
31
32
    /**
33
     * @access protected
34
     * @param string $namespace
35
     * @param string $namespace_base_dir
36
     * @throws InvalidDataTypeException
37
     */
38
    protected function setNamespace($namespace, $namespace_base_dir)
39
    {
40
        if (! is_string($namespace)) {
41
            throw new InvalidDataTypeException('$namespace', $namespace, 'string');
42
        }
43
        if (! is_string($namespace_base_dir)) {
44
            throw new InvalidDataTypeException('$namespace_base_dir', $namespace_base_dir, 'string');
45
        }
46
        $this->namespaces[ $namespace ] = $namespace_base_dir;
47
    }
48
49
50
    /**
51
     * @access public
52
     * @return array
53
     */
54
    public function getFQCNs()
55
    {
56
        return $this->FQCNs;
57
    }
58
59
60
    /**
61
     * @access public
62
     * @return int
63
     */
64
    public function count()
65
    {
66
        return count($this->FQCNs);
67
    }
68
69
70
    /**
71
     * given a valid namespace, will find all files that match the provided mask
72
     *
73
     * @access public
74
     * @param string|array $namespaces
75
     * @return array
76
     * @throws InvalidClassException
77
     * @throws InvalidDataTypeException
78
     */
79 View Code Duplication
    public function locate($namespaces)
80
    {
81
        if (! (is_string($namespaces) || is_array($namespaces))) {
82
            throw new InvalidDataTypeException('$namespaces', $namespaces, 'string or array');
83
        }
84
        foreach ((array) $namespaces as $namespace) {
85
            foreach ($this->findFQCNsByNamespace($namespace) as $key => $file) {
86
                $this->FQCNs[ $key ] = $file;
87
            }
88
        }
89
        return $this->FQCNs;
90
    }
91
92
93
    /**
94
     * given a partial namespace, will find all files in that folder
95
     * ** PLZ NOTE **
96
     * This assumes that all files within the specified folder should be loaded
97
     *
98
     * @access protected
99
     * @param string $partial_namespace
100
     * @return array
101
     * @throws InvalidClassException
102
     * @throws InvalidDataTypeException
103
     */
104
    protected function findFQCNsByNamespace($partial_namespace)
105
    {
106
        $iterator = new FilesystemIterator(
107
            $this->getDirectoryFromPartialNamespace($partial_namespace)
108
        );
109
        $iterator->setFlags(FilesystemIterator::CURRENT_AS_FILEINFO);
110
        $iterator->setFlags(FilesystemIterator::UNIX_PATHS);
111
        if (iterator_count($iterator) === 0) {
112
            return array();
113
        }
114
        foreach ($iterator as $file) {
115
            if ($file->isFile() && $file->getExtension() === 'php') {
116
                $file = $file->getPath() . DS . $file->getBasename('.php');
117
                foreach ($this->namespaces as $namespace => $base_dir) {
118
                    $namespace .= Psr4Autoloader::NS;
119
                    if (strpos($file, $base_dir) === 0) {
120
                        $this->FQCNs[] = Psr4Autoloader::NS . str_replace(
121
                            array($base_dir, DS),
122
                            array($namespace, Psr4Autoloader::NS),
123
                            $file
124
                        );
125
                    }
126
                }
127
            }
128
        }
129
        return $this->FQCNs;
130
    }
131
132
133
    /**
134
     * getDirectoryFromPartialNamespace
135
     *
136
     * @access protected
137
     * @param  string $partial_namespace almost fully qualified class name ?
138
     * @return string
139
     * @throws InvalidDataTypeException
140
     * @throws InvalidClassException
141
     */
142
    protected function getDirectoryFromPartialNamespace($partial_namespace)
143
    {
144
        if (empty($partial_namespace)) {
145
            throw new InvalidClassException($partial_namespace);
146
        }
147
        // load our PSR-4 Autoloader so we can get the list of registered namespaces from it
148
        $psr4_loader = EE_Psr4AutoloaderInit::psr4_loader();
149
        // breakup the incoming namespace into segments then loop thru them
150
        $namespace_segments = explode(Psr4Autoloader::NS, trim($partial_namespace, Psr4Autoloader::NS));
151
        // we're only interested in the first element, so pull that from the array
152
        $namespace = array_shift($namespace_segments);
153
        // check if there's a base directory registered for that namespace
154
        $prefix = $psr4_loader->prefixes($namespace . Psr4Autoloader::NS);
155
        // nope? then the incoming namespace is invalid
156
        if (empty($prefix) || empty($prefix[0])) {
157
            throw new InvalidClassException($partial_namespace);
158
        }
159
        $this->setNamespace($namespace, $prefix[0]);
160
        // but if it's good, add that base directory to the rest of the path, and return it
161
        return $prefix[0] . implode(DS, $namespace_segments) . DS;
162
    }
163
}
164