Complex classes like Core 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. You can also have a look at the cohesion graph to spot any un-connected, or weakly-connected components.
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 Core, and based on these observations, apply Extract Interface, too.
| 1 | <?php |
||
| 24 | class Core implements SystemInterface |
||
| 25 | { |
||
| 26 | /* Rendering models */ |
||
| 27 | /** Standard algorithm for view rendering */ |
||
| 28 | const RENDER_STANDART = 1; |
||
| 29 | /** View rendering algorithm from array of view variables */ |
||
| 30 | const RENDER_VARIABLE = 3; |
||
| 31 | |||
| 32 | /** @var ResourceMap Current web-application resource map */ |
||
| 33 | public $map; |
||
| 34 | |||
| 35 | /** @var Module[] Collection of loaded modules */ |
||
| 36 | public $module_stack = array(); |
||
| 37 | /** @var string Path to current web-application */ |
||
| 38 | public $system_path = __SAMSON_CWD__; |
||
| 39 | /** @var string View path loading mode */ |
||
| 40 | public $render_mode = self::RENDER_STANDART; |
||
| 41 | /** @var Module Pointer to current active module */ |
||
| 42 | protected $active = null; |
||
| 43 | /** @var bool Flag for outputting layout template, used for asynchronous requests */ |
||
| 44 | protected $async = false; |
||
| 45 | /** @var string Path to main system template */ |
||
| 46 | protected $template_path = __SAMSON_DEFAULT_TEMPLATE; |
||
| 47 | /** @var string Current system environment */ |
||
| 48 | protected $environment; |
||
| 49 | |||
| 50 | /** |
||
| 51 | * Core constructor. |
||
| 52 | * |
||
| 53 | * @param ResourceMap|null $map system resources |
||
| 54 | */ |
||
| 55 | public function __construct(ResourceMap $map = null) |
||
| 56 | { |
||
| 57 | if (!isset($map)) { |
||
| 58 | // Get correct web-application path |
||
| 59 | $this->system_path = __SAMSON_CWD__; |
||
| 60 | |||
| 61 | // Get web-application resource map |
||
| 62 | $this->map = ResourceMap::get($this->system_path, false, array('src/')); |
||
| 63 | } else { // Use data from passed map |
||
| 64 | $this->map = $map; |
||
| 65 | $this->system_path = $map->entryPoint; |
||
| 66 | } |
||
| 67 | |||
| 68 | // Connect static collection with this dynamic field to avoid duplicates |
||
| 69 | $this->module_stack = &Module::$instances; |
||
| 70 | |||
| 71 | // Temporary add template worker |
||
| 72 | $this->subscribe('core.rendered', array($this, 'generateTemplate')); |
||
| 73 | |||
| 74 | $whoops = new \Whoops\Run; |
||
| 75 | $whoops->pushHandler(new \Whoops\Handler\PrettyPageHandler); |
||
| 76 | $whoops->register(); |
||
| 77 | |||
| 78 | // Fire core creation event |
||
| 79 | Event::fire('core.created', array(&$this)); |
||
| 80 | |||
| 81 | // Signal core configure event |
||
| 82 | Event::signal('core.configure', array($this->system_path . __SAMSON_CONFIG_PATH)); |
||
| 83 | } |
||
| 84 | |||
| 85 | /** |
||
| 86 | * Generic wrap for Event system subscription. |
||
| 87 | * @see \samson\core\\samsonphp\event\Event::subscribe() |
||
| 88 | * |
||
| 89 | * @param string $key Event identifier |
||
| 90 | * @param callable $handler Event handler |
||
| 91 | * @param array $params Event parameters |
||
| 92 | * |
||
| 93 | * @return $this Chaining |
||
| 94 | */ |
||
| 95 | public function subscribe($key, $handler, $params = array()) |
||
| 96 | { |
||
| 97 | Event::subscribe($key, $handler, $params); |
||
| 98 | |||
| 99 | return $this; |
||
| 100 | } |
||
| 101 | |||
| 102 | /** |
||
| 103 | * Change current system working environment or receive |
||
| 104 | * current system enviroment if no arguments are passed. |
||
| 105 | * |
||
| 106 | * @param string $environment Environment identifier |
||
| 107 | * |
||
| 108 | * TODO: Function has two different logics - needs to be changed! |
||
| 109 | * @return $this|string Chaining or current system environment |
||
| 110 | 1 | */ |
|
| 111 | public function environment($environment = Scheme::BASE) |
||
| 112 | { |
||
| 113 | if (func_num_args() !== 0) { |
||
| 114 | $this->environment = $environment; |
||
| 115 | |||
| 116 | // Signal core environment change |
||
| 117 | Event::signal('core.environment.change', array($environment, &$this)); |
||
| 118 | return $this; |
||
| 119 | } |
||
| 120 | |||
| 121 | 1 | return $this->environment; |
|
| 122 | } |
||
| 123 | |||
| 124 | /** |
||
| 125 | * Generate special response header triggering caching mechanisms |
||
| 126 | * @param int $cacheLife Amount of seconds for cache(default 3600 - 1 hour) |
||
| 127 | * @param string $accessibility Cache-control accessibility value(default public) |
||
| 128 | */ |
||
| 129 | public function cached($cacheLife = 3600, $accessibility = 'public') |
||
| 130 | { |
||
| 131 | static $cached; |
||
| 132 | // Protect sending cached headers once |
||
| 133 | if (!isset($cached) or $cached !== true) { |
||
| 134 | header('Expires: ' . gmdate('D, d M Y H:i:s T', time() + $cacheLife)); |
||
| 135 | header('Cache-Control: ' . $accessibility . ', max-age=' . $cacheLife); |
||
| 136 | header('Pragma: cache'); |
||
| 137 | |||
| 138 | $cached = true; |
||
| 139 | } |
||
| 140 | } |
||
| 141 | |||
| 142 | /** |
||
| 143 | * Set asynchronous mode. |
||
| 144 | * This mode will not output template and will just path everything that |
||
| 145 | * was outputted to client. |
||
| 146 | * |
||
| 147 | * @param bool $async True to switch to asynchronous output mode |
||
| 148 | * |
||
| 149 | * @return $this Chaining |
||
| 150 | */ |
||
| 151 | public function async($async) |
||
| 152 | { |
||
| 153 | $this->async = $async; |
||
| 154 | |||
| 155 | return $this; |
||
| 156 | } |
||
| 157 | |||
| 158 | /** @see iCore::path() */ |
||
| 159 | public function path($path = null) |
||
| 160 | { |
||
| 161 | // Если передан аргумент |
||
| 162 | if (func_num_args()) { |
||
| 163 | // Сформируем новый относительный путь к главному шаблону системы |
||
| 164 | $this->template_path = $path . $this->template_path; |
||
| 165 | |||
| 166 | // Сохраним относительный путь к Веб-приложению |
||
| 167 | $this->system_path = $path; |
||
| 168 | |||
| 169 | // Продолжил цепирование |
||
| 170 | return $this; |
||
| 171 | } |
||
| 172 | |||
| 173 | // Вернем текущее значение |
||
| 174 | return $this->system_path; |
||
| 175 | } |
||
| 176 | |||
| 177 | /** @see iModule::active() */ |
||
| 178 | public function &active(iModule &$module = null) |
||
| 179 | { |
||
| 180 | // Сохраним старый текущий модуль |
||
| 181 | $old = &$this->active; |
||
| 182 | |||
| 183 | // Если передано значение модуля для установки как текущий - проверим и установим его |
||
| 184 | if (isset($module)) { |
||
| 185 | $this->active = &$module; |
||
| 186 | } |
||
| 187 | |||
| 188 | // Вернем значение текущего модуля |
||
| 189 | return $old; |
||
| 190 | } |
||
| 191 | |||
| 192 | /** |
||
| 193 | * Retrieve module instance by identifier. |
||
| 194 | * |
||
| 195 | * @param string|null $module Module identifier |
||
| 196 | * |
||
| 197 | * @return null|Module Found or active module |
||
| 198 | */ |
||
| 199 | public function &module($module = null) |
||
| 200 | { |
||
| 201 | $return = null; |
||
| 202 | |||
| 203 | // Ничего не передано - вернем текущуй модуль системы |
||
| 204 | if (!isset($module) && isset($this->active)) { |
||
| 205 | $return = &$this->active; |
||
| 206 | } elseif (is_object($module)) { |
||
| 207 | $return = &$module; |
||
| 208 | } elseif (is_string($module) && isset($this->module_stack[$module])) { |
||
| 209 | $return = &$this->module_stack[$module]; |
||
| 210 | } |
||
| 211 | |||
| 212 | // Ничего не получилось вернем ошибку |
||
| 213 | if ($return === null) { |
||
| 214 | e('Не возможно получить модуль(##) системы', E_SAMSON_CORE_ERROR, array($module)); |
||
| 215 | } |
||
| 216 | |||
| 217 | return $return; |
||
| 218 | } |
||
| 219 | |||
| 220 | /** |
||
| 221 | * Unload module from core. |
||
| 222 | * |
||
| 223 | * @param string $moduleID Module identifier |
||
| 224 | */ |
||
| 225 | public function unload($moduleID) |
||
| 226 | { |
||
| 227 | if (isset($this->module_stack[$moduleID])) { |
||
| 228 | unset($this->module_stack[$moduleID]); |
||
| 229 | } |
||
| 230 | } |
||
| 231 | |||
| 232 | /** |
||
| 233 | * Insert generic html template tags and data |
||
| 234 | * |
||
| 235 | * @param string $templateHtml Generated HTML |
||
| 236 | * |
||
| 237 | * @deprecated Must be moved to a new HTML output object |
||
| 238 | * @return mixed Changed HTML template |
||
| 239 | */ |
||
| 240 | public function generateTemplate(&$templateHtml) |
||
| 262 | |||
| 263 | /** |
||
| 264 | 2 | * Start SamsonPHP framework. |
|
| 265 | * |
||
| 266 | * @param string $default Default module identifier |
||
| 267 | * |
||
| 268 | * @throws ViewPathNotFound |
||
| 269 | */ |
||
| 270 | public function start($default) |
||
| 271 | 2 | { |
|
| 272 | // TODO: Change ExternalModule::init() signature |
||
| 273 | // Fire core started event |
||
| 274 | 2 | Event::fire('core.started'); |
|
| 275 | |||
| 276 | // TODO: Does not see why it should be here |
||
| 277 | // Set main template path |
||
| 278 | 2 | $this->template($this->template_path); |
|
| 279 | |||
| 280 | 2 | // Security layer |
|
| 281 | $securityResult = true; |
||
| 282 | 2 | // Fire core security event |
|
| 283 | 2 | Event::fire('core.security', array(&$this, &$securityResult)); |
|
| 284 | |||
| 285 | /** @var mixed $result External route controller action result */ |
||
| 286 | 2 | $result = false; |
|
| 287 | |||
| 288 | 2 | // If we have passed security application layer |
|
| 289 | if ($securityResult) { |
||
| 290 | 2 | // Fire core routing event - go to routing application layer |
|
| 291 | Event::signal('core.routing', array(&$this, &$result, $default)); |
||
| 292 | } |
||
| 293 | |||
| 294 | // If no one has passed back routing callback |
||
| 295 | 2 | if (!isset($result) || $result === false) { |
|
| 296 | // Fire core e404 - routing failed event |
||
| 297 | $result = Event::signal('core.e404', array(url()->module, url()->method)); |
||
| 298 | } |
||
| 299 | |||
| 300 | // Response |
||
| 301 | $output = ''; |
||
| 302 | |||
| 303 | // If this is not asynchronous response and controller has been executed |
||
| 304 | if (!$this->async && ($result !== false)) { |
||
| 305 | // Store module data |
||
| 306 | $data = $this->active->toView(); |
||
| 307 | |||
| 308 | // Render main template |
||
| 309 | $output = $this->render($this->template_path, $data); |
||
| 310 | |||
| 311 | // Fire after render event |
||
| 312 | Event::fire('core.rendered', array(&$output, &$data, &$this->active)); |
||
| 313 | } |
||
| 314 | |||
| 315 | // Output results to client |
||
| 316 | echo $output; |
||
| 317 | |||
| 318 | // Fire ended event |
||
| 319 | Event::fire('core.ended', array(&$output)); |
||
| 320 | 2 | } |
|
| 321 | |||
| 322 | /** @see iCore::template() */ |
||
|
1 ignored issue
–
show
|
|||
| 323 | 2 | public function template( $template = NULL, $absolutePath = false ) |
|
| 324 | { |
||
| 325 | // Если передан аргумент |
||
| 326 | 2 | if( func_num_args() ){ |
|
| 327 | $this->template_path = ($absolutePath)?$template:$this->active->path().$template; |
||
| 328 | } |
||
| 329 | 2 | ||
| 330 | // Аргументы не переданы - вернем текущий путь к шаблону системы |
||
| 331 | return $this->template_path; |
||
| 332 | 2 | } |
|
| 333 | |||
| 334 | /** |
||
| 335 | 2 | * Render file to a buffer. |
|
| 336 | * |
||
| 337 | * @param string $view Path to file |
||
| 338 | 2 | * @param array $data Collection of variables to path to file |
|
| 339 | * |
||
| 340 | * @return string Rendered file contents |
||
| 341 | * @throws ViewPathNotFound |
||
| 342 | */ |
||
| 343 | public function render($view, $data = array()) |
||
| 407 | |||
| 408 | //[PHPCOMPRESSOR(remove,start)] |
||
| 409 | 2 | ||
| 410 | 2 | /** |
|
| 411 | 2 | * Load system from composer.json |
|
| 412 | * @param string $dependencyFilePath Path to dependencies file |
||
| 413 | * @return $this Chaining |
||
| 414 | 2 | */ |
|
| 415 | public function composer($dependencyFilePath = null) |
||
| 474 | |||
| 475 | /** |
||
| 476 | * Load module from path to core. |
||
| 477 | * |
||
| 478 | * @param string $path Path for module loading |
||
| 479 | * @param array $parameters Collection of loading parameters |
||
| 480 | * |
||
| 481 | * @return $this|bool |
||
| 482 | */ |
||
| 483 | public function load($path, $parameters = array()) |
||
| 565 | //[PHPCOMPRESSOR(remove,end)] |
||
| 566 | |||
| 567 | 7 | /** Магический метод для десериализации объекта */ |
|
| 568 | public function __wakeup() |
||
| 572 | |||
| 573 | 7 | /** Магический метод для сериализации объекта */ |
|
| 574 | public function __sleep() |
||
| 578 | } |
||
| 579 |