1
|
|
|
<?php |
2
|
|
|
namespace WebServCo\Framework; |
3
|
|
|
|
4
|
|
|
use WebServCo\Framework\Settings as S; |
5
|
|
|
use WebServCo\Framework\Framework as Fw; |
6
|
|
|
use WebServCo\Framework\Environment as Env; |
7
|
|
|
use WebServCo\Framework\ErrorHandler as Err; |
8
|
|
|
|
9
|
|
|
class Application extends \WebServCo\Framework\AbstractApplication |
10
|
|
|
{ |
11
|
|
|
public function __construct($publicPath, $projectPath) |
12
|
|
|
{ |
13
|
|
|
$publicPath = rtrim($publicPath, DIRECTORY_SEPARATOR) . DIRECTORY_SEPARATOR; |
14
|
|
|
$projectPath = rtrim($projectPath, DIRECTORY_SEPARATOR) . DIRECTORY_SEPARATOR; |
15
|
|
|
|
16
|
|
|
if (!is_readable("{$publicPath}index.php") || !is_readable("{$projectPath}.env")) { |
17
|
|
|
throw new \ErrorException( |
18
|
|
|
'Invalid paths specified when initializing Application.' |
19
|
|
|
); |
20
|
|
|
} |
21
|
|
|
|
22
|
|
|
$this->config()->set(sprintf('app%1$spath%1$sweb', S::DIVIDER), $publicPath); |
23
|
|
|
$this->config()->set(sprintf('app%1$spath%1$sproject', S::DIVIDER), $projectPath); |
24
|
|
|
} |
25
|
|
|
|
26
|
|
|
/** |
27
|
|
|
* Sets the env value from the project .env file. |
28
|
|
|
*/ |
29
|
|
|
final public function setEnvironmentValue() |
30
|
|
|
{ |
31
|
|
|
/** |
32
|
|
|
* Project path is set in the constructor. |
33
|
|
|
*/ |
34
|
|
|
$pathProject = $this->config()->get(sprintf('app%1$spath%1$sproject', S::DIVIDER)); |
35
|
|
|
/** |
36
|
|
|
* Env file existence is verified in the controller. |
37
|
|
|
*/ |
38
|
|
|
$this->config()->setEnv(trim(file_get_contents("{$pathProject}.env"))); |
39
|
|
|
|
40
|
|
|
return true; |
41
|
|
|
} |
42
|
|
|
|
43
|
|
|
/** |
44
|
|
|
* Starts the execution of the application. |
45
|
|
|
*/ |
46
|
|
|
final public function start() |
47
|
|
|
{ |
48
|
|
|
Err::set(); |
49
|
|
|
register_shutdown_function([$this, 'shutdown']); |
50
|
|
|
|
51
|
|
|
try { |
52
|
|
|
$this->setEnvironmentValue(); |
53
|
|
|
|
54
|
|
|
/** |
55
|
|
|
* With no argument, timezone will be set from the configuration. |
56
|
|
|
*/ |
57
|
|
|
$this->date()->setTimezone(); |
58
|
|
|
/** |
59
|
|
|
* @todo i18n, log, session (if not cli), users (if not cli) |
60
|
|
|
*/ |
61
|
|
|
|
62
|
|
|
return true; |
63
|
|
|
} catch (\Throwable $e) { // php7 |
64
|
|
|
return $this->shutdown($e, true); |
|
|
|
|
65
|
|
|
} catch (\Exception $e) { // php5 |
66
|
|
|
return $this->shutdown($e, true); |
|
|
|
|
67
|
|
|
} |
68
|
|
|
} |
69
|
|
|
|
70
|
|
|
/** |
71
|
|
|
* Runs the application. |
72
|
|
|
*/ |
73
|
|
|
final public function run() |
74
|
|
|
{ |
75
|
|
|
try { |
76
|
|
|
$response = $this->execute(); |
77
|
|
|
if ($response instanceof |
78
|
|
|
\WebServCo\Framework\Interfaces\ResponseInterface) { |
79
|
|
|
$statusCode = $response->send($this->request()); |
80
|
|
|
return $this->shutdown( |
|
|
|
|
81
|
|
|
null, |
82
|
|
|
true, |
83
|
|
|
Fw::isCLI() ? $statusCode : 0 |
84
|
|
|
); |
85
|
|
|
} |
86
|
|
|
} catch (\Throwable $e) { // php7 |
87
|
|
|
return $this->shutdown($e, true); |
|
|
|
|
88
|
|
|
} catch (\Exception $e) { // php5 |
89
|
|
|
return $this->shutdown($e, true); |
|
|
|
|
90
|
|
|
} |
91
|
|
|
} |
92
|
|
|
|
93
|
|
|
final protected function execute() |
94
|
|
|
{ |
95
|
|
|
$classType = Fw::isCLI() ? 'Command' : 'Controller'; |
96
|
|
|
$route = $this->router()->getRoute( |
97
|
|
|
$this->request()->target, |
98
|
|
|
$this->router()->setting('routes'), |
99
|
|
|
$this->request()->args |
100
|
|
|
); |
101
|
|
|
|
102
|
|
|
$class = isset($route[0]) ? $route[0] : null; |
103
|
|
|
$method = isset($route[1]) ? $route[1] : null; |
104
|
|
|
$args = isset($route[2]) ? $route[2] : []; |
105
|
|
|
|
106
|
|
|
if (empty($class) || empty($method)) { |
107
|
|
|
throw new \ErrorException("Invalid route"); |
108
|
|
|
} |
109
|
|
|
$className = "\\Project\\Domain\\{$class}\\{$class}{$classType}"; |
110
|
|
|
if (!class_exists($className)) { |
111
|
|
|
throw new \ErrorException("No matching {$classType} found", 404); |
112
|
|
|
} |
113
|
|
|
$object = new $className; |
114
|
|
|
$parent = get_parent_class($object); |
115
|
|
|
if (method_exists($parent, $method) || |
116
|
|
|
!is_callable([$className, $method])) { |
117
|
|
|
throw new \ErrorException('No matching action found', 404); |
118
|
|
|
} |
119
|
|
|
return call_user_func_array([$object, $method], $args); |
120
|
|
|
} |
121
|
|
|
|
122
|
|
|
/** |
123
|
|
|
* Finishes the execution of the Application. |
124
|
|
|
* |
125
|
|
|
* This method is also registered as a shutdown handler. |
126
|
|
|
*/ |
127
|
|
|
final public function shutdown($exception = null, $manual = false, $statusCode = 0) |
128
|
|
|
{ |
129
|
|
|
$hasError = $this->handleErrors($exception); |
130
|
|
|
if ($hasError) { |
131
|
|
|
$statusCode = 1; |
132
|
|
|
} |
133
|
|
|
|
134
|
|
|
if (!$manual) { //if shutdown handler |
135
|
|
|
/** |
136
|
|
|
* Warning: this part will always be executed, |
137
|
|
|
* independent of the outcome of the script. |
138
|
|
|
*/ |
139
|
|
|
Err::restore(); |
140
|
|
|
} |
141
|
|
|
exit($statusCode); |
|
|
|
|
142
|
|
|
} |
143
|
|
|
} |
144
|
|
|
|
This check looks for function or method calls that always return null and whose return value is used.
The method
getObject()
can return nothing but null, so it makes no sense to use the return value.The reason is most likely that a function or method is imcomplete or has been reduced for debug purposes.