1 <?php
2
3 4 5 6 7 8 9 10
11
12 namespace ICanBoogie;
13
14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
32 class Core extends Object
33 {
34 static private $instance;
35
36 37 38 39 40
41 static public function get()
42 {
43 return self::$instance;
44 }
45
46 47 48 49 50
51 static public $is_running = false;
52
53 54 55 56 57
58 static public function exception_handler(\Exception $exception)
59 {
60 Debug::exception_handler($exception);
61 }
62
63 64 65 66 67 68 69
70 public function __construct(array $options=[])
71 {
72 if (self::$instance)
73 {
74 throw new \Exception('Only one instance of the Core object can be created');
75 }
76
77 self::$instance = $this;
78
79 if (php_sapi_name() !== 'cli')
80 {
81 $class = get_class($this);
82
83 set_exception_handler($class . '::exception_handler');
84 set_error_handler('ICanBoogie\Debug::error_handler');
85 }
86
87 if (!date_default_timezone_get())
88 {
89 date_default_timezone_set('UTC');
90 }
91
92 $this->configs = $configs = $this->create_config_manager($options['config-path'], $options['config-constructor']);
93
94 $config = $this->config;
95
96 $this->config['locale-path'] = $options['locale-path'];
97 $this->config['module-path'] = $options['module-path'];
98
99
100
101 if (class_exists('ICanBoogie\I18n', true))
102 {
103 I18n::$load_paths = array_merge(I18n::$load_paths, $options['locale-path']);
104 }
105
106
107
108
109
110 if ($config['cache configs'])
111 {
112 $configs->cache_repository = $config['repository.cache'] . '/core';
113 }
114 }
115
116 protected function create_config_manager($path_list, $constructors)
117 {
118 return new Configs($path_list, $constructors);
119 }
120
121 122 123 124 125
126 protected function lazy_get_modules()
127 {
128 $config = $this->config;
129
130 return new Modules($config['module-path'], $config['cache modules'] ? $this->vars : null);
131 }
132
133 134 135 136 137
138 protected function lazy_get_models()
139 {
140 return new Models($this->connections, [], $this->modules);
141 }
142
143 144 145 146 147
148 protected function lazy_get_vars()
149 {
150 return new Vars(REPOSITORY . 'vars' . DIRECTORY_SEPARATOR);
151 }
152
153 154 155 156 157
158 protected function lazy_get_config()
159 {
160 $config = $this->configs['core'];
161
162 return $config;
163 }
164
165 166 167 168 169
170 protected function get_dispatcher()
171 {
172 return HTTP\get_dispatcher();
173 }
174
175 176 177 178 179
180 protected function lazy_get_initial_request()
181 {
182 return HTTP\Request::from($_SERVER);
183 }
184
185 186 187 188 189
190 protected function get_request()
191 {
192 return HTTP\Request::get_current_request() ?: $this->initial_request;
193 }
194
195 196 197 198 199
200 protected function get_language()
201 {
202 return I18n\get_language();
203 }
204
205 206 207 208 209
210 protected function set_locale($id)
211 {
212 I18n\set_locale($id);
213 }
214
215 216 217 218 219
220 protected function get_locale()
221 {
222 return I18n\get_locale();
223 }
224
225 226 227
228 private $timezone;
229
230 231 232 233 234 235 236 237 238
239 protected function set_timezone($timezone)
240 {
241 if (is_numeric($timezone))
242 {
243 $timezone = timezone_name_from_abbr(null, $timezone, 0);
244 }
245
246 $this->timezone = TimeZone::from($timezone);
247
248 date_default_timezone_set((string) $this->timezone);
249 }
250
251 252 253 254 255 256 257 258
259 protected function get_timezone()
260 {
261 if (!$this->timezone)
262 {
263 $this->timezone = TimeZone::from(date_default_timezone_get() ?: 'UTC');
264 }
265
266 return $this->timezone;
267 }
268
269 270 271 272 273
274 protected function get_routes()
275 {
276 return Routes::get();
277 }
278
279 280 281
282 public function __invoke()
283 {
284 self::$is_running = true;
285
286 Debug::configure($this->configs['debug']);
287
288 $this->run_modules();
289
290 Prototype::configure($this->configs['prototypes']);
291
292 Events::patch('get', function() {
293
294 return $this->events;
295
296 });
297
298 new Core\RunEvent($this, $this->initial_request);
299
300
301
302
303
304 $_SERVER['ICANBOOGIE_READY_TIME_FLOAT'] = microtime(true);
305
306 return $this->initial_request;
307 }
308
309 310 311 312 313 314
315 protected function run_modules()
316 {
317 $modules = $this->modules;
318 $index = $modules->index;
319
320 if (class_exists('ICanBoogie\I18n', true))
321 {
322 I18n::$load_paths = array_merge(I18n::$load_paths, $modules->locale_paths);
323 }
324
325
326
327
328
329 $modules_config_paths = $modules->config_paths;
330
331 if ($modules_config_paths)
332 {
333 $this->configs->add($modules->config_paths, -10);
334 }
335 }
336
337 338 339 340 341 342 343 344 345 346
347 public function generate_path($pattern_or_route_id_or_route, $params=null, array $options=[])
348 {
349 if ($pattern_or_route_id_or_route instanceof Route)
350 {
351 $path = $pattern_or_route_id_or_route->format($params);
352 }
353 else if (isset($this->routes[$pattern_or_route_id_or_route]))
354 {
355 $path = $this->routes[$pattern_or_route_id_or_route]->format($params);
356 }
357 else if (Route::is_pattern($pattern_or_route_id_or_route))
358 {
359 $path = Routing\Pattern::from($pattern_or_route_id_or_route)->format($params);
360 }
361 else
362 {
363 throw new \InvalidArgumentException("Invalid \$pattern_or_route_id_or_route.");
364 }
365
366 return Routing\contextualize($path);
367 }
368
369 public function generate_url($pattern_or_route_id_or_route, $params=null, array $options=[])
370 {
371 return $this->site->url . $this->generate_path($pattern_or_route_id_or_route, $params, $options);
372 }
373 }
374
375 namespace ICanBoogie\Core;
376
377 use ICanBoogie\HTTP\Request;
378
379 380 381
382 class BeforeRunEvent extends \ICanBoogie\Event
383 {
384 385 386 387 388
389 public function __construct(\ICanBoogie\Core $target)
390 {
391 parent::__construct($target, 'run:before');
392 }
393 }
394
395 396 397
398 class RunEvent extends \ICanBoogie\Event
399 {
400 401 402 403 404
405 public $request;
406
407 408 409 410 411
412 public function __construct(\ICanBoogie\Core $target, Request $request)
413 {
414 $this->request = $request;
415
416 parent::__construct($target, 'run');
417 }
418 }
419
420 421 422 423 424 425