Completed
Push — master ( 71d2f0...8e5780 )
by Derek
02:14
created

Autoloader::includeClass()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 21
Code Lines 11

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 14
CRAP Score 3

Importance

Changes 11
Bugs 1 Features 1
Metric Value
c 11
b 1
f 1
dl 0
loc 21
ccs 14
cts 14
cp 1
rs 9.3142
cc 3
eloc 11
nc 3
nop 1
crap 3
1
<?php
2
namespace Subreality\Dilmun\Nabu;
3
4
use Subreality\Dilmun\LoggedClassTrait;
5
6
/**
7
 * PSR-4 compliant autoloading class
8
 *
9
 * @author derek
10
 */
11
class Autoloader
12
{
13
    use LoggedClassTrait;
14
15
    protected $packages = array();
16
17
    /**
18
     * Registers the includeClass function as an autoloader.
19
     *
20
     * @see Autoloader::includeClass
21
     *
22
     * @return void
23
     */
24 2
    public function register()
25
    {
26 2
        spl_autoload_register(array($this,"includeClass"));
27 2
    }
28
29
    /**
30
     * Registers a given package with an associated path.
31
     *
32
     * Duplicate package/path combinations will not be re-registered.
33
     *
34
     * @param string $package   The name of the package to be registered
35
     * @param string $path      The path to be associated with the registered package
36
     *
37
     * @return void
38
     */
39 14
    public function registerPackages($package, $path)
40
    {
41 14
        $this->updateLog("info", "Preparing package {$package} for registration with path {$path}.");
42
43 14
        $package = trim($package, "\\");
44 14
        $package = $package . "\\";
45
46 14
        $path = rtrim($path, DIRECTORY_SEPARATOR);
47 14
        $path = $path . "/";
48
49 14
        $path_registered = $this->registrationExists($package, $path);
50
51 14
        if (!$path_registered) {
52 10
            $this->packages[$package][] = $path;
53
54 10
            $this->updateLog("info", "Registered index {$package} as {$path}");
55 10
        }
56 14
    }
57
58
    /**
59
     * Returns an array of registered packages.
60
     *
61
     * @return array
62
     */
63 9
    public function getRegisteredPackages()
64
    {
65 9
        return $this->packages;
66
    }
67
68
    /**
69
     * Includes the file corresponding with the class name to be autoloaded
70
     *
71
     * @param string $class Class name as defined by PHP autoloading
72
     *
73
     * @return void
74
     */
75 3
    protected function includeClass($class)
76
    {
77 3
        $this->updateLog("info", "Setting up {$class} class for inclusion.");
78
79 3
        $class_bits = explode("\\", $class);
80
81 3
        $package = "";
0 ignored issues
show
Coding Style introduced by
Equals sign not aligned with surrounding assignments; expected 7 spaces but found 1 space

This check looks for multiple assignments in successive lines of code. It will report an issue if the operators are not in a straight line.

To visualize

$a = "a";
$ab = "ab";
$abc = "abc";

will produce issues in the first and second line, while this second example

$a   = "a";
$ab  = "ab";
$abc = "abc";

will produce no issues.

Loading history...
82 3
        $package_stack = array();
83
84 3
        foreach ($class_bits as $bit) {
85 3
            $package = $package . $bit . "\\";
86
87 3
            $package_registered = $this->packageRegistered($package);
88
89 3
            if ($package_registered) {
90 2
                $package_stack[] = $package;
91 2
            }
92 3
        }
93
94 3
        $this->loadPackageStack($class, $package_stack);
95 3
    }
96
97
    /**
98
     * Attempts to load a class from a stack of packages
99
     *
100
     * @param string $class
101
     * @param array $package_stack
102
     *
103
     * @return bool
104
     */
105 3
    protected function loadPackageStack($class, array $package_stack)
106
    {
107 3
        foreach ($package_stack as $package) {
108 2
            $package_length = strlen($package);
109
110 2
            $class_path = substr($class, $package_length);
111
112 2
            $this->updateLog("debug", "Found class path {$class_path} in {$class} given {$package}");
113
114 2
            $package_loaded = $this->loadPackage($package, $class_path);
115
116 2
            if ($package_loaded) {
117 1
                $this->updateLog("info", "Loaded {$class_path} using package {$package}");
118 1
                return true;
119
            }
120 3
        }
121
122 2
        $this->updateLog("alert", "No files found for {$class} in registered packages!");
123
124 2
        return false;
125
    }
126
127
    /**
128
     * Loads a package based on registered paths associated with the package.
129
     *
130
     * @param string $package_name  The name of the package in Vendor\Package format
131
     * @param string $class_name    The full, relative name of the class with the vendor and package names stripped
132
     *
133
     * @return bool                 The path to the class on success; otherwise false
134
     */
135 2
    protected function loadPackage($package_name, $class_name)
136
    {
137 2
        $this->updateLog("info", "Working on loading {$class_name} from {$package_name}");
138
139 2
        $class_file_found = false;
140
141 2
        foreach ($this->packages[$package_name] as $path) {
142 2
            $converted_class = str_replace('\\', DIRECTORY_SEPARATOR, $class_name);
143 2
            $class_path      = $path . $converted_class . ".php";
144
145 2
            $this->updateLog("debug", "Class file path is {$class_path}");
146
147 2
            if (file_exists($class_path)) {
148 1
                $this->updateLog("debug", "File {$class_path} exists; including file");
149
150
                /** @noinspection PhpIncludeInspection */
151 1
                require $class_path;
152
153 1
                $class_file_found = true;
154
155 1
                $this->updateLog("info", "Completed loading {$class_path}");
156 1
            } else {
157 2
                $this->updateLog("debug", "File {$class_path} does not exist");
158
159 2
                $class_file_found = false;
160
            }
161 2
        }
162
163 2
        return $class_file_found;
164
    }
165
166
    /**
167
     * Determines whether a given package is registered with the Autoloader
168
     *
169
     * @param string $package   The package to check
170
     *
171
     * @return bool             Returns true if the given package is registered
172
     *                          Returns false if the given package is not registered
173
     */
174 14
    private function packageRegistered($package)
175
    {
176 14
        $package_registered = array_key_exists($package, $this->packages);
177
178 14
        if ($package_registered) {
179 12
            $this->updateLog("info", "Package {$package} is registered");
180 12
        } else {
181 13
            $this->updateLog("info", "Package {$package} is not registered");
182
        }
183
184 14
        return $package_registered;
185
    }
186
187
    /**
188
     * Determines whether a given package/path combination has already been registered with the Autoloader
189
     *
190
     * @param string $package   The package to check
191
     * @param string $path      The path to check
192
     *
193
     * @return bool             Returns true if the given path has been registered with the given package
194
     *                          Returns false if the given path has not been registered with the given package
195
     */
196 14
    private function registrationExists($package, $path)
197
    {
198 14
        $package_registered = $this->packageRegistered($package);
199
200 14
        if ($package_registered) {
201 12
            $path_registered = array_search($path, $this->packages[$package]);
202
203 12
            if ($path_registered !== false) {
204 12
                $path_registered = true;
205
206 12
                $this->updateLog("info", "Path {$path} already registered for package {$package}");
207 12
            }
208 12
        } else {
209 10
            $path_registered = false;
210
        }
211
212 14
        return $path_registered;
213
    }
214
}
215