Browse code

Serialization and ViewEngines basics

RafaƂ Szklarczyk authored on 06/06/2019 20:03:48
Showing 8 changed files
... ...
@@ -8,6 +8,7 @@ class Application{
8 8
     public $response; // response to be send
9 9
     public $router; // routing engine
10 10
     public $serialization; // serialization engine
11
+    public $viewEngines; // view engines configuration
11 12
     public $baseDirecotry; // directory root of the application
12 13
     public $controllersDirecotry; // subdirectory/namespace part added to controller class 
13 14
     public $viewsDirecotry; // subdirectory to search for the view files
... ...
@@ -36,6 +37,11 @@ class Application{
36 37
 
37 38
         //create serialization object
38 39
         $this->serialization = new Serialization(); 
40
+        //create view engines configuretion object
41
+        $this->viewEngines = new ViewEngine();
42
+
43
+        //perform configuration operations
44
+        $this->config->configure($this);
39 45
     }
40 46
 
41 47
     public function basePath(){
... ...
@@ -26,4 +26,8 @@ class Config{
26 26
     public function getViewsDirectory(){
27 27
         return "views";
28 28
     }
29
+
30
+    public function configure($_L3){
31
+        // function to be overriden
32
+    }
29 33
 }
30 34
\ No newline at end of file
31 35
new file mode 100644
... ...
@@ -0,0 +1,7 @@
1
+<?php
2
+
3
+namespace elanpl\L3;
4
+
5
+interface ISerializer{
6
+    public function serialize($viewModel);
7
+}
0 8
\ No newline at end of file
1 9
new file mode 100644
... ...
@@ -0,0 +1,7 @@
1
+<?php
2
+
3
+namespace elanpl\L3;
4
+
5
+interface IViewEngine{
6
+    public function render($viewFile, $viewParams);
7
+}
0 8
\ No newline at end of file
... ...
@@ -3,21 +3,25 @@
3 3
 namespace elanpl\L3;
4 4
 
5 5
 class Serialization{
6
-    protected static $serializers; //registered serializers dictionary
6
+    protected $serializers; //registered serializers dictionary
7 7
 
8 8
     public function __construct()
9 9
     {
10
-        if(!isset(self::$serializers)) self::$serializers = array(); 
10
+        $this->serializers = array(); 
11 11
     }
12 12
 
13
-    public static function register($contentType, $serializer, $viewModelClass = null){
13
+    public function register($contentType, $serializer, $viewModelClass = null){
14
+        if(!isset(class_implements($serializer, true)['ISerializer'])){
15
+            throw new \Exception("Class \"$serializer\" does not implement ISerializer interface!");
16
+        }
17
+
14 18
         if(isset($viewModelClass) && $viewModelClass!=''){
15 19
             $class_key = $viewModelClass.'|';
16 20
         }
17 21
         else{
18 22
             $class_key = '';
19 23
         }
20
-        self::$serializers[$class_key.$contentType] = $serializer;
24
+        $this->serializers[$class_key.$contentType] = $serializer;
21 25
     }
22 26
 
23 27
     public function match($acceptTypes, $viewModel=null){
... ...
@@ -31,11 +35,11 @@ class Serialization{
31 35
         }
32 36
 
33 37
         if(is_array($acceptTypes)){
34
-            $registeredTypes = array_keys(self::$serializers);
38
+            $registeredTypes = array_keys($this->serializers);
35 39
 
36 40
             foreach ($acceptTypes as $type){
37 41
                 //Dedicated config for ViewModel class first...
38
-                if(array_key_exists($viewModelClass."|".$type, self::$serializers)){
42
+                if(array_key_exists($viewModelClass."|".$type, $this->serializers)){
39 43
                     return $type;
40 44
                 }
41 45
                 foreach($registeredTypes as $rtype_with_class){
... ...
@@ -51,7 +55,7 @@ class Serialization{
51 55
                 }
52 56
 
53 57
                 //Then check configs without the ViewModel class name
54
-                if(array_key_exists($type, self::$serializers)){
58
+                if(array_key_exists($type, $this->serializers)){
55 59
                     return $type;
56 60
                 }
57 61
                 foreach($registeredTypes as $rtype){
... ...
@@ -67,16 +71,16 @@ class Serialization{
67 71
     }
68 72
 
69 73
     public function serialize($contentType, $viewModel){
70
-        if(isset(Serialization::$serializers[get_class($viewModel).'|'.$contentType])){
71
-            $serializerClass = Serialization::$serializers[get_class($viewModel).'|'.$contentType];
74
+        if(isset($this->serializers[get_class($viewModel).'|'.$contentType])){
75
+            $serializerClass = $this->serializers[get_class($viewModel).'|'.$contentType];
72 76
         }
73
-        else if(isset(Serialization::$serializers[$contentType])){
74
-            $serializerClass = Serialization::$serializers[$contentType];
77
+        else if(isset($this->serializers[$contentType])){
78
+            $serializerClass = $this->serializers[$contentType];
75 79
         }
76 80
 
77 81
         if(isset($serializerClass)){
78 82
             $serializer = new $serializerClass();
79
-            return $serializer->Serialize($viewModel);
83
+            return $serializer->serialize($viewModel);
80 84
         }
81 85
         else{
82 86
             return null;
83 87
new file mode 100644
... ...
@@ -0,0 +1,141 @@
1
+<?php
2
+
3
+namespace elanpl\L3;
4
+
5
+class View{
6
+    protected $viewFileExtension;
7
+    protected $viewFile;
8
+    protected $context;
9
+    public $_L3; //The L3 instance
10
+
11
+    public function __construct(){
12
+        $numargs = func_num_args();
13
+     
14
+        if ($numargs == 0) {
15
+            $view = "";
16
+            $context = array();
17
+        }
18
+        else if ($numargs == 1) {
19
+            $arg = func_get_arg(0);
20
+            if(is_object($arg) && $arg instanceof ViewModel){
21
+                if(method_exists($arg, 'getContext')){
22
+                    $context = $arg->getContext();
23
+                }
24
+                else{
25
+                    $context = array();
26
+                    $context['vm'] = $arg;
27
+                }
28
+
29
+                if(method_exists($arg, 'getView')){
30
+                    $view = $arg->getView();
31
+                }
32
+                else{
33
+                    $view = $arg;
34
+                }
35
+
36
+                if(isset($arg->_L3)){
37
+                    $this->_L3 = $arg->_L3;
38
+                }
39
+            }
40
+            else{
41
+                $view = "";
42
+                $context = $arg;
43
+            }
44
+        }
45
+        else {
46
+            $arg = func_get_arg(0);
47
+            if($arg instanceof Application){
48
+                $this->_L3 = $arg;
49
+                $view = func_get_arg(1);
50
+                $context = func_get_arg(2);
51
+            }
52
+            else{
53
+                $view = func_get_arg(0);
54
+                $context = func_get_arg(1);
55
+            }
56
+        }
57
+
58
+        if(!isset($this->_L3)){
59
+            // if an Application object was not injected, take it form the global context...
60
+            global $_L3;
61
+            $this->_L3 = $_L3;
62
+        }
63
+        
64
+
65
+        if($this->viewFile = $this->find($view)){
66
+            $this->viewFileExtension = ".".pathinfo($this->viewFile, PATHINFO_EXTENSION);
67
+        }
68
+        else{
69
+            throw new \Exception("View file:\"$view\" not found!");
70
+        }
71
+        $this->context = $context;
72
+    }
73
+
74
+    public function render(){
75
+        if ($viewEngineClass = $this->_L3->viewEngines::get($this->viewFileExtension)){
76
+            $view = new $viewEngineClass();
77
+            return $view->render($this->viewFile, $this->context);
78
+        }
79
+        else{
80
+            throw new \Exception("View Engine not found for the view file extension:\"".$this->viewFileExtension."\"!");
81
+        }
82
+    }
83
+
84
+    public function find($view){
85
+        //find the view file
86
+        if(is_string($view) && is_file($view)){
87
+            // full path was provided...
88
+            return $view;
89
+        }
90
+        else{
91
+            // search for the view file
92
+            
93
+            //search for controller, action and module if present  
94
+            if(is_object($view) && $view instanceof ViewModel){
95
+                $controller = $view->getController();
96
+                $module = $view->getModule();
97
+                $action = $view->getAction();
98
+                $view = "";
99
+            }
100
+            else{                    
101
+                
102
+                $match = $this->_L3->findControllerInCallStack();
103
+
104
+                $controller = $match['controller'];
105
+                $module = $match['module'];
106
+                $action = $match['action'];     
107
+            }
108
+            //locate the view file
109
+            
110
+            // The search order:
111
+            // check [module/]views/controller/action/ directory (file)
112
+            // check [module/]views/controller/ directory (file)
113
+            // check [module/]views/
114
+
115
+            $viewsPath = $this->_L3->baseDirectory.$this->_L3->applicationDirectory.DIRECTORY_SEPARATOR
116
+                .($module!=""?$module.DIRECTORY_SEPARATOR:"").$this->_L3->viewsDirectory.DIRECTORY_SEPARATOR;
117
+
118
+            $dirs = array();
119
+
120
+            $dirs[] = $viewsPath.$controller.DIRECTORY_SEPARATOR.$action;
121
+            $dirs[] = $viewsPath.$controller.DIRECTORY_SEPARATOR;
122
+            $dirs[] = $viewsPath;
123
+
124
+            foreach($dirs as $dir){
125
+                // check if the file exists
126
+                if(is_file($found = $dir.($action!=""&&$view!=""?DIRECTORY_SEPARATOR:"").$view)){
127
+                    return $found;
128
+                }
129
+                // try to add extension and check again
130
+                else foreach($this->_L3->viewEngines->getRegisteredFileExtensions() as $registeredExtension){
131
+                    if(is_file($found = $dir.($action!=""&&$view!=""?DIRECTORY_SEPARATOR:"").$view.$registeredExtension)){
132
+                        return $found;
133
+                    }
134
+                }
135
+            }
136
+            
137
+
138
+        }
139
+        return null;
140
+    }
141
+}
0 142
\ No newline at end of file
1 143
new file mode 100644
... ...
@@ -0,0 +1,34 @@
1
+<?php
2
+
3
+namespace elanpl\L3;
4
+
5
+class ViewEngine{
6
+    protected $viewengines; //registered view engines dictionary
7
+
8
+    public function __construct()
9
+    {
10
+        $this->viewengines = array(); 
11
+    }
12
+
13
+    public function register($fileExtension, $viewEngine){
14
+        if(!isset(class_implements($viewEngine, true)['IViewEngine'])){
15
+            throw new \Exception("Class \"$viewEngine\" does not implement IViewEngine interface!");
16
+        }
17
+
18
+        $this->viewengines[$fileExtension] = $viewEngine;
19
+    }
20
+
21
+    public function get($fileExtension){
22
+        if(array_key_exists($fileExtension, $this->viewengines)){
23
+            return $this->viewengines[$fileExtension];
24
+        }
25
+        else{
26
+            return null;
27
+        }
28
+    }
29
+
30
+    public function getRegisteredFileExtensions(){
31
+        return array_keys($this->viewengines);
32
+    }
33
+
34
+}
0 35
\ No newline at end of file
1 36
new file mode 100644
... ...
@@ -0,0 +1,62 @@
1
+<?php
2
+
3
+namespace elanpl\L3;
4
+
5
+abstract class ViewModel{
6
+    private $module;
7
+    private $controller;
8
+    private $action;
9
+    public $_L3;
10
+                    
11
+    public function __construct($arg)
12
+    {
13
+        if($arg instanceof Applicstion){
14
+            $this->_L3 = $_L3;
15
+        }
16
+        else{
17
+            global $_L3;
18
+            $this->_L3 = $_L3;
19
+        }
20
+
21
+        $match = $_L3->findControllerInCallStack();
22
+
23
+        $this->controller = $match['controller'];
24
+        $this->module = $match['module'];
25
+        $this->action = $match['action'];
26
+    }
27
+
28
+    public function getController(){
29
+        if(!isset($this->controller)){
30
+            throw new \Exception("Controller not found in ViewModel \"".get_class($this)."! Use parent::__construct() in the class constructor or setController method.");
31
+        }
32
+        else
33
+            return $this->controller;
34
+    }
35
+
36
+    public function getAction(){
37
+        if(!isset($this->action)){
38
+            throw new \Exception("Action not found in ViewModel \"".get_class($this)."! Use parent::___construct() in the class constructor or setAction method.");
39
+        }
40
+        return $this->action;
41
+    }
42
+
43
+    public function getModule(){
44
+        return $this->module;
45
+    }
46
+
47
+    public function setController($controller){ 
48
+        return $this->controller = $controller;
49
+    }
50
+
51
+    public function setAction($action){ 
52
+        return $this->action = $action;
53
+    }
54
+
55
+    public function setModule($module){ 
56
+        return $this->module = $module;
57
+    }
58
+
59
+    public function getDTO(){
60
+        //function to be overriden
61
+    }
62
+}
0 63
\ No newline at end of file