ClassLoader   A
last analyzed

Complexity

Total Complexity 27

Size/Duplication

Total Lines 176
Duplicated Lines 6.82 %

Coupling/Cohesion

Components 2
Dependencies 0

Importance

Changes 0
Metric Value
dl 12
loc 176
rs 10
c 0
b 0
f 0
wmc 27
lcom 2
cbo 0

13 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 3 1
A __clone() 0 3 1
A getInstance() 0 6 2
A addPath() 0 14 4
A registerNamespacedPath() 0 4 1
A registerClassesPath() 0 4 1
A registerAlias() 0 4 1
A autoload() 0 8 2
A lookInAliases() 0 18 4
A splitClassName() 0 5 1
A loadNamespacedClass() 6 13 4
A loadClass() 6 10 3
A includeClass() 0 7 2

How to fix   Duplicated Code   

Duplicated Code

Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.

Common duplication problems, and corresponding solutions are:

1
<?php
2
3
/**
4
 * require_once APPPATH . 'libraries' . DIRECTORY_SEPARATOR . 'ClassLoader.php';
5
 * ClassLoader::getInstance()
6
 *     ->registerNamespacedPath(APPPATH)
7
 *     ->registerNamespacedPath(APPPATH . 'modules');
8
 *
9
 * @author ailok <[email protected]>
10
 *
11
 */
12
class ClassLoader
0 ignored issues
show
Coding Style introduced by
Since you have declared the constructor as private, maybe you should also declare the class as final.
Loading history...
13
{
14
15
    const EXT = '.php';
16
    const DS = DIRECTORY_SEPARATOR;
17
18
    private static $instance;
19
20
    private $namespacedPaths = [];
21
22
    private $aliases = [];
23
24
    private $classesPaths = [];
25
26
    private function __construct() {
27
        spl_autoload_register([$this, 'autoload'], false);
28
    }
29
30
    private function __clone() {
31
32
    }
33
34
    /**
35
     *
36
     * @return ClassLoader
37
     */
38
    public static function getInstance() {
39
        if (self::$instance == null) {
40
            self::$instance = new self;
41
        }
42
        return self::$instance;
43
    }
44
45
    /**
46
     *
47
     * @param array $array
48
     * @param string $path
49
     * @param string (optional) $key
50
     * @param string $key
51
     * @throws \Exception
52
     */
53
    private function addPath(array &$array, $path, $key = null) {
54
        if (!is_dir($path)) {
55
            throw new \Exception('Error registering [' . $path . '] - folder do not exist');
56
        }
57
        if (in_array($path, $array)) {
58
            return;
59
        }
60
61
        if ($key == null) {
62
            $array[] = $path;
63
        } else {
64
            $array[$key] = $path;
65
        }
66
    }
67
68
    /**
69
     *
70
     * @param string $path
71
     * @return \ClassLoader
72
     */
73
    public function registerNamespacedPath($path) {
74
        $this->addPath($this->namespacedPaths, $path);
75
        return $this;
76
    }
77
78
    /**
79
     *
80
     * @param string $path
81
     * @return \ClassLoader
82
     */
83
    public function registerClassesPath($path) {
84
        $this->addPath($this->classesPaths, $path);
85
        return $this;
86
    }
87
88
    /**
89
     *
90
     * @param string $path
91
     * @param string $name
92
     * @return \ClassLoader
93
     */
94
    public function registerAlias($path, $name) {
95
        $this->addPath($this->aliases, $path, $name);
96
        return $this;
97
    }
98
99
    /**
100
     * Function for registering in spl_autoload_register()
101
     * @param string $className
102
     */
103
    public function autoload($className) {
104
        $className = ltrim($className, '\\');
105
        if (strpos($className, '\\') > 0) {
106
            $this->loadNamespacedClass($className);
107
        } else {
108
            $this->loadClass($className);
109
        }
110
    }
111
112
    /**
113
     * @param string $className
114
     */
115
    private function lookInAliases($className) {
116
        // getting first element of namespace path and search it in namespaces
117
        list($namespace, $fileName) = $this->splitClassName($className);
118
        if (array_key_exists($namespace, $this->aliases) && strpos($namespace, '\\') > 0) {
119
            $classPath = $this->aliases[$namespace] . '/' . $fileName . self::EXT;
120
            $this->includeClass($classPath);
121
            return true;
122
        }
123
124
        $parts = explode('\\', $className);
125
        $alias = array_shift($parts);
126
        if (!array_key_exists($alias, $this->aliases)) {
127
            return false;
128
        }
129
        $pathToNamepace = rtrim($this->aliases[$alias], self::DS) . self::DS;
130
        $classPath = $pathToNamepace . implode(self::DS, $parts) . self::EXT;
131
        return $this->includeClass($classPath);
132
    }
133
134
    /**
135
     *
136
     * @param string $className
137
     * @return array [namespace, fileName]
138
     */
139
    private function splitClassName($className) {
140
        $parts = explode('\\', $className);
141
        $fileName = array_pop($parts);
142
        return [implode('\\', $parts), $fileName];
143
    }
144
145
    /**
146
     * @param string $className
147
     */
148
    private function loadNamespacedClass($className) {
149
        if (true == $this->lookInAliases($className)) {
150
            return;
151
        }
152
        $namespacedClassPath = str_replace('\\', self::DS, $className);
153
        $namespacedPathsCount = count($this->namespacedPaths);
154 View Code Duplication
        for ($i = 0; $i < $namespacedPathsCount; $i++) {
155
            $classPath = rtrim($this->namespacedPaths[$i], self::DS) . self::DS . $namespacedClassPath . self::EXT;
156
            if (true == $this->includeClass($classPath)) {
157
                return;
158
            }
159
        }
160
    }
161
162
    /**
163
     * @param string $className
164
     */
165
    private function loadClass($className) {
166
        $classesPathsCount = count($this->classesPaths);
167
168 View Code Duplication
        for ($i = 0; $i < $classesPathsCount; $i++) {
169
            $classPath = rtrim($this->classesPaths[$i], self::DS) . self::DS . $className . self::EXT;
170
            if (true == $this->includeClass($classPath)) {
171
                return;
172
            }
173
        }
174
    }
175
176
    /**
177
     * @param string $classPath
178
     */
179
    private function includeClass($classPath) {
180
        if (file_exists($classPath)) {
181
            include_once $classPath;
182
            return true;
183
        }
184
        return false;
185
    }
186
187
}