Forráskód Böngészése

Wesmiler 人人车 初始化项目 0816

APPLE 3 éve
szülő
commit
93d6cde77d
30 módosított fájl, 1717 hozzáadás és 0 törlés
  1. 29 0
      vendor/easywechat-composer/easywechat-composer/easywechat-composer/.php_cs
  2. 12 0
      vendor/easywechat-composer/easywechat-composer/easywechat-composer/.travis.yml
  3. 21 0
      vendor/easywechat-composer/easywechat-composer/easywechat-composer/LICENSE
  4. 55 0
      vendor/easywechat-composer/easywechat-composer/easywechat-composer/README.md
  5. 35 0
      vendor/easywechat-composer/easywechat-composer/easywechat-composer/composer.json
  6. 2 0
      vendor/easywechat-composer/easywechat-composer/easywechat-composer/extensions.php
  7. 20 0
      vendor/easywechat-composer/easywechat-composer/easywechat-composer/phpunit.xml
  8. 63 0
      vendor/easywechat-composer/easywechat-composer/easywechat-composer/src/Commands/ExtensionsCommand.php
  9. 31 0
      vendor/easywechat-composer/easywechat-composer/easywechat-composer/src/Commands/Provider.php
  10. 35 0
      vendor/easywechat-composer/easywechat-composer/easywechat-composer/src/Contracts/Encrypter.php
  11. 80 0
      vendor/easywechat-composer/easywechat-composer/easywechat-composer/src/Delegation/DelegationOptions.php
  12. 83 0
      vendor/easywechat-composer/easywechat-composer/easywechat-composer/src/Delegation/DelegationTo.php
  13. 83 0
      vendor/easywechat-composer/easywechat-composer/easywechat-composer/src/Delegation/Hydrate.php
  14. 79 0
      vendor/easywechat-composer/easywechat-composer/easywechat-composer/src/EasyWeChat.php
  15. 89 0
      vendor/easywechat-composer/easywechat-composer/easywechat-composer/src/Encryption/DefaultEncrypter.php
  16. 21 0
      vendor/easywechat-composer/easywechat-composer/easywechat-composer/src/Exceptions/DecryptException.php
  17. 42 0
      vendor/easywechat-composer/easywechat-composer/easywechat-composer/src/Exceptions/DelegationException.php
  18. 21 0
      vendor/easywechat-composer/easywechat-composer/easywechat-composer/src/Exceptions/EncryptException.php
  19. 143 0
      vendor/easywechat-composer/easywechat-composer/easywechat-composer/src/Extension.php
  20. 25 0
      vendor/easywechat-composer/easywechat-composer/easywechat-composer/src/Http/DelegationResponse.php
  21. 104 0
      vendor/easywechat-composer/easywechat-composer/easywechat-composer/src/Http/Response.php
  22. 49 0
      vendor/easywechat-composer/easywechat-composer/easywechat-composer/src/Laravel/Http/Controllers/DelegatesController.php
  23. 116 0
      vendor/easywechat-composer/easywechat-composer/easywechat-composer/src/Laravel/ServiceProvider.php
  24. 29 0
      vendor/easywechat-composer/easywechat-composer/easywechat-composer/src/Laravel/config.php
  25. 16 0
      vendor/easywechat-composer/easywechat-composer/easywechat-composer/src/Laravel/routes.php
  26. 120 0
      vendor/easywechat-composer/easywechat-composer/easywechat-composer/src/ManifestManager.php
  27. 107 0
      vendor/easywechat-composer/easywechat-composer/easywechat-composer/src/Plugin.php
  28. 110 0
      vendor/easywechat-composer/easywechat-composer/easywechat-composer/src/Traits/MakesHttpRequests.php
  29. 60 0
      vendor/easywechat-composer/easywechat-composer/easywechat-composer/src/Traits/WithAggregator.php
  30. 37 0
      vendor/easywechat-composer/easywechat-composer/easywechat-composer/tests/ManifestManagerTest.php

+ 29 - 0
vendor/easywechat-composer/easywechat-composer/easywechat-composer/.php_cs

@@ -0,0 +1,29 @@
+<?php
+
+$header = <<<EOF
+This file is part of the EasyWeChatComposer.
+
+(c) 张铭阳 <mingyoungcheung@gmail.com>
+
+This source file is subject to the MIT license that is bundled
+with this source code in the file LICENSE.
+EOF;
+
+return PhpCsFixer\Config::create()
+    ->setRiskyAllowed(true)
+    ->setRules([
+        '@Symfony' => true,
+        'header_comment' => ['header' => $header],
+        'declare_strict_types' => true,
+        'ordered_imports' => true,
+        'strict_comparison' => true,
+        'no_empty_comment' => false,
+        'yoda_style' => false,
+    ])
+    ->setFinder(
+        PhpCsFixer\Finder::create()
+            ->exclude('vendor')
+            ->notPath('src/Laravel/config.php', 'src/Laravel/routes.php')
+            ->in(__DIR__)
+    )
+;

+ 12 - 0
vendor/easywechat-composer/easywechat-composer/easywechat-composer/.travis.yml

@@ -0,0 +1,12 @@
+language: php
+
+php:
+  - 7.0
+  - 7.1
+  - 7.2
+  - 7.3
+
+install:
+  - travis_retry composer install --no-interaction --no-suggest
+
+script: ./vendor/bin/phpunit

+ 21 - 0
vendor/easywechat-composer/easywechat-composer/easywechat-composer/LICENSE

@@ -0,0 +1,21 @@
+MIT License
+
+Copyright (c) 张铭阳
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.

+ 55 - 0
vendor/easywechat-composer/easywechat-composer/easywechat-composer/README.md

