Completed
Push — master ( c7d4dc...13d232 )
by Carlos
32:44 queued 24:34
created

Application   A

Complexity

Total Complexity 22

Size/Duplication

Total Lines 227
Duplicated Lines 0 %

Coupling/Cohesion

Components 2
Dependencies 9

Test Coverage

Coverage 67.57%

Importance

Changes 3
Bugs 0 Features 2
Metric Value
wmc 22
c 3
b 0
f 2
lcom 2
cbo 9
dl 0
loc 227
ccs 50
cts 74
cp 0.6757
rs 10

12 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 19 2
A setExceptionHandler() 0 6 1
A getExceptionHandler() 0 4 1
A addProvider() 0 6 1
A setProviders() 0 8 2
A getProviders() 0 4 1
A __get() 0 4 1
A __set() 0 4 1
A registerProviders() 0 6 2
A registerBase() 0 18 1
B registerExceptionHandler() 0 33 5
A initializeLogger() 0 12 4
1
<?php
2
3
/*
4
 * This file is part of the overtrue/wechat.
5
 *
6
 * (c) overtrue <[email protected]>
7
 *
8
 * This source file is subject to the MIT license that is bundled
9
 * with this source code in the file LICENSE.
10
 */
11
12
/**
13
 * Application.php.
14
 *
15
 * Part of Overtrue\WeChat.
16
 *
17
 * For the full copyright and license information, please view the LICENSE
18
 * file that was distributed with this source code.
19
 *
20
 * @author    overtrue <[email protected]>
21
 * @copyright 2015
22
 *
23
 * @link      https://github.com/overtrue/wechat
24
 * @link      http://overtrue.me
25
 */
26
namespace EasyWeChat\Foundation;
27
28
use Doctrine\Common\Cache\FilesystemCache;
29
use EasyWeChat\Core\AccessToken;
30
use EasyWeChat\Support\Log;
31
use ErrorException;
32
use Monolog\Handler\NullHandler;
33
use Monolog\Handler\StreamHandler;
34
use Monolog\Logger;
35
use Pimple\Container;
36
use Symfony\Component\HttpFoundation\Request;
37
38
/**
39
 * Class Application.
40
 */
