Passed
Push — Accessing-and-setting-the-site... ( e712c3...48e404 )
by Stone
02:00
created

Controller   A

Complexity

Total Complexity 26

Size/Duplication

Total Lines 181
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
eloc 67
dl 0
loc 181
rs 10
c 0
b 0
f 0
wmc 26

6 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 15 2
F loadModule() 0 49 15
A getView() 0 4 1
A renderView() 0 11 3
A devHelper() 0 17 3
A index() 0 7 2
1
<?php
2
3
namespace Core;
4
5
use Twig\Template;
6
7
/**
8
 * Class Controller
9
 * @package Core
10
 *
11
 * PHP version 7
12
 */
13
abstract class Controller
14
{
15
    /**
16
     * the data that will be pushed to the view
17
     * @var array
18
     */
19
    protected $data = [];
20
21
    /**
22
     * @var Container dependency injector
23
     */
24
    protected $container;
25
26
    /**
27
     * @var Dependency\Session the session handler
28
     */
29
    protected $session;
30
31
    /**
32
     * this will automaticly load all the modules listed and store them as $moduleName in tle class
33
     * Child classes can call aditional modules by calling $this->
34
     * @var array List of modules to load
35
     */
36
    protected $loadModules = [
37
        'Csrf',
38
        'AlertBox'
39
    ];
40
41
    /**
42
     * We need to declare out modules here, else they will be public
43
     * @var object
44
     */
45
    protected $csrf;
46
    protected $alertBox;
47
48
    /**
49
     * Controller constructor.
50
     * 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
51
     * @param Container $container
52
     *
53
     * @throws \ErrorException on module loading error
54
     * @throws \ReflectionException should never be thrown since only child classes call this
55
     */
56
    public function __construct(Container $container)
57
    {
58
        $this->container = $container;
59
60
        //removing any duplicates that could have been passed in child classes
61
        $this->loadModules = array_unique($this->loadModules);
62
63
        //We load all our module objects into our object
64
        foreach ($this->loadModules as $loadModule) {
65
            $this->loadModule($loadModule);
66
        }
67
        $this->session = $this->container->getSession();
68
69
        //Setting up csrf token security for all calls
70
        $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
71
    }
72
73
    /**
74
     * load the module to the object
75
     * We loog for module in the namespace, then in app and finaly in the core.
76
     * This enables us to over-ride the core or app module with a custom module for the namespace.
77
     * @param $loadModule string grabbed from the loadmodules array
78
     * @throws \ErrorException if module doesn't exits
79
     * @throws \ReflectionException should never be thrown since only child classes call this
80
     */
81
    private function loadModule($loadModule)
82
    {
83
        $loadModuleName = lcfirst($loadModule);
84
        //checking for module in namespace, app and core.
85
        $found = false;
86
        $childClassNamespace = new \ReflectionClass(get_class($this));
87
        $childClassNamespace = $childClassNamespace->getNamespaceName();
88
        //check in classNameSpace, make sure we are not already in App or core
89
        if (class_exists($childClassNamespace . '\\Modules\\' . $loadModule)) {
90
            if($childClassNamespace !== 'App\\Modules\\' || $childClassNamespace !== 'Core\\Modules\\'){
91
                $loadModuleObj = $childClassNamespace . '\\' . $loadModule;
92
                $found = true;
93
            }
94
        }
95
        //check in app
96
        if (class_exists('App\\Modules\\' . $loadModule)) {
97
            if($found && Config::DEV_ENVIRONMENT){
98
                $this->alertBox->setAlert($loadModule.' already defined in namespace', 'error');
99
            }
100
            if(!$found){
101
                $loadModuleObj = 'App\\Modules\\' . $loadModule;
102
                $found = true;
103
            }
104
        }
105
        //check in core, send error popup if overcharged
106
        if (class_exists('Core\\Modules\\' . $loadModule)) {
107
            if($found && Config::DEV_ENVIRONMENT){
108
                $this->alertBox->setAlert($loadModule.' already defined in app', 'error');
109
            }
110
            if(!$found){
111
                $loadModuleObj = 'Core\\Modules\\' . $loadModule;
112
                $found = true;
113
            }
114
        }
115
        if(!$found) {
116
            throw new \ErrorException('module ' . $loadModule . ' does not exist');
117
        }
118
119
        //Modules must be children of the Module template
120
        if (!is_subclass_of($loadModuleObj, 'Core\Modules\Module')) {
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $loadModuleObj does not seem to be defined for all execution paths leading up to this point.
Loading history...
121
            throw new \ErrorException('Module ' . $loadModuleName . ' must be a sub class of module');
122
        }
123
124
        $loadedModule = new $loadModuleObj($this->container);
125
        //we are not allowed to create public modules, they must be a placeholder ready
126
        if (!property_exists($this, $loadModuleName)) {
127
            throw new \ErrorException('the protected or private variable of ' . $loadModuleName . ' is not present');
128
        }
129
        $this->$loadModuleName = $loadedModule;
130
    }
131
132
    public function index()
133
    {
134
        //if no index, then redirect to the home page or throw an error if in dev; just for debugging purposes
135
        if (Config::DEV_ENVIRONMENT) {
136
            throw new \ErrorException("no index() available in controller call");
137
        }
138
        $this->container->getResponse()->redirect();
139
    }
140
141
    /**
142
     * Calls the templating engine and returns the rendered view
143
     *
144
     * @param $template string the template file name. .twig will be appended
145
     * @return string the rendered template
146
     * @throws \Twig_Error_Loader
147
     * @throws \Twig_Error_Runtime
148
     * @throws \Twig_Error_Syntax
149
     */
150
    public function getView($template)
151
    {
152
        $twig = $this->container->getTemplate();
153
        return $twig->render($template . '.twig', $this->data);
154
    }
155
156
    /**
157
     * rendering the view
158
     *
159
     * @param $template string the template file
160
     * @throws \Twig_Error_Loader
161
     * @throws \Twig_Error_Runtime
162
     * @throws \Twig_Error_Syntax
163
     */
164
    public function renderView($template): void
165
    {
166
        //checking if any alerts and pas the to the template
167
        if ($this->alertBox->alertsPending()) {
168
            $this->data['alert_messages'] = $this->alertBox->getAlerts();
169
        }
170
        if (Config::DEV_ENVIRONMENT) {
171
            $this->devHelper();
172
        }
173
        $twig = $this->container->getTemplate();
174
        $twig->display($template . '.twig', $this->data);
175
    }
176
177
    protected function devHelper($var = '')
178
    {
179
        if (!isset($this->data['dev_info'])) {
180
            $this->data['dev'] = true;
181
            $classMethods = [];
182
            if ($var != '') {
183
                $classMethods['passed_var'] = $var;
184
            }
185
            $classMethods['class_object_methods'] = get_class_methods(get_class($this));
186
            $classMethods['class_object_vars'] = get_object_vars($this);
187
            $classMethods['session_vars'] = $_SESSION;
188
            $classMethods['namespace'] = __NAMESPACE__;
189
            $childClassNamespace = new \ReflectionClass(get_class($this));
190
            $childClassNamespace = $childClassNamespace->getNamespaceName();
191
            $classMethods['classNamespace'] = $childClassNamespace;
192
193
            $this->data['dev_info'] = $classMethods;
194
        }
195
196
    }
197
}