This commit is contained in:
mkm 2023-08-09 14:43:30 +08:00
parent 2ce3ce34e1
commit 656d98bde1
2677 changed files with 151614 additions and 29171 deletions

View File

@ -75,13 +75,13 @@ class CompanyController extends BaseApiController
}
$company['company_type_name'] = Db::name('dict_data')->where('id', $company['company_type'])->value('name');
$company['day_money_count'] = UserAccountLog::where(['company_id' => $company['id'], 'action' => 1])->whereDay('create_time')->sum('change_amount');
$users = Admin::where('id', $company['admin_id'])->field('id,name,account,phone,qualification')->select()->toArray();
foreach ($users as &$user) {
$user['is_main'] = $user['id'] == $company['admin_id'] ? 1 : 0;
$user['qualification'] = $user['qualification'] != null ? json_decode($user['qualification'], true) : [];
unset($user['role_id'], $user['dept_id'], $user['jobs_id'], $user['id']);
}
return $this->success('success', ['contract' => $contract ?? [], 'company' => $company, 'users' => $users]);
// $users = Admin::where('id', $company['admin_id'])->field('id,name,account,phone,qualification')->select()->toArray();
// foreach ($users as &$user) {
// $user['is_main'] = $user['id'] == $company['admin_id'] ? 1 : 0;
// $user['qualification'] = $user['qualification'] != null ? json_decode($user['qualification'], true) : [];
// unset($user['role_id'], $user['dept_id'], $user['jobs_id'], $user['id']);
// }
return $this->success('success', ['contract' => $contract ?? [], 'company' => $company]);
}
public function areaManager()
@ -112,8 +112,8 @@ class CompanyController extends BaseApiController
$count = $query->count();
$users = $query->order('id', 'desc')->page($page)->limit($limit)->with(['company' => function ($query) {
$query->field('id,company_name');
}])->append(['province_name', 'city_name', 'area_name', 'street_name'])
->field('id,avatar,real_name,account,mobile as phone,province,city,area,street,company_id,qualification,nickname,is_contract,is_captain')
}])->append(['province_name', 'city_name', 'area_name', 'street_name','village_name','brigade_name'])
->field('id,avatar,real_name,account,mobile as phone,province,city,area,street,village,brigade,company_id,qualification,nickname,is_contract,is_captain')
->select()->each(function ($item, $key) {
if ($item['qualification'] != '') {
$item['qualification'] = json_decode($item['qualification'], true);

View File

@ -81,7 +81,7 @@ class LoginLogic extends BaseLogic
'area'=>$params['area'],
'street'=>$params['street'],
'village'=>$params['village'],
'brigade'=>$params['brigade'],
'brigade'=>implode(',',$params['brigade']),
'address'=>$params['address'],
'qualification'=>json_encode($params['qualification']),
'company_id'=>$params['company_id'],

View File

@ -53,6 +53,7 @@ class AccountLogEnum
*/
const UM_INC_ADMIN = 200;
const UM_INC_RECHARGE = 201;
const UM_INC_TASK = 202;
/**
@ -108,6 +109,7 @@ class AccountLogEnum
self::UM_DEC_ADMIN => '平台减少余额',
self::UM_INC_ADMIN => '平台增加余额',
self::UM_INC_RECHARGE => '充值增加余额',
self::UM_INC_TASK => '任务增加余额',
self::UM_DEC_RECHARGE_REFUND => '充值订单退款减少余额',
];
if ($flag) {

View File

@ -70,7 +70,7 @@ class CompanyLogic extends BaseLogic
'other_contacts' => $params['other_contacts'],
'area_manager' => $params['area_manager'] ?? 0,
'qualification' => $params['qualification'],
'admin_id' => $params['admin_id'] ?? 0,
'admin_id' => 0,
'level_one' => $level_one,
];
$data = Company::create($arr);
@ -96,7 +96,8 @@ class CompanyLogic extends BaseLogic
$admin['nickname']=$params['master_name'];
$admin['mobile']=$params['master_phone'];
$admin['phone']=$params['master_phone'];
User::strict(false)->insert($admin);
$user_id=User::strict(false)->insertGetId($admin);
Company::where('id',$data['id'])->update(['admin_id'=>$admin_id,'user_id'=>$user_id]);
// if ($level_one > 0) {
// $contractId = self::contract($data['id'], $params);
// }
@ -155,8 +156,10 @@ class CompanyLogic extends BaseLogic
Admin::strict(false)->where('account',$account)->update($admin);
$admin_id=Admin::where('account',$account)->value('id');
$user_id=User::where('account',$account)->value('id');
$arr['admin_id']=$admin_id;
$arr['user_id']=$user_id;
Company::where('id', $params['id'])->update($arr);
$admin['admin_id']=$admin_id;

View File

@ -0,0 +1,23 @@
<?php
namespace app\common\logic\finance;
use app\common\enum\user\AccountLogEnum;
use app\common\logic\AccountLogLogic;
use app\common\model\user\User;
class ShareProfit
{
public function first($data,$company_id,$user_id,$money)
{
$userAll=User::where('company_id',$data['company_id'])->where('admin_id',0)->field('id,user_money')->select();
$master_maoney=bcdiv($data['money'],2,2);
$this->master($data,$master_maoney,$data['user_id']);
}
private function master($data,$money,$user_id){
$master=User::where('id',$user_id)->field('id,user_money')->find();
AccountLogLogic::add($user_id, AccountLogEnum::UM_INC_TASK, AccountLogEnum::INC,$money,
$data['sn'],
'充值订单退款');
}
}

View File

@ -208,6 +208,10 @@ class User extends BaseModel
}
public function getBrigadeNameAttr($value)
{
return Db::name('geo_brigade')->where(['id' => $this->brigade])->value('brigade_name');
if($this->brigade){
return Db::name('geo_brigade')->where('id' ,'in' ,explode(',',$value))->field('brigade_name')->select()->toArray();
}else{
return [];
}
}
}

View File

@ -0,0 +1,20 @@
<?php
namespace app\job;
use think\queue\Job;
class TaskInformationJob
{
public function fire(Job $job, $data)
{
if ($job->attempts() > 3) {
//通过这个方法可以检查这个任务已经重试了几次了
}
//如果任务执行成功后 记得删除任务不然这个任务会重复执行直到达到最大重试次数后失败后执行failed方法
$job->delete();
}
}

View File

@ -34,8 +34,9 @@
"alibabacloud/client": "^1.5",
"rmccue/requests": "^2.0",
"w7corp/easywechat": "^6.8",
"ebaoquan/junziqian_sdk":">=2.0.2"
"ebaoquan/junziqian_sdk":">=2.0.2",
"yunwuxin/think-cron": "^3.0",
"topthink/think-queue": "^3.0"
},
"require-dev": {
"symfony/var-dumper": "^4.2",
@ -52,7 +53,8 @@
"config": {
"preferred-install": "dist",
"allow-plugins": {
"easywechat-composer/easywechat-composer": false
"easywechat-composer/easywechat-composer": false,
"kylekatarnls/update-helper": true
}
},
"scripts": {

1379
composer.lock generated

File diff suppressed because it is too large Load Diff

5
config/cron.php Normal file
View File

@ -0,0 +1,5 @@
<?php
return [
'tasks' => []
];

39
config/queue.php Normal file
View File

@ -0,0 +1,39 @@
<?php
// +----------------------------------------------------------------------
// | ThinkPHP [ WE CAN DO IT JUST THINK IT ]
// +----------------------------------------------------------------------
// | Copyright (c) 2006-2016 http://thinkphp.cn All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +----------------------------------------------------------------------
// | Author: yunwuxin <448901948@qq.com>
// +----------------------------------------------------------------------
return [
'default' => 'sync',
'connections' => [
'sync' => [
'type' => 'sync',
],
'database' => [
'type' => 'database',
'queue' => 'default',
'table' => 'jobs',
'connection' => null,
],
'redis' => [
'type' => 'redis',
'queue' => 'default',
'host' => '127.0.0.1',
'port' => 6379,
'password' => '',
'select' => 0,
'timeout' => 0,
'persistent' => false,
],
],
'failed' => [
'type' => 'none',
'table' => 'failed_jobs',
],
];

119
vendor/bin/carbon vendored Executable file
View File

@ -0,0 +1,119 @@
#!/usr/bin/env php
<?php
/**
* Proxy PHP file generated by Composer
*
* This file includes the referenced bin path (../nesbot/carbon/bin/carbon)
* using a stream wrapper to prevent the shebang from being output on PHP<8
*
* @generated
*/
namespace Composer;
$GLOBALS['_composer_bin_dir'] = __DIR__;
$GLOBALS['_composer_autoload_path'] = __DIR__ . '/..'.'/autoload.php';
if (PHP_VERSION_ID < 80000) {
if (!class_exists('Composer\BinProxyWrapper')) {
/**
* @internal
*/
final class BinProxyWrapper
{
private $handle;
private $position;
private $realpath;
public function stream_open($path, $mode, $options, &$opened_path)
{
// get rid of phpvfscomposer:// prefix for __FILE__ & __DIR__ resolution
$opened_path = substr($path, 17);
$this->realpath = realpath($opened_path) ?: $opened_path;
$opened_path = $this->realpath;
$this->handle = fopen($this->realpath, $mode);
$this->position = 0;
return (bool) $this->handle;
}
public function stream_read($count)
{
$data = fread($this->handle, $count);
if ($this->position === 0) {
$data = preg_replace('{^#!.*\r?\n}', '', $data);
}
$this->position += strlen($data);
return $data;
}
public function stream_cast($castAs)
{
return $this->handle;
}
public function stream_close()
{
fclose($this->handle);
}
public function stream_lock($operation)
{
return $operation ? flock($this->handle, $operation) : true;
}
public function stream_seek($offset, $whence)
{
if (0 === fseek($this->handle, $offset, $whence)) {
$this->position = ftell($this->handle);
return true;
}
return false;
}
public function stream_tell()
{
return $this->position;
}
public function stream_eof()
{
return feof($this->handle);
}
public function stream_stat()
{
return array();
}
public function stream_set_option($option, $arg1, $arg2)
{
return true;
}
public function url_stat($path, $flags)
{
$path = substr($path, 17);
if (file_exists($path)) {
return stat($path);
}
return false;
}
}
}
if (
(function_exists('stream_get_wrappers') && in_array('phpvfscomposer', stream_get_wrappers(), true))
|| (function_exists('stream_wrapper_register') && stream_wrapper_register('phpvfscomposer', 'Composer\BinProxyWrapper'))
) {
return include("phpvfscomposer://" . __DIR__ . '/..'.'/nesbot/carbon/bin/carbon');
}
}
return include __DIR__ . '/..'.'/nesbot/carbon/bin/carbon';

5
vendor/bin/carbon.bat vendored Executable file
View File

@ -0,0 +1,5 @@
@ECHO OFF
setlocal DISABLEDELAYEDEXPANSION
SET BIN_TARGET=%~dp0/carbon
SET COMPOSER_RUNTIME_BIN_DIR=%~dp0
php "%BIN_TARGET%" %*

19
vendor/clagiordano/weblibs-configmanager/.github/workflows/php.yml vendored Executable file → Normal file
View File

@ -13,20 +13,13 @@ jobs:
matrix:
operating-system: [ ubuntu-18.04 ]
php: [ '5.4', '5.5', '5.6', '7.1', '7.2', '7.3', '7.4' ]
name: PHP ${{ matrix.php }}@${{ matrix.operating-system }}
name: PHP ${{ matrix.operating-system }} ${{ matrix.php }}
steps:
- uses: actions/checkout@v2
- uses: shivammathur/setup-php@master
- uses: nanasess/setup-php@master
with:
php-version: ${{ matrix.php }}
extensions: xdebug
- name: check php version
run: php --version
- name: check composer version
run: composer --version
- name: Validate composer.json and composer.lock
run: composer validate
@ -34,10 +27,8 @@ jobs:
- name: Install dependencies
run: composer install --prefer-dist --no-progress
# Add a test script to composer.json, for instance: "test": "vendor/bin/phpunit"
# Docs: https://getcomposer.org/doc/articles/scripts.md
- name: Run test suite
run: ./vendor/bin/phpunit
- name: Upload coverage results to Coveralls
env:
COVERALLS_REPO_TOKEN: ${{ secrets.COVERALLS_TOKEN }}
run: ./vendor/bin/coveralls --coverage_clover=build/logs/clover.xml -v

1
vendor/clagiordano/weblibs-configmanager/.gitignore vendored Executable file → Normal file
View File

@ -1,3 +1,2 @@
composer.phar
vendor
testsdata/phpunit_*

View File

@ -0,0 +1,17 @@
language: php
php:
- 5.4
- 5.5
- 5.6
- 7.0
- 7.1
- 7.2
- 7.3
- hhvm
before_script:
- travis_retry composer self-update
- travis_retry composer update --prefer-source --no-interaction --dev
script: phpunit

23
vendor/clagiordano/weblibs-configmanager/README.md vendored Executable file → Normal file
View File

@ -1,36 +1,23 @@
[![PHP Composer](https://github.com/clagiordano/weblibs-configmanager/actions/workflows/php.yml/badge.svg)](https://github.com/clagiordano/weblibs-configmanager/actions/workflows/php.yml)
[![Coverage Status](https://coveralls.io/repos/github/clagiordano/weblibs-configmanager/badge.svg?branch=master)](https://coveralls.io/github/clagiordano/weblibs-configmanager?branch=master)
[![SymfonyInsight](https://insight.symfony.com/projects/54c4e80c-ff15-4235-8bec-a4c71bbe3ba5/mini.svg)](https://insight.symfony.com/projects/54c4e80c-ff15-4235-8bec-a4c71bbe3ba5)
![BuildStatus](https://travis-ci.org/clagiordano/weblibs-configmanager.svg?branch=master) ![License](https://img.shields.io/github/license/clagiordano/weblibs-configmanager.svg)
# weblibs-configmanager
weblibs-configmanager is a tool library for easily read and access to php config array file and direct read/write configuration file / object.
[![SensioLabsInsight](https://insight.sensiolabs.com/projects/54c4e80c-ff15-4235-8bec-a4c71bbe3ba5/big.png)](https://insight.sensiolabs.com/projects/54c4e80c-ff15-4235-8bec-a4c71bbe3ba5)
## Why use weblibs-configmanager ?
The purpose of this project is to propose a simple and lightweight library to manage php hierarchical configuration files.
## Supported formats
This package supports config files in the following format:
Format | Component | Since version | Description
:---: | :---: | :---: | ---
Array | `ConfigManager` | `v0.1.0` | Deprecated, legacy name for the php array reader, only for compatibility support
Array | `ArrayConfigManager` | `v1.2.0` | A file that returns a php array, the original supported format
Yaml | `YamlConfigManager` | `v1.3.0` | A file containing a valid YAML file
JSON | `JsonConfigManager` | `v1.4.0` | A file containing a valid JSON file
All the supported format are parsed and internally handled in the same way granting the same functionalities.
## Installation
The recommended way to install weblibs-configmanager is through [Composer](https://getcomposer.org).
```bash
composer require clagiordano/weblibs-configmanager
```
## Usage examples (Array format)
## Usage examples
### Write a sample config file like this
```php
```
<?php
return array (

7
vendor/clagiordano/weblibs-configmanager/composer.json vendored Executable file → Normal file
View File

@ -17,14 +17,11 @@
}
},
"require": {
"php": ">=5.4",
"symfony/yaml": "^2.8",
"ext-json": "*"
"php": ">=5.4"
},
"require-dev": {
"phpunit/phpunit": "^4.8",
"clagiordano/phpunit-result-printer": "^1",
"php-coveralls/php-coveralls": "^1.1"
"clagiordano/phpunit-result-printer": "^1"
},
"autoload-dev": {
"psr-4": {

666
vendor/clagiordano/weblibs-configmanager/composer.lock generated vendored Executable file → Normal file
View File

@ -4,135 +4,8 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
"content-hash": "f98dd1d9d1b8f4986c6a54cc483c1166",
"packages": [
{
"name": "symfony/polyfill-ctype",
"version": "v1.19.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/polyfill-ctype.git",
"reference": "aed596913b70fae57be53d86faa2e9ef85a2297b"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/aed596913b70fae57be53d86faa2e9ef85a2297b",
"reference": "aed596913b70fae57be53d86faa2e9ef85a2297b",
"shasum": ""
},
"require": {
"php": ">=5.3.3"
},
"suggest": {
"ext-ctype": "For best performance"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-main": "1.19-dev"
},
"thanks": {
"name": "symfony/polyfill",
"url": "https://github.com/symfony/polyfill"
}
},
"autoload": {
"psr-4": {
"Symfony\\Polyfill\\Ctype\\": ""
},
"files": [
"bootstrap.php"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Gert de Pagter",
"email": "BackEndTea@gmail.com"
},
{
"name": "Symfony Community",
"homepage": "https://symfony.com/contributors"
}
],
"description": "Symfony polyfill for ctype functions",
"homepage": "https://symfony.com",
"keywords": [
"compatibility",
"ctype",
"polyfill",
"portable"
],
"funding": [
{
"url": "https://symfony.com/sponsor",
"type": "custom"
},
{
"url": "https://github.com/fabpot",
"type": "github"
},
{
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
"type": "tidelift"
}
],
"time": "2020-10-23T09:01:57+00:00"
},
{
"name": "symfony/yaml",
"version": "v2.8.52",
"source": {
"type": "git",
"url": "https://github.com/symfony/yaml.git",
"reference": "02c1859112aa779d9ab394ae4f3381911d84052b"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/yaml/zipball/02c1859112aa779d9ab394ae4f3381911d84052b",
"reference": "02c1859112aa779d9ab394ae4f3381911d84052b",
"shasum": ""
},
"require": {
"php": ">=5.3.9",
"symfony/polyfill-ctype": "~1.8"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "2.8-dev"
}
},
"autoload": {
"psr-4": {
"Symfony\\Component\\Yaml\\": ""
},
"exclude-from-classmap": [
"/Tests/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Fabien Potencier",
"email": "fabien@symfony.com"
},
{
"name": "Symfony Community",
"homepage": "https://symfony.com/contributors"
}
],
"description": "Symfony Yaml Component",
"homepage": "https://symfony.com",
"time": "2018-11-11T11:18:13+00:00"
}
],
"content-hash": "6d2aba6439fb7be37e7120eed3311f56",
"packages": [],
"packages-dev": [
{
"name": "clagiordano/phpunit-result-printer",
@ -218,163 +91,6 @@
],
"time": "2015-06-14T21:17:01+00:00"
},
{
"name": "guzzle/guzzle",
"version": "v3.9.3",
"source": {
"type": "git",
"url": "https://github.com/guzzle/guzzle3.git",
"reference": "0645b70d953bc1c067bbc8d5bc53194706b628d9"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/guzzle/guzzle3/zipball/0645b70d953bc1c067bbc8d5bc53194706b628d9",
"reference": "0645b70d953bc1c067bbc8d5bc53194706b628d9",
"shasum": ""
},
"require": {
"ext-curl": "*",
"php": ">=5.3.3",
"symfony/event-dispatcher": "~2.1"
},
"replace": {
"guzzle/batch": "self.version",
"guzzle/cache": "self.version",
"guzzle/common": "self.version",
"guzzle/http": "self.version",
"guzzle/inflection": "self.version",
"guzzle/iterator": "self.version",
"guzzle/log": "self.version",
"guzzle/parser": "self.version",
"guzzle/plugin": "self.version",
"guzzle/plugin-async": "self.version",
"guzzle/plugin-backoff": "self.version",
"guzzle/plugin-cache": "self.version",
"guzzle/plugin-cookie": "self.version",
"guzzle/plugin-curlauth": "self.version",
"guzzle/plugin-error-response": "self.version",
"guzzle/plugin-history": "self.version",
"guzzle/plugin-log": "self.version",
"guzzle/plugin-md5": "self.version",
"guzzle/plugin-mock": "self.version",
"guzzle/plugin-oauth": "self.version",
"guzzle/service": "self.version",
"guzzle/stream": "self.version"
},
"require-dev": {
"doctrine/cache": "~1.3",
"monolog/monolog": "~1.0",
"phpunit/phpunit": "3.7.*",
"psr/log": "~1.0",
"symfony/class-loader": "~2.1",
"zendframework/zend-cache": "2.*,<2.3",
"zendframework/zend-log": "2.*,<2.3"
},
"suggest": {
"guzzlehttp/guzzle": "Guzzle 5 has moved to a new package name. The package you have installed, Guzzle 3, is deprecated."
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "3.9-dev"
}
},
"autoload": {
"psr-0": {
"Guzzle": "src/",
"Guzzle\\Tests": "tests/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Michael Dowling",
"email": "mtdowling@gmail.com",
"homepage": "https://github.com/mtdowling"
},
{
"name": "Guzzle Community",
"homepage": "https://github.com/guzzle/guzzle/contributors"
}
],
"description": "PHP HTTP client. This library is deprecated in favor of https://packagist.org/packages/guzzlehttp/guzzle",
"homepage": "http://guzzlephp.org/",
"keywords": [
"client",
"curl",
"framework",
"http",
"http client",
"rest",
"web service"
],
"abandoned": "guzzlehttp/guzzle",
"time": "2015-03-18T18:23:50+00:00"
},
{
"name": "php-coveralls/php-coveralls",
"version": "v1.1.0",
"source": {
"type": "git",
"url": "https://github.com/php-coveralls/php-coveralls.git",
"reference": "37f8f83fe22224eb9d9c6d593cdeb33eedd2a9ad"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/php-coveralls/php-coveralls/zipball/37f8f83fe22224eb9d9c6d593cdeb33eedd2a9ad",
"reference": "37f8f83fe22224eb9d9c6d593cdeb33eedd2a9ad",
"shasum": ""
},
"require": {
"ext-json": "*",
"ext-simplexml": "*",
"guzzle/guzzle": "^2.8 || ^3.0",
"php": "^5.3.3 || ^7.0",
"psr/log": "^1.0",
"symfony/config": "^2.1 || ^3.0 || ^4.0",
"symfony/console": "^2.1 || ^3.0 || ^4.0",
"symfony/stopwatch": "^2.0 || ^3.0 || ^4.0",
"symfony/yaml": "^2.0 || ^3.0 || ^4.0"
},
"require-dev": {
"phpunit/phpunit": "^4.8.35 || ^5.4.3 || ^6.0"
},
"suggest": {
"symfony/http-kernel": "Allows Symfony integration"
},
"bin": [
"bin/coveralls"
],
"type": "library",
"autoload": {
"psr-4": {
"Satooshi\\": "src/Satooshi/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Kitamura Satoshi",
"email": "with.no.parachute@gmail.com",
"homepage": "https://www.facebook.com/satooshi.jp"
}
],
"description": "PHP client library for Coveralls API",
"homepage": "https://github.com/php-coveralls/php-coveralls",
"keywords": [
"ci",
"coverage",
"github",
"test"
],
"time": "2017-12-06T23:17:56+00:00"
},
{
"name": "phpdocumentor/reflection-docblock",
"version": "2.0.5",
@ -733,7 +449,6 @@
"keywords": [
"tokenizer"
],
"abandoned": true,
"time": "2017-12-04T08:55:13+00:00"
},
{
@ -865,53 +580,6 @@
"abandoned": true,
"time": "2015-10-02T06:51:40+00:00"
},
{
"name": "psr/log",
"version": "1.1.4",
"source": {
"type": "git",
"url": "https://github.com/php-fig/log.git",
"reference": "d49695b909c3b7628b6289db5479a1c204601f11"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/php-fig/log/zipball/d49695b909c3b7628b6289db5479a1c204601f11",
"reference": "d49695b909c3b7628b6289db5479a1c204601f11",
"shasum": ""
},
"require": {
"php": ">=5.3.0"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.1.x-dev"
}
},
"autoload": {
"psr-4": {
"Psr\\Log\\": "Psr/Log/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "PHP-FIG",
"homepage": "https://www.php-fig.org/"
}
],
"description": "Common interface for logging libraries",
"homepage": "https://github.com/php-fig/log",
"keywords": [
"log",
"psr",
"psr-3"
],
"time": "2021-05-03T11:20:27+00:00"
},
{
"name": "sebastian/comparator",
"version": "1.2.4",
@ -1285,309 +953,24 @@
"time": "2015-06-21T13:59:46+00:00"
},
{
"name": "symfony/config",
"version": "v2.8.52",
"source": {
"type": "git",
"url": "https://github.com/symfony/config.git",
"reference": "7dd5f5040dc04c118d057fb5886563963eb70011"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/config/zipball/7dd5f5040dc04c118d057fb5886563963eb70011",
"reference": "7dd5f5040dc04c118d057fb5886563963eb70011",
"shasum": ""
},
"require": {
"php": ">=5.3.9",
"symfony/filesystem": "~2.3|~3.0.0",
"symfony/polyfill-ctype": "~1.8"
},
"require-dev": {
"symfony/yaml": "~2.7|~3.0.0"
},
"suggest": {
"symfony/yaml": "To use the yaml reference dumper"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "2.8-dev"
}
},
"autoload": {
"psr-4": {
"Symfony\\Component\\Config\\": ""
},
"exclude-from-classmap": [
"/Tests/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Fabien Potencier",
"email": "fabien@symfony.com"
},
{
"name": "Symfony Community",
"homepage": "https://symfony.com/contributors"
}
],
"description": "Symfony Config Component",
"homepage": "https://symfony.com",
"time": "2018-11-26T09:38:12+00:00"
},
{
"name": "symfony/console",
"version": "v2.8.52",
"source": {
"type": "git",
"url": "https://github.com/symfony/console.git",
"reference": "cbcf4b5e233af15cd2bbd50dee1ccc9b7927dc12"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/console/zipball/cbcf4b5e233af15cd2bbd50dee1ccc9b7927dc12",
"reference": "cbcf4b5e233af15cd2bbd50dee1ccc9b7927dc12",
"shasum": ""
},
"require": {
"php": ">=5.3.9",
"symfony/debug": "^2.7.2|~3.0.0",
"symfony/polyfill-mbstring": "~1.0"
},
"require-dev": {
"psr/log": "~1.0",
"symfony/event-dispatcher": "~2.1|~3.0.0",
"symfony/process": "~2.1|~3.0.0"
},
"suggest": {
"psr/log-implementation": "For using the console logger",
"symfony/event-dispatcher": "",
"symfony/process": ""
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "2.8-dev"
}
},
"autoload": {
"psr-4": {
"Symfony\\Component\\Console\\": ""
},
"exclude-from-classmap": [
"/Tests/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Fabien Potencier",
"email": "fabien@symfony.com"
},
{
"name": "Symfony Community",
"homepage": "https://symfony.com/contributors"
}
],
"description": "Symfony Console Component",
"homepage": "https://symfony.com",
"time": "2018-11-20T15:55:20+00:00"
},
{
"name": "symfony/debug",
"version": "v2.8.52",
"source": {
"type": "git",
"url": "https://github.com/symfony/debug.git",
"reference": "74251c8d50dd3be7c4ce0c7b862497cdc641a5d0"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/debug/zipball/74251c8d50dd3be7c4ce0c7b862497cdc641a5d0",
"reference": "74251c8d50dd3be7c4ce0c7b862497cdc641a5d0",
"shasum": ""
},
"require": {
"php": ">=5.3.9",
"psr/log": "~1.0"
},
"conflict": {
"symfony/http-kernel": ">=2.3,<2.3.24|~2.4.0|>=2.5,<2.5.9|>=2.6,<2.6.2"
},
"require-dev": {
"symfony/class-loader": "~2.2|~3.0.0",
"symfony/http-kernel": "~2.3.24|~2.5.9|^2.6.2|~3.0.0"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "2.8-dev"
}
},
"autoload": {
"psr-4": {
"Symfony\\Component\\Debug\\": ""
},
"exclude-from-classmap": [
"/Tests/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Fabien Potencier",
"email": "fabien@symfony.com"
},
{
"name": "Symfony Community",
"homepage": "https://symfony.com/contributors"
}
],
"description": "Symfony Debug Component",
"homepage": "https://symfony.com",
"time": "2018-11-11T11:18:13+00:00"
},
{
"name": "symfony/event-dispatcher",
"version": "v2.8.52",
"source": {
"type": "git",
"url": "https://github.com/symfony/event-dispatcher.git",
"reference": "a77e974a5fecb4398833b0709210e3d5e334ffb0"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/a77e974a5fecb4398833b0709210e3d5e334ffb0",
"reference": "a77e974a5fecb4398833b0709210e3d5e334ffb0",
"shasum": ""
},
"require": {
"php": ">=5.3.9"
},
"require-dev": {
"psr/log": "~1.0",
"symfony/config": "^2.0.5|~3.0.0",
"symfony/dependency-injection": "~2.6|~3.0.0",
"symfony/expression-language": "~2.6|~3.0.0",
"symfony/stopwatch": "~2.3|~3.0.0"
},
"suggest": {
"symfony/dependency-injection": "",
"symfony/http-kernel": ""
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "2.8-dev"
}
},
"autoload": {
"psr-4": {
"Symfony\\Component\\EventDispatcher\\": ""
},
"exclude-from-classmap": [
"/Tests/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Fabien Potencier",
"email": "fabien@symfony.com"
},
{
"name": "Symfony Community",
"homepage": "https://symfony.com/contributors"
}
],
"description": "Symfony EventDispatcher Component",
"homepage": "https://symfony.com",
"time": "2018-11-21T14:20:20+00:00"
},
{
"name": "symfony/filesystem",
"version": "v2.8.52",
"source": {
"type": "git",
"url": "https://github.com/symfony/filesystem.git",
"reference": "7ae46872dad09dffb7fe1e93a0937097339d0080"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/filesystem/zipball/7ae46872dad09dffb7fe1e93a0937097339d0080",
"reference": "7ae46872dad09dffb7fe1e93a0937097339d0080",
"shasum": ""
},
"require": {
"php": ">=5.3.9",
"symfony/polyfill-ctype": "~1.8"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "2.8-dev"
}
},
"autoload": {
"psr-4": {
"Symfony\\Component\\Filesystem\\": ""
},
"exclude-from-classmap": [
"/Tests/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Fabien Potencier",
"email": "fabien@symfony.com"
},
{
"name": "Symfony Community",
"homepage": "https://symfony.com/contributors"
}
],
"description": "Symfony Filesystem Component",
"homepage": "https://symfony.com",
"time": "2018-11-11T11:18:13+00:00"
},
{
"name": "symfony/polyfill-mbstring",
"name": "symfony/polyfill-ctype",
"version": "v1.19.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/polyfill-mbstring.git",
"reference": "b5f7b932ee6fa802fc792eabd77c4c88084517ce"
"url": "https://github.com/symfony/polyfill-ctype.git",
"reference": "aed596913b70fae57be53d86faa2e9ef85a2297b"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/b5f7b932ee6fa802fc792eabd77c4c88084517ce",
"reference": "b5f7b932ee6fa802fc792eabd77c4c88084517ce",
"url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/aed596913b70fae57be53d86faa2e9ef85a2297b",
"reference": "aed596913b70fae57be53d86faa2e9ef85a2297b",
"shasum": ""
},
"require": {
"php": ">=5.3.3"
},
"suggest": {
"ext-mbstring": "For best performance"
"ext-ctype": "For best performance"
},
"type": "library",
"extra": {
@ -1601,7 +984,7 @@
},
"autoload": {
"psr-4": {
"Symfony\\Polyfill\\Mbstring\\": ""
"Symfony\\Polyfill\\Ctype\\": ""
},
"files": [
"bootstrap.php"
@ -1613,22 +996,21 @@
],
"authors": [
{
"name": "Nicolas Grekas",
"email": "p@tchwork.com"
"name": "Gert de Pagter",
"email": "BackEndTea@gmail.com"
},
{
"name": "Symfony Community",
"homepage": "https://symfony.com/contributors"
}
],
"description": "Symfony polyfill for the Mbstring extension",
"description": "Symfony polyfill for ctype functions",
"homepage": "https://symfony.com",
"keywords": [
"compatibility",
"mbstring",
"ctype",
"polyfill",
"portable",
"shim"
"portable"
],
"funding": [
{
@ -1647,21 +1029,22 @@
"time": "2020-10-23T09:01:57+00:00"
},
{
"name": "symfony/stopwatch",
"name": "symfony/yaml",
"version": "v2.8.52",
"source": {
"type": "git",
"url": "https://github.com/symfony/stopwatch.git",
"reference": "752586c80af8a85aeb74d1ae8202411c68836663"
"url": "https://github.com/symfony/yaml.git",
"reference": "02c1859112aa779d9ab394ae4f3381911d84052b"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/stopwatch/zipball/752586c80af8a85aeb74d1ae8202411c68836663",
"reference": "752586c80af8a85aeb74d1ae8202411c68836663",
"url": "https://api.github.com/repos/symfony/yaml/zipball/02c1859112aa779d9ab394ae4f3381911d84052b",
"reference": "02c1859112aa779d9ab394ae4f3381911d84052b",
"shasum": ""
},
"require": {
"php": ">=5.3.9"
"php": ">=5.3.9",
"symfony/polyfill-ctype": "~1.8"
},
"type": "library",
"extra": {
@ -1671,7 +1054,7 @@
},
"autoload": {
"psr-4": {
"Symfony\\Component\\Stopwatch\\": ""
"Symfony\\Component\\Yaml\\": ""
},
"exclude-from-classmap": [
"/Tests/"
@ -1691,7 +1074,7 @@
"homepage": "https://symfony.com/contributors"
}
],
"description": "Symfony Stopwatch Component",
"description": "Symfony Yaml Component",
"homepage": "https://symfony.com",
"time": "2018-11-11T11:18:13+00:00"
}
@ -1702,8 +1085,7 @@
"prefer-stable": false,
"prefer-lowest": false,
"platform": {
"php": ">=5.4",
"ext-json": "*"
"php": ">=5.4"
},
"platform-dev": [],
"platform-overrides": {

2
vendor/clagiordano/weblibs-configmanager/phpunit.xml vendored Executable file → Normal file
View File

@ -34,6 +34,6 @@
<log type="coverage-clover" target="build/logs/clover.xml"/>
<log type="coverage-crap4j" target="build/logs/crap4j.xml"/>
<log type="junit" target="build/logs/junit.xml"/>
<log type="coverage-text" target="build/logs/coverage.txt" showUncoveredFiles="true" />
<log type="coverage-text" target="php://stdout" showUncoveredFiles="true" />
</logging>
</phpunit>

View File

@ -1,159 +0,0 @@
<?php
namespace clagiordano\weblibs\configmanager;
use Exception;
use RuntimeException;
/**
* Class AbstractConfigManager
* @package clagiordano\weblibs\configmanager
*/
abstract class AbstractConfigManager implements IConfigurable
{
/** @var array $configData */
protected $configData = null;
/** @var string $configFilePath */
protected $configFilePath = null;
/**
* Create config object, optionally automatic load config
* from argument $configFilePath
*
* @param string $configFilePath
*/
public function __construct($configFilePath = null)
{
try {
$this->loadConfig($configFilePath);
} catch (Exception $exception) {
/**
* Allow not existent file name at construct
*/
}
}
/**
* Get value pointer from config for get/set value
*
* @param string $configPath
*
* @return mixed
*/
protected function & getValuePointer($configPath)
{
$configData =& $this->configData;
$parts = explode('.', $configPath);
$length = count($parts);
for ($i = 0; $i < $length; $i++) {
if (!isset($configData[ $parts[ $i ] ])) {
$configData[ $parts[ $i ] ] = ($i === $length) ? [] : null;
}
$configData = &$configData[ $parts[ $i ] ];
}
return $configData;
}
/**
* Get value from config data throught keyValue path
*
* @param string $configPath
* @param mixed $defaultValue
*
* @return mixed
*/
public function getValue($configPath, $defaultValue = null)
{
$stored = $this->getValuePointer($configPath);
return (is_null($stored)
? $defaultValue
: $stored);
}
/**
* Check if exist required config for keyValue
*
* @param string $keyValue
*
* @return mixed
*/
public function existValue($keyValue)
{
return !is_null($this->getValue($keyValue));
}
/**
* Set value in config path
*
* @param string $configPath
* @param mixed $newValue
*
* @return IConfigurable
*/
public function setValue($configPath, $newValue)
{
$configData = &$this->getValuePointer($configPath);
$configData = $newValue;
return $this;
}
/**
* @inheritDoc
*/
public function getConfig()
{
return $this->configData;
}
/**
* @inheritDoc
*/
public function setConfig($config)
{
$this->configData = (array)$config;
return $this;
}
/**
* @inheritDoc
*/
public function convert(IConfigurable $target)
{
$target->setConfig($this->getConfig());
return $target;
}
/**
* Check if configFilePath exists and is readable
* @return bool
* @throws RuntimeException
*/
protected function checkLoadable()
{
if ($this->configFilePath !== null) {
if (file_exists($this->configFilePath) && is_readable($this->configFilePath)) {
/**
* Readable
*/
return true;
}
/**
* $configFilePath is not null, but not existent or not readable
*/
throw new RuntimeException("Failed to read config file from path '{$this->configFilePath}'");
}
/**
* $configFilePath is null
*/
return false;
}
}

View File

@ -1,72 +0,0 @@
<?php
namespace clagiordano\weblibs\configmanager;
use Exception;
use RuntimeException;
/**
* Class ArrayConfigManager, class for easily read and access to php config array file.
* @package clagiordano\weblibs\configmanager
*/
class ArrayConfigManager extends AbstractConfigManager
{
/**
* Load config data from file and store it into internal property
*
* @param null|string $configFilePath
*
* @return IConfigurable
*/
public function loadConfig($configFilePath = null)
{
$this->configFilePath = $configFilePath;
if ($this->checkLoadable()) {
$this->configData = require $this->configFilePath;
}
return $this;
}
/**
* Prepare and write config file on disk
*
* @param null|string $configFilePath
* @param bool $autoReloadConfig
*
* @return IConfigurable
* @throws RuntimeException
*/
public function saveConfigFile($configFilePath = null, $autoReloadConfig = false)
{
if (is_null($configFilePath)) {
$configFilePath = $this->configFilePath;
}
$configFileContent = "<?php\n\n";
$configFileContent .= "return ";
$configFileContent .= var_export($this->configData, true);
$configFileContent .= ";\n\n";
try {
file_put_contents($configFilePath, $configFileContent);
if (is_callable('opcache_invalidate')) {
/**
* Invalidate opcache for writed file if opcache is available
*/
opcache_invalidate($configFilePath, true);
}
} catch (Exception $exception) {
throw new RuntimeException(
"Failed to write config file to path '{$configFilePath}'\n{$exception->getMessage()}"
);
}
if ($autoReloadConfig) {
$this->loadConfig($configFilePath);
}
return $this;
}
}

153
vendor/clagiordano/weblibs-configmanager/src/ConfigManager.php vendored Executable file → Normal file
View File

@ -2,13 +2,160 @@
namespace clagiordano\weblibs\configmanager;
use Exception;
use RuntimeException;
/**
* Class ConfigManager, class for easily read and access to php config array file.
* @package clagiordano\weblibs\configmanager
* @deprecated This is a wrapper for the same class with the new name,
* please use directly ArrayConfigManager instead
*/
class ConfigManager extends ArrayConfigManager
class ConfigManager implements IConfigurable
{
/** @var array $configData */
private $configData = null;
/** @var string $configFilePath */
private $configFilePath = null;
/**
* Create config object, optionally automatic load config
* from argument $configFilePath
*
* @param string $configFilePath
* @return IConfigurable
*/
public function __construct($configFilePath = null)
{
return $this->loadConfig($configFilePath);
}
/**
* Load config data from file and store it into internal property
*
* @param null|string $configFilePath
*
* @return IConfigurable
*/
public function loadConfig($configFilePath = null)
{
if (!is_null($configFilePath)) {
$this->configFilePath = $configFilePath;
if (file_exists($configFilePath)) {
$this->configData = require $configFilePath;
}
}
return $this;
}
/**
* Prepare and write config file on disk
*
* @param null|string $configFilePath
* @param bool $autoReloadConfig
*
* @return IConfigurable
* @throws RuntimeException
*/
public function saveConfigFile($configFilePath = null, $autoReloadConfig = false)
{
if (is_null($configFilePath)) {
$configFilePath = $this->configFilePath;
}
$configFileContent = "<?php\n\n";
$configFileContent .= "return ";
$configFileContent .= var_export($this->configData, true);
$configFileContent .= ";\n\n";
try {
file_put_contents($configFilePath, $configFileContent);
if (is_callable('opcache_invalidate')) {
/**
* Invalidate opcache for writed file if opcache is available
*/
opcache_invalidate($configFilePath, true);
}
} catch (Exception $exc) {
throw new RuntimeException(
__METHOD__ . ": Failed to write config file to path '{$configFilePath}'"
);
}
if ($autoReloadConfig) {
$this->loadConfig($configFilePath);
}
return $this;
}
/**
* Get value pointer from config for get/set value
*
* @param string $configPath
*
* @return mixed
*/
private function & getValuePointer($configPath)
{
$configData =& $this->configData;
$parts = explode('.', $configPath);
$length = count($parts);
for ($i = 0; $i < $length; $i++) {
if (!isset($configData[ $parts[ $i ] ])) {
$configData[ $parts[ $i ] ] = ($i === $length) ? [] : null;
}
$configData = &$configData[ $parts[ $i ] ];
}
return $configData;
}
/**
* Get value from config data throught keyValue path
*
* @param string $configPath
* @param mixed $defaultValue
*
* @return mixed
*/
public function getValue($configPath, $defaultValue = null)
{
$stored = $this->getValuePointer($configPath);
return (is_null($stored)
? $defaultValue
: $stored);
}
/**
* Check if exist required config for keyValue
*
* @param string $keyValue
*
* @return mixed
*/
public function existValue($keyValue)
{
return !is_null($this->getValue($keyValue));
}
/**
* Set value in config path
*
* @param string $configPath
* @param mixed $newValue
*
* @return IConfigurable
*/
public function setValue($configPath, $newValue)
{
$configData = &$this->getValuePointer($configPath);
$configData = $newValue;
return $this;
}
}

View File

@ -1,28 +0,0 @@
<?php
namespace clagiordano\weblibs\configmanager;
/**
* Class FileConverter
* @package clagiordano\weblibs\configmanager
*/
class FileConverter implements IConvertable
{
/**
* @inheritDoc
*/
public static function convert(IConfigurable $source, IConfigurable $target)
{
return $target->setConfig($source->getConfig());
}
/**
* @inheritDoc
*/
public static function convertAndSave(IConfigurable $source, IConfigurable $target)
{
$target->setConfig($source->getConfig());
return $target->saveConfigFile();
}
}

25
vendor/clagiordano/weblibs-configmanager/src/IConfigurable.php vendored Executable file → Normal file
View File

@ -58,27 +58,4 @@ interface IConfigurable
* @return IConfigurable
*/
public function setValue($configPath, $newValue);
/**
* Returns the whole internal configuration as array
* @return array
*/
public function getConfig();
/**
* Sets the whole internal configuration from array
*
* @param array $config
* @return IConfigurable
*/
public function setConfig($config);
/**
* Converts the current instance into another one provided as argument,
* migrating its internal configuration and returning the new one.
*
* @param IConfigurable $target
* @return IConfigurable
*/
public function convert(IConfigurable $target);
}
}

View File

@ -1,28 +0,0 @@
<?php
namespace clagiordano\weblibs\configmanager;
/**
* Class FileConverter
* @package clagiordano\weblibs\configmanager
*/
interface IConvertable
{
/**
* Converts source config to target config format
*
* @param IConfigurable $source
* @param IConfigurable $target
* @return IConfigurable
*/
public static function convert(IConfigurable $source, IConfigurable $target);
/**
* Converts source config to target config format and save it on target config file
*
* @param IConfigurable $source
* @param IConfigurable $target
* @return IConfigurable
*/
public static function convertAndSave(IConfigurable $source, IConfigurable $target);
}

View File

@ -1,68 +0,0 @@
<?php
namespace clagiordano\weblibs\configmanager;
use Exception;
use RuntimeException;
/**
* Class JsonConfigManager
* @package clagiordano\weblibs\configmanager
*/
class JsonConfigManager extends AbstractConfigManager
{
/**
* Load config data from file and store it into internal property
*
* @param null|string $configFilePath
*
* @return IConfigurable
*/
public function loadConfig($configFilePath = null)
{
$this->configFilePath = $configFilePath;
if ($this->checkLoadable()) {
if (!is_callable('json_decode')) {
throw new RuntimeException('Missing php-json extension');
}
$this->configData = json_decode(file_get_contents($configFilePath), true);
}
return $this;
}
/**
* Prepare and write config file on disk
*
* @param null|string $configFilePath
* @param bool $autoReloadConfig
*
* @return IConfigurable
* @throws RuntimeException
*/
public function saveConfigFile($configFilePath = null, $autoReloadConfig = false)
{
if (is_null($configFilePath)) {
$configFilePath = $this->configFilePath;
}
try {
if (!is_callable('json_encode')) {
throw new RuntimeException('Missing php-json extension');
}
file_put_contents($configFilePath, json_encode($this->configData, JSON_UNESCAPED_UNICODE));
} catch (Exception $exception) {
throw new RuntimeException(
"Failed to write config file to path '{$configFilePath}'\n{$exception->getMessage()}"
);
}
if ($autoReloadConfig) {
$this->loadConfig($configFilePath);
}
return $this;
}
}

View File

@ -1,64 +0,0 @@
<?php
namespace clagiordano\weblibs\configmanager;
use Exception;
use RuntimeException;
use Symfony\Component\Yaml\Yaml;
/**
* Class YamlConfigManager
* @package clagiordano\weblibs\configmanager
*/
class YamlConfigManager extends AbstractConfigManager
{
/**
* Load config data from file and store it into internal property
*
* @param null|string $configFilePath
*
* @return IConfigurable
*/
public function loadConfig($configFilePath = null)
{
$this->configFilePath = $configFilePath;
if ($this->checkLoadable()) {
$this->configData = Yaml::parse(file_get_contents($configFilePath));
}
return $this;
}
/**
* Prepare and write config file on disk
*
* @param null|string $configFilePath
* @param bool $autoReloadConfig
*
* @return IConfigurable
* @throws RuntimeException
*/
public function saveConfigFile($configFilePath = null, $autoReloadConfig = false)
{
if (is_null($configFilePath)) {
$configFilePath = $this->configFilePath;
}
try {
file_put_contents(
$configFilePath,
Yaml::dump($this->configData, 2, 2)
);
} catch (Exception $exception) {
throw new RuntimeException(
"Failed to write config file to path '{$configFilePath}'\n{$exception->getMessage()}"
);
}
if ($autoReloadConfig) {
$this->loadConfig($configFilePath);
}
return $this;
}
}

View File

@ -1,223 +0,0 @@
<?php
namespace clagiordano\weblibs\configmanager\tests;
use clagiordano\weblibs\configmanager\IConfigurable;
use PHPUnit\Framework\TestCase;
/**
* Class AbstractConfigManagerTest
* @package clagiordano\weblibs\configmanager\tests
*/
abstract class AbstractConfigManagerTest extends TestCase
{
/** @var string $configFile */
protected $configFile = null;
/** @var IConfigurable $config */
protected $config = null;
public static function setUpBeforeClass()
{
parent::setUpBeforeClass();
/**
* Remove temp dir
*/
shell_exec("rm -rf " . __DIR__ . '/../testsdata/temp');
/**
* Create temp dir
*/
$status = mkdir(__DIR__ . '/../testsdata/temp/');
self::assertTrue($status);
}
public static function tearDownAfterClass()
{
parent::tearDownAfterClass();
/**
* Remove temp dir
*/
shell_exec("rm -rf " . __DIR__ . '/../testsdata/temp');
}
public function testBasicUsage()
{
$this->assertNotNull(
$this->config->getValue('app')
);
}
public function testFastUsage()
{
$this->assertNotNull(
$this->config->getValue('app')
);
}
public function testFastInvalidKey()
{
$this->assertNull(
$this->config->getValue('invalidKey')
);
}
public function testFastInvalidKeyWithDefault()
{
$this->assertEquals(
$this->config->getValue('invalidKey', 'defaultValue'),
'defaultValue'
);
}
public function testFastNestedConfig()
{
$this->assertNotNull(
$this->config->getValue('other.multi.deep.nested')
);
}
public function testCheckExistConfig()
{
$this->assertTrue(
$this->config->existValue('other.multi.deep.nested')
);
}
public function testCheckNotExistConfig()
{
$this->assertFalse(
$this->config->existValue('invalid.config.path')
);
}
public function testSetValue()
{
$this->config->setValue('other.multi.deep.nested', __FUNCTION__);
$this->assertEquals(
$this->config->getValue('other.multi.deep.nested'),
__FUNCTION__
);
}
public function testFailedSaveConfig()
{
$this->setExpectedException('Exception');
$this->config->saveConfigFile('/invalid/path');
}
public function testSuccessSaveConfigOnTempAndReload()
{
$this->config->setValue('other.multi.deep.nested', "SUPERNESTED");
$this->config->saveConfigFile("/tmp/testconfig.sample", true);
$this->assertEquals(
$this->config->getValue('other.multi.deep.nested'),
"SUPERNESTED"
);
}
public function testOverwriteSameConfigFile()
{
$this->config->saveConfigFile();
}
public function testFailWriteConfig()
{
$this->setExpectedException('\RuntimeException');
$this->config->saveConfigFile('/invalid/path/test.sample');
}
/**
* @test
* @group permissions
*/
public function canRaiseExceptionOnUnreadableFile()
{
/**
* Create new temp file
*/
$testFile = tempnam(__DIR__ . '/../testsdata/temp/', 'phpunit_');
self::assertFileExists($testFile);
/**
* Make tempfile unreadable by everyone, but still writeable
*/
$status = chmod($testFile, 0200);
self::assertTrue($status);
/**
* Check permissions it must be 0200 ( --w------- )
*/
$filePerms = (fileperms($testFile) & 0777);
self::assertSame(0200, $filePerms);
/**
* Try to read that file, an exception must be thrown
*/
self::setExpectedException('\RuntimeException');
$this->config->loadConfig($testFile);
/**
* Remove temp file
*/
$status = chmod($testFile, 0744);
self::assertTrue($status);
$filePerms = (fileperms($testFile) & 0777);
self::assertSame(0755, $filePerms);
$status = unlink($testFile);
self::assertTrue($status);
self::assertFileNotExists($testFile);
}
/**
* @return array
*/
public function configDataProvider()
{
return [
[
__DIR__ . '/../testsdata/sample_config_data.converted.yml',
'\clagiordano\weblibs\configmanager\YamlConfigManager',
],
[
__DIR__ . '/../testsdata/sample_config_data.converted.json',
'\clagiordano\weblibs\configmanager\JsonConfigManager',
],
[
__DIR__ . '/../testsdata/sample_config_data.converted.php',
'\clagiordano\weblibs\configmanager\ArrayConfigManager',
],
];
}
/**
* @test
* @dataProvider configDataProvider
* @param mixed $targetConfig
* @param mixed $targetInstance
*/
public function canConvertOneFormatToAnother($targetConfig, $targetInstance)
{
if (file_exists($targetConfig)) {
/**
* Drop target file if already existing
*/
unlink($targetConfig);
}
self::assertFileNotExists($targetConfig);
$target = new $targetInstance($targetConfig);
self::assertInstanceOf($targetInstance, $target);
$converted = $this->config->convert($target);
self::assertInstanceOf($targetInstance, $converted);
self::assertFileNotExists($targetConfig);
}
}

View File

@ -1,25 +0,0 @@
<?php
namespace clagiordano\weblibs\configmanager\tests;
use clagiordano\weblibs\configmanager\ArrayConfigManager;
/**
* Class ArrayConfigManagerTest
* @package clagiordano\weblibs\configmanager\tests
*/
class ArrayConfigManagerTest extends AbstractConfigManagerTest
{
protected $configFile = 'testsdata/sample_config_data.php';
public function setUp()
{
parent::setUp();
$this->config = new ArrayConfigManager("TestConfigData.php");
$this->assertInstanceOf('clagiordano\weblibs\configmanager\ArrayConfigManager', $this->config);
$this->assertFileExists($this->configFile);
$this->config->loadConfig($this->configFile);
}
}

95
vendor/clagiordano/weblibs-configmanager/tests/ConfigManagerTest.php vendored Executable file → Normal file
View File

@ -3,14 +3,17 @@
namespace clagiordano\weblibs\configmanager\tests;
use clagiordano\weblibs\configmanager\ConfigManager;
use PHPUnit\Framework\TestCase;
/**
* Class ConfigManagerTest
* @package clagiordano\weblibs\configmanager\tests
*/
class ConfigManagerTest extends AbstractConfigManagerTest
class ConfigManagerTest extends TestCase
{
protected $configFile = 'testsdata/sample_config_data.php';
/** @var ConfigManager $config */
private $config = null;
private $configFile = 'testsdata/sample_config_data.php';
public function setUp()
{
@ -22,4 +25,92 @@ class ConfigManagerTest extends AbstractConfigManagerTest
$this->assertFileExists($this->configFile);
$this->config->loadConfig($this->configFile);
}
public function testBasicUsage()
{
$this->assertNotNull(
$this->config->getValue('app')
);
}
public function testFastUsage()
{
$this->assertNotNull(
$this->config->getValue('app')
);
}
public function testFastInvalidKey()
{
$this->assertNull(
$this->config->getValue('invalidKey')
);
}
public function testFastInvalidKeyWithDefault()
{
$this->assertEquals(
$this->config->getValue('invalidKey', 'defaultValue'),
'defaultValue'
);
}
public function testFastNestedConfig()
{
$this->assertNotNull(
$this->config->getValue('other.multi.deep.nested')
);
}
public function testCheckExistConfig()
{
$this->assertTrue(
$this->config->existValue('other.multi.deep.nested')
);
}
public function testCheckNotExistConfig()
{
$this->assertFalse(
$this->config->existValue('invalid.config.path')
);
}
public function testSetValue()
{
$this->config->setValue('other.multi.deep.nested', __FUNCTION__);
$this->assertEquals(
$this->config->getValue('other.multi.deep.nested'),
__FUNCTION__
);
}
public function testFailedSaveConfig()
{
$this->setExpectedException('Exception');
$this->config->saveConfigFile('/invalid/path');
}
public function testSuccessSaveConfigOnTempAndReload()
{
$this->config->setValue('other.multi.deep.nested', "SUPERNESTED");
$this->config->saveConfigFile("/tmp/testconfig.php", true);
$this->assertEquals(
$this->config->getValue('other.multi.deep.nested'),
"SUPERNESTED"
);
}
public function testOverwriteSameConfigFile()
{
$this->config->saveConfigFile();
}
public function testFailWriteConfig()
{
$this->setExpectedException('\RuntimeException');
$this->config->saveConfigFile('/invalid/path/test.php');
}
}

View File

@ -1,148 +0,0 @@
<?php
namespace clagiordano\weblibs\configmanager\tests;
use clagiordano\weblibs\configmanager\ArrayConfigManager;
use clagiordano\weblibs\configmanager\FileConverter;
use clagiordano\weblibs\configmanager\YamlConfigManager;
use PHPUnit\Framework\TestCase;
/**
* Class FileConverterTest
* @package clagiordano\weblibs\configmanager\tests
*/
class FileConverterTest extends TestCase
{
/**
* @return array
*/
public function configDataProvider()
{
return [
[
__DIR__ . '/../testsdata/sample_config_data.php',
'\clagiordano\weblibs\configmanager\ArrayConfigManager',
__DIR__ . '/../testsdata/sample_config_data.php.converted.yml',
'\clagiordano\weblibs\configmanager\YamlConfigManager',
],
[
__DIR__ . '/../testsdata/sample_config_data.php',
'\clagiordano\weblibs\configmanager\ArrayConfigManager',
__DIR__ . '/../testsdata/sample_config_data.php.converted.json',
'\clagiordano\weblibs\configmanager\JsonConfigManager',
],
[
__DIR__ . '/../testsdata/sample_config_data.yml',
'\clagiordano\weblibs\configmanager\YamlConfigManager',
__DIR__ . '/../testsdata/sample_config_data.yml.converted.json',
'\clagiordano\weblibs\configmanager\JsonConfigManager',
],
[
__DIR__ . '/../testsdata/sample_config_data.yml',
'\clagiordano\weblibs\configmanager\YamlConfigManager',
__DIR__ . '/../testsdata/sample_config_data.yml.converted.php',
'\clagiordano\weblibs\configmanager\ArrayConfigManager',
],
[
__DIR__ . '/../testsdata/sample_config_data.json',
'\clagiordano\weblibs\configmanager\JsonConfigManager',
__DIR__ . '/../testsdata/sample_config_data.json.converted.yml',
'\clagiordano\weblibs\configmanager\YamlConfigManager',
],
[
__DIR__ . '/../testsdata/sample_config_data.json',
'\clagiordano\weblibs\configmanager\JsonConfigManager',
__DIR__ . '/../testsdata/sample_config_data.json.converted.php',
'\clagiordano\weblibs\configmanager\ArrayConfigManager',
],
];
}
/**
* @test
* @dataProvider configDataProvider
* @param mixed $sourceConfig
* @param mixed $sourceInstance
* @param mixed $targetConfig
* @param mixed $targetInstance
*/
public function canConvertOneFormatToAnother($sourceConfig, $sourceInstance, $targetConfig, $targetInstance)
{
if (file_exists($targetConfig)) {
/**
* Drop target file if already existing
*/
unlink($targetConfig);
}
$source = new $sourceInstance($sourceConfig);
self::assertInstanceOf($sourceInstance, $source);
$target = new $targetInstance($targetConfig);
self::assertInstanceOf($targetInstance, $target);
$converted = FileConverter::convert($source, $target);
self::assertInstanceOf($targetInstance, $converted);
$converted = FileConverter::convertAndSave($source, $target);
self::assertInstanceOf($targetInstance, $converted);
self::assertFileExists($targetConfig);
}
/**
* @test
*/
public function canSuccessConversionOnInvalidSource()
{
$source = new ArrayConfigManager();
$target = new YamlConfigManager(__DIR__ . '/../testsdata/sample_config_data.empty.converted.yml');
$converted = FileConverter::convert($source, $target);
self::assertInstanceOf('\clagiordano\weblibs\configmanager\YamlConfigManager', $converted);
self::assertSame($target, $converted);
}
/**
* @test
*/
public function canSuccessConversionAndSaveOnInvalidSource()
{
$source = new ArrayConfigManager();
$target = new YamlConfigManager(__DIR__ . '/../testsdata/sample_config_data.empty.converted.yml');
$converted = FileConverter::convertAndSave($source, $target);
self::assertInstanceOf('\clagiordano\weblibs\configmanager\YamlConfigManager', $converted);
self::assertSame($target, $converted);
}
/**
* @test
*/
public function cannotFailConversionOnInvalidTarget()
{
$source = new ArrayConfigManager(__DIR__ . '/../testsdata/sample_config_data.php');
$target = new YamlConfigManager();
$converted = FileConverter::convert($source, $target);
self::assertInstanceOf('\clagiordano\weblibs\configmanager\YamlConfigManager', $converted);
}
/**
* @test
*/
public function canFailConversionAndSaveOnInvalidTarget()
{
self::setExpectedException('\RuntimeException');
$source = new ArrayConfigManager(__DIR__ . '/../testsdata/sample_config_data.php');
$target = new YamlConfigManager();
$converted = FileConverter::convertAndSave($source, $target);
self::assertInstanceOf('\clagiordano\weblibs\configmanager\YamlConfigManager', $converted);
}
}

View File

@ -1,25 +0,0 @@
<?php
namespace clagiordano\weblibs\configmanager\tests;
use clagiordano\weblibs\configmanager\JsonConfigManager;
/**
* Class JsonConfigManagerTest
* @package clagiordano\weblibs\configmanager\tests
*/
class JsonConfigManagerTest extends AbstractConfigManagerTest
{
protected $configFile = 'testsdata/sample_config_data.json';
public function setUp()
{
parent::setUp();
$this->config = new JsonConfigManager("TestConfigData.json");
$this->assertInstanceOf('clagiordano\weblibs\configmanager\JsonConfigManager', $this->config);
$this->assertFileExists($this->configFile);
$this->config->loadConfig($this->configFile);
}
}

View File

@ -1,25 +0,0 @@
<?php
namespace clagiordano\weblibs\configmanager\tests;
use clagiordano\weblibs\configmanager\YamlConfigManager;
/**
* Class YamlConfigManagerTest
* @package clagiordano\weblibs\configmanager\tests
*/
class YamlConfigManagerTest extends AbstractConfigManagerTest
{
protected $configFile = 'testsdata/sample_config_data.yml';
public function setUp()
{
parent::setUp();
$this->config = new YamlConfigManager("TestConfigData.yml");
$this->assertInstanceOf('clagiordano\weblibs\configmanager\YamlConfigManager', $this->config);
$this->assertFileExists($this->configFile);
$this->config->loadConfig($this->configFile);
}
}

View File

@ -1 +0,0 @@
{"app":"name","db":{"host":"localhost","user":"sample_user","pass":"sample_pass","port":"3306"},"other":{"multi":{"deep":{"nested":"config_value"}}}}

View File

@ -1,23 +0,0 @@
<?php
return array (
'app' => 'name',
'db' =>
array (
'host' => 'localhost',
'user' => 'sample_user',
'pass' => 'sample_pass',
'port' => '3306',
),
'other' =>
array (
'multi' =>
array (
'deep' =>
array (
'nested' => 'config_value',
),
),
),
);

View File

@ -1,8 +0,0 @@
app: name
db:
host: localhost
user: sample_user
pass: sample_pass
port: '3306'
other:
multi: { deep: { nested: config_value } }

View File

View File

@ -1 +0,0 @@
{"app":"app_name","db":{"host":"localhost","user":"sample_user","pass":"sample_pass","port":3306},"other":{"multi":{"deep":{"nested":"config_value"}}}}

View File

@ -1,8 +0,0 @@
app: app_name
db:
host: localhost
user: sample_user
pass: sample_pass
port: 3306
other:
multi: { deep: { nested: config_value } }

View File

@ -1,8 +0,0 @@
app: name
db:
host: localhost
user: sample_user
pass: sample_pass
port: 3306
other:
multi: { deep: { nested: config_value } }

View File

@ -1 +0,0 @@
{"app":"name","db":{"host":"localhost","user":"sample_user","pass":"sample_pass","port":3306},"other":{"multi":{"deep":{"nested":"config_value"}}}}

View File

@ -1,23 +0,0 @@
<?php
return array (
'app' => 'name',
'db' =>
array (
'host' => 'localhost',
'user' => 'sample_user',
'pass' => 'sample_pass',
'port' => 3306,
),
'other' =>
array (
'multi' =>
array (
'deep' =>
array (
'nested' => 'config_value',
),
),
),
);

View File

@ -7,16 +7,15 @@ $baseDir = dirname($vendorDir);
return array(
'6e3fae29631ef280660b3cdad06f25a8' => $vendorDir . '/symfony/deprecation-contracts/function.php',
'7b11c4dc42b3b3023073cb14e519683c' => $vendorDir . '/ralouphie/getallheaders/src/getallheaders.php',
'c964ee0ededf28c96ebd9db5099ef910' => $vendorDir . '/guzzlehttp/promises/src/functions_include.php',
'0e6d7bf4a5811bfa5cf40c5ccd6fae6a' => $vendorDir . '/symfony/polyfill-mbstring/bootstrap.php',
'37a3dc5111fe8f707ab4c132ef1dbc62' => $vendorDir . '/guzzlehttp/guzzle/src/functions_include.php',
'9b552a3cc426e3287cc811caefa3cf53' => $vendorDir . '/topthink/think-helper/src/helper.php',
'7b11c4dc42b3b3023073cb14e519683c' => $vendorDir . '/ralouphie/getallheaders/src/getallheaders.php',
'a4a119a56e50fbb293281d9a48007e0e' => $vendorDir . '/symfony/polyfill-php80/bootstrap.php',
'25072dd6e2470089de65ae7bf11d3109' => $vendorDir . '/symfony/polyfill-php72/bootstrap.php',
'320cde22f66dd4f5d3fd621d3e88b98f' => $vendorDir . '/symfony/polyfill-ctype/bootstrap.php',
'e69f7f6ee287b969198c3c9d6777bd38' => $vendorDir . '/symfony/polyfill-intl-normalizer/bootstrap.php',
'9b552a3cc426e3287cc811caefa3cf53' => $vendorDir . '/topthink/think-helper/src/helper.php',
'37a3dc5111fe8f707ab4c132ef1dbc62' => $vendorDir . '/guzzlehttp/guzzle/src/functions_include.php',
'35fab96057f1bf5e7aba31a8a6d5fdde' => $vendorDir . '/topthink/think-orm/stubs/load_stubs.php',
'25072dd6e2470089de65ae7bf11d3109' => $vendorDir . '/symfony/polyfill-php72/bootstrap.php',
'e69f7f6ee287b969198c3c9d6777bd38' => $vendorDir . '/symfony/polyfill-intl-normalizer/bootstrap.php',
'a1105708a18b76903365ca1c4aa61b02' => $vendorDir . '/symfony/translation/Resources/functions.php',
'f598d06aa772fa33d905e87be6398fb1' => $vendorDir . '/symfony/polyfill-intl-idn/bootstrap.php',
'0d59ee240a4cd96ddbb4ff164fccea4d' => $vendorDir . '/symfony/polyfill-php73/bootstrap.php',
'd767e4fc2dc52fe66584ab8c6684783e' => $vendorDir . '/adbario/php-dot-notation/src/helpers.php',
@ -31,4 +30,5 @@ return array(
'841780ea2e1d6545ea3a253239d59c05' => $vendorDir . '/qiniu/php-sdk/src/Qiniu/functions.php',
'941748b3c8cae4466c827dfb5ca9602a' => $vendorDir . '/rmccue/requests/library/Deprecated.php',
'667aeda72477189d0494fecd327c3641' => $vendorDir . '/symfony/var-dumper/Resources/functions/dump.php',
'cc56288302d9df745d97c934d6a6e5f0' => $vendorDir . '/topthink/think-queue/src/common.php',
);

View File

@ -6,10 +6,11 @@ $vendorDir = dirname(__DIR__);
$baseDir = dirname($vendorDir);
return array(
'yunwuxin\\cron\\' => array($vendorDir . '/yunwuxin/think-cron/src/cron'),
'think\\view\\driver\\' => array($vendorDir . '/topthink/think-view/src'),
'think\\trace\\' => array($vendorDir . '/topthink/think-trace/src'),
'think\\app\\' => array($vendorDir . '/topthink/think-multi-app/src'),
'think\\' => array($vendorDir . '/topthink/framework/src/think', $vendorDir . '/topthink/think-helper/src', $vendorDir . '/topthink/think-orm/src', $vendorDir . '/topthink/think-template/src'),
'think\\' => array($vendorDir . '/topthink/framework/src/think', $vendorDir . '/topthink/think-helper/src', $vendorDir . '/topthink/think-orm/src', $vendorDir . '/topthink/think-template/src', $vendorDir . '/topthink/think-queue/src'),
'com\\junziqian\\sdk\\' => array($vendorDir . '/ebaoquan/junziqian_sdk/src/com/junziqian/sdk'),
'clagiordano\\weblibs\\configmanager\\' => array($vendorDir . '/clagiordano/weblibs-configmanager/src'),
'app\\' => array($baseDir . '/app'),
@ -25,13 +26,14 @@ return array(
'Symfony\\Polyfill\\Mbstring\\' => array($vendorDir . '/symfony/polyfill-mbstring'),
'Symfony\\Polyfill\\Intl\\Normalizer\\' => array($vendorDir . '/symfony/polyfill-intl-normalizer'),
'Symfony\\Polyfill\\Intl\\Idn\\' => array($vendorDir . '/symfony/polyfill-intl-idn'),
'Symfony\\Polyfill\\Ctype\\' => array($vendorDir . '/symfony/polyfill-ctype'),
'Symfony\\Contracts\\Translation\\' => array($vendorDir . '/symfony/translation-contracts'),
'Symfony\\Contracts\\Service\\' => array($vendorDir . '/symfony/service-contracts'),
'Symfony\\Contracts\\HttpClient\\' => array($vendorDir . '/symfony/http-client-contracts'),
'Symfony\\Contracts\\Cache\\' => array($vendorDir . '/symfony/cache-contracts'),
'Symfony\\Component\\Yaml\\' => array($vendorDir . '/symfony/yaml'),
'Symfony\\Component\\VarExporter\\' => array($vendorDir . '/symfony/var-exporter'),
'Symfony\\Component\\VarDumper\\' => array($vendorDir . '/symfony/var-dumper'),
'Symfony\\Component\\Translation\\' => array($vendorDir . '/symfony/translation'),
'Symfony\\Component\\Process\\' => array($vendorDir . '/symfony/process'),
'Symfony\\Component\\Mime\\' => array($vendorDir . '/symfony/mime'),
'Symfony\\Component\\HttpFoundation\\' => array($vendorDir . '/symfony/http-foundation'),
'Symfony\\Component\\HttpClient\\' => array($vendorDir . '/symfony/http-client'),
@ -50,7 +52,6 @@ return array(
'OSS\\' => array($vendorDir . '/aliyuncs/oss-sdk-php/src/OSS'),
'Nyholm\\Psr7\\' => array($vendorDir . '/nyholm/psr7/src'),
'Nyholm\\Psr7Server\\' => array($vendorDir . '/nyholm/psr7-server/src'),
'MyCLabs\\Enum\\' => array($vendorDir . '/myclabs/php-enum/src'),
'Monolog\\' => array($vendorDir . '/monolog/monolog/src/Monolog'),
'Matrix\\' => array($vendorDir . '/markbaker/matrix/classes/src'),
'JmesPath\\' => array($vendorDir . '/mtdowling/jmespath.php/src'),
@ -63,6 +64,7 @@ return array(
'EasyWeChat\\' => array($vendorDir . '/w7corp/easywechat/src'),
'Cron\\' => array($vendorDir . '/dragonmantank/cron-expression/src/Cron'),
'Complex\\' => array($vendorDir . '/markbaker/complex/classes/src'),
'Carbon\\' => array($vendorDir . '/nesbot/carbon/src/Carbon'),
'AlibabaCloud\\Client\\' => array($vendorDir . '/alibabacloud/client/src'),
'Adbar\\' => array($vendorDir . '/adbario/php-dot-notation/src'),
);

View File

@ -8,16 +8,15 @@ class ComposerStaticInitd2a74ba94e266cc4f45a64c54a292d7e
{
public static $files = array (
'6e3fae29631ef280660b3cdad06f25a8' => __DIR__ . '/..' . '/symfony/deprecation-contracts/function.php',
'7b11c4dc42b3b3023073cb14e519683c' => __DIR__ . '/..' . '/ralouphie/getallheaders/src/getallheaders.php',
'c964ee0ededf28c96ebd9db5099ef910' => __DIR__ . '/..' . '/guzzlehttp/promises/src/functions_include.php',
'0e6d7bf4a5811bfa5cf40c5ccd6fae6a' => __DIR__ . '/..' . '/symfony/polyfill-mbstring/bootstrap.php',
'37a3dc5111fe8f707ab4c132ef1dbc62' => __DIR__ . '/..' . '/guzzlehttp/guzzle/src/functions_include.php',
'9b552a3cc426e3287cc811caefa3cf53' => __DIR__ . '/..' . '/topthink/think-helper/src/helper.php',
'7b11c4dc42b3b3023073cb14e519683c' => __DIR__ . '/..' . '/ralouphie/getallheaders/src/getallheaders.php',
'a4a119a56e50fbb293281d9a48007e0e' => __DIR__ . '/..' . '/symfony/polyfill-php80/bootstrap.php',
'25072dd6e2470089de65ae7bf11d3109' => __DIR__ . '/..' . '/symfony/polyfill-php72/bootstrap.php',
'320cde22f66dd4f5d3fd621d3e88b98f' => __DIR__ . '/..' . '/symfony/polyfill-ctype/bootstrap.php',
'e69f7f6ee287b969198c3c9d6777bd38' => __DIR__ . '/..' . '/symfony/polyfill-intl-normalizer/bootstrap.php',
'9b552a3cc426e3287cc811caefa3cf53' => __DIR__ . '/..' . '/topthink/think-helper/src/helper.php',
'37a3dc5111fe8f707ab4c132ef1dbc62' => __DIR__ . '/..' . '/guzzlehttp/guzzle/src/functions_include.php',
'35fab96057f1bf5e7aba31a8a6d5fdde' => __DIR__ . '/..' . '/topthink/think-orm/stubs/load_stubs.php',
'25072dd6e2470089de65ae7bf11d3109' => __DIR__ . '/..' . '/symfony/polyfill-php72/bootstrap.php',
'e69f7f6ee287b969198c3c9d6777bd38' => __DIR__ . '/..' . '/symfony/polyfill-intl-normalizer/bootstrap.php',
'a1105708a18b76903365ca1c4aa61b02' => __DIR__ . '/..' . '/symfony/translation/Resources/functions.php',
'f598d06aa772fa33d905e87be6398fb1' => __DIR__ . '/..' . '/symfony/polyfill-intl-idn/bootstrap.php',
'0d59ee240a4cd96ddbb4ff164fccea4d' => __DIR__ . '/..' . '/symfony/polyfill-php73/bootstrap.php',
'd767e4fc2dc52fe66584ab8c6684783e' => __DIR__ . '/..' . '/adbario/php-dot-notation/src/helpers.php',
@ -32,9 +31,14 @@ class ComposerStaticInitd2a74ba94e266cc4f45a64c54a292d7e
'841780ea2e1d6545ea3a253239d59c05' => __DIR__ . '/..' . '/qiniu/php-sdk/src/Qiniu/functions.php',
'941748b3c8cae4466c827dfb5ca9602a' => __DIR__ . '/..' . '/rmccue/requests/library/Deprecated.php',
'667aeda72477189d0494fecd327c3641' => __DIR__ . '/..' . '/symfony/var-dumper/Resources/functions/dump.php',
'cc56288302d9df745d97c934d6a6e5f0' => __DIR__ . '/..' . '/topthink/think-queue/src/common.php',
);
public static $prefixLengthsPsr4 = array (
'y' =>
array (
'yunwuxin\\cron\\' => 14,
),
't' =>
array (
'think\\view\\driver\\' => 18,
@ -74,13 +78,14 @@ class ComposerStaticInitd2a74ba94e266cc4f45a64c54a292d7e
'Symfony\\Polyfill\\Mbstring\\' => 26,
'Symfony\\Polyfill\\Intl\\Normalizer\\' => 33,
'Symfony\\Polyfill\\Intl\\Idn\\' => 26,
'Symfony\\Polyfill\\Ctype\\' => 23,
'Symfony\\Contracts\\Translation\\' => 30,
'Symfony\\Contracts\\Service\\' => 26,
'Symfony\\Contracts\\HttpClient\\' => 29,
'Symfony\\Contracts\\Cache\\' => 24,
'Symfony\\Component\\Yaml\\' => 23,
'Symfony\\Component\\VarExporter\\' => 30,
'Symfony\\Component\\VarDumper\\' => 28,
'Symfony\\Component\\Translation\\' => 30,
'Symfony\\Component\\Process\\' => 26,
'Symfony\\Component\\Mime\\' => 23,
'Symfony\\Component\\HttpFoundation\\' => 33,
'Symfony\\Component\\HttpClient\\' => 29,
@ -114,7 +119,6 @@ class ComposerStaticInitd2a74ba94e266cc4f45a64c54a292d7e
),
'M' =>
array (
'MyCLabs\\Enum\\' => 13,
'Monolog\\' => 8,
'Matrix\\' => 7,
),
@ -139,6 +143,7 @@ class ComposerStaticInitd2a74ba94e266cc4f45a64c54a292d7e
array (
'Cron\\' => 5,
'Complex\\' => 8,
'Carbon\\' => 7,
),
'A' =>
array (
@ -148,6 +153,10 @@ class ComposerStaticInitd2a74ba94e266cc4f45a64c54a292d7e
);
public static $prefixDirsPsr4 = array (
'yunwuxin\\cron\\' =>
array (
0 => __DIR__ . '/..' . '/yunwuxin/think-cron/src/cron',
),
'think\\view\\driver\\' =>
array (
0 => __DIR__ . '/..' . '/topthink/think-view/src',
@ -166,6 +175,7 @@ class ComposerStaticInitd2a74ba94e266cc4f45a64c54a292d7e
1 => __DIR__ . '/..' . '/topthink/think-helper/src',
2 => __DIR__ . '/..' . '/topthink/think-orm/src',
3 => __DIR__ . '/..' . '/topthink/think-template/src',
4 => __DIR__ . '/..' . '/topthink/think-queue/src',
),
'com\\junziqian\\sdk\\' =>
array (
@ -227,9 +237,9 @@ class ComposerStaticInitd2a74ba94e266cc4f45a64c54a292d7e
array (
0 => __DIR__ . '/..' . '/symfony/polyfill-intl-idn',
),
'Symfony\\Polyfill\\Ctype\\' =>
'Symfony\\Contracts\\Translation\\' =>
array (
0 => __DIR__ . '/..' . '/symfony/polyfill-ctype',
0 => __DIR__ . '/..' . '/symfony/translation-contracts',
),
'Symfony\\Contracts\\Service\\' =>
array (
@ -243,10 +253,6 @@ class ComposerStaticInitd2a74ba94e266cc4f45a64c54a292d7e
array (
0 => __DIR__ . '/..' . '/symfony/cache-contracts',
),
'Symfony\\Component\\Yaml\\' =>
array (
0 => __DIR__ . '/..' . '/symfony/yaml',
),
'Symfony\\Component\\VarExporter\\' =>
array (
0 => __DIR__ . '/..' . '/symfony/var-exporter',
@ -255,6 +261,14 @@ class ComposerStaticInitd2a74ba94e266cc4f45a64c54a292d7e
array (
0 => __DIR__ . '/..' . '/symfony/var-dumper',
),
'Symfony\\Component\\Translation\\' =>
array (
0 => __DIR__ . '/..' . '/symfony/translation',
),
'Symfony\\Component\\Process\\' =>
array (
0 => __DIR__ . '/..' . '/symfony/process',
),
'Symfony\\Component\\Mime\\' =>
array (
0 => __DIR__ . '/..' . '/symfony/mime',
@ -328,10 +342,6 @@ class ComposerStaticInitd2a74ba94e266cc4f45a64c54a292d7e
array (
0 => __DIR__ . '/..' . '/nyholm/psr7-server/src',
),
'MyCLabs\\Enum\\' =>
array (
0 => __DIR__ . '/..' . '/myclabs/php-enum/src',
),
'Monolog\\' =>
array (
0 => __DIR__ . '/..' . '/monolog/monolog/src/Monolog',
@ -380,6 +390,10 @@ class ComposerStaticInitd2a74ba94e266cc4f45a64c54a292d7e
array (
0 => __DIR__ . '/..' . '/markbaker/complex/classes/src',
),
'Carbon\\' =>
array (
0 => __DIR__ . '/..' . '/nesbot/carbon/src/Carbon',
),
'AlibabaCloud\\Client\\' =>
array (
0 => __DIR__ . '/..' . '/alibabacloud/client/src',

File diff suppressed because it is too large Load Diff

View File

@ -3,7 +3,7 @@
'name' => 'topthink/think',
'pretty_version' => 'dev-master',
'version' => 'dev-master',
'reference' => '0197552395b685f53388789e60cb3a0be9f37b16',
'reference' => '2ce3ce34e1ecd3baf3de0336dbc82d38522186d8',
'type' => 'project',
'install_path' => __DIR__ . '/../../',
'aliases' => array(),
@ -38,18 +38,18 @@
'dev_requirement' => false,
),
'clagiordano/weblibs-configmanager' => array(
'pretty_version' => 'v1.5.0',
'version' => '1.5.0.0',
'reference' => '8802c7396d61a923c9a73e37ead062b24bb1b273',
'pretty_version' => 'v1.2.0',
'version' => '1.2.0.0',
'reference' => '5c8ebcc62782313b1278afe802b120d18c07a059',
'type' => 'library',
'install_path' => __DIR__ . '/../clagiordano/weblibs-configmanager',
'aliases' => array(),
'dev_requirement' => false,
),
'dragonmantank/cron-expression' => array(
'pretty_version' => 'v3.3.1',
'version' => '3.3.1.0',
'reference' => 'be85b3f05b46c39bbc0d95f6c071ddff669510fa',
'pretty_version' => 'v3.3.2',
'version' => '3.3.2.0',
'reference' => '782ca5968ab8b954773518e9e49a6f892a34b2a8',
'type' => 'library',
'install_path' => __DIR__ . '/../dragonmantank/cron-expression',
'aliases' => array(),
@ -101,18 +101,18 @@
'dev_requirement' => false,
),
'guzzlehttp/promises' => array(
'pretty_version' => '1.5.3',
'version' => '1.5.3.0',
'reference' => '67ab6e18aaa14d753cc148911d273f6e6cb6721e',
'pretty_version' => '2.0.1',
'version' => '2.0.1.0',
'reference' => '111166291a0f8130081195ac4556a5587d7f1b5d',
'type' => 'library',
'install_path' => __DIR__ . '/../guzzlehttp/promises',
'aliases' => array(),
'dev_requirement' => false,
),
'guzzlehttp/psr7' => array(
'pretty_version' => '2.5.0',
'version' => '2.5.0.0',
'reference' => 'b635f279edd83fc275f822a1188157ffea568ff6',
'pretty_version' => '2.6.0',
'version' => '2.6.0.0',
'reference' => '8bd7c33a0734ae1c5d074360512beb716bef3f77',
'type' => 'library',
'install_path' => __DIR__ . '/../guzzlehttp/psr7',
'aliases' => array(),
@ -128,9 +128,9 @@
'dev_requirement' => false,
),
'maennchen/zipstream-php' => array(
'pretty_version' => '2.4.0',
'version' => '2.4.0.0',
'reference' => '3fa72e4c71a43f9e9118752a5c90e476a8dc9eb3',
'pretty_version' => '3.1.0',
'version' => '3.1.0.0',
'reference' => 'b8174494eda667f7d13876b4a7bfef0f62a7c0d1',
'type' => 'library',
'install_path' => __DIR__ . '/../maennchen/zipstream-php',
'aliases' => array(),
@ -178,12 +178,12 @@
'aliases' => array(),
'dev_requirement' => false,
),
'myclabs/php-enum' => array(
'pretty_version' => '1.8.3',
'version' => '1.8.3.0',
'reference' => 'b942d263c641ddb5190929ff840c68f78713e937',
'nesbot/carbon' => array(
'pretty_version' => '2.68.1',
'version' => '2.68.1.0',
'reference' => '4f991ed2a403c85efbc4f23eb4030063fdbe01da',
'type' => 'library',
'install_path' => __DIR__ . '/../myclabs/php-enum',
'install_path' => __DIR__ . '/../nesbot/carbon',
'aliases' => array(),
'dev_requirement' => false,
),
@ -233,9 +233,9 @@
),
),
'phpoffice/phpspreadsheet' => array(
'pretty_version' => '1.28.0',
'version' => '1.28.0.0',
'reference' => '6e81cf39bbd93ebc3a4e8150444c41e8aa9b769a',
'pretty_version' => '1.29.0',
'version' => '1.29.0.0',
'reference' => 'fde2ccf55eaef7e86021ff1acce26479160a0fa0',
'type' => 'library',
'install_path' => __DIR__ . '/../phpoffice/phpspreadsheet',
'aliases' => array(),
@ -266,9 +266,9 @@
'dev_requirement' => false,
),
'psr/http-client' => array(
'pretty_version' => '1.0.1',
'version' => '1.0.1.0',
'reference' => '2dfb5f6c5eff0e91e20e913f8c5452ed95b86621',
'pretty_version' => '1.0.2',
'version' => '1.0.2.0',
'reference' => '0955afe48220520692d2d09f7ab7e0f93ffd6a31',
'type' => 'library',
'install_path' => __DIR__ . '/../psr/http-client',
'aliases' => array(),
@ -368,9 +368,9 @@
'dev_requirement' => false,
),
'rmccue/requests' => array(
'pretty_version' => 'v2.0.5',
'version' => '2.0.5.0',
'reference' => 'b717f1d2f4ef7992ec0c127747ed8b7e170c2f49',
'pretty_version' => 'v2.0.7',
'version' => '2.0.7.0',
'reference' => 'e14a6f4e7438d3f8da3f2657759e6367b906ee23',
'type' => 'library',
'install_path' => __DIR__ . '/../rmccue/requests',
'aliases' => array(),
@ -401,27 +401,27 @@
),
),
'symfony/deprecation-contracts' => array(
'pretty_version' => 'v3.0.2',
'version' => '3.0.2.0',
'reference' => '26954b3d62a6c5fd0ea8a2a00c0353a14978d05c',
'pretty_version' => 'v3.3.0',
'version' => '3.3.0.0',
'reference' => '7c3aff79d10325257a001fcf92d991f24fc967cf',
'type' => 'library',
'install_path' => __DIR__ . '/../symfony/deprecation-contracts',
'aliases' => array(),
'dev_requirement' => false,
),
'symfony/http-client' => array(
'pretty_version' => 'v6.0.20',
'version' => '6.0.20.0',
'reference' => '541c04560da1875f62c963c3aab6ea12a7314e11',
'pretty_version' => 'v6.2.13',
'version' => '6.2.13.0',
'reference' => '297374a399ce6852d5905d92a1351df00bb9dd10',
'type' => 'library',
'install_path' => __DIR__ . '/../symfony/http-client',
'aliases' => array(),
'dev_requirement' => false,
),
'symfony/http-client-contracts' => array(
'pretty_version' => 'v3.0.2',
'version' => '3.0.2.0',
'reference' => '4184b9b63af1edaf35b6a7974c6f1f9f33294129',
'pretty_version' => 'v3.3.0',
'version' => '3.3.0.0',
'reference' => '3b66325d0176b4ec826bffab57c9037d759c31fb',
'type' => 'library',
'install_path' => __DIR__ . '/../symfony/http-client-contracts',
'aliases' => array(),
@ -434,32 +434,23 @@
),
),
'symfony/http-foundation' => array(
'pretty_version' => 'v6.0.20',
'version' => '6.0.20.0',
'reference' => 'e16b2676a4b3b1fa12378a20b29c364feda2a8d6',
'pretty_version' => 'v6.1.12',
'version' => '6.1.12.0',
'reference' => 'bd1bcfb0eba14de22c4d086c5023e608f37366ed',
'type' => 'library',
'install_path' => __DIR__ . '/../symfony/http-foundation',
'aliases' => array(),
'dev_requirement' => false,
),
'symfony/mime' => array(
'pretty_version' => 'v6.0.19',
'version' => '6.0.19.0',
'reference' => 'd7052547a0070cbeadd474e172b527a00d657301',
'pretty_version' => 'v6.3.3',
'version' => '6.3.3.0',
'reference' => '9a0cbd52baa5ba5a5b1f0cacc59466f194730f98',
'type' => 'library',
'install_path' => __DIR__ . '/../symfony/mime',
'aliases' => array(),
'dev_requirement' => false,
),
'symfony/polyfill-ctype' => array(
'pretty_version' => 'v1.27.0',
'version' => '1.27.0.0',
'reference' => '5bbc823adecdae860bb64756d639ecfec17b050a',
'type' => 'library',
'install_path' => __DIR__ . '/../symfony/polyfill-ctype',
'aliases' => array(),
'dev_requirement' => false,
),
'symfony/polyfill-intl-idn' => array(
'pretty_version' => 'v1.27.0',
'version' => '1.27.0.0',
@ -523,10 +514,19 @@
'aliases' => array(),
'dev_requirement' => false,
),
'symfony/process' => array(
'pretty_version' => 'v5.4.26',
'version' => '5.4.26.0',
'reference' => '1a44dc377ec86a50fab40d066cd061e28a6b482f',
'type' => 'library',
'install_path' => __DIR__ . '/../symfony/process',
'aliases' => array(),
'dev_requirement' => false,
),
'symfony/psr-http-message-bridge' => array(
'pretty_version' => 'v2.2.0',
'version' => '2.2.0.0',
'reference' => '28a732c05bbad801304ad5a5c674cf2970508993',
'pretty_version' => 'v2.3.1',
'version' => '2.3.1.0',
'reference' => '581ca6067eb62640de5ff08ee1ba6850a0ee472e',
'type' => 'symfony-bridge',
'install_path' => __DIR__ . '/../symfony/psr-http-message-bridge',
'aliases' => array(),
@ -541,6 +541,30 @@
'aliases' => array(),
'dev_requirement' => false,
),
'symfony/translation' => array(
'pretty_version' => 'v6.3.3',
'version' => '6.3.3.0',
'reference' => '3ed078c54bc98bbe4414e1e9b2d5e85ed5a5c8bd',
'type' => 'library',
'install_path' => __DIR__ . '/../symfony/translation',
'aliases' => array(),
'dev_requirement' => false,
),
'symfony/translation-contracts' => array(
'pretty_version' => 'v3.3.0',
'version' => '3.3.0.0',
'reference' => '02c24deb352fb0d79db5486c0c79905a85e37e86',
'type' => 'library',
'install_path' => __DIR__ . '/../symfony/translation-contracts',
'aliases' => array(),
'dev_requirement' => false,
),
'symfony/translation-implementation' => array(
'dev_requirement' => false,
'provided' => array(
0 => '2.3|3.0',
),
),
'symfony/var-dumper' => array(
'pretty_version' => 'v4.4.47',
'version' => '4.4.47.0',
@ -551,27 +575,18 @@
'dev_requirement' => true,
),
'symfony/var-exporter' => array(
'pretty_version' => 'v6.0.19',
'version' => '6.0.19.0',
'reference' => 'df56f53818c2d5d9f683f4ad2e365ba73a3b69d2',
'pretty_version' => 'v6.3.2',
'version' => '6.3.2.0',
'reference' => '3400949782c0cb5b3e73aa64cfd71dde000beccc',
'type' => 'library',
'install_path' => __DIR__ . '/../symfony/var-exporter',
'aliases' => array(),
'dev_requirement' => false,
),
'symfony/yaml' => array(
'pretty_version' => 'v2.8.52',
'version' => '2.8.52.0',
'reference' => '02c1859112aa779d9ab394ae4f3381911d84052b',
'type' => 'library',
'install_path' => __DIR__ . '/../symfony/yaml',
'aliases' => array(),
'dev_requirement' => false,
),
'tencentcloud/tencentcloud-sdk-php' => array(
'pretty_version' => '3.0.935',
'version' => '3.0.935.0',
'reference' => '91af4a89502782136c969c70b96d2fe7f76fba48',
'pretty_version' => '3.0.950',
'version' => '3.0.950.0',
'reference' => '33490ab22dc357d297c3419740a23c39ea70b20e',
'type' => 'library',
'install_path' => __DIR__ . '/../tencentcloud/tencentcloud-sdk-php',
'aliases' => array(),
@ -598,7 +613,7 @@
'topthink/think' => array(
'pretty_version' => 'dev-master',
'version' => 'dev-master',
'reference' => '0197552395b685f53388789e60cb3a0be9f37b16',
'reference' => '2ce3ce34e1ecd3baf3de0336dbc82d38522186d8',
'type' => 'project',
'install_path' => __DIR__ . '/../../',
'aliases' => array(),
@ -631,6 +646,15 @@
'aliases' => array(),
'dev_requirement' => false,
),
'topthink/think-queue' => array(
'pretty_version' => 'v3.0.9',
'version' => '3.0.9.0',
'reference' => '654812b47dd7c708c4443deed27f212f8382e8da',
'type' => 'library',
'install_path' => __DIR__ . '/../topthink/think-queue',
'aliases' => array(),
'dev_requirement' => false,
),
'topthink/think-template' => array(
'pretty_version' => 'v2.0.9',
'version' => '2.0.9.0',
@ -659,9 +683,9 @@
'dev_requirement' => false,
),
'w7corp/easywechat' => array(
'pretty_version' => '6.8.0',
'version' => '6.8.0.0',
'reference' => '60f0b4ba2ac3144df1a2291193daa34beb949d26',
'pretty_version' => '6.12.3',
'version' => '6.12.3.0',
'reference' => '10b9f31b61b4e5327c9e4457dffcf307de2deb6c',
'type' => 'library',
'install_path' => __DIR__ . '/../w7corp/easywechat',
'aliases' => array(),
@ -676,5 +700,14 @@
'aliases' => array(),
'dev_requirement' => false,
),
'yunwuxin/think-cron' => array(
'pretty_version' => 'v3.0.6',
'version' => '3.0.6.0',
'reference' => '4013c39cea4600e05ffd10de5b63177bfb9bf480',
'type' => 'library',
'install_path' => __DIR__ . '/../yunwuxin/think-cron',
'aliases' => array(),
'dev_requirement' => false,
),
),
);

View File

@ -4,8 +4,8 @@
$issues = array();
if (!(PHP_VERSION_ID >= 80002)) {
$issues[] = 'Your Composer dependencies require a PHP version ">= 8.0.2". You are running ' . PHP_VERSION . '.';
if (!(PHP_VERSION_ID >= 80100)) {
$issues[] = 'Your Composer dependencies require a PHP version ">= 8.1.0". You are running ' . PHP_VERSION . '.';
}
if ($issues) {

View File

@ -1,5 +1,16 @@
# Change Log
## [3.3.2] - 2022-09-19
### Added
- N/A
### Changed
- Skip some daylight savings time tests for PHP 8.1 daylight savings time weirdness (#146)
### Fixed
- Changed string interpolations to work better with PHP 8.2 (#142)
## [3.3.1] - 2022-01-18
### Added

View File

@ -37,5 +37,11 @@
"scripts": {
"phpstan": "./vendor/bin/phpstan analyze",
"test": "phpunit"
},
"config": {
"allow-plugins": {
"ocramius/package-versions": true,
"phpstan/extension-installer": true
}
}
}

View File

@ -49,7 +49,7 @@ class DayOfMonthField extends AbstractField
private static function getNearestWeekday(int $currentYear, int $currentMonth, int $targetDay): ?DateTime
{
$tday = str_pad((string) $targetDay, 2, '0', STR_PAD_LEFT);
$target = DateTime::createFromFormat('Y-m-d', "${currentYear}-${currentMonth}-${tday}");
$target = DateTime::createFromFormat('Y-m-d', "{$currentYear}-{$currentMonth}-{$tday}");
if ($target === false) {
return null;
@ -94,9 +94,9 @@ class DayOfMonthField extends AbstractField
}
// Check to see if this is the nearest weekday to a particular value
if (strpos($value, 'W')) {
if ($wPosition = strpos($value, 'W')) {
// Parse the target day
$targetDay = (int) substr($value, 0, strpos($value, 'W'));
$targetDay = (int) substr($value, 0, $wPosition);
// Find out if the current day is the nearest day of the week
$nearest = self::getNearestWeekday(
(int) $date->format('Y'),

View File

@ -68,8 +68,8 @@ class DayOfWeekField extends AbstractField
$lastDayOfMonth = (int) $date->format('t');
// Find out if this is the last specific weekday of the month
if (strpos($value, 'L')) {
$weekday = $this->convertLiterals(substr($value, 0, strpos($value, 'L')));
if ($lPosition = strpos($value, 'L')) {
$weekday = $this->convertLiterals(substr($value, 0, $lPosition));
$weekday %= 7;
$daysInMonth = (int) $date->format('t');

View File

@ -25,7 +25,7 @@ class HoursField extends AbstractField
/**
* @var array|null Transitions returned by DateTimeZone::getTransitions()
*/
protected $transitions = null;
protected $transitions = [];
/**
* @var int|null Timestamp of the start of the transitions range
@ -92,7 +92,7 @@ class HoursField extends AbstractField
$dtLimitStart->getTimestamp(),
$dtLimitEnd->getTimestamp()
);
if ($this->transitions === false) {
if (empty($this->transitions)) {
return null;
}
$this->transitionsStart = $dtLimitStart->getTimestamp();

@ -1 +1 @@
Subproject commit 1294ea49ff9ecc4532821f8798304816cbf8dd74
Subproject commit 9acc82cd23d807280ddd29df2117e7890094d049

View File

@ -1,17 +1,43 @@
# CHANGELOG
## 2.0.1 - 2023-08-03
### Changed
- PHP 8.3 support
## 2.0.0 - 2023-05-21
### Added
- Added PHP 7 type hints
### Changed
- All previously non-final non-exception classes have been marked as soft-final
### Removed
- Dropped PHP < 7.2 support
- All functions in the `GuzzleHttp\Promise` namespace
## 1.5.3 - 2023-05-21
### Changed
- Removed remaining usage of deprecated functions
## 1.5.2 - 2022-08-07
### Changed
- Officially support PHP 8.2
## 1.5.1 - 2021-10-22
### Fixed
@ -19,6 +45,7 @@
- Revert "Call handler when waiting on fulfilled/rejected Promise"
- Fix pool memory leak when empty array of promises provided
## 1.5.0 - 2021-10-07
### Changed
@ -30,12 +57,14 @@
- Fix manually settle promises generated with `Utils::task`
## 1.4.1 - 2021-02-18
### Fixed
- Fixed `each_limit` skipping promises and failing
## 1.4.0 - 2020-09-30
### Added

View File

@ -29,6 +29,21 @@ for a general introduction to promises.
`GuzzleHttp\Promise\Coroutine::of()`.
## Installation
```shell
composer require guzzlehttp/promises
```
## Version Guidance
| Version | Status | PHP Version |
|---------|------------------------|--------------|
| 1.x | Bug and security fixes | >=5.5,<8.3 |
| 2.x | Latest | >=7.2.5,<8.4 |
## Quick Start
A *promise* represents the eventual result of an asynchronous operation. The
@ -430,8 +445,6 @@ $loop = React\EventLoop\Factory::create();
$loop->addPeriodicTimer(0, [$queue, 'run']);
```
*TODO*: Perhaps adding a `futureTick()` on each tick would be faster?
## Implementation Notes
@ -501,8 +514,8 @@ $promise->resolve('foo');
A static API was first introduced in 1.4.0, in order to mitigate problems with
functions conflicting between global and local copies of the package. The
function API will be removed in 2.0.0. A migration table has been provided here
for your convenience:
function API was removed in 2.0.0. A migration table has been provided here for
your convenience:
| Original Function | Replacement Method |
|----------------|----------------|

View File

@ -26,27 +26,32 @@
}
],
"require": {
"php": ">=5.5"
"php": "^7.2.5 || ^8.0"
},
"require-dev": {
"symfony/phpunit-bridge": "^4.4 || ^5.1"
"bamarni/composer-bin-plugin": "^1.8.1",
"phpunit/phpunit": "^8.5.29 || ^9.5.23"
},
"autoload": {
"psr-4": {
"GuzzleHttp\\Promise\\": "src/"
},
"files": ["src/functions_include.php"]
}
},
"autoload-dev": {
"psr-4": {
"GuzzleHttp\\Promise\\Tests\\": "tests/"
}
},
"scripts": {
"test": "vendor/bin/simple-phpunit",
"test-ci": "vendor/bin/simple-phpunit --coverage-text"
"extra": {
"bamarni-bin": {
"bin-links": true,
"forward-command": false
}
},
"config": {
"allow-plugins": {
"bamarni/composer-bin-plugin": true
},
"preferred-install": "dist",
"sort-packages": true
}

View File

@ -1,5 +1,7 @@
<?php
declare(strict_types=1);
namespace GuzzleHttp\Promise;
/**
@ -7,7 +9,7 @@ namespace GuzzleHttp\Promise;
*/
class AggregateException extends RejectionException
{
public function __construct($msg, array $reasons)
public function __construct(string $msg, array $reasons)
{
parent::__construct(
$reasons,

View File

@ -1,5 +1,7 @@
<?php
declare(strict_types=1);
namespace GuzzleHttp\Promise;
/**

View File

@ -1,8 +1,9 @@
<?php
declare(strict_types=1);
namespace GuzzleHttp\Promise;
use Exception;
use Generator;
use Throwable;
@ -27,7 +28,7 @@ use Throwable;
* $value = (yield createPromise('a'));
* try {
* $value = (yield createPromise($value . 'b'));
* } catch (\Exception $e) {
* } catch (\Throwable $e) {
* // The promise was rejected.
* }
* yield $value . 'c';
@ -40,7 +41,7 @@ use Throwable;
*
* @return Promise
*
* @link https://github.com/petkaantonov/bluebird/blob/master/API.md#generators inspiration
* @see https://github.com/petkaantonov/bluebird/blob/master/API.md#generators inspiration
*/
final class Coroutine implements PromiseInterface
{
@ -62,15 +63,13 @@ final class Coroutine implements PromiseInterface
public function __construct(callable $generatorFn)
{
$this->generator = $generatorFn();
$this->result = new Promise(function () {
$this->result = new Promise(function (): void {
while (isset($this->currentPromise)) {
$this->currentPromise->wait();
}
});
try {
$this->nextCoroutine($this->generator->current());
} catch (\Exception $exception) {
$this->result->reject($exception);
} catch (Throwable $throwable) {
$this->result->reject($throwable);
}
@ -78,10 +77,8 @@ final class Coroutine implements PromiseInterface
/**
* Create a new coroutine.
*
* @return self
*/
public static function of(callable $generatorFn)
public static function of(callable $generatorFn): self
{
return new self($generatorFn);
}
@ -89,42 +86,42 @@ final class Coroutine implements PromiseInterface
public function then(
callable $onFulfilled = null,
callable $onRejected = null
) {
): PromiseInterface {
return $this->result->then($onFulfilled, $onRejected);
}
public function otherwise(callable $onRejected)
public function otherwise(callable $onRejected): PromiseInterface
{
return $this->result->otherwise($onRejected);
}
public function wait($unwrap = true)
public function wait(bool $unwrap = true)
{
return $this->result->wait($unwrap);
}
public function getState()
public function getState(): string
{
return $this->result->getState();
}
public function resolve($value)
public function resolve($value): void
{
$this->result->resolve($value);
}
public function reject($reason)
public function reject($reason): void
{
$this->result->reject($reason);
}
public function cancel()
public function cancel(): void
{
$this->currentPromise->cancel();
$this->result->cancel();
}
private function nextCoroutine($yielded)
private function nextCoroutine($yielded): void
{
$this->currentPromise = Create::promiseFor($yielded)
->then([$this, '_handleSuccess'], [$this, '_handleFailure']);
@ -133,7 +130,7 @@ final class Coroutine implements PromiseInterface
/**
* @internal
*/
public function _handleSuccess($value)
public function _handleSuccess($value): void
{
unset($this->currentPromise);
try {
@ -143,8 +140,6 @@ final class Coroutine implements PromiseInterface
} else {
$this->result->resolve($value);
}
} catch (Exception $exception) {
$this->result->reject($exception);
} catch (Throwable $throwable) {
$this->result->reject($throwable);
}
@ -153,15 +148,13 @@ final class Coroutine implements PromiseInterface
/**
* @internal
*/
public function _handleFailure($reason)
public function _handleFailure($reason): void
{
unset($this->currentPromise);
try {
$nextYield = $this->generator->throw(Create::exceptionFor($reason));
// The throw was caught, so keep iterating on the coroutine
$this->nextCoroutine($nextYield);
} catch (Exception $exception) {
$this->result->reject($exception);
} catch (Throwable $throwable) {
$this->result->reject($throwable);
}

View File

@ -1,5 +1,7 @@
<?php
declare(strict_types=1);
namespace GuzzleHttp\Promise;
final class Create
@ -8,10 +10,8 @@ final class Create
* Creates a promise for a value if the value is not a promise.
*
* @param mixed $value Promise or value.
*
* @return PromiseInterface
*/
public static function promiseFor($value)
public static function promiseFor($value): PromiseInterface
{
if ($value instanceof PromiseInterface) {
return $value;
@ -23,6 +23,7 @@ final class Create
$cfn = method_exists($value, 'cancel') ? [$value, 'cancel'] : null;
$promise = new Promise($wfn, $cfn);
$value->then([$promise, 'resolve'], [$promise, 'reject']);
return $promise;
}
@ -34,10 +35,8 @@ final class Create
* If the provided reason is a promise, then it is returned as-is.
*
* @param mixed $reason Promise or reason.
*
* @return PromiseInterface
*/
public static function rejectionFor($reason)
public static function rejectionFor($reason): PromiseInterface
{
if ($reason instanceof PromiseInterface) {
return $reason;
@ -50,12 +49,10 @@ final class Create
* Create an exception for a rejected promise value.
*
* @param mixed $reason
*
* @return \Exception|\Throwable
*/
public static function exceptionFor($reason)
public static function exceptionFor($reason): \Throwable
{
if ($reason instanceof \Exception || $reason instanceof \Throwable) {
if ($reason instanceof \Throwable) {
return $reason;
}
@ -66,10 +63,8 @@ final class Create
* Returns an iterator for the given value.
*
* @param mixed $value
*
* @return \Iterator
*/
public static function iterFor($value)
public static function iterFor($value): \Iterator
{
if ($value instanceof \Iterator) {
return $value;

View File

@ -1,5 +1,7 @@
<?php
declare(strict_types=1);
namespace GuzzleHttp\Promise;
final class Each
@ -20,17 +22,15 @@ final class Each
* @param mixed $iterable Iterator or array to iterate over.
* @param callable $onFulfilled
* @param callable $onRejected
*
* @return PromiseInterface
*/
public static function of(
$iterable,
callable $onFulfilled = null,
callable $onRejected = null
) {
): PromiseInterface {
return (new EachPromise($iterable, [
'fulfilled' => $onFulfilled,
'rejected' => $onRejected
'rejected' => $onRejected,
]))->promise();
}
@ -46,19 +46,17 @@ final class Each
* @param int|callable $concurrency
* @param callable $onFulfilled
* @param callable $onRejected
*
* @return PromiseInterface
*/
public static function ofLimit(
$iterable,
$concurrency,
callable $onFulfilled = null,
callable $onRejected = null
) {
): PromiseInterface {
return (new EachPromise($iterable, [
'fulfilled' => $onFulfilled,
'rejected' => $onRejected,
'concurrency' => $concurrency
'fulfilled' => $onFulfilled,
'rejected' => $onRejected,
'concurrency' => $concurrency,
]))->promise();
}
@ -70,19 +68,17 @@ final class Each
* @param mixed $iterable
* @param int|callable $concurrency
* @param callable $onFulfilled
*
* @return PromiseInterface
*/
public static function ofLimitAll(
$iterable,
$concurrency,
callable $onFulfilled = null
) {
): PromiseInterface {
return self::ofLimit(
$iterable,
$concurrency,
$onFulfilled,
function ($reason, $idx, PromiseInterface $aggregate) {
function ($reason, $idx, PromiseInterface $aggregate): void {
$aggregate->reject($reason);
}
);

View File

@ -1,10 +1,14 @@
<?php
declare(strict_types=1);
namespace GuzzleHttp\Promise;
/**
* Represents a promise that iterates over many promises and invokes
* side-effect functions in the process.
*
* @final
*/
class EachPromise implements PromisorInterface
{
@ -69,7 +73,7 @@ class EachPromise implements PromisorInterface
}
/** @psalm-suppress InvalidNullableReturnType */
public function promise()
public function promise(): PromiseInterface
{
if ($this->aggregate) {
return $this->aggregate;
@ -82,21 +86,18 @@ class EachPromise implements PromisorInterface
$this->refillPending();
} catch (\Throwable $e) {
$this->aggregate->reject($e);
} catch (\Exception $e) {
$this->aggregate->reject($e);
}
/**
* @psalm-suppress NullableReturnStatement
* @phpstan-ignore-next-line
*/
return $this->aggregate;
}
private function createPromise()
private function createPromise(): void
{
$this->mutex = false;
$this->aggregate = new Promise(function () {
$this->aggregate = new Promise(function (): void {
if ($this->checkIfFinished()) {
return;
}
@ -113,7 +114,7 @@ class EachPromise implements PromisorInterface
});
// Clear the references when the promise is resolved.
$clearFn = function () {
$clearFn = function (): void {
$this->iterable = $this->concurrency = $this->pending = null;
$this->onFulfilled = $this->onRejected = null;
$this->nextPendingIndex = 0;
@ -122,11 +123,13 @@ class EachPromise implements PromisorInterface
$this->aggregate->then($clearFn, $clearFn);
}
private function refillPending()
private function refillPending(): void
{
if (!$this->concurrency) {
// Add all pending promises.
while ($this->addPending() && $this->advanceIterator());
while ($this->addPending() && $this->advanceIterator()) {
}
return;
}
@ -147,10 +150,11 @@ class EachPromise implements PromisorInterface
// next value to yield until promise callbacks are called.
while (--$concurrency
&& $this->advanceIterator()
&& $this->addPending());
&& $this->addPending()) {
}
}
private function addPending()
private function addPending(): bool
{
if (!$this->iterable || !$this->iterable->valid()) {
return false;
@ -164,7 +168,7 @@ class EachPromise implements PromisorInterface
$idx = $this->nextPendingIndex++;
$this->pending[$idx] = $promise->then(
function ($value) use ($idx, $key) {
function ($value) use ($idx, $key): void {
if ($this->onFulfilled) {
call_user_func(
$this->onFulfilled,
@ -175,7 +179,7 @@ class EachPromise implements PromisorInterface
}
$this->step($idx);
},
function ($reason) use ($idx, $key) {
function ($reason) use ($idx, $key): void {
if ($this->onRejected) {
call_user_func(
$this->onRejected,
@ -191,7 +195,7 @@ class EachPromise implements PromisorInterface
return true;
}
private function advanceIterator()
private function advanceIterator(): bool
{
// Place a lock on the iterator so that we ensure to not recurse,
// preventing fatal generator errors.
@ -204,19 +208,17 @@ class EachPromise implements PromisorInterface
try {
$this->iterable->next();
$this->mutex = false;
return true;
} catch (\Throwable $e) {
$this->aggregate->reject($e);
$this->mutex = false;
return false;
} catch (\Exception $e) {
$this->aggregate->reject($e);
$this->mutex = false;
return false;
}
}
private function step($idx)
private function step(int $idx): void
{
// If the promise was already resolved, then ignore this step.
if (Is::settled($this->aggregate)) {
@ -234,11 +236,12 @@ class EachPromise implements PromisorInterface
}
}
private function checkIfFinished()
private function checkIfFinished(): bool
{
if (!$this->pending && !$this->iterable->valid()) {
// Resolve the promise if there's nothing left to do.
$this->aggregate->resolve(null);
return true;
}

View File

@ -1,5 +1,7 @@
<?php
declare(strict_types=1);
namespace GuzzleHttp\Promise;
/**
@ -7,11 +9,16 @@ namespace GuzzleHttp\Promise;
*
* Thenning off of this promise will invoke the onFulfilled callback
* immediately and ignore other callbacks.
*
* @final
*/
class FulfilledPromise implements PromiseInterface
{
private $value;
/**
* @param mixed $value
*/
public function __construct($value)
{
if (is_object($value) && method_exists($value, 'then')) {
@ -26,7 +33,7 @@ class FulfilledPromise implements PromiseInterface
public function then(
callable $onFulfilled = null,
callable $onRejected = null
) {
): PromiseInterface {
// Return itself if there is no onFulfilled function.
if (!$onFulfilled) {
return $this;
@ -35,14 +42,12 @@ class FulfilledPromise implements PromiseInterface
$queue = Utils::queue();
$p = new Promise([$queue, 'run']);
$value = $this->value;
$queue->add(static function () use ($p, $value, $onFulfilled) {
$queue->add(static function () use ($p, $value, $onFulfilled): void {
if (Is::pending($p)) {
try {
$p->resolve($onFulfilled($value));
} catch (\Throwable $e) {
$p->reject($e);
} catch (\Exception $e) {
$p->reject($e);
}
}
});
@ -50,34 +55,34 @@ class FulfilledPromise implements PromiseInterface
return $p;
}
public function otherwise(callable $onRejected)
public function otherwise(callable $onRejected): PromiseInterface
{
return $this->then(null, $onRejected);
}
public function wait($unwrap = true, $defaultDelivery = null)
public function wait(bool $unwrap = true)
{
return $unwrap ? $this->value : null;
}
public function getState()
public function getState(): string
{
return self::FULFILLED;
}
public function resolve($value)
public function resolve($value): void
{
if ($value !== $this->value) {
throw new \LogicException("Cannot resolve a fulfilled promise");
throw new \LogicException('Cannot resolve a fulfilled promise');
}
}
public function reject($reason)
public function reject($reason): void
{
throw new \LogicException("Cannot reject a fulfilled promise");
throw new \LogicException('Cannot reject a fulfilled promise');
}
public function cancel()
public function cancel(): void
{
// pass
}

View File

@ -1,45 +1,39 @@
<?php
declare(strict_types=1);
namespace GuzzleHttp\Promise;
final class Is
{
/**
* Returns true if a promise is pending.
*
* @return bool
*/
public static function pending(PromiseInterface $promise)
public static function pending(PromiseInterface $promise): bool
{
return $promise->getState() === PromiseInterface::PENDING;
}
/**
* Returns true if a promise is fulfilled or rejected.
*
* @return bool
*/
public static function settled(PromiseInterface $promise)
public static function settled(PromiseInterface $promise): bool
{
return $promise->getState() !== PromiseInterface::PENDING;
}
/**
* Returns true if a promise is fulfilled.
*
* @return bool
*/
public static function fulfilled(PromiseInterface $promise)
public static function fulfilled(PromiseInterface $promise): bool
{
return $promise->getState() === PromiseInterface::FULFILLED;
}
/**
* Returns true if a promise is rejected.
*
* @return bool
*/
public static function rejected(PromiseInterface $promise)
public static function rejected(PromiseInterface $promise): bool
{
return $promise->getState() === PromiseInterface::REJECTED;
}

View File

@ -1,11 +1,15 @@
<?php
declare(strict_types=1);
namespace GuzzleHttp\Promise;
/**
* Promises/A+ implementation that avoids recursion when possible.
*
* @link https://promisesaplus.com/
* @see https://promisesaplus.com/
*
* @final
*/
class Promise implements PromiseInterface
{
@ -31,33 +35,36 @@ class Promise implements PromiseInterface
public function then(
callable $onFulfilled = null,
callable $onRejected = null
) {
): PromiseInterface {
if ($this->state === self::PENDING) {
$p = new Promise(null, [$this, 'cancel']);
$this->handlers[] = [$p, $onFulfilled, $onRejected];
$p->waitList = $this->waitList;
$p->waitList[] = $this;
return $p;
}
// Return a fulfilled promise and immediately invoke any callbacks.
if ($this->state === self::FULFILLED) {
$promise = Create::promiseFor($this->result);
return $onFulfilled ? $promise->then($onFulfilled) : $promise;
}
// It's either cancelled or rejected, so return a rejected promise
// and immediately invoke any callbacks.
$rejection = Create::rejectionFor($this->result);
return $onRejected ? $rejection->then(null, $onRejected) : $rejection;
}
public function otherwise(callable $onRejected)
public function otherwise(callable $onRejected): PromiseInterface
{
return $this->then(null, $onRejected);
}
public function wait($unwrap = true)
public function wait(bool $unwrap = true)
{
$this->waitIfPending();
@ -73,12 +80,12 @@ class Promise implements PromiseInterface
}
}
public function getState()
public function getState(): string
{
return $this->state;
}
public function cancel()
public function cancel(): void
{
if ($this->state !== self::PENDING) {
return;
@ -93,8 +100,6 @@ class Promise implements PromiseInterface
$fn();
} catch (\Throwable $e) {
$this->reject($e);
} catch (\Exception $e) {
$this->reject($e);
}
}
@ -105,17 +110,17 @@ class Promise implements PromiseInterface
}
}
public function resolve($value)
public function resolve($value): void
{
$this->settle(self::FULFILLED, $value);
}
public function reject($reason)
public function reject($reason): void
{
$this->settle(self::REJECTED, $reason);
}
private function settle($state, $value)
private function settle(string $state, $value): void
{
if ($this->state !== self::PENDING) {
// Ignore calls with the same resolution.
@ -148,7 +153,7 @@ class Promise implements PromiseInterface
if (!is_object($value) || !method_exists($value, 'then')) {
$id = $state === self::FULFILLED ? 1 : 2;
// It's a success, so resolve the handlers in the queue.
Utils::queue()->add(static function () use ($id, $value, $handlers) {
Utils::queue()->add(static function () use ($id, $value, $handlers): void {
foreach ($handlers as $handler) {
self::callHandler($id, $value, $handler);
}
@ -159,12 +164,12 @@ class Promise implements PromiseInterface
} else {
// Resolve the handlers when the forwarded promise is resolved.
$value->then(
static function ($value) use ($handlers) {
static function ($value) use ($handlers): void {
foreach ($handlers as $handler) {
self::callHandler(1, $value, $handler);
}
},
static function ($reason) use ($handlers) {
static function ($reason) use ($handlers): void {
foreach ($handlers as $handler) {
self::callHandler(2, $reason, $handler);
}
@ -180,7 +185,7 @@ class Promise implements PromiseInterface
* @param mixed $value Value to pass to the callback.
* @param array $handler Array of handler data (promise and callbacks).
*/
private static function callHandler($index, $value, array $handler)
private static function callHandler(int $index, $value, array $handler): void
{
/** @var PromiseInterface $promise */
$promise = $handler[0];
@ -211,12 +216,10 @@ class Promise implements PromiseInterface
}
} catch (\Throwable $reason) {
$promise->reject($reason);
} catch (\Exception $reason) {
$promise->reject($reason);
}
}
private function waitIfPending()
private function waitIfPending(): void
{
if ($this->state !== self::PENDING) {
return;
@ -227,9 +230,9 @@ class Promise implements PromiseInterface
} else {
// If there's no wait function, then reject the promise.
$this->reject('Cannot wait on a promise that has '
. 'no internal wait function. You must provide a wait '
. 'function when constructing the promise to be able to '
. 'wait on a promise.');
.'no internal wait function. You must provide a wait '
.'function when constructing the promise to be able to '
.'wait on a promise.');
}
Utils::queue()->run();
@ -240,13 +243,13 @@ class Promise implements PromiseInterface
}
}
private function invokeWaitFn()
private function invokeWaitFn(): void
{
try {
$wfn = $this->waitFn;
$this->waitFn = null;
$wfn(true);
} catch (\Exception $reason) {
} catch (\Throwable $reason) {
if ($this->state === self::PENDING) {
// The promise has not been resolved yet, so reject the promise
// with the exception.
@ -259,7 +262,7 @@ class Promise implements PromiseInterface
}
}
private function invokeWaitList()
private function invokeWaitList(): void
{
$waitList = $this->waitList;
$this->waitList = null;

View File

@ -1,5 +1,7 @@
<?php
declare(strict_types=1);
namespace GuzzleHttp\Promise;
/**
@ -9,13 +11,13 @@ namespace GuzzleHttp\Promise;
* which registers callbacks to receive either a promises eventual value or
* the reason why the promise cannot be fulfilled.
*
* @link https://promisesaplus.com/
* @see https://promisesaplus.com/
*/
interface PromiseInterface
{
const PENDING = 'pending';
const FULFILLED = 'fulfilled';
const REJECTED = 'rejected';
public const PENDING = 'pending';
public const FULFILLED = 'fulfilled';
public const REJECTED = 'rejected';
/**
* Appends fulfillment and rejection handlers to the promise, and returns
@ -23,13 +25,11 @@ interface PromiseInterface
*
* @param callable $onFulfilled Invoked when the promise fulfills.
* @param callable $onRejected Invoked when the promise is rejected.
*
* @return PromiseInterface
*/
public function then(
callable $onFulfilled = null,
callable $onRejected = null
);
): PromiseInterface;
/**
* Appends a rejection handler callback to the promise, and returns a new
@ -38,20 +38,16 @@ interface PromiseInterface
* fulfilled.
*
* @param callable $onRejected Invoked when the promise is rejected.
*
* @return PromiseInterface
*/
public function otherwise(callable $onRejected);
public function otherwise(callable $onRejected): PromiseInterface;
/**
* Get the state of the promise ("pending", "rejected", or "fulfilled").
*
* The three states can be checked against the constants defined on
* PromiseInterface: PENDING, FULFILLED, and REJECTED.
*
* @return string
*/
public function getState();
public function getState(): string;
/**
* Resolve the promise with the given value.
@ -60,7 +56,7 @@ interface PromiseInterface
*
* @throws \RuntimeException if the promise is already resolved.
*/
public function resolve($value);
public function resolve($value): void;
/**
* Reject the promise with the given reason.
@ -69,14 +65,14 @@ interface PromiseInterface
*
* @throws \RuntimeException if the promise is already resolved.
*/
public function reject($reason);
public function reject($reason): void;
/**
* Cancels the promise if possible.
*
* @link https://github.com/promises-aplus/cancellation-spec/issues/7
* @see https://github.com/promises-aplus/cancellation-spec/issues/7
*/
public function cancel();
public function cancel(): void;
/**
* Waits until the promise completes if possible.
@ -86,12 +82,10 @@ interface PromiseInterface
*
* If the promise cannot be waited on, then the promise will be rejected.
*
* @param bool $unwrap
*
* @return mixed
*
* @throws \LogicException if the promise has no wait function or if the
* promise does not settle after waiting.
*/
public function wait($unwrap = true);
public function wait(bool $unwrap = true);
}

View File

@ -1,5 +1,7 @@
<?php
declare(strict_types=1);
namespace GuzzleHttp\Promise;
/**
@ -9,8 +11,6 @@ interface PromisorInterface
{
/**
* Returns a promise.
*
* @return PromiseInterface
*/
public function promise();
public function promise(): PromiseInterface;
}

View File

@ -1,5 +1,7 @@
<?php
declare(strict_types=1);
namespace GuzzleHttp\Promise;
/**
@ -7,11 +9,16 @@ namespace GuzzleHttp\Promise;
*
* Thenning off of this promise will invoke the onRejected callback
* immediately and ignore other callbacks.
*
* @final
*/
class RejectedPromise implements PromiseInterface
{
private $reason;
/**
* @param mixed $reason
*/
public function __construct($reason)
{
if (is_object($reason) && method_exists($reason, 'then')) {
@ -26,7 +33,7 @@ class RejectedPromise implements PromiseInterface
public function then(
callable $onFulfilled = null,
callable $onRejected = null
) {
): PromiseInterface {
// If there's no onRejected callback then just return self.
if (!$onRejected) {
return $this;
@ -35,7 +42,7 @@ class RejectedPromise implements PromiseInterface
$queue = Utils::queue();
$reason = $this->reason;
$p = new Promise([$queue, 'run']);
$queue->add(static function () use ($p, $reason, $onRejected) {
$queue->add(static function () use ($p, $reason, $onRejected): void {
if (Is::pending($p)) {
try {
// Return a resolved promise if onRejected does not throw.
@ -43,9 +50,6 @@ class RejectedPromise implements PromiseInterface
} catch (\Throwable $e) {
// onRejected threw, so return a rejected promise.
$p->reject($e);
} catch (\Exception $e) {
// onRejected threw, so return a rejected promise.
$p->reject($e);
}
}
});
@ -53,12 +57,12 @@ class RejectedPromise implements PromiseInterface
return $p;
}
public function otherwise(callable $onRejected)
public function otherwise(callable $onRejected): PromiseInterface
{
return $this->then(null, $onRejected);
}
public function wait($unwrap = true, $defaultDelivery = null)
public function wait(bool $unwrap = true)
{
if ($unwrap) {
throw Create::exceptionFor($this->reason);
@ -67,24 +71,24 @@ class RejectedPromise implements PromiseInterface
return null;
}
public function getState()
public function getState(): string
{
return self::REJECTED;
}
public function resolve($value)
public function resolve($value): void
{
throw new \LogicException("Cannot resolve a rejected promise");
throw new \LogicException('Cannot resolve a rejected promise');
}
public function reject($reason)
public function reject($reason): void
{
if ($reason !== $this->reason) {
throw new \LogicException("Cannot reject a rejected promise");
throw new \LogicException('Cannot reject a rejected promise');
}
}
public function cancel()
public function cancel(): void
{
// pass
}

View File

@ -1,5 +1,7 @@
<?php
declare(strict_types=1);
namespace GuzzleHttp\Promise;
/**
@ -13,24 +15,23 @@ class RejectionException extends \RuntimeException
private $reason;
/**
* @param mixed $reason Rejection reason.
* @param string $description Optional description
* @param mixed $reason Rejection reason.
* @param string|null $description Optional description.
*/
public function __construct($reason, $description = null)
public function __construct($reason, ?string $description = null)
{
$this->reason = $reason;
$message = 'The promise was rejected';
if ($description) {
$message .= ' with reason: ' . $description;
$message .= ' with reason: '.$description;
} elseif (is_string($reason)
|| (is_object($reason) && method_exists($reason, '__toString'))
) {
$message .= ' with reason: ' . $this->reason;
$message .= ' with reason: '.$this->reason;
} elseif ($reason instanceof \JsonSerializable) {
$message .= ' with reason: '
. json_encode($this->reason, JSON_PRETTY_PRINT);
$message .= ' with reason: '.json_encode($this->reason, JSON_PRETTY_PRINT);
}
parent::__construct($message);

View File

@ -1,5 +1,7 @@
<?php
declare(strict_types=1);
namespace GuzzleHttp\Promise;
/**
@ -10,16 +12,18 @@ namespace GuzzleHttp\Promise;
* by calling the `run()` function of the global task queue in an event loop.
*
* GuzzleHttp\Promise\Utils::queue()->run();
*
* @final
*/
class TaskQueue implements TaskQueueInterface
{
private $enableShutdown = true;
private $queue = [];
public function __construct($withShutdown = true)
public function __construct(bool $withShutdown = true)
{
if ($withShutdown) {
register_shutdown_function(function () {
register_shutdown_function(function (): void {
if ($this->enableShutdown) {
// Only run the tasks if an E_ERROR didn't occur.
$err = error_get_last();
@ -31,17 +35,17 @@ class TaskQueue implements TaskQueueInterface
}
}
public function isEmpty()
public function isEmpty(): bool
{
return !$this->queue;
}
public function add(callable $task)
public function add(callable $task): void
{
$this->queue[] = $task;
}
public function run()
public function run(): void
{
while ($task = array_shift($this->queue)) {
/** @var callable $task */
@ -60,7 +64,7 @@ class TaskQueue implements TaskQueueInterface
*
* Note: This shutdown will occur before any destructors are triggered.
*/
public function disableShutdown()
public function disableShutdown(): void
{
$this->enableShutdown = false;
}

View File

@ -1,24 +1,24 @@
<?php
declare(strict_types=1);
namespace GuzzleHttp\Promise;
interface TaskQueueInterface
{
/**
* Returns true if the queue is empty.
*
* @return bool
*/
public function isEmpty();
public function isEmpty(): bool;
/**
* Adds a task to the queue that will be executed the next time run is
* called.
*/
public function add(callable $task);
public function add(callable $task): void;
/**
* Execute all of the pending task in the queue.
*/
public function run();
public function run(): void;
}

View File

@ -1,5 +1,7 @@
<?php
declare(strict_types=1);
namespace GuzzleHttp\Promise;
final class Utils
@ -17,11 +19,9 @@ final class Utils
* }
* </code>
*
* @param TaskQueueInterface $assign Optionally specify a new queue instance.
*
* @return TaskQueueInterface
* @param TaskQueueInterface|null $assign Optionally specify a new queue instance.
*/
public static function queue(TaskQueueInterface $assign = null)
public static function queue(TaskQueueInterface $assign = null): TaskQueueInterface
{
static $queue;
@ -39,22 +39,18 @@ final class Utils
* returns a promise that is fulfilled or rejected with the result.
*
* @param callable $task Task function to run.
*
* @return PromiseInterface
*/
public static function task(callable $task)
public static function task(callable $task): PromiseInterface
{
$queue = self::queue();
$promise = new Promise([$queue, 'run']);
$queue->add(function () use ($task, $promise) {
$queue->add(function () use ($task, $promise): void {
try {
if (Is::pending($promise)) {
$promise->resolve($task());
}
} catch (\Throwable $e) {
$promise->reject($e);
} catch (\Exception $e) {
$promise->reject($e);
}
});
@ -72,22 +68,18 @@ final class Utils
* key mapping to the rejection reason of the promise.
*
* @param PromiseInterface $promise Promise or value.
*
* @return array
*/
public static function inspect(PromiseInterface $promise)
public static function inspect(PromiseInterface $promise): array
{
try {
return [
'state' => PromiseInterface::FULFILLED,
'value' => $promise->wait()
'value' => $promise->wait(),
];
} catch (RejectionException $e) {
return ['state' => PromiseInterface::REJECTED, 'reason' => $e->getReason()];
} catch (\Throwable $e) {
return ['state' => PromiseInterface::REJECTED, 'reason' => $e];
} catch (\Exception $e) {
return ['state' => PromiseInterface::REJECTED, 'reason' => $e];
}
}
@ -100,10 +92,8 @@ final class Utils
* @see inspect for the inspection state array format.
*
* @param PromiseInterface[] $promises Traversable of promises to wait upon.
*
* @return array
*/
public static function inspectAll($promises)
public static function inspectAll($promises): array
{
$results = [];
foreach ($promises as $key => $promise) {
@ -122,12 +112,9 @@ final class Utils
*
* @param iterable<PromiseInterface> $promises Iterable of PromiseInterface objects to wait on.
*
* @return array
*
* @throws \Exception on error
* @throws \Throwable on error in PHP >=7
* @throws \Throwable on error
*/
public static function unwrap($promises)
public static function unwrap($promises): array
{
$results = [];
foreach ($promises as $key => $promise) {
@ -147,22 +134,21 @@ final class Utils
*
* @param mixed $promises Promises or values.
* @param bool $recursive If true, resolves new promises that might have been added to the stack during its own resolution.
*
* @return PromiseInterface
*/
public static function all($promises, $recursive = false)
public static function all($promises, bool $recursive = false): PromiseInterface
{
$results = [];
$promise = Each::of(
$promises,
function ($value, $idx) use (&$results) {
function ($value, $idx) use (&$results): void {
$results[$idx] = $value;
},
function ($reason, $idx, Promise $aggregate) {
function ($reason, $idx, Promise $aggregate): void {
$aggregate->reject($reason);
}
)->then(function () use (&$results) {
ksort($results);
return $results;
});
@ -173,6 +159,7 @@ final class Utils
return self::all($promises, $recursive);
}
}
return $results;
});
}
@ -193,17 +180,15 @@ final class Utils
*
* @param int $count Total number of promises.
* @param mixed $promises Promises or values.
*
* @return PromiseInterface
*/
public static function some($count, $promises)
public static function some(int $count, $promises): PromiseInterface
{
$results = [];
$rejections = [];
return Each::of(
$promises,
function ($value, $idx, PromiseInterface $p) use (&$results, $count) {
function ($value, $idx, PromiseInterface $p) use (&$results, $count): void {
if (Is::settled($p)) {
return;
}
@ -212,7 +197,7 @@ final class Utils
$p->resolve(null);
}
},
function ($reason) use (&$rejections) {
function ($reason) use (&$rejections): void {
$rejections[] = $reason;
}
)->then(
@ -224,6 +209,7 @@ final class Utils
);
}
ksort($results);
return array_values($results);
}
);
@ -234,10 +220,8 @@ final class Utils
* fulfillment value is not an array of 1 but the value directly.
*
* @param mixed $promises Promises or values.
*
* @return PromiseInterface
*/
public static function any($promises)
public static function any($promises): PromiseInterface
{
return self::some(1, $promises)->then(function ($values) {
return $values[0];
@ -253,23 +237,22 @@ final class Utils
* @see inspect for the inspection state array format.
*
* @param mixed $promises Promises or values.
*
* @return PromiseInterface
*/
public static function settle($promises)
public static function settle($promises): PromiseInterface
{
$results = [];
return Each::of(
$promises,
function ($value, $idx) use (&$results) {
function ($value, $idx) use (&$results): void {
$results[$idx] = ['state' => PromiseInterface::FULFILLED, 'value' => $value];
},
function ($reason, $idx) use (&$results) {
function ($reason, $idx) use (&$results): void {
$results[$idx] = ['state' => PromiseInterface::REJECTED, 'reason' => $reason];
}
)->then(function () use (&$results) {
ksort($results);
return $results;
});
}

View File

@ -1,363 +0,0 @@
<?php
namespace GuzzleHttp\Promise;
/**
* Get the global task queue used for promise resolution.
*
* This task queue MUST be run in an event loop in order for promises to be
* settled asynchronously. It will be automatically run when synchronously
* waiting on a promise.
*
* <code>
* while ($eventLoop->isRunning()) {
* GuzzleHttp\Promise\queue()->run();
* }
* </code>
*
* @param TaskQueueInterface $assign Optionally specify a new queue instance.
*
* @return TaskQueueInterface
*
* @deprecated queue will be removed in guzzlehttp/promises:2.0. Use Utils::queue instead.
*/
function queue(TaskQueueInterface $assign = null)
{
return Utils::queue($assign);
}
/**
* Adds a function to run in the task queue when it is next `run()` and returns
* a promise that is fulfilled or rejected with the result.
*
* @param callable $task Task function to run.
*
* @return PromiseInterface
*
* @deprecated task will be removed in guzzlehttp/promises:2.0. Use Utils::task instead.
*/
function task(callable $task)
{
return Utils::task($task);
}
/**
* Creates a promise for a value if the value is not a promise.
*
* @param mixed $value Promise or value.
*
* @return PromiseInterface
*
* @deprecated promise_for will be removed in guzzlehttp/promises:2.0. Use Create::promiseFor instead.
*/
function promise_for($value)
{
return Create::promiseFor($value);
}
/**
* Creates a rejected promise for a reason if the reason is not a promise. If
* the provided reason is a promise, then it is returned as-is.
*
* @param mixed $reason Promise or reason.
*
* @return PromiseInterface
*
* @deprecated rejection_for will be removed in guzzlehttp/promises:2.0. Use Create::rejectionFor instead.
*/
function rejection_for($reason)
{
return Create::rejectionFor($reason);
}
/**
* Create an exception for a rejected promise value.
*
* @param mixed $reason
*
* @return \Exception|\Throwable
*
* @deprecated exception_for will be removed in guzzlehttp/promises:2.0. Use Create::exceptionFor instead.
*/
function exception_for($reason)
{
return Create::exceptionFor($reason);
}
/**
* Returns an iterator for the given value.
*
* @param mixed $value
*
* @return \Iterator
*
* @deprecated iter_for will be removed in guzzlehttp/promises:2.0. Use Create::iterFor instead.
*/
function iter_for($value)
{
return Create::iterFor($value);
}
/**
* Synchronously waits on a promise to resolve and returns an inspection state
* array.
*
* Returns a state associative array containing a "state" key mapping to a
* valid promise state. If the state of the promise is "fulfilled", the array
* will contain a "value" key mapping to the fulfilled value of the promise. If
* the promise is rejected, the array will contain a "reason" key mapping to
* the rejection reason of the promise.
*
* @param PromiseInterface $promise Promise or value.
*
* @return array
*
* @deprecated inspect will be removed in guzzlehttp/promises:2.0. Use Utils::inspect instead.
*/
function inspect(PromiseInterface $promise)
{
return Utils::inspect($promise);
}
/**
* Waits on all of the provided promises, but does not unwrap rejected promises
* as thrown exception.
*
* Returns an array of inspection state arrays.
*
* @see inspect for the inspection state array format.
*
* @param PromiseInterface[] $promises Traversable of promises to wait upon.
*
* @return array
*
* @deprecated inspect will be removed in guzzlehttp/promises:2.0. Use Utils::inspectAll instead.
*/
function inspect_all($promises)
{
return Utils::inspectAll($promises);
}
/**
* Waits on all of the provided promises and returns the fulfilled values.
*
* Returns an array that contains the value of each promise (in the same order
* the promises were provided). An exception is thrown if any of the promises
* are rejected.
*
* @param iterable<PromiseInterface> $promises Iterable of PromiseInterface objects to wait on.
*
* @return array
*
* @throws \Exception on error
* @throws \Throwable on error in PHP >=7
*
* @deprecated unwrap will be removed in guzzlehttp/promises:2.0. Use Utils::unwrap instead.
*/
function unwrap($promises)
{
return Utils::unwrap($promises);
}
/**
* Given an array of promises, return a promise that is fulfilled when all the
* items in the array are fulfilled.
*
* The promise's fulfillment value is an array with fulfillment values at
* respective positions to the original array. If any promise in the array
* rejects, the returned promise is rejected with the rejection reason.
*
* @param mixed $promises Promises or values.
* @param bool $recursive If true, resolves new promises that might have been added to the stack during its own resolution.
*
* @return PromiseInterface
*
* @deprecated all will be removed in guzzlehttp/promises:2.0. Use Utils::all instead.
*/
function all($promises, $recursive = false)
{
return Utils::all($promises, $recursive);
}
/**
* Initiate a competitive race between multiple promises or values (values will
* become immediately fulfilled promises).
*
* When count amount of promises have been fulfilled, the returned promise is
* fulfilled with an array that contains the fulfillment values of the winners
* in order of resolution.
*
* This promise is rejected with a {@see AggregateException} if the number of
* fulfilled promises is less than the desired $count.
*
* @param int $count Total number of promises.
* @param mixed $promises Promises or values.
*
* @return PromiseInterface
*
* @deprecated some will be removed in guzzlehttp/promises:2.0. Use Utils::some instead.
*/
function some($count, $promises)
{
return Utils::some($count, $promises);
}
/**
* Like some(), with 1 as count. However, if the promise fulfills, the
* fulfillment value is not an array of 1 but the value directly.
*
* @param mixed $promises Promises or values.
*
* @return PromiseInterface
*
* @deprecated any will be removed in guzzlehttp/promises:2.0. Use Utils::any instead.
*/
function any($promises)
{
return Utils::any($promises);
}
/**
* Returns a promise that is fulfilled when all of the provided promises have
* been fulfilled or rejected.
*
* The returned promise is fulfilled with an array of inspection state arrays.
*
* @see inspect for the inspection state array format.
*
* @param mixed $promises Promises or values.
*
* @return PromiseInterface
*
* @deprecated settle will be removed in guzzlehttp/promises:2.0. Use Utils::settle instead.
*/
function settle($promises)
{
return Utils::settle($promises);
}
/**
* Given an iterator that yields promises or values, returns a promise that is
* fulfilled with a null value when the iterator has been consumed or the
* aggregate promise has been fulfilled or rejected.
*
* $onFulfilled is a function that accepts the fulfilled value, iterator index,
* and the aggregate promise. The callback can invoke any necessary side
* effects and choose to resolve or reject the aggregate if needed.
*
* $onRejected is a function that accepts the rejection reason, iterator index,
* and the aggregate promise. The callback can invoke any necessary side
* effects and choose to resolve or reject the aggregate if needed.
*
* @param mixed $iterable Iterator or array to iterate over.
* @param callable $onFulfilled
* @param callable $onRejected
*
* @return PromiseInterface
*
* @deprecated each will be removed in guzzlehttp/promises:2.0. Use Each::of instead.
*/
function each(
$iterable,
callable $onFulfilled = null,
callable $onRejected = null
) {
return Each::of($iterable, $onFulfilled, $onRejected);
}
/**
* Like each, but only allows a certain number of outstanding promises at any
* given time.
*
* $concurrency may be an integer or a function that accepts the number of
* pending promises and returns a numeric concurrency limit value to allow for
* dynamic a concurrency size.
*
* @param mixed $iterable
* @param int|callable $concurrency
* @param callable $onFulfilled
* @param callable $onRejected
*
* @return PromiseInterface
*
* @deprecated each_limit will be removed in guzzlehttp/promises:2.0. Use Each::ofLimit instead.
*/
function each_limit(
$iterable,
$concurrency,
callable $onFulfilled = null,
callable $onRejected = null
) {
return Each::ofLimit($iterable, $concurrency, $onFulfilled, $onRejected);
}
/**
* Like each_limit, but ensures that no promise in the given $iterable argument
* is rejected. If any promise is rejected, then the aggregate promise is
* rejected with the encountered rejection.
*
* @param mixed $iterable
* @param int|callable $concurrency
* @param callable $onFulfilled
*
* @return PromiseInterface
*
* @deprecated each_limit_all will be removed in guzzlehttp/promises:2.0. Use Each::ofLimitAll instead.
*/
function each_limit_all(
$iterable,
$concurrency,
callable $onFulfilled = null
) {
return Each::ofLimitAll($iterable, $concurrency, $onFulfilled);
}
/**
* Returns true if a promise is fulfilled.
*
* @return bool
*
* @deprecated is_fulfilled will be removed in guzzlehttp/promises:2.0. Use Is::fulfilled instead.
*/
function is_fulfilled(PromiseInterface $promise)
{
return Is::fulfilled($promise);
}
/**
* Returns true if a promise is rejected.
*
* @return bool
*
* @deprecated is_rejected will be removed in guzzlehttp/promises:2.0. Use Is::rejected instead.
*/
function is_rejected(PromiseInterface $promise)
{
return Is::rejected($promise);
}
/**
* Returns true if a promise is fulfilled or rejected.
*
* @return bool
*
* @deprecated is_settled will be removed in guzzlehttp/promises:2.0. Use Is::settled instead.
*/
function is_settled(PromiseInterface $promise)
{
return Is::settled($promise);
}
/**
* Create a new coroutine.
*
* @see Coroutine
*
* @return PromiseInterface
*
* @deprecated coroutine will be removed in guzzlehttp/promises:2.0. Use Coroutine::of instead.
*/
function coroutine(callable $generatorFn)
{
return Coroutine::of($generatorFn);
}

View File

@ -1,6 +0,0 @@
<?php
// Don't redefine the functions if included multiple times.
if (!function_exists('GuzzleHttp\Promise\promise_for')) {
require __DIR__ . '/functions.php';
}

17
vendor/guzzlehttp/psr7/CHANGELOG.md vendored Executable file → Normal file
View File

@ -5,7 +5,22 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/)
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## Unreleased
## 2.6.0 - 2023-08-03
### Changed
- Updated the mime type map to add some new entries, fix a couple of invalid entries, and remove an invalid entry
- Fallback to `application/octet-stream` if we are unable to guess the content type for a multipart file upload
## 2.5.1 - 2023-08-03
### Fixed
- Corrected mime type for `.acc` files to `audio/aac`
### Changed
- PHP 8.3 support
## 2.5.0 - 2023-04-17

0
vendor/guzzlehttp/psr7/LICENSE vendored Executable file → Normal file
View File

24
vendor/guzzlehttp/psr7/README.md vendored Executable file → Normal file
View File

@ -8,16 +8,24 @@ functionality like query string parsing.
![Static analysis](https://github.com/guzzle/psr7/workflows/Static%20analysis/badge.svg)
# Installation
## Features
This package comes with a number of stream implementations and stream
decorators.
## Installation
```shell
composer require guzzlehttp/psr7
```
# Stream implementation
## Version Guidance
This package comes with a number of stream implementations and stream
decorators.
| Version | Status | PHP Version |
|---------|---------------------|--------------|
| 1.x | Security fixes only | >=5.4,<8.1 |
| 2.x | Latest | >=7.2.5,<8.4 |
## AppendStream
@ -855,14 +863,6 @@ This of course assumes they will be resolved against the same base URI. If this
equivalence or difference of relative references does not mean anything.
## Version Guidance
| Version | Status | PHP Version |
|---------|----------------|------------------|
| 1.x | Security fixes | >=5.4,<8.1 |
| 2.x | Latest | ^7.2.5 \|\| ^8.0 |
## Security
If you discover a security vulnerability within this package, please send an email to security@tidelift.com. All security vulnerabilities will be promptly addressed. Please do not disclose security-related issues publicly until a fix has been announced. Please see [Security Policy](https://github.com/guzzle/psr7/security/policy) for more information.

0
vendor/guzzlehttp/psr7/composer.json vendored Executable file → Normal file
View File

6
vendor/guzzlehttp/psr7/src/AppendStream.php vendored Executable file → Normal file
View File

@ -40,12 +40,14 @@ final class AppendStream implements StreamInterface
{
try {
$this->rewind();
return $this->getContents();
} catch (\Throwable $e) {
if (\PHP_VERSION_ID >= 70400) {
throw $e;
}
trigger_error(sprintf('%s::__toString exception: %s', self::class, (string) $e), E_USER_ERROR);
return '';
}
}
@ -167,7 +169,7 @@ final class AppendStream implements StreamInterface
$stream->rewind();
} catch (\Exception $e) {
throw new \RuntimeException('Unable to seek stream '
. $i . ' of the AppendStream', 0, $e);
.$i.' of the AppendStream', 0, $e);
}
}
@ -197,7 +199,7 @@ final class AppendStream implements StreamInterface
if ($this->current === $total) {
break;
}
$this->current++;
++$this->current;
}
$result = $this->streams[$this->current]->read($remaining);

0
vendor/guzzlehttp/psr7/src/BufferStream.php vendored Executable file → Normal file
View File

0
vendor/guzzlehttp/psr7/src/CachingStream.php vendored Executable file → Normal file
View File

0
vendor/guzzlehttp/psr7/src/DroppingStream.php vendored Executable file → Normal file
View File

0
vendor/guzzlehttp/psr7/src/Exception/MalformedUriException.php vendored Executable file → Normal file
View File

7
vendor/guzzlehttp/psr7/src/FnStream.php vendored Executable file → Normal file
View File

@ -18,7 +18,7 @@ final class FnStream implements StreamInterface
private const SLOTS = [
'__toString', 'close', 'detach', 'rewind',
'getSize', 'tell', 'eof', 'isSeekable', 'seek', 'isWritable', 'write',
'isReadable', 'read', 'getContents', 'getMetadata'
'isReadable', 'read', 'getContents', 'getMetadata',
];
/** @var array<string, callable> */
@ -33,7 +33,7 @@ final class FnStream implements StreamInterface
// Create the functions on the class
foreach ($methods as $name => $fn) {
$this->{'_fn_' . $name} = $fn;
$this->{'_fn_'.$name} = $fn;
}
}
@ -45,7 +45,7 @@ final class FnStream implements StreamInterface
public function __get(string $name): void
{
throw new \BadMethodCallException(str_replace('_fn_', '', $name)
. '() is not implemented in the FnStream');
.'() is not implemented in the FnStream');
}
/**
@ -99,6 +99,7 @@ final class FnStream implements StreamInterface
throw $e;
}
trigger_error(sprintf('%s::__toString exception: %s', self::class, (string) $e), E_USER_ERROR);
return '';
}
}

2
vendor/guzzlehttp/psr7/src/Header.php vendored Executable file → Normal file
View File

@ -89,7 +89,7 @@ final class Header
$v = '';
$isQuoted = false;
$isEscaped = false;
for ($i = 0, $max = \strlen($value); $i < $max; $i++) {
for ($i = 0, $max = \strlen($value); $i < $max; ++$i) {
if ($isEscaped) {
$v .= $value[$i];
$isEscaped = false;

8
vendor/guzzlehttp/psr7/src/HttpFactory.php vendored Executable file → Normal file
View File

@ -23,13 +23,7 @@ use Psr\Http\Message\UriInterface;
* Note: in consuming code it is recommended to require the implemented interfaces
* and inject the instance of this class multiple times.
*/
final class HttpFactory implements
RequestFactoryInterface,
ResponseFactoryInterface,
ServerRequestFactoryInterface,
StreamFactoryInterface,
UploadedFileFactoryInterface,
UriFactoryInterface
final class HttpFactory implements RequestFactoryInterface, ResponseFactoryInterface, ServerRequestFactoryInterface, StreamFactoryInterface, UploadedFileFactoryInterface, UriFactoryInterface
{
public function createUploadedFile(
StreamInterface $stream,

6
vendor/guzzlehttp/psr7/src/InflateStream.php vendored Executable file → Normal file
View File

@ -13,9 +13,9 @@ use Psr\Http\Message\StreamInterface;
* then appends the zlib.inflate filter. The stream is then converted back
* to a Guzzle stream resource to be used as a Guzzle stream.
*
* @link http://tools.ietf.org/html/rfc1950
* @link http://tools.ietf.org/html/rfc1952
* @link http://php.net/manual/en/filters.compression.php
* @see http://tools.ietf.org/html/rfc1950
* @see http://tools.ietf.org/html/rfc1952
* @see http://php.net/manual/en/filters.compression.php
*/
final class InflateStream implements StreamInterface
{

0
vendor/guzzlehttp/psr7/src/LazyOpenStream.php vendored Executable file → Normal file
View File

0
vendor/guzzlehttp/psr7/src/LimitStream.php vendored Executable file → Normal file
View File

24
vendor/guzzlehttp/psr7/src/Message.php vendored Executable file → Normal file
View File

@ -18,16 +18,16 @@ final class Message
public static function toString(MessageInterface $message): string
{
if ($message instanceof RequestInterface) {
$msg = trim($message->getMethod() . ' '
. $message->getRequestTarget())
. ' HTTP/' . $message->getProtocolVersion();
$msg = trim($message->getMethod().' '
.$message->getRequestTarget())
.' HTTP/'.$message->getProtocolVersion();
if (!$message->hasHeader('host')) {
$msg .= "\r\nHost: " . $message->getUri()->getHost();
$msg .= "\r\nHost: ".$message->getUri()->getHost();
}
} elseif ($message instanceof ResponseInterface) {
$msg = 'HTTP/' . $message->getProtocolVersion() . ' '
. $message->getStatusCode() . ' '
. $message->getReasonPhrase();
$msg = 'HTTP/'.$message->getProtocolVersion().' '
.$message->getStatusCode().' '
.$message->getReasonPhrase();
} else {
throw new \InvalidArgumentException('Unknown message type');
}
@ -35,14 +35,14 @@ final class Message
foreach ($message->getHeaders() as $name => $values) {
if (strtolower($name) === 'set-cookie') {
foreach ($values as $value) {
$msg .= "\r\n{$name}: " . $value;
$msg .= "\r\n{$name}: ".$value;
}
} else {
$msg .= "\r\n{$name}: " . implode(', ', $values);
$msg .= "\r\n{$name}: ".implode(', ', $values);
}
}
return "{$msg}\r\n\r\n" . $message->getBody();
return "{$msg}\r\n\r\n".$message->getBody();
}
/**
@ -190,7 +190,7 @@ final class Message
$host = $headers[reset($hostKey)][0];
$scheme = substr($host, -4) === ':443' ? 'https' : 'http';
return $scheme . '://' . $host . '/' . ltrim($path, '/');
return $scheme.'://'.$host.'/'.ltrim($path, '/');
}
/**
@ -231,7 +231,7 @@ final class Message
// between status-code and reason-phrase is required. But browsers accept
// responses without space and reason as well.
if (!preg_match('/^HTTP\/.* [0-9]{3}( .*|$)/', $data['start-line'])) {
throw new \InvalidArgumentException('Invalid response string: ' . $data['start-line']);
throw new \InvalidArgumentException('Invalid response string: '.$data['start-line']);
}
$parts = explode(' ', $data['start-line'], 3);

8
vendor/guzzlehttp/psr7/src/MessageTrait.php vendored Executable file → Normal file
View File

@ -16,7 +16,7 @@ trait MessageTrait
private $headers = [];
/** @var array<string, string> Map of lowercase header name => original name at registration */
private $headerNames = [];
private $headerNames = [];
/** @var string */
private $protocol = '1.1';
@ -37,6 +37,7 @@ trait MessageTrait
$new = clone $this;
$new->protocol = $version;
return $new;
}
@ -135,6 +136,7 @@ trait MessageTrait
$new = clone $this;
$new->stream = $body;
return $new;
}
@ -224,7 +226,7 @@ trait MessageTrait
));
}
if (! preg_match('/^[a-zA-Z0-9\'`#$%&*+.^_|~!-]+$/D', $header)) {
if (!preg_match('/^[a-zA-Z0-9\'`#$%&*+.^_|~!-]+$/D', $header)) {
throw new \InvalidArgumentException(
sprintf('"%s" is not valid header name.', $header)
);
@ -254,7 +256,7 @@ trait MessageTrait
// Clients must not send a request with line folding and a server sending folded headers is
// likely very rare. Line folding is a fairly obscure feature of HTTP/1.1 and thus not accepting
// folding is not likely to break any legitimate use case.
if (! preg_match('/^[\x20\x09\x21-\x7E\x80-\xFF]*$/D', $value)) {
if (!preg_match('/^[\x20\x09\x21-\x7E\x80-\xFF]*$/D', $value)) {
throw new \InvalidArgumentException(
sprintf('"%s" is not valid header value.', $value)
);

34
vendor/guzzlehttp/psr7/src/MimeType.php vendored Executable file → Normal file
View File

@ -18,7 +18,7 @@ final class MimeType
'7zip' => 'application/x-7z-compressed',
'123' => 'application/vnd.lotus-1-2-3',
'aab' => 'application/x-authorware-bin',
'aac' => 'audio/x-acc',
'aac' => 'audio/aac',
'aam' => 'application/x-authorware-map',
'aas' => 'application/x-authorware-seg',
'abw' => 'application/x-abiword',
@ -29,6 +29,7 @@ final class MimeType
'acu' => 'application/vnd.acucobol',
'acutc' => 'application/vnd.acucorp',
'adp' => 'audio/adpcm',
'adts' => 'audio/aac',
'aep' => 'application/vnd.audiograph',
'afm' => 'application/x-font-type1',
'afp' => 'application/vnd.ibm.modcap',
@ -41,11 +42,16 @@ final class MimeType
'air' => 'application/vnd.adobe.air-application-installer-package+zip',
'ait' => 'application/vnd.dvb.ait',
'ami' => 'application/vnd.amiga.ami',
'aml' => 'application/automationml-aml+xml',
'amlx' => 'application/automationml-amlx+zip',
'amr' => 'audio/amr',
'apk' => 'application/vnd.android.package-archive',
'apng' => 'image/apng',
'appcache' => 'text/cache-manifest',
'appinstaller' => 'application/appinstaller',
'application' => 'application/x-ms-application',
'appx' => 'application/appx',
'appxbundle' => 'application/appxbundle',
'apr' => 'application/vnd.lotus-approach',
'arc' => 'application/x-freearc',
'arj' => 'application/x-arj',
@ -90,6 +96,7 @@ final class MimeType
'bpk' => 'application/octet-stream',
'bpmn' => 'application/octet-stream',
'bsp' => 'model/vnd.valve.source.compiled-map',
'btf' => 'image/prs.btif',
'btif' => 'image/prs.btif',
'buffer' => 'application/octet-stream',
'bz' => 'application/x-bzip',
@ -141,6 +148,7 @@ final class MimeType
'cjs' => 'application/node',
'cla' => 'application/vnd.claymore',
'class' => 'application/octet-stream',
'cld' => 'model/vnd.cld',
'clkk' => 'application/vnd.crick.clicker.keyboard',
'clkp' => 'application/vnd.crick.clicker.palette',
'clkt' => 'application/vnd.crick.clicker.template',
@ -175,6 +183,7 @@ final class MimeType
'csv' => 'text/csv',
'cu' => 'application/cu-seeme',
'curl' => 'text/vnd.curl',
'cwl' => 'application/cwl',
'cww' => 'application/prs.cww',
'cxt' => 'application/x-director',
'cxx' => 'text/x-c',
@ -197,6 +206,7 @@ final class MimeType
'der' => 'application/x-x509-ca-cert',
'dfac' => 'application/vnd.dreamfactory',
'dgc' => 'application/x-dgc-compressed',
'dib' => 'image/bmp',
'dic' => 'text/x-c',
'dir' => 'application/x-director',
'dis' => 'application/vnd.mobius.dis',
@ -219,6 +229,7 @@ final class MimeType
'dotx' => 'application/vnd.openxmlformats-officedocument.wordprocessingml.template',
'dp' => 'application/vnd.osgi.dp',
'dpg' => 'application/vnd.dpgraph',
'dpx' => 'image/dpx',
'dra' => 'audio/vnd.dra',
'drle' => 'image/dicom-rle',
'dsc' => 'text/prs.lines.tag',
@ -255,7 +266,6 @@ final class MimeType
'eot' => 'application/vnd.ms-fontobject',
'eps' => 'application/postscript',
'epub' => 'application/epub+zip',
'es' => 'application/ecmascript',
'es3' => 'application/vnd.eszigno3+xml',
'esa' => 'application/vnd.osgi.subsystem',
'esf' => 'application/vnd.epson.esf',
@ -448,6 +458,7 @@ final class MimeType
'jsonld' => 'application/ld+json',
'jsonml' => 'application/jsonml+json',
'jsx' => 'text/jsx',
'jt' => 'model/jt',
'jxr' => 'image/jxr',
'jxra' => 'image/jxra',
'jxrs' => 'image/jxrs',
@ -552,7 +563,7 @@ final class MimeType
'mime' => 'message/rfc822',
'mj2' => 'video/mj2',
'mjp2' => 'video/mj2',
'mjs' => 'application/javascript',
'mjs' => 'text/javascript',
'mk3d' => 'video/x-matroska',
'mka' => 'audio/x-matroska',
'mkd' => 'text/x-markdown',
@ -602,6 +613,8 @@ final class MimeType
'msg' => 'application/vnd.ms-outlook',
'msh' => 'model/mesh',
'msi' => 'application/x-msdownload',
'msix' => 'application/msix',
'msixbundle' => 'application/msixbundle',
'msl' => 'application/vnd.mobius.msl',
'msm' => 'application/octet-stream',
'msp' => 'application/octet-stream',
@ -775,6 +788,8 @@ final class MimeType
'pvb' => 'application/vnd.3gpp.pic-bw-var',
'pwn' => 'application/vnd.3m.post-it-notes',
'pya' => 'audio/vnd.ms-playready.media.pya',
'pyo' => 'model/vnd.pytha.pyox',
'pyox' => 'model/vnd.pytha.pyox',
'pyv' => 'video/vnd.ms-playready.media.pyv',
'qam' => 'application/vnd.epson.quickanime',
'qbo' => 'application/vnd.intu.qbo',
@ -923,10 +938,12 @@ final class MimeType
'st' => 'application/vnd.sailingtracker.track',
'stc' => 'application/vnd.sun.xml.calc.template',
'std' => 'application/vnd.sun.xml.draw.template',
'step' => 'application/STEP',
'stf' => 'application/vnd.wt.stf',
'sti' => 'application/vnd.sun.xml.impress.template',
'stk' => 'application/hyperstudio',
'stl' => 'model/stl',
'stp' => 'application/STEP',
'stpx' => 'model/step+xml',
'stpxz' => 'model/step-xml+zip',
'stpz' => 'model/step+zip',
@ -1013,10 +1030,12 @@ final class MimeType
'ulx' => 'application/x-glulx',
'umj' => 'application/vnd.umajin',
'unityweb' => 'application/vnd.unity',
'uo' => 'application/vnd.uoml+xml',
'uoml' => 'application/vnd.uoml+xml',
'uri' => 'text/uri-list',
'uris' => 'text/uri-list',
'urls' => 'text/uri-list',
'usda' => 'model/vnd.usda',
'usdz' => 'model/vnd.usdz+zip',
'ustar' => 'application/x-ustar',
'utz' => 'application/vnd.uiq.theme',
@ -1096,6 +1115,7 @@ final class MimeType
'webmanifest' => 'application/manifest+json',
'webp' => 'image/webp',
'wg' => 'application/vnd.pmi.widget',
'wgsl' => 'text/wgsl',
'wgt' => 'application/widget',
'wif' => 'application/watcherinfo+xml',
'wks' => 'application/vnd.ms-works',
@ -1150,9 +1170,10 @@ final class MimeType
'xel' => 'application/xcap-el+xml',
'xenc' => 'application/xenc+xml',
'xer' => 'application/patch-ops-error+xml',
'xfdf' => 'application/vnd.adobe.xfdf',
'xfdf' => 'application/xfdf',
'xfdl' => 'application/vnd.xfdl',
'xht' => 'application/xhtml+xml',
'xhtm' => 'application/vnd.pwg-xhtml-print+xml',
'xhtml' => 'application/xhtml+xml',
'xhvml' => 'application/xv+xml',
'xif' => 'image/vnd.xiff',
@ -1183,6 +1204,7 @@ final class MimeType
'xpw' => 'application/vnd.intercon.formnet',
'xpx' => 'application/vnd.intercon.formnet',
'xsd' => 'application/xml',
'xsf' => 'application/prs.xsf+xml',
'xsl' => 'application/xml',
'xslt' => 'application/xslt+xml',
'xsm' => 'application/vnd.syncml+xml',
@ -1218,7 +1240,7 @@ final class MimeType
/**
* Determines the mimetype of a file by looking at its extension.
*
* @link https://raw.githubusercontent.com/jshttp/mime-db/master/db.json
* @see https://raw.githubusercontent.com/jshttp/mime-db/master/db.json
*/
public static function fromFilename(string $filename): ?string
{
@ -1228,7 +1250,7 @@ final class MimeType
/**
* Maps a file extensions to a mimetype.
*
* @link https://raw.githubusercontent.com/jshttp/mime-db/master/db.json
* @see https://raw.githubusercontent.com/jshttp/mime-db/master/db.json
*/
public static function fromExtension(string $extension): ?string
{

8
vendor/guzzlehttp/psr7/src/MultipartStream.php vendored Executable file → Normal file
View File

@ -60,7 +60,7 @@ final class MultipartStream implements StreamInterface
$str .= "{$key}: {$value}\r\n";
}
return "--{$this->boundary}\r\n" . trim($str) . "\r\n\r\n";
return "--{$this->boundary}\r\n".trim($str)."\r\n\r\n";
}
/**
@ -72,7 +72,7 @@ final class MultipartStream implements StreamInterface
foreach ($elements as $element) {
if (!is_array($element)) {
throw new \UnexpectedValueException("An array is expected");
throw new \UnexpectedValueException('An array is expected');
}
$this->addElement($stream, $element);
}
@ -137,9 +137,7 @@ final class MultipartStream implements StreamInterface
// Set a default Content-Type if one was not supplied
$type = $this->getHeader($headers, 'content-type');
if (!$type && ($filename === '0' || $filename)) {
if ($type = MimeType::fromFilename($filename)) {
$headers['Content-Type'] = $type;
}
$headers['Content-Type'] = MimeType::fromFilename($filename) ?? 'application/octet-stream';
}
return [$stream, $headers];

0
vendor/guzzlehttp/psr7/src/NoSeekStream.php vendored Executable file → Normal file
View File

2
vendor/guzzlehttp/psr7/src/PumpStream.php vendored Executable file → Normal file
View File

@ -60,6 +60,7 @@ final class PumpStream implements StreamInterface
throw $e;
}
trigger_error(sprintf('%s::__toString exception: %s', self::class, (string) $e), E_USER_ERROR);
return '';
}
}
@ -169,6 +170,7 @@ final class PumpStream implements StreamInterface
$data = call_user_func($this->source, $length);
if ($data === false || $data === null) {
$this->source = null;
return;
}
$this->buffer->write($data);

4
vendor/guzzlehttp/psr7/src/Query.php vendored Executable file → Normal file
View File

@ -93,7 +93,7 @@ final class Query
$qs .= $k;
$v = is_bool($v) ? (int) $v : $v;
if ($v !== null) {
$qs .= '=' . $encoder((string) $v);
$qs .= '='.$encoder((string) $v);
}
$qs .= '&';
} else {
@ -101,7 +101,7 @@ final class Query
$qs .= $k;
$vv = is_bool($vv) ? (int) $vv : $vv;
if ($vv !== null) {
$qs .= '=' . $encoder((string) $vv);
$qs .= '='.$encoder((string) $vv);
}
$qs .= '&';
}

6
vendor/guzzlehttp/psr7/src/Request.php vendored Executable file → Normal file
View File

@ -69,7 +69,7 @@ class Request implements RequestInterface
$target = '/';
}
if ($this->uri->getQuery() != '') {
$target .= '?' . $this->uri->getQuery();
$target .= '?'.$this->uri->getQuery();
}
return $target;
@ -85,6 +85,7 @@ class Request implements RequestInterface
$new = clone $this;
$new->requestTarget = $requestTarget;
return $new;
}
@ -98,6 +99,7 @@ class Request implements RequestInterface
$this->assertMethod($method);
$new = clone $this;
$new->method = strtoupper($method);
return $new;
}
@ -131,7 +133,7 @@ class Request implements RequestInterface
}
if (($port = $this->uri->getPort()) !== null) {
$host .= ':' . $port;
$host .= ':'.$port;
}
if (isset($this->headerNames['host'])) {

Some files were not shown because too many files have changed in this diff Show More