Completed
Push — master ( 2a6148...c1b249 )
by Park Jong-Hun
03:18
created

Application::setErrorReporterConfig()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 1
Metric Value
c 1
b 0
f 1
dl 0
loc 4
rs 10
cc 1
eloc 2
nc 1
nop 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
14
class Application
15
{
16
    /**
17
     * @var Map
18
     */
19
    private $routerMap;
20
21
    private $routeConfig = [];
22
    private $siteConfig = [];
23
    private $errorReporterConfig = [];
24
    private $viewEngineConfig = [];
25
    private $dbConfig = [];
26
27
    private $errorReporters = [];
28
29
    /**
30
     * Singleton: private constructor
31
     */
32
    private function __construct()
33
    {
34
    }
35
36
    /**
37
     * @return Application
38
     */
39
    public static function getInstance()
40
    {
41
        static $instance = null;
42
43
        if ($instance === null) {
44
            $instance = new self();
45
        }
46
47
        return $instance;
48
    }
49
50
    public function boot()
51
    {
52
        $this->setSiteConfig(require '../config/site.php');
53
        $this->setErrorReporterConfig(require '../config/errorReporter.php');
54
        $this->setDbConfig(require '../config/db.php');
55
        $this->setViewEngineConfig(require '../config/viewEngine.php');
56
57
        $this->setDisplayError($this->siteConfig['displayErrors']);
58
        $this->registerErrorReporters();
59
60
        $this->setRouterConfig(require '../config/router.php');
61
        $this->dispatcher(new Request());
62
    }
63
64
    public function setSiteConfig(array $siteConfig)
65
    {
66
        $this->siteConfig = $siteConfig;
67
    }
68
69
    public function setErrorReporterConfig(array $errorReporterConfig)
70
    {
71
        $this->errorReporterConfig = $errorReporterConfig;
72
    }
73
74
    public function setDbConfig(array $dbConfig)
75
    {
76
        $this->dbConfig = $dbConfig;
77
    }
78
79
    public function setViewEngineConfig(array $viewEngineConfig)
80
    {
81
        $this->viewEngineConfig = $viewEngineConfig;
82
    }
83
84
    public function setDisplayError($isDisplay)
85
    {
86
        error_reporting(E_ALL);
87
        ini_set('display_errors', $isDisplay);
88
    }
89
90
    public function registerErrorReporters()
91
    {
92
        $enabledReporters = $this->siteConfig['errorReporters'];
93
        $errorReporters = [];
94
95
        foreach ($enabledReporters as $reporter) {
96
            $errorReporters[] = $this->buildErrorReporter($reporter);
97
        }
98
99
        $this->errorReporters = $errorReporters;
100
101
        /**
102
         * @var ErrorReporter $reporter
103
         */
104
        set_exception_handler(function ($exception) {
105
            foreach ($this->errorReporters as $reporter) {
106
                $reporter->report($exception);
107
            }
108
        });
109
    }
110
111
    private function buildErrorReporter($reporterName)
112
    {
113
        $namespace = $this->errorReporterConfig['namespace'];
114
        $class = $namespace. '\\' . $reporterName;
115
116
        $setting = $this->errorReporterConfig[$reporterName];
117
118
        /* @var ErrorReporter */
119
        $reporter = new $class();
120
        $reporter->init($setting);
121
122
        return $reporter;
123
    }
124
125
    public function setRouterConfig(array $routeConfig)
126
    {
127
        $this->routeConfig = $routeConfig;
128
        $this->buildRouterMap();
129
    }
130
131
    private function buildRouterMap()
132
    {
133
        $routerMap = new Map();
134
        $routerMap->setNamespace($this->routeConfig['namespace']);
135
136
        foreach ($this->getRoutePathMap() as $k => $v) {
137
            $this->addRouterMap($routerMap, $k, $v);
138
        }
139
140
        $this->routerMap = $routerMap;
141
    }
142
143
    private function getRoutePathMap()
144
    {
145
        $paths = $this->routeConfig;
146
        unset($paths['namespace']);
147
148
        return $paths;
149
    }
150
151
    /**
152
     * @param Map    $routerMap
153
     * @param string $path  url path
154
     * @param string|array|closure $handler
155
     */
156
    private function addRouterMap(Map $routerMap, $path, $handler)
157
    {
158
        // string | closure
159
        if (gettype($handler) === 'string' || is_callable($handler)) {
160
            $routerMap->get($path, $handler);
161
            return;
162
        }
163
164
        /**
165
         * $handler array schema
166
         * (optional) $handler['GET' | 'POST']
167
         *                => method_name(ex. 'classname.methodname')
168
         *                    or function_name
169
         *                    or closure
170
         */
171
        if (isset($handler['GET'])) {
172
            $routerMap->get($path, $handler['GET']);
173
        }
174
        if (isset($handler['POST'])) {
175
            $routerMap->post($path, $handler['POST']);
176
        }
177
    }
178
179
180
    public function dispatcher(Request $request)
181
    {
182
        $url = $this->resolveUrl($request);
183
        $viewModel = new ViewModel();
184
185
        $parameterMap = new ParameterMap();
186
        $this->bindUrlParameter($parameterMap, $url);
187
        $this->bindViewModelParameter($parameterMap, $viewModel);
188
189
        $returnOfController = $this->executeController($request, $parameterMap);
190
191
        $view = $this->resolveView($returnOfController);
192
        $this->setViewVariables($view, $viewModel->getVariables());
193
        $view->render();
194
    }
195
196
    private function resolveUrl(Request $request)
197
    {
198
        $matcher = new Matcher($this->routerMap);
199
        return $matcher->match($request)['urlNameMatching'] ?: [];
200
    }
201
202
    private function executeController(Request $request, ParameterMap $parameterMap)
203
    {
204
        $dispatcher = new Dispatcher($this->routerMap);
205
        return $dispatcher->dispatch($request, $parameterMap);
206
    }
207
208
    /**
209
     * @param  mixed $returnOfController
210
     * @return View
211
     */
212
    private function resolveView($returnOfController)
213
    {
214
        $viewResolver = new ViewResolver($returnOfController);
215
        return $viewResolver->resolve($this->viewEngineConfig[$this->siteConfig['viewEngine']]);
216
    }
217
218
    private function bindUrlParameter(ParameterMap $map, array $url)
219
    {
220
        $map->bindByNameWithType('array', 'url', $url);
221
222
        foreach ($url as $name => $value) {
223
            $map->bindByName($name, $value);
224
        }
225
    }
226
227
    private function bindViewModelParameter(ParameterMap $map, ViewModel $viewModel)
228
    {
229
        $map->bindByType(ViewModel::class, $viewModel);
230
    }
231
232
    private function setViewVariables(View $view, array $var)
233
    {
234
        foreach ($var as $key => $value) {
235
            $view->set($key, $value);
236
        }
237
    }
238
239
240
    /**
241
     * Return url path with site url
242
     * @param  string $url sub url
243
     * @return string
244
     */
245
    public function url($url = '')
246
    {
247
        return $this->siteConfig['url'] . $url;
248
    }
249
250
251
    /**
252
     * @return EntityManager
253
     */
254
    public function getEntityManager()
255
    {
256
        $config = Setup::createAnnotationMetadataConfiguration(
257
                    $this->dbConfig['entityPath'],
258
                    $this->dbConfig['devMode']
259
                    );
260
        return EntityManager::create($this->dbConfig[$this->siteConfig['database']], $config);
261
    }
262
}
263