BfwController::run()   A
last analyzed

Complexity

Conditions 4
Paths 4

Size

Total Lines 24
Code Lines 15

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 15
nc 4
nop 0
dl 0
loc 24
c 0
b 0
f 0
cc 4
rs 9.7666
1
<?php
2
3
namespace BfwController;
4
5
use Exception;
6
7
/**
8
 * Controller system class
9
 */
10
class BfwController implements \SplObserver
11
{
12
    /**
13
     * @const ERR_RUN_OBJECT_MISSING_DATAS_INTO_TARGET Error code if the class
14
     * and the method is not declared for the current route. In object mode only
15
     */
16
    const ERR_RUN_OBJECT_MISSING_DATAS_INTO_TARGET = 2001001;
17
    
18
    /**
19
     * @const ERR_RUN_OBJECT_CLASS_NOT_FOUND Error code if the class declared
20
     * for the route is not found. In object mode only.
21
     */
22
    const ERR_RUN_OBJECT_CLASS_NOT_FOUND = 2001002;
23
    
24
    /**
25
     * @const ERR_RUN_OBJECT_METHOD_NOT_FOUND Error code if the method declared
26
     * for the route is not found. In object mode only.
27
     */
28
    const ERR_RUN_OBJECT_METHOD_NOT_FOUND = 2001003;
29
    
30
    /**
31
     * @const ERR_RUN_PROCEDURAL_FILE_NOT_FOUND Error code if the file to use
32
     * for the route is not found. In procedural mode only.
33
     */
34
    const ERR_RUN_PROCEDURAL_FILE_NOT_FOUND = 2001004;
35
    
36
    /**
37
     * @var \BFW\Module $module The bfw module instance for this module
38
     */
39
    protected $module;
40
    
41
    /**
42
     * @var \BFW\Config $config The bfw config instance for this module
43
     */
44
    protected $config;
45
    
46
    /**
47
     * @var object|null $ctrlRouterInfos The context object passed to
48
     * subject for the action "searchRoute".
49
     */
50
    protected $ctrlRouterInfos;
51
    
52
    /**
53
     * @var string $execRouteSystemName The name of the current system. Used on
54
     * event "execRoute". Allow to extends this class in another module :)
55
     */
56
    protected $execRouteSystemName = 'bfw-controller';
57
    
58
    /**
59
     * Constructor
60
     * Get config and linker instance
61
     * 
62
     * @param \BFW\Module $module
63
     */
64
    public function __construct(\BFW\Module $module)
65
    {
66
        $this->module = $module;
67
        $this->config = $module->getConfig();
68
    }
69
    
70
    /**
71
     * Getter accessor for module property
72
     * 
73
     * @return \BFW\Module
74
     */
75
    public function getModule(): \BFW\Module
76
    {
77
        return $this->module;
78
    }
79
80
    /**
81
     * Getter accessor for config property
82
     * 
83
     * @return \BFW\Config
84
     */
85
    public function getConfig(): \BFW\Config
86
    {
87
        return $this->config;
88
    }
89
90
    /**
91
     * Getter accessor for ctrlRouterInfos property
92
     * 
93
     * @return object
94
     */
95
    public function getCtrlRouterInfos()
96
    {
97
        return $this->ctrlRouterInfos;
98
    }
99
    
100
    /**
101
     * Getter accessor for execRouteSystemName property
102
     * 
103
     * @return string
104
     */
105
    public function getExecRouteSystemName(): string
106
    {
107
        return $this->execRouteSystemName;
108
    }
109
    
110
    /**
111
     * Observer update method
112
     * 
113
     * @param \SplSubject $subject
114
     * 
115
     * @return void
116
     */
117
    public function update(\SplSubject $subject)
118
    {
119
        if ($subject->getAction() === 'ctrlRouterLink_exec_execRoute') {
120
            $this->obtainCtrlRouterInfos($subject);
121
            
122
            if (
123
                $this->ctrlRouterInfos->isFound === true &&
124
                $this->ctrlRouterInfos->forWho === $this->execRouteSystemName
125
            ) {
126
                $this->run();
127
            }
128
        }
129
    }
130
    
131
    /**
132
     * Set the property ctrlRouterInfos with the context object obtain linked
133
     * to the subject.
134
     * Allow override to get only some part. And used for unit test.
135
     * 
136
     * @param \BFW\Subject $subject
137
     * 
138
     * @return void
139
     */
140
    protected function obtainCtrlRouterInfos(\BFW\Subject $subject)
141
    {
142
        $this->ctrlRouterInfos = $subject->getContext();
143
    }
144
    
145
    /**
146
     * Run controller system if application is not run in cli mode
147
     * 
148
     * @return void
149
     */
150
    protected function run()
151
    {
152
        if (PHP_SAPI === 'cli') {
153
            return;
154
        }
155
        
156
        if ($this->ctrlRouterInfos->target === null) {
157
            return;
158
        }
159
        
160
        $this->module
161
            ->monolog
162
            ->getLogger()
163
            ->debug(
164
                'Execute current route.',
165
                ['target' => $this->ctrlRouterInfos->target]
166
            );
167
        
168
        $useClass = $this->config->getValue('useClass');
169
        
170
        if ($useClass === true) {
171
            $this->runObject();
172
        } else {
173
            $this->runProcedural();
174
        }
175
    }
176
    
177
    /**
178
     * Call controller when is an object.
179
     * 
180
     * @return void
181
     */
182
    protected function runObject()
183
    {
184
        $targetInfos = $this->ctrlRouterInfos->target;
185
        
186
        if (
187
            !is_array($targetInfos) ||
188
            (is_array($targetInfos) && count($targetInfos) !== 2)
189
        ) {
190
            throw new Exception(
191
                'The route target should be an array with the class name '
192
                .'(first value) and the method name (second value).',
193
                self::ERR_RUN_OBJECT_MISSING_DATAS_INTO_TARGET
194
            );
195
        }
196
        
197
        $class  = $targetInfos[0];
198
        $method = $targetInfos[1];
199
        
200
        if (!class_exists($class)) {
201
            throw new Exception(
202
                'Class '.$class.' not found',
203
                self::ERR_RUN_OBJECT_CLASS_NOT_FOUND
204
            );
205
        }
206
        
207
        $classInstance = new $class;
208
        if (!method_exists($classInstance, $method)) {
209
            throw new Exception(
210
                'Method '.$method.' not found in class '.$class,
211
                self::ERR_RUN_OBJECT_METHOD_NOT_FOUND
212
            );
213
        }
214
        
215
        $classInstance->{$method}();
216
    }
217
    
218
    /**
219
     * Call controler when is a procedural file
220
     * 
221
     * @return void
222
     */
223
    protected function runProcedural()
224
    {
225
        $routerLinker = $this->ctrlRouterInfos;
226
        
227
        $runFct = function() use ($routerLinker) {
228
            $controllerFile = (string) $routerLinker->target;
229
            
230
            if (!file_exists(CTRL_DIR.$controllerFile)) {
231
                throw new Exception(
232
                    'Controller file '.$controllerFile.' not found.',
233
                    self::ERR_RUN_PROCEDURAL_FILE_NOT_FOUND
234
                );
235
            }
236
            
237
            include(CTRL_DIR.$controllerFile);
238
        };
239
        
240
        $runFct();
241
    }
242
}
243