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) |
||
477 | |||
478 | /** |
||
479 | * Load module from path to core. |
||
480 | * |
||
481 | * @param string $path Path for module loading |
||
482 | * @param array $parameters Collection of loading parameters |
||
483 | * |
||
484 | * @return $this|bool |
||
485 | */ |
||
486 | public function load($path, $parameters = array()) |
||
568 | //[PHPCOMPRESSOR(remove,end)] |
||
569 | |||
570 | 7 | /** Магический метод для десериализации объекта */ |
|
571 | public function __wakeup() |
||
575 | |||
576 | 7 | /** Магический метод для сериализации объекта */ |
|
577 | 7 | public function __sleep() |
|
581 | } |
||
582 |