-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathapp.php
More file actions
369 lines (272 loc) · 8.39 KB
/
app.php
File metadata and controls
369 lines (272 loc) · 8.39 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
<?php
namespace Kirby;
use Kirby\Toolkit\A;
use Kirby\Toolkit\C;
use Kirby\Toolkit\Dir;
use Kirby\Toolkit\Event;
use Kirby\Toolkit\F;
use Kirby\Toolkit\Response;
use Kirby\Toolkit\Router;
use Kirby\Toolkit\Router\Route;
use Kirby\Toolkit\Str;
use Kirby\Toolkit\URI;
use Kirby\Toolkit\URL;
// direct access protection
if(!defined('KIRBY')) die('Direct access is not allowed');
/**
* App
*
* @package Kirby App
* @author Bastian Allgeier <bastian@getkirby.com>
* @link http://getkirby.com
* @copyright Bastian Allgeier
* @license http://www.opensource.org/licenses/mit-license.php MIT License
*/
class App {
// module instance cache
static protected $modules;
// the current active module
static protected $module;
// the current active controller
static protected $controller;
// the current active action
static protected $action;
// the current uri object
static protected $uri;
// all registered routes
static protected $routes;
// the current route object
static protected $route;
/**
* Returns an array with all modules
*
* @return array
*/
static public function modules($dir = null) {
if(!is_null(static::$modules)) return static::$modules;
if(is_null($dir)) raise('Module installation failed');
static::$modules = array();
$modules = dir::read($dir);
foreach($modules as $module) {
if(!is_dir($dir . DS . $module)) continue;
$file = $dir . DS . $module . DS . $module . '.php';
$class = $module . 'module';
f::load($file);
// skip broken modules
if(!class_exists($class)) continue;
// add the new module class
static::$modules[$module] = new $class($file);
}
// load all installed modules
foreach(static::$modules as $module) {
$module->load();
$module->autoloader();
}
return static::$modules;
}
/**
* Returns a module class by its name or the current module
*
* @return object
*/
static public function module($name = null) {
// if no name is specified, return the current module
if(is_null($name)) return static::$module;
// return a specific module
return a::get(static::$modules, $name, null);
}
/**
* Returns the currently active controller
*
* @return object
*/
static public function controller() {
return static::$controller;
}
/**
* Returns the currently active action
*
* @return string
*/
static public function action() {
return static::$action;
}
/**
* Registers and returns all routes
*
* @return array
*/
static public function routes() {
if(!is_null(static::$routes)) return static::$routes;
foreach(static::modules() as $module) {
// register all routes for each module
$module->routes();
}
return static::$routes = router::routes();
}
/**
* Returns the current route object
*
* @return object
*/
static public function route() {
return static::$route;
}
/**
* Initiates and returns the app's current uri
*
* @return object
*/
static public function uri() {
if(!is_null(static::$uri)) return static::$uri;
return static::$uri = new URI(array(
'subfolder' => c::get('app.subfolder', '@auto'),
'strip' => 'index.php'
));
}
/**
* Smart url builder
* You can pass the following:
*
* 1. nothing or / to get the url of the home page
* 2. a simple uri like some/uri to get the full url
* 3. a controller path like todos > todos::index to get the url from the router
*
* Add arguments to replace placeholders in the url with them.
*
* This can be used with the url::to(), url(), and u() shortcuts
*
* @param string $path
* @param array $arguments
* @return string
*/
static public function url($path = null, $arguments = array()) {
$baseurl = static::uri()->baseurl();
// return the home url
if(is_null($path) or $path == '/') return $baseurl;
// controller
if(str::contains($path, '>')) {
// make sure all routes are registered
static::routes();
$route = route::findByAction($path);
// return the home url if nothing could be found
if(empty($route)) return static::url();
// return the final url
$url = rtrim($baseurl . '/' . $route->pattern , '/');
} else {
$url = $baseurl . '/' . ltrim($path, '/');
}
// replace all placeholders in the url with proper arguments
if(!empty($arguments)) {
// replace all placeholders with %s so it can be used in sprintf later
$url = preg_replace('!(\(\:.*?\))!', '%s', $url);
// only use the array values from the arguments array
$arguments = array_values((array)$arguments);
// add the pattern as first argument
array_unshift($arguments, $url);
// replace all placeholders with arguments
$url = call_user_func_array('sprintf', $arguments);
}
return $url;
}
/**
* Fetches all routes, tries to resolve the current uri
* loads the current module and controller and fires the
* current controller action.
*
* @return mixed
*/
static public function dispatch() {
event::trigger('kirby.app.dispatch:before');
// get the current route
static::$route = router::run(static::uri()->path());
// check for an existing route and send to the 404 page if no route exists
if(!static::$route) raise('Page not found', 404);
// get the router action
$action = static::$route->action();
// check for a route closure
if(static::$route->isCallable()) {
// get the result of the router call
$result = static::$route->call();
// and pass it to the dispatch:after event
event::trigger('kirby.app.dispatch:after', array(&$result));
// return the result afterwards
return $result;
} else {
// module > controller::action
// parse the string and extract all important parts
preg_match('!^(.*?)\>(.*?)\:\:(.*?)$!i', trim($action), $matches);
$m = trim($matches[1]); // module
$c = trim($matches[2]); // controller
$a = trim($matches[3]); // action
$module = static::module($m);
// check if the module is available
if(!$module) raise('Invalid module: ' . $m);
// initial config event for the module
$module->config();
// load the controller file
f::load($module->root() . DS . 'controllers' . DS . $c . '.php');
// create the controller class name
$class = $c . 'controller';
// check if the controller exists
if(!class_exists($class)) raise('Invalid controller: ' . $c);
$controller = new $class;
$controller->module = $module;
$controller->action = $a;
$controller->arguments = static::$route->arguments();
static::$module = $module;
static::$controller = $controller;
static::$action = $a;
// run the controller action and return the result
$result = $controller->run();
// and pass it to the dispatch:after event
event::trigger('kirby.app.dispatch:after', array(&$result));
// return the result afterwards
return $result;
}
}
/**
* Runs the dispatcher and echos the response
*/
static public function run() {
// register all routes
static::routes();
// trigger the configuration event
event::trigger('kirby.app.configure');
// call the dispatcher
$response = static::dispatch();
if(is_a($response, 'Kirby\\Toolkit\\Response')) {
$response->header();
}
// make it possible to work with the repsone before it gets echoed
event::trigger('kirby.app.response', array(&$response));
// send the response to the user
echo $response;
}
/**
* Returns the full root for a smart path (tm)
*
* @param string $path
* @return string
*/
static public function root($path) {
$parts = str::split($path, '>');
$module = $parts[0];
$module = static::module($module);
if(!$module) return false;
return $module->root() . DS . $parts[1];
}
/**
* A simple loader for collections, models and lib stuff
* from any module
*
* @param string $path
*/
static public function load($path) {
if(is_array($path)) {
foreach($path as $p) static::load($p);
return;
}
f::load(static::root($path . '.php'));
}
}