From 482d6849a4153d010121da174c5e24349aaeda1b Mon Sep 17 00:00:00 2001 From: mkm <727897186@qq.com> Date: Tue, 20 Jun 2023 17:22:23 +0800 Subject: [PATCH 1/3] =?UTF-8?q?=E6=8F=90=E4=BA=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 1 + .user.ini | 1 + composer.json | 3 +- composer.lock | 237 +++++++++- config/swoole.php | 2 +- vendor/composer/ClassLoader.php | 12 +- vendor/composer/InstalledVersions.php | 17 +- vendor/composer/autoload_psr4.php | 3 + vendor/composer/autoload_real.php | 6 +- vendor/composer/autoload_static.php | 15 + vendor/composer/installed.json | 244 ++++++++++ vendor/composer/installed.php | 39 +- vendor/graham-campbell/result-type/LICENSE | 21 + .../graham-campbell/result-type/composer.json | 33 ++ .../graham-campbell/result-type/src/Error.php | 120 +++++ .../result-type/src/Result.php | 69 +++ .../result-type/src/Success.php | 119 +++++ vendor/phpoption/phpoption/LICENSE | 201 ++++++++ vendor/phpoption/phpoption/composer.json | 52 +++ .../phpoption/src/PhpOption/LazyOption.php | 175 +++++++ .../phpoption/src/PhpOption/None.php | 136 ++++++ .../phpoption/src/PhpOption/Option.php | 434 ++++++++++++++++++ .../phpoption/src/PhpOption/Some.php | 169 +++++++ vendor/services.php | 2 +- vendor/vlucas/phpdotenv/LICENSE | 30 ++ vendor/vlucas/phpdotenv/composer.json | 53 +++ vendor/vlucas/phpdotenv/src/Dotenv.php | 267 +++++++++++ .../src/Exception/ExceptionInterface.php | 12 + .../Exception/InvalidEncodingException.php | 12 + .../src/Exception/InvalidFileException.php | 12 + .../src/Exception/InvalidPathException.php | 12 + .../src/Exception/ValidationException.php | 12 + vendor/vlucas/phpdotenv/src/Loader/Loader.php | 47 ++ .../phpdotenv/src/Loader/LoaderInterface.php | 20 + .../vlucas/phpdotenv/src/Loader/Resolver.php | 65 +++ vendor/vlucas/phpdotenv/src/Parser/Entry.php | 59 +++ .../phpdotenv/src/Parser/EntryParser.php | 293 ++++++++++++ vendor/vlucas/phpdotenv/src/Parser/Lexer.php | 62 +++ vendor/vlucas/phpdotenv/src/Parser/Lines.php | 125 +++++ vendor/vlucas/phpdotenv/src/Parser/Parser.php | 52 +++ .../phpdotenv/src/Parser/ParserInterface.php | 19 + vendor/vlucas/phpdotenv/src/Parser/Value.php | 88 ++++ .../Repository/Adapter/AdapterInterface.php | 15 + .../src/Repository/Adapter/ApacheAdapter.php | 89 ++++ .../src/Repository/Adapter/ArrayAdapter.php | 80 ++++ .../Repository/Adapter/EnvConstAdapter.php | 87 ++++ .../src/Repository/Adapter/GuardedWriter.php | 85 ++++ .../Repository/Adapter/ImmutableWriter.php | 110 +++++ .../src/Repository/Adapter/MultiReader.php | 48 ++ .../src/Repository/Adapter/MultiWriter.php | 64 +++ .../src/Repository/Adapter/PutenvAdapter.php | 91 ++++ .../Repository/Adapter/ReaderInterface.php | 17 + .../Repository/Adapter/ReplacingWriter.php | 104 +++++ .../Repository/Adapter/ServerConstAdapter.php | 87 ++++ .../Repository/Adapter/WriterInterface.php | 27 ++ .../src/Repository/AdapterRepository.php | 88 ++++ .../src/Repository/RepositoryBuilder.php | 274 +++++++++++ .../src/Repository/RepositoryInterface.php | 45 ++ .../vlucas/phpdotenv/src/Store/File/Paths.php | 44 ++ .../phpdotenv/src/Store/File/Reader.php | 81 ++++ .../vlucas/phpdotenv/src/Store/FileStore.php | 72 +++ .../phpdotenv/src/Store/StoreBuilder.php | 143 ++++++ .../phpdotenv/src/Store/StoreInterface.php | 17 + .../phpdotenv/src/Store/StringStore.php | 37 ++ vendor/vlucas/phpdotenv/src/Util/Regex.php | 110 +++++ vendor/vlucas/phpdotenv/src/Util/Str.php | 90 ++++ vendor/vlucas/phpdotenv/src/Validator.php | 209 +++++++++ 67 files changed, 5432 insertions(+), 33 deletions(-) create mode 100644 .user.ini create mode 100644 vendor/graham-campbell/result-type/LICENSE create mode 100644 vendor/graham-campbell/result-type/composer.json create mode 100644 vendor/graham-campbell/result-type/src/Error.php create mode 100644 vendor/graham-campbell/result-type/src/Result.php create mode 100644 vendor/graham-campbell/result-type/src/Success.php create mode 100644 vendor/phpoption/phpoption/LICENSE create mode 100644 vendor/phpoption/phpoption/composer.json create mode 100644 vendor/phpoption/phpoption/src/PhpOption/LazyOption.php create mode 100644 vendor/phpoption/phpoption/src/PhpOption/None.php create mode 100644 vendor/phpoption/phpoption/src/PhpOption/Option.php create mode 100644 vendor/phpoption/phpoption/src/PhpOption/Some.php create mode 100644 vendor/vlucas/phpdotenv/LICENSE create mode 100644 vendor/vlucas/phpdotenv/composer.json create mode 100644 vendor/vlucas/phpdotenv/src/Dotenv.php create mode 100644 vendor/vlucas/phpdotenv/src/Exception/ExceptionInterface.php create mode 100644 vendor/vlucas/phpdotenv/src/Exception/InvalidEncodingException.php create mode 100644 vendor/vlucas/phpdotenv/src/Exception/InvalidFileException.php create mode 100644 vendor/vlucas/phpdotenv/src/Exception/InvalidPathException.php create mode 100644 vendor/vlucas/phpdotenv/src/Exception/ValidationException.php create mode 100644 vendor/vlucas/phpdotenv/src/Loader/Loader.php create mode 100644 vendor/vlucas/phpdotenv/src/Loader/LoaderInterface.php create mode 100644 vendor/vlucas/phpdotenv/src/Loader/Resolver.php create mode 100644 vendor/vlucas/phpdotenv/src/Parser/Entry.php create mode 100644 vendor/vlucas/phpdotenv/src/Parser/EntryParser.php create mode 100644 vendor/vlucas/phpdotenv/src/Parser/Lexer.php create mode 100644 vendor/vlucas/phpdotenv/src/Parser/Lines.php create mode 100644 vendor/vlucas/phpdotenv/src/Parser/Parser.php create mode 100644 vendor/vlucas/phpdotenv/src/Parser/ParserInterface.php create mode 100644 vendor/vlucas/phpdotenv/src/Parser/Value.php create mode 100644 vendor/vlucas/phpdotenv/src/Repository/Adapter/AdapterInterface.php create mode 100644 vendor/vlucas/phpdotenv/src/Repository/Adapter/ApacheAdapter.php create mode 100644 vendor/vlucas/phpdotenv/src/Repository/Adapter/ArrayAdapter.php create mode 100644 vendor/vlucas/phpdotenv/src/Repository/Adapter/EnvConstAdapter.php create mode 100644 vendor/vlucas/phpdotenv/src/Repository/Adapter/GuardedWriter.php create mode 100644 vendor/vlucas/phpdotenv/src/Repository/Adapter/ImmutableWriter.php create mode 100644 vendor/vlucas/phpdotenv/src/Repository/Adapter/MultiReader.php create mode 100644 vendor/vlucas/phpdotenv/src/Repository/Adapter/MultiWriter.php create mode 100644 vendor/vlucas/phpdotenv/src/Repository/Adapter/PutenvAdapter.php create mode 100644 vendor/vlucas/phpdotenv/src/Repository/Adapter/ReaderInterface.php create mode 100644 vendor/vlucas/phpdotenv/src/Repository/Adapter/ReplacingWriter.php create mode 100644 vendor/vlucas/phpdotenv/src/Repository/Adapter/ServerConstAdapter.php create mode 100644 vendor/vlucas/phpdotenv/src/Repository/Adapter/WriterInterface.php create mode 100644 vendor/vlucas/phpdotenv/src/Repository/AdapterRepository.php create mode 100644 vendor/vlucas/phpdotenv/src/Repository/RepositoryBuilder.php create mode 100644 vendor/vlucas/phpdotenv/src/Repository/RepositoryInterface.php create mode 100644 vendor/vlucas/phpdotenv/src/Store/File/Paths.php create mode 100644 vendor/vlucas/phpdotenv/src/Store/File/Reader.php create mode 100644 vendor/vlucas/phpdotenv/src/Store/FileStore.php create mode 100644 vendor/vlucas/phpdotenv/src/Store/StoreBuilder.php create mode 100644 vendor/vlucas/phpdotenv/src/Store/StoreInterface.php create mode 100644 vendor/vlucas/phpdotenv/src/Store/StringStore.php create mode 100644 vendor/vlucas/phpdotenv/src/Util/Regex.php create mode 100644 vendor/vlucas/phpdotenv/src/Util/Str.php create mode 100644 vendor/vlucas/phpdotenv/src/Validator.php diff --git a/.gitignore b/.gitignore index 60c4f43a..bf33c970 100644 --- a/.gitignore +++ b/.gitignore @@ -11,3 +11,4 @@ app/controller/api/Test.php public/protocol.html /runtime/* runtime/swoole.pid +cert_crmeb copy.key diff --git a/.user.ini b/.user.ini new file mode 100644 index 00000000..ed9480b1 --- /dev/null +++ b/.user.ini @@ -0,0 +1 @@ +open_basedir=/www/wwwroot/shop-php/:/tmp/ \ No newline at end of file diff --git a/composer.json b/composer.json index 09e90fa2..a9bb3e7c 100644 --- a/composer.json +++ b/composer.json @@ -54,7 +54,8 @@ "ucloud/ufile-php-sdk": "^1.0", "swoole/ide-helper": "^4.8", "alibabacloud/dysmsapi-20170525": "2.0.9", - "fastknife/ajcaptcha": "^1.1" + "fastknife/ajcaptcha": "^1.1", + "vlucas/phpdotenv": "^5.3" }, "require-dev": { "symfony/var-dumper": "^4.2", diff --git a/composer.lock b/composer.lock index d5fa651f..b233bee6 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "a1e4f8118804a0d4921567860412c9a2", + "content-hash": "cdcb3c1e7a4e523b77afdea055928bd4", "packages": [ { "name": "adbario/php-dot-notation", @@ -1038,6 +1038,74 @@ "homepage": "https://github.com/firebase/php-jwt", "time": "2020-02-24T23:15:03+00:00" }, + { + "name": "graham-campbell/result-type", + "version": "v1.1.0", + "source": { + "type": "git", + "url": "https://github.com/GrahamCampbell/Result-Type.git", + "reference": "a878d45c1914464426dc94da61c9e1d36ae262a8" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/GrahamCampbell/Result-Type/zipball/a878d45c1914464426dc94da61c9e1d36ae262a8", + "reference": "a878d45c1914464426dc94da61c9e1d36ae262a8", + "shasum": "", + "mirrors": [ + { + "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%", + "preferred": true + } + ] + }, + "require": { + "php": "^7.2.5 || ^8.0", + "phpoption/phpoption": "^1.9" + }, + "require-dev": { + "phpunit/phpunit": "^8.5.28 || ^9.5.21" + }, + "type": "library", + "autoload": { + "psr-4": { + "GrahamCampbell\\ResultType\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Graham Campbell", + "email": "hello@gjcampbell.co.uk", + "homepage": "https://github.com/GrahamCampbell" + } + ], + "description": "An Implementation Of The Result Type", + "keywords": [ + "Graham Campbell", + "GrahamCampbell", + "Result Type", + "Result-Type", + "result" + ], + "support": { + "issues": "https://github.com/GrahamCampbell/Result-Type/issues", + "source": "https://github.com/GrahamCampbell/Result-Type/tree/v1.1.0" + }, + "funding": [ + { + "url": "https://github.com/GrahamCampbell", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/graham-campbell/result-type", + "type": "tidelift" + } + ], + "time": "2022-07-30T15:56:11+00:00" + }, { "name": "gregwar/captcha", "version": "v1.1.8", @@ -2851,6 +2919,87 @@ ], "time": "2020-07-19T09:51:35+00:00" }, + { + "name": "phpoption/phpoption", + "version": "1.9.1", + "source": { + "type": "git", + "url": "https://github.com/schmittjoh/php-option.git", + "reference": "dd3a383e599f49777d8b628dadbb90cae435b87e" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/schmittjoh/php-option/zipball/dd3a383e599f49777d8b628dadbb90cae435b87e", + "reference": "dd3a383e599f49777d8b628dadbb90cae435b87e", + "shasum": "", + "mirrors": [ + { + "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%", + "preferred": true + } + ] + }, + "require": { + "php": "^7.2.5 || ^8.0" + }, + "require-dev": { + "bamarni/composer-bin-plugin": "^1.8.2", + "phpunit/phpunit": "^8.5.32 || ^9.6.3 || ^10.0.12" + }, + "type": "library", + "extra": { + "bamarni-bin": { + "bin-links": true, + "forward-command": true + }, + "branch-alias": { + "dev-master": "1.9-dev" + } + }, + "autoload": { + "psr-4": { + "PhpOption\\": "src/PhpOption/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "Apache-2.0" + ], + "authors": [ + { + "name": "Johannes M. Schmitt", + "email": "schmittjoh@gmail.com", + "homepage": "https://github.com/schmittjoh" + }, + { + "name": "Graham Campbell", + "email": "hello@gjcampbell.co.uk", + "homepage": "https://github.com/GrahamCampbell" + } + ], + "description": "Option Type for PHP", + "keywords": [ + "language", + "option", + "php", + "type" + ], + "support": { + "issues": "https://github.com/schmittjoh/php-option/issues", + "source": "https://github.com/schmittjoh/php-option/tree/1.9.1" + }, + "funding": [ + { + "url": "https://github.com/GrahamCampbell", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/phpoption/phpoption", + "type": "tidelift" + } + ], + "time": "2023-02-25T19:38:58+00:00" + }, { "name": "pimple/pimple", "version": "v3.3.0", @@ -5220,6 +5369,92 @@ }, "time": "2018-05-08T02:37:11+00:00" }, + { + "name": "vlucas/phpdotenv", + "version": "v5.3.0", + "source": { + "type": "git", + "url": "https://github.com/vlucas/phpdotenv.git", + "reference": "b3eac5c7ac896e52deab4a99068e3f4ab12d9e56" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/vlucas/phpdotenv/zipball/b3eac5c7ac896e52deab4a99068e3f4ab12d9e56", + "reference": "b3eac5c7ac896e52deab4a99068e3f4ab12d9e56", + "shasum": "", + "mirrors": [ + { + "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%", + "preferred": true + } + ] + }, + "require": { + "ext-pcre": "*", + "graham-campbell/result-type": "^1.0.1", + "php": "^7.1.3 || ^8.0", + "phpoption/phpoption": "^1.7.4", + "symfony/polyfill-ctype": "^1.17", + "symfony/polyfill-mbstring": "^1.17", + "symfony/polyfill-php80": "^1.17" + }, + "require-dev": { + "bamarni/composer-bin-plugin": "^1.4.1", + "ext-filter": "*", + "phpunit/phpunit": "^7.5.20 || ^8.5.14 || ^9.5.1" + }, + "suggest": { + "ext-filter": "Required to use the boolean validator." + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "5.3-dev" + } + }, + "autoload": { + "psr-4": { + "Dotenv\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Graham Campbell", + "email": "graham@alt-three.com", + "homepage": "https://gjcampbell.co.uk/" + }, + { + "name": "Vance Lucas", + "email": "vance@vancelucas.com", + "homepage": "https://vancelucas.com/" + } + ], + "description": "Loads environment variables from `.env` to `getenv()`, `$_ENV` and `$_SERVER` automagically.", + "keywords": [ + "dotenv", + "env", + "environment" + ], + "support": { + "issues": "https://github.com/vlucas/phpdotenv/issues", + "source": "https://github.com/vlucas/phpdotenv/tree/v5.3.0" + }, + "funding": [ + { + "url": "https://github.com/GrahamCampbell", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/vlucas/phpdotenv", + "type": "tidelift" + } + ], + "time": "2021-01-20T15:23:13+00:00" + }, { "name": "xaboy/form-builder", "version": "2.0.15", diff --git a/config/swoole.php b/config/swoole.php index 34e2ad4d..8429e475 100644 --- a/config/swoole.php +++ b/config/swoole.php @@ -17,7 +17,7 @@ use think\swoole\websocket\socketio\Parser; return [ 'server' => [ 'host' => env('SWOOLE_HOST', '0.0.0.0'), // 监听地址 - 'port' => env('SWOOLE_PORT', 8325), // 监听端口 + 'port' => env('SWOOLE_PORT', 8324), // 监听端口 'mode' => SWOOLE_PROCESS, // 运行模式 默认为SWOOLE_PROCESS 'sock_type' => SWOOLE_SOCK_TCP, // sock type 默认为SWOOLE_SOCK_TCP 'options' => [ diff --git a/vendor/composer/ClassLoader.php b/vendor/composer/ClassLoader.php index a72151c7..fd56bd7d 100644 --- a/vendor/composer/ClassLoader.php +++ b/vendor/composer/ClassLoader.php @@ -429,8 +429,7 @@ class ClassLoader public function loadClass($class) { if ($file = $this->findFile($class)) { - $includeFile = self::$includeFile; - $includeFile($file); + (self::$includeFile)($file); return true; } @@ -561,10 +560,7 @@ class ClassLoader return false; } - /** - * @return void - */ - private static function initializeIncludeClosure() + private static function initializeIncludeClosure(): void { if (self::$includeFile !== null) { return; @@ -578,8 +574,8 @@ class ClassLoader * @param string $file * @return void */ - self::$includeFile = \Closure::bind(static function($file) { + self::$includeFile = static function($file) { include $file; - }, null, null); + }; } } diff --git a/vendor/composer/InstalledVersions.php b/vendor/composer/InstalledVersions.php index 51e734a7..c6b54af7 100644 --- a/vendor/composer/InstalledVersions.php +++ b/vendor/composer/InstalledVersions.php @@ -98,7 +98,7 @@ class InstalledVersions { foreach (self::getInstalled() as $installed) { if (isset($installed['versions'][$packageName])) { - return $includeDevRequirements || !isset($installed['versions'][$packageName]['dev_requirement']) || $installed['versions'][$packageName]['dev_requirement'] === false; + return $includeDevRequirements || empty($installed['versions'][$packageName]['dev_requirement']); } } @@ -119,7 +119,7 @@ class InstalledVersions */ public static function satisfies(VersionParser $parser, $packageName, $constraint) { - $constraint = $parser->parseConstraints((string) $constraint); + $constraint = $parser->parseConstraints($constraint); $provided = $parser->parseConstraints(self::getVersionRanges($packageName)); return $provided->matches($constraint); @@ -328,9 +328,7 @@ class InstalledVersions if (isset(self::$installedByVendor[$vendorDir])) { $installed[] = self::$installedByVendor[$vendorDir]; } elseif (is_file($vendorDir.'/composer/installed.php')) { - /** @var array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array} $required */ - $required = require $vendorDir.'/composer/installed.php'; - $installed[] = self::$installedByVendor[$vendorDir] = $required; + $installed[] = self::$installedByVendor[$vendorDir] = require $vendorDir.'/composer/installed.php'; if (null === self::$installed && strtr($vendorDir.'/composer', '\\', '/') === strtr(__DIR__, '\\', '/')) { self::$installed = $installed[count($installed) - 1]; } @@ -342,17 +340,12 @@ class InstalledVersions // only require the installed.php file if this file is loaded from its dumped location, // and not from its source location in the composer/composer package, see https://github.com/composer/composer/issues/9937 if (substr(__DIR__, -8, 1) !== 'C') { - /** @var array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array} $required */ - $required = require __DIR__ . '/installed.php'; - self::$installed = $required; + self::$installed = require __DIR__ . '/installed.php'; } else { self::$installed = array(); } } - - if (self::$installed !== array()) { - $installed[] = self::$installed; - } + $installed[] = self::$installed; return $installed; } diff --git a/vendor/composer/autoload_psr4.php b/vendor/composer/autoload_psr4.php index 6b97c9c3..379a66a3 100644 --- a/vendor/composer/autoload_psr4.php +++ b/vendor/composer/autoload_psr4.php @@ -41,6 +41,7 @@ return array( 'Psr\\Http\\Client\\' => array($vendorDir . '/psr/http-client/src'), 'Psr\\Container\\' => array($vendorDir . '/psr/container/src'), 'Psr\\Cache\\' => array($vendorDir . '/psr/cache/src'), + 'PhpOption\\' => array($vendorDir . '/phpoption/phpoption/src/PhpOption'), 'PhpOffice\\PhpSpreadsheet\\' => array($vendorDir . '/phpoffice/phpspreadsheet/src/PhpSpreadsheet'), 'Payment\\' => array($vendorDir . '/riverslei/payment/src'), 'Overtrue\\Socialite\\' => array($vendorDir . '/overtrue/socialite/src'), @@ -59,11 +60,13 @@ return array( 'GuzzleHttp\\Promise\\' => array($vendorDir . '/guzzlehttp/promises/src'), 'GuzzleHttp\\' => array($vendorDir . '/guzzlehttp/guzzle/src'), 'Gregwar\\' => array($vendorDir . '/gregwar/captcha/src/Gregwar'), + 'GrahamCampbell\\ResultType\\' => array($vendorDir . '/graham-campbell/result-type/src'), 'FormBuilder\\' => array($vendorDir . '/xaboy/form-builder/src'), 'Firebase\\JWT\\' => array($vendorDir . '/firebase/php-jwt/src'), 'Fastknife\\' => array($vendorDir . '/fastknife/ajcaptcha/src'), 'Endroid\\QrCode\\' => array($vendorDir . '/endroid/qr-code/src'), 'EasyWeChat\\' => array($vendorDir . '/overtrue/wechat/src'), + 'Dotenv\\' => array($vendorDir . '/vlucas/phpdotenv/src'), 'Doctrine\\Common\\Lexer\\' => array($vendorDir . '/doctrine/lexer/lib/Doctrine/Common/Lexer'), 'Darabonba\\OpenApi\\' => array($vendorDir . '/alibabacloud/darabonba-openapi/src'), 'Darabonba\\GatewaySpi\\' => array($vendorDir . '/alibabacloud/gateway-spi/src'), diff --git a/vendor/composer/autoload_real.php b/vendor/composer/autoload_real.php index 5afd5549..f1e605a7 100644 --- a/vendor/composer/autoload_real.php +++ b/vendor/composer/autoload_real.php @@ -34,15 +34,15 @@ class ComposerAutoloaderInitb1229d2685c190533aa1234015613f09 $loader->register(true); $filesToLoad = \Composer\Autoload\ComposerStaticInitb1229d2685c190533aa1234015613f09::$files; - $requireFile = \Closure::bind(static function ($fileIdentifier, $file) { + $requireFile = static function ($fileIdentifier, $file) { if (empty($GLOBALS['__composer_autoload_files'][$fileIdentifier])) { $GLOBALS['__composer_autoload_files'][$fileIdentifier] = true; require $file; } - }, null, null); + }; foreach ($filesToLoad as $fileIdentifier => $file) { - $requireFile($fileIdentifier, $file); + ($requireFile)($fileIdentifier, $file); } return $loader; diff --git a/vendor/composer/autoload_static.php b/vendor/composer/autoload_static.php index 61d2fd4a..25252ad1 100644 --- a/vendor/composer/autoload_static.php +++ b/vendor/composer/autoload_static.php @@ -147,6 +147,7 @@ class ComposerStaticInitb1229d2685c190533aa1234015613f09 'Psr\\Http\\Client\\' => 16, 'Psr\\Container\\' => 14, 'Psr\\Cache\\' => 10, + 'PhpOption\\' => 10, 'PhpOffice\\PhpSpreadsheet\\' => 25, 'Payment\\' => 8, ), @@ -183,6 +184,7 @@ class ComposerStaticInitb1229d2685c190533aa1234015613f09 'GuzzleHttp\\Promise\\' => 19, 'GuzzleHttp\\' => 11, 'Gregwar\\' => 8, + 'GrahamCampbell\\ResultType\\' => 26, ), 'F' => array ( @@ -197,6 +199,7 @@ class ComposerStaticInitb1229d2685c190533aa1234015613f09 ), 'D' => array ( + 'Dotenv\\' => 7, 'Doctrine\\Common\\Lexer\\' => 22, 'Darabonba\\OpenApi\\' => 18, 'Darabonba\\GatewaySpi\\' => 21, @@ -370,6 +373,10 @@ class ComposerStaticInitb1229d2685c190533aa1234015613f09 array ( 0 => __DIR__ . '/..' . '/psr/cache/src', ), + 'PhpOption\\' => + array ( + 0 => __DIR__ . '/..' . '/phpoption/phpoption/src/PhpOption', + ), 'PhpOffice\\PhpSpreadsheet\\' => array ( 0 => __DIR__ . '/..' . '/phpoffice/phpspreadsheet/src/PhpSpreadsheet', @@ -442,6 +449,10 @@ class ComposerStaticInitb1229d2685c190533aa1234015613f09 array ( 0 => __DIR__ . '/..' . '/gregwar/captcha/src/Gregwar', ), + 'GrahamCampbell\\ResultType\\' => + array ( + 0 => __DIR__ . '/..' . '/graham-campbell/result-type/src', + ), 'FormBuilder\\' => array ( 0 => __DIR__ . '/..' . '/xaboy/form-builder/src', @@ -462,6 +473,10 @@ class ComposerStaticInitb1229d2685c190533aa1234015613f09 array ( 0 => __DIR__ . '/..' . '/overtrue/wechat/src', ), + 'Dotenv\\' => + array ( + 0 => __DIR__ . '/..' . '/vlucas/phpdotenv/src', + ), 'Doctrine\\Common\\Lexer\\' => array ( 0 => __DIR__ . '/..' . '/doctrine/lexer/lib/Doctrine/Common/Lexer', diff --git a/vendor/composer/installed.json b/vendor/composer/installed.json index ab8fbb6f..dd242941 100644 --- a/vendor/composer/installed.json +++ b/vendor/composer/installed.json @@ -1086,6 +1086,77 @@ "homepage": "https://github.com/firebase/php-jwt", "install-path": "../firebase/php-jwt" }, + { + "name": "graham-campbell/result-type", + "version": "v1.1.0", + "version_normalized": "1.1.0.0", + "source": { + "type": "git", + "url": "https://github.com/GrahamCampbell/Result-Type.git", + "reference": "a878d45c1914464426dc94da61c9e1d36ae262a8" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/GrahamCampbell/Result-Type/zipball/a878d45c1914464426dc94da61c9e1d36ae262a8", + "reference": "a878d45c1914464426dc94da61c9e1d36ae262a8", + "shasum": "", + "mirrors": [ + { + "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%", + "preferred": true + } + ] + }, + "require": { + "php": "^7.2.5 || ^8.0", + "phpoption/phpoption": "^1.9" + }, + "require-dev": { + "phpunit/phpunit": "^8.5.28 || ^9.5.21" + }, + "time": "2022-07-30T15:56:11+00:00", + "type": "library", + "installation-source": "dist", + "autoload": { + "psr-4": { + "GrahamCampbell\\ResultType\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Graham Campbell", + "email": "hello@gjcampbell.co.uk", + "homepage": "https://github.com/GrahamCampbell" + } + ], + "description": "An Implementation Of The Result Type", + "keywords": [ + "Graham Campbell", + "GrahamCampbell", + "Result Type", + "Result-Type", + "result" + ], + "support": { + "issues": "https://github.com/GrahamCampbell/Result-Type/issues", + "source": "https://github.com/GrahamCampbell/Result-Type/tree/v1.1.0" + }, + "funding": [ + { + "url": "https://github.com/GrahamCampbell", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/graham-campbell/result-type", + "type": "tidelift" + } + ], + "install-path": "../graham-campbell/result-type" + }, { "name": "gregwar/captcha", "version": "v1.1.8", @@ -2977,6 +3048,90 @@ ], "install-path": "../phpoffice/phpspreadsheet" }, + { + "name": "phpoption/phpoption", + "version": "1.9.1", + "version_normalized": "1.9.1.0", + "source": { + "type": "git", + "url": "https://github.com/schmittjoh/php-option.git", + "reference": "dd3a383e599f49777d8b628dadbb90cae435b87e" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/schmittjoh/php-option/zipball/dd3a383e599f49777d8b628dadbb90cae435b87e", + "reference": "dd3a383e599f49777d8b628dadbb90cae435b87e", + "shasum": "", + "mirrors": [ + { + "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%", + "preferred": true + } + ] + }, + "require": { + "php": "^7.2.5 || ^8.0" + }, + "require-dev": { + "bamarni/composer-bin-plugin": "^1.8.2", + "phpunit/phpunit": "^8.5.32 || ^9.6.3 || ^10.0.12" + }, + "time": "2023-02-25T19:38:58+00:00", + "type": "library", + "extra": { + "bamarni-bin": { + "bin-links": true, + "forward-command": true + }, + "branch-alias": { + "dev-master": "1.9-dev" + } + }, + "installation-source": "dist", + "autoload": { + "psr-4": { + "PhpOption\\": "src/PhpOption/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "Apache-2.0" + ], + "authors": [ + { + "name": "Johannes M. Schmitt", + "email": "schmittjoh@gmail.com", + "homepage": "https://github.com/schmittjoh" + }, + { + "name": "Graham Campbell", + "email": "hello@gjcampbell.co.uk", + "homepage": "https://github.com/GrahamCampbell" + } + ], + "description": "Option Type for PHP", + "keywords": [ + "language", + "option", + "php", + "type" + ], + "support": { + "issues": "https://github.com/schmittjoh/php-option/issues", + "source": "https://github.com/schmittjoh/php-option/tree/1.9.1" + }, + "funding": [ + { + "url": "https://github.com/GrahamCampbell", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/phpoption/phpoption", + "type": "tidelift" + } + ], + "install-path": "../phpoption/phpoption" + }, { "name": "pimple/pimple", "version": "v3.3.0", @@ -5674,6 +5829,95 @@ }, "install-path": "../ucloud/ufile-php-sdk" }, + { + "name": "vlucas/phpdotenv", + "version": "v5.3.0", + "version_normalized": "5.3.0.0", + "source": { + "type": "git", + "url": "https://github.com/vlucas/phpdotenv.git", + "reference": "b3eac5c7ac896e52deab4a99068e3f4ab12d9e56" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/vlucas/phpdotenv/zipball/b3eac5c7ac896e52deab4a99068e3f4ab12d9e56", + "reference": "b3eac5c7ac896e52deab4a99068e3f4ab12d9e56", + "shasum": "", + "mirrors": [ + { + "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%", + "preferred": true + } + ] + }, + "require": { + "ext-pcre": "*", + "graham-campbell/result-type": "^1.0.1", + "php": "^7.1.3 || ^8.0", + "phpoption/phpoption": "^1.7.4", + "symfony/polyfill-ctype": "^1.17", + "symfony/polyfill-mbstring": "^1.17", + "symfony/polyfill-php80": "^1.17" + }, + "require-dev": { + "bamarni/composer-bin-plugin": "^1.4.1", + "ext-filter": "*", + "phpunit/phpunit": "^7.5.20 || ^8.5.14 || ^9.5.1" + }, + "suggest": { + "ext-filter": "Required to use the boolean validator." + }, + "time": "2021-01-20T15:23:13+00:00", + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "5.3-dev" + } + }, + "installation-source": "dist", + "autoload": { + "psr-4": { + "Dotenv\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Graham Campbell", + "email": "graham@alt-three.com", + "homepage": "https://gjcampbell.co.uk/" + }, + { + "name": "Vance Lucas", + "email": "vance@vancelucas.com", + "homepage": "https://vancelucas.com/" + } + ], + "description": "Loads environment variables from `.env` to `getenv()`, `$_ENV` and `$_SERVER` automagically.", + "keywords": [ + "dotenv", + "env", + "environment" + ], + "support": { + "issues": "https://github.com/vlucas/phpdotenv/issues", + "source": "https://github.com/vlucas/phpdotenv/tree/v5.3.0" + }, + "funding": [ + { + "url": "https://github.com/GrahamCampbell", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/vlucas/phpdotenv", + "type": "tidelift" + } + ], + "install-path": "../vlucas/phpdotenv" + }, { "name": "xaboy/form-builder", "version": "2.0.15", diff --git a/vendor/composer/installed.php b/vendor/composer/installed.php index ff26d7ea..029a03d9 100644 --- a/vendor/composer/installed.php +++ b/vendor/composer/installed.php @@ -1,9 +1,9 @@ array( 'name' => 'topthink/think', - 'pretty_version' => '1.0.0+no-version-set', - 'version' => '1.0.0.0', - 'reference' => NULL, + 'pretty_version' => 'dev-master', + 'version' => 'dev-master', + 'reference' => '9ff9e05d922b426d2829e28386114e1d19ba5adb', 'type' => 'project', 'install_path' => __DIR__ . '/../../', 'aliases' => array(), @@ -172,6 +172,15 @@ 'aliases' => array(), 'dev_requirement' => false, ), + 'graham-campbell/result-type' => array( + 'pretty_version' => 'v1.1.0', + 'version' => '1.1.0.0', + 'reference' => 'a878d45c1914464426dc94da61c9e1d36ae262a8', + 'type' => 'library', + 'install_path' => __DIR__ . '/../graham-campbell/result-type', + 'aliases' => array(), + 'dev_requirement' => false, + ), 'gregwar/captcha' => array( 'pretty_version' => 'v1.1.8', 'version' => '1.1.8.0', @@ -538,6 +547,15 @@ 'aliases' => array(), 'dev_requirement' => false, ), + 'phpoption/phpoption' => array( + 'pretty_version' => '1.9.1', + 'version' => '1.9.1.0', + 'reference' => 'dd3a383e599f49777d8b628dadbb90cae435b87e', + 'type' => 'library', + 'install_path' => __DIR__ . '/../phpoption/phpoption', + 'aliases' => array(), + 'dev_requirement' => false, + ), 'pimple/pimple' => array( 'pretty_version' => 'v3.3.0', 'version' => '3.3.0.0', @@ -863,9 +881,9 @@ 'dev_requirement' => false, ), 'topthink/think' => array( - 'pretty_version' => '1.0.0+no-version-set', - 'version' => '1.0.0.0', - 'reference' => NULL, + 'pretty_version' => 'dev-master', + 'version' => 'dev-master', + 'reference' => '9ff9e05d922b426d2829e28386114e1d19ba5adb', 'type' => 'project', 'install_path' => __DIR__ . '/../../', 'aliases' => array(), @@ -943,6 +961,15 @@ 'aliases' => array(), 'dev_requirement' => false, ), + 'vlucas/phpdotenv' => array( + 'pretty_version' => 'v5.3.0', + 'version' => '5.3.0.0', + 'reference' => 'b3eac5c7ac896e52deab4a99068e3f4ab12d9e56', + 'type' => 'library', + 'install_path' => __DIR__ . '/../vlucas/phpdotenv', + 'aliases' => array(), + 'dev_requirement' => false, + ), 'xaboy/form-builder' => array( 'pretty_version' => '2.0.15', 'version' => '2.0.15.0', diff --git a/vendor/graham-campbell/result-type/LICENSE b/vendor/graham-campbell/result-type/LICENSE new file mode 100644 index 00000000..9a8accb9 --- /dev/null +++ b/vendor/graham-campbell/result-type/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2020-2022 Graham Campbell + +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. diff --git a/vendor/graham-campbell/result-type/composer.json b/vendor/graham-campbell/result-type/composer.json new file mode 100644 index 00000000..f85e1d13 --- /dev/null +++ b/vendor/graham-campbell/result-type/composer.json @@ -0,0 +1,33 @@ +{ + "name": "graham-campbell/result-type", + "description": "An Implementation Of The Result Type", + "keywords": ["result", "result-type", "Result", "Result Type", "Result-Type", "Graham Campbell", "GrahamCampbell"], + "license": "MIT", + "authors": [ + { + "name": "Graham Campbell", + "email": "hello@gjcampbell.co.uk", + "homepage": "https://github.com/GrahamCampbell" + } + ], + "require": { + "php": "^7.2.5 || ^8.0", + "phpoption/phpoption": "^1.9" + }, + "require-dev": { + "phpunit/phpunit": "^8.5.28 || ^9.5.21" + }, + "autoload": { + "psr-4": { + "GrahamCampbell\\ResultType\\": "src/" + } + }, + "autoload-dev": { + "psr-4": { + "GrahamCampbell\\Tests\\ResultType\\": "tests/" + } + }, + "config": { + "preferred-install": "dist" + } +} diff --git a/vendor/graham-campbell/result-type/src/Error.php b/vendor/graham-campbell/result-type/src/Error.php new file mode 100644 index 00000000..add9b2d7 --- /dev/null +++ b/vendor/graham-campbell/result-type/src/Error.php @@ -0,0 +1,120 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace GrahamCampbell\ResultType; + +use PhpOption\None; +use PhpOption\Some; + +/** + * @template T + * @template E + * @extends \GrahamCampbell\ResultType\Result + */ +final class Error extends Result +{ + /** + * @var E + */ + private $value; + + /** + * Internal constructor for an error value. + * + * @param E $value + * + * @return void + */ + private function __construct($value) + { + $this->value = $value; + } + + /** + * Create a new error value. + * + * @template F + * + * @param F $value + * + * @return \GrahamCampbell\ResultType\Result + */ + public static function create($value) + { + return new self($value); + } + + /** + * Get the success option value. + * + * @return \PhpOption\Option + */ + public function success() + { + return None::create(); + } + + /** + * Map over the success value. + * + * @template S + * + * @param callable(T):S $f + * + * @return \GrahamCampbell\ResultType\Result + */ + public function map(callable $f) + { + return self::create($this->value); + } + + /** + * Flat map over the success value. + * + * @template S + * @template F + * + * @param callable(T):\GrahamCampbell\ResultType\Result $f + * + * @return \GrahamCampbell\ResultType\Result + */ + public function flatMap(callable $f) + { + /** @var \GrahamCampbell\ResultType\Result */ + return self::create($this->value); + } + + /** + * Get the error option value. + * + * @return \PhpOption\Option + */ + public function error() + { + return Some::create($this->value); + } + + /** + * Map over the error value. + * + * @template F + * + * @param callable(E):F $f + * + * @return \GrahamCampbell\ResultType\Result + */ + public function mapError(callable $f) + { + return self::create($f($this->value)); + } +} diff --git a/vendor/graham-campbell/result-type/src/Result.php b/vendor/graham-campbell/result-type/src/Result.php new file mode 100644 index 00000000..8c67bcdd --- /dev/null +++ b/vendor/graham-campbell/result-type/src/Result.php @@ -0,0 +1,69 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace GrahamCampbell\ResultType; + +/** + * @template T + * @template E + */ +abstract class Result +{ + /** + * Get the success option value. + * + * @return \PhpOption\Option + */ + abstract public function success(); + + /** + * Map over the success value. + * + * @template S + * + * @param callable(T):S $f + * + * @return \GrahamCampbell\ResultType\Result + */ + abstract public function map(callable $f); + + /** + * Flat map over the success value. + * + * @template S + * @template F + * + * @param callable(T):\GrahamCampbell\ResultType\Result $f + * + * @return \GrahamCampbell\ResultType\Result + */ + abstract public function flatMap(callable $f); + + /** + * Get the error option value. + * + * @return \PhpOption\Option + */ + abstract public function error(); + + /** + * Map over the error value. + * + * @template F + * + * @param callable(E):F $f + * + * @return \GrahamCampbell\ResultType\Result + */ + abstract public function mapError(callable $f); +} diff --git a/vendor/graham-campbell/result-type/src/Success.php b/vendor/graham-campbell/result-type/src/Success.php new file mode 100644 index 00000000..b68ad57e --- /dev/null +++ b/vendor/graham-campbell/result-type/src/Success.php @@ -0,0 +1,119 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace GrahamCampbell\ResultType; + +use PhpOption\None; +use PhpOption\Some; + +/** + * @template T + * @template E + * @extends \GrahamCampbell\ResultType\Result + */ +final class Success extends Result +{ + /** + * @var T + */ + private $value; + + /** + * Internal constructor for a success value. + * + * @param T $value + * + * @return void + */ + private function __construct($value) + { + $this->value = $value; + } + + /** + * Create a new error value. + * + * @template S + * + * @param S $value + * + * @return \GrahamCampbell\ResultType\Result + */ + public static function create($value) + { + return new self($value); + } + + /** + * Get the success option value. + * + * @return \PhpOption\Option + */ + public function success() + { + return Some::create($this->value); + } + + /** + * Map over the success value. + * + * @template S + * + * @param callable(T):S $f + * + * @return \GrahamCampbell\ResultType\Result + */ + public function map(callable $f) + { + return self::create($f($this->value)); + } + + /** + * Flat map over the success value. + * + * @template S + * @template F + * + * @param callable(T):\GrahamCampbell\ResultType\Result $f + * + * @return \GrahamCampbell\ResultType\Result + */ + public function flatMap(callable $f) + { + return $f($this->value); + } + + /** + * Get the error option value. + * + * @return \PhpOption\Option + */ + public function error() + { + return None::create(); + } + + /** + * Map over the error value. + * + * @template F + * + * @param callable(E):F $f + * + * @return \GrahamCampbell\ResultType\Result + */ + public function mapError(callable $f) + { + return self::create($this->value); + } +} diff --git a/vendor/phpoption/phpoption/LICENSE b/vendor/phpoption/phpoption/LICENSE new file mode 100644 index 00000000..f49a4e16 --- /dev/null +++ b/vendor/phpoption/phpoption/LICENSE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. \ No newline at end of file diff --git a/vendor/phpoption/phpoption/composer.json b/vendor/phpoption/phpoption/composer.json new file mode 100644 index 00000000..82a83005 --- /dev/null +++ b/vendor/phpoption/phpoption/composer.json @@ -0,0 +1,52 @@ +{ + "name": "phpoption/phpoption", + "description": "Option Type for PHP", + "keywords": ["php", "option", "language", "type"], + "license": "Apache-2.0", + "authors": [ + { + "name": "Johannes M. Schmitt", + "email": "schmittjoh@gmail.com", + "homepage": "https://github.com/schmittjoh" + }, + { + "name": "Graham Campbell", + "email": "hello@gjcampbell.co.uk", + "homepage": "https://github.com/GrahamCampbell" + } + ], + "require": { + "php": "^7.2.5 || ^8.0" + }, + "require-dev": { + "bamarni/composer-bin-plugin": "^1.8.2", + "phpunit/phpunit": "^8.5.32 || ^9.6.3 || ^10.0.12" + }, + "autoload": { + "psr-4": { + "PhpOption\\": "src/PhpOption/" + } + }, + "autoload-dev": { + "psr-4": { + "PhpOption\\Tests\\": "tests/PhpOption/Tests/" + } + }, + "config": { + "allow-plugins": { + "bamarni/composer-bin-plugin": true + }, + "preferred-install": "dist" + }, + "extra": { + "bamarni-bin": { + "bin-links": true, + "forward-command": true + }, + "branch-alias": { + "dev-master": "1.9-dev" + } + }, + "minimum-stability": "dev", + "prefer-stable": true +} diff --git a/vendor/phpoption/phpoption/src/PhpOption/LazyOption.php b/vendor/phpoption/phpoption/src/PhpOption/LazyOption.php new file mode 100644 index 00000000..9cb77c86 --- /dev/null +++ b/vendor/phpoption/phpoption/src/PhpOption/LazyOption.php @@ -0,0 +1,175 @@ + + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +namespace PhpOption; + +use Traversable; + +/** + * @template T + * + * @extends Option + */ +final class LazyOption extends Option +{ + /** @var callable(mixed...):(Option) */ + private $callback; + + /** @var array */ + private $arguments; + + /** @var Option|null */ + private $option; + + /** + * @template S + * @param callable(mixed...):(Option) $callback + * @param array $arguments + * + * @return LazyOption + */ + public static function create($callback, array $arguments = []): self + { + return new self($callback, $arguments); + } + + /** + * @param callable(mixed...):(Option) $callback + * @param array $arguments + */ + public function __construct($callback, array $arguments = []) + { + if (!is_callable($callback)) { + throw new \InvalidArgumentException('Invalid callback given'); + } + + $this->callback = $callback; + $this->arguments = $arguments; + } + + public function isDefined(): bool + { + return $this->option()->isDefined(); + } + + public function isEmpty(): bool + { + return $this->option()->isEmpty(); + } + + public function get() + { + return $this->option()->get(); + } + + public function getOrElse($default) + { + return $this->option()->getOrElse($default); + } + + public function getOrCall($callable) + { + return $this->option()->getOrCall($callable); + } + + public function getOrThrow(\Exception $ex) + { + return $this->option()->getOrThrow($ex); + } + + public function orElse(Option $else) + { + return $this->option()->orElse($else); + } + + public function ifDefined($callable) + { + $this->option()->forAll($callable); + } + + public function forAll($callable) + { + return $this->option()->forAll($callable); + } + + public function map($callable) + { + return $this->option()->map($callable); + } + + public function flatMap($callable) + { + return $this->option()->flatMap($callable); + } + + public function filter($callable) + { + return $this->option()->filter($callable); + } + + public function filterNot($callable) + { + return $this->option()->filterNot($callable); + } + + public function select($value) + { + return $this->option()->select($value); + } + + public function reject($value) + { + return $this->option()->reject($value); + } + + /** + * @return Traversable + */ + public function getIterator(): Traversable + { + return $this->option()->getIterator(); + } + + public function foldLeft($initialValue, $callable) + { + return $this->option()->foldLeft($initialValue, $callable); + } + + public function foldRight($initialValue, $callable) + { + return $this->option()->foldRight($initialValue, $callable); + } + + /** + * @return Option + */ + private function option(): Option + { + if (null === $this->option) { + /** @var mixed */ + $option = call_user_func_array($this->callback, $this->arguments); + if ($option instanceof Option) { + $this->option = $option; + } else { + throw new \RuntimeException(sprintf('Expected instance of %s', Option::class)); + } + } + + return $this->option; + } +} diff --git a/vendor/phpoption/phpoption/src/PhpOption/None.php b/vendor/phpoption/phpoption/src/PhpOption/None.php new file mode 100644 index 00000000..4b85d22d --- /dev/null +++ b/vendor/phpoption/phpoption/src/PhpOption/None.php @@ -0,0 +1,136 @@ + + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +namespace PhpOption; + +use EmptyIterator; + +/** + * @extends Option + */ +final class None extends Option +{ + /** @var None|null */ + private static $instance; + + /** + * @return None + */ + public static function create(): self + { + if (null === self::$instance) { + self::$instance = new self(); + } + + return self::$instance; + } + + public function get() + { + throw new \RuntimeException('None has no value.'); + } + + public function getOrCall($callable) + { + return $callable(); + } + + public function getOrElse($default) + { + return $default; + } + + public function getOrThrow(\Exception $ex) + { + throw $ex; + } + + public function isEmpty(): bool + { + return true; + } + + public function isDefined(): bool + { + return false; + } + + public function orElse(Option $else) + { + return $else; + } + + public function ifDefined($callable) + { + // Just do nothing in that case. + } + + public function forAll($callable) + { + return $this; + } + + public function map($callable) + { + return $this; + } + + public function flatMap($callable) + { + return $this; + } + + public function filter($callable) + { + return $this; + } + + public function filterNot($callable) + { + return $this; + } + + public function select($value) + { + return $this; + } + + public function reject($value) + { + return $this; + } + + public function getIterator(): EmptyIterator + { + return new EmptyIterator(); + } + + public function foldLeft($initialValue, $callable) + { + return $initialValue; + } + + public function foldRight($initialValue, $callable) + { + return $initialValue; + } + + private function __construct() + { + } +} diff --git a/vendor/phpoption/phpoption/src/PhpOption/Option.php b/vendor/phpoption/phpoption/src/PhpOption/Option.php new file mode 100644 index 00000000..172924cf --- /dev/null +++ b/vendor/phpoption/phpoption/src/PhpOption/Option.php @@ -0,0 +1,434 @@ + + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +namespace PhpOption; + +use ArrayAccess; +use IteratorAggregate; + +/** + * @template T + * + * @implements IteratorAggregate + */ +abstract class Option implements IteratorAggregate +{ + /** + * Creates an option given a return value. + * + * This is intended for consuming existing APIs and allows you to easily + * convert them to an option. By default, we treat ``null`` as the None + * case, and everything else as Some. + * + * @template S + * + * @param S $value The actual return value. + * @param S $noneValue The value which should be considered "None"; null by + * default. + * + * @return Option + */ + public static function fromValue($value, $noneValue = null) + { + if ($value === $noneValue) { + return None::create(); + } + + return new Some($value); + } + + /** + * Creates an option from an array's value. + * + * If the key does not exist in the array, the array is not actually an + * array, or the array's value at the given key is null, None is returned. + * Otherwise, Some is returned wrapping the value at the given key. + * + * @template S + * + * @param array|ArrayAccess|null $array A potential array or \ArrayAccess value. + * @param string $key The key to check. + * + * @return Option + */ + public static function fromArraysValue($array, $key) + { + if (!(is_array($array) || $array instanceof ArrayAccess) || !isset($array[$key])) { + return None::create(); + } + + return new Some($array[$key]); + } + + /** + * Creates a lazy-option with the given callback. + * + * This is also a helper constructor for lazy-consuming existing APIs where + * the return value is not yet an option. By default, we treat ``null`` as + * None case, and everything else as Some. + * + * @template S + * + * @param callable $callback The callback to evaluate. + * @param array $arguments The arguments for the callback. + * @param S $noneValue The value which should be considered "None"; + * null by default. + * + * @return LazyOption + */ + public static function fromReturn($callback, array $arguments = [], $noneValue = null) + { + return new LazyOption(static function () use ($callback, $arguments, $noneValue) { + /** @var mixed */ + $return = call_user_func_array($callback, $arguments); + + if ($return === $noneValue) { + return None::create(); + } + + return new Some($return); + }); + } + + /** + * Option factory, which creates new option based on passed value. + * + * If value is already an option, it simply returns. If value is callable, + * LazyOption with passed callback created and returned. If Option + * returned from callback, it returns directly. On other case value passed + * to Option::fromValue() method. + * + * @template S + * + * @param Option|callable|S $value + * @param S $noneValue Used when $value is mixed or + * callable, for None-check. + * + * @return Option|LazyOption + */ + public static function ensure($value, $noneValue = null) + { + if ($value instanceof self) { + return $value; + } elseif (is_callable($value)) { + return new LazyOption(static function () use ($value, $noneValue) { + /** @var mixed */ + $return = $value(); + + if ($return instanceof self) { + return $return; + } else { + return self::fromValue($return, $noneValue); + } + }); + } else { + return self::fromValue($value, $noneValue); + } + } + + /** + * Lift a function so that it accepts Option as parameters. + * + * We return a new closure that wraps the original callback. If any of the + * parameters passed to the lifted function is empty, the function will + * return a value of None. Otherwise, we will pass all parameters to the + * original callback and return the value inside a new Option, unless an + * Option is returned from the function, in which case, we use that. + * + * @template S + * + * @param callable $callback + * @param mixed $noneValue + * + * @return callable + */ + public static function lift($callback, $noneValue = null) + { + return static function () use ($callback, $noneValue) { + /** @var array */ + $args = func_get_args(); + + $reduced_args = array_reduce( + $args, + /** @param bool $status */ + static function ($status, self $o) { + return $o->isEmpty() ? true : $status; + }, + false + ); + // if at least one parameter is empty, return None + if ($reduced_args) { + return None::create(); + } + + $args = array_map( + /** @return T */ + static function (self $o) { + // it is safe to do so because the fold above checked + // that all arguments are of type Some + /** @var T */ + return $o->get(); + }, + $args + ); + + return self::ensure(call_user_func_array($callback, $args), $noneValue); + }; + } + + /** + * Returns the value if available, or throws an exception otherwise. + * + * @throws \RuntimeException If value is not available. + * + * @return T + */ + abstract public function get(); + + /** + * Returns the value if available, or the default value if not. + * + * @template S + * + * @param S $default + * + * @return T|S + */ + abstract public function getOrElse($default); + + /** + * Returns the value if available, or the results of the callable. + * + * This is preferable over ``getOrElse`` if the computation of the default + * value is expensive. + * + * @template S + * + * @param callable():S $callable + * + * @return T|S + */ + abstract public function getOrCall($callable); + + /** + * Returns the value if available, or throws the passed exception. + * + * @param \Exception $ex + * + * @return T + */ + abstract public function getOrThrow(\Exception $ex); + + /** + * Returns true if no value is available, false otherwise. + * + * @return bool + */ + abstract public function isEmpty(); + + /** + * Returns true if a value is available, false otherwise. + * + * @return bool + */ + abstract public function isDefined(); + + /** + * Returns this option if non-empty, or the passed option otherwise. + * + * This can be used to try multiple alternatives, and is especially useful + * with lazy evaluating options: + * + * ```php + * $repo->findSomething() + * ->orElse(new LazyOption(array($repo, 'findSomethingElse'))) + * ->orElse(new LazyOption(array($repo, 'createSomething'))); + * ``` + * + * @param Option $else + * + * @return Option + */ + abstract public function orElse(self $else); + + /** + * This is similar to map() below except that the return value has no meaning; + * the passed callable is simply executed if the option is non-empty, and + * ignored if the option is empty. + * + * In all cases, the return value of the callable is discarded. + * + * ```php + * $comment->getMaybeFile()->ifDefined(function($file) { + * // Do something with $file here. + * }); + * ``` + * + * If you're looking for something like ``ifEmpty``, you can use ``getOrCall`` + * and ``getOrElse`` in these cases. + * + * @deprecated Use forAll() instead. + * + * @param callable(T):mixed $callable + * + * @return void + */ + abstract public function ifDefined($callable); + + /** + * This is similar to map() except that the return value of the callable has no meaning. + * + * The passed callable is simply executed if the option is non-empty, and ignored if the + * option is empty. This method is preferred for callables with side-effects, while map() + * is intended for callables without side-effects. + * + * @param callable(T):mixed $callable + * + * @return Option + */ + abstract public function forAll($callable); + + /** + * Applies the callable to the value of the option if it is non-empty, + * and returns the return value of the callable wrapped in Some(). + * + * If the option is empty, then the callable is not applied. + * + * ```php + * (new Some("foo"))->map('strtoupper')->get(); // "FOO" + * ``` + * + * @template S + * + * @param callable(T):S $callable + * + * @return Option + */ + abstract public function map($callable); + + /** + * Applies the callable to the value of the option if it is non-empty, and + * returns the return value of the callable directly. + * + * In contrast to ``map``, the return value of the callable is expected to + * be an Option itself; it is not automatically wrapped in Some(). + * + * @template S + * + * @param callable(T):Option $callable must return an Option + * + * @return Option + */ + abstract public function flatMap($callable); + + /** + * If the option is empty, it is returned immediately without applying the callable. + * + * If the option is non-empty, the callable is applied, and if it returns true, + * the option itself is returned; otherwise, None is returned. + * + * @param callable(T):bool $callable + * + * @return Option + */ + abstract public function filter($callable); + + /** + * If the option is empty, it is returned immediately without applying the callable. + * + * If the option is non-empty, the callable is applied, and if it returns false, + * the option itself is returned; otherwise, None is returned. + * + * @param callable(T):bool $callable + * + * @return Option + */ + abstract public function filterNot($callable); + + /** + * If the option is empty, it is returned immediately. + * + * If the option is non-empty, and its value does not equal the passed value + * (via a shallow comparison ===), then None is returned. Otherwise, the + * Option is returned. + * + * In other words, this will filter all but the passed value. + * + * @param T $value + * + * @return Option + */ + abstract public function select($value); + + /** + * If the option is empty, it is returned immediately. + * + * If the option is non-empty, and its value does equal the passed value (via + * a shallow comparison ===), then None is returned; otherwise, the Option is + * returned. + * + * In other words, this will let all values through except the passed value. + * + * @param T $value + * + * @return Option + */ + abstract public function reject($value); + + /** + * Binary operator for the initial value and the option's value. + * + * If empty, the initial value is returned. If non-empty, the callable + * receives the initial value and the option's value as arguments. + * + * ```php + * + * $some = new Some(5); + * $none = None::create(); + * $result = $some->foldLeft(1, function($a, $b) { return $a + $b; }); // int(6) + * $result = $none->foldLeft(1, function($a, $b) { return $a + $b; }); // int(1) + * + * // This can be used instead of something like the following: + * $option = Option::fromValue($integerOrNull); + * $result = 1; + * if ( ! $option->isEmpty()) { + * $result += $option->get(); + * } + * ``` + * + * @template S + * + * @param S $initialValue + * @param callable(S, T):S $callable + * + * @return S + */ + abstract public function foldLeft($initialValue, $callable); + + /** + * foldLeft() but with reversed arguments for the callable. + * + * @template S + * + * @param S $initialValue + * @param callable(T, S):S $callable + * + * @return S + */ + abstract public function foldRight($initialValue, $callable); +} diff --git a/vendor/phpoption/phpoption/src/PhpOption/Some.php b/vendor/phpoption/phpoption/src/PhpOption/Some.php new file mode 100644 index 00000000..032632ea --- /dev/null +++ b/vendor/phpoption/phpoption/src/PhpOption/Some.php @@ -0,0 +1,169 @@ + + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +namespace PhpOption; + +use ArrayIterator; + +/** + * @template T + * + * @extends Option + */ +final class Some extends Option +{ + /** @var T */ + private $value; + + /** + * @param T $value + */ + public function __construct($value) + { + $this->value = $value; + } + + /** + * @template U + * + * @param U $value + * + * @return Some + */ + public static function create($value): self + { + return new self($value); + } + + public function isDefined(): bool + { + return true; + } + + public function isEmpty(): bool + { + return false; + } + + public function get() + { + return $this->value; + } + + public function getOrElse($default) + { + return $this->value; + } + + public function getOrCall($callable) + { + return $this->value; + } + + public function getOrThrow(\Exception $ex) + { + return $this->value; + } + + public function orElse(Option $else) + { + return $this; + } + + public function ifDefined($callable) + { + $this->forAll($callable); + } + + public function forAll($callable) + { + $callable($this->value); + + return $this; + } + + public function map($callable) + { + return new self($callable($this->value)); + } + + public function flatMap($callable) + { + /** @var mixed */ + $rs = $callable($this->value); + if (!$rs instanceof Option) { + throw new \RuntimeException('Callables passed to flatMap() must return an Option. Maybe you should use map() instead?'); + } + + return $rs; + } + + public function filter($callable) + { + if (true === $callable($this->value)) { + return $this; + } + + return None::create(); + } + + public function filterNot($callable) + { + if (false === $callable($this->value)) { + return $this; + } + + return None::create(); + } + + public function select($value) + { + if ($this->value === $value) { + return $this; + } + + return None::create(); + } + + public function reject($value) + { + if ($this->value === $value) { + return None::create(); + } + + return $this; + } + + /** + * @return ArrayIterator + */ + public function getIterator(): ArrayIterator + { + return new ArrayIterator([$this->value]); + } + + public function foldLeft($initialValue, $callable) + { + return $callable($initialValue, $this->value); + } + + public function foldRight($initialValue, $callable) + { + return $callable($this->value, $initialValue); + } +} diff --git a/vendor/services.php b/vendor/services.php index f6c0cbf0..84cae3e4 100644 --- a/vendor/services.php +++ b/vendor/services.php @@ -1,5 +1,5 @@ 'think\\queue\\Service', diff --git a/vendor/vlucas/phpdotenv/LICENSE b/vendor/vlucas/phpdotenv/LICENSE new file mode 100644 index 00000000..922c5522 --- /dev/null +++ b/vendor/vlucas/phpdotenv/LICENSE @@ -0,0 +1,30 @@ +BSD 3-Clause License + +Copyright (c) 2014, Graham Campbell. +Copyright (c) 2013, Vance Lucas. +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +3. Neither the name of the copyright holder nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/vendor/vlucas/phpdotenv/composer.json b/vendor/vlucas/phpdotenv/composer.json new file mode 100644 index 00000000..d7a1e8c4 --- /dev/null +++ b/vendor/vlucas/phpdotenv/composer.json @@ -0,0 +1,53 @@ +{ + "name": "vlucas/phpdotenv", + "description": "Loads environment variables from `.env` to `getenv()`, `$_ENV` and `$_SERVER` automagically.", + "keywords": ["env", "dotenv", "environment"], + "license": "BSD-3-Clause", + "authors": [ + { + "name": "Graham Campbell", + "email": "graham@alt-three.com", + "homepage": "https://gjcampbell.co.uk/" + }, + { + "name": "Vance Lucas", + "email": "vance@vancelucas.com", + "homepage": "https://vancelucas.com/" + } + ], + "require": { + "php": "^7.1.3 || ^8.0", + "ext-pcre": "*", + "graham-campbell/result-type": "^1.0.1", + "phpoption/phpoption": "^1.7.4", + "symfony/polyfill-ctype": "^1.17", + "symfony/polyfill-mbstring": "^1.17", + "symfony/polyfill-php80": "^1.17" + }, + "require-dev": { + "ext-filter": "*", + "bamarni/composer-bin-plugin": "^1.4.1", + "phpunit/phpunit": "^7.5.20 || ^8.5.14 || ^9.5.1" + }, + "autoload": { + "psr-4": { + "Dotenv\\": "src/" + } + }, + "autoload-dev": { + "psr-4": { + "Dotenv\\Tests\\": "tests/Dotenv/" + } + }, + "suggest": { + "ext-filter": "Required to use the boolean validator." + }, + "config": { + "preferred-install": "dist" + }, + "extra": { + "branch-alias": { + "dev-master": "5.3-dev" + } + } +} diff --git a/vendor/vlucas/phpdotenv/src/Dotenv.php b/vendor/vlucas/phpdotenv/src/Dotenv.php new file mode 100644 index 00000000..0460ced2 --- /dev/null +++ b/vendor/vlucas/phpdotenv/src/Dotenv.php @@ -0,0 +1,267 @@ +store = $store; + $this->parser = $parser; + $this->loader = $loader; + $this->repository = $repository; + } + + /** + * Create a new dotenv instance. + * + * @param \Dotenv\Repository\RepositoryInterface $repository + * @param string|string[] $paths + * @param string|string[]|null $names + * @param bool $shortCircuit + * @param string|null $fileEncoding + * + * @return \Dotenv\Dotenv + */ + public static function create(RepositoryInterface $repository, $paths, $names = null, bool $shortCircuit = true, string $fileEncoding = null) + { + $builder = $names === null ? StoreBuilder::createWithDefaultName() : StoreBuilder::createWithNoNames(); + + foreach ((array) $paths as $path) { + $builder = $builder->addPath($path); + } + + foreach ((array) $names as $name) { + $builder = $builder->addName($name); + } + + if ($shortCircuit) { + $builder = $builder->shortCircuit(); + } + + return new self($builder->fileEncoding($fileEncoding)->make(), new Parser(), new Loader(), $repository); + } + + /** + * Create a new mutable dotenv instance with default repository. + * + * @param string|string[] $paths + * @param string|string[]|null $names + * @param bool $shortCircuit + * @param string|null $fileEncoding + * + * @return \Dotenv\Dotenv + */ + public static function createMutable($paths, $names = null, bool $shortCircuit = true, string $fileEncoding = null) + { + $repository = RepositoryBuilder::createWithDefaultAdapters()->make(); + + return self::create($repository, $paths, $names, $shortCircuit, $fileEncoding); + } + + /** + * Create a new mutable dotenv instance with default repository with the putenv adapter. + * + * @param string|string[] $paths + * @param string|string[]|null $names + * @param bool $shortCircuit + * @param string|null $fileEncoding + * + * @return \Dotenv\Dotenv + */ + public static function createUnsafeMutable($paths, $names = null, bool $shortCircuit = true, string $fileEncoding = null) + { + $repository = RepositoryBuilder::createWithDefaultAdapters() + ->addAdapter(PutenvAdapter::class) + ->make(); + + return self::create($repository, $paths, $names, $shortCircuit, $fileEncoding); + } + + /** + * Create a new immutable dotenv instance with default repository. + * + * @param string|string[] $paths + * @param string|string[]|null $names + * @param bool $shortCircuit + * @param string|null $fileEncoding + * + * @return \Dotenv\Dotenv + */ + public static function createImmutable($paths, $names = null, bool $shortCircuit = true, string $fileEncoding = null) + { + $repository = RepositoryBuilder::createWithDefaultAdapters()->immutable()->make(); + + return self::create($repository, $paths, $names, $shortCircuit, $fileEncoding); + } + + /** + * Create a new immutable dotenv instance with default repository with the putenv adapter. + * + * @param string|string[] $paths + * @param string|string[]|null $names + * @param bool $shortCircuit + * @param string|null $fileEncoding + * + * @return \Dotenv\Dotenv + */ + public static function createUnsafeImmutable($paths, $names = null, bool $shortCircuit = true, string $fileEncoding = null) + { + $repository = RepositoryBuilder::createWithDefaultAdapters() + ->addAdapter(PutenvAdapter::class) + ->immutable() + ->make(); + + return self::create($repository, $paths, $names, $shortCircuit, $fileEncoding); + } + + /** + * Create a new dotenv instance with an array backed repository. + * + * @param string|string[] $paths + * @param string|string[]|null $names + * @param bool $shortCircuit + * @param string|null $fileEncoding + * + * @return \Dotenv\Dotenv + */ + public static function createArrayBacked($paths, $names = null, bool $shortCircuit = true, string $fileEncoding = null) + { + $repository = RepositoryBuilder::createWithNoAdapters()->addAdapter(ArrayAdapter::class)->make(); + + return self::create($repository, $paths, $names, $shortCircuit, $fileEncoding); + } + + /** + * Parse the given content and resolve nested variables. + * + * This method behaves just like load(), only without mutating your actual + * environment. We do this by using an array backed repository. + * + * @param string $content + * + * @throws \Dotenv\Exception\InvalidFileException + * + * @return array + */ + public static function parse(string $content) + { + $repository = RepositoryBuilder::createWithNoAdapters()->addAdapter(ArrayAdapter::class)->make(); + + $phpdotenv = new self(new StringStore($content), new Parser(), new Loader(), $repository); + + return $phpdotenv->load(); + } + + /** + * Read and load environment file(s). + * + * @throws \Dotenv\Exception\InvalidPathException|\Dotenv\Exception\InvalidEncodingException|\Dotenv\Exception\InvalidFileException + * + * @return array + */ + public function load() + { + $entries = $this->parser->parse($this->store->read()); + + return $this->loader->load($this->repository, $entries); + } + + /** + * Read and load environment file(s), silently failing if no files can be read. + * + * @throws \Dotenv\Exception\InvalidEncodingException|\Dotenv\Exception\InvalidFileException + * + * @return array + */ + public function safeLoad() + { + try { + return $this->load(); + } catch (InvalidPathException $e) { + // suppressing exception + return []; + } + } + + /** + * Required ensures that the specified variables exist, and returns a new validator object. + * + * @param string|string[] $variables + * + * @return \Dotenv\Validator + */ + public function required($variables) + { + return (new Validator($this->repository, (array) $variables))->required(); + } + + /** + * Returns a new validator object that won't check if the specified variables exist. + * + * @param string|string[] $variables + * + * @return \Dotenv\Validator + */ + public function ifPresent($variables) + { + return new Validator($this->repository, (array) $variables); + } +} diff --git a/vendor/vlucas/phpdotenv/src/Exception/ExceptionInterface.php b/vendor/vlucas/phpdotenv/src/Exception/ExceptionInterface.php new file mode 100644 index 00000000..1e80f531 --- /dev/null +++ b/vendor/vlucas/phpdotenv/src/Exception/ExceptionInterface.php @@ -0,0 +1,12 @@ + + */ + public function load(RepositoryInterface $repository, array $entries) + { + return \array_reduce($entries, static function (array $vars, Entry $entry) use ($repository) { + $name = $entry->getName(); + + $value = $entry->getValue()->map(static function (Value $value) use ($repository) { + return Resolver::resolve($repository, $value); + }); + + if ($value->isDefined()) { + $inner = $value->get(); + if ($repository->set($name, $inner)) { + return \array_merge($vars, [$name => $inner]); + } + } else { + if ($repository->clear($name)) { + return \array_merge($vars, [$name => null]); + } + } + + return $vars; + }, []); + } +} diff --git a/vendor/vlucas/phpdotenv/src/Loader/LoaderInterface.php b/vendor/vlucas/phpdotenv/src/Loader/LoaderInterface.php new file mode 100644 index 00000000..275d98e8 --- /dev/null +++ b/vendor/vlucas/phpdotenv/src/Loader/LoaderInterface.php @@ -0,0 +1,20 @@ + + */ + public function load(RepositoryInterface $repository, array $entries); +} diff --git a/vendor/vlucas/phpdotenv/src/Loader/Resolver.php b/vendor/vlucas/phpdotenv/src/Loader/Resolver.php new file mode 100644 index 00000000..36d7a4b9 --- /dev/null +++ b/vendor/vlucas/phpdotenv/src/Loader/Resolver.php @@ -0,0 +1,65 @@ +getVars(), static function (string $s, int $i) use ($repository) { + return Str::substr($s, 0, $i).self::resolveVariable($repository, Str::substr($s, $i)); + }, $value->getChars()); + } + + /** + * Resolve a single nested variable. + * + * @param \Dotenv\Repository\RepositoryInterface $repository + * @param string $str + * + * @return string + */ + private static function resolveVariable(RepositoryInterface $repository, string $str) + { + return Regex::replaceCallback( + '/\A\${([a-zA-Z0-9_.]+)}/', + static function (array $matches) use ($repository) { + return Option::fromValue($repository->get($matches[1])) + ->getOrElse($matches[0]); + }, + $str, + 1 + )->success()->getOrElse($str); + } +} diff --git a/vendor/vlucas/phpdotenv/src/Parser/Entry.php b/vendor/vlucas/phpdotenv/src/Parser/Entry.php new file mode 100644 index 00000000..7570f587 --- /dev/null +++ b/vendor/vlucas/phpdotenv/src/Parser/Entry.php @@ -0,0 +1,59 @@ +name = $name; + $this->value = $value; + } + + /** + * Get the entry name. + * + * @return string + */ + public function getName() + { + return $this->name; + } + + /** + * Get the entry value. + * + * @return \PhpOption\Option<\Dotenv\Parser\Value> + */ + public function getValue() + { + /** @var \PhpOption\Option<\Dotenv\Parser\Value> */ + return Option::fromValue($this->value); + } +} diff --git a/vendor/vlucas/phpdotenv/src/Parser/EntryParser.php b/vendor/vlucas/phpdotenv/src/Parser/EntryParser.php new file mode 100644 index 00000000..5cfa3eef --- /dev/null +++ b/vendor/vlucas/phpdotenv/src/Parser/EntryParser.php @@ -0,0 +1,293 @@ + + */ + public static function parse(string $entry) + { + return self::splitStringIntoParts($entry)->flatMap(static function (array $parts) { + [$name, $value] = $parts; + + return self::parseName($name)->flatMap(static function (string $name) use ($value) { + /** @var Result */ + $parsedValue = $value === null ? Success::create(null) : self::parseValue($value); + + return $parsedValue->map(static function (?Value $value) use ($name) { + return new Entry($name, $value); + }); + }); + }); + } + + /** + * Split the compound string into parts. + * + * @param string $line + * + * @return \GrahamCampbell\ResultType\Result + */ + private static function splitStringIntoParts(string $line) + { + /** @var array{string,string|null} */ + $result = Str::pos($line, '=')->map(static function () use ($line) { + return \array_map('trim', \explode('=', $line, 2)); + })->getOrElse([$line, null]); + + if ($result[0] === '') { + return Error::create(self::getErrorMessage('an unexpected equals', $line)); + } + + /** @var \GrahamCampbell\ResultType\Result */ + return Success::create($result); + } + + /** + * Parse the given variable name. + * + * That is, strip the optional quotes and leading "export" from the + * variable name. We wrap the answer in a result type. + * + * @param string $name + * + * @return \GrahamCampbell\ResultType\Result + */ + private static function parseName(string $name) + { + if (Str::len($name) > 8 && Str::substr($name, 0, 6) === 'export' && \ctype_space(Str::substr($name, 6, 1))) { + $name = \ltrim(Str::substr($name, 6)); + } + + if (self::isQuotedName($name)) { + $name = Str::substr($name, 1, -1); + } + + if (!self::isValidName($name)) { + return Error::create(self::getErrorMessage('an invalid name', $name)); + } + + return Success::create($name); + } + + /** + * Is the given variable name quoted? + * + * @param string $name + * + * @return bool + */ + private static function isQuotedName(string $name) + { + if (Str::len($name) < 3) { + return false; + } + + $first = Str::substr($name, 0, 1); + $last = Str::substr($name, -1, 1); + + return ($first === '"' && $last === '"') || ($first === '\'' && $last === '\''); + } + + /** + * Is the given variable name valid? + * + * @param string $name + * + * @return bool + */ + private static function isValidName(string $name) + { + return Regex::matches('~\A[a-zA-Z0-9_.]+\z~', $name)->success()->getOrElse(false); + } + + /** + * Parse the given variable value. + * + * This has the effect of stripping quotes and comments, dealing with + * special characters, and locating nested variables, but not resolving + * them. Formally, we run a finite state automaton with an output tape: a + * transducer. We wrap the answer in a result type. + * + * @param string $value + * + * @return \GrahamCampbell\ResultType\Result<\Dotenv\Parser\Value,string> + */ + private static function parseValue(string $value) + { + if (\trim($value) === '') { + return Success::create(Value::blank()); + } + + return \array_reduce(\iterator_to_array(Lexer::lex($value)), static function (Result $data, string $token) { + return $data->flatMap(static function (array $data) use ($token) { + return self::processToken($data[1], $token)->map(static function (array $val) use ($data) { + return [$data[0]->append($val[0], $val[1]), $val[2]]; + }); + }); + }, Success::create([Value::blank(), self::INITIAL_STATE]))->flatMap(static function (array $result) { + if (in_array($result[1], self::REJECT_STATES, true)) { + return Error::create('a missing closing quote'); + } + + return Success::create($result[0]); + })->mapError(static function (string $err) use ($value) { + return self::getErrorMessage($err, $value); + }); + } + + /** + * Process the given token. + * + * @param int $state + * @param string $token + * + * @return \GrahamCampbell\ResultType\Result + */ + private static function processToken(int $state, string $token) + { + switch ($state) { + case self::INITIAL_STATE: + if ($token === '\'') { + /** @var \GrahamCampbell\ResultType\Result */ + return Success::create(['', false, self::SINGLE_QUOTED_STATE]); + } elseif ($token === '"') { + /** @var \GrahamCampbell\ResultType\Result */ + return Success::create(['', false, self::DOUBLE_QUOTED_STATE]); + } elseif ($token === '#') { + /** @var \GrahamCampbell\ResultType\Result */ + return Success::create(['', false, self::COMMENT_STATE]); + } elseif ($token === '$') { + /** @var \GrahamCampbell\ResultType\Result */ + return Success::create([$token, true, self::UNQUOTED_STATE]); + } else { + /** @var \GrahamCampbell\ResultType\Result */ + return Success::create([$token, false, self::UNQUOTED_STATE]); + } + case self::UNQUOTED_STATE: + if ($token === '#') { + /** @var \GrahamCampbell\ResultType\Result */ + return Success::create(['', false, self::COMMENT_STATE]); + } elseif (\ctype_space($token)) { + /** @var \GrahamCampbell\ResultType\Result */ + return Success::create(['', false, self::WHITESPACE_STATE]); + } elseif ($token === '$') { + /** @var \GrahamCampbell\ResultType\Result */ + return Success::create([$token, true, self::UNQUOTED_STATE]); + } else { + /** @var \GrahamCampbell\ResultType\Result */ + return Success::create([$token, false, self::UNQUOTED_STATE]); + } + case self::SINGLE_QUOTED_STATE: + if ($token === '\'') { + /** @var \GrahamCampbell\ResultType\Result */ + return Success::create(['', false, self::WHITESPACE_STATE]); + } else { + /** @var \GrahamCampbell\ResultType\Result */ + return Success::create([$token, false, self::SINGLE_QUOTED_STATE]); + } + case self::DOUBLE_QUOTED_STATE: + if ($token === '"') { + /** @var \GrahamCampbell\ResultType\Result */ + return Success::create(['', false, self::WHITESPACE_STATE]); + } elseif ($token === '\\') { + /** @var \GrahamCampbell\ResultType\Result */ + return Success::create(['', false, self::ESCAPE_SEQUENCE_STATE]); + } elseif ($token === '$') { + /** @var \GrahamCampbell\ResultType\Result */ + return Success::create([$token, true, self::DOUBLE_QUOTED_STATE]); + } else { + /** @var \GrahamCampbell\ResultType\Result */ + return Success::create([$token, false, self::DOUBLE_QUOTED_STATE]); + } + case self::ESCAPE_SEQUENCE_STATE: + if ($token === '"' || $token === '\\') { + /** @var \GrahamCampbell\ResultType\Result */ + return Success::create([$token, false, self::DOUBLE_QUOTED_STATE]); + } elseif ($token === '$') { + /** @var \GrahamCampbell\ResultType\Result */ + return Success::create([$token, false, self::DOUBLE_QUOTED_STATE]); + } else { + $first = Str::substr($token, 0, 1); + if (\in_array($first, ['f', 'n', 'r', 't', 'v'], true)) { + /** @var \GrahamCampbell\ResultType\Result */ + return Success::create([\stripcslashes('\\'.$first).Str::substr($token, 1), false, self::DOUBLE_QUOTED_STATE]); + } else { + /** @var \GrahamCampbell\ResultType\Result */ + return Error::create('an unexpected escape sequence'); + } + } + case self::WHITESPACE_STATE: + if ($token === '#') { + /** @var \GrahamCampbell\ResultType\Result */ + return Success::create(['', false, self::COMMENT_STATE]); + } elseif (!\ctype_space($token)) { + /** @var \GrahamCampbell\ResultType\Result */ + return Error::create('unexpected whitespace'); + } else { + /** @var \GrahamCampbell\ResultType\Result */ + return Success::create(['', false, self::WHITESPACE_STATE]); + } + case self::COMMENT_STATE: + /** @var \GrahamCampbell\ResultType\Result */ + return Success::create(['', false, self::COMMENT_STATE]); + default: + throw new \Error('Parser entered invalid state.'); + } + } + + /** + * Generate a friendly error message. + * + * @param string $cause + * @param string $subject + * + * @return string + */ + private static function getErrorMessage(string $cause, string $subject) + { + return \sprintf( + 'Encountered %s at [%s].', + $cause, + \strtok($subject, "\n") + ); + } +} diff --git a/vendor/vlucas/phpdotenv/src/Parser/Lexer.php b/vendor/vlucas/phpdotenv/src/Parser/Lexer.php new file mode 100644 index 00000000..c5eb64d3 --- /dev/null +++ b/vendor/vlucas/phpdotenv/src/Parser/Lexer.php @@ -0,0 +1,62 @@ + + */ + public static function lex(string $content) + { + static $regex; + + if ($regex === null) { + $regex = '(('.\implode(')|(', self::PATTERNS).'))A'; + } + + $tokens = []; + + $offset = 0; + + while (isset($content[$offset])) { + if (!\preg_match($regex, $content, $matches, 0, $offset)) { + throw new \Error(\sprintf('Lexer encountered unexpected character [%s].', $content[$offset])); + } + + $offset += \strlen($matches[0]); + + yield $matches[0]; + } + } +} diff --git a/vendor/vlucas/phpdotenv/src/Parser/Lines.php b/vendor/vlucas/phpdotenv/src/Parser/Lines.php new file mode 100644 index 00000000..38397947 --- /dev/null +++ b/vendor/vlucas/phpdotenv/src/Parser/Lines.php @@ -0,0 +1,125 @@ +map(static function () use ($line) { + return self::looksLikeMultilineStop($line, true) === false; + })->getOrElse(false); + } + + /** + * Determine if the given line can be the start of a multiline variable. + * + * @param string $line + * @param bool $started + * + * @return bool + */ + private static function looksLikeMultilineStop(string $line, bool $started) + { + if ($line === '"') { + return true; + } + + return Regex::occurences('/(?=([^\\\\]"))/', \str_replace('\\\\', '', $line))->map(static function (int $count) use ($started) { + return $started ? $count > 1 : $count >= 1; + })->success()->getOrElse(false); + } + + /** + * Determine if the line in the file is a comment or whitespace. + * + * @param string $line + * + * @return bool + */ + private static function isCommentOrWhitespace(string $line) + { + $line = \trim($line); + + return $line === '' || (isset($line[0]) && $line[0] === '#'); + } +} diff --git a/vendor/vlucas/phpdotenv/src/Parser/Parser.php b/vendor/vlucas/phpdotenv/src/Parser/Parser.php new file mode 100644 index 00000000..3c115e55 --- /dev/null +++ b/vendor/vlucas/phpdotenv/src/Parser/Parser.php @@ -0,0 +1,52 @@ +mapError(static function () { + return 'Could not split into separate lines.'; + })->flatMap(static function (array $lines) { + return self::process(Lines::process($lines)); + })->mapError(static function (string $error) { + throw new InvalidFileException(\sprintf('Failed to parse dotenv file. %s', $error)); + })->success()->get(); + } + + /** + * Convert the raw entries into proper entries. + * + * @param string[] $entries + * + * @return \GrahamCampbell\ResultType\Result<\Dotenv\Parser\Entry[],string> + */ + private static function process(array $entries) + { + /** @var \GrahamCampbell\ResultType\Result<\Dotenv\Parser\Entry[],string> */ + return \array_reduce($entries, static function (Result $result, string $raw) { + return $result->flatMap(static function (array $entries) use ($raw) { + return EntryParser::parse($raw)->map(static function (Entry $entry) use ($entries) { + return \array_merge($entries, [$entry]); + }); + }); + }, Success::create([])); + } +} diff --git a/vendor/vlucas/phpdotenv/src/Parser/ParserInterface.php b/vendor/vlucas/phpdotenv/src/Parser/ParserInterface.php new file mode 100644 index 00000000..17cc42ad --- /dev/null +++ b/vendor/vlucas/phpdotenv/src/Parser/ParserInterface.php @@ -0,0 +1,19 @@ +chars = $chars; + $this->vars = $vars; + } + + /** + * Create an empty value instance. + * + * @return \Dotenv\Parser\Value + */ + public static function blank() + { + return new self('', []); + } + + /** + * Create a new value instance, appending the characters. + * + * @param string $chars + * @param bool $var + * + * @return \Dotenv\Parser\Value + */ + public function append(string $chars, bool $var) + { + return new self( + $this->chars.$chars, + $var ? \array_merge($this->vars, [Str::len($this->chars)]) : $this->vars + ); + } + + /** + * Get the string representation of the parsed value. + * + * @return string + */ + public function getChars() + { + return $this->chars; + } + + /** + * Get the locations of the variables in the value. + * + * @return int[] + */ + public function getVars() + { + $vars = $this->vars; + + \rsort($vars); + + return $vars; + } +} diff --git a/vendor/vlucas/phpdotenv/src/Repository/Adapter/AdapterInterface.php b/vendor/vlucas/phpdotenv/src/Repository/Adapter/AdapterInterface.php new file mode 100644 index 00000000..5604398a --- /dev/null +++ b/vendor/vlucas/phpdotenv/src/Repository/Adapter/AdapterInterface.php @@ -0,0 +1,15 @@ + + */ + public static function create(); +} diff --git a/vendor/vlucas/phpdotenv/src/Repository/Adapter/ApacheAdapter.php b/vendor/vlucas/phpdotenv/src/Repository/Adapter/ApacheAdapter.php new file mode 100644 index 00000000..868033af --- /dev/null +++ b/vendor/vlucas/phpdotenv/src/Repository/Adapter/ApacheAdapter.php @@ -0,0 +1,89 @@ + + */ + public static function create() + { + if (self::isSupported()) { + /** @var \PhpOption\Option */ + return Some::create(new self()); + } + + return None::create(); + } + + /** + * Determines if the adapter is supported. + * + * This happens if PHP is running as an Apache module. + * + * @return bool + */ + private static function isSupported() + { + return \function_exists('apache_getenv') && \function_exists('apache_setenv'); + } + + /** + * Read an environment variable, if it exists. + * + * @param string $name + * + * @return \PhpOption\Option + */ + public function read(string $name) + { + /** @var \PhpOption\Option */ + return Option::fromValue(apache_getenv($name))->filter(static function ($value) { + return \is_string($value) && $value !== ''; + }); + } + + /** + * Write to an environment variable, if possible. + * + * @param string $name + * @param string $value + * + * @return bool + */ + public function write(string $name, string $value) + { + return apache_setenv($name, $value); + } + + /** + * Delete an environment variable, if possible. + * + * @param string $name + * + * @return bool + */ + public function delete(string $name) + { + return apache_setenv($name, ''); + } +} diff --git a/vendor/vlucas/phpdotenv/src/Repository/Adapter/ArrayAdapter.php b/vendor/vlucas/phpdotenv/src/Repository/Adapter/ArrayAdapter.php new file mode 100644 index 00000000..2881a7e1 --- /dev/null +++ b/vendor/vlucas/phpdotenv/src/Repository/Adapter/ArrayAdapter.php @@ -0,0 +1,80 @@ + + */ + private $variables; + + /** + * Create a new array adapter instance. + * + * @return void + */ + private function __construct() + { + $this->variables = []; + } + + /** + * Create a new instance of the adapter, if it is available. + * + * @return \PhpOption\Option<\Dotenv\Repository\Adapter\AdapterInterface> + */ + public static function create() + { + /** @var \PhpOption\Option */ + return Some::create(new self()); + } + + /** + * Read an environment variable, if it exists. + * + * @param string $name + * + * @return \PhpOption\Option + */ + public function read(string $name) + { + return Option::fromArraysValue($this->variables, $name); + } + + /** + * Write to an environment variable, if possible. + * + * @param string $name + * @param string $value + * + * @return bool + */ + public function write(string $name, string $value) + { + $this->variables[$name] = $value; + + return true; + } + + /** + * Delete an environment variable, if possible. + * + * @param string $name + * + * @return bool + */ + public function delete(string $name) + { + unset($this->variables[$name]); + + return true; + } +} diff --git a/vendor/vlucas/phpdotenv/src/Repository/Adapter/EnvConstAdapter.php b/vendor/vlucas/phpdotenv/src/Repository/Adapter/EnvConstAdapter.php new file mode 100644 index 00000000..9ef7fb4d --- /dev/null +++ b/vendor/vlucas/phpdotenv/src/Repository/Adapter/EnvConstAdapter.php @@ -0,0 +1,87 @@ + + */ + public static function create() + { + /** @var \PhpOption\Option */ + return Some::create(new self()); + } + + /** + * Read an environment variable, if it exists. + * + * @param string $name + * + * @return \PhpOption\Option + */ + public function read(string $name) + { + /** @var \PhpOption\Option */ + return Option::fromArraysValue($_ENV, $name) + ->map(static function ($value) { + if ($value === false) { + return 'false'; + } + + if ($value === true) { + return 'true'; + } + + return $value; + })->filter(static function ($value) { + return \is_string($value); + }); + } + + /** + * Write to an environment variable, if possible. + * + * @param string $name + * @param string $value + * + * @return bool + */ + public function write(string $name, string $value) + { + $_ENV[$name] = $value; + + return true; + } + + /** + * Delete an environment variable, if possible. + * + * @param string $name + * + * @return bool + */ + public function delete(string $name) + { + unset($_ENV[$name]); + + return true; + } +} diff --git a/vendor/vlucas/phpdotenv/src/Repository/Adapter/GuardedWriter.php b/vendor/vlucas/phpdotenv/src/Repository/Adapter/GuardedWriter.php new file mode 100644 index 00000000..7bb69e82 --- /dev/null +++ b/vendor/vlucas/phpdotenv/src/Repository/Adapter/GuardedWriter.php @@ -0,0 +1,85 @@ +writer = $writer; + $this->allowList = $allowList; + } + + /** + * Write to an environment variable, if possible. + * + * @param string $name + * @param string $value + * + * @return bool + */ + public function write(string $name, string $value) + { + // Don't set non-allowed variables + if (!$this->isAllowed($name)) { + return false; + } + + // Set the value on the inner writer + return $this->writer->write($name, $value); + } + + /** + * Delete an environment variable, if possible. + * + * @param string $name + * + * @return bool + */ + public function delete(string $name) + { + // Don't clear non-allowed variables + if (!$this->isAllowed($name)) { + return false; + } + + // Set the value on the inner writer + return $this->writer->delete($name); + } + + /** + * Determine if the given variable is allowed. + * + * @param string $name + * + * @return bool + */ + private function isAllowed(string $name) + { + return \in_array($name, $this->allowList, true); + } +} diff --git a/vendor/vlucas/phpdotenv/src/Repository/Adapter/ImmutableWriter.php b/vendor/vlucas/phpdotenv/src/Repository/Adapter/ImmutableWriter.php new file mode 100644 index 00000000..574fcd69 --- /dev/null +++ b/vendor/vlucas/phpdotenv/src/Repository/Adapter/ImmutableWriter.php @@ -0,0 +1,110 @@ + + */ + private $loaded; + + /** + * Create a new immutable writer instance. + * + * @param \Dotenv\Repository\Adapter\WriterInterface $writer + * @param \Dotenv\Repository\Adapter\ReaderInterface $reader + * + * @return void + */ + public function __construct(WriterInterface $writer, ReaderInterface $reader) + { + $this->writer = $writer; + $this->reader = $reader; + $this->loaded = []; + } + + /** + * Write to an environment variable, if possible. + * + * @param string $name + * @param string $value + * + * @return bool + */ + public function write(string $name, string $value) + { + // Don't overwrite existing environment variables + // Ruby's dotenv does this with `ENV[key] ||= value` + if ($this->isExternallyDefined($name)) { + return false; + } + + // Set the value on the inner writer + if (!$this->writer->write($name, $value)) { + return false; + } + + // Record that we have loaded the variable + $this->loaded[$name] = ''; + + return true; + } + + /** + * Delete an environment variable, if possible. + * + * @param string $name + * + * @return bool + */ + public function delete(string $name) + { + // Don't clear existing environment variables + if ($this->isExternallyDefined($name)) { + return false; + } + + // Clear the value on the inner writer + if (!$this->writer->delete($name)) { + return false; + } + + // Leave the variable as fair game + unset($this->loaded[$name]); + + return true; + } + + /** + * Determine if the given variable is externally defined. + * + * That is, is it an "existing" variable. + * + * @param string $name + * + * @return bool + */ + private function isExternallyDefined(string $name) + { + return $this->reader->read($name)->isDefined() && !isset($this->loaded[$name]); + } +} diff --git a/vendor/vlucas/phpdotenv/src/Repository/Adapter/MultiReader.php b/vendor/vlucas/phpdotenv/src/Repository/Adapter/MultiReader.php new file mode 100644 index 00000000..12b3bda4 --- /dev/null +++ b/vendor/vlucas/phpdotenv/src/Repository/Adapter/MultiReader.php @@ -0,0 +1,48 @@ +readers = $readers; + } + + /** + * Read an environment variable, if it exists. + * + * @param string $name + * + * @return \PhpOption\Option + */ + public function read(string $name) + { + foreach ($this->readers as $reader) { + $result = $reader->read($name); + if ($result->isDefined()) { + return $result; + } + } + + return None::create(); + } +} diff --git a/vendor/vlucas/phpdotenv/src/Repository/Adapter/MultiWriter.php b/vendor/vlucas/phpdotenv/src/Repository/Adapter/MultiWriter.php new file mode 100644 index 00000000..e1dcf56b --- /dev/null +++ b/vendor/vlucas/phpdotenv/src/Repository/Adapter/MultiWriter.php @@ -0,0 +1,64 @@ +writers = $writers; + } + + /** + * Write to an environment variable, if possible. + * + * @param string $name + * @param string $value + * + * @return bool + */ + public function write(string $name, string $value) + { + foreach ($this->writers as $writers) { + if (!$writers->write($name, $value)) { + return false; + } + } + + return true; + } + + /** + * Delete an environment variable, if possible. + * + * @param string $name + * + * @return bool + */ + public function delete(string $name) + { + foreach ($this->writers as $writers) { + if (!$writers->delete($name)) { + return false; + } + } + + return true; + } +} diff --git a/vendor/vlucas/phpdotenv/src/Repository/Adapter/PutenvAdapter.php b/vendor/vlucas/phpdotenv/src/Repository/Adapter/PutenvAdapter.php new file mode 100644 index 00000000..126c4656 --- /dev/null +++ b/vendor/vlucas/phpdotenv/src/Repository/Adapter/PutenvAdapter.php @@ -0,0 +1,91 @@ + + */ + public static function create() + { + if (self::isSupported()) { + /** @var \PhpOption\Option */ + return Some::create(new self()); + } + + return None::create(); + } + + /** + * Determines if the adapter is supported. + * + * @return bool + */ + private static function isSupported() + { + return \function_exists('getenv') && \function_exists('putenv'); + } + + /** + * Read an environment variable, if it exists. + * + * @param string $name + * + * @return \PhpOption\Option + */ + public function read(string $name) + { + /** @var \PhpOption\Option */ + return Option::fromValue(\getenv($name), false)->filter(static function ($value) { + return \is_string($value); + }); + } + + /** + * Write to an environment variable, if possible. + * + * @param string $name + * @param string $value + * + * @return bool + */ + public function write(string $name, string $value) + { + \putenv("$name=$value"); + + return true; + } + + /** + * Delete an environment variable, if possible. + * + * @param string $name + * + * @return bool + */ + public function delete(string $name) + { + \putenv($name); + + return true; + } +} diff --git a/vendor/vlucas/phpdotenv/src/Repository/Adapter/ReaderInterface.php b/vendor/vlucas/phpdotenv/src/Repository/Adapter/ReaderInterface.php new file mode 100644 index 00000000..5ece5ee7 --- /dev/null +++ b/vendor/vlucas/phpdotenv/src/Repository/Adapter/ReaderInterface.php @@ -0,0 +1,17 @@ + + */ + public function read(string $name); +} diff --git a/vendor/vlucas/phpdotenv/src/Repository/Adapter/ReplacingWriter.php b/vendor/vlucas/phpdotenv/src/Repository/Adapter/ReplacingWriter.php new file mode 100644 index 00000000..326cd187 --- /dev/null +++ b/vendor/vlucas/phpdotenv/src/Repository/Adapter/ReplacingWriter.php @@ -0,0 +1,104 @@ + + */ + private $seen; + + /** + * Create a new replacement writer instance. + * + * @param \Dotenv\Repository\Adapter\WriterInterface $writer + * @param \Dotenv\Repository\Adapter\ReaderInterface $reader + * + * @return void + */ + public function __construct(WriterInterface $writer, ReaderInterface $reader) + { + $this->writer = $writer; + $this->reader = $reader; + $this->seen = []; + } + + /** + * Write to an environment variable, if possible. + * + * @param string $name + * @param string $value + * + * @return bool + */ + public function write(string $name, string $value) + { + if ($this->exists($name)) { + return $this->writer->write($name, $value); + } + + // succeed if nothing to do + return true; + } + + /** + * Delete an environment variable, if possible. + * + * @param string $name + * + * @return bool + */ + public function delete(string $name) + { + if ($this->exists($name)) { + return $this->writer->delete($name); + } + + // succeed if nothing to do + return true; + } + + /** + * Does the given environment variable exist. + * + * Returns true if it currently exists, or existed at any point in the past + * that we are aware of. + * + * @param string $name + * + * @return bool + */ + private function exists(string $name) + { + if (isset($this->seen[$name])) { + return true; + } + + if ($this->reader->read($name)->isDefined()) { + $this->seen[$name] = ''; + + return true; + } + + return false; + } +} diff --git a/vendor/vlucas/phpdotenv/src/Repository/Adapter/ServerConstAdapter.php b/vendor/vlucas/phpdotenv/src/Repository/Adapter/ServerConstAdapter.php new file mode 100644 index 00000000..8e3dc98e --- /dev/null +++ b/vendor/vlucas/phpdotenv/src/Repository/Adapter/ServerConstAdapter.php @@ -0,0 +1,87 @@ + + */ + public static function create() + { + /** @var \PhpOption\Option */ + return Some::create(new self()); + } + + /** + * Read an environment variable, if it exists. + * + * @param string $name + * + * @return \PhpOption\Option + */ + public function read(string $name) + { + /** @var \PhpOption\Option */ + return Option::fromArraysValue($_SERVER, $name) + ->map(static function ($value) { + if ($value === false) { + return 'false'; + } + + if ($value === true) { + return 'true'; + } + + return $value; + })->filter(static function ($value) { + return \is_string($value); + }); + } + + /** + * Write to an environment variable, if possible. + * + * @param string $name + * @param string $value + * + * @return bool + */ + public function write(string $name, string $value) + { + $_SERVER[$name] = $value; + + return true; + } + + /** + * Delete an environment variable, if possible. + * + * @param string $name + * + * @return bool + */ + public function delete(string $name) + { + unset($_SERVER[$name]); + + return true; + } +} diff --git a/vendor/vlucas/phpdotenv/src/Repository/Adapter/WriterInterface.php b/vendor/vlucas/phpdotenv/src/Repository/Adapter/WriterInterface.php new file mode 100644 index 00000000..8b3fa577 --- /dev/null +++ b/vendor/vlucas/phpdotenv/src/Repository/Adapter/WriterInterface.php @@ -0,0 +1,27 @@ +reader = $reader; + $this->writer = $writer; + } + + /** + * Determine if the given environment variable is defined. + * + * @param string $name + * + * @return bool + */ + public function has(string $name) + { + return $this->reader->read($name)->isDefined(); + } + + /** + * Get an environment variable. + * + * @param string $name + * + * @return string|null + */ + public function get(string $name) + { + return $this->reader->read($name)->getOrElse(null); + } + + /** + * Set an environment variable. + * + * @param string $name + * @param string $value + * + * @return bool + */ + public function set(string $name, string $value) + { + return $this->writer->write($name, $value); + } + + /** + * Clear an environment variable. + * + * @param string $name + * + * @return bool + */ + public function clear(string $name) + { + return $this->writer->delete($name); + } +} diff --git a/vendor/vlucas/phpdotenv/src/Repository/RepositoryBuilder.php b/vendor/vlucas/phpdotenv/src/Repository/RepositoryBuilder.php new file mode 100644 index 00000000..f8a92644 --- /dev/null +++ b/vendor/vlucas/phpdotenv/src/Repository/RepositoryBuilder.php @@ -0,0 +1,274 @@ +readers = $readers; + $this->writers = $writers; + $this->immutable = $immutable; + $this->allowList = $allowList; + } + + /** + * Create a new repository builder instance with no adapters added. + * + * @return \Dotenv\Repository\RepositoryBuilder + */ + public static function createWithNoAdapters() + { + return new self(); + } + + /** + * Create a new repository builder instance with the default adapters added. + * + * @return \Dotenv\Repository\RepositoryBuilder + */ + public static function createWithDefaultAdapters() + { + $adapters = \iterator_to_array(self::defaultAdapters()); + + return new self($adapters, $adapters); + } + + /** + * Return the array of default adapters. + * + * @return \Generator<\Dotenv\Repository\Adapter\AdapterInterface> + */ + private static function defaultAdapters() + { + foreach (self::DEFAULT_ADAPTERS as $adapter) { + $instance = $adapter::create(); + if ($instance->isDefined()) { + yield $instance->get(); + } + } + } + + /** + * Determine if the given name if of an adapaterclass. + * + * @param string $name + * + * @return bool + */ + private static function isAnAdapterClass(string $name) + { + if (!\class_exists($name)) { + return false; + } + + return (new ReflectionClass($name))->implementsInterface(AdapterInterface::class); + } + + /** + * Creates a repository builder with the given reader added. + * + * Accepts either a reader instance, or a class-string for an adapter. If + * the adapter is not supported, then we silently skip adding it. + * + * @param \Dotenv\Repository\Adapter\ReaderInterface|string $reader + * + * @throws \InvalidArgumentException + * + * @return \Dotenv\Repository\RepositoryBuilder + */ + public function addReader($reader) + { + if (!(\is_string($reader) && self::isAnAdapterClass($reader)) && !($reader instanceof ReaderInterface)) { + throw new InvalidArgumentException( + \sprintf( + 'Expected either an instance of %s or a class-string implementing %s', + ReaderInterface::class, + AdapterInterface::class + ) + ); + } + + $optional = Some::create($reader)->flatMap(static function ($reader) { + return \is_string($reader) ? $reader::create() : Some::create($reader); + }); + + $readers = \array_merge($this->readers, \iterator_to_array($optional)); + + return new self($readers, $this->writers, $this->immutable, $this->allowList); + } + + /** + * Creates a repository builder with the given writer added. + * + * Accepts either a writer instance, or a class-string for an adapter. If + * the adapter is not supported, then we silently skip adding it. + * + * @param \Dotenv\Repository\Adapter\WriterInterface|string $writer + * + * @throws \InvalidArgumentException + * + * @return \Dotenv\Repository\RepositoryBuilder + */ + public function addWriter($writer) + { + if (!(\is_string($writer) && self::isAnAdapterClass($writer)) && !($writer instanceof WriterInterface)) { + throw new InvalidArgumentException( + \sprintf( + 'Expected either an instance of %s or a class-string implementing %s', + WriterInterface::class, + AdapterInterface::class + ) + ); + } + + $optional = Some::create($writer)->flatMap(static function ($writer) { + return \is_string($writer) ? $writer::create() : Some::create($writer); + }); + + $writers = \array_merge($this->writers, \iterator_to_array($optional)); + + return new self($this->readers, $writers, $this->immutable, $this->allowList); + } + + /** + * Creates a repository builder with the given adapter added. + * + * Accepts either an adapter instance, or a class-string for an adapter. If + * the adapter is not supported, then we silently skip adding it. We will + * add the adapter as both a reader and a writer. + * + * @param \Dotenv\Repository\Adapter\WriterInterface|string $adapter + * + * @throws \InvalidArgumentException + * + * @return \Dotenv\Repository\RepositoryBuilder + */ + public function addAdapter($adapter) + { + if (!(\is_string($adapter) && self::isAnAdapterClass($adapter)) && !($adapter instanceof AdapterInterface)) { + throw new InvalidArgumentException( + \sprintf( + 'Expected either an instance of %s or a class-string implementing %s', + WriterInterface::class, + AdapterInterface::class + ) + ); + } + + $optional = Some::create($adapter)->flatMap(static function ($adapter) { + return \is_string($adapter) ? $adapter::create() : Some::create($adapter); + }); + + $readers = \array_merge($this->readers, \iterator_to_array($optional)); + $writers = \array_merge($this->writers, \iterator_to_array($optional)); + + return new self($readers, $writers, $this->immutable, $this->allowList); + } + + /** + * Creates a repository builder with mutability enabled. + * + * @return \Dotenv\Repository\RepositoryBuilder + */ + public function immutable() + { + return new self($this->readers, $this->writers, true, $this->allowList); + } + + /** + * Creates a repository builder with the given allow list. + * + * @param string[]|null $allowList + * + * @return \Dotenv\Repository\RepositoryBuilder + */ + public function allowList(array $allowList = null) + { + return new self($this->readers, $this->writers, $this->immutable, $allowList); + } + + /** + * Creates a new repository instance. + * + * @return \Dotenv\Repository\RepositoryInterface + */ + public function make() + { + $reader = new MultiReader($this->readers); + $writer = new MultiWriter($this->writers); + + if ($this->immutable) { + $writer = new ImmutableWriter($writer, $reader); + } + + if ($this->allowList !== null) { + $writer = new GuardedWriter($writer, $this->allowList); + } + + return new AdapterRepository($reader, $writer); + } +} diff --git a/vendor/vlucas/phpdotenv/src/Repository/RepositoryInterface.php b/vendor/vlucas/phpdotenv/src/Repository/RepositoryInterface.php new file mode 100644 index 00000000..a2a7d32f --- /dev/null +++ b/vendor/vlucas/phpdotenv/src/Repository/RepositoryInterface.php @@ -0,0 +1,45 @@ + + */ + public static function read(array $filePaths, bool $shortCircuit = true, string $fileEncoding = null) + { + $output = []; + + foreach ($filePaths as $filePath) { + $content = self::readFromFile($filePath, $fileEncoding); + if ($content->isDefined()) { + $output[$filePath] = $content->get(); + if ($shortCircuit) { + break; + } + } + } + + return $output; + } + + /** + * Read the given file. + * + * @param string $path + * @param string|null $encoding + * + * @throws \Dotenv\Exception\InvalidEncodingException + * + * @return \PhpOption\Option + */ + private static function readFromFile(string $path, string $encoding = null) + { + /** @var Option */ + $content = Option::fromValue(@\file_get_contents($path), false); + + return $content->flatMap(static function (string $content) use ($encoding) { + return Str::utf8($content, $encoding)->mapError(static function (string $error) { + throw new InvalidEncodingException($error); + })->success(); + }); + } +} diff --git a/vendor/vlucas/phpdotenv/src/Store/FileStore.php b/vendor/vlucas/phpdotenv/src/Store/FileStore.php new file mode 100644 index 00000000..43f6135c --- /dev/null +++ b/vendor/vlucas/phpdotenv/src/Store/FileStore.php @@ -0,0 +1,72 @@ +filePaths = $filePaths; + $this->shortCircuit = $shortCircuit; + $this->fileEncoding = $fileEncoding; + } + + /** + * Read the content of the environment file(s). + * + * @throws \Dotenv\Exception\InvalidEncodingException|\Dotenv\Exception\InvalidPathException + * + * @return string + */ + public function read() + { + if ($this->filePaths === []) { + throw new InvalidPathException('At least one environment file path must be provided.'); + } + + $contents = Reader::read($this->filePaths, $this->shortCircuit, $this->fileEncoding); + + if (\count($contents) > 0) { + return \implode("\n", $contents); + } + + throw new InvalidPathException( + \sprintf('Unable to read any of the environment file(s) at [%s].', \implode(', ', $this->filePaths)) + ); + } +} diff --git a/vendor/vlucas/phpdotenv/src/Store/StoreBuilder.php b/vendor/vlucas/phpdotenv/src/Store/StoreBuilder.php new file mode 100644 index 00000000..d1fb26fb --- /dev/null +++ b/vendor/vlucas/phpdotenv/src/Store/StoreBuilder.php @@ -0,0 +1,143 @@ +paths = $paths; + $this->names = $names; + $this->shortCircuit = $shortCircuit; + $this->fileEncoding = $fileEncoding; + } + + /** + * Create a new store builder instance with no names. + * + * @return \Dotenv\Store\StoreBuilder + */ + public static function createWithNoNames() + { + return new self(); + } + + /** + * Create a new store builder instance with the default name. + * + * @return \Dotenv\Store\StoreBuilder + */ + public static function createWithDefaultName() + { + return new self([], [self::DEFAULT_NAME]); + } + + /** + * Creates a store builder with the given path added. + * + * @param string $path + * + * @return \Dotenv\Store\StoreBuilder + */ + public function addPath(string $path) + { + return new self(\array_merge($this->paths, [$path]), $this->names, $this->shortCircuit, $this->fileEncoding); + } + + /** + * Creates a store builder with the given name added. + * + * @param string $name + * + * @return \Dotenv\Store\StoreBuilder + */ + public function addName(string $name) + { + return new self($this->paths, \array_merge($this->names, [$name]), $this->shortCircuit, $this->fileEncoding); + } + + /** + * Creates a store builder with short circuit mode enabled. + * + * @return \Dotenv\Store\StoreBuilder + */ + public function shortCircuit() + { + return new self($this->paths, $this->names, true, $this->fileEncoding); + } + + /** + * Creates a store builder with the specified file encoding. + * + * @param string|null $fileEncoding + * + * @return \Dotenv\Store\StoreBuilder + */ + public function fileEncoding(string $fileEncoding = null) + { + return new self($this->paths, $this->names, $this->shortCircuit, $fileEncoding); + } + + /** + * Creates a new store instance. + * + * @return \Dotenv\Store\StoreInterface + */ + public function make() + { + return new FileStore( + Paths::filePaths($this->paths, $this->names), + $this->shortCircuit, + $this->fileEncoding + ); + } +} diff --git a/vendor/vlucas/phpdotenv/src/Store/StoreInterface.php b/vendor/vlucas/phpdotenv/src/Store/StoreInterface.php new file mode 100644 index 00000000..6f5b9862 --- /dev/null +++ b/vendor/vlucas/phpdotenv/src/Store/StoreInterface.php @@ -0,0 +1,17 @@ +content = $content; + } + + /** + * Read the content of the environment file(s). + * + * @return string + */ + public function read() + { + return $this->content; + } +} diff --git a/vendor/vlucas/phpdotenv/src/Util/Regex.php b/vendor/vlucas/phpdotenv/src/Util/Regex.php new file mode 100644 index 00000000..e558f407 --- /dev/null +++ b/vendor/vlucas/phpdotenv/src/Util/Regex.php @@ -0,0 +1,110 @@ + + */ + public static function matches(string $pattern, string $subject) + { + return self::pregAndWrap(static function (string $subject) use ($pattern) { + return @\preg_match($pattern, $subject) === 1; + }, $subject); + } + + /** + * Perform a preg match all, wrapping up the result. + * + * @param string $pattern + * @param string $subject + * + * @return \GrahamCampbell\ResultType\Result + */ + public static function occurences(string $pattern, string $subject) + { + return self::pregAndWrap(static function (string $subject) use ($pattern) { + return (int) @\preg_match_all($pattern, $subject); + }, $subject); + } + + /** + * Perform a preg replace callback, wrapping up the result. + * + * @param string $pattern + * @param callable $callback + * @param string $subject + * @param int|null $limit + * + * @return \GrahamCampbell\ResultType\Result + */ + public static function replaceCallback(string $pattern, callable $callback, string $subject, int $limit = null) + { + return self::pregAndWrap(static function (string $subject) use ($pattern, $callback, $limit) { + return (string) @\preg_replace_callback($pattern, $callback, $subject, $limit ?? -1); + }, $subject); + } + + /** + * Perform a preg split, wrapping up the result. + * + * @param string $pattern + * @param string $subject + * + * @return \GrahamCampbell\ResultType\Result + */ + public static function split(string $pattern, string $subject) + { + return self::pregAndWrap(static function (string $subject) use ($pattern) { + /** @var string[] */ + return (array) @\preg_split($pattern, $subject); + }, $subject); + } + + /** + * Perform a preg operation, wrapping up the result. + * + * @template V + * + * @param callable(string):V $operation + * @param string $subject + * + * @return \GrahamCampbell\ResultType\Result + */ + private static function pregAndWrap(callable $operation, string $subject) + { + $result = $operation($subject); + + if (\preg_last_error() !== \PREG_NO_ERROR) { + return Error::create(\preg_last_error_msg()); + } + + return Success::create($result); + } +} diff --git a/vendor/vlucas/phpdotenv/src/Util/Str.php b/vendor/vlucas/phpdotenv/src/Util/Str.php new file mode 100644 index 00000000..582c2144 --- /dev/null +++ b/vendor/vlucas/phpdotenv/src/Util/Str.php @@ -0,0 +1,90 @@ + + */ + public static function utf8(string $input, string $encoding = null) + { + if ($encoding !== null && !\in_array($encoding, \mb_list_encodings(), true)) { + /** @var \GrahamCampbell\ResultType\Result */ + return Error::create( + \sprintf('Illegal character encoding [%s] specified.', $encoding) + ); + } + + /** @var \GrahamCampbell\ResultType\Result */ + return Success::create( + $encoding === null ? @\mb_convert_encoding($input, 'UTF-8') : @\mb_convert_encoding($input, 'UTF-8', $encoding) + ); + } + + /** + * Search for a given substring of the input. + * + * @param string $haystack + * @param string $needle + * + * @return \PhpOption\Option + */ + public static function pos(string $haystack, string $needle) + { + /** @var \PhpOption\Option */ + return Option::fromValue(\mb_strpos($haystack, $needle, 0, 'UTF-8'), false); + } + + /** + * Grab the specified substring of the input. + * + * @param string $input + * @param int $start + * @param int|null $length + * + * @return string + */ + public static function substr(string $input, int $start, int $length = null) + { + return \mb_substr($input, $start, $length, 'UTF-8'); + } + + /** + * Compute the length of the given string. + * + * @param string $input + * + * @return int + */ + public static function len(string $input) + { + return \mb_strlen($input, 'UTF-8'); + } +} diff --git a/vendor/vlucas/phpdotenv/src/Validator.php b/vendor/vlucas/phpdotenv/src/Validator.php new file mode 100644 index 00000000..0c04ab62 --- /dev/null +++ b/vendor/vlucas/phpdotenv/src/Validator.php @@ -0,0 +1,209 @@ +repository = $repository; + $this->variables = $variables; + } + + /** + * Assert that each variable is present. + * + * @throws \Dotenv\Exception\ValidationException + * + * @return \Dotenv\Validator + */ + public function required() + { + return $this->assert( + static function (?string $value) { + return $value !== null; + }, + 'is missing' + ); + } + + /** + * Assert that each variable is not empty. + * + * @throws \Dotenv\Exception\ValidationException + * + * @return \Dotenv\Validator + */ + public function notEmpty() + { + return $this->assertNullable( + static function (string $value) { + return Str::len(\trim($value)) > 0; + }, + 'is empty' + ); + } + + /** + * Assert that each specified variable is an integer. + * + * @throws \Dotenv\Exception\ValidationException + * + * @return \Dotenv\Validator + */ + public function isInteger() + { + return $this->assertNullable( + static function (string $value) { + return \ctype_digit($value); + }, + 'is not an integer' + ); + } + + /** + * Assert that each specified variable is a boolean. + * + * @throws \Dotenv\Exception\ValidationException + * + * @return \Dotenv\Validator + */ + public function isBoolean() + { + return $this->assertNullable( + static function (string $value) { + if ($value === '') { + return false; + } + + return \filter_var($value, \FILTER_VALIDATE_BOOLEAN, \FILTER_NULL_ON_FAILURE) !== null; + }, + 'is not a boolean' + ); + } + + /** + * Assert that each variable is amongst the given choices. + * + * @param string[] $choices + * + * @throws \Dotenv\Exception\ValidationException + * + * @return \Dotenv\Validator + */ + public function allowedValues(array $choices) + { + return $this->assertNullable( + static function (string $value) use ($choices) { + return \in_array($value, $choices, true); + }, + \sprintf('is not one of [%s]', \implode(', ', $choices)) + ); + } + + /** + * Assert that each variable matches the given regular expression. + * + * @param string $regex + * + * @throws \Dotenv\Exception\ValidationException + * + * @return \Dotenv\Validator + */ + public function allowedRegexValues(string $regex) + { + return $this->assertNullable( + static function (string $value) use ($regex) { + return Regex::matches($regex, $value)->success()->getOrElse(false); + }, + \sprintf('does not match "%s"', $regex) + ); + } + + /** + * Assert that the callback returns true for each variable. + * + * @param callable(?string):bool $callback + * @param string $message + * + * @throws \Dotenv\Exception\ValidationException + * + * @return \Dotenv\Validator + */ + public function assert(callable $callback, string $message) + { + $failing = []; + + foreach ($this->variables as $variable) { + if ($callback($this->repository->get($variable)) === false) { + $failing[] = \sprintf('%s %s', $variable, $message); + } + } + + if (\count($failing) > 0) { + throw new ValidationException(\sprintf( + 'One or more environment variables failed assertions: %s.', + \implode(', ', $failing) + )); + } + + return $this; + } + + /** + * Assert that the callback returns true for each variable. + * + * Skip checking null variable values. + * + * @param callable(string):bool $callback + * @param string $message + * + * @throws \Dotenv\Exception\ValidationException + * + * @return \Dotenv\Validator + */ + public function assertNullable(callable $callback, string $message) + { + return $this->assert( + static function (?string $value) use ($callback) { + if ($value === null) { + return true; + } + + return $callback($value); + }, + $message + ); + } +} From 8f522e588da1cd02adf10228cb9e61ef3dd77215 Mon Sep 17 00:00:00 2001 From: luofei <604446095@qq.com> Date: Thu, 29 Jun 2023 13:52:40 +0800 Subject: [PATCH 2/3] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E6=9E=81=E5=85=89push?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- vendor/composer/ClassLoader.php | 12 +- vendor/composer/InstalledVersions.php | 17 +- vendor/composer/autoload_psr4.php | 1 + vendor/composer/autoload_real.php | 6 +- vendor/composer/autoload_static.php | 5 + vendor/composer/installed.json | 50 ++ vendor/composer/installed.php | 13 +- vendor/jpush/jpush/.gitignore | 18 + vendor/jpush/jpush/.travis.yml | 13 + vendor/jpush/jpush/LICENSE | 21 + vendor/jpush/jpush/README.md | 121 +++ vendor/jpush/jpush/autoload.php | 10 + vendor/jpush/jpush/composer.json | 31 + vendor/jpush/jpush/doc/api.md | 494 ++++++++++++ vendor/jpush/jpush/doc/grouppush.md | 28 + vendor/jpush/jpush/doc/http2.md | 56 ++ vendor/jpush/jpush/examples/admin_example.php | 14 + .../jpush/examples/batch_push_example.php | 35 + vendor/jpush/jpush/examples/cid_example.php | 7 + .../jpush/jpush/examples/config.php.example | 10 + .../examples/devices/delete_alias_example.php | 5 + .../examples/devices/delete_tag_example.php | 5 + .../devices/get_alias_devices_example.php | 6 + .../examples/devices/get_devices_example.php | 6 + .../devices/get_devices_status_example.php | 13 + .../examples/devices/get_tags_example.php | 6 + .../devices/update_device_example.php | 56 ++ .../examples/devices/update_tag_example.php | 29 + .../jpush/examples/grouppush_example.php | 24 + .../jpush/examples/huawei_push_example.php | 36 + vendor/jpush/jpush/examples/push_example.php | 140 ++++ .../reports/messages_detail_example.php | 5 + .../reports/received_detail_example.php | 5 + .../jpush/jpush/examples/schedule_example.php | 26 + vendor/jpush/jpush/examples/zone_examples.php | 24 + vendor/jpush/jpush/phpunit.xml.dist | 15 + vendor/jpush/jpush/src/JPush/AdminClient.php | 42 + vendor/jpush/jpush/src/JPush/Client.php | 71 ++ vendor/jpush/jpush/src/JPush/Config.php | 16 + .../jpush/jpush/src/JPush/DevicePayload.php | 224 ++++++ .../Exceptions/APIConnectionException.php | 9 + .../JPush/Exceptions/APIRequestException.php | 36 + .../src/JPush/Exceptions/JPushException.php | 9 + .../JPush/Exceptions/ServiceNotAvaliable.php | 25 + vendor/jpush/jpush/src/JPush/Http.php | 139 ++++ vendor/jpush/jpush/src/JPush/PushPayload.php | 761 ++++++++++++++++++ .../jpush/jpush/src/JPush/ReportPayload.php | 109 +++ .../jpush/jpush/src/JPush/SchedulePayload.php | 182 +++++ vendor/jpush/jpush/src/JPush/version.php | 4 + .../jpush/tests/JPush/DevicePayloadTest.php | 131 +++ .../jpush/tests/JPush/PushPayloadTest.php | 315 ++++++++ .../jpush/tests/JPush/ReportPayloadTest.php | 77 ++ .../jpush/tests/JPush/SchedulePayloadTest.php | 18 + vendor/jpush/jpush/tests/bootstrap.php | 8 + 54 files changed, 3525 insertions(+), 14 deletions(-) create mode 100644 vendor/jpush/jpush/.gitignore create mode 100644 vendor/jpush/jpush/.travis.yml create mode 100644 vendor/jpush/jpush/LICENSE create mode 100644 vendor/jpush/jpush/README.md create mode 100644 vendor/jpush/jpush/autoload.php create mode 100644 vendor/jpush/jpush/composer.json create mode 100644 vendor/jpush/jpush/doc/api.md create mode 100644 vendor/jpush/jpush/doc/grouppush.md create mode 100644 vendor/jpush/jpush/doc/http2.md create mode 100644 vendor/jpush/jpush/examples/admin_example.php create mode 100644 vendor/jpush/jpush/examples/batch_push_example.php create mode 100644 vendor/jpush/jpush/examples/cid_example.php create mode 100644 vendor/jpush/jpush/examples/config.php.example create mode 100644 vendor/jpush/jpush/examples/devices/delete_alias_example.php create mode 100644 vendor/jpush/jpush/examples/devices/delete_tag_example.php create mode 100644 vendor/jpush/jpush/examples/devices/get_alias_devices_example.php create mode 100644 vendor/jpush/jpush/examples/devices/get_devices_example.php create mode 100644 vendor/jpush/jpush/examples/devices/get_devices_status_example.php create mode 100644 vendor/jpush/jpush/examples/devices/get_tags_example.php create mode 100644 vendor/jpush/jpush/examples/devices/update_device_example.php create mode 100644 vendor/jpush/jpush/examples/devices/update_tag_example.php create mode 100644 vendor/jpush/jpush/examples/grouppush_example.php create mode 100644 vendor/jpush/jpush/examples/huawei_push_example.php create mode 100644 vendor/jpush/jpush/examples/push_example.php create mode 100644 vendor/jpush/jpush/examples/reports/messages_detail_example.php create mode 100644 vendor/jpush/jpush/examples/reports/received_detail_example.php create mode 100644 vendor/jpush/jpush/examples/schedule_example.php create mode 100644 vendor/jpush/jpush/examples/zone_examples.php create mode 100644 vendor/jpush/jpush/phpunit.xml.dist create mode 100644 vendor/jpush/jpush/src/JPush/AdminClient.php create mode 100644 vendor/jpush/jpush/src/JPush/Client.php create mode 100644 vendor/jpush/jpush/src/JPush/Config.php create mode 100644 vendor/jpush/jpush/src/JPush/DevicePayload.php create mode 100644 vendor/jpush/jpush/src/JPush/Exceptions/APIConnectionException.php create mode 100644 vendor/jpush/jpush/src/JPush/Exceptions/APIRequestException.php create mode 100644 vendor/jpush/jpush/src/JPush/Exceptions/JPushException.php create mode 100644 vendor/jpush/jpush/src/JPush/Exceptions/ServiceNotAvaliable.php create mode 100644 vendor/jpush/jpush/src/JPush/Http.php create mode 100644 vendor/jpush/jpush/src/JPush/PushPayload.php create mode 100644 vendor/jpush/jpush/src/JPush/ReportPayload.php create mode 100644 vendor/jpush/jpush/src/JPush/SchedulePayload.php create mode 100644 vendor/jpush/jpush/src/JPush/version.php create mode 100644 vendor/jpush/jpush/tests/JPush/DevicePayloadTest.php create mode 100644 vendor/jpush/jpush/tests/JPush/PushPayloadTest.php create mode 100644 vendor/jpush/jpush/tests/JPush/ReportPayloadTest.php create mode 100644 vendor/jpush/jpush/tests/JPush/SchedulePayloadTest.php create mode 100644 vendor/jpush/jpush/tests/bootstrap.php diff --git a/vendor/composer/ClassLoader.php b/vendor/composer/ClassLoader.php index fd56bd7d..a72151c7 100644 --- a/vendor/composer/ClassLoader.php +++ b/vendor/composer/ClassLoader.php @@ -429,7 +429,8 @@ class ClassLoader public function loadClass($class) { if ($file = $this->findFile($class)) { - (self::$includeFile)($file); + $includeFile = self::$includeFile; + $includeFile($file); return true; } @@ -560,7 +561,10 @@ class ClassLoader return false; } - private static function initializeIncludeClosure(): void + /** + * @return void + */ + private static function initializeIncludeClosure() { if (self::$includeFile !== null) { return; @@ -574,8 +578,8 @@ class ClassLoader * @param string $file * @return void */ - self::$includeFile = static function($file) { + self::$includeFile = \Closure::bind(static function($file) { include $file; - }; + }, null, null); } } diff --git a/vendor/composer/InstalledVersions.php b/vendor/composer/InstalledVersions.php index c6b54af7..51e734a7 100644 --- a/vendor/composer/InstalledVersions.php +++ b/vendor/composer/InstalledVersions.php @@ -98,7 +98,7 @@ class InstalledVersions { foreach (self::getInstalled() as $installed) { if (isset($installed['versions'][$packageName])) { - return $includeDevRequirements || empty($installed['versions'][$packageName]['dev_requirement']); + return $includeDevRequirements || !isset($installed['versions'][$packageName]['dev_requirement']) || $installed['versions'][$packageName]['dev_requirement'] === false; } } @@ -119,7 +119,7 @@ class InstalledVersions */ public static function satisfies(VersionParser $parser, $packageName, $constraint) { - $constraint = $parser->parseConstraints($constraint); + $constraint = $parser->parseConstraints((string) $constraint); $provided = $parser->parseConstraints(self::getVersionRanges($packageName)); return $provided->matches($constraint); @@ -328,7 +328,9 @@ class InstalledVersions if (isset(self::$installedByVendor[$vendorDir])) { $installed[] = self::$installedByVendor[$vendorDir]; } elseif (is_file($vendorDir.'/composer/installed.php')) { - $installed[] = self::$installedByVendor[$vendorDir] = require $vendorDir.'/composer/installed.php'; + /** @var array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array} $required */ + $required = require $vendorDir.'/composer/installed.php'; + $installed[] = self::$installedByVendor[$vendorDir] = $required; if (null === self::$installed && strtr($vendorDir.'/composer', '\\', '/') === strtr(__DIR__, '\\', '/')) { self::$installed = $installed[count($installed) - 1]; } @@ -340,12 +342,17 @@ class InstalledVersions // only require the installed.php file if this file is loaded from its dumped location, // and not from its source location in the composer/composer package, see https://github.com/composer/composer/issues/9937 if (substr(__DIR__, -8, 1) !== 'C') { - self::$installed = require __DIR__ . '/installed.php'; + /** @var array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array} $required */ + $required = require __DIR__ . '/installed.php'; + self::$installed = $required; } else { self::$installed = array(); } } - $installed[] = self::$installed; + + if (self::$installed !== array()) { + $installed[] = self::$installed; + } return $installed; } diff --git a/vendor/composer/autoload_psr4.php b/vendor/composer/autoload_psr4.php index 379a66a3..a2440bbc 100644 --- a/vendor/composer/autoload_psr4.php +++ b/vendor/composer/autoload_psr4.php @@ -55,6 +55,7 @@ return array( 'League\\Flysystem\\Cached\\' => array($vendorDir . '/league/flysystem-cached-adapter/src'), 'League\\Flysystem\\' => array($vendorDir . '/league/flysystem/src'), 'Joypack\\Tencent\\Map\\' => array($vendorDir . '/joypack/tencent-map/src'), + 'JPush\\' => array($vendorDir . '/jpush/jpush/src/JPush'), 'Intervention\\Image\\' => array($vendorDir . '/intervention/image/src/Intervention/Image'), 'GuzzleHttp\\Psr7\\' => array($vendorDir . '/guzzlehttp/psr7/src'), 'GuzzleHttp\\Promise\\' => array($vendorDir . '/guzzlehttp/promises/src'), diff --git a/vendor/composer/autoload_real.php b/vendor/composer/autoload_real.php index f1e605a7..5afd5549 100644 --- a/vendor/composer/autoload_real.php +++ b/vendor/composer/autoload_real.php @@ -34,15 +34,15 @@ class ComposerAutoloaderInitb1229d2685c190533aa1234015613f09 $loader->register(true); $filesToLoad = \Composer\Autoload\ComposerStaticInitb1229d2685c190533aa1234015613f09::$files; - $requireFile = static function ($fileIdentifier, $file) { + $requireFile = \Closure::bind(static function ($fileIdentifier, $file) { if (empty($GLOBALS['__composer_autoload_files'][$fileIdentifier])) { $GLOBALS['__composer_autoload_files'][$fileIdentifier] = true; require $file; } - }; + }, null, null); foreach ($filesToLoad as $fileIdentifier => $file) { - ($requireFile)($fileIdentifier, $file); + $requireFile($fileIdentifier, $file); } return $loader; diff --git a/vendor/composer/autoload_static.php b/vendor/composer/autoload_static.php index 25252ad1..9a9b37da 100644 --- a/vendor/composer/autoload_static.php +++ b/vendor/composer/autoload_static.php @@ -173,6 +173,7 @@ class ComposerStaticInitb1229d2685c190533aa1234015613f09 'J' => array ( 'Joypack\\Tencent\\Map\\' => 20, + 'JPush\\' => 6, ), 'I' => array ( @@ -429,6 +430,10 @@ class ComposerStaticInitb1229d2685c190533aa1234015613f09 array ( 0 => __DIR__ . '/..' . '/joypack/tencent-map/src', ), + 'JPush\\' => + array ( + 0 => __DIR__ . '/..' . '/jpush/jpush/src/JPush', + ), 'Intervention\\Image\\' => array ( 0 => __DIR__ . '/..' . '/intervention/image/src/Intervention/Image', diff --git a/vendor/composer/installed.json b/vendor/composer/installed.json index dd242941..4fba8f53 100644 --- a/vendor/composer/installed.json +++ b/vendor/composer/installed.json @@ -1685,6 +1685,56 @@ ], "install-path": "../joypack/tencent-map" }, + { + "name": "jpush/jpush", + "version": "v3.6.8", + "version_normalized": "3.6.8.0", + "source": { + "type": "git", + "url": "https://github.com/jpush/jpush-api-php-client.git", + "reference": "ebb191e8854a35c3fb7a6626028b3a23132cbe2c" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/jpush/jpush-api-php-client/zipball/ebb191e8854a35c3fb7a6626028b3a23132cbe2c", + "reference": "ebb191e8854a35c3fb7a6626028b3a23132cbe2c", + "shasum": "" + }, + "require": { + "ext-curl": "*", + "php": ">=5.3.3" + }, + "require-dev": { + "phpunit/phpunit": "*" + }, + "time": "2021-08-12T07:43:39+00:00", + "type": "library", + "installation-source": "dist", + "autoload": { + "psr-4": { + "JPush\\": "src/JPush/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "JPush", + "email": "support@jpush.cn", + "homepage": "https://www.jpush.cn/", + "role": "Developer" + } + ], + "description": "JPush API PHP Client", + "homepage": "https://github.com/jpush/jpush-api-php-client", + "support": { + "issues": "https://github.com/jpush/jpush-api-php-client/issues", + "source": "https://github.com/jpush/jpush-api-php-client/tree/v3.6.8" + }, + "install-path": "../jpush/jpush" + }, { "name": "khanamiryan/qrcode-detector-decoder", "version": "1.0.3", diff --git a/vendor/composer/installed.php b/vendor/composer/installed.php index 029a03d9..99318ad6 100644 --- a/vendor/composer/installed.php +++ b/vendor/composer/installed.php @@ -3,7 +3,7 @@ 'name' => 'topthink/think', 'pretty_version' => 'dev-master', 'version' => 'dev-master', - 'reference' => '9ff9e05d922b426d2829e28386114e1d19ba5adb', + 'reference' => 'fa730cf99f81c843e926f633ad856764fdcf6f49', 'type' => 'project', 'install_path' => __DIR__ . '/../../', 'aliases' => array(), @@ -376,6 +376,15 @@ 'aliases' => array(), 'dev_requirement' => false, ), + 'jpush/jpush' => array( + 'pretty_version' => 'v3.6.8', + 'version' => '3.6.8.0', + 'reference' => 'ebb191e8854a35c3fb7a6626028b3a23132cbe2c', + 'type' => 'library', + 'install_path' => __DIR__ . '/../jpush/jpush', + 'aliases' => array(), + 'dev_requirement' => false, + ), 'khanamiryan/qrcode-detector-decoder' => array( 'pretty_version' => '1.0.3', 'version' => '1.0.3.0', @@ -883,7 +892,7 @@ 'topthink/think' => array( 'pretty_version' => 'dev-master', 'version' => 'dev-master', - 'reference' => '9ff9e05d922b426d2829e28386114e1d19ba5adb', + 'reference' => 'fa730cf99f81c843e926f633ad856764fdcf6f49', 'type' => 'project', 'install_path' => __DIR__ . '/../../', 'aliases' => array(), diff --git a/vendor/jpush/jpush/.gitignore b/vendor/jpush/jpush/.gitignore new file mode 100644 index 00000000..72d22537 --- /dev/null +++ b/vendor/jpush/jpush/.gitignore @@ -0,0 +1,18 @@ +*.pyc +log/ +build/ +bin/ +.pydevproject +.tar +.zip +.buildpath +.project +.settings/ +.idea +composer.lock +vendor/ +*.log +vendor.tar.gz +composer.phar +vendor.zip +examples/config.php diff --git a/vendor/jpush/jpush/.travis.yml b/vendor/jpush/jpush/.travis.yml new file mode 100644 index 00000000..b560f04c --- /dev/null +++ b/vendor/jpush/jpush/.travis.yml @@ -0,0 +1,13 @@ +language: php + +php: + - '5.3' + - '5.4' + - '5.5' + - '5.6' + - '7.0' + +before_script: + - composer install +script: + - ./vendor/bin/phpunit tests diff --git a/vendor/jpush/jpush/LICENSE b/vendor/jpush/jpush/LICENSE new file mode 100644 index 00000000..99ff8e71 --- /dev/null +++ b/vendor/jpush/jpush/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2016 极光 + +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. diff --git a/vendor/jpush/jpush/README.md b/vendor/jpush/jpush/README.md new file mode 100644 index 00000000..3e48c541 --- /dev/null +++ b/vendor/jpush/jpush/README.md @@ -0,0 +1,121 @@ +# JPush API PHP Client + +这是 JPush REST API 的 PHP 版本封装开发包,是由极光推送官方提供的,一般支持最新的 API 功能。 + +对应的 REST API 文档: https://docs.jiguang.cn/jpush/server/push/server_overview/ + +> 支持的 PHP 版本: 5.3.3 ~ 5.6.x, 7.x + +> 若需要兼容 PHP 5.3.3 以下版本,可以使用 [v3 分支的代码](https://github.com/jpush/jpush-api-php-client/tree/v3)。 +因为运行 Composer 需要 PHP 5.3.2+ 以上版本,所以其不提供 Composer 支持, +也可以[点击链接](https://github.com/jpush/jpush-api-php-client/releases)下载 v3.4.x 版本源码。 + +## Installation + +#### 使用 Composer 安装 + +- 执行 `$ php composer.phar install` 或 `$ composer install` 进行安装。 + +#### 直接下载源码安装 + +> 直接下载源代码也是一种安装 SDK 的方法,不过因为有版本更新的维护问题,所以这种安装方式**十分不推荐**,但由于种种原因导致无法使用 Composer,所以我们也提供了这种情况下的备选方案。 + +- 下载源代码包,解压到项目中 +- 在项目中引入 autoload: + +```php +require 'path_to_sdk/autoload.php'; +``` + +## Usage + +- [Init API](https://github.com/jpush/jpush-api-php-client/blob/master/doc/api.md#init-api) +- [Push API](https://github.com/jpush/jpush-api-php-client/blob/master/doc/api.md#push-api) +- [Report API](https://github.com/jpush/jpush-api-php-client/blob/master/doc/api.md#report-api) +- [Device API](https://github.com/jpush/jpush-api-php-client/blob/master/doc/api.md#device-api) +- [Schedule API](https://github.com/jpush/jpush-api-php-client/blob/master/doc/api.md#schedule-api) +- [Exception Handle](https://github.com/jpush/jpush-api-php-client/blob/master/doc/api.md#schedule-api) +- [HTTP/2 Support](https://github.com/jpush/jpush-api-php-client/blob/master/doc/http2.md) +- [Group Push](https://github.com/jpush/jpush-api-php-client/blob/master/doc/grouppush.md) + +#### 初始化 + +```php +use JPush\Client as JPush; +... +... + + $client = new JPush($app_key, $master_secret); + +... +``` + +OR + +```php +$client = new \JPush\Client($app_key, $master_secret); +``` + +#### 简单推送 + +```php +$client->push() + ->setPlatform('all') + ->addAllAudience() + ->setNotificationAlert('Hello, JPush') + ->send(); +``` + +#### 异常处理 + +```php +$pusher = $client->push(); +$pusher->setPlatform('all'); +$pusher->addAllAudience(); +$pusher->setNotificationAlert('Hello, JPush'); +try { + $pusher->send(); +} catch (\JPush\Exceptions\JPushException $e) { + // try something else here + print $e; +} +``` + +## Examples + +**注意: 这只是使用样例, 不应该直接用于实际环境中!!** + +在下载的中的 [examples](https://github.com/jpush/jpush-api-php-client/tree/master/examples) 文件夹有简单示例代码, 开发者可以参考其中的样例快速了解该库的使用方法。 + +**简单使用方法** + +先填写对应的appKey和masterSecret,可以额外设定Registration_id。 + +若要运行 push_example.php 中的示例代码: + +``` bash +# 假定当前目录为 JPush 源码所在的根目录 +$ php examples/push_example.php +``` +> 同时也可编辑相关的示例文件,更改参数查看执行效果 + +## Testing + +```bash +# 编辑 tests/bootstrap.php 文件,填入必须的变量值 +# OR 设置相应的环境变量 + +# 运行全部测试用例 +$ composer tests + +# 运行某一具体测试用例 +$ composer tests/JPush/xxTest.php +``` + +## Contributing + +Bug reports and pull requests are welcome on GitHub at https://github.com/jpush/jpush-api-php-client. + +## License + +The library is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT). diff --git a/vendor/jpush/jpush/autoload.php b/vendor/jpush/jpush/autoload.php new file mode 100644 index 00000000..d27a7d84 --- /dev/null +++ b/vendor/jpush/jpush/autoload.php @@ -0,0 +1,10 @@ +=5.3.3", + "ext-curl": "*" + }, + "require-dev": { + "phpunit/phpunit": "*" + }, + "autoload" : { + "psr-4": {"JPush\\": "src/JPush/"} + }, + "autoload-dev": { + "psr-4": { "JPush\\Tests\\": "tests/" } + }, + "scripts": { + "test": "vendor/bin/phpunit" + } +} diff --git a/vendor/jpush/jpush/doc/api.md b/vendor/jpush/jpush/doc/api.md new file mode 100644 index 00000000..d84850dc --- /dev/null +++ b/vendor/jpush/jpush/doc/api.md @@ -0,0 +1,494 @@ +# 目录 + +- [Init API](#init-api) +- [Push API](#push-api) +- [Report API](#report-api) +- [Device API](#device-api) +- [Schedule API](#schedule-api) +- [Exception Handle](#schedule-api) + +> **注:PHP SDK 全面支持 namespaces 但为方便表达,以下例子都不使用 use 语句** + +## Init API + +在调用推送之前,我们必须先初始化 JPushClient,调用以下代码可以进行快速初始化: + +```php +$client = new \JPush\Client($app_key, $master_secret); +``` + +在初始化 JPushClient 的时候,可以指定**日志路径**: + +```php +$client = new \JPush\Client($app_key, $master_secret, $log_path); +``` +> 默认日志路径为 `./jpush.log`,即保存在当前运行目录,如果想关闭日志,可以指定为 `null`。 + +## Push API + +在初始化 JPushClient 后,调用以下代码将返回一个推送 Payload 构建器,它提供丰富的API来帮助你构建 PushPayload。 + +```php +$push = $client->push(); +``` + +通过 [JPush Push API](https://docs.jiguang.cn/jpush/server/push/rest_api_v3_push/) 我们知道,一个 PushPayload 是由以下几个部分构成的: + +- Cid +- Platform +- Audience +- Notification +- Message +- SmsContent +- Options + +#### Cid + +```php +$push->setCid($cid); +``` + +#### Platform + +```php +$push->setPlatform('all'); +// OR +$push->setPlatform('ios', 'android'); +// OR +$push->setPlatform(['ios', 'android']); +``` + +#### Audience + +```php +$push->addAllAudience(); +``` + +```php +$push->addTag('tag1'); +// OR +$push->addTag(['tag1', 'tag2']); +``` + +其他诸如 `addAlias()`, `addRegistrationId()`, `addTagAnd()`, `addTagNot()`, `addSegmentId()`, `addAbtest()` 的使用方法与 `addTag()` 类似,在此不做赘述。 + +#### Notification + +```php +// 简单地给所有平台推送相同的 alert 消息 +$push->setNotificationAlert('alert'); +``` + +**iOS Notification** + +```php +// iosNotification($alert = '', array $notification = array()) +// 数组 $notification 的键支持 'sound', 'badge', 'content-available', 'mutable-content', category', 'extras', 'thread-id' 中的一个或多个 + +// 调用示例 +$push->iosNotification(); +// OR +$push->iosNotification('hello'); +// OR +$push->iosNotification('hello', [ + 'sound' => 'sound', + 'badge' => '+1', + 'extras' => [ + 'key' => 'value' + ] +]); +``` + +参数说明: + +| 参数 | 说明 | +| --- | --- | +| alert |表示通知内容,会覆盖上级统一指定的 alert 信息;默认内容可以为空字符串,表示不展示到通知栏, 支持字符串和数组两种形式 | +| sound | 表示通知提示声音,默认填充为空字符串 | +| badge | 表示应用角标,把角标数字改为指定的数字;为 0 表示清除,支持 '+1','-1' 这样的字符串,表示在原有的 badge 基础上进行增减,默认填充为 '+1' | +| content-available | 表示推送唤醒,仅接受 true 表示为 Background Remote Notification,若不填默认表示普通的 Remote Notification | +| mutable-content | 表示通知扩展, 仅接受 true 表示支持 iOS10 的 UNNotificationServiceExtension, 若不填默认表示普通的 Remote Notification | +| category | IOS8才支持。设置 APNs payload 中的 'category' 字段值 | +| thread-id | 表示通知分组,ios 的远程通知通过该属性来对通知进行分组,同一个 thread-id 的通知归为一组 | +| extras | 表示扩展字段,接受一个数组,自定义 Key/value 信息以供业务使用 | + +**Android Notification** + +```php +// androidNotification($alert = '', array $notification = array()) +// 调用示例同 IOS,数组 $notification 的键支持 'title', 'builder_id', 'priority', 'category', 'style', 'alert_type', 'big_text', 'inbox', 'big_pic_path', 'large_icon', 'intent', 'extras' 中的一个或多个 +``` + +参数说明: + +| 参数 | 说明 | +| --- | --- | +| alert | 表示通知内容,会覆盖上级统一指定的 alert 信息;默认内容可以为空字符串,表示不展示到通知栏 | +| title | 表示通知标题,会替换通知里原来展示 App 名称的地方 | +| builder_id | 表示通知栏样式 ID | +| priority | 表示通知栏展示优先级,默认为 0,范围为 -2~2 ,其他值将会被忽略而采用默认值 | +| category | 表示通知栏条目过滤或排序,完全依赖 rom 厂商对 category 的处理策略 | +| style | 表示通知栏样式类型,默认为 0,还有1,2,3可选,用来指定选择哪种通知栏样式,其他值无效。有三种可选分别为 bigText=1,Inbox=2,bigPicture=3 | +| alert_type | 表示通知提醒方式, 可选范围为 -1~7 ,对应 Notification.DEFAULT_ALL = -1 或者 Notification.DEFAULT_SOUND = 1, Notification.DEFAULT_VIBRATE = 2, Notification.DEFAULT_LIGHTS = 4 的任意 “or” 组合。默认按照 -1 处理。 | +| big_text | 表示大文本通知栏样式,当 style = 1 时可用,内容会被通知栏以大文本的形式展示出来,支持 api 16 以上的 rom | +| inbox | 表示文本条目通知栏样式,接受一个数组,当 style = 2 时可用,数组的每个 key 对应的 value 会被当作文本条目逐条展示,支持 api 16 以上的 rom | +| big_pic_path | 表示大图片通知栏样式,当 style = 3 时可用,可以是网络图片 url,或本地图片的 path,目前支持 .jpg 和 .png 后缀的图片。图片内容会被通知栏以大图片的形式展示出来。如果是 http/https 的 url,会自动下载;如果要指定开发者准备的本地图片就填 sdcard 的相对路径,支持 api 16 以上的 rom | +| large_icon | 表示通知栏大图标,图标路径可以是以 http 或 https 开头的网络图片,如:"http:jiguang.cn/logo.png",图标大小不超过 30k; 也可以是位于 drawable 资源文件夹的图标路径,如:"R.drawable.lg_icon";| +| intent | 表示扩展字段,接受一个数组,自定义 Key/value 信息以供业务使用 | +| extras | 表示扩展字段,接受一个数组,自定义 Key/value 信息以供业务使用 | + +**WinPhone Notification** + +```php +$push->addWinPhoneNotification($alert=null, $title=null, $_open_page=null, $extras=null) +``` + +参数说明: + +| 参数 | 说明 | +| --- | --- | +| alert | 表示通知内容,会覆盖上级统一指定的 alert 信息;内容为空则不展示到通知栏 | +| title | 通知标题,会填充到 toast 类型 text1 字段上 | +| _open_page | 点击打开的页面名称 | + +#### Message + +```php +// message($msg_content, array $msg = array()) +// 数组 $msg 的键支持 'title', 'content_type', 'extras' 中的一个或多个 + +// 调用示例 +$push->message('Hello JPush'); +// OR +$push->message('Hello JPush', [ + 'title' => 'Hello', + 'content_type' => 'text', + 'extras' => [ + 'key' => 'value' + ] +]); +``` + +参数说明: + +| 参数 | 说明 | +| --- | --- | +| msg_content | 消息内容本身 | +| title | 消息标题 | +| content_type | 消息内容类型 | +| extras | 表示扩展字段,接受一个数组,自定义 Key/value 信息以供业务使用 | + +#### Sms Message + +```php +$push->setSms($delay_time, $temp_id, array $temp_para = []) +``` + +参数说明: +* delay_time: 表示短信发送的延迟时间,单位为秒,不能超过 24 小时(即大于等于 0 小于等于 86400)。仅对 android 平台有效。 +* temp_id: 短信补充的内容模板 ID。没有填写该字段即表示不使用短信补充功能。 +* temp_para: 短信模板中的参数 + +##### 已弃用 + +```php +$push->setSmsMessage($content, $delay_time) +``` + +参数说明: +* content: 短信文本,不超过 480 字符 +* delay_time: 表示短信发送的延迟时间,单位为秒,不能超过 24 小时(即大于等于 0 小于等于 86400)。仅对 android 平台有效。默认为 0,表示立即发送短信 + +#### Options + +```php +// options(array $opts = array()) +// 数组 $opts 的键支持 'sendno', 'time_to_live', 'override_msg_id', 'apns_production', 'big_push_duration', 'apns_collapse_id' 中的一个或多个 +``` + +参数说明: + +| 可选项 | 说明 | +| --- | --- | +| sendno | 表示推送序号,纯粹用来作为 API 调用标识,API 返回时被原样返回,以方便 API 调用方匹配请求与返回 | +| time_to_live | 表示离线消息保留时长(秒),推送当前用户不在线时,为该用户保留多长时间的离线消息,以便其上线时再次推送。默认 86400 (1 天),最长 10 天。设置为 0 表示不保留离线消息,只有推送当前在线的用户可以收到 | +| override_msg_id | 表示要覆盖的消息ID,如果当前的推送要覆盖之前的一条推送,这里填写前一条推送的 msg_id 就会产生覆盖效果 | +| apns_production | 表示 APNs 是否生产环境,True 表示推送生产环境,False 表示要推送开发环境;如果不指定则默认为推送开发环境 | +| apns_collapse_id | APNs 新通知如果匹配到当前通知中心有相同 apns-collapse-id 字段的通知,则会用新通知内容来更新它,并使其置于通知中心首位;collapse id 长度不可超过 64 bytes| +| big_push_duration | 表示定速推送时长(分钟),又名缓慢推送,把原本尽可能快的推送速度,降低下来,给定的 n 分钟内,均匀地向这次推送的目标用户推送。最大值为1400.未设置则不是定速推送 | + +#### Common Method + +```php +// 发送推送 +// 该方法内部将自动调用构建方法获得当前构建对象,并转化为 JSON 向 JPush 服务器发送请求 +$push->send(); +``` + +> 构建 PushPayload 的 API 每一次都会返回自身的引用,所以我们可用使用链式调用的方法提高代码的简洁性,如: + +```php +$response = $push() + ->setCid('xxxxxx') + ->setPlatform(['ios', 'android']) + ->addTag(['tag1', 'tag2']) + ->setNotificationAlert('Hello, JPush') + ->iosNotification('hello', [ + 'sound' => 'sound', + 'badge' => '+1', + 'extras' => [ + 'key' => 'value' + ] + ]) + ->androidNotification('hello') + ->message('Hello JPush', [ + 'title' => 'Hello', + 'content_type' => 'text', + 'extras' => [ + 'key' => 'value' + ] + ]) + ->send(); + +// OR 也可以提前准备好所有的参数,然后链式调用,这样代码可读性更好一点 +$cid = 'xxxxxx'; +$platform = array('ios', 'android'); +$alert = 'Hello JPush'; +$tag = array('tag1', 'tag2'); +$regId = array('rid1', 'rid2'); +$ios_notification = array( + 'sound' => 'hello jpush', + 'badge' => 2, + 'content-available' => true, + 'category' => 'jiguang', + 'extras' => array( + 'key' => 'value', + 'jiguang' + ), +); +$android_notification = array( + 'title' => 'hello jpush', + 'builder_id' => 2, + 'extras' => array( + 'key' => 'value', + 'jiguang' + ), +); +$content = 'Hello World'; +$message = array( + 'title' => 'hello jpush', + 'content_type' => 'text', + 'extras' => array( + 'key' => 'value', + 'jiguang' + ), +); +$options = array( + 'sendno' => 100, + 'time_to_live' => 100, + 'override_msg_id' => 100, + 'big_push_duration' => 100 +); +$response = $push->setCid($cid) + ->setPlatform($platform) + ->addTag($tag) + ->addRegistrationId($regId) + ->iosNotification($alert, $ios_notification) + ->androidNotification($alert, $android_notification) + ->message($content, $message) + ->options($options) + ->send(); +``` + +#### 获取 Cid + +```php +$push->getCid($count = 1, $type = 'push'); +``` + +## Report API + +```php + $report = $client->report(); + ``` + +#### 获取送达统计 + +```php +$report->getReceived('msg_id'); +// OR +$report->getReceived(['msg_id1', 'msg_id2']); +``` + +#### 送达状态查询 + +```php +$msg_id0 = 66666666666; +$report->getMessageStatus($msg_id0, 'rid0'); +# OR +$report->getMessageStatus($msg_id0, ['rid0', 'rid1']); +#OR +$report->getMessageStatus($msg_id0, ['rid0', 'rid1'], '2017-12-21'); +``` + +#### 获取消息统计 + +```php +// getMessages(getMessages($msgIds)); +// 消息统计与送达统计一样,接受一个数组的参数,在这里不做赘述 +``` + +#### 获取用户统计 + +调用一下代码可以获得用户统计 + +```php +$report->getUsers($time_unit, $start, $duration) +``` + +参数说明: + +- time_unit:`String` 时间单位, 可取值HOUR, DAY, MONTH +- start:`String` 起始时间 + - 如果单位是小时,则起始时间是小时(包含天),格式例:2014-06-11 09 + - 如果单位是天,则起始时间是日期(天),格式例:2014-06-11 + - 如果单位是月,则起始时间是日期(月),格式例:2014-06 +- duration:`String` 持续时长 + - 如果单位是天,则是持续的天数。以此类推 + - 只支持查询60天以内的用户信息,对于time_unit为HOUR的,只支持输出当天的统计结果。 + +## Device API + +```php +$device = $client->device(); +``` + +#### 操作 Device(registration_id) + +```php +// 查询指定设备的别名与标签 +$device->getDevices($registration_id); + + +// 更新指定设备的别名与标签 + +// 更新 Alias +$device->updateAlias($registration_id, 'alias'); +// 添加 tag, 支持字符串和数组两种参数 +$device->addTags($registration_id, 'tag'); +// OR +$device->addTags($registration_id, ['tag1', 'tag2']); +// 移除 tag,支持字符串和数组两种参数 +$device->removeTags($registration_id, 'tags'); +// OR +$device->removeTags($registration_id, ['tag1', 'tag2']); +// 清空所有 tag +$device->clearTags($registration_id); + +// 更新 mobile +$device->updateMoblie($registration_id, '13800138000'); +// 取消手机绑定 +$device->clearMobile($registration_id); + +// getDevicesStatus($registrationId) +// 获取在线用户的登录状态(VIP专属接口),支持字符串和数组两种参数 +$device->getDevicesStatus('rid'); +// OR +$device->getDevicesStatus(['rid1', 'rid2']); +``` + +#### 操作标签 + +```php +// 获取标签列表 +$device->getTags() + +// 判断指定设备是否在指定标签之下 +$device->isDeviceInTag($registrationId, $tag); + + +// 更新标签 + +// 为标签添加设备,支持字符串和数组两种参数 +$device->addDevicesToTag($tag, 'rid'); +$device->addDevicesToTag($tag, ['rid1', 'rid2']); + +// 为标签移除设备,支持字符串和数组两种参数 +$device->removeDevicesFromTag($tag, 'rid'); +$device->removeDevicesFromTag($tag, ['rid1', 'rid2']); + + +// 删除标签 +$device->deleteTag('tag'); +``` + +#### 操作别名 + +```php +// 获取指定别名下的设备 +$device->getAliasDevices('alias'); + +// 删除别名 +$device->deleteAlias('alias'); +``` + +## Schedule API + +```php +$schedule = $client->schedule(); +``` + +#### 创建定时任务 + +定时任务分为Single与Periodical两种,可以通过调用以下方法创建定时任务 + +```php +$schedule->createSingleSchedule($name, $push_payload, $trigger) +$schedule->createPeriodicalSchedule($name, $push_payload, $trigger) +``` + +参数说明: +- name: `String` 定时任务的名称 +- push_payload: `PushPayload` Push的构建对象,通过Push模块的`build()`方法获得 +- trigger: `Array` 触发器对象 + +#### 更新定时任务 + +```php +$schedule->updateSingleSchedule($schedule_id, $name=null, $enabled=null, $push_payload=null, $trigger=null) +$schedule->updatePeriodicalSchedule($schedule_id, $name=null, $enabled=null, $push_payload=null, $trigger=null) +``` + +#### 其他 + +```php +// 获取定时任务列表 +$schedule->getSchedules($page=1); + +// 获取指定定时任务 +$schedule->getSchedule($schedule_id); + +// 删除指定定时任务 +$schedule->deleteSchedule($schedule_id); + +// 获取定时任务对应的所有 msg_id +$schedule->getMsgIds($schedule_id); +``` + +## Exception Handle + +当 API 请求发生错误时,SDK 将抛出异常,Pushpayload 具体错误代码请参考[ API 错误代码表](https://docs.jiguang.cn/jpush/server/push/rest_api_v3_push/#_19)。 +PHP SDK 主要抛出两个异常 `\JPush\Exceptions\APIConnectionException` 和 `\JPush\Exceptions\APIRequestException` 分别对应请求连接产生的异常和请求响应的异常。 +这两种异常都需要捕获,为简单起见,也可以捕获他们的父类异常 `JPush\Exceptions\JPushException`(见 README)。另外 APIRequestException 异常还提供其他方法供开发者调用。 + +```php +try { + $pusher->send(); +} catch (\JPush\Exceptions\APIConnectionException $e) { + // try something here + print $e; +} catch (\JPush\Exceptions\APIRequestException $e) { + // try something here + print $e; +} +``` diff --git a/vendor/jpush/jpush/doc/grouppush.md b/vendor/jpush/jpush/doc/grouppush.md new file mode 100644 index 00000000..81fd3d65 --- /dev/null +++ b/vendor/jpush/jpush/doc/grouppush.md @@ -0,0 +1,28 @@ +# JPush Group Push + +## 获取 Group Key 和 Group Master Secret + +```php +$group_key = 'xxxx'; +$group_master_secret = 'xxxx'; +``` + +## 初始化 + +**注:Group Key 需拼接 'group-' 使用** + +```php +$client = new \JPush\Client('group-' . $group_key, $group_master_secret); +``` + +## 简单群组推送 + +```php +$client->push() + ->setPlatform('all') + ->addAllAudience() + ->setNotificationAlert('Hello, JPush') + ->send(); +``` + +> [Example](https://github.com/jpush/jpush-api-php-client/blob/master/examples/push_example.php) diff --git a/vendor/jpush/jpush/doc/http2.md b/vendor/jpush/jpush/doc/http2.md new file mode 100644 index 00000000..4fe87de1 --- /dev/null +++ b/vendor/jpush/jpush/doc/http2.md @@ -0,0 +1,56 @@ +# JPush API PHP Client With HTTP/2 Support + +> JPush API PHP Client 全面支持 HTTP/2, +> **要求 PHP >= 5.5.24**, +> 但由于 libcurl 对于 HTTP/2 的实现依赖于第三方库 [nghttp2](https://github.com/nghttp2/nghttp2) 所以如果要支持 HTTP/2 需要做一些其他的配置。 + +### 安装 nghttp2 + +系统依赖仅针对 Ubuntu 14.04 LTS (trusty) 和 Debian 7.0 (wheezy) 或以上版本,其他系统版本请按照 nghttp2 的文档来操作: + +> From Ubuntu 15.10, spdylay has been available as a package named libspdylay-dev. For the earlier Ubuntu release, you need to build it yourself: http://tatsuhiro-t.github.io/spdylay/ + +详细情况请查看 [nghttp2 的文档](https://github.com/nghttp2/nghttp2#requirements)。 + +```bash +# Get build requirements +# Some of these are used for the Python bindings +# this package also installs +$ sudo apt-get install g++ make binutils autoconf automake autotools-dev libtool pkg-config \ + zlib1g-dev libcunit1-dev libssl-dev libxml2-dev libev-dev libevent-dev libjansson-dev \ + libjemalloc-dev cython python3-dev python-setuptools + +# Build nghttp2 from source +$ git clone https://github.com/tatsuhiro-t/nghttp2.git +$ cd nghttp2 +$ autoreconf -i +$ automake +$ autoconf +$ ./configure +$ make +$ sudo make install +``` + +### 升级 curl 至最新版本 + +```bash +$ sudo apt-get build-dep curl +# 请根据当前的 curl 官网中的最新版本(https://curl.haxx.se/download/)替换下面的相应位置 +$ wget https://curl.haxx.se/download/curl-7.x.x.tar.bz2 +$ tar -xvjf curl-7.x.x.tar.bz2 +$ cd curl-7.x.x +$ ./configure --with-nghttp2=/usr/local --with-ssl +$ make +$ sudo make install +``` + +### 测试 + +##### 命令行测试 +命令行运行 `$ curl --version`,若输出中的 Features 栏中有 `HTTP2` 一项则证明配置成功。 + +##### 样例测试 +运行样例 `$ php examples/devices/get_devices_example.php`,若输出中的 HTTP 版本是 HTTP/2 则证明已经在使用 HTTP2 发送请求和接受响应了。 + +##### 测试测试 +运行测试 `$./vendor/bin/phpunit tests/JPush/DevicePayloadTest.php`,若打印出的 http headers 中的 HTTP 版本是 HTTP/2 则证明已经在使用 HTTP2 发送请求和接受响应了。 diff --git a/vendor/jpush/jpush/examples/admin_example.php b/vendor/jpush/jpush/examples/admin_example.php new file mode 100644 index 00000000..9b955516 --- /dev/null +++ b/vendor/jpush/jpush/examples/admin_example.php @@ -0,0 +1,14 @@ +createApp('aaa', 'cn.jpush.app'); +print_r($response); + +$appKey = $response['body']['app_key']; +$response = $admin->deleteApp($appKey); +print_r($response); diff --git a/vendor/jpush/jpush/examples/batch_push_example.php b/vendor/jpush/jpush/examples/batch_push_example.php new file mode 100644 index 00000000..52b4e5e7 --- /dev/null +++ b/vendor/jpush/jpush/examples/batch_push_example.php @@ -0,0 +1,35 @@ + 'all', + 'target' => 'regid1', + 'notification' => array( + 'alert' => 'NotificationAlert1' + ) + ), + array( + 'platform' => 'all', + 'target' => 'regid2', + 'notification' => array( + 'alert' => 'NotificationAlert2' + ) + ) +); + +$push_payload = $client -> push(); +try { + $response = $push_payload -> batchPushByRegid($singlePayloads); + print_r($response); + $response = $push_payload -> batchPushByAlias($singlePayloads); + print_r($response); +} catch (\JPush\Exceptions\APIConnectionException $e) { + // try something here + print $e; +} catch (\JPush\Exceptions\APIRequestException $e) { + // try something here + print $e; +} \ No newline at end of file diff --git a/vendor/jpush/jpush/examples/cid_example.php b/vendor/jpush/jpush/examples/cid_example.php new file mode 100644 index 00000000..97b6aeeb --- /dev/null +++ b/vendor/jpush/jpush/examples/cid_example.php @@ -0,0 +1,7 @@ +push()->getCid(); + +print_r($response); diff --git a/vendor/jpush/jpush/examples/config.php.example b/vendor/jpush/jpush/examples/config.php.example new file mode 100644 index 00000000..3d8627fb --- /dev/null +++ b/vendor/jpush/jpush/examples/config.php.example @@ -0,0 +1,10 @@ +device()->deleteAlias('alias'); +print_r($response); diff --git a/vendor/jpush/jpush/examples/devices/delete_tag_example.php b/vendor/jpush/jpush/examples/devices/delete_tag_example.php new file mode 100644 index 00000000..09a29148 --- /dev/null +++ b/vendor/jpush/jpush/examples/devices/delete_tag_example.php @@ -0,0 +1,5 @@ +device()->deleteTag('tag'); +print_r($response); diff --git a/vendor/jpush/jpush/examples/devices/get_alias_devices_example.php b/vendor/jpush/jpush/examples/devices/get_alias_devices_example.php new file mode 100644 index 00000000..707548e4 --- /dev/null +++ b/vendor/jpush/jpush/examples/devices/get_alias_devices_example.php @@ -0,0 +1,6 @@ +device()->getAliasDevices('alias'); +print_r($response); diff --git a/vendor/jpush/jpush/examples/devices/get_devices_example.php b/vendor/jpush/jpush/examples/devices/get_devices_example.php new file mode 100644 index 00000000..6e983c1f --- /dev/null +++ b/vendor/jpush/jpush/examples/devices/get_devices_example.php @@ -0,0 +1,6 @@ +device()->getDevices($registration_id); +print_r($response); \ No newline at end of file diff --git a/vendor/jpush/jpush/examples/devices/get_devices_status_example.php b/vendor/jpush/jpush/examples/devices/get_devices_status_example.php new file mode 100644 index 00000000..47efe392 --- /dev/null +++ b/vendor/jpush/jpush/examples/devices/get_devices_status_example.php @@ -0,0 +1,13 @@ +device()->getDevicesStatus($registration_id); +} catch(\JPush\Exceptions\APIRequestException $e) { + print $e; + print $e->getHttpCode(); + print $e->getHeaders(); +} + +print_r($response); diff --git a/vendor/jpush/jpush/examples/devices/get_tags_example.php b/vendor/jpush/jpush/examples/devices/get_tags_example.php new file mode 100644 index 00000000..72041cf8 --- /dev/null +++ b/vendor/jpush/jpush/examples/devices/get_tags_example.php @@ -0,0 +1,6 @@ +device()->getDevices($registration_id); +print_r($response); \ No newline at end of file diff --git a/vendor/jpush/jpush/examples/devices/update_device_example.php b/vendor/jpush/jpush/examples/devices/update_device_example.php new file mode 100644 index 00000000..51c0e88d --- /dev/null +++ b/vendor/jpush/jpush/examples/devices/update_device_example.php @@ -0,0 +1,56 @@ +device()->getDevices($registration_id); +print "before update alias = " . $result['body']['alias'] . "\n"; + +print 'updating alias ... response = '; +$response = $client->device()->updateAlias($registration_id, 'jpush_alias'); +print_r($response); + +$result = $client->device()->getDevices($registration_id); +print "after update alias = " . $result['body']['alias'] . "\n\n"; + +// 添加 tag +$result = $client->device()->getDevices($registration_id); +print "before add tags = [" . implode(',', $result['body']['tags']) . "]\n"; + +print 'add tag1 tag2 ... response = '; + +$response = $client->device()->addTags($registration_id, 'tag0'); +print_r($response); + +$response = $client->device()->addTags($registration_id, ['tag1', 'tag2']); +print_r($response); + +$result = $client->device()->getDevices($registration_id); +print "after add tags = [" . implode(',', $result['body']['tags']) . "]\n\n"; + + +// 移除 tag +$result = $client->device()->getDevices($registration_id); +print "before remove tags = [" . implode(',', $result['body']['tags']) . "]\n"; + +print 'removing tag1 tag2 ... response = '; + +$response = $client->device()->removeTags($registration_id, 'tag0'); +print_r($response); + +$response = $client->device()->removeTags($registration_id, ['tag1', 'tag2']); +print_r($response); + +$result = $client->device()->getDevices($registration_id); +print "after remove tags = [" . implode(',', $result['body']['tags']) . "]\n\n"; + + +// 更新 mobile +$result = $client->device()->getDevices($registration_id); +print "before update mobile = " . $result['body']['mobile'] . "\n"; + +print 'updating mobile ... response = '; +$response = $client->device()->updateMoblie($registration_id, '13800138000'); +print_r($response); + +$result = $client->device()->getDevices($registration_id); +print "after update mobile = " . $result['body']['mobile'] . "\n\n"; \ No newline at end of file diff --git a/vendor/jpush/jpush/examples/devices/update_tag_example.php b/vendor/jpush/jpush/examples/devices/update_tag_example.php new file mode 100644 index 00000000..a5f19bae --- /dev/null +++ b/vendor/jpush/jpush/examples/devices/update_tag_example.php @@ -0,0 +1,29 @@ +device()->isDeviceInTag($registration_id, 'tag'); +$r = $result['body']['result'] ? 'true' : 'false'; +print "before add device = " . $r . "\n"; + +print 'adding device ... response = '; +$response = $client->device()->addDevicesToTag('tag', $registration_id); +print_r($response); + +$result = $client->device()->isDeviceInTag($registration_id, 'tag'); +$r = $result['body']['result'] ? 'true' : 'false'; +print "after add tags = " . $r . "\n\n"; + +// 为一个标签删除设备 +$result = $client->device()->isDeviceInTag($registration_id, 'tag'); +$r = $result['body']['result'] ? 'true' : 'false'; +print "before remove device = " . $r . "\n"; + +print 'removing device ... response = '; +$response = $client->device()->removeDevicesFromTag('tag', $registration_id); +print_r($response); + +$result = $client->device()->isDeviceInTag($registration_id, 'tag'); +$r = $result['body']['result'] ? 'true' : 'false'; +print "after remove device = " . $r . "\n\n"; + diff --git a/vendor/jpush/jpush/examples/grouppush_example.php b/vendor/jpush/jpush/examples/grouppush_example.php new file mode 100644 index 00000000..4cbe45ac --- /dev/null +++ b/vendor/jpush/jpush/examples/grouppush_example.php @@ -0,0 +1,24 @@ +push() + ->setPlatform('all') + ->addAllAudience() + ->setNotificationAlert('Hi, JPush'); +try { + $response = $push_payload->send(); + print_r($response); +} catch (\JPush\Exceptions\APIConnectionException $e) { + // try something here + print $e; +} catch (\JPush\Exceptions\APIRequestException $e) { + // try something here + print $e; +} diff --git a/vendor/jpush/jpush/examples/huawei_push_example.php b/vendor/jpush/jpush/examples/huawei_push_example.php new file mode 100644 index 00000000..c601fc68 --- /dev/null +++ b/vendor/jpush/jpush/examples/huawei_push_example.php @@ -0,0 +1,36 @@ +push() + ->setPlatform(array('ios', 'android')) + // ->addAlias('alias') + ->addTag(array('tag1', 'tag2')) + // ->addRegistrationId($registration_id) + ->setNotificationAlert('Hi, JPush') + ->androidNotification('Hello HUAWEI', array( + 'title' => 'huawei demo', + + // --------------------------------------------------- + // `uri_activity` 字段用于指定想要打开的 activity. + // 值为 activity 节点的 “android:name” 属性值。 + 'uri_activity' => 'cn.jpush.android.ui.OpenClickActivity', + // --------------------------------------------------- + + 'extras' => array( + 'key' => 'value', + 'jiguang' + ), + )); + // ->send(); + print_r($payload->build()); + +} catch (\JPush\Exceptions\APIConnectionException $e) { + // try something here + print $e; +} catch (\JPush\Exceptions\APIRequestException $e) { + // try something here + print $e; +} diff --git a/vendor/jpush/jpush/examples/push_example.php b/vendor/jpush/jpush/examples/push_example.php new file mode 100644 index 00000000..3a950615 --- /dev/null +++ b/vendor/jpush/jpush/examples/push_example.php @@ -0,0 +1,140 @@ +push() +// ->setPlatform('all') +// ->addAllAudience() +// ->setNotificationAlert('Hi, JPush'); +// try { +// $response = $push_payload->send(); +// print_r($response); +// } catch (\JPush\Exceptions\APIConnectionException $e) { +// // try something here +// print $e; +// } catch (\JPush\Exceptions\APIRequestException $e) { +// // try something here +// print $e; +// } + +// 完整的推送示例 +// 这只是使用样例,不应该直接用于实际生产环境中 !! +try { + $response = $client->push() + ->setPlatform(array('ios', 'android')) + // 一般情况下,关于 audience 的设置只需要调用 addAlias、addTag、addTagAnd 或 addRegistrationId + // 这四个方法中的某一个即可,这里仅作为示例,当然全部调用也可以,多项 audience 调用表示其结果的交集 + // 即是说一般情况下,下面三个方法和没有列出的 addTagAnd 一共四个,只适用一个便可满足大多数的场景需求 + + // ->addAlias('alias') + // ->addTag(array('tag1', 'tag2')) + // ->addRegistrationId($registration_id) + ->addAllAudience() + + ->setNotificationAlert('Test custom') + ->iosNotification('Hello IOS', array( + 'sound' => 'sound.caf', + // 'badge' => '+1', + // 'content-available' => true, + // 'mutable-content' => true, + 'category' => 'jiguang', + 'extras' => array( + 'key' => 'value', + 'jiguang' + ), + )) + ->androidNotification('Hello Android', array( + 'title' => 'hello jpush', + // 'builder_id' => 2, + 'extras' => array( + 'key' => 'value', + 'jiguang' + ), + )) + // voip可以传输任意键值对,可用作自定义 + ->voip(array( + 'test123' => 'val1', + 'jsontest' => 2, + 'booleantest' => true + )) + ->message('message content', array( + 'title' => 'hello jpush', + // 'content_type' => 'text', + 'extras' => array( + 'key' => 'value', + 'jiguang' + ), + )) + ->options(array( + // sendno: 表示推送序号,纯粹用来作为 API 调用标识, + // API 返回时被原样返回,以方便 API 调用方匹配请求与返回 + // 这里设置为 100 仅作为示例 + + // 'sendno' => 100, + + // time_to_live: 表示离线消息保留时长(秒), + // 推送当前用户不在线时,为该用户保留多长时间的离线消息,以便其上线时再次推送。 + // 默认 86400 (1 天),最长 10 天。设置为 0 表示不保留离线消息,只有推送当前在线的用户可以收到 + // 这里设置为 1 仅作为示例 + + 'time_to_live' => 1, + + // apns_production: 表示APNs是否生产环境, + // True 表示推送生产环境,False 表示要推送开发环境;如果不指定则默认为推送开发环境 + + // 'apns_production' => false, + + // big_push_duration: 表示定速推送时长(分钟),又名缓慢推送,把原本尽可能快的推送速度,降低下来, + // 给定的 n 分钟内,均匀地向这次推送的目标用户推送。最大值为1400.未设置则不是定速推送 + // 这里设置为 1 仅作为示例 + + // 'big_push_duration' => 1 + )) + ->setSmsMessage(array( + 'delay_time' => 60, + 'signid' => 154, + 'temp_id' => 1, + 'temp_para' => array( + 'code' => 357 + ), + 'active_filter' => false + )) + // custom可自定义最外层参数,如skd未支持部分文档功能,用户可自行写入 + // 这里仅作为例子展示 + // ->custom(array( + // 'sms_message' => array( + // 'active_filter' => false, + // 'delay_time' => 60, + // 'signid' => 154, + // 'temp_id' => 1, + // 'temp_para' => array( + // 'code' => 357 + // )), + // 'options' => array( + // 'apns_production' => false, + // 'time_to_live' => 62000, + // ) + // )) + ->send(); + print_r($response); + +} catch (\JPush\Exceptions\APIConnectionException $e) { + // try something here + print $e; +} catch (\JPush\Exceptions\APIRequestException $e) { + // try something here + print $e; +} diff --git a/vendor/jpush/jpush/examples/reports/messages_detail_example.php b/vendor/jpush/jpush/examples/reports/messages_detail_example.php new file mode 100644 index 00000000..5f7a9ae6 --- /dev/null +++ b/vendor/jpush/jpush/examples/reports/messages_detail_example.php @@ -0,0 +1,5 @@ +report()->getMessagesDetail('149646415212'); +print_r($result); \ No newline at end of file diff --git a/vendor/jpush/jpush/examples/reports/received_detail_example.php b/vendor/jpush/jpush/examples/reports/received_detail_example.php new file mode 100644 index 00000000..b2dc5da2 --- /dev/null +++ b/vendor/jpush/jpush/examples/reports/received_detail_example.php @@ -0,0 +1,5 @@ +report()->getReceivedDetail('149646415212'); +print_r($result); \ No newline at end of file diff --git a/vendor/jpush/jpush/examples/schedule_example.php b/vendor/jpush/jpush/examples/schedule_example.php new file mode 100644 index 00000000..67d60f5b --- /dev/null +++ b/vendor/jpush/jpush/examples/schedule_example.php @@ -0,0 +1,26 @@ +push() + ->setPlatform("all") + ->addAllAudience() + ->setNotificationAlert("Hi, 这是一条定时发送的消息") + ->build(); + +// 创建一个2016-12-22 13:45:00触发的定时任务 +$response = $client->schedule()->createSingleSchedule("每天14点发送的定时任务", $payload, array("time"=>"2016-12-22 13:45:00")); +print_r($response); + +// 创建一个每天14点发送的定时任务 +$response = $client->schedule()->createPeriodicalSchedule("每天14点发送的定时任务", $payload, + array( + "start"=>"2016-12-22 13:45:00", + "end"=>"2016-12-25 13:45:00", + "time"=>"14:00:00", + "time_unit"=>"DAY", + "frequency"=>1 + )); +print_r($response); + diff --git a/vendor/jpush/jpush/examples/zone_examples.php b/vendor/jpush/jpush/examples/zone_examples.php new file mode 100644 index 00000000..377f334b --- /dev/null +++ b/vendor/jpush/jpush/examples/zone_examples.php @@ -0,0 +1,24 @@ +push() + ->setPlatform('all') + ->addAllAudience() + ->setNotificationAlert('Hi, JPush'); +try { + $response = $push_payload->send(); + print_r($response); +} catch (\JPush\Exceptions\APIConnectionException $e) { + // try something here + print $e; +} catch (\JPush\Exceptions\APIRequestException $e) { + // try something here + print $e; +} \ No newline at end of file diff --git a/vendor/jpush/jpush/phpunit.xml.dist b/vendor/jpush/jpush/phpunit.xml.dist new file mode 100644 index 00000000..2b8af6ee --- /dev/null +++ b/vendor/jpush/jpush/phpunit.xml.dist @@ -0,0 +1,15 @@ + + + + + tests/JPush + + + diff --git a/vendor/jpush/jpush/src/JPush/AdminClient.php b/vendor/jpush/jpush/src/JPush/AdminClient.php new file mode 100644 index 00000000..cfe96fd7 --- /dev/null +++ b/vendor/jpush/jpush/src/JPush/AdminClient.php @@ -0,0 +1,42 @@ +devKey = $devKey; + $this->devSecret = $devSecret; + $this->retryTimes = 1; + $this->logFile = null; + } + + public function getAuthStr() { return $this->devKey . ":" . $this->devSecret; } + public function getRetryTimes() { return $this->retryTimes; } + public function getLogFile() { return $this->logFile; } + + public function createApp($appName, $androidPackage, $groupName=null) { + $url = AdminClient::ADMIN_URL; + $body = [ + 'app_name' => $appName, + 'android_package'=> $androidPackage, + 'group_name' => $groupName + + ]; + return Http::post($this, $url, $body); + } + + public function deleteApp($appKey) { + $url = AdminClient::ADMIN_URL . $appKey . '/delete'; + return Http::post($this, $url, []); + } +} diff --git a/vendor/jpush/jpush/src/JPush/Client.php b/vendor/jpush/jpush/src/JPush/Client.php new file mode 100644 index 00000000..9c07d00c --- /dev/null +++ b/vendor/jpush/jpush/src/JPush/Client.php @@ -0,0 +1,71 @@ + [ + 'push' => 'https://api.jpush.cn/v3/', + 'report' => 'https://report.jpush.cn/v3/', + 'device' => 'https://device.jpush.cn/v3/devices/', + 'alias' => 'https://device.jpush.cn/v3/aliases/', + 'tag' => 'https://device.jpush.cn/v3/tags/', + 'schedule' => 'https://api.jpush.cn/v3/schedules' + ], + 'BJ' => [ + 'push' => 'https://bjapi.push.jiguang.cn/v3/', + 'report' => 'https://bjapi.push.jiguang.cn/v3/report/', + 'device' => 'https://bjapi.push.jiguang.cn/v3/device/', + 'alias' => 'https://bjapi.push.jiguang.cn/v3/device/aliases/', + 'tag' => 'https://bjapi.push.jiguang.cn/v3/device/tags/', + 'schedules' => 'https://bjapi.push.jiguang.cn/v3/push/schedules' + ] + ]; + + public function __construct($appKey, $masterSecret, $logFile=Config::DEFAULT_LOG_FILE, $retryTimes=Config::DEFAULT_MAX_RETRY_TIMES, $zone = null) { + if (!is_string($appKey) || !is_string($masterSecret)) { + throw new InvalidArgumentException("Invalid appKey or masterSecret"); + } + $this->appKey = $appKey; + $this->masterSecret = $masterSecret; + if (!is_null($retryTimes)) { + $this->retryTimes = $retryTimes; + } else { + $this->retryTimes = 1; + } + $this->logFile = $logFile; + if (!is_null($zone) && in_array(strtoupper($zone), array_keys(self::$zones))) { + $this->zone = strtoupper($zone); + } else { + $this->zone = null; + } + } + + public function push() { return new PushPayload($this); } + public function report() { return new ReportPayload($this); } + public function device() { return new DevicePayload($this); } + public function schedule() { return new SchedulePayload($this);} + + public function getAuthStr() { return $this->appKey . ":" . $this->masterSecret; } + public function getRetryTimes() { return $this->retryTimes; } + public function getLogFile() { return $this->logFile; } + + public function is_group() { + $str = substr($this->appKey, 0, 6); + return $str === 'group-'; + } + + public function makeURL($key) { + if (is_null($this->zone)) { + return self::$zones['DEFAULT'][$key]; + } else { + return self::$zones[$this->zone][$key]; + } + } +} diff --git a/vendor/jpush/jpush/src/JPush/Config.php b/vendor/jpush/jpush/src/JPush/Config.php new file mode 100644 index 00000000..e2007a10 --- /dev/null +++ b/vendor/jpush/jpush/src/JPush/Config.php @@ -0,0 +1,16 @@ +client = $client; + } + + public function getDevices($registrationId) { + $url = $this->client->makeURL('device') . $registrationId; + return Http::get($this->client, $url); + } + + public function updateAlias($registration_id, $alias) { + return $this->updateDevice($registration_id, $alias); + } + public function addTags($registration_id, $tags) { + $tags = is_array($tags) ? $tags : array($tags); + return $this->updateDevice($registration_id, null, null, $tags); + } + public function removeTags($registration_id, $tags) { + $tags = is_array($tags) ? $tags : array($tags); + return $this->updateDevice($registration_id, null, null, null, $tags); + } + public function updateMoblie($registration_id, $mobile) { + return $this->updateDevice($registration_id, null, $mobile); + } + + public function clearMobile($registrationId) { + $url = $this->client->makeURL('device') . $registrationId; + return Http::post($this->client, $url, ['mobile' => '']); + } + + public function clearTags($registrationId) { + $url = $this->client->makeURL('device') . $registrationId; + return Http::post($this->client, $url, ['tags' => '']); + } + + public function updateDevice($registrationId, $alias = null, $mobile = null, $addTags = null, $removeTags = null) { + $payload = array(); + if (!is_string($registrationId)) { + throw new InvalidArgumentException('Invalid registration_id'); + } + + $aliasIsNull = is_null($alias); + $mobileIsNull = is_null($mobile); + $addTagsIsNull = is_null($addTags); + $removeTagsIsNull = is_null($removeTags); + + if ($aliasIsNull && $addTagsIsNull && $removeTagsIsNull && $mobileIsNull) { + throw new InvalidArgumentException("alias, addTags, removeTags not all null"); + } + + if (!$aliasIsNull) { + if (is_string($alias)) { + $payload['alias'] = $alias; + } else { + throw new InvalidArgumentException("Invalid alias string"); + } + } + + if (!$mobileIsNull) { + if (is_string($mobile)) { + $payload['mobile'] = $mobile; + } else { + throw new InvalidArgumentException("Invalid mobile string"); + } + } + + $tags = array(); + + if (!$addTagsIsNull) { + if (is_array($addTags)) { + $tags['add'] = $addTags; + } else { + throw new InvalidArgumentException("Invalid addTags array"); + } + } + + if (!$removeTagsIsNull) { + if (is_array($removeTags)) { + $tags['remove'] = $removeTags; + } else { + throw new InvalidArgumentException("Invalid removeTags array"); + } + } + + if (count($tags) > 0) { + $payload['tags'] = $tags; + } + + $url = $this->client->makeURL('device') . $registrationId; + return Http::post($this->client, $url, $payload); + } + + public function getTags() { + $url = $this->client->makeURL('tag'); + return Http::get($this->client, $url); + } + + public function isDeviceInTag($registrationId, $tag) { + if (!is_string($registrationId)) { + throw new InvalidArgumentException("Invalid registration_id"); + } + + if (!is_string($tag)) { + throw new InvalidArgumentException("Invalid tag"); + } + $url = $this->client->makeURL('tag') . $tag . '/registration_ids/' . $registrationId; + return Http::get($this->client, $url); + } + + public function addDevicesToTag($tag, $addDevices) { + $device = is_array($addDevices) ? $addDevices : array($addDevices); + return $this->updateTag($tag, $device, null); + } + public function removeDevicesFromTag($tag, $removeDevices) { + $device = is_array($removeDevices) ? $removeDevices : array($removeDevices); + return $this->updateTag($tag, null, $device); + } + public function updateTag($tag, $addDevices = null, $removeDevices = null) { + if (!is_string($tag)) { + throw new InvalidArgumentException("Invalid tag"); + } + + $addDevicesIsNull = is_null($addDevices); + $removeDevicesIsNull = is_null($removeDevices); + + if ($addDevicesIsNull && $removeDevicesIsNull) { + throw new InvalidArgumentException("Either or both addDevices and removeDevices must be set."); + } + + $registrationId = array(); + + if (!$addDevicesIsNull) { + if (is_array($addDevices)) { + $registrationId['add'] = $addDevices; + } else { + throw new InvalidArgumentException("Invalid addDevices"); + } + } + + if (!$removeDevicesIsNull) { + if (is_array($removeDevices)) { + $registrationId['remove'] = $removeDevices; + } else { + throw new InvalidArgumentException("Invalid removeDevices"); + } + } + + $url = $this->client->makeURL('tag') . $tag; + $payload = array('registration_ids'=>$registrationId); + return Http::post($this->client, $url, $payload); + } + + public function deleteTag($tag) { + if (!is_string($tag)) { + throw new InvalidArgumentException("Invalid tag"); + } + $url = $this->client->makeURL('tag') . $tag; + return Http::delete($this->client, $url); + } + + public function getAliasDevices($alias, $platform = null) { + if (!is_string($alias)) { + throw new InvalidArgumentException("Invalid alias"); + } + + $url = $this->client->makeURL('alias') . $alias; + + if (!is_null($platform)) { + if (is_array($platform)) { + $isFirst = true; + foreach($platform as $item) { + if ($isFirst) { + $url = $url . '?platform=' . $item; + $isFirst = false; + } else { + $url = $url . ',' . $item; + } + } + } else if (is_string($platform)) { + $url = $url . '?platform=' . $platform; + } else { + throw new InvalidArgumentException("Invalid platform"); + } + } + return Http::get($this->client, $url); + } + + public function deleteAlias($alias) { + if (!is_string($alias)) { + throw new InvalidArgumentException("Invalid alias"); + } + $url = $this->client->makeURL('alias') . $alias; + return Http::delete($this->client, $url); + } + + public function getDevicesStatus($registrationId) { + if (!is_array($registrationId) && !is_string($registrationId)) { + throw new InvalidArgumentException('Invalid registration_id'); + } + + if (is_string($registrationId)) { + $registrationId = explode(',', $registrationId); + } + + $payload = array(); + if (count($registrationId) <= 0) { + throw new InvalidArgumentException('Invalid registration_id'); + } + $payload['registration_ids'] = $registrationId; + $url = $this->client->makeURL('device') . 'status'; + return Http::post($this->client, $url, $payload); + } +} diff --git a/vendor/jpush/jpush/src/JPush/Exceptions/APIConnectionException.php b/vendor/jpush/jpush/src/JPush/Exceptions/APIConnectionException.php new file mode 100644 index 00000000..e5dcb936 --- /dev/null +++ b/vendor/jpush/jpush/src/JPush/Exceptions/APIConnectionException.php @@ -0,0 +1,9 @@ +message} \n"; + } +} diff --git a/vendor/jpush/jpush/src/JPush/Exceptions/APIRequestException.php b/vendor/jpush/jpush/src/JPush/Exceptions/APIRequestException.php new file mode 100644 index 00000000..dc98b788 --- /dev/null +++ b/vendor/jpush/jpush/src/JPush/Exceptions/APIRequestException.php @@ -0,0 +1,36 @@ +http_code = $response['http_code']; + $this->headers = $response['headers']; + + $body = json_decode($response['body'], true); + + if (key_exists('error', $body)) { + $this->code = $body['error']['code']; + $this->message = $body['error']['message']; + } else { + $this->code = $body['code']; + $this->message = $body['message']; + } + } + + public function __toString() { + return "\n" . __CLASS__ . " -- [{$this->code}]: {$this->message} \n"; + } + + public function getHttpCode() { + return $this->http_code; + } + public function getHeaders() { + return $this->headers; + } + +} diff --git a/vendor/jpush/jpush/src/JPush/Exceptions/JPushException.php b/vendor/jpush/jpush/src/JPush/Exceptions/JPushException.php new file mode 100644 index 00000000..e59460a7 --- /dev/null +++ b/vendor/jpush/jpush/src/JPush/Exceptions/JPushException.php @@ -0,0 +1,9 @@ +http_code = $response['http_code']; + $this->headers = $response['headers']; + $this->message = $response['body']; + } + + function __toString() { + return "\n" . __CLASS__ . " -- [{$this->http_code}]: {$this->message} \n"; + } + + public function getHttpCode() { + return $this->http_code; + } + public function getHeaders() { + return $this->headers; + } +} diff --git a/vendor/jpush/jpush/src/JPush/Http.php b/vendor/jpush/jpush/src/JPush/Http.php new file mode 100644 index 00000000..20fe8bd0 --- /dev/null +++ b/vendor/jpush/jpush/src/JPush/Http.php @@ -0,0 +1,139 @@ +getAuthStr()); + curl_setopt($ch, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_2_0); + + // 设置Post参数 + if ($method === Config::HTTP_POST) { + curl_setopt($ch, CURLOPT_POST, true); + } else if ($method === Config::HTTP_DELETE || $method === Config::HTTP_PUT) { + curl_setopt($ch, CURLOPT_CUSTOMREQUEST, $method); + } + if (!is_null($body)) { + curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($body)); + } + + curl_setopt($ch, CURLOPT_HTTPHEADER, array( + 'Content-Type: application/json', + 'Connection: Keep-Alive' + )); + + $output = curl_exec($ch); + $response = array(); + $errorCode = curl_errno($ch); + + // $msg = ''; + // $data = json_decode($body, true); + // if (isset($data['options']['sendno'])) { + // $sendno = $data['options']['sendno']; + // $msg = 'sendno: ' . $sendno; + // } + + $msg = ''; + if (isset($body['options']['sendno'])) { + $sendno = $body['options']['sendno']; + $msg = 'sendno: ' . $sendno; + } + + + if ($errorCode) { + $retries = $client->getRetryTimes(); + if ($times < $retries) { + return self::sendRequest($client, $url, $method, $body, ++$times); + } else { + if ($errorCode === 28) { + throw new APIConnectionException($msg . "Response timeout. Your request has probably be received by JPush Server,please check that whether need to be pushed again." ); + } elseif ($errorCode === 56) { + // resolve error[56 Problem (2) in the Chunked-Encoded data] + throw new APIConnectionException($msg . "Response timeout, maybe cause by old CURL version. Your request has probably be received by JPush Server, please check that whether need to be pushed again."); + } else { + throw new APIConnectionException("$msg . Connect timeout. Please retry later. Error:" . $errorCode . " " . curl_error($ch)); + } + } + } else { + $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE); + $header_size = curl_getinfo($ch, CURLINFO_HEADER_SIZE); + $header_text = substr($output, 0, $header_size); + $body = substr($output, $header_size); + $headers = array(); + foreach (explode("\r\n", $header_text) as $i => $line) { + if (!empty($line)) { + if ($i === 0) { + $headers[0] = $line; + } else if (strpos($line, ": ")) { + list ($key, $value) = explode(': ', $line); + $headers[$key] = $value; + } + } + } + $response['headers'] = $headers; + $response['body'] = $body; + $response['http_code'] = $httpCode; + } + curl_close($ch); + return $response; + } + + public static function processResp($response) { + $data = json_decode($response['body'], true); + if ($response['http_code'] === 200) { + $result = array(); + $result['body'] = $data; + $result['http_code'] = $response['http_code']; + $result['headers'] = $response['headers']; + return $result; + } elseif (is_null($data)) { + throw new ServiceNotAvaliable($response); + } else { + throw new APIRequestException($response); + } + } + + public static function log($client, $content) { + if (!is_null($client->getLogFile())) { + error_log($content . "\r\n", 3, $client->getLogFile()); + } + } +} diff --git a/vendor/jpush/jpush/src/JPush/PushPayload.php b/vendor/jpush/jpush/src/JPush/PushPayload.php new file mode 100644 index 00000000..6a1d23ab --- /dev/null +++ b/vendor/jpush/jpush/src/JPush/PushPayload.php @@ -0,0 +1,761 @@ +client = $client; + $url = $this->client->is_group() ? 'grouppush' : 'push'; + $this->url = $this->client->makeURL('push') . $url; + } + + public function getCid($count = 1, $type = 'push') { + $url = $this->client->makeURL('push') . 'push/cid?count=' . $count . '&type=' . $type; + return Http::get($this->client, $url); + } + + public function setCid($cid) { + $this->cid = trim($cid); + return $this; + } + + public function setPlatform($platform) { + # $required_keys = array('all', 'android', 'ios', 'winphone'); + if (is_string($platform)) { + $ptf = strtolower($platform); + if ('all' === $ptf) { + $this->platform = 'all'; + } elseif (in_array($ptf, self::$EFFECTIVE_DEVICE_TYPES)) { + $this->platform = array($ptf); + } + } elseif (is_array($platform)) { + $ptf = array_map('strtolower', $platform); + $this->platform = array_intersect($ptf, self::$EFFECTIVE_DEVICE_TYPES); + } + return $this; + } + + public function setAudience($all) { + if (strtolower($all) === 'all') { + $this->addAllAudience(); + return $this; + } else { + throw new InvalidArgumentException('Invalid audience value'); + } + } + + public function addAllAudience() { + $this->audience = "all"; + return $this; + } + + public function addTag($tag) { + return $this->updateAudience('tags', $tag, 'tag'); + } + + public function addTagAnd($tag) { + return $this->updateAudience('tagAnds', $tag, 'tag_and'); + } + + public function addTagNot($tag) { + return $this->updateAudience('tagNots', $tag, 'tag_not'); + } + + public function addAlias($alias) { + return $this->updateAudience('alias', $alias, 'alias'); + } + + public function addRegistrationId($registrationId) { + return $this->updateAudience('registrationIds', $registrationId, 'registration_id'); + } + + public function addSegmentId($segmentId) { + return $this->updateAudience('segmentIds', $segmentId, 'segment'); + } + + public function addAbtest($abtest) { + return $this->updateAudience('abtests', $abtest, 'abtest'); + } + + private function updateAudience($key, $value, $name) { + if (is_null($this->$key)) { + $this->$key = array(); + } + + if (is_array($value)) { + foreach($value as $v) { + if (!is_string($v)) { + throw new InvalidArgumentException("Invalid $name value"); + } + if (!in_array($v, $this->$key)) { + array_push($this->$key, $v); + } + } + } else if (is_string($value)) { + if (!in_array($value, $this->$key)) { + array_push($this->$key, $value); + } + } else { + throw new InvalidArgumentException("Invalid $name value"); + } + + return $this; + } + + public function setNotificationAlert($alert) { + if (!is_string($alert)) { + throw new InvalidArgumentException("Invalid alert value"); + } + $this->notificationAlert = $alert; + return $this; + } + + public function addWinPhoneNotification($alert=null, $title=null, $_open_page=null, $extras=null) { + $winPhone = array(); + + if (!is_null($alert)) { + if (!is_string($alert)) { + throw new InvalidArgumentException("Invalid winphone notification"); + } + $winPhone['alert'] = $alert; + } + + if (!is_null($title)) { + if (!is_string($title)) { + throw new InvalidArgumentException("Invalid winphone title notification"); + } + if(strlen($title) > 0) { + $winPhone['title'] = $title; + } + } + + if (!is_null($_open_page)) { + if (!is_string($_open_page)) { + throw new InvalidArgumentException("Invalid winphone _open_page notification"); + } + if (strlen($_open_page) > 0) { + $winPhone['_open_page'] = $_open_page; + } + } + + if (!is_null($extras)) { + if (!is_array($extras)) { + throw new InvalidArgumentException("Invalid winphone extras notification"); + } + if (count($extras) > 0) { + $winPhone['extras'] = $extras; + } + } + + if (count($winPhone) <= 0) { + throw new InvalidArgumentException("Invalid winphone notification"); + } + + $this->winPhoneNotification = $winPhone; + return $this; + } + + public function setSms($delay_time, $temp_id, array $temp_para = []) { + $sms = array(); + $sms['temp_id'] = $temp_id; + $sms['delay_time'] = ($delay_time === 0 || (is_int($delay_time) && $delay_time > 0 && $delay_time <= 86400)) ? $delay_time : 0; + + if (!empty($temp_para)) { + $sms['temp_para'] = $temp_para; + } + + $this->smsMessage = $sms; + return $this; + } + + public function build() { + $payload = array(); + + // validate platform + if (is_null($this->platform)) { + throw new InvalidArgumentException("platform must be set"); + } + $payload["platform"] = $this->platform; + + if (!is_null($this->cid)) { + $payload['cid'] = $this->cid; + } + + // validate audience + $audience = array(); + if (!is_null($this->tags)) { + $audience["tag"] = $this->tags; + } + if (!is_null($this->tagAnds)) { + $audience["tag_and"] = $this->tagAnds; + } + if (!is_null($this->tagNots)) { + $audience["tag_not"] = $this->tagNots; + } + if (!is_null($this->alias)) { + $audience["alias"] = $this->alias; + } + if (!is_null($this->registrationIds)) { + $audience["registration_id"] = $this->registrationIds; + } + if (!is_null($this->segmentIds)) { + $audience["segment"] = $this->segmentIds; + } + if (!is_null($this->abtests)) { + $audience["abtest"] = $this->abtests; + } + if (is_null($this->audience) && count($audience) <= 0) { + throw new InvalidArgumentException("audience must be set"); + } else if (!is_null($this->audience) && count($audience) > 0) { + throw new InvalidArgumentException("you can't add tags/alias/registration_id/tag_and when audience='all'"); + } else if (is_null($this->audience)) { + $payload["audience"] = $audience; + } else { + $payload["audience"] = $this->audience; + } + + + // validate notification + $notification = array(); + + if (!is_null($this->notificationAlert)) { + $notification['alert'] = $this->notificationAlert; + } + + if (!is_null($this->androidNotification)) { + $notification['android'] = $this->androidNotification; + if (is_null($this->androidNotification['alert'])) { + if (is_null($this->notificationAlert)) { + throw new InvalidArgumentException("Android alert can not be null"); + } else { + $notification['android']['alert'] = $this->notificationAlert; + } + } + } + + if (!is_null($this->iosNotification)) { + $notification['ios'] = $this->iosNotification; + if (is_null($this->iosNotification['alert'])) { + if (is_null($this->notificationAlert)) { + throw new InvalidArgumentException("iOS alert can not be null"); + } else { + $notification['ios']['alert'] = $this->notificationAlert; + } + } + } + + if (!is_null($this->winPhoneNotification)) { + $notification['winphone'] = $this->winPhoneNotification; + if (is_null($this->winPhoneNotification['alert'])) { + if (is_null($this->winPhoneNotification)) { + throw new InvalidArgumentException("WinPhone alert can not be null"); + } else { + $notification['winphone']['alert'] = $this->notificationAlert; + } + } + } + + if (!is_null($this->voip)) { + $notification['voip'] = $this->voip; + } + + if (count($notification) > 0) { + $payload['notification'] = $notification; + } + + if (!is_null($this->message)) { + $payload['message'] = $this->message; + } + if (!array_key_exists('notification', $payload) && !array_key_exists('message', $payload)) { + throw new InvalidArgumentException('notification and message can not all be null'); + } + + if (!is_null($this->smsMessage)) { + $payload['sms_message'] = $this->smsMessage; + } + + if (is_null($this->options)) { + $this->options(); + } + + $payload['options'] = $this->options; + + if (!is_null($this->custom)) { + foreach($this->custom as $key=>$val) { + $payload[$key] = $val; + } + } + + return $payload; + } + + public function toJSON() { + $payload = $this->build(); + return json_encode($payload); + } + + public function printJSON() { + echo $this->toJSON(); + return $this; + } + + public function send() { + return Http::post($this->client, $this->url, $this->build()); + } + + public function validate() { + $url = $this->client->makeURL('push') . '/push/validate'; + return Http::post($this->client, $url, $this->build()); + } + + private function generateSendno() { + return rand(100000, getrandmax()); + } + + # new methods + public function iosNotification($alert = '', array $notification = array()) { + $ios = array(); + $ios['alert'] = (is_string($alert) || is_array($alert)) ? $alert : ''; + if (!empty($notification)) { + if (isset($notification['sound'])) { + if (is_string($notification['sound']) || is_array($notification['sound'])) { + $ios['sound'] = $notification['sound']; + } else { + unset($notification['sound']); + } + } + if (isset($notification['content-available'])) { + if (is_bool($notification['content-available'])) { + $ios['content-available'] = $notification['content-available']; + } else { + unset($notification['content-available']); + } + } + if (isset($notification['mutable-content'])) { + if (is_bool($notification['mutable-content'])) { + $ios['mutable-content'] = $notification['mutable-content']; + } else { + unset($notification['mutable-content']); + } + } + if (isset($notification['extras'])) { + if (is_array($notification['extras']) && !empty($notification['extras'])) { + $ios['extras'] = $notification['extras']; + } else { + unset($notification['extras']); + } + } + $ios = array_merge($notification, $ios); + } + if (!isset($ios['sound'])) { + $ios['sound'] = ''; + } + if (!isset($ios['badge'])) { + $ios['badge'] = '+1'; + } + $this->iosNotification = $ios; + return $this; + } + + public function androidNotification($alert = '', array $notification = array()) { + $android = array(); + $android['alert'] = is_string($alert) ? $alert : ''; + if (!empty($notification)) { + if (isset($notification['builder_id'])) { + if (is_int($notification['builder_id'])) { + $android['builder_id'] = $notification['builder_id']; + } else { + unset($notification['builder_id']); + } + } + if (isset($notification['priority'])) { + if (is_int($notification['priority'])) { + $android['priority'] = $notification['priority']; + } else { + unset($notification['priority']); + } + } + if (isset($notification['style'])) { + if (is_int($notification['style'])) { + $android['style'] = $notification['style']; + } else { + unset($notification['style']); + } + } + if (isset($notification['alert_type'])) { + if (is_int($notification['alert_type'])) { + $android['alert_type'] = $notification['alert_type']; + } else { + unset($notification['alert_type']); + } + } + if (isset($notification['inbox'])) { + if (is_array($notification['inbox']) && !empty($notification['inbox'])) { + $android['inbox'] = $notification['inbox']; + } else { + unset($notification['inbox']); + } + } + if (isset($notification['intent'])) { + if (is_array($notification['intent']) && !empty($notification['intent'])) { + $android['intent'] = $notification['intent']; + } else { + unset($notification['intent']); + } + } + if (isset($notification['extras'])) { + if (is_array($notification['extras']) && !empty($notification['extras'])) { + $android['extras'] = $notification['extras']; + } else { + unset($notification['extras']); + } + } + $android = array_merge($notification, $android); + } + $this->androidNotification = $android; + return $this; + } + + /** + * Voip in notification + * could add any custom key/value into it + */ + public function voip (array $extras = array()) { + $voip = array(); + if(!empty($extras)) { + foreach($extras as $key=>$val) { + $voip[$key] = $val; + } + } + $voip = array_merge($extras, $voip); + $this->voip=$voip; + return $this; + } + + public function message($msg_content, array $msg = array()) { + # $required_keys = array('title', 'content_type', 'extras'); + if (is_string($msg_content)) { + $message = array(); + $message['msg_content'] = $msg_content; + if (!empty($msg)) { + if (isset($msg['title']) && is_string($msg['title'])) { + $message['title'] = $msg['title']; + } + if (isset($msg['content_type']) && is_string($msg['content_type'])) { + $message['content_type'] = $msg['content_type']; + } + if (isset($msg['extras']) && is_array($msg['extras']) && !empty($msg['extras'])) { + $message['extras'] = $msg['extras']; + } + } + $this->message = $message; + } + return $this; + } + + public function options(array $opts = array()) { + # $required_keys = array('sendno', 'time_to_live', 'override_msg_id', 'apns_production', 'apns_collapse_id', 'big_push_duration'); + $options = array(); + if (isset($opts['sendno'])) { + $options['sendno'] = $opts['sendno']; + } else { + $options['sendno'] = $this->generateSendno(); + } + if (isset($opts['time_to_live']) && $opts['time_to_live'] <= 864000 && $opts['time_to_live'] >= 0) { + $options['time_to_live'] = $opts['time_to_live']; + } + if (isset($opts['override_msg_id'])) { + $options['override_msg_id'] = $opts['override_msg_id']; + } + if (isset($opts['apns_production'])) { + $options['apns_production'] = (bool)$opts['apns_production']; + } else { + $options['apns_production'] = false; + } + if (isset($opts['apns_collapse_id'])) { + $options['apns_collapse_id'] = $opts['apns_collapse_id']; + } + if (isset($opts['big_push_duration']) && $opts['big_push_duration'] <= 1400 && $opts['big_push_duration'] >= 0) { + $options['big_push_duration'] = $opts['big_push_duration']; + } + $options = array_merge($opts, $options); + $this->options = $options; + + return $this; + } + + public function custom (array $extras = array()) { + if(!empty($extras)) { + $this->custom=$extras; + } + return $this; + } + + ############################################################################### + ############# 以下函数已过期,不推荐使用,仅作为兼容接口存在 ######################### + ############################################################################### + public function addIosNotification($alert=null, $sound=null, $badge=null, $content_available=null, $category=null, $extras=null) { + $ios = array(); + + if (!is_null($alert)) { + if (!is_string($alert) && !is_array($alert)) { + throw new InvalidArgumentException("Invalid ios alert value"); + } + $ios['alert'] = $alert; + } + + if (!is_null($sound)) { + if (!is_string($sound)) { + throw new InvalidArgumentException("Invalid ios sound value"); + } + if ($sound !== Config::DISABLE_SOUND) { + $ios['sound'] = $sound; + } + } else { + // 默认sound为'' + $ios['sound'] = ''; + } + + if (!is_null($badge)) { + if (is_string($badge) && !preg_match("/^[+-]{1}[0-9]{1,3}$/", $badge)) { + if (!is_int($badge)) { + throw new InvalidArgumentException("Invalid ios badge value"); + } + } + if ($badge != Config::DISABLE_BADGE) { + $ios['badge'] = $badge; + } + } else { + // 默认badge为'+1' + $ios['badge'] = '+1'; + } + + if (!is_null($content_available)) { + if (!is_bool($content_available)) { + throw new InvalidArgumentException("Invalid ios content-available value"); + } + $ios['content-available'] = $content_available; + } + + if (!is_null($category)) { + if (!is_string($category)) { + throw new InvalidArgumentException("Invalid ios category value"); + } + if (strlen($category)) { + $ios['category'] = $category; + } + } + + if (!is_null($extras)) { + if (!is_array($extras)) { + throw new InvalidArgumentException("Invalid ios extras value"); + } + if (count($extras) > 0) { + $ios['extras'] = $extras; + } + } + + if (count($ios) <= 0) { + throw new InvalidArgumentException("Invalid iOS notification"); + } + + $this->iosNotification = $ios; + return $this; + } + + public function addAndroidNotification($alert=null, $title=null, $builderId=null, $extras=null) { + $android = array(); + + if (!is_null($alert)) { + if (!is_string($alert)) { + throw new InvalidArgumentException("Invalid android alert value"); + } + $android['alert'] = $alert; + } + + if (!is_null($title)) { + if(!is_string($title)) { + throw new InvalidArgumentException("Invalid android title value"); + } + if(strlen($title) > 0) { + $android['title'] = $title; + } + } + + if (!is_null($builderId)) { + if (!is_int($builderId)) { + throw new InvalidArgumentException("Invalid android builder_id value"); + } + $android['builder_id'] = $builderId; + } + + if (!is_null($extras)) { + if (!is_array($extras)) { + throw new InvalidArgumentException("Invalid android extras value"); + } + if (count($extras) > 0) { + $android['extras'] = $extras; + } + } + + if (count($android) <= 0) { + throw new InvalidArgumentException("Invalid android notification"); + } + + $this->androidNotification = $android; + return $this; + } + + public function setMessage($msg_content, $title=null, $content_type=null, $extras=null) { + $message = array(); + + if (is_null($msg_content) || !is_string($msg_content)) { + throw new InvalidArgumentException("Invalid message content"); + } else { + $message['msg_content'] = $msg_content; + } + + if (!is_null($title)) { + if (!is_string($title)) { + throw new InvalidArgumentException("Invalid message title"); + } + $message['title'] = $title; + } + + if (!is_null($content_type)) { + if (!is_string($content_type)) { + throw new InvalidArgumentException("Invalid message content type"); + } + $message["content_type"] = $content_type; + } + + if (!is_null($extras)) { + if (!is_array($extras)) { + throw new InvalidArgumentException("Invalid message extras"); + } + if (count($extras) > 0) { + $message['extras'] = $extras; + } + } + + $this->message = $message; + return $this; + } + + public function setSmsMessage($smsMessage) { + $this->smsMessage = $smsMessage; + return $this; + } + + public function setOptions($sendno=null, $time_to_live=null, $override_msg_id=null, $apns_production=null, $big_push_duration=null) { + $options = array(); + + if (!is_null($sendno)) { + if (!is_int($sendno)) { + throw new InvalidArgumentException('Invalid option sendno'); + } + $options['sendno'] = $sendno; + } else { + $options['sendno'] = $this->generateSendno(); + } + + if (!is_null($time_to_live)) { + if (!is_int($time_to_live) || $time_to_live < 0 || $time_to_live > 864000) { + throw new InvalidArgumentException('Invalid option time to live, it must be a int and in [0, 864000]'); + } + $options['time_to_live'] = $time_to_live; + } + + if (!is_null($override_msg_id)) { + if (!is_long($override_msg_id)) { + throw new InvalidArgumentException('Invalid option override msg id'); + } + $options['override_msg_id'] = $override_msg_id; + } + + if (!is_null($apns_production)) { + if (!is_bool($apns_production)) { + throw new InvalidArgumentException('Invalid option apns production'); + } + $options['apns_production'] = $apns_production; + } else { + $options['apns_production'] = false; + } + + if (!is_null($big_push_duration)) { + if (!is_int($big_push_duration) || $big_push_duration < 0 || $big_push_duration > 1440) { + throw new InvalidArgumentException('Invalid option big push duration, it must be a int and in [0, 1440]'); + } + $options['big_push_duration'] = $big_push_duration; + } + + $this->options = $options; + return $this; + } + + /* + 针对RegID方式批量单推 + https://docs.jiguang.cn/jpush/server/push/rest_api_v3_push/#vip + */ + public function batchPushByRegid(array $singlePayloads) { + $body = array( + "pushlist"=>array() + ); + $response = $this -> getCid(count($singlePayloads), 'push'); + $cidlist = $response['body']['cidlist']; + foreach ($cidlist as $i => $cid) { + $body["pushlist"][$cid] = $singlePayloads[$i]; + } + $url = $this->client->makeURL('push') . 'push/batch/regid/single'; + return Http::post($this->client, $url, $body); + } + + /* + 针对Alias方式批量单推 + https://docs.jiguang.cn/jpush/server/push/rest_api_v3_push/#vip + */ + public function batchPushByAlias(array $singlePayloads) { + $body = array( + "pushlist"=>array() + ); + $response = $this -> getCid(count($singlePayloads), 'push'); + $cidlist = $response['body']['cidlist']; + foreach ($cidlist as $i => $cid) { + $body["pushlist"][$cid] = $singlePayloads[$i]; + } + $url = $this->client->makeURL('push') . 'push/batch/alias/single'; + return Http::post($this->client, $url, $body); + } +} diff --git a/vendor/jpush/jpush/src/JPush/ReportPayload.php b/vendor/jpush/jpush/src/JPush/ReportPayload.php new file mode 100644 index 00000000..520137d1 --- /dev/null +++ b/vendor/jpush/jpush/src/JPush/ReportPayload.php @@ -0,0 +1,109 @@ +client = $client; + } + + public function getReceived($msgIds) { + $queryParams = '?msg_ids='; + if (is_array($msgIds) && !empty($msgIds)) { + $msgIdsStr = implode(',', $msgIds); + $queryParams .= $msgIdsStr; + } elseif (is_string($msgIds)) { + $queryParams .= $msgIds; + } else { + throw new InvalidArgumentException("Invalid msg_ids"); + } + + $url = $this->client->makeURL('report') . 'received' . $queryParams; + return Http::get($this->client, $url); + } + + /* + 送达统计详情(新) + https://docs.jiguang.cn/jpush/server/push/rest_api_v3_report/#_7 + */ + public function getReceivedDetail($msgIds) { + $queryParams = '?msg_ids='; + if (is_array($msgIds) && !empty($msgIds)) { + $msgIdsStr = implode(',', $msgIds); + $queryParams .= $msgIdsStr; + } elseif (is_string($msgIds)) { + $queryParams .= $msgIds; + } else { + throw new InvalidArgumentException("Invalid msg_ids"); + } + + $url = $this->client->makeURL('report') . 'received/detail' . $queryParams; + return Http::get($this->client, $url); + } + + public function getMessageStatus($msgId, $rids, $data = null) { + $url = $this->client->makeURL('report') . 'status/message'; + $registrationIds = is_array($rids) ? $rids : array($rids); + $body = [ + 'msg_id' => $msgId, + 'registration_ids' => $registrationIds + ]; + if (!is_null($data)) { + $body['data'] = $data; + } + return Http::post($this->client, $url, $body); + } + + public function getMessages($msgIds) { + $queryParams = '?msg_ids='; + if (is_array($msgIds) && !empty($msgIds)) { + $msgIdsStr = implode(',', $msgIds); + $queryParams .= $msgIdsStr; + } elseif (is_string($msgIds)) { + $queryParams .= $msgIds; + } else { + throw new InvalidArgumentException("Invalid msg_ids"); + } + + $url = $this->client->makeURL('report') . 'messages/' .$queryParams; + return Http::get($this->client, $url); + } + + /* + 消息统计详情(VIP 专属接口,新) + https://docs.jiguang.cn/jpush/server/push/rest_api_v3_report/#vip_1 + */ + public function getMessagesDetail($msgIds) { + $queryParams = '?msg_ids='; + if (is_array($msgIds) && !empty($msgIds)) { + $msgIdsStr = implode(',', $msgIds); + $queryParams .= $msgIdsStr; + } elseif (is_string($msgIds)) { + $queryParams .= $msgIds; + } else { + throw new InvalidArgumentException("Invalid msg_ids"); + } + + $url = $this->client->makeURL('report') . 'messages/detail' .$queryParams; + return Http::get($this->client, $url); + } + + public function getUsers($time_unit, $start, $duration) { + $time_unit = strtoupper($time_unit); + if (!in_array($time_unit, self::$EFFECTIVE_TIME_UNIT)) { + throw new InvalidArgumentException('Invalid time unit'); + } + + $url = $this->client->makeURL('report') . 'users/?time_unit=' . $time_unit . '&start=' . $start . '&duration=' . $duration; + return Http::get($this->client, $url); + } +} diff --git a/vendor/jpush/jpush/src/JPush/SchedulePayload.php b/vendor/jpush/jpush/src/JPush/SchedulePayload.php new file mode 100644 index 00000000..5f35262e --- /dev/null +++ b/vendor/jpush/jpush/src/JPush/SchedulePayload.php @@ -0,0 +1,182 @@ +client = $client; + } + + public function createSingleSchedule($name, $push_payload, $trigger) { + if (!is_string($name)) { + throw new InvalidArgumentException('Invalid schedule name'); + } + if (!is_array($push_payload)) { + throw new InvalidArgumentException('Invalid schedule push payload'); + } + if (!is_array($trigger)) { + throw new InvalidArgumentException('Invalid schedule trigger'); + } + $payload = array(); + $payload['name'] = $name; + $payload['enabled'] = true; + $payload['trigger'] = array("single"=>$trigger); + $payload['push'] = $push_payload; + + $url = $this->client->makeURL('schedule'); + return Http::post($this->client, $url, $payload); + } + + public function createPeriodicalSchedule($name, $push_payload, $trigger) { + if (!is_string($name)) { + throw new InvalidArgumentException('Invalid schedule name'); + } + if (!is_array($push_payload)) { + throw new InvalidArgumentException('Invalid schedule push payload'); + } + if (!is_array($trigger)) { + throw new InvalidArgumentException('Invalid schedule trigger'); + } + $payload = array(); + $payload['name'] = $name; + $payload['enabled'] = true; + $payload['trigger'] = array("periodical"=>$trigger); + $payload['push'] = $push_payload; + + $url = $this->client->makeURL('schedule'); + return Http::post($this->client, $url, $payload); + } + + public function updateSingleSchedule($schedule_id, $name=null, $enabled=null, $push_payload=null, $trigger=null) { + if (!is_string($schedule_id)) { + throw new InvalidArgumentException('Invalid schedule id'); + } + $payload = array(); + if (!is_null($name)) { + if (!is_string($name)) { + throw new InvalidArgumentException('Invalid schedule name'); + } else { + $payload['name'] = $name; + } + } + + if (!is_null($enabled)) { + if (!is_bool($enabled)) { + throw new InvalidArgumentException('Invalid schedule enable'); + } else { + $payload['enabled'] = $enabled; + } + } + + if (!is_null($push_payload)) { + if (!is_array($push_payload)) { + throw new InvalidArgumentException('Invalid schedule push payload'); + } else { + $payload['push'] = $push_payload; + } + } + + if (!is_null($trigger)) { + if (!is_array($trigger)) { + throw new InvalidArgumentException('Invalid schedule trigger'); + } else { + $payload['trigger'] = array("single"=>$trigger); + } + } + + if (count($payload) <= 0) { + throw new InvalidArgumentException('Invalid schedule, name, enabled, trigger, push can not all be null'); + } + + $url = $this->client->makeURL('schedule') . "/" . $schedule_id; + + return Http::put($this->client, $url, $payload); + + } + + public function updatePeriodicalSchedule($schedule_id, $name=null, $enabled=null, $push_payload=null, $trigger=null) { + if (!is_string($schedule_id)) { + throw new InvalidArgumentException('Invalid schedule id'); + } + $payload = array(); + if (!is_null($name)) { + if (!is_string($name)) { + throw new InvalidArgumentException('Invalid schedule name'); + } else { + $payload['name'] = $name; + } + } + + if (!is_null($enabled)) { + if (!is_bool($enabled)) { + throw new InvalidArgumentException('Invalid schedule enable'); + } else { + $payload['enabled'] = $enabled; + } + } + + if (!is_null($push_payload)) { + if (!is_array($push_payload)) { + throw new InvalidArgumentException('Invalid schedule push payload'); + } else { + $payload['push'] = $push_payload; + } + } + + if (!is_null($trigger)) { + if (!is_array($trigger)) { + throw new InvalidArgumentException('Invalid schedule trigger'); + } else { + $payload['trigger'] = array("periodical"=>$trigger); + } + } + + if (count($payload) <= 0) { + throw new InvalidArgumentException('Invalid schedule, name, enabled, trigger, push can not all be null'); + } + + $url = $this->client->makeURL('schedule') . "/" . $schedule_id; + return Http::put($this->client, $url, $payload); + } + + public function getSchedules($page = 1) { + if (!is_int($page)) { + $page = 1; + } + $url = $this->client->makeURL('schedule') . "?page=" . $page; + return Http::get($this->client, $url); + } + + public function getSchedule($schedule_id) { + if (!is_string($schedule_id)) { + throw new InvalidArgumentException('Invalid schedule id'); + } + $url = $this->client->makeURL('schedule') . "/" . $schedule_id; + return Http::get($this->client, $url); + } + + public function deleteSchedule($schedule_id) { + if (!is_string($schedule_id)) { + throw new InvalidArgumentException('Invalid schedule id'); + } + $url = $this->client->makeURL('schedule') . "/" . $schedule_id; + return Http::delete($this->client, $url); + } + + public function getMsgIds($schedule_id) { + if (!is_string($schedule_id)) { + throw new InvalidArgumentException('Invalid schedule id'); + } + $url = $this->client->makeURL('schedule') . '/' . $schedule_id . '/msg_ids'; + return Http::get($this->client, $url); + } + +} + diff --git a/vendor/jpush/jpush/src/JPush/version.php b/vendor/jpush/jpush/src/JPush/version.php new file mode 100644 index 00000000..31f70473 --- /dev/null +++ b/vendor/jpush/jpush/src/JPush/version.php @@ -0,0 +1,4 @@ +device = $client->device(); + $this->test_tag = 'jpush_tag'; + } + + function testGetDevices() { + global $registration_id; + $response = $this->device->getDevices($registration_id); + $this->assertEquals('200', $response['http_code']); + + echo "HTTP HEADERS ARE: "; + print_r($response['headers']); + + $body = $response['body']; + $this->assertTrue(is_array($body)); + $this->assertEquals(3, count($body)); + $this->assertArrayHasKey('tags', $body); + $this->assertArrayHasKey('alias', $body); + $this->assertArrayHasKey('mobile', $body); + $this->assertTrue(is_array($body['tags'])); + } + + /** + * @expectedException \JPush\Exceptions\APIRequestException + * @expectedExceptionCode 7002 + */ + function testGetDevicesWithInvalidRid() { + $response = $this->device->getDevices('INVALID_REGISTRATION_ID'); + } + + function testUpdateDevicesAlias() { + global $registration_id; + $result = $this->device->getDevices($registration_id); + $old_alias = $result['body']['alias']; + if ($old_alias == null) { + $old_alias = ''; + } + $new_alias = 'jpush_alias'; + if ($old_alias == $new_alias) { + $new_alias = $new_alias . time(); + } + $response = $this->device->updateAlias($registration_id, $new_alias); + $this->assertEquals('200', $response['http_code']); + + $response = $this->device->updateAlias($registration_id, $old_alias); + $this->assertEquals('200', $response['http_code']); + } + + function testUpdateDevicesTags() { + global $registration_id; + $new_tag = $this->test_tag; + + $response = $this->device->addTags($registration_id, array($new_tag)); + $this->assertEquals('200', $response['http_code']); + + $response = $this->device->removeTags($registration_id, array($new_tag)); + $this->assertEquals('200', $response['http_code']); + } + + function testGetTags() { + $response = $this->device->getTags(); + $this->assertEquals('200', $response['http_code']); + + $body = $response['body']; + $this->assertTrue(is_array($body)); + $this->assertEquals(1, count($body)); + $this->assertArrayHasKey('tags', $body); + } + + function testIsDeviceInTag() { + global $registration_id; + $test_tag = $this->test_tag; + + $this->device->addTags($registration_id, array($test_tag)); + $response = $this->device->isDeviceInTag($registration_id, $test_tag); + $this->assertEquals('200', $response['http_code']); + $body = $response['body']; + $this->assertTrue(is_array($body)); + $this->assertTrue($body['result']); + + $this->device->removeTags($registration_id, array($test_tag)); + $response = $this->device->isDeviceInTag($registration_id, $test_tag); + $this->assertEquals('200', $response['http_code']); + $body = $response['body']; + $this->assertTrue(is_array($body)); + $this->assertFalse($body['result']); + } + + function testUpdateTag() { + global $registration_id; + $test_tag = $this->test_tag; + + $response = $this->device->addDevicesToTag($test_tag, array($registration_id)); + $this->assertEquals('200', $response['http_code']); + + $response = $this->device->removeDevicesFromTag($test_tag, array($registration_id)); + $this->assertEquals('200', $response['http_code']); + } + + function testDeleteTag() {} + + function testGetAliasDevices() { + $test_tag = $this->test_tag; + + $response = $this->device->getAliasDevices($test_tag); + $this->assertEquals('200', $response['http_code']); + $body = $response['body']; + $this->assertTrue(is_array($body)); + $this->assertEquals(1, count($body)); + $this->assertArrayHasKey('registration_ids', $body); + } + + function testDeleteAlias() {} + + function testGetDevicesStatus() { + global $registration_id; + $response = $this->device->getDevicesStatus($registration_id); + $this->assertEquals('200', $response['http_code']); + $body = $response['body']; + $this->assertTrue(is_array($body)); + $this->assertEquals(1, count($body)); + } + +} diff --git a/vendor/jpush/jpush/tests/JPush/PushPayloadTest.php b/vendor/jpush/jpush/tests/JPush/PushPayloadTest.php new file mode 100644 index 00000000..2bd300c7 --- /dev/null +++ b/vendor/jpush/jpush/tests/JPush/PushPayloadTest.php @@ -0,0 +1,315 @@ +payload = $client->push() + ->setPlatform('all') + ->addAllAudience() + ->setNotificationAlert('Hello JPush'); + + $this->payload_without_audience = $client->push() + ->setPlatform('all') + ->setNotificationAlert('Hello JPush'); + } + + public function testSimplePushToAll() { + $payload = $this->payload; + $result = $payload->build(); + + $this->assertTrue(is_array($result)); + $this->assertEquals(4, count($result)); + $this->assertArrayHasKey('platform', $result); + $this->assertArrayHasKey('audience', $result); + $this->assertArrayHasKey('notification', $result); + $this->assertArrayHasKey('options', $result); + } + + public function testSetPlatform() { + $payload = $this->payload; + + $result = $payload->build(); + $this->assertEquals('all', $result['platform']); + + $result = $payload->setPlatform('ios')->build(); + $this->assertTrue(is_array($result['platform'])); + $this->assertEquals(1, count($result['platform'])); + $this->assertTrue(in_array('ios', $result['platform'])); + + $result = $payload->setPlatform(array('ios', 'android', 'blackberry'))->build(); + $this->assertTrue(is_array($result['platform'])); + $this->assertEquals(2, count($result['platform'])); + $this->assertFalse(in_array('blackberry', $result['platform'])); + } + + public function testSetAudience() { + $result = $this->payload->build(); + $this->assertEquals('all', $result['audience']); + } + + public function testAddTag() { + $payload = $this->payload_without_audience; + $result = $payload->addTag('hello')->build(); + $audience = $result['audience']; + $this->assertTrue(is_array($audience['tag'])); + $this->assertEquals(1, count($audience['tag'])); + + $result = $payload->addTag(array('jpush', 'jiguang'))->build(); + $this->assertEquals(3, count($result['audience']['tag'])); + } + public function testAddTag2() { + $payload = $this->payload_without_audience; + $result = $payload->addTagAnd(array('jpush', 'jiguang'))->build(); + $audience = $result['audience']; + $this->assertTrue(is_array($audience['tag_and'])); + $this->assertEquals(2, count($audience['tag_and'])); + + $result = $payload->addTagAnd('hello')->build(); + $this->assertEquals(3, count($result['audience']['tag_and'])); + } + + public function testAddTagAnd1() { + $payload = $this->payload_without_audience; + $result = $payload->addTagAnd('hello')->build(); + $audience = $result['audience']; + $this->assertTrue(is_array($audience['tag_and'])); + $this->assertEquals(1, count($audience['tag_and'])); + + $result = $payload->addTagAnd(array('jpush', 'jiguang'))->build(); + $this->assertEquals(3, count($result['audience']['tag_and'])); + } + public function testAddTagAnd2() { + $payload = $this->payload_without_audience; + $result = $payload->addTagAnd(array('jpush', 'jiguang'))->build(); + $audience = $result['audience']; + $this->assertTrue(is_array($audience['tag_and'])); + $this->assertEquals(2, count($audience['tag_and'])); + + $result = $payload->addTagAnd('hello')->build(); + $this->assertEquals(3, count($result['audience']['tag_and'])); + } + + public function testAddRegistrationId1() { + $payload = $this->payload_without_audience; + $result = $payload->addRegistrationId('hello')->build(); + $audience = $result['audience']; + $this->assertTrue(is_array($audience['registration_id'])); + $this->assertEquals(1, count($audience['registration_id'])); + + $result = $payload->addRegistrationId(array('jpush', 'jiguang'))->build(); + $this->assertEquals(3, count($result['audience']['registration_id'])); + } + public function testAddRegistrationId2() { + $payload = $this->payload_without_audience; + $result = $payload->addRegistrationId(array('jpush', 'jiguang'))->build(); + $audience = $result['audience']; + $this->assertTrue(is_array($audience['registration_id'])); + $this->assertEquals(2, count($audience['registration_id'])); + + $result = $payload->addRegistrationId('hello')->build(); + $this->assertEquals(3, count($result['audience']['registration_id'])); + } + + public function testSetNotificationAlert() { + $result = $this->payload->build(); + $notification = $result['notification']; + $this->assertTrue(is_array($notification)); + $this->assertEquals(1, count($notification)); + $this->assertEquals('Hello JPush', $result['notification']['alert']); + } + + public function testIosNotification() { + $payload = $this->payload; + $result = $payload->iosNotification()->build(); + $ios = $result['notification']['ios']; + $this->assertTrue(is_array($ios)); + $this->assertEquals(3, count($ios)); + $this->assertArrayHasKey('alert', $ios); + $this->assertArrayHasKey('sound', $ios); + $this->assertArrayHasKey('badge', $ios); + $this->assertEquals('', $ios['alert']); + $this->assertEquals('', $ios['sound']); + $this->assertEquals('+1', $ios['badge']); + + $result = $payload->iosNotification('hello')->build(); + $ios = $result['notification']['ios']; + $this->assertEquals('hello', $result['notification']['ios']['alert']); + } + public function testIosNotificationWithArray() { + $payload = $this->payload; + $alert_array = array( + 'alert_k1' => 'alert_v1', + 'alert_k2' => 'alert_v2', + 'alert_k3' => 'alert_v3', + 'alert_k4' => 'alert_v4' + ); + $array = array( + 'sound' => 'jpush.caf', + 'badge' => 2, + 'content-available' => true, + 'category' => 'jiguang', + 'extras' => array( + 'key' => 'value', + 'jiguang' + ), + 'invalid_key' => 'invalid_value' + ); + $result = $payload->iosNotification($alert_array, $array)->build(); + $ios = $result['notification']['ios']; + $this->assertTrue(is_array($ios['alert'])); + $this->assertEquals(6, count($ios)); + $this->assertFalse(array_key_exists('invalid_key', $ios)); + } + + public function testAndroidNotification() { + $payload = $this->payload; + $result = $payload->androidNotification()->build(); + $android = $result['notification']['android']; + $this->assertTrue(is_array($android)); + $this->assertEquals(1, count($android)); + $this->assertArrayHasKey('alert', $android); + $this->assertEquals('', $android['alert']); + + $result = $payload->androidNotification('hello')->build(); + $android = $result['notification']['android']; + $this->assertEquals('hello', $result['notification']['android']['alert']); + } + public function testAndroidNotificationWithArray() { + $payload = $this->payload; + $array = array( + 'title' => 'hello jpush', + 'builder_id' => 2, + 'extras' => array( + 'key' => 'value', + 'jiguang' + ), + 'invalid_key' => 'invalid_value' + ); + $result = $payload->androidNotification('', $array)->build(); + $android = $result['notification']['android']; + $this->assertEquals(4, count($android)); + $this->assertFalse(array_key_exists('invalid_key', $android)); + } + + public function testSetSmsMessage() { + $payload = $this->payload; + $smsMessage = array( + 'delay_time' => 60, + 'signid' => 154, + 'temp_id' => 1, + 'temp_para' => array( + 'code' => 357 + ), + 'active_filter' => false + ); + $result = $payload->setSmsMessage($smsMessage)->build(); + $sms = $result['sms_message']; + $this->assertTrue(is_array($sms)); + $this->assertEquals(5, count($sms)); + $this->assertEquals(60, $sms['delay_time']); + $this->assertEquals(154, $sms['signid']); + $this->assertEquals(1, $sms['temp_id']); + } + + public function testMessage() { + $payload = $this->payload; + $result = $payload->message('Hello JPush')->build(); + $message = $result['message']; + $this->assertTrue(is_array($message)); + $this->assertEquals(1, count($message)); + $this->assertEquals('Hello JPush', $message['msg_content']); + + $array = array( + 'title' => 'hello jpush', + 'content_type' => '', + 'extras' => array( + 'key' => 'value', + 'jiguang' + ), + 'invalid_key' => 'invalid_value' + ); + $result = $payload->message('Hello JPush', $array)->build(); + } + + public function testOptions() { + $payload = $this->payload; + $result = $payload->options()->build(); + $this->assertTrue(array_key_exists('options', $result)); + $this->assertEquals(false, $result['options']['apns_production']); + $this->assertTrue(array_key_exists('sendno', $result['options'])); + + $array = array( + 'sendno' => 100, + 'time_to_live' => 100, + 'apns_production' => true, + 'override_msg_id' => 100, + 'big_push_duration' => 100 + ); + $result = $payload->options($array)->build(); + $options = $result['options']; + $this->assertEquals(5, count($options)); + $this->assertArrayHasKey('apns_production', $options); + $this->assertEquals(true, $options['apns_production']); + } + + public function testPushToAll() { + $payload = $this->payload; + $platform = array('ios', 'android', 'blackberry'); + $ios_alert = array( + 'k1' => 'v1', + 'k2' => 'v2', + 'k3' => 'v3', + 'k4' => 'v4' + ); + $ios_notification = array( + 'sound' => 'jpush.caf', + 'badge' => 2, + 'content-available' => true, + 'category' => 'jiguang', + 'extras' => array( + 'key' => 'value', + 'jiguang' + ), + 'invalid_key' => 'invalid_value' + ); + $android_notification = array( + 'title' => 'hello jpush', + 'builder_id' => 2, + 'extras' => array( + 'key' => 'value', + 'jiguang' + ), + 'invalid_key' => 'invalid_value' + ); + $message = array( + 'title' => 'hello jpush', + 'content_type' => '', + 'extras' => array( + 'key' => 'value', + 'jiguang' + ), + 'invalid_key' => 'invalid_value' + ); + + $result = $payload->setPlatform($platform) + ->iosNotification($ios_alert, $ios_notification) + ->androidNotification('Hello Android', $android_notification) + ->message('Hello JPush', $message) + ->build(); + + $response = $payload->send(); + $this->assertEquals('200', $response['http_code']); + + echo "HTTP HEADERS ARE: "; + print_r($response['headers']); + + $body = $response['body']; + $this->assertTrue(is_array($body)); + $this->assertEquals(2, count($body)); + $this->assertArrayHasKey('sendno', $body); + $this->assertArrayHasKey('msg_id', $body); + } +} diff --git a/vendor/jpush/jpush/tests/JPush/ReportPayloadTest.php b/vendor/jpush/jpush/tests/JPush/ReportPayloadTest.php new file mode 100644 index 00000000..f86ca766 --- /dev/null +++ b/vendor/jpush/jpush/tests/JPush/ReportPayloadTest.php @@ -0,0 +1,77 @@ +payload = $client->push() + ->setPlatform('all') + ->addAllAudience() + ->setNotificationAlert('Hello JPush'); + $this->reporter = $client->report(); + } + + public function testPusher0() { + $payload = $this->payload; + $response = $payload->send(); + + $this->assertEquals('200', $response['http_code']); + $body = $response['body']; + $this->assertTrue(is_array($body)); + $this->assertEquals(2, count($body)); + $this->assertArrayHasKey('sendno', $body); + $this->assertArrayHasKey('msg_id', $body); + sleep(10); + return $body['msg_id']; + } + public function testPusher1() { + $payload = $this->payload; + $response = $payload->send(); + $this->assertEquals('200', $response['http_code']); + sleep(10); + return $response['body']['msg_id']; + } + + /** + * @depends testPusher0 + * @depends testPusher1 + */ + public function testGetReceived($msg_id_0, $msg_id_1) { + $response = $this->reporter->getReceived($msg_id_0); + $this->assertEquals('200', $response['http_code']); + $body = $response['body']; + $this->assertTrue(is_array($body)); + $this->assertEquals(1, count($body)); + $this->assertTrue(is_array($body[0])); + $this->assertArrayHasKey('msg_id', $body[0]); + + $response = $this->reporter->getReceived(array($msg_id_0, $msg_id_1)); + $this->assertEquals('200', $response['http_code']); + $body = $response['body']; + $this->assertTrue(is_array($body)); + $this->assertEquals(2, count($body)); + } + + /** + * @depends testPusher0 + * @depends testPusher1 + */ + public function testGetMessages($msg_id_0, $msg_id_1) { + $response = $this->reporter->getMessages($msg_id_0); + $this->assertEquals('200', $response['http_code']); + $body = $response['body']; + $this->assertTrue(is_array($body)); + $this->assertEquals(1, count($body)); + $this->assertTrue(is_array($body[0])); + $this->assertEquals(4, count($body[0])); + $this->assertArrayHasKey('msg_id', $body[0]); + + $response = $this->reporter->getMessages(array($msg_id_0, $msg_id_1)); + $this->assertEquals('200', $response['http_code']); + $body = $response['body']; + $this->assertTrue(is_array($body)); + $this->assertEquals(2, count($body)); + } +} diff --git a/vendor/jpush/jpush/tests/JPush/SchedulePayloadTest.php b/vendor/jpush/jpush/tests/JPush/SchedulePayloadTest.php new file mode 100644 index 00000000..391738e1 --- /dev/null +++ b/vendor/jpush/jpush/tests/JPush/SchedulePayloadTest.php @@ -0,0 +1,18 @@ +schedule = $client->schedule(); + } + + public function testGetSchedules() { + $schedule = $this->schedule; + $response = $schedule->getSchedules(); + $this->assertEquals('200', $response['http_code']); + } + +} diff --git a/vendor/jpush/jpush/tests/bootstrap.php b/vendor/jpush/jpush/tests/bootstrap.php new file mode 100644 index 00000000..bfe7e844 --- /dev/null +++ b/vendor/jpush/jpush/tests/bootstrap.php @@ -0,0 +1,8 @@ + Date: Fri, 30 Jun 2023 17:27:43 +0800 Subject: [PATCH 3/3] =?UTF-8?q?=E8=B0=83=E8=AF=95=E6=9E=81=E5=85=89?= =?UTF-8?q?=E6=8E=A8=E9=80=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../system/notice/SystemNoticeConfigDao.php | 2 +- app/common/service/JgPush.php | 200 ++++++++++++++++++ app/controller/api/Auth.php | 19 ++ crmeb/jobs/SendSmsJob.php | 13 ++ route/api.php | 2 + 5 files changed, 235 insertions(+), 1 deletion(-) create mode 100644 app/common/service/JgPush.php diff --git a/app/common/dao/system/notice/SystemNoticeConfigDao.php b/app/common/dao/system/notice/SystemNoticeConfigDao.php index ae2307a3..12c54e96 100644 --- a/app/common/dao/system/notice/SystemNoticeConfigDao.php +++ b/app/common/dao/system/notice/SystemNoticeConfigDao.php @@ -34,7 +34,7 @@ class SystemNoticeConfigDao extends BaseDao public function getNoticeStatusByConstKey(string $key) { - $value = $this->getModel()::getDb()->where('const_key',$key)->field('notice_sys,notice_wechat,notice_routine,notice_sms')->find(); + $value = $this->getModel()::getDb()->where('const_key',$key)->field('notice_sys,notice_wechat,notice_routine,notice_sms,notice_app')->find(); return $value; } diff --git a/app/common/service/JgPush.php b/app/common/service/JgPush.php new file mode 100644 index 00000000..4a0af2f4 --- /dev/null +++ b/app/common/service/JgPush.php @@ -0,0 +1,200 @@ +client = new Client('b5f679f4357018605ea6fd2e', 'c4fb573758f8d7058d697c54'); + $this->push = $this->client->push(); + } + + public function init($type, $data) + { + switch ($type) { + case 'ADMIN_PAY_SUCCESS_CODE': + $groupOrder = app()->make(StoreGroupOrderRepository::class)->get($data['group_order_id']); + if ($groupOrder) { + foreach ($groupOrder->orderList as $order) { + $route = "/pages/admin/orderDetail/index?id={$order['order_id']}&mer_id={$order['mer_id']}"; + $merUserId = Merchant::where('mer_id', $order->mer_id)->value('uid'); + $jgRegisterId = User::where('uid', $merUserId)->value('jg_register_id'); + if (empty($jgRegisterId)) { + continue; + } + $this->addRegistrationId($jgRegisterId); + $this->androidNotification('您有新的订单,请注意查看。', ['extras' => ['route' => $route]]); + $this->iosNotification('您有新的订单,请注意查看。', ['extras' => ['route' => $route]]); + } + } + break; + case 'DELIVER_GOODS_CODE': + case 'ORDER_DELIVER_SUCCESS': + $order = app()->make(StoreOrderRepository::class)->get($data['order_id']); + if ($order) { + $route = "/pages/order_details/index?order_id={$order['order_id']}"; + $jgRegisterId = User::where('uid', $order['uid'])->value('jg_register_id'); + if (!empty($jgRegisterId)) { + $this->addRegistrationId($jgRegisterId); + $this->androidNotification('您的订单已发货,请注意查看。', ['extras' => ['route' => $route]]); + $this->iosNotification('您的订单已发货,请注意查看。', ['extras' => ['route' => $route]]); + } + } + break; + default: + break; + } + $this->setPlatform(); + return $this; + } + + /** + * 设置推送平台 + * @param array $platform + */ + public function setPlatform(array $platform = ['android', 'ios']) + { + $this->push->setPlatform($platform); + } + + /** + * 设置推送设备 + * @param $registrationId + * @return void + */ + public function addRegistrationId($registrationId) + { + $this->push->addRegistrationId($registrationId); + } + + /** + * 给所有平台推送相同的 alert 消息 + * @param $alert + * @return void + */ + public function setNotificationAlert($alert) + { + $this->push->setNotificationAlert($alert); + } + + /** + * ios平台通知 + * @param $alert + * @param $extras + * @return void + * @example $extras = ['sound' => 'sound', 'badge' => '+1', 'extras' => ['key' => 'value'] + */ + public function iosNotification($alert, $extras = []) + { + $this->push->iosNotification($alert, $extras); + } + + /** + * android平台通知 + * @param $alert + * @param $extras + * @return void + * @example $extras = ['alert' => 'alert', 'title' => 'title', 'extras' => ['key' => 'value'] + */ + public function androidNotification($alert, $extras = []) + { + $this->push->androidNotification($alert, $extras); + } + + /** + * iOS VOIP 功能 + * @param $extras + * @return void + * @example $extras = ['key' => 'value'] //任意自定义 key/value 对,会透传给 APP + */ + public function voip($extras = []) + { + $this->push->voip($extras); + } + + /** + * @param $msg_content + * @param array $extras + * @return void + * @example $extras = ['title' => 'title', 'content_type' => 'text', 'extras' => ['key' => 'value'] + */ + public function message($msg_content, array $extras = []) + { + $this->push->message($msg_content, $extras); + } + + /** + * 推送可选项 + * @param array $options + * @return void + * @example $options = ['sendno' => 100, 'time_to_live' => 1, 'apns_production' => false, 'big_push_duration' => 1] + * sendno: 表示推送序号,纯粹用来作为 API 调用标识, + * time_to_live: 表示离线消息保留时长(秒), + * apns_production: 表示APNs是否生产环境, + * big_push_duration: 表示定速推送时长(分钟),又名缓慢推送 + */ + public function options(array $options = []) + { + $this->push->options($options); + } + + /** + * 发送短信通知 + * @param int $delay 延迟时间,单位秒 + * @param string $templateId 模板id + * @param array $param 模板参数 + * @return void + */ + public function setSms(int $delay, string $templateId, array $param = []) + { + $this->push->setSms($delay, $templateId, $param); + } + + /** + * 设备标签 + * @param $tag + */ + public function addTag($tag) + { + $this->push->addTag($tag); + } + + + /** + * 设备标签AND + * @param $tag + */ + public function addTagAnd($tag) + { + $this->push->addTagAnd($tag); + } + + /** + * 设备别名 + * @param $alias + */ + public function addAlias($alias) + { + $this->push->addAlias($alias); + } + + /** + * 所有用户 + */ + public function addAllAudience() + { + $this->push->addAllAudience(); + } + +} \ No newline at end of file diff --git a/app/controller/api/Auth.php b/app/controller/api/Auth.php index e06a6a1a..d3c4cc99 100644 --- a/app/controller/api/Auth.php +++ b/app/controller/api/Auth.php @@ -393,6 +393,25 @@ class Auth extends BaseController return app('json')->success(); } + /** + * 绑定极光register_id + * @param UserRepository $repository + * @return mixed + * @throws DataNotFoundException + * @throws DbException + * @throws ModelNotFoundException + */ + public function bindJg(UserRepository $repository) + { + $phone = $this->request->param('phone'); + $jgRegisterId = $this->request->param('jg_register_id'); + $user = $repository->accountByUser($phone); + if ($user->save(['jg_register_id' => $jgRegisterId]) === false) { + return app('json')->fail('绑定失败'); + } + return app('json')->success(); + } + public function getCaptcha() { $codeBuilder = new CaptchaBuilder(null, new PhraseBuilder(4)); diff --git a/crmeb/jobs/SendSmsJob.php b/crmeb/jobs/SendSmsJob.php index 6c0e17f0..b300df03 100644 --- a/crmeb/jobs/SendSmsJob.php +++ b/crmeb/jobs/SendSmsJob.php @@ -15,9 +15,11 @@ namespace crmeb\jobs; use app\common\repositories\system\notice\SystemNoticeConfigRepository; +use app\common\service\JgPush; use crmeb\interfaces\JobInterface; use crmeb\services\SmsService; use crmeb\services\WechatTemplateMessageService; +use crmeb\utils\DingTalk; use think\facade\Log; class SendSmsJob implements JobInterface @@ -26,6 +28,17 @@ class SendSmsJob implements JobInterface public function fire($job, $data) { $status = app()->make(SystemNoticeConfigRepository::class)->getNoticeStatusByConstKey($data['tempId']); + if ($status['notice_app'] == 1) { + try { + /** @var JgPush $push */ + $push = app()->make(JgPush::class); + Log::info('app推送发送数据:' . var_export($data, 1)); + $push->init($data['tempId'], $data)->push->send(); + } catch (\Exception $e) { + Log::info('app推送消息发送失败' . var_export($data, 1) . $e->getMessage()); + DingTalk::exception($e, 'app推送消息发送失败' . var_export($data, 1)); + } + } if ($status['notice_sms'] == 1) { try { SmsService::sendMessage($data); diff --git a/route/api.php b/route/api.php index 6dabf1d3..c74de9b1 100644 --- a/route/api.php +++ b/route/api.php @@ -602,6 +602,8 @@ Route::group('api/', function () { Route::post('auth/mp', 'api.Auth/mpAuth'); //绑定小程序账号 Route::post('auth/bindMp', 'api.Auth/bindMp'); + //绑定极光register_id + Route::post('auth/bindJg', 'api.Auth/bindJg'); //app授权 Route::post('auth/app', 'api.Auth/appAuth'); //apple授权