Passed
Push — Auth ( aacdac...a6c03c )
by Stone
02:44
created

Controller   A

Complexity

Total Complexity 25

Size/Duplication

Total Lines 266
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
eloc 82
dl 0
loc 266
rs 10
c 0
b 0
f 0
wmc 25

12 Methods

Rating   Name   Duplication   Size   Complexity  
A loadModule() 0 14 3
A getView() 0 4 1
A __construct() 0 19 2
A getModuleNamespace() 0 22 4
A addToDevHelper() 0 10 3
A sendSessionVars() 0 3 1
A renderView() 0 15 3
A devHelper() 0 15 1
A getSessionVars() 0 3 1
A index() 0 7 2
A onlyPost() 0 6 2
A onlyUser() 0 5 2
1
<?php
2
3
namespace Core;
4
5
use Twig\Template;
6
use Core\Traits\StringFunctions;
7
8
/**
9
 * Class Controller
10
 * @package Core
11
 *
12
 * PHP version 7
13
 */
14
abstract class Controller
15
{
16
    use StringFunctions;
0 ignored issues
show
Bug introduced by
The trait Core\Traits\StringFunctions requires the property $childNodes which is not provided by Core\Controller.
Loading history...
17
    /**
18
     * the data that will be pushed to the view
19
     * @var array
20
     */
21
    protected $data = [];
22
23
    /**
24
     * @var Container dependency injector
25
     */
26
    protected $container;
27
28
    /**
29
     * @var Dependency\Session the session handler
30
     */
31
    protected $session;
32
33
    /**
34
     * The request object to handle all gets and posts
35
     * @var Dependency\Request
36
     *
37
     */
38
    protected $request;
39
40
    /**
41
     * The response module to handle response messages
42
     * @var Dependency\Response
43
     */
44
    protected $response;
45
46
    protected $cookie;
47
48
    /**
49
     * this will automaticly load all the modules listed and store them as $moduleName in tle class
50
     * Child classes can call aditional modules by calling $this->
51
     * @var array List of modules to load
52
     */
53
    protected $loadModules = [
54
        'Csrf',
55
        'AlertBox',
56
        'Auth',
57
        'pagination'
58
    ];
59
60
    /**
61
     * We need to declare out modules here, else they will be public
62
     * @var object
63
     */
64
    protected $csrf;
65
    protected $alertBox;
66
    protected $auth;
67
    protected $pagination;
68
69
    /**
70
     * Controller constructor.
71
     * We get the module list and construct it. We can also over wright the module in app but sill has to inherit from core module
72
     * @param Container $container
73
     *
74
     * @throws \ErrorException on module loading error
75
     * @throws \ReflectionException should never be thrown since only child classes call this
76
     */
77
    public function __construct(Container $container)
78
    {
79
        $this->container = $container;
80
81
        //removing any duplicates that could have been passed in child classes
82
        $this->loadModules = array_unique($this->loadModules);
83
84
        //We load all our module objects into our object
85
        foreach ($this->loadModules as $loadModule) {
86
            $this->loadModule($loadModule);
87
        }
88
        $this->session = $this->container->getSession();
89
90
        $this->request = $container->getRequest(); //adding our request object as it will be needed in the ajax calls
91
        $this->response = $container->getResponse();
92
        $this->cookie = $container->getCookie();
93
94
        //Setting up csrf token security for all calls
95
        $this->data['csrf_token'] = $this->csrf->getCsrfKey(); //storing the security id into the data array to be sent to the view and added in the meta head
96
    }
97
98
    /**
99
     * load the module to the object
100
     * We look for module in the namespace, then in app and finally in the core.
101
     * This enables us to over-ride the core or app module with a custom module for the namespace.
102
     * @param $loadModule string the module to search for and load
103
     * @throws \ErrorException if module doesn't exits
104
     * @throws \ReflectionException
105
     */
106
    private function loadModule($loadModule)
107
    {
108
        $loadModuleName = lcfirst($loadModule);
109
        $loadModuleObj = $this->getModuleNamespace($loadModule);
110
        //Modules must be children of the Module template
111
        if (!is_subclass_of($loadModuleObj, 'Core\Modules\Module')) {
112
            throw new \ErrorException('Module ' . $loadModuleName . ' must be a sub class of module');
113
        }
114
        $loadedModule = new $loadModuleObj($this->container);
115
        //we are not allowed to create public modules, they must be a placeholder ready
116
        if (!property_exists($this, $loadModuleName)) {
117
            throw new \ErrorException('the protected or private variable of ' . $loadModuleName . ' is not present');
118
        }
119
        $this->$loadModuleName = $loadedModule;
120
    }
121
122
    /**
123
     * takes a module to load and verifies if exists in the current namespace modules, app modules or core modules
124
     * @param $loadModule string Module to look for
125
     * @return string the full module namespace
126
     * @throws \ErrorException if no module is found
127
     * @throws \ReflectionException Should never happen since we are calling on $this
128
     */
129
    private function getModuleNamespace($loadModule)
130
    {
131
        $childClass = new \ReflectionClass(get_class($this));
132
        $childClassNamespace = $childClass->getNamespaceName();
133
        //check in classNameSpace
134
        if (class_exists($childClassNamespace . '\\Modules\\' . $loadModule)) {
135
            $this->addToDevHelper('module ' . $loadModule . ' loaded', $childClassNamespace . '\\' . $loadModule);
136
            return $childClassNamespace . '\\' . $loadModule;
137
        }
138
        //check in app
139
        if (class_exists('App\\Modules\\' . $loadModule)) {
140
            $this->addToDevHelper('module ' . $loadModule . ' loaded', 'App\\Modules\\' . $loadModule);
141
            return 'App\\Modules\\' . $loadModule;
142
        }
143
        //check in core, send error popup if overcharged
144
        if (class_exists('Core\\Modules\\' . $loadModule)) {
145
            $this->addToDevHelper('module ' . $loadModule . ' loaded', 'Core\\Modules\\' . $loadModule);
146
            return 'Core\\Modules\\' . $loadModule;
147
        }
148
149
        //if we are here then no module found
150
        throw new \ErrorException('module ' . $loadModule . ' does not exist or not loaded');
151
152
    }
153
154
    public function index()
155
    {
156
        //if no index, then redirect to the home page or throw an error if in dev; just for debugging purposes
157
        if (Config::DEV_ENVIRONMENT) {
158
            throw new \ErrorException("no index() available in controller call");
159
        }
160
        $this->container->getResponse()->redirect();
161
    }
162
163
    /**
164
     * Calls the templating engine and returns the rendered view
165
     *
166
     * @param $template string the template file name. .twig will be appended
167
     * @return string the rendered template
168
     * @throws \Twig_Error_Loader
169
     * @throws \Twig_Error_Runtime
170
     * @throws \Twig_Error_Syntax
171
     */
172
    public function getView($template)
173
    {
174
        $twig = $this->container->getTemplate();
175
        return $twig->render($template . '.twig', $this->data);
176
    }
177
178
    /**
179
     * rendering the view
180
     *
181
     * @param $template string the template file
182
     * @throws \Twig_Error_Loader
183
     * @throws \Twig_Error_Runtime
184
     * @throws \Twig_Error_Syntax
185
     * @throws \ReflectionException
186
     */
187
    public function renderView($template): void
188
    {
189
        //checking if any alerts and pas the to the template
190
        if ($this->alertBox->alertsPending()) {
191
            $this->data['alert_messages'] = $this->alertBox->getAlerts();
192
        }
193
        //adding the session vars to the page
194
        $this->sendSessionVars();
195
        //adding the dev helper to the page
196
        if (Config::DEV_ENVIRONMENT) {
197
            $this->devHelper();
198
        }
199
200
        $twig = $this->container->getTemplate();
201
        $twig->display($template . '.twig', $this->data);
202
    }
203
204
    /**
205
     * construct a dev helper panel
206
     * @throws \ReflectionException
207
     */
208
    protected function devHelper()
209
    {
210
        $this->data['dev'] = true;
211
212
        $this->addToDevHelper('Class Methods', get_class_methods(get_class($this)));
213
        $this->addToDevHelper('Session Vars', $this->session->getAllSessionVars());
214
        $this->addToDevHelper('uri', $this->container->getRequest()->getUri());
215
        $childClassNamespace = new \ReflectionClass(get_class($this));
216
        $childClassNamespace = $childClassNamespace->getNamespaceName();
217
        $this->addToDevHelper('Child Namespace', $childClassNamespace);
218
219
        //for our object variables, we don't want the devinfo
220
        $objVars = get_object_vars($this);
221
        unset($objVars['data']['dev_info']);
222
        $this->addToDevHelper('Object Variables', $objVars);
223
    }
224
225
    /**
226
     * add info to our dev helper panel
227
     * @param $name
228
     * @param $var
229
     */
230
    protected function addToDevHelper($name, $var)
231
    {
232
        //only populate if in dev environment
233
        if (Config::DEV_ENVIRONMENT) {
234
            $classMethods = [];
235
            $classMethods[$name] = $var;
236
            if (!isset($this->data['dev_info'])) {
237
                $this->data['dev_info'] = [];
238
            }
239
            $this->data['dev_info'] += $classMethods;
240
        }
241
    }
242
243
    /**
244
     * get all the session variables
245
     * @return mixed
246
     */
247
    protected function getSessionVars()
248
    {
249
        return $this->container->getSession()->getAllSessionVars();
250
    }
251
252
    /**
253
     * Send the session variables to the data variable to enable access in twig
254
     */
255
    protected function sendSessionVars()
256
    {
257
        $this->data['session'] = $this->getSessionVars();
258
    }
259
260
    /**
261
     * Only allow post messages
262
     */
263
    protected function onlyPost()
264
    {
265
        //is post
266
        if (!$this->request->isPost()) {
267
            $this->alertBox->setAlert('Only post messages allowed', 'error');
268
            $this->response->redirect('/');
269
        }
270
    }
271
272
    /**
273
     * only allow registered users
274
     */
275
    protected function onlyUser()
276
    {
277
        if (!$this->auth->isUser()) {
278
            $this->alertBox->setAlert("Only registered users can access this", 'error');
279
            $this->container->getResponse()->redirect();
280
        }
281
    }
282
}