Completed
Push — master ( c423df...c8e3b5 )
by Park Jong-Hun
03:08
created

Application::boot()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 13
Code Lines 9

Duplication

Lines 0
Ratio 0 %

Importance

Changes 4
Bugs 0 Features 1
Metric Value
c 4
b 0
f 1
dl 0
loc 13
rs 9.4285
cc 1
eloc 9
nc 1
nop 0

1 Method

Rating   Name   Duplication   Size   Complexity  
A Application::setErrorReporterConfig() 0 4 1
1
<?php
2
3
namespace Core;
4
5
use Prob\Handler\ParameterMap;
6
use Prob\Router\Dispatcher;
7
use Prob\Rewrite\Request;
8
use Prob\Router\Map;
9
use Prob\Router\Matcher;
10
use Doctrine\ORM\Tools\Setup;
11
use Doctrine\ORM\EntityManager;
12
use Core\ErrorReporter;
13
use \ErrorException;
14
15
class Application
16
{
17
    /**
18
     * @var Map
19
     */
20
    private $routerMap;
21
22
    private $routeConfig = [];
23
    private $siteConfig = [];
24
    private $errorReporterConfig = [];
25
    private $viewEngineConfig = [];
26
    private $dbConfig = [];
27
28
    private $errorReporters = [];
29
30
    /**
31
     * Singleton: private constructor
32
     */
33
    private function __construct()
34
    {
35
    }
36
37
    /**
38
     * @return Application
39
     */
40
    public static function getInstance()
41
    {
42
        static $instance = null;
43
44
        if ($instance === null) {
45
            $instance = new self();
46
        }
47
48
        return $instance;
49
    }
50
51
    public function setSiteConfig(array $siteConfig)
52
    {
53
        $this->siteConfig = $siteConfig;
54
    }
55
56
    public function setErrorReporterConfig(array $errorReporterConfig)
57
    {
58
        $this->errorReporterConfig = $errorReporterConfig;
59
    }
60
61
    public function setDbConfig(array $dbConfig)
62
    {
63
        $this->dbConfig = $dbConfig;
64
    }
65
66
    public function setViewEngineConfig(array $viewEngineConfig)
67
    {
68
        $this->viewEngineConfig = $viewEngineConfig;
69
    }
70
71
    public function setDisplayError($isDisplay)
72
    {
73
        error_reporting(E_ALL);
74
        ini_set('display_errors', $isDisplay);
75
    }
76
77
    public function registerErrorReporters()
78
    {
79
        $this->errorReporters = $this->getErrorReporterInstances();
80
81
        /**
82
         * @var ErrorReporter $reporter
83
         */
84
        set_exception_handler(function ($exception) {
85
            foreach ($this->errorReporters as $reporter) {
86
                $reporter->report($exception);
87
            }
88
        });
89
90
        set_error_handler(function ($errno, $errstr, $errfile, $errline, array $errcontext) {
0 ignored issues
show
Unused Code introduced by
The parameter $errcontext is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
91
            throw new ErrorException($errstr, 0, $errno, $errfile, $errline);
92
        });
93
    }
94
95
    private function getErrorReporterInstances()
96
    {
97
        $enabledReporters = $this->siteConfig['errorReporters'];
98
        $errorReporters = [];
99
100
        foreach ($enabledReporters as $reporter) {
101
            $errorReporters[] = $this->buildErrorReporter($reporter);
102
        }
103
104
        return $errorReporters;
105
    }
106
107
    private function buildErrorReporter($reporterName)
108
    {
109
        $namespace = $this->errorReporterConfig['namespace'];
110
        $class = $namespace. '\\' . $reporterName;
111
112
        $setting = $this->errorReporterConfig[$reporterName];
113
114
        /* @var ErrorReporter */
115
        $reporter = new $class();
116
        $reporter->init($setting);
117
118
        return $reporter;
119
    }
120
121
    public function setRouterConfig(array $routeConfig)
122
    {
123
        $this->routeConfig = $routeConfig;
124
        $this->buildRouterMap();
125
    }
126
127
    private function buildRouterMap()
128
    {
129
        $routerMap = new Map();
130
        $routerMap->setNamespace($this->routeConfig['namespace']);
131
132
        foreach ($this->getRoutePathMap() as $k => $v) {
133
            $this->addRouterMap($routerMap, $k, $v);
134
        }
135
136
        $this->routerMap = $routerMap;
137
    }
138
139
    private function getRoutePathMap()
140
    {
141
        $paths = $this->routeConfig;
142
        unset($paths['namespace']);
143
144
        return $paths;
145
    }
146
147
    /**
148
     * @param Map    $routerMap
149
     * @param string $path  url path
150
     * @param string|array|closure $handler
151
     */
152
    private function addRouterMap(Map $routerMap, $path, $handler)
153
    {
154
        // string | closure
155
        if (gettype($handler) === 'string' || is_callable($handler)) {
156
            $routerMap->get($path, $handler);
157
            return;
158
        }
159
160
        /**
161
         * $handler array schema
162
         * (optional) $handler['GET' | 'POST']
163
         *                => method_name(ex. 'classname.methodname')
164
         *                    or function_name
165
         *                    or closure
166
         */
167
        if (isset($handler['GET'])) {
168
            $routerMap->get($path, $handler['GET']);
169
        }
170
        if (isset($handler['POST'])) {
171
            $routerMap->post($path, $handler['POST']);
172
        }
173
    }
174
175
176
    public function dispatcher(Request $request)
177
    {
178
        $url = $this->resolveUrl($request);
179
        $viewModel = new ViewModel();
180
181
        $parameterMap = new ParameterMap();
182
        $this->bindUrlParameter($parameterMap, $url);
183
        $this->bindViewModelParameter($parameterMap, $viewModel);
184
185
        $returnOfController = $this->executeController($request, $parameterMap);
186
187
        $view = $this->resolveView($returnOfController);
188
        $this->setViewVariables($view, $viewModel->getVariables());
189
        $view->render();
190
    }
191
192
    private function resolveUrl(Request $request)
193
    {
194
        $matcher = new Matcher($this->routerMap);
195
        return $matcher->match($request)['urlNameMatching'] ?: [];
196
    }
197
198
    private function executeController(Request $request, ParameterMap $parameterMap)
199
    {
200
        $dispatcher = new Dispatcher($this->routerMap);
201
        return $dispatcher->dispatch($request, $parameterMap);
202
    }
203
204
    /**
205
     * @param  mixed $returnOfController
206
     * @return View
207
     */
208
    private function resolveView($returnOfController)
209
    {
210
        $viewResolver = new ViewResolver($returnOfController);
211
        return $viewResolver->resolve($this->viewEngineConfig[$this->siteConfig['viewEngine']]);
212
    }
213
214
    private function bindUrlParameter(ParameterMap $map, array $url)
215
    {
216
        $map->bindByNameWithType('array', 'url', $url);
217
218
        foreach ($url as $name => $value) {
219
            $map->bindByName($name, $value);
220
        }
221
    }
222
223
    private function bindViewModelParameter(ParameterMap $map, ViewModel $viewModel)
224
    {
225
        $map->bindByType(ViewModel::class, $viewModel);
226
    }
227
228
    private function setViewVariables(View $view, array $var)
229
    {
230
        foreach ($var as $key => $value) {
231
            $view->set($key, $value);
232
        }
233
    }
234
235
236
    /**
237
     * Return url path with site url
238
     * @param  string $url sub url
239
     * @return string
240
     */
241
    public function url($url = '')
242
    {
243
        return $this->siteConfig['url'] . $url;
244
    }
245
246
247
    /**
248
     * @return EntityManager
249
     */
250
    public function getEntityManager()
251
    {
252
        $config = Setup::createAnnotationMetadataConfiguration(
253
                    $this->dbConfig['entityPath'],
254
                    $this->dbConfig['devMode']
255
                    );
256
        return EntityManager::create($this->dbConfig[$this->siteConfig['database']], $config);
257
    }
258
}
259