Passed
Pull Request — master (#579)
by Songda
03:10
created

Pay::has()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 1
c 1
b 0
f 0
dl 0
loc 3
rs 10
cc 1
nc 1
nop 1
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Yansongda\Pay;
6
7
use Closure;
8
use Psr\Container\ContainerInterface;
9
use Psr\Container\NotFoundExceptionInterface;
10
use Throwable;
11
use Yansongda\Pay\Contract\ServiceProviderInterface;
12
use Yansongda\Pay\Exception\ContainerException;
13
use Yansongda\Pay\Exception\ContainerNotFoundException;
14
use Yansongda\Pay\Exception\ServiceNotFoundException;
15
use Yansongda\Pay\Provider\Alipay;
16
use Yansongda\Pay\Provider\Wechat;
17
use Yansongda\Pay\Service\AlipayServiceProvider;
18
use Yansongda\Pay\Service\ConfigServiceProvider;
19
use Yansongda\Pay\Service\ContainerServiceProvider;
20
use Yansongda\Pay\Service\EventServiceProvider;
21
use Yansongda\Pay\Service\HttpServiceProvider;
22
use Yansongda\Pay\Service\LoggerServiceProvider;
23
use Yansongda\Pay\Service\WechatServiceProvider;
24
25
/**
26
 * @method static Alipay alipay(array $config = [])
27
 * @method static Wechat wechat(array $config = [])
28
 */
29
class Pay
30
{
31
    /**
32
     * 正常模式.
33
     */
34
    public const MODE_NORMAL = 0;
35
36
    /**
37
     * 沙箱模式.
38
     */
39
    public const MODE_SANDBOX = 1;
40
41
    /**
42
     * 服务商模式.
43
     */
44
    public const MODE_SERVICE = 2;
45
46
    /**
47
     * @var string[]
48
     */
49
    protected $service = [
50
        AlipayServiceProvider::class,
51
        WechatServiceProvider::class,
52
    ];
53
54
    /**
55
     * @var string[]
56
     */
57
    private $coreService = [
58
        ContainerServiceProvider::class,
59
        ConfigServiceProvider::class,
60
        LoggerServiceProvider::class,
61
        EventServiceProvider::class,
62
        HttpServiceProvider::class,
63
    ];
64
65
    /**
66
     * @var \Closure|\Psr\Container\ContainerInterface|null
67
     */
68
    private static $container = null;
69
70
    /**
71
     * @param \Closure|\Psr\Container\ContainerInterface|null $container
72
     *
73
     * @throws \Yansongda\Pay\Exception\ContainerException
74
     */
75
    private function __construct(array $config, $container = null)
76
    {
77
        $this->registerServices($config, $container);
78
    }
79
80
    /**
81
     * @throws \Yansongda\Pay\Exception\ContainerException
82
     * @throws \Yansongda\Pay\Exception\ServiceNotFoundException
83
     *
84
     * @return mixed
85
     */
86
    public static function __callStatic(string $service, array $config)
87
    {
88
        if (!empty($config)) {
89
            self::config(...$config);
0 ignored issues
show
Bug introduced by
$config is expanded, but the parameter $config of Yansongda\Pay\Pay::config() does not expect variable arguments. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

89
            self::config(/** @scrutinizer ignore-type */ ...$config);
Loading history...
90
        }
91
92
        return self::get($service);
93
    }
94
95
    /**
96
     * @param \Closure|\Psr\Container\ContainerInterface|null $container
97
     *
98
     * @throws \Yansongda\Pay\Exception\ContainerException
99
     */
100
    public static function config(array $config = [], $container = null): bool
101
    {
102
        if (self::hasContainer() && !($config['_force'] ?? false)) {
103
            return false;
104
        }
105
106
        new self($config, $container);
107
108
        return true;
109
    }
110
111
    /**
112
     * @param mixed $value
113
     *
114
     * @throws \Yansongda\Pay\Exception\ContainerException
115
     */
116
    public static function set(string $name, $value): void
117
    {
118
        try {
119
            $container = Pay::getContainer();
120
121
            if (method_exists($container, 'set')) {
122
                $container->set(...func_get_args());
123
124
                return;
125
            }
126
127
            // laravel
128
            if (method_exists($container, 'singleton')) {
129
                $container->singleton($name, $value instanceof Closure ? $value : static function () use ($value) {
130
                    return $value;
131
                });
132
133
                return;
134
            }
135
136
            // thinkphp
137
            if (method_exists($container, 'bind')) {
138
                $container->bind(...func_get_args());
139
140
                return;
141
            }
142
        } catch (ContainerNotFoundException $e) {
143
            throw $e;
144
        } catch (Throwable $e) {
145
            throw new ContainerException($e->getMessage());
146
        }
147
148
        throw new ContainerException('Current container does NOT support `set` method');
149
    }
150
151
    /**
152
     * @throws \Yansongda\Pay\Exception\ContainerException
153
     *
154
     * @return mixed
155
     */
156
    public static function make(string $service, array $parameters = [])
157
    {
158
        try {
159
            $container = Pay::getContainer();
160
161
            if ($container instanceof Contract\ContainerInterface || method_exists($container, 'make')) {
162
                return $container->make(...func_get_args());
0 ignored issues
show
Bug introduced by
func_get_args() is expanded, but the parameter $name of Yansongda\Pay\Contract\ContainerInterface::make() does not expect variable arguments. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

162
                return $container->make(/** @scrutinizer ignore-type */ ...func_get_args());
Loading history...
163
            }
164
        } catch (ContainerNotFoundException $e) {
165
            throw $e;
166
        } catch (Throwable $e) {
167
            throw new ContainerException($e->getMessage());
168
        }
169
170
        $parameters = array_values($parameters);
171
172
        return new $service(...$parameters);
173
    }
174
175
    /**
176
     * @throws \Yansongda\Pay\Exception\ServiceNotFoundException
177
     * @throws \Yansongda\Pay\Exception\ContainerException
178
     *
179
     * @return mixed
180
     */
181
    public static function get(string $service)
182
    {
183
        try {
184
            return Pay::getContainer()->get($service);
185
        } catch (NotFoundExceptionInterface $e) {
186
            throw new ServiceNotFoundException($e->getMessage());
187
        } catch (Throwable $e) {
188
            throw new ContainerException($e->getMessage());
189
        }
190
    }
191
192
    /**
193
     * @throws \Yansongda\Pay\Exception\ContainerNotFoundException
194
     */
195
    public static function has(string $service): bool
196
    {
197
        return Pay::getContainer()->has($service);
198
    }
199
200
    /**
201
     * @param \Closure|\Psr\Container\ContainerInterface|null $container
202
     */
203
    public static function setContainer($container): void
204
    {
205
        self::$container = $container;
206
    }
207
208
    /**
209
     * @throws \Yansongda\Pay\Exception\ContainerNotFoundException
210
     */
211
    public static function getContainer(): ContainerInterface
212
    {
213
        if (self::$container instanceof ContainerInterface) {
214
            return self::$container;
215
        }
216
217
        if (self::$container instanceof Closure) {
218
            return (self::$container)();
219
        }
220
221
        throw new ContainerNotFoundException('`getContainer()` failed! Maybe you should `setContainer()` first', Exception\Exception::CONTAINER_NOT_FOUND);
222
    }
223
224
    public static function hasContainer(): bool
225
    {
226
        return self::$container instanceof ContainerInterface || self::$container instanceof Closure;
227
    }
228
229
    public static function clear(): void
230
    {
231
        self::$container = null;
232
    }
233
234
    /**
235
     * @param mixed $data
236
     *
237
     * @throws \Yansongda\Pay\Exception\ContainerException
238
     */
239
    public static function registerService(string $service, $data): void
240
    {
241
        $var = new $service();
242
243
        if ($var instanceof ServiceProviderInterface) {
244
            $var->register($data);
245
        }
246
    }
247
248
    /**
249
     * @param \Closure|\Psr\Container\ContainerInterface|null $container
250
     *
251
     * @throws \Yansongda\Pay\Exception\ContainerException
252
     */
253
    private function registerServices(array $config, $container = null): void
254
    {
255
        foreach (array_merge($this->coreService, $this->service) as $service) {
256
            self::registerService($service, ContainerServiceProvider::class == $service ? $container : $config);
257
        }
258
    }
259
}
260