Passed
Push — master ( 71ed3e...aec68f )
by Carlos
02:37
created

Application::__construct()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 22
Code Lines 12

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 11
CRAP Score 2.0145

Importance

Changes 0
Metric Value
cc 2
eloc 12
nc 2
nop 1
dl 0
loc 22
ccs 11
cts 13
cp 0.8462
crap 2.0145
rs 9.2
c 0
b 0
f 0
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
 * @see      https://github.com/overtrue
24
 * @see      http://overtrue.me
25
 */
26
27
namespace EasyWeChat\Foundation;
28
29
use Doctrine\Common\Cache\Cache as CacheInterface;
30
use Doctrine\Common\Cache\FilesystemCache;
31
use EasyWeChat\Core\AbstractAPI;
32
use EasyWeChat\Core\AccessToken;
33
use EasyWeChat\Core\Http;
34
use EasyWeChat\Support\Log;
35
use Monolog\Handler\HandlerInterface;
36
use Monolog\Handler\NullHandler;
37
use Monolog\Handler\StreamHandler;
38
use Monolog\Logger;
39
use Pimple\Container;
40
use Symfony\Component\HttpFoundation\Request;
41
42
/**
43
 * Class Application.
44
 *
45
 * @property \EasyWeChat\Core\AccessToken                    $access_token
46
 * @property \EasyWeChat\Server\Guard                        $server
47
 * @property \EasyWeChat\User\User                           $user
48
 * @property \EasyWeChat\User\Tag                            $user_tag
49
 * @property \EasyWeChat\User\Group                          $user_group
50
 * @property \EasyWeChat\Js\Js                               $js
51
 * @property \Overtrue\Socialite\Providers\WeChatProvider    $oauth
52
 * @property \EasyWeChat\Menu\Menu                           $menu
53
 * @property \EasyWeChat\Notice\Notice                       $notice
54
 * @property \EasyWeChat\Material\Material                   $material
55
 * @property \EasyWeChat\Material\Temporary                  $material_temporary
56
 * @property \EasyWeChat\Staff\Staff                         $staff
57
 * @property \EasyWeChat\Url\Url                             $url
58
 * @property \EasyWeChat\QRCode\QRCode                       $qrcode
59
 * @property \EasyWeChat\Semantic\Semantic                   $semantic
60
 * @property \EasyWeChat\Stats\Stats                         $stats
61
 * @property \EasyWeChat\Payment\Merchant                    $merchant
62
 * @property \EasyWeChat\Payment\Payment                     $payment
63
 * @property \EasyWeChat\Payment\LuckyMoney\LuckyMoney       $lucky_money
64
 * @property \EasyWeChat\Payment\MerchantPay\MerchantPay     $merchant_pay
65
 * @property \EasyWeChat\Payment\CashCoupon\CashCoupon       $cash_coupon
66
 * @property \EasyWeChat\Reply\Reply                         $reply
67
 * @property \EasyWeChat\Broadcast\Broadcast                 $broadcast
68
 * @property \EasyWeChat\Card\Card                           $card
69
 * @property \EasyWeChat\Device\Device                       $device
70
 * @property \EasyWeChat\Comment\Comment                     $comment
71
 * @property \EasyWeChat\ShakeAround\ShakeAround             $shakearound
72
 * @property \EasyWeChat\OpenPlatform\OpenPlatform           $open_platform
73
 * @property \EasyWeChat\MiniProgram\MiniProgram             $mini_program
74
 *
75
 * @method \EasyWeChat\Support\Collection clearQuota()
76
 * @method \EasyWeChat\Support\Collection getCallbackIp()
77
 */