41
class Application extends Container
42
{
43
    /**
44
     * Service Providers.
45
     *
46
     * @var array
47
     */
48
    protected $providers = [
49
        ServiceProviders\ServerServiceProvider::class,
50
        ServiceProviders\UserServiceProvider::class,
51
        ServiceProviders\JsServiceProvider::class,
52
        ServiceProviders\OAuthServiceProvider::class,
53
        ServiceProviders\MenuServiceProvider::class,
54
        ServiceProviders\NoticeServiceProvider::class,
55
        ServiceProviders\MaterialServiceProvider::class,
56
        ServiceProviders\StaffServiceProvider::class,
57
        ServiceProviders\UrlServiceProvider::class,
58
        ServiceProviders\QRCodeServiceProvider::class,
59
        ServiceProviders\SemanticServiceProvider::class,
60
        ServiceProviders\StatsServiceProvider::class,
61
        ServiceProviders\PaymentServiceProvider::class,
62
        ServiceProviders\POIServiceProvider::class,
63
        ServiceProviders\BroadcastServiceProvider::class,
64
    ];
65
66
    /**
67
     * The exception handler.
68
     *
69
     * @var callable
70
     */
71
    protected $exceptionHandler;
72
73
    /**
74
     * Application constructor.
75
     *
76
     * @param array $config
77
     */
78 3
    public function __construct($config)
79
    {
80 3
        parent::__construct();
81
82
        $this['config'] = function () use ($config) {
83 3
            return new Config($config);
84
        };
85
86 3
        if ($this['config']['debug']) {
87
            error_reporting(E_ALL);
88
        }
89
90 3
        $this->registerProviders();
91 3
        $this->registerBase();
92 3
        $this->initializeLogger();
93 3
        $this->registerExceptionHandler();
94
95 3
        Log::debug('Current configuration:', $config);
96 3
    }
97
98
    /**
99
     * Set the exception handler.
100
     *
101
     * @param callable $callback
102
     *
103
     * @return $this
104
     */
105
    public function setExceptionHandler(callable $callback)
106
    {
107
        $this->exceptionHandler = $callback;
108
109
        return $this;
110
    }
111
112
    /**
113
     * Return current exception handler.
114
     *
115
     * @return callable
116
     */
117
    public function getExceptionHandler()
118
    {
119
        return $this->exceptionHandler;
120
    }
121
122
    /**
123
     * Add a provider.
124
     *
125
     * @param string $provider
126
     *
127
     * @return Application
128
     */
129 1
    public function addProvider($provider)
130
    {
131 1
        array_push($this->providers, $provider);
132
133 1
        return $this;
134
    }
135
136
    /**
137
     * Set providers.
138
     *
139
     * @param array $providers
140
     */
141 1
    public function setProviders(array $providers)
142
    {
143 1
        $this->providers = [];
144
145 1
        foreach ($providers as $provider) {
146 1
            $this->addProvider($provider);
147 1
        }
148 1
    }
149
150
    /**
151
     * Return all providers.
152
     *
153
     * @return array
154
     */
155 2
    public function getProviders()
156
    {
157 2
        return $this->providers;
158
    }
159
160
    /**
161
     * Magic get access. 
162
     *
163
     * @param string $id
164
     *
165
     * @return mixed
166
     */
167 1
    public function __get($id)
168
    {
169 1
        return $this->offsetGet($id);
170
    }
171
172
    /**
173
     * Magic set access.
174
     *
175
     * @param string $id    
176
     * @param mixed  $value 
177
     */
178 1
    public function __set($id, $value)
179
    {
180 1
        return $this->offsetSet($id, $value);
181
    }
182
183
    /**
184
     * Register providers.
185
     */
186 3
    private function registerProviders()
187
    {
188 3
        foreach ($this->providers as $provider) {
189 3
            $this->register(new $provider());
190 3
        }
191 3
    }
192
193
    /**
194
     * Register basic providers.
195
     */
196 3
    private function registerBase()
197
    {
198
        $this['request'] = function () {
199
            return Request::createFromGlobals();
200
        };
201
202
        $this['cache'] = function () {
203
            return new FilesystemCache(sys_get_temp_dir());
204
        };
205
206
        $this['access_token'] = function () {
207
           return new AccessToken(
208
               $this['config']['app_id'],
209
               $this['config']['secret'],
210
               $this['cache']
211
           );
212
        };
213 3
    }
214
215
    /**
216
     * Register exception and error handler.
217
     */
218 3
    private function registerExceptionHandler()
219
    {
220 3
        $logTemplate = '%s: %s in %s on line %s.';
221
222
        $lastExceptionHandler = set_exception_handler(function ($e) use (&$lastExceptionHandler, $logTemplate) {
223
            Log::error(sprintf($logTemplate, $e->getCode(), $e->getMessage(), $e->getFile(), $e->getLine()));
224
225
            $this->exceptionHandler && call_user_func_array($this->exceptionHandler, [$e]);
226
227
            if (is_callable($lastExceptionHandler)) {
228
                return call_user_func($lastExceptionHandler, $e);
229
            }
230 3
        });
231
232
        $errorHandler = function ($severity, $message, $file, $line) use ($logTemplate) {
233 1
            Log::error(sprintf($logTemplate, $severity, $message, $file, $line));
234
235 1
            if (error_reporting() & $severity) {
236 1
                throw new ErrorException($message, 0, $severity, $file, $line);
237
            }
238 3
        };
239
240 3
        set_error_handler($errorHandler);
241
242 3
        register_shutdown_function(function () use ($errorHandler) {
243
            $lastError = error_get_last();
244
245
            if ($lastError['type'] === E_ERROR) {
246
                // fatal error
247
                $errorHandler(E_ERROR, $lastError['message'], $lastError['file'], $lastError['line']);
248
            }
249 3
        });
250 3
    }
251
252
    /**
253
     * Initialize logger.
254
     */
255 3
    private function initializeLogger()
256
    {
257 3
        $logger = new Logger('easywechat');
258
259 3
        if (!$this['config']['debug'] || defined('PHPUNIT_RUNNING')) {
260 3
            $logger->pushHandler(new NullHandler());
261 3
        } elseif ($logFile = $this['config']['log.file']) {
262
            $logger->pushHandler(new StreamHandler($logFile, $this['config']->get('log.level', Logger::WARNING)));
263
        }
264
265 3
        Log::setLogger($logger);
266 3
    }
267
}
268