Passed
Pull Request — dev (#45)
by Stone
03:41 queued 01:40
created

Controller::loadModule()   F

Complexity

Conditions 16
Paths 300

Size

Total Lines 50
Code Lines 29

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 16
eloc 29
nc 300
nop 1
dl 0
loc 50
rs 3.4833
c 0
b 0
f 0

How to fix   Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

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
        $loadModuleObj = '';
86
        $found = false;
87
        $childClassNamespace = new \ReflectionClass(get_class($this));
88
        $childClassNamespace = $childClassNamespace->getNamespaceName();
89
        //check in classNameSpace, make sure we are not already in App or core
90
        if (class_exists($childClassNamespace . '\\Modules\\' . $loadModule)) {
91
            if($childClassNamespace !== 'App\\Modules\\' || $childClassNamespace !== 'Core\\Modules\\'){
92
                $loadModuleObj = $childClassNamespace . '\\' . $loadModule;
93
                $found = true;
94
            }
95
        }
96
        //check in app
97
        if (class_exists('App\\Modules\\' . $loadModule)) {
98
            if($found && Config::DEV_ENVIRONMENT){
99
                $this->alertBox->setAlert($loadModule.' already defined in namespace', 'error');
100
            }
101
            if(!$found){
102
                $loadModuleObj = 'App\\Modules\\' . $loadModule;
103
                $found = true;
104
            }
105
        }
106
        //check in core, send error popup if overcharged
107
        if (class_exists('Core\\Modules\\' . $loadModule)) {
108
            if($found && Config::DEV_ENVIRONMENT){
109
                $this->alertBox->setAlert($loadModule.' already defined in app', 'error');
110
            }
111
            if(!$found){
112
                $loadModuleObj = 'Core\\Modules\\' . $loadModule;
113
                $found = true;
114
            }
115
        }
116
        if(!$found || $loadModuleObj ==='') {
117
            throw new \ErrorException('module ' . $loadModule . ' does not exist or not loaded');
118
        }
119
120
        //Modules must be children of the Module template
121
        if (!is_subclass_of($loadModuleObj, 'Core\Modules\Module')) {
122
            throw new \ErrorException('Module ' . $loadModuleName . ' must be a sub class of module');
123
        }
124
125
        $loadedModule = new $loadModuleObj($this->container);
126
        //we are not allowed to create public modules, they must be a placeholder ready
127
        if (!property_exists($this, $loadModuleName)) {
128
            throw new \ErrorException('the protected or private variable of ' . $loadModuleName . ' is not present');
129
        }
130
        $this->$loadModuleName = $loadedModule;
131
    }
132
133
    public function index()
134
    {
135
        //if no index, then redirect to the home page or throw an error if in dev; just for debugging purposes
136
        if (Config::DEV_ENVIRONMENT) {
137
            throw new \ErrorException("no index() available in controller call");
138
        }
139
        $this->container->getResponse()->redirect();
140
    }
141
142
    /**
143
     * Calls the templating engine and returns the rendered view
144
     *
145
     * @param $template string the template file name. .twig will be appended
146
     * @return string the rendered template
147
     * @throws \Twig_Error_Loader
148
     * @throws \Twig_Error_Runtime
149
     * @throws \Twig_Error_Syntax
150
     */
151
    public function getView($template)
152
    {
153
        $twig = $this->container->getTemplate();
154
        return $twig->render($template . '.twig', $this->data);
155
    }
156
157
    /**
158
     * rendering the view
159
     *
160
     * @param $template string the template file
161
     * @throws \Twig_Error_Loader
162
     * @throws \Twig_Error_Runtime
163
     * @throws \Twig_Error_Syntax
164
     */
165
    public function renderView($template): void
166
    {
167
        //checking if any alerts and pas the to the template
168
        if ($this->alertBox->alertsPending()) {
169
            $this->data['alert_messages'] = $this->alertBox->getAlerts();
170
        }
171
        if (Config::DEV_ENVIRONMENT) {
172
            $this->devHelper();
173
        }
174
        $twig = $this->container->getTemplate();
175
        $twig->display($template . '.twig', $this->data);
176
    }
177
178
    protected function devHelper($var = '')
179
    {
180
        if (!isset($this->data['dev_info'])) {
181
            $this->data['dev'] = true;
182
            $classMethods = [];
183
            if ($var != '') {
184
                $classMethods['passed_var'] = $var;
185
            }
186
            $classMethods['class_object_methods'] = get_class_methods(get_class($this));
187
            $classMethods['class_object_vars'] = get_object_vars($this);
188
            $classMethods['session_vars'] = $_SESSION;
189
            $classMethods['namespace'] = __NAMESPACE__;
190
            $childClassNamespace = new \ReflectionClass(get_class($this));
191
            $childClassNamespace = $childClassNamespace->getNamespaceName();
192
            $classMethods['classNamespace'] = $childClassNamespace;
193
194
            $this->data['dev_info'] = $classMethods;
195
        }
196
197
    }
198
}