Browse code

Application class - initial feed

RafaƂ Szklarczyk authored on 26/04/2019 20:52:24
Showing 1 changed files
1 1
new file mode 100644
... ...
@@ -0,0 +1,279 @@
1
+<?php
2
+
3
+namespace elanpl\L3;
4
+
5
+class Application{
6
+    public $Request; // build from received HTTP request
7
+    public $Response; // response to be send
8
+    public $Router; // routing engine
9
+    public $Serialization; // serialization engine
10
+    public $BaseDirectory; // directory root of the application
11
+    public $ConfigDirectory; // directory containing application configuration files
12
+    public $ControllersDirectory; // subdirectory/namespace part added to controller class 
13
+    public $ViewsDirectory; // subdirectory to search for the view files
14
+    public $ApplicationDirectory; // subdirectory/namespace part of the application
15
+    //public $Controller; //Active controller
16
+    //public $Module; //Active module
17
+    //public $Action; //Active action
18
+
19
+    public function __construct(){
20
+        //create request object
21
+        $this->Request = new Request();
22
+        //create response objcet
23
+        $this->Response = new Response();
24
+        //create router object
25
+        $this->Router = new Router();
26
+        //create serialization object
27
+        $this->Serialization = new Serialization(); 
28
+    }
29
+
30
+    public function basePath(){
31
+        return strstr($_SERVER['REQUEST_URI'], $this->Request->Path, true);
32
+    }
33
+
34
+    public function relPath($file){
35
+        return ($this->Router->depth>0 ? str_repeat("../", substr($this->Request->Path,-1)=='/'?$this->Router->depth:$this->Router->depth-1) : "" ).$file; 
36
+    }
37
+
38
+    public function link($name, $parameters){
39
+        return $this->Router->link($name, $parameters);
40
+    }
41
+
42
+    public function LoadApplicationConfiguration(){
43
+        //include routing configuration
44
+        include_once($this->ConfigDirectory."routing.php");
45
+        //include the application configuration
46
+        include_once($this->ConfigDirectory.'app.php');
47
+    }
48
+
49
+    public function LoadConfigFile($file){
50
+        //include configuration file
51
+        return include_once($this->ConfigDirectory.$file);
52
+    }
53
+
54
+    public function IncludeFromConfigDir($file){
55
+        //include configuration file
56
+        return include($this->ConfigDirectory.$file);
57
+    }
58
+
59
+    /*
60
+    //not need - PSR-4 autoload handles that
61
+    function IncludeControler($Controller){
62
+        include_once(_L3_CONTROLLER_PATH.$Controller.'.php');
63
+    }*/
64
+
65
+    public function FindControllerInCallStack($search_level=5){
66
+        //search for controller, action and module if present
67
+        $controller = "";
68
+        $module = "";
69
+        $action = "";
70
+        $match = array();
71
+
72
+        //analize the call stack
73
+          $call_stack = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, $search_level);
74
+        
75
+        for($i=0; $i<$search_level; $i++){
76
+            if(preg_match(
77
+                    $pattern = '#('.$this->ApplicationDirectory.')(\\\\(?P<module>.+))?\\\\'.$this->ControllersDirectory.'\\\\(?P<controller>.+)#',
78
+                    $call_stack[$i]['class'],
79
+                    $match
80
+                )
81
+            ){
82
+                $action = $call_stack[$i]['function'];
83
+                $module = $match['module'];
84
+                $controller = $match['controller'];
85
+                break;
86
+            }
87
+        }
88
+
89
+        return array(
90
+            'module' => $module,
91
+            'controller' => $controller,
92
+            'action' => $action
93
+        );
94
+    }
95
+
96
+    function RunControllerAction($ControllerAction, $Parameters){
97
+        
98
+        //prepare object and action name
99
+        /*
100
+        TODO ...
101
+        if(is_object($this->controler) && (is_a($this->controler,'L2_controler') || is_subclass_of($this->controler,'L2_controler'))){
102
+            if(is_string($this->action)){
103
+                $controler_object = $this->controler;
104
+                $controler_action = $this->action;
105
+            }
106
+        }
107
+        else if(is_string($this->controler)){
108
+            if(is_string($this->action)){
109
+                $this->includeControler($this->controler);
110
+                $controler_object = new $this->controler();
111
+                $controler_action = $this->action;
112
+            }
113
+        }*/
114
+
115
+        if(is_array($ControllerAction)){
116
+            //$this->IncludeControler($ControllerAction['controller']);
117
+            $controller_class = "\\".$this->ApplicationDirectory."\\"
118
+                .(isset($ControllerAction['module'])?$ControllerAction['module']."\\":"")
119
+                .$this->ControllersDirectory."\\"
120
+                .$ControllerAction['controller'];
121
+            $controller_object = new $controller_class;
122
+            $controller_action = $ControllerAction['action'];
123
+        }
124
+
125
+        //fire the action
126
+        if(isset($controller_object) && isset($controller_action)){
127
+            $this->Module = (isset($ControllerAction['module'])?$ControllerAction['module']:"");
128
+            $this->Controller = $ControllerAction['controller'];
129
+            $this->Action = $controller_action;
130
+            // prepare args and start the action
131
+            if(!isset($reflection)){
132
+                $reflection = new \ReflectionMethod($controller_object, $controller_action);
133
+            }
134
+            if($reflection->getNumberOfParameters()){
135
+                $fire_args=array();
136
+
137
+                foreach($reflection->getParameters() AS $arg)
138
+                {
139
+                    if(isset($Parameters[$arg->name]) || (is_array($ControllerAction) && isset($ControllerAction['defaults'][$arg->name])))
140
+                        if(isset($Parameters[$arg->name]))
141
+                            $fire_args[$arg->name]=$Parameters[$arg->name];
142
+                        else
143
+                            $fire_args[$arg->name]=$ControllerAction['defaults'][$arg->name];
144
+                    else
145
+                    {
146
+                        if($arg->isDefaultValueAvailable()){
147
+                            $fire_args[$arg->name]=$arg->getDefaultValue();
148
+                        }
149
+                        else{
150
+                            $fire_args[$arg->name]=null;
151
+                        }
152
+                    }
153
+                }
154
+                return $reflection->invokeArgs ($controller_object , $fire_args );
155
+            }
156
+            else{
157
+                return $reflection->invoke($controller_object);
158
+            }
159
+        }
160
+    }
161
+
162
+    public function HandleActionResult($result){
163
+        if(is_string($result)){
164
+            $content = $result;
165
+        }
166
+        else if(is_object($result)){
167
+            if($result instanceof ViewModel){
168
+                if($SerializationContentType = $this->Serialization->Match($this->Request->AcceptTypes, $result)){
169
+                    $content = $this->Serialization->Serialize($SerializationContentType, $result);
170
+                    if(is_object($content)){
171
+                        if($content instanceof Response){
172
+                            $this->Response = $content;
173
+                            unset($content);
174
+                        }
175
+                    }
176
+                }
177
+                else{
178
+                    echo "Serializer not defined for Content-Type: ".$this->Request->Accept."<br>".PHP_EOL;
179
+                    throw new \Exception("Not implemented!");
180
+                }
181
+            }
182
+            else if($result instanceof View){
183
+                $content = $result->render();
184
+            }
185
+            else if($result instanceof Response){
186
+                $this->Response = $result;
187
+            }  
188
+        }
189
+        if(isset($content))
190
+                $this->Response->withBody($content);
191
+        $this->Response->send();
192
+    }
193
+
194
+    public function BeforeAction(){
195
+        if(!empty($this->Router->RouteInfo->BeforeAction)){
196
+            foreach($this->Router->RouteInfo->BeforeAction as $event_handler){
197
+                $this->Router->RouteInfo::EventHandlerFormatCheck($event_handler, $eh);
198
+                if(isset($eh['class'])){
199
+                    $object = new $eh['class'];
200
+                    $reflection = new \ReflectionMethod($object, $eh['function']);
201
+                    $fire_args = array();
202
+                    $fire_args[] = $this->Request;
203
+                    $fire_args[] = $this->Router->RouteInfo;
204
+                    if(isset($eh['arguments'])){
205
+                        $this->Router->RouteInfo::EventHandlerArgumentsFormatCheck($eh['arguments'], $args);
206
+                        $fire_args = array_merge($fire_args, $args);
207
+                    }
208
+                    $result = $reflection->invokeArgs ($object , $fire_args );
209
+                }
210
+                else if (is_callable($eh['function'])){
211
+                    throw new \Exception("Not implemented!");
212
+                }
213
+                if(isset($result)){
214
+                    if(is_object($result)){
215
+                        if($result instanceof Response){
216
+                            $this->HandleActionResult($result);
217
+                            exit();
218
+                        }
219
+                    }
220
+                }
221
+            }
222
+        }
223
+    }
224
+
225
+    public function Run(){
226
+        // Check if routing path is found
227
+        if($action = $this->Router->match($this->Request)){
228
+            // routing match found decide what to do next...
229
+            // BeforeAction event
230
+            $this->BeforeAction();
231
+
232
+            // function -> call it...
233
+            if(is_callable($action)){
234
+                $reflection = new \ReflectionFunction($action);
235
+                if($reflection->getNumberOfParameters()){
236
+                    $fire_args=array();
237
+      
238
+                    foreach($reflection->getParameters() AS $arg)
239
+                    {
240
+                        if(isset($this->Router->parsedParameters[$arg->name]))
241
+                            $fire_args[$arg->name]=$this->Router->parsedParameters[$arg->name];
242
+                        else
243
+                            $fire_args[$arg->name]=null;
244
+                    }
245
+                    
246
+                    $result = call_user_func_array($action, $fire_args);
247
+                }
248
+                else{
249
+                    $result = call_user_func($action);
250
+                }
251
+            }
252
+            else if(is_object($action) && is_a($action, 'L2_controler_info')){
253
+                // not implemented yet.
254
+                throw new \Exception("Not implemented!");
255
+                ///$action->runControlerAction($this->routing->param);
256
+            }
257
+            // array with controller, and action -> run the controller action
258
+            else if(is_array($action) && array_key_exists('controller',$action) && array_key_exists('action', $action)){
259
+                $result = $this->RunControllerAction($action, $this->Router->parsedParameters);
260
+                
261
+            }
262
+            // string
263
+            else if(is_string($action)){
264
+                $result = $action;
265
+            }
266
+
267
+            // Handle the action result
268
+            if(isset($result)){
269
+                $this->HandleActionResult($result);
270
+            }
271
+        }
272
+        // routing path not found -> generate 404 response
273
+        else{
274
+            echo "Routing not found!<br>".PHP_EOL;
275
+            throw new \Exception("Not implemented!");
276
+        }
277
+ 
278
+    }
279
+}
0 280
\ No newline at end of file