Completed
Pull Request — master (#700)
by mingyoung
03:03
created

Application::__call()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 8
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 6

Importance

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