Completed
Push — master ( 5ddcc0...9e0ead )
by Carlos
42s
created

Application::addProvider()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 6
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 3
CRAP Score 1

Importance

Changes 1
Bugs 0 Features 1
Metric Value
c 1
b 0
f 1
dl 0
loc 6
ccs 3
cts 3
cp 1
rs 9.4285
cc 1
eloc 3
nc 1
nop 1
crap 1
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\ReplyServiceProvider::class,
64
        ServiceProviders\BroadcastServiceProvider::class,
65
    ];
66
67
    /**
68
     * The exception handler.
69
     *
70
     * @var callable
71
     */
72
    protected $exceptionHandler;
73
74
    /**
75
     * Application constructor.
76
     *
77
     * @param array $config
78
     */
79 3
    public function __construct($config)
80
    {
81 3
        parent::__construct();
82
83
        $this['config'] = function () use ($config) {
84 3
            return new Config($config);
85
        };
86
87 3
        if ($this['config']['debug']) {
88
            error_reporting(E_ALL);
89
        }
90
91 3
        $this->registerProviders();
92 3
        $this->registerBase();
93 3
        $this->initializeLogger();
94 3
        $this->registerExceptionHandler();
95
96 3
        Log::debug('Current configuration:', $config);
97 3
    }
98
99
    /**
100
     * Set the exception handler.
101
     *
102
     * @param callable $callback
103
     *
104
     * @return $this
105
     */
106
    public function setExceptionHandler(callable $callback)
107
    {
108
        $this->exceptionHandler = $callback;
109
110
        return $this;
111
    }
112
113
    /**
114
     * Return current exception handler.
115
     *
116
     * @return callable
117
     */
118
    public function getExceptionHandler()
119
    {
120
        return $this->exceptionHandler;
121
    }
122
123
    /**
124
     * Add a provider.
125
     *
126
     * @param string $provider
127
     *
128
     * @return Application
129
     */
130 1
    public function addProvider($provider)
131
    {
132 1
        array_push($this->providers, $provider);
133
134 1
        return $this;
135
    }
136
137
    /**
138
     * Set providers.
139
     *
140
     * @param array $providers
141
     */
142 1
    public function setProviders(array $providers)
143
    {
144 1
        $this->providers = [];
145
146 1
        foreach ($providers as $provider) {
147 1
            $this->addProvider($provider);
148 1
        }
149 1
    }
150
151
    /**
152
     * Return all providers.
153
     *
154
     * @return array
155
     */
156 2
    public function getProviders()
157
    {
158 2
        return $this->providers;
159
    }
160
161
    /**
162
     * Magic get access. 
163
     *
164
     * @param string $id
165
     *
166
     * @return mixed
167
     */
168 1
    public function __get($id)
169
    {
170 1
        return $this->offsetGet($id);
171
    }
172
173
    /**
174
     * Magic set access.
175
     *
176
     * @param string $id
177
     * @param mixed  $value
178
     */
179 1
    public function __set($id, $value)
180
    {
181 1
        return $this->offsetSet($id, $value);
182
    }
183
184
    /**
185
     * Register providers.
186
     */
187 3
    private function registerProviders()
188
    {
189 3
        foreach ($this->providers as $provider) {
190 3
            $this->register(new $provider());
191 3
        }
192 3
    }
193
194
    /**
195
     * Register basic providers.
196
     */
197 3
    private function registerBase()
198
    {
199
        $this['request'] = function () {
200
            return Request::createFromGlobals();
201
        };
202
203
        $this['cache'] = function () {
204
            return new FilesystemCache(sys_get_temp_dir());
205
        };
206
207
        $this['access_token'] = function () {
208
           return new AccessToken(
209
               $this['config']['app_id'],
210
               $this['config']['secret'],
211
               $this['cache']
212
           );
213
        };
214 3
    }
215
216
    /**
217
     * Register exception and error handler.
218
     */
219 3
    private function registerExceptionHandler()
220
    {
221 3
        $logTemplate = '%s: %s in %s on line %s.';
222
223
        $lastExceptionHandler = set_exception_handler(function ($e) use (&$lastExceptionHandler, $logTemplate) {
224
            Log::error(sprintf($logTemplate, $e->getCode(), $e->getMessage(), $e->getFile(), $e->getLine()));
225
226
            $this->exceptionHandler && call_user_func_array($this->exceptionHandler, [$e]);
227
228
            if (is_callable($lastExceptionHandler)) {
229
                return call_user_func($lastExceptionHandler, $e);
230
            }
231 3
        });
232
233
        $errorHandler = function ($severity, $message, $file, $line) use ($logTemplate) {
234 1
            Log::error(sprintf($logTemplate, $severity, $message, $file, $line));
235
236 1
            if (error_reporting() & $severity) {
237 1
                throw new ErrorException($message, 0, $severity, $file, $line);
238
            }
239 3
        };
240
241 3
        set_error_handler($errorHandler);
242
243 3
        register_shutdown_function(function () use ($errorHandler) {
244
            $lastError = error_get_last();
245
246
            if ($lastError['type'] === E_ERROR) {
247
                // fatal error
248
                $errorHandler(E_ERROR, $lastError['message'], $lastError['file'], $lastError['line']);
249
            }
250 3
        });
251 3
    }
252
253
    /**
254
     * Initialize logger.
255
     */
256 3
    private function initializeLogger()
257
    {
258 3
        $logger = new Logger('easywechat');
259
260 3
        if (!$this['config']['debug'] || defined('PHPUNIT_RUNNING')) {
261 3
            $logger->pushHandler(new NullHandler());
262 3
        } elseif ($logFile = $this['config']['log.file']) {
263
            $logger->pushHandler(new StreamHandler($logFile, $this['config']->get('log.level', Logger::WARNING)));
264
        }
265
266 3
        Log::setLogger($logger);
267 3
    }
268
}
269