Total Complexity | 45 |
Total Lines | 313 |
Duplicated Lines | 0 % |
Changes | 22 | ||
Bugs | 4 | Features | 2 |
Complex classes like Suricate often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.
Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.
While breaking up the class, it is a good idea to analyze how other classes use Suricate, and based on these observations, apply Extract Interface, too.
1 | <?php |
||
48 | class Suricate |
||
49 | { |
||
50 | const VERSION = '0.6.0'; |
||
51 | |||
52 | const CONF_DIR = '/conf/'; |
||
53 | |||
54 | private $config = []; |
||
55 | private $configFile = []; |
||
56 | |||
57 | private $useAutoloader = false; |
||
58 | |||
59 | private static $servicesContainer; |
||
60 | private static $servicesRepository; |
||
61 | |||
62 | private $servicesList = [ |
||
63 | 'App' => App::class, |
||
64 | 'Cache' => Cache::class, |
||
65 | 'CacheMemcache' => CacheMemcache::class, |
||
66 | 'CacheMemcached' => CacheMemcached::class, |
||
67 | 'CacheRedis' => CacheRedis::class, |
||
68 | 'CacheApc' => CacheApc::class, |
||
69 | 'CacheFile' => CacheFile::class, |
||
70 | 'Curl' => Curl::class, |
||
71 | 'Database' => Database::class, |
||
72 | 'Error' => Error::class, |
||
73 | 'EventDispatcher' => EventDispatcher::class, |
||
74 | 'I18n' => I18n::class, |
||
75 | 'Logger' => Logger::class, |
||
76 | 'Request' => Request::class, |
||
77 | 'Response' => Request::class, |
||
78 | 'Router' => Router::class, |
||
79 | 'Session' => Session::class, |
||
80 | 'SessionNative' => SessionNative::class, |
||
81 | 'Migration' => MigrationService::class, |
||
82 | ]; |
||
83 | |||
84 | /** |
||
85 | * Suricate contructor |
||
86 | * |
||
87 | * @param array $paths Application paths |
||
88 | * @param string|array|null $configFile path of configuration file(s) |
||
89 | * |
||
90 | * @SuppressWarnings(PHPMD.StaticAccess) |
||
91 | */ |
||
92 | public function __construct($paths = [], $configFile = null) |
||
93 | { |
||
94 | if ($configFile !== null) { |
||
95 | $this->setConfigFile($configFile); |
||
96 | } |
||
97 | |||
98 | // Load helpers |
||
99 | require_once __DIR__ . DIRECTORY_SEPARATOR . 'Helper.php'; |
||
100 | |||
101 | $this->loadConfig(); |
||
102 | $this->setAppPaths($paths); |
||
103 | |||
104 | if ($this->useAutoloader) { |
||
105 | // Configure autoloader |
||
106 | require_once __DIR__ . DIRECTORY_SEPARATOR . 'AutoLoader.php'; |
||
107 | AutoLoader::register(); |
||
108 | } |
||
109 | |||
110 | // Define error handler |
||
111 | set_exception_handler([Error::class, 'handleException']); |
||
112 | set_error_handler([Error::class, 'handleError']); |
||
113 | register_shutdown_function([Error::class, 'handleShutdownError']); |
||
114 | |||
115 | self::$servicesRepository = new Container(); |
||
116 | |||
117 | $this->initServices(); |
||
118 | } |
||
119 | |||
120 | /** |
||
121 | * Get app configuration |
||
122 | * |
||
123 | * @return array |
||
124 | */ |
||
125 | public function getConfig(): array |
||
126 | { |
||
127 | return $this->config; |
||
128 | } |
||
129 | |||
130 | private function setAppPaths($paths = []) |
||
131 | { |
||
132 | foreach ($paths as $key => $value) { |
||
133 | $this->config['App']['path.' . $key] = realpath($value); |
||
134 | } |
||
135 | |||
136 | return $this; |
||
137 | } |
||
138 | /** |
||
139 | * Initialize Framework services |
||
140 | * @return void |
||
141 | */ |
||
142 | private function initServices() |
||
182 | } |
||
183 | |||
184 | public static function hasService(string $serviceName): bool |
||
185 | { |
||
186 | return isset(self::$servicesContainer[$serviceName]); |
||
187 | } |
||
188 | |||
189 | public static function listServices(): array |
||
190 | { |
||
191 | return self::$servicesContainer->getKeys(); |
||
192 | } |
||
193 | |||
194 | private function setConfigFile($configFile) |
||
195 | { |
||
196 | foreach ((array) $configFile as $file) { |
||
197 | if (is_file($file)) { |
||
198 | $this->configFile[] = $file; |
||
199 | } |
||
200 | } |
||
201 | |||
202 | return $this; |
||
203 | } |
||
204 | |||
205 | private function parseYamlConfig($filename) { |
||
206 | return yaml_parse_file($filename, 0, $ndocs, |
||
207 | [ |
||
208 | '!include' => function($value, $tag, $flags) use($filename) |
||
209 | { |
||
210 | $directory = dirname($filename); |
||
211 | return $this->parseYamlConfig("$directory/$value"); |
||
212 | } |
||
213 | ]); |
||
214 | } |
||
215 | /** |
||
216 | * Load framework configuration from ini file |
||
217 | * @return void |
||
218 | */ |
||
219 | private function loadConfig() |
||
263 | } |
||
264 | |||
265 | private function configureAppMode() |
||
317 | } |
||
318 | /** |
||
319 | * Default setup template |
||
320 | * @return array setup |
||
321 | */ |
||
322 | private function getDefaultConfig() |
||
323 | { |
||
324 | return [ |
||
325 | 'Router' => [], |
||
326 | 'Logger' => [ |
||
327 | 'enabled' => true |
||
328 | ], |
||
329 | 'App' => ['base_uri' => '/'] |
||
330 | ]; |
||
331 | } |
||
332 | |||
333 | public function run() |
||
334 | { |
||
335 | self::$servicesContainer['Router']->doRouting(); |
||
336 | } |
||
337 | |||
338 | public static function __callStatic($name, $arguments) |
||
345 | } |
||
346 | |||
347 | public function registerService(string $serviceName, string $serviceClass): self |
||
348 | { |
||
349 | if (isset(self::$servicesContainer[$serviceName])) { |
||
350 | throw new InvalidArgumentException('Service ' . $serviceName . ' already registered'); |
||
361 | } |
||
362 | } |
||
363 |
This check looks for parameters that have been defined for a function or method, but which are not used in the method body.