78
class Application extends Container
79
{
80
    /**
81
     * Service Providers.
82
     *
83
     * @var array
84
     */
85
    protected $providers = [
86
        ServiceProviders\FundamentalServiceProvider::class,
87
        ServiceProviders\ServerServiceProvider::class,
88
        ServiceProviders\UserServiceProvider::class,
89
        ServiceProviders\JsServiceProvider::class,
90
        ServiceProviders\OAuthServiceProvider::class,
91
        ServiceProviders\MenuServiceProvider::class,
92
        ServiceProviders\NoticeServiceProvider::class,
93
        ServiceProviders\MaterialServiceProvider::class,
94
        ServiceProviders\StaffServiceProvider::class,
95
        ServiceProviders\UrlServiceProvider::class,
96
        ServiceProviders\QRCodeServiceProvider::class,
97
        ServiceProviders\SemanticServiceProvider::class,
98
        ServiceProviders\StatsServiceProvider::class,
99
        ServiceProviders\PaymentServiceProvider::class,
100
        ServiceProviders\POIServiceProvider::class,
101
        ServiceProviders\ReplyServiceProvider::class,
102
        ServiceProviders\BroadcastServiceProvider::class,
103
        ServiceProviders\CardServiceProvider::class,
104
        ServiceProviders\DeviceServiceProvider::class,
105
        ServiceProviders\ShakeAroundServiceProvider::class,
106
        ServiceProviders\OpenPlatformServiceProvider::class,
107
        ServiceProviders\MiniProgramServiceProvider::class,
108
        ServiceProviders\CommentServiceProvider::class,
109
    ];
110
111
    /**
112
     * Application constructor.
113
     *
114
     * @param array $config
115
     */
116 8
    public function __construct($config)
117
    {
118 8
        parent::__construct();
119
120
        $this['config'] = function () use ($config) {
121 8
            return new Config($config);
122
        };
123
124 8
        if ($this['config']['debug']) {
125
            error_reporting(E_ALL);
126
        }
127
128 8
        $this->registerProviders();
129 8
        $this->registerBase();
130 8
        $this->initializeLogger();
131
132 8
        Http::setDefaultOptions($this['config']->get('guzzle', ['timeout' => 5.0]));
133
134 8
        AbstractAPI::maxRetries($this['config']->get('max_retries', 2));
135
136 8
        $this->logConfiguration($config);
137 8
    }
138
139
    /**
140
     * Log configuration.
141
     *
142
     * @param array $config
143
     */
144 8
    public function logConfiguration($config)
145
    {
146 8
        $config = new Config($config);
147
148 8
        $keys = ['app_id', 'secret', 'open_platform.app_id', 'open_platform.secret', 'mini_program.app_id', 'mini_program.secret'];
149 8
        foreach ($keys as $key) {
150 8
            !$config->has($key) || $config[$key] = '***'.substr($config[$key], -5);
151 8
        }
152
153 8
        Log::debug('Current config:', $config->toArray());
154 8
    }
155
156
    /**
157
     * Add a provider.
158
     *
159
     * @param string $provider
160
     *
161
     * @return Application
162
     */
163 1
    public function addProvider($provider)
164
    {
165 1
        array_push($this->providers, $provider);
166
167 1
        return $this;
168
    }
169
170
    /**
171
     * Set providers.
172
     *
173
     * @param array $providers
174
     */
175 1
    public function setProviders(array $providers)
176
    {
177 1
        $this->providers = [];
178
179 1
        foreach ($providers as $provider) {
180 1
            $this->addProvider($provider);
181 1
        }
182 1
    }
183
184
    /**
185
     * Return all providers.
186
     *
187
     * @return array
188
     */
189 2
    public function getProviders()
190
    {
191 2
        return $this->providers;
192
    }
193
194
    /**
195
     * Magic get access.
196
     *
197
     * @param string $id
198
     *
199
     * @return mixed
200
     */
201 4
    public function __get($id)
202
    {
203 4
        return $this->offsetGet($id);
204
    }
205
206
    /**
207
     * Magic set access.
208
     *
209
     * @param string $id
210
     * @param mixed  $value
211
     */
212 1
    public function __set($id, $value)
213
    {
214 1
        $this->offsetSet($id, $value);
215 1
    }
216
217
    /**
218
     * Register providers.
219
     */
220 8
    private function registerProviders()
221
    {
222 8
        foreach ($this->providers as $provider) {
223 8
            $this->register(new $provider());
224 8
        }
225 8
    }
226
227
    /**
228
     * Register basic providers.
229
     */
230 8
    private function registerBase()
231
    {
232
        $this['request'] = function () {
233 2
            return Request::createFromGlobals();
234
        };
235
236 8
        if (!empty($this['config']['cache']) && $this['config']['cache'] instanceof CacheInterface) {
237
            $this['cache'] = $this['config']['cache'];
238
        } else {
239
            $this['cache'] = function () {
240 4
                return new FilesystemCache(sys_get_temp_dir());
241
            };
242
        }
243
244 1
        $this['access_token'] = function () {
245 1
            return new AccessToken(
246 1
                $this['config']['app_id'],
247 1
                $this['config']['secret'],
248 1
                $this['cache']
249 1
            );
250
        };
251 8
    }
252
253
    /**
254
     * Initialize logger.
255
     */
256 8
    private function initializeLogger()
257
    {
258 8
        if (Log::hasLogger()) {
259 8
            return;
260
        }
261
262
        $logger = new Logger('easywechat');
263
264
        if (!$this['config']['debug'] || defined('PHPUNIT_RUNNING')) {
265
            $logger->pushHandler(new NullHandler());
266
        } elseif ($this['config']['log.handler'] instanceof HandlerInterface) {
267
            $logger->pushHandler($this['config']['log.handler']);
268
        } elseif ($logFile = $this['config']['log.file']) {
269
            $logger->pushHandler(new StreamHandler(
270
                $logFile,
271
                $this['config']->get('log.level', Logger::WARNING),
272
                true,
273
                $this['config']->get('log.permission', null))
274
            );
275
        }
276
277
        Log::setLogger($logger);
278
    }
279
280
    /**
281
     * Magic call.
282
     *
283
     * @param string $method
284
     * @param array  $args
285
     *
286
     * @return mixed
287
     *
288
     * @throws \Exception
289
     */
290
    public function __call($method, $args)
291
    {
292
        if (is_callable([$this['fundamental.api'], $method])) {
293
            return call_user_func_array([$this['fundamental.api'], $method], $args);
294
        }
295
296
        throw new \Exception("Call to undefined method {$method}()");
297
    }
298
}
299