@@ -0,0 +1,55 @@
+<p align="center">
+    <h1 align="center">EasyWeChat Composer Plugin</h1>
+</p>
+
+<p align="center">
+    <a href="https://travis-ci.org/mingyoung/easywechat-composer"><img src="https://travis-ci.org/mingyoung/easywechat-composer.svg" alt="Build Status"></a>
+    <a href="https://scrutinizer-ci.com/g/mingyoung/easywechat-composer/?branch=master"><img src="https://scrutinizer-ci.com/g/mingyoung/easywechat-composer/badges/quality-score.png?b=master" alt="Scrutinizer Code Quality"></a>
+    <a href="https://packagist.org/packages/easywechat-composer/easywechat-composer"><img src="https://poser.pugx.org/easywechat-composer/easywechat-composer/v/stable.svg" alt="Latest Stable Version"></a>
+    <a href="https://packagist.org/packages/easywechat-composer/easywechat-composer"><img src="https://poser.pugx.org/easywechat-composer/easywechat-composer/d/total.svg" alt="Total Downloads"></a>
+    <a href="https://packagist.org/packages/easywechat-composer/easywechat-composer"><img src="https://poser.pugx.org/easywechat-composer/easywechat-composer/license.svg" alt="License"></a>
+</p>
+
+Usage
+---
+
+Set the `type` to be `easywechat-extension` in your package composer.json file:
+
+```json
+{
+    "name": "your/package",
+    "type": "easywechat-extension"
+}
+```
+
+Specify server observer classes in the extra section:
+
+```json
+{
+    "name": "your/package",
+    "type": "easywechat-extension",
+    "extra": {
+        "observers": [
+            "Acme\\Observers\\Handler"
+        ]
+    }
+}
+```
+
+Examples
+---
+* [easywechat-composer/open-platform-testcase](https://github.com/mingyoung/open-platform-testcase)
+
+Server Delegation
+---
+
+> 目前仅支持 Laravel
+
+1. 在 `config/app.php` 中添加 `EasyWeChatComposer\Laravel\ServiceProvider::class`
+
+2. 在**本地项目**的 `.env` 文件中添加如下配置:
+
+```
+EASYWECHAT_DELEGATION=true # false 则不启用
+EASYWECHAT_DELEGATION_HOST=https://example.com # 线上域名
+```

+ 35 - 0
vendor/easywechat-composer/easywechat-composer/easywechat-composer/composer.json

@@ -0,0 +1,35 @@
+{
+    "name": "easywechat-composer/easywechat-composer",
+    "description": "The composer plugin for EasyWeChat",
+    "type": "composer-plugin",
+    "license": "MIT",
+    "authors": [
+        {
+            "name": "张铭阳",
+            "email": "mingyoungcheung@gmail.com"
+        }
+    ],
+    "require": {
+        "php": ">=7.0",
+        "composer-plugin-api": "^1.0 || ^2.0"
+    },
+    "require-dev": {
+        "composer/composer": "^1.0 || ^2.0",
+        "phpunit/phpunit": "^6.5 || ^7.0"
+    },
+    "autoload": {
+        "psr-4": {
+            "EasyWeChatComposer\\": "src/"
+        }
+    },
+    "autoload-dev": {
+        "psr-4": {
+            "EasyWeChatComposer\\Tests\\": "tests/"
+        }
+    },
+    "extra": {
+        "class": "EasyWeChatComposer\\Plugin"
+    },
+    "minimum-stability": "dev",
+    "prefer-stable": true
+}

+ 2 - 0
vendor/easywechat-composer/easywechat-composer/easywechat-composer/extensions.php

@@ -0,0 +1,2 @@
+<?php return array (
+);

+ 20 - 0
vendor/easywechat-composer/easywechat-composer/easywechat-composer/phpunit.xml

@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:noNamespaceSchemaLocation="https://schema.phpunit.de/7.0/phpunit.xsd"
+         bootstrap="vendor/autoload.php"
+         colors="true"
+         forceCoversAnnotation="true"
+         beStrictAboutCoversAnnotation="true"
+         beStrictAboutOutputDuringTests="true"
+         beStrictAboutTodoAnnotatedTests="true"
+         verbose="true">
+    <testsuite name="EasyWeChatComposer Test">
+        <directory suffix="Test.php">tests</directory>
+    </testsuite>
+
+    <filter>
+        <whitelist processUncoveredFilesFromWhitelist="true">
+            <directory suffix=".php">src</directory>
+        </whitelist>
+    </filter>
+</phpunit>

+ 63 - 0
vendor/easywechat-composer/easywechat-composer/easywechat-composer/src/Commands/ExtensionsCommand.php

@@ -0,0 +1,63 @@
+<?php
+
+declare(strict_types=1);
+
+/*
+ * This file is part of the EasyWeChatComposer.
+ *
+ * (c) 张铭阳 <mingyoungcheung@gmail.com>
+ *
+ * This source file is subject to the MIT license that is bundled
+ * with this source code in the file LICENSE.
+ */
+
+namespace EasyWeChatComposer\Commands;
+
+use Composer\Command\BaseCommand;
+use Symfony\Component\Console\Helper\Table;
+use Symfony\Component\Console\Input\InputInterface;
+use Symfony\Component\Console\Output\OutputInterface;
+
+class ExtensionsCommand extends BaseCommand
+{
+    /**
+     * Configures the current command.
+     */
+    protected function configure()
+    {
+        $this->setName('easywechat:extensions')
+            ->setDescription('Lists all installed extensions.');
+    }
+
+    /**
+     * Executes the current command.
+     *
+     * @param InputInterface  $input
+     * @param OutputInterface $output
+     */
+    protected function execute(InputInterface $input, OutputInterface $output)
+    {
+        $extensions = require __DIR__.'/../../extensions.php';
+
+        if (empty($extensions) || !is_array($extensions)) {
+            return $output->writeln('<info>No extension installed.</info>');
+        }
+
+        $table = new Table($output);
+        $table->setHeaders(['Name', 'Observers'])
+            ->setRows(
+                array_map([$this, 'getRows'], array_keys($extensions), $extensions)
+            )->render();
+    }
+
+    /**
+     * @param string $name
+     * @param array  $extension
+     *
+     * @return array
+     */
+    protected function getRows($name, $extension)
+    {
+        return [$name, implode("\n", $extension['observers'] ?? [])];
+    }
+}

+ 31 - 0
vendor/easywechat-composer/easywechat-composer/easywechat-composer/src/Commands/Provider.php

@@ -0,0 +1,31 @@
+<?php
+
+declare(strict_types=1);
+
+/*
+ * This file is part of the EasyWeChatComposer.
+ *
+ * (c) 张铭阳 <mingyoungcheung@gmail.com>
+ *
+ * This source file is subject to the MIT license that is bundled
+ * with this source code in the file LICENSE.
+ */
+
+namespace EasyWeChatComposer\Commands;
+
+use Composer\Plugin\Capability\CommandProvider;
+
+class Provider implements CommandProvider
+{
+    /**
+     * Retrieves an array of commands.
+     *
+     * @return \Composer\Command\BaseCommand[]
+     */
+    public function getCommands()
+    {
+        return [
+            new ExtensionsCommand(),
+        ];
+    }
+}

+ 35 - 0
vendor/easywechat-composer/easywechat-composer/easywechat-composer/src/Contracts/Encrypter.php

@@ -0,0 +1,35 @@
+<?php
+
+declare(strict_types=1);
+
+/*
+ * This file is part of the EasyWeChatComposer.
+ *
+ * (c) 张铭阳 <mingyoungcheung@gmail.com>
+ *
+ * This source file is subject to the MIT license that is bundled
+ * with this source code in the file LICENSE.
+ */
+
+namespace EasyWeChatComposer\Contracts;
+
+interface Encrypter
+{
+    /**
+     * Encrypt the given value.
+     *
+     * @param string $value
+     *
+     * @return string
+     */
+    public function encrypt($value);
+
+    /**
+     * Decrypt the given value.
+     *
+     * @param string $payload
+     *
+     * @return string
+     */
+    public function decrypt($payload);
+}

+ 80 - 0
vendor/easywechat-composer/easywechat-composer/easywechat-composer/src/Delegation/DelegationOptions.php

@@ -0,0 +1,80 @@
+<?php
+
+declare(strict_types=1);
+
+/*
+ * This file is part of the EasyWeChatComposer.
+ *
+ * (c) 张铭阳 <mingyoungcheung@gmail.com>
+ *
+ * This source file is subject to the MIT license that is bundled
+ * with this source code in the file LICENSE.
+ */
+
+namespace EasyWeChatComposer\Delegation;
+
+use EasyWeChatComposer\EasyWeChat;
+
+class DelegationOptions
+{
+    /**
+     * @var array
+     */
+    protected $config = [
+        'enabled' => false,
+    ];
+
+    /**
+     * @return $this
+     */
+    public function enable()
+    {
+        $this->config['enabled'] = true;
+
+        return $this;
+    }
+
+    /**
+     * @return $this
+     */
+    public function disable()
+    {
+        $this->config['enabled'] = false;
+
+        return $this;
+    }
+
+    /**
+     * @param bool $ability
+     *
+     * @return $this
+     */
+    public function ability($ability)
+    {
+        $this->config['enabled'] = (bool) $ability;
+
+        return $this;
+    }
+
+    /**
+     * @param string $host
+     *
+     * @return $this
+     */
+    public function toHost($host)
+    {
+        $this->config['host'] = $host;
+
+        return $this;
+    }
+
+    /**
+     * Destructor.
+     */
+    public function __destruct()
+    {
+        EasyWeChat::mergeConfig([
+            'delegation' => $this->config,
+        ]);
+    }
+}

+ 83 - 0
vendor/easywechat-composer/easywechat-composer/easywechat-composer/src/Delegation/DelegationTo.php

@@ -0,0 +1,83 @@
+<?php
+
+declare(strict_types=1);
+
+/*
+ * This file is part of the EasyWeChatComposer.
+ *
+ * (c) 张铭阳 <mingyoungcheung@gmail.com>
+ *
+ * This source file is subject to the MIT license that is bundled
+ * with this source code in the file LICENSE.
+ */
+
+namespace EasyWeChatComposer\Delegation;
+
+use EasyWeChatComposer\Traits\MakesHttpRequests;
+
+class DelegationTo
+{
+    use MakesHttpRequests;
+
+    /**
+     * @var \EasyWeChat\Kernel\ServiceContainer
+     */
+    protected $app;
+
+    /**
+     * @var array
+     */
+    protected $identifiers = [];
+
+    /**
+     * @param \EasyWeChat\Kernel\ServiceContainer $app
+     * @param string                              $identifier
+     */
+    public function __construct($app, $identifier)
+    {
+        $this->app = $app;
+
+        $this->push($identifier);
+    }
+
+    /**
+     * @param string $identifier
+     */
+    public function push($identifier)
+    {
+        $this->identifiers[] = $identifier;
+    }
+
+    /**
+     * @param string $identifier
+     *
+     * @return $this
+     */
+    public function __get($identifier)
+    {
+        $this->push($identifier);
+
+        return $this;
+    }
+
+    /**
+     * @param string $method
+     * @param array  $arguments
+     *
+     * @return mixed
+     */
+    public function __call($method, $arguments)
+    {
+        $config = array_intersect_key($this->app->getConfig(), array_flip(['app_id', 'secret', 'token', 'aes_key', 'response_type', 'component_app_id', 'refresh_token']));
+
+        $data = [
+            'config' => $config,
+            'application' => get_class($this->app),
+            'identifiers' => $this->identifiers,
+            'method' => $method,
+            'arguments' => $arguments,
+        ];
+
+        return $this->request('easywechat-composer/delegate', $data);
+    }
+}

+ 83 - 0
vendor/easywechat-composer/easywechat-composer/easywechat-composer/src/Delegation/Hydrate.php

@@ -0,0 +1,83 @@
+<?php
+
+declare(strict_types=1);
+
+/*
+ * This file is part of the EasyWeChatComposer.
+ *
+ * (c) 张铭阳 <mingyoungcheung@gmail.com>
+ *
+ * This source file is subject to the MIT license that is bundled
+ * with this source code in the file LICENSE.
+ */
+
+namespace EasyWeChatComposer\Delegation;
+
+use EasyWeChat;
+use EasyWeChatComposer\Http\DelegationResponse;
+
+class Hydrate
+{
+    /**
+     * @var array
+     */
+    protected $attributes;
+
+    /**
+     * @param array $attributes
+     */
+    public function __construct(array $attributes)
+    {
+        $this->attributes = $attributes;
+    }
+
+    /**
+     * @return array
+     */
+    public function handle()
+    {
+        $app = $this->createsApplication()->shouldntDelegate();
+
+        foreach ($this->attributes['identifiers'] as $identifier) {
+            $app = $app->$identifier;
+        }
+
+        return call_user_func_array([$app, $this->attributes['method']], $this->attributes['arguments']);
+    }
+
+    /**
+     * @return \EasyWeChat\Kernel\ServiceContainer
+     */
+    protected function createsApplication()
+    {
+        $application = $this->attributes['application'];
+
+        if ($application === EasyWeChat\OpenPlatform\Authorizer\OfficialAccount\Application::class) {
+            return $this->createsOpenPlatformApplication('officialAccount');
+        }
+
+        if ($application === EasyWeChat\OpenPlatform\Authorizer\MiniProgram\Application::class) {
+            return $this->createsOpenPlatformApplication('miniProgram');
+        }
+
+        return new $application($this->buildConfig($this->attributes['config']));
+    }
+
+    protected function createsOpenPlatformApplication($type)
+    {
+        $config = $this->attributes['config'];
+
+        $authorizerAppId = $config['app_id'];
+
+        $config['app_id'] = $config['component_app_id'];
+
+        return EasyWeChat\Factory::openPlatform($this->buildConfig($config))->$type($authorizerAppId, $config['refresh_token']);
+    }
+
+    protected function buildConfig(array $config)
+    {
+        $config['response_type'] = DelegationResponse::class;
+
+        return $config;
+    }
+}

+ 79 - 0
vendor/easywechat-composer/easywechat-composer/easywechat-composer/src/EasyWeChat.php

@@ -0,0 +1,79 @@
+<?php
+
+declare(strict_types=1);
+
+/*
+ * This file is part of the EasyWeChatComposer.
+ *
+ * (c) 张铭阳 <mingyoungcheung@gmail.com>
+ *
+ * This source file is subject to the MIT license that is bundled
+ * with this source code in the file LICENSE.
+ */
+
+namespace EasyWeChatComposer;
+
+use EasyWeChatComposer\Delegation\DelegationOptions;
+
+class EasyWeChat
+{
+    /**
+     * @var array
+     */
+    protected static $config = [];
+
+    /**
+     * Encryption key.
+     *
+     * @var string
+     */
+    protected static $encryptionKey;
+
+    /**
+     * @param array $config
+     */
+    public static function mergeConfig(array $config)
+    {
+        static::$config = array_merge(static::$config, $config);
+    }
+
+    /**
+     * @return array
+     */
+    public static function config()
+    {
+        return static::$config;
+    }
+
+    /**
+     * Set encryption key.
+     *
+     * @param string $key
+     *
+     * @return static
+     */
+    public static function setEncryptionKey(string $key)
+    {
+        static::$encryptionKey = $key;
+
+        return new static();
+    }
+
+    /**
+     * Get encryption key.
+     *
+     * @return string
+     */
+    public static function getEncryptionKey(): string
+    {
+        return static::$encryptionKey;
+    }
+
+    /**
+     * @return \EasyWeChatComposer\Delegation\DelegationOptions
+     */
+    public static function withDelegation()
+    {
+        return new DelegationOptions();
+    }
+}

+ 89 - 0
vendor/easywechat-composer/easywechat-composer/easywechat-composer/src/Encryption/DefaultEncrypter.php

@@ -0,0 +1,89 @@
+<?php
+
+declare(strict_types=1);
+
+/*
+ * This file is part of the EasyWeChatComposer.
+ *
+ * (c) 张铭阳 <mingyoungcheung@gmail.com>
+ *
+ * This source file is subject to the MIT license that is bundled
+ * with this source code in the file LICENSE.
+ */
+
+namespace EasyWeChatComposer\Encryption;
+
+use EasyWeChatComposer\Contracts\Encrypter;
+use EasyWeChatComposer\Exceptions\DecryptException;
+use EasyWeChatComposer\Exceptions\EncryptException;
+
+class DefaultEncrypter implements Encrypter
+{
+    /**
+     * @var string
+     */
+    protected $key;
+
+    /**
+     * @var string
+     */
+    protected $cipher;
+
+    /**
+     * @param string $key
+     * @param string $cipher
+     */
+    public function __construct($key, $cipher = 'AES-256-CBC')
+    {
+        $this->key = $key;
+        $this->cipher = $cipher;
+    }
+
+    /**
+     * Encrypt the given value.
+     *
+     * @param string $value
+     *
+     * @return string
+     *
+     * @throws \EasyWeChatComposer\Exceptions\EncryptException
+     */
+    public function encrypt($value)
+    {
+        $iv = random_bytes(openssl_cipher_iv_length($this->cipher));
+
+        $value = openssl_encrypt($value, $this->cipher, $this->key, 0, $iv);
+
+        if ($value === false) {
+            throw new EncryptException('Could not encrypt the data.');
+        }
+
+        $iv = base64_encode($iv);
+
+        return base64_encode(json_encode(compact('iv', 'value')));
+    }
+
+    /**
+     * Decrypt the given value.
+     *
+     * @param string $payload
+     *
+     * @return string
+     *
+     * @throws \EasyWeChatComposer\Exceptions\DecryptException
+     */
+    public function decrypt($payload)
+    {
+        $payload = json_decode(base64_decode($payload), true);
+
+        $iv = base64_decode($payload['iv']);
+
+        $decrypted = openssl_decrypt($payload['value'], $this->cipher, $this->key, 0, $iv);
+
+        if ($decrypted === false) {
+            throw new DecryptException('Could not decrypt the data.');
+        }
+
+        return $decrypted;
+    }
+}

+ 21 - 0
vendor/easywechat-composer/easywechat-composer/easywechat-composer/src/Exceptions/DecryptException.php

@@ -0,0 +1,21 @@
+<?php
+
+declare(strict_types=1);
+
+/*
+ * This file is part of the EasyWeChatComposer.
+ *
+ * (c) 张铭阳 <mingyoungcheung@gmail.com>
+ *
+ * This source file is subject to the MIT license that is bundled
+ * with this source code in the file LICENSE.
+ */
+
+namespace EasyWeChatComposer\Exceptions;
+
+use Exception;
+
+class DecryptException extends Exception
+{
+    //
+}

+ 42 - 0
vendor/easywechat-composer/easywechat-composer/easywechat-composer/src/Exceptions/DelegationException.php

@@ -0,0 +1,42 @@
+<?php
+
+declare(strict_types=1);
+
+/*
+ * This file is part of the EasyWeChatComposer.
+ *
+ * (c) 张铭阳 <mingyoungcheung@gmail.com>
+ *
+ * This source file is subject to the MIT license that is bundled
+ * with this source code in the file LICENSE.
+ */
+
+namespace EasyWeChatComposer\Exceptions;
+
+use Exception;
+
+class DelegationException extends Exception
+{
+    /**
+     * @var string
+     */
+    protected $exception;
+
+    /**
+     * @param string $exception
+     */
+    public function setException($exception)
+    {
+        $this->exception = $exception;
+
+        return $this;
+    }
+
+    /**
+     * @return string
+     */
+    public function getException()
+    {
+        return $this->exception;
+    }
+}

+ 21 - 0
vendor/easywechat-composer/easywechat-composer/easywechat-composer/src/Exceptions/EncryptException.php

@@ -0,0 +1,21 @@
+<?php
+
+declare(strict_types=1);
+
+/*
+ * This file is part of the EasyWeChatComposer.
+ *
+ * (c) 张铭阳 <mingyoungcheung@gmail.com>
+ *
+ * This source file is subject to the MIT license that is bundled
+ * with this source code in the file LICENSE.
+ */
+
+namespace EasyWeChatComposer\Exceptions;
+
+use Exception;
+
+class EncryptException extends Exception
+{
+    //
+}

+ 143 - 0
vendor/easywechat-composer/easywechat-composer/easywechat-composer/src/Extension.php

@@ -0,0 +1,143 @@
+<?php
+
+declare(strict_types=1);
+
+/*
+ * This file is part of the EasyWeChatComposer.
+ *
+ * (c) 张铭阳 <mingyoungcheung@gmail.com>
+ *
+ * This source file is subject to the MIT license that is bundled
+ * with this source code in the file LICENSE.
+ */
+
+namespace EasyWeChatComposer;
+
+use EasyWeChat\Kernel\Contracts\EventHandlerInterface;
+use Pimple\Container;
+use ReflectionClass;
+
+class Extension
+{
+    /**
+     * @var \Pimple\Container
+     */
+    protected $app;
+
+    /**
+     * @var string
+     */
+    protected $manifestPath;
+
+    /**
+     * @var array|null
+     */
+    protected $manifest;
+
+    /**
+     * @param \Pimple\Container $app
+     */
+    public function __construct(Container $app)
+    {
+        $this->app = $app;
+        $this->manifestPath = __DIR__.'/../extensions.php';
+    }
+
+    /**
+     * Get observers.
+     *
+     * @return array
+     */
+    public function observers(): array
+    {
+        if ($this->shouldIgnore()) {
+            return [];
+        }
+
+        $observers = [];
+
+        foreach ($this->getManifest() as $name => $extra) {
+            $observers = array_merge($observers, $extra['observers'] ?? []);
+        }
+
+        return array_map([$this, 'listObserver'], array_filter($observers, [$this, 'validateObserver']));
+    }
+
+    /**
+     * @param mixed $observer
+     *
+     * @return bool
+     */
+    protected function isDisable($observer): bool
+    {
+        return in_array($observer, $this->app->config->get('disable_observers', []));
+    }
+
+    /**
+     * Get the observers should be ignore.
+     *
+     * @return bool
+     */
+    protected function shouldIgnore(): bool
+    {
+        return !file_exists($this->manifestPath) || $this->isDisable('*');
+    }
+
+    /**
+     * Validate the given observer.
+     *
+     * @param mixed $observer
+     *
+     * @return bool
+     *
+     * @throws \ReflectionException
+     */
+    protected function validateObserver($observer): bool
+    {
+        return !$this->isDisable($observer)
+            && (new ReflectionClass($observer))->implementsInterface(EventHandlerInterface::class)
+            && $this->accessible($observer);
+    }
+
+    /**
+     * Determine whether the given observer is accessible.
+     *
+     * @param string $observer
+     *
+     * @return bool
+     */
+    protected function accessible($observer): bool
+    {
+        if (!method_exists($observer, 'getAccessor')) {
+            return true;
+        }
+
+        return in_array(get_class($this->app), (array) $observer::getAccessor());
+    }
+
+    /**
+     * @param mixed $observer
+     *
+     * @return array
+     */
+    protected function listObserver($observer): array
+    {
+        $condition = method_exists($observer, 'onCondition') ? $observer::onCondition() : '*';
+
+        return [$observer, $condition];
+    }
+
+    /**
+     * Get the easywechat manifest.
+     *
+     * @return array
+     */
+    protected function getManifest(): array
+    {
+        if (!is_null($this->manifest)) {
+            return $this->manifest;
+        }
+
+        return $this->manifest = file_exists($this->manifestPath) ? require $this->manifestPath : [];
+    }
+}

+ 25 - 0
vendor/easywechat-composer/easywechat-composer/easywechat-composer/src/Http/DelegationResponse.php

@@ -0,0 +1,25 @@
+<?php
+
+declare(strict_types=1);
+
+/*
+ * This file is part of the EasyWeChatComposer.
+ *
+ * (c) 张铭阳 <mingyoungcheung@gmail.com>
+ *
+ * This source file is subject to the MIT license that is bundled
+ * with this source code in the file LICENSE.
+ */
+
+namespace EasyWeChatComposer\Http;
+
+class DelegationResponse extends Response
+{
+    /**
+     * @return string
+     */
+    public function getBodyContents()
+    {
+        return $this->response->getBodyContents();
+    }
+}

+ 104 - 0
vendor/easywechat-composer/easywechat-composer/easywechat-composer/src/Http/Response.php

@@ -0,0 +1,104 @@
+<?php
+
+declare(strict_types=1);
+
+/*
+ * This file is part of the EasyWeChatComposer.
+ *
+ * (c) 张铭阳 <mingyoungcheung@gmail.com>
+ *
+ * This source file is subject to the MIT license that is bundled
+ * with this source code in the file LICENSE.
+ */
+
+namespace EasyWeChatComposer\Http;
+
+use EasyWeChat\Kernel\Contracts\Arrayable;
+use EasyWeChat\Kernel\Http\Response as HttpResponse;
+use JsonSerializable;
+
+class Response implements Arrayable, JsonSerializable
+{
+    /**
+     * @var \EasyWeChat\Kernel\Http\Response
+     */
+    protected $response;
+
+    /**
+     * @var array
+     */
+    protected $array;
+
+    /**
+     * @param \EasyWeChat\Kernel\Http\Response $response
+     */
+    public function __construct(HttpResponse $response)
+    {
+        $this->response = $response;
+    }
+
+    /**
+     * @see \ArrayAccess::offsetExists
+     *
+     * @param string $offset
+     *
+     * @return bool
+     */
+    public function offsetExists($offset)
+    {
+        return isset($this->toArray()[$offset]);
+    }
+
+    /**
+     * @see \ArrayAccess::offsetGet
+     *
+     * @param string $offset
+     *
+     * @return mixed
+     */
+    public function offsetGet($offset)
+    {
+        return $this->toArray()[$offset] ?? null;
+    }
+
+    /**
+     * @see \ArrayAccess::offsetSet
+     *
+     * @param string $offset
+     * @param mixed  $value
+     */
+    public function offsetSet($offset, $value)
+    {
+        //
+    }
+
+    /**
+     * @see \ArrayAccess::offsetUnset
+     *
+     * @param string $offset
+     */
+    public function offsetUnset($offset)
+    {
+        //
+    }
+
+    /**
+     * Get the instance as an array.
+     *
+     * @return array
+     */
+    public function toArray()
+    {
+        return $this->array ?: $this->array = $this->response->toArray();
+    }
+
+    /**
+     * Convert the object into something JSON serializable.
+     *
+     * @return array
+     */
+    public function jsonSerialize()
+    {
+        return $this->toArray();
+    }
+}

+ 49 - 0
vendor/easywechat-composer/easywechat-composer/easywechat-composer/src/Laravel/Http/Controllers/DelegatesController.php

@@ -0,0 +1,49 @@
+<?php
+
+declare(strict_types=1);
+
+/*
+ * This file is part of the EasyWeChatComposer.
+ *
+ * (c) 张铭阳 <mingyoungcheung@gmail.com>
+ *
+ * This source file is subject to the MIT license that is bundled
+ * with this source code in the file LICENSE.
+ */
+
+namespace EasyWeChatComposer\Laravel\Http\Controllers;
+
+use EasyWeChatComposer\Delegation\Hydrate;
+use EasyWeChatComposer\Encryption\DefaultEncrypter;
+use Illuminate\Http\Request;
+use Throwable;
+
+class DelegatesController
+{
+    /**
+     * @param \Illuminate\Http\Request                        $request
+     * @param \EasyWeChatComposer\Encryption\DefaultEncrypter $encrypter
+     *
+     * @return \Illuminate\Http\Response
+     */
+    public function __invoke(Request $request, DefaultEncrypter $encrypter)
+    {
+        try {
+            $data = json_decode($encrypter->decrypt($request->get('encrypted')), true);
+
+            $hydrate = new Hydrate($data);
+
+            $response = $hydrate->handle();
+
+            return response()->json([
+                'response_type' => get_class($response),
+                'response' => $encrypter->encrypt($response->getBodyContents()),
+            ]);
+        } catch (Throwable $t) {
+            return [
+                'exception' => get_class($t),
+                'message' => $t->getMessage(),
+            ];
+        }
+    }
+}

+ 116 - 0
vendor/easywechat-composer/easywechat-composer/easywechat-composer/src/Laravel/ServiceProvider.php

@@ -0,0 +1,116 @@
+<?php
+
+declare(strict_types=1);
+
+/*
+ * This file is part of the EasyWeChatComposer.
+ *
+ * (c) 张铭阳 <mingyoungcheung@gmail.com>
+ *
+ * This source file is subject to the MIT license that is bundled
+ * with this source code in the file LICENSE.
+ */
+
+namespace EasyWeChatComposer\Laravel;
+
+use EasyWeChatComposer\EasyWeChat;
+use EasyWeChatComposer\Encryption\DefaultEncrypter;
+use Illuminate\Foundation\Application;
+use Illuminate\Support\Arr;
+use Illuminate\Support\Facades\Cache;
+use Illuminate\Support\Facades\Route;
+use Illuminate\Support\ServiceProvider as LaravelServiceProvider;
+use RuntimeException;
+
+class ServiceProvider extends LaravelServiceProvider
+{
+    /**
+     * Bootstrap any application services.
+     */
+    public function boot()
+    {
+        $this->registerRoutes();
+        $this->publishes([
+            __DIR__.'/config.php' => config_path('easywechat-composer.php'),
+        ]);
+
+        EasyWeChat::setEncryptionKey(
+            $defaultKey = $this->getKey()
+        );
+
+        EasyWeChat::withDelegation()
+                    ->toHost($this->config('delegation.host'))
+                    ->ability($this->config('delegation.enabled'));
+
+        $this->app->when(DefaultEncrypter::class)->needs('$key')->give($defaultKey);
+    }
+
+    /**
+     * Register routes.
+     */
+    protected function registerRoutes()
+    {
+        Route::prefix('easywechat-composer')->namespace('EasyWeChatComposer\Laravel\Http\Controllers')->group(function () {
+            $this->loadRoutesFrom(__DIR__.'/routes.php');
+        });
+    }
+
+    /**
+     * Register any application services.
+     */
+    public function register()
+    {
+        $this->configure();
+    }
+
+    /**
+     * Register config.
+     */
+    protected function configure()
+    {
+        $this->mergeConfigFrom(
+            __DIR__.'/config.php', 'easywechat-composer'
+        );
+    }
+
+    /**
+     * Get the specified configuration value.
+     *
+     * @param string|null $key
+     * @param mixed       $default
+     *
+     * @return mixed
+     */
+    protected function config($key = null, $default = null)
+    {
+        $config = $this->app['config']->get('easywechat-composer');
+
+        if (is_null($key)) {
+            return $config;
+        }
+
+        return Arr::get($config, $key, $default);
+    }
+
+    /**
+     * @return string
+     */
+    protected function getKey()
+    {
+        return $this->config('encryption.key') ?: $this->getMd5Key();
+    }
+
+    /**
+     * @return string
+     */
+    protected function getMd5Key()
+    {
+        $ttl = (version_compare(Application::VERSION, '5.8') === -1) ? 30 : 1800;
+
+        return Cache::remember('easywechat-composer.encryption_key', $ttl, function () {
+            throw_unless(file_exists($path = base_path('composer.lock')), RuntimeException::class, 'No encryption key provided.');
+
+            return md5_file($path);
+        });
+    }
+}

+ 29 - 0
vendor/easywechat-composer/easywechat-composer/easywechat-composer/src/Laravel/config.php

@@ -0,0 +1,29 @@
+<?php
+
+declare(strict_types=1);
+
+/*
+ * This file is part of the EasyWeChatComposer.
+ *
+ * (c) mingyoung <mingyoungcheung@gmail.com>
+ *
+ * This source file is subject to the MIT license that is bundled
+ * with this source code in the file LICENSE.
+ */
+
+return [
+
+    'encryption' => [
+
+        'key' => env('EASYWECHAT_KEY'),
+
+    ],
+
+    'delegation' => [
+
+        'enabled' => env('EASYWECHAT_DELEGATION', false),
+
+        'host' => env('EASYWECHAT_DELEGATION_HOST'),
+    ],
+
+];

+ 16 - 0
vendor/easywechat-composer/easywechat-composer/easywechat-composer/src/Laravel/routes.php

@@ -0,0 +1,16 @@
+<?php
+
+declare(strict_types=1);
+
+/*
+ * This file is part of the EasyWeChatComposer.
+ *
+ * (c) 张铭阳 <mingyoungcheung@gmail.com>
+ *
+ * This source file is subject to the MIT license that is bundled
+ * with this source code in the file LICENSE.
+ */
+
+use Illuminate\Support\Facades\Route;
+
+Route::post('delegate', 'DelegatesController');

+ 120 - 0
vendor/easywechat-composer/easywechat-composer/easywechat-composer/src/ManifestManager.php

@@ -0,0 +1,120 @@
+<?php
+
+declare(strict_types=1);
+
+/*
+ * This file is part of the EasyWeChatComposer.
+ *
+ * (c) 张铭阳 <mingyoungcheung@gmail.com>
+ *
+ * This source file is subject to the MIT license that is bundled
+ * with this source code in the file LICENSE.
+ */
+
+namespace EasyWeChatComposer;
+
+class ManifestManager
+{
+    const PACKAGE_TYPE = 'easywechat-extension';
+
+    const EXTRA_OBSERVER = 'observers';
+
+    /**
+     * The vendor path.
+     *
+     * @var string
+     */
+    protected $vendorPath;
+
+    /**
+     * The manifest path.
+     *
+     * @var string
+     */
+    protected $manifestPath;
+
+    /**
+     * @param string      $vendorPath
+     * @param string|null $manifestPath
+     */
+    public function __construct(string $vendorPath, string $manifestPath = null)
+    {
+        $this->vendorPath = $vendorPath;
+        $this->manifestPath = $manifestPath ?: $vendorPath.'/easywechat-composer/easywechat-composer/extensions.php';
+    }
+
+    /**
+     * Remove manifest file.
+     *
+     * @return $this
+     */
+    public function unlink()
+    {
+        if (file_exists($this->manifestPath)) {
+            @unlink($this->manifestPath);
+        }
+
+        return $this;
+    }
+
+    /**
+     * Build the manifest file.
+     */
+    public function build()
+    {
+        $packages = [];
+
+        if (file_exists($installed = $this->vendorPath.'/composer/installed.json')) {
+            $packages = json_decode(file_get_contents($installed), true);
+        }
+
+        $this->write($this->map($packages));
+    }
+
+    /**
+     * @param array $packages
+     *
+     * @return array
+     */
+    protected function map(array $packages): array
+    {
+        $manifest = [];
+
+        $packages = array_filter($packages, function ($package) {
+            return $package['type'] === self::PACKAGE_TYPE;
+        });
+
+        foreach ($packages as $package) {
+            $manifest[$package['name']] = [self::EXTRA_OBSERVER => $package['extra'][self::EXTRA_OBSERVER] ?? []];
+        }
+
+        return $manifest;
+    }
+
+    /**
+     * Write the manifest array to a file.
+     *
+     * @param array $manifest
+     */
+    protected function write(array $manifest)
+    {
+        file_put_contents(
+            $this->manifestPath,
+            '<?php return '.var_export($manifest, true).';'
+        );
+
+        $this->invalidate($this->manifestPath);
+    }
+
+    /**
+     * Invalidate the given file.
+     *
+     * @param string $file
+     */
+    protected function invalidate($file)
+    {
+        if (function_exists('opcache_invalidate')) {
+            @opcache_invalidate($file, true);
+        }
+    }
+}

+ 107 - 0
vendor/easywechat-composer/easywechat-composer/easywechat-composer/src/Plugin.php

@@ -0,0 +1,107 @@
+<?php
+
+declare(strict_types=1);
+
+/*
+ * This file is part of the EasyWeChatComposer.
+ *
+ * (c) 张铭阳 <mingyoungcheung@gmail.com>
+ *
+ * This source file is subject to the MIT license that is bundled
+ * with this source code in the file LICENSE.
+ */
+
+namespace EasyWeChatComposer;
+
+use Composer\Composer;
+use Composer\EventDispatcher\EventSubscriberInterface;
+use Composer\Installer\PackageEvent;
+use Composer\Installer\PackageEvents;
+use Composer\IO\IOInterface;
+use Composer\Plugin\Capable;
+use Composer\Plugin\PluginInterface;
+use Composer\Script\Event;
+use Composer\Script\ScriptEvents;
+
+class Plugin implements PluginInterface, EventSubscriberInterface, Capable
+{
+    /**
+     * @var bool
+     */
+    protected $activated = true;
+
+    /**
+     * Apply plugin modifications to Composer.
+     */
+    public function activate(Composer $composer, IOInterface $io)
+    {
+        //
+    }
+
+    /**
+     * Remove any hooks from Composer.
+     *
+     * This will be called when a plugin is deactivated before being
+     * uninstalled, but also before it gets upgraded to a new version
+     * so the old one can be deactivated and the new one activated.
+     */
+    public function deactivate(Composer $composer, IOInterface $io)
+    {
+        //
+    }
+
+    /**
+     * Prepare the plugin to be uninstalled.
+     *
+     * This will be called after deactivate.
+     */
+    public function uninstall(Composer $composer, IOInterface $io)
+    {
+    }
+
+    /**
+     * @return array
+     */
+    public function getCapabilities()
+    {
+        return [
+            'Composer\Plugin\Capability\CommandProvider' => 'EasyWeChatComposer\Commands\Provider',
+        ];
+    }
+
+    /**
+     * Listen events.
+     *
+     * @return array
+     */
+    public static function getSubscribedEvents()
+    {
+        return [
+            PackageEvents::PRE_PACKAGE_UNINSTALL => 'prePackageUninstall',
+            ScriptEvents::POST_AUTOLOAD_DUMP => 'postAutoloadDump',
+        ];
+    }
+
+    /**
+     * @param \Composer\Installer\PackageEvent
+     */
+    public function prePackageUninstall(PackageEvent $event)
+    {
+        if ($event->getOperation()->getPackage()->getName() === 'overtrue/wechat') {
+            $this->activated = false;
+        }
+    }
+
+    public function postAutoloadDump(Event $event)
+    {
+        if (!$this->activated) {
+            return;
+        }
+
+        $manifest = new ManifestManager(
+            rtrim($event->getComposer()->getConfig()->get('vendor-dir'), '/')
+        );
+
+        $manifest->unlink()->build();
+    }
+}

+ 110 - 0
vendor/easywechat-composer/easywechat-composer/easywechat-composer/src/Traits/MakesHttpRequests.php

@@ -0,0 +1,110 @@
+<?php
+
+declare(strict_types=1);
+
+/*
+ * This file is part of the EasyWeChatComposer.
+ *
+ * (c) 张铭阳 <mingyoungcheung@gmail.com>
+ *
+ * This source file is subject to the MIT license that is bundled
+ * with this source code in the file LICENSE.
+ */
+
+namespace EasyWeChatComposer\Traits;
+
+use EasyWeChat\Kernel\Http\StreamResponse;
+use EasyWeChat\Kernel\Traits\ResponseCastable;
+use EasyWeChatComposer\Contracts\Encrypter;
+use EasyWeChatComposer\EasyWeChat;
+use EasyWeChatComposer\Encryption\DefaultEncrypter;
+use EasyWeChatComposer\Exceptions\DelegationException;
+use GuzzleHttp\Client;
+use GuzzleHttp\ClientInterface;
+
+trait MakesHttpRequests
+{
+    use ResponseCastable;
+
+    /**
+     * @var \GuzzleHttp\ClientInterface
+     */
+    protected $httpClient;
+
+    /**
+     * @var \EasyWeChatComposer\Contracts\Encrypter
+     */
+    protected $encrypter;
+
+    /**
+     * @param string $endpoint
+     * @param array  $payload
+     *
+     * @return array|\EasyWeChat\Kernel\Support\Collection|object|\Psr\Http\Message\ResponseInterface|string
+     *
+     * @throws \EasyWeChat\Kernel\Exceptions\InvalidArgumentException
+     * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException
+     * @throws \GuzzleHttp\Exception\GuzzleException
+     */
+    protected function request($endpoint, array $payload)
+    {
+        $response = $this->getHttpClient()->request('POST', $endpoint, [
+            'form_params' => $this->buildFormParams($payload),
+        ]);
+
+        $parsed = $this->parseResponse($response);
+
+        return $this->detectAndCastResponseToType(
+            $this->getEncrypter()->decrypt($parsed['response']),
+            ($parsed['response_type'] === StreamResponse::class) ? 'raw' : $this->app['config']['response_type']
+        );
+    }
+
+    /**
+     * @param array $payload
+     *
+     * @return array
+     */
+    protected function buildFormParams($payload)
+    {
+        return [
+            'encrypted' => $this->getEncrypter()->encrypt(json_encode($payload)),
+        ];
+    }
+
+    /**
+     * @param \Psr\Http\Message\ResponseInterface $response
+     *
+     * @return array
+     */
+    protected function parseResponse($response)
+    {
+        $result = json_decode((string) $response->getBody(), true);
+
+        if (isset($result['exception'])) {
+            throw (new DelegationException($result['message']))->setException($result['exception']);
+        }
+
+        return $result;
+    }
+
+    /**
+     * @return \GuzzleHttp\ClientInterface
+     */
+    protected function getHttpClient(): ClientInterface
+    {
+        return $this->httpClient ?: $this->httpClient = new Client([
+            'base_uri' => $this->app['config']['delegation']['host'],
+        ]);
+    }
+
+    /**
+     * @return \EasyWeChatComposer\Contracts\Encrypter
+     */
+    protected function getEncrypter(): Encrypter
+    {
+        return $this->encrypter ?: $this->encrypter = new DefaultEncrypter(
+            EasyWeChat::getEncryptionKey()
+        );
+    }
+}

+ 60 - 0
vendor/easywechat-composer/easywechat-composer/easywechat-composer/src/Traits/WithAggregator.php

@@ -0,0 +1,60 @@
+<?php
+
+declare(strict_types=1);
+
+/*
+ * This file is part of the EasyWeChatComposer.
+ *
+ * (c) 张铭阳 <mingyoungcheung@gmail.com>
+ *
+ * This source file is subject to the MIT license that is bundled
+ * with this source code in the file LICENSE.
+ */
+
+namespace EasyWeChatComposer\Traits;
+
+use EasyWeChat\Kernel\BaseClient;
+use EasyWeChatComposer\Delegation\DelegationTo;
+use EasyWeChatComposer\EasyWeChat;
+
+trait WithAggregator
+{
+    /**
+     * Aggregate.
+     */
+    protected function aggregate()
+    {
+        foreach (EasyWeChat::config() as $key => $value) {
+            $this['config']->set($key, $value);
+        }
+    }
+
+    /**
+     * @return bool
+     */
+    public function shouldDelegate($id)
+    {
+        return $this['config']->get('delegation.enabled')
+            && $this->offsetGet($id) instanceof BaseClient;
+    }
+
+    /**
+     * @return $this
+     */
+    public function shouldntDelegate()
+    {
+        $this['config']->set('delegation.enabled', false);
+
+        return $this;
+    }
+
+    /**
+     * @param string $id
+     *
+     * @return \EasyWeChatComposer\Delegation
+     */
+    public function delegateTo($id)
+    {
+        return new DelegationTo($this, $id);
+    }
+}

+ 37 - 0
vendor/easywechat-composer/easywechat-composer/easywechat-composer/tests/ManifestManagerTest.php

@@ -0,0 +1,37 @@
+<?php
+
+declare(strict_types=1);
+
+/*
+ * This file is part of the EasyWeChatComposer.
+ *
+ * (c) 张铭阳 <mingyoungcheung@gmail.com>
+ *
+ * This source file is subject to the MIT license that is bundled
+ * with this source code in the file LICENSE.
+ */
+
+namespace EasyWeChatComposer\Tests;
+
+use EasyWeChatComposer\ManifestManager;
+use PHPUnit\Framework\TestCase;
+
+class ManifestManagerTest extends TestCase
+{
+    private $vendorPath;
+    private $manifestPath;
+
+    protected function getManifestManager()
+    {
+        return new ManifestManager(
+            $this->vendorPath = __DIR__.'/__fixtures__/vendor/',
+            $this->manifestPath = __DIR__.'/__fixtures__/extensions.php'
+        );
+    }
+
+    public function testUnlink()
+    {
+        $this->assertInstanceOf(ManifestManager::class, $this->getManifestManager()->unlink());
+        $this->assertFalse(file_exists($this->manifestPath));
+    }
+}