From 3e781226591d946778822b4fcc6b223e50a8889c Mon Sep 17 00:00:00 2001
From: wong <106998207@qq.com>
Date: Thu, 20 Nov 2025 11:45:53 +0800
Subject: [PATCH 01/10] =?UTF-8?q?composer=E4=BE=9D=E8=B5=96=E6=8F=90?=
=?UTF-8?q?=E4=BA=A4?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
Server/composer.json | 48 +-
Server/composer.lock | 4299 +++++++++++++++++++++++++++++++++++++++++-
2 files changed, 4320 insertions(+), 27 deletions(-)
diff --git a/Server/composer.json b/Server/composer.json
index 61d3fa7c..1f70969d 100644
--- a/Server/composer.json
+++ b/Server/composer.json
@@ -13,21 +13,59 @@
{
"name": "liu21st",
"email": "liu21st@gmail.com"
+ },
+ {
+ "name": "yunwuxin",
+ "email": "448901948@qq.com"
}
],
"require": {
- "php": ">=5.4.0",
- "topthink/framework": "5.0.*"
+ "php": ">=5.6.0",
+ "topthink/framework": "5.1.41",
+ "topthink/think-installer": "2.*",
+ "topthink/think-captcha": "^2.0",
+ "topthink/think-helper": "^3.0",
+ "topthink/think-image": "^1.0",
+ "topthink/think-queue": "^2.0",
+ "topthink/think-worker": "^2.0",
+ "textalk/websocket": "^1.5",
+ "aliyuncs/oss-sdk-php": "^2.6",
+ "monolog/monolog": "^1.27",
+ "guzzlehttp/guzzle": "^6.5",
+ "overtrue/wechat": "~4.6",
+ "endroid/qr-code": "^3.9",
+ "phpoffice/phpspreadsheet": "^1.29",
+ "workerman/workerman": "^3.5",
+ "workerman/gateway-worker": "^3.0",
+ "hashids/hashids": "^2.0",
+ "khanamiryan/qrcode-detector-decoder": "^1.0",
+ "lizhichao/word": "^2.0",
+ "adbario/php-dot-notation": "^2.2"
+ },
+ "require-dev": {
+ "symfony/var-dumper": "^3.4|^4.4",
+ "topthink/think-migration": "^2.0",
+ "phpunit/phpunit": "^5.0|^6.0"
},
"autoload": {
"psr-4": {
"app\\": "application"
- }
+ },
+ "files": [
+ "application/common.php"
+ ],
+ "classmap": []
},
"extra": {
"think-path": "thinkphp"
},
"config": {
- "preferred-install": "dist"
- }
+ "preferred-install": "dist",
+ "allow-plugins": {
+ "topthink/think-installer": true,
+ "easywechat-composer/easywechat-composer": true
+ }
+ },
+ "minimum-stability": "dev",
+ "prefer-stable": true
}
diff --git a/Server/composer.lock b/Server/composer.lock
index 50bf3cea..56ff4a97 100644
--- a/Server/composer.lock
+++ b/Server/composer.lock
@@ -4,48 +4,3832 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
- "content-hash": "ba81097bd3bedb9a9265465b0f578307",
+ "content-hash": "5bca28194f84a7d13965d1851e6ce38a",
"packages": [
{
- "name": "topthink/framework",
- "version": "v5.0.25",
+ "name": "adbario/php-dot-notation",
+ "version": "2.5.0",
"source": {
"type": "git",
- "url": "https://github.com/top-think/framework.git",
- "reference": "643c58ed1bd22a2823ce5e95b3b68a5075f9087c"
+ "url": "https://github.com/adbario/php-dot-notation.git",
+ "reference": "081e2cca50c84bfeeea2e3ef9b2c8d206d80ccae"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/top-think/framework/zipball/643c58ed1bd22a2823ce5e95b3b68a5075f9087c",
- "reference": "643c58ed1bd22a2823ce5e95b3b68a5075f9087c",
+ "url": "https://api.github.com/repos/adbario/php-dot-notation/zipball/081e2cca50c84bfeeea2e3ef9b2c8d206d80ccae",
+ "reference": "081e2cca50c84bfeeea2e3ef9b2c8d206d80ccae",
+ "shasum": ""
+ },
+ "require": {
+ "ext-json": "*",
+ "php": "^5.5 || ^7.0 || ^8.0"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "^4.8|^5.7|^6.6|^7.5|^8.5|^9.5",
+ "squizlabs/php_codesniffer": "^3.6"
+ },
+ "type": "library",
+ "autoload": {
+ "files": [
+ "src/helpers.php"
+ ],
+ "psr-4": {
+ "Adbar\\": "src"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Riku Särkinen",
+ "email": "riku@adbar.io"
+ }
+ ],
+ "description": "PHP dot notation access to arrays",
+ "homepage": "https://github.com/adbario/php-dot-notation",
+ "keywords": [
+ "ArrayAccess",
+ "dotnotation"
+ ],
+ "support": {
+ "issues": "https://github.com/adbario/php-dot-notation/issues",
+ "source": "https://github.com/adbario/php-dot-notation/tree/2.5.0"
+ },
+ "time": "2022-10-14T20:31:46+00:00"
+ },
+ {
+ "name": "aliyuncs/oss-sdk-php",
+ "version": "v2.7.2",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/aliyun/aliyun-oss-php-sdk.git",
+ "reference": "483dd0b8bff5d47f0e4ffc99f6077a295c5ccbb5"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/aliyun/aliyun-oss-php-sdk/zipball/483dd0b8bff5d47f0e4ffc99f6077a295c5ccbb5",
+ "reference": "483dd0b8bff5d47f0e4ffc99f6077a295c5ccbb5",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=5.3"
+ },
+ "require-dev": {
+ "php-coveralls/php-coveralls": "*",
+ "phpunit/phpunit": "*"
+ },
+ "type": "library",
+ "autoload": {
+ "psr-4": {
+ "OSS\\": "src/OSS"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Aliyuncs",
+ "homepage": "http://www.aliyun.com"
+ }
+ ],
+ "description": "Aliyun OSS SDK for PHP",
+ "homepage": "http://www.aliyun.com/product/oss/",
+ "support": {
+ "issues": "https://github.com/aliyun/aliyun-oss-php-sdk/issues",
+ "source": "https://github.com/aliyun/aliyun-oss-php-sdk/tree/v2.7.2"
+ },
+ "time": "2024-10-28T10:41:12+00:00"
+ },
+ {
+ "name": "bacon/bacon-qr-code",
+ "version": "2.0.8",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/Bacon/BaconQrCode.git",
+ "reference": "8674e51bb65af933a5ffaf1c308a660387c35c22"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/Bacon/BaconQrCode/zipball/8674e51bb65af933a5ffaf1c308a660387c35c22",
+ "reference": "8674e51bb65af933a5ffaf1c308a660387c35c22",
+ "shasum": ""
+ },
+ "require": {
+ "dasprid/enum": "^1.0.3",
+ "ext-iconv": "*",
+ "php": "^7.1 || ^8.0"
+ },
+ "require-dev": {
+ "phly/keep-a-changelog": "^2.1",
+ "phpunit/phpunit": "^7 | ^8 | ^9",
+ "spatie/phpunit-snapshot-assertions": "^4.2.9",
+ "squizlabs/php_codesniffer": "^3.4"
+ },
+ "suggest": {
+ "ext-imagick": "to generate QR code images"
+ },
+ "type": "library",
+ "autoload": {
+ "psr-4": {
+ "BaconQrCode\\": "src/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-2-Clause"
+ ],
+ "authors": [
+ {
+ "name": "Ben Scholzen 'DASPRiD'",
+ "email": "mail@dasprids.de",
+ "homepage": "https://dasprids.de/",
+ "role": "Developer"
+ }
+ ],
+ "description": "BaconQrCode is a QR code generator for PHP.",
+ "homepage": "https://github.com/Bacon/BaconQrCode",
+ "support": {
+ "issues": "https://github.com/Bacon/BaconQrCode/issues",
+ "source": "https://github.com/Bacon/BaconQrCode/tree/2.0.8"
+ },
+ "time": "2022-12-07T17:46:57+00:00"
+ },
+ {
+ "name": "composer/pcre",
+ "version": "3.3.2",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/composer/pcre.git",
+ "reference": "b2bed4734f0cc156ee1fe9c0da2550420d99a21e"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/composer/pcre/zipball/b2bed4734f0cc156ee1fe9c0da2550420d99a21e",
+ "reference": "b2bed4734f0cc156ee1fe9c0da2550420d99a21e",
+ "shasum": ""
+ },
+ "require": {
+ "php": "^7.4 || ^8.0"
+ },
+ "conflict": {
+ "phpstan/phpstan": "<1.11.10"
+ },
+ "require-dev": {
+ "phpstan/phpstan": "^1.12 || ^2",
+ "phpstan/phpstan-strict-rules": "^1 || ^2",
+ "phpunit/phpunit": "^8 || ^9"
+ },
+ "type": "library",
+ "extra": {
+ "phpstan": {
+ "includes": [
+ "extension.neon"
+ ]
+ },
+ "branch-alias": {
+ "dev-main": "3.x-dev"
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "Composer\\Pcre\\": "src"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Jordi Boggiano",
+ "email": "j.boggiano@seld.be",
+ "homepage": "http://seld.be"
+ }
+ ],
+ "description": "PCRE wrapping library that offers type-safe preg_* replacements.",
+ "keywords": [
+ "PCRE",
+ "preg",
+ "regex",
+ "regular expression"
+ ],
+ "support": {
+ "issues": "https://github.com/composer/pcre/issues",
+ "source": "https://github.com/composer/pcre/tree/3.3.2"
+ },
+ "funding": [
+ {
+ "url": "https://packagist.com",
+ "type": "custom"
+ },
+ {
+ "url": "https://github.com/composer",
+ "type": "github"
+ },
+ {
+ "url": "https://tidelift.com/funding/github/packagist/composer/composer",
+ "type": "tidelift"
+ }
+ ],
+ "time": "2024-11-12T16:29:46+00:00"
+ },
+ {
+ "name": "dasprid/enum",
+ "version": "1.0.7",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/DASPRiD/Enum.git",
+ "reference": "b5874fa9ed0043116c72162ec7f4fb50e02e7cce"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/DASPRiD/Enum/zipball/b5874fa9ed0043116c72162ec7f4fb50e02e7cce",
+ "reference": "b5874fa9ed0043116c72162ec7f4fb50e02e7cce",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=7.1 <9.0"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "^7 || ^8 || ^9 || ^10 || ^11",
+ "squizlabs/php_codesniffer": "*"
+ },
+ "type": "library",
+ "autoload": {
+ "psr-4": {
+ "DASPRiD\\Enum\\": "src/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-2-Clause"
+ ],
+ "authors": [
+ {
+ "name": "Ben Scholzen 'DASPRiD'",
+ "email": "mail@dasprids.de",
+ "homepage": "https://dasprids.de/",
+ "role": "Developer"
+ }
+ ],
+ "description": "PHP 7.1 enum implementation",
+ "keywords": [
+ "enum",
+ "map"
+ ],
+ "support": {
+ "issues": "https://github.com/DASPRiD/Enum/issues",
+ "source": "https://github.com/DASPRiD/Enum/tree/1.0.7"
+ },
+ "time": "2025-09-16T12:23:56+00:00"
+ },
+ {
+ "name": "easywechat-composer/easywechat-composer",
+ "version": "1.4.1",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/mingyoung/easywechat-composer.git",
+ "reference": "3fc6a7ab6d3853c0f4e2922539b56cc37ef361cd"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/mingyoung/easywechat-composer/zipball/3fc6a7ab6d3853c0f4e2922539b56cc37ef361cd",
+ "reference": "3fc6a7ab6d3853c0f4e2922539b56cc37ef361cd",
+ "shasum": ""
+ },
+ "require": {
+ "composer-plugin-api": "^1.0 || ^2.0",
+ "php": ">=7.0"
+ },
+ "require-dev": {
+ "composer/composer": "^1.0 || ^2.0",
+ "phpunit/phpunit": "^6.5 || ^7.0"
+ },
+ "type": "composer-plugin",
+ "extra": {
+ "class": "EasyWeChatComposer\\Plugin"
+ },
+ "autoload": {
+ "psr-4": {
+ "EasyWeChatComposer\\": "src/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "张铭阳",
+ "email": "mingyoungcheung@gmail.com"
+ }
+ ],
+ "description": "The composer plugin for EasyWeChat",
+ "support": {
+ "issues": "https://github.com/mingyoung/easywechat-composer/issues",
+ "source": "https://github.com/mingyoung/easywechat-composer/tree/1.4.1"
+ },
+ "time": "2021-07-05T04:03:22+00:00"
+ },
+ {
+ "name": "endroid/qr-code",
+ "version": "3.9.7",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/endroid/qr-code.git",
+ "reference": "94563d7b3105288e6ac53a67ae720e3669fac1f6"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/endroid/qr-code/zipball/94563d7b3105288e6ac53a67ae720e3669fac1f6",
+ "reference": "94563d7b3105288e6ac53a67ae720e3669fac1f6",
+ "shasum": ""
+ },
+ "require": {
+ "bacon/bacon-qr-code": "^2.0",
+ "khanamiryan/qrcode-detector-decoder": "^1.0.5",
+ "myclabs/php-enum": "^1.5",
+ "php": "^7.3||^8.0",
+ "symfony/options-resolver": "^3.4||^4.4||^5.0",
+ "symfony/property-access": "^3.4||^4.4||^5.0"
+ },
+ "require-dev": {
+ "endroid/quality": "^1.5.2",
+ "setasign/fpdf": "^1.8"
+ },
+ "suggest": {
+ "ext-gd": "Required for generating PNG images",
+ "roave/security-advisories": "Avoids installation of package versions with vulnerabilities",
+ "setasign/fpdf": "Required to use the FPDF writer.",
+ "symfony/security-checker": "Checks your composer.lock for vulnerabilities"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "3.x-dev"
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "Endroid\\QrCode\\": "src/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Jeroen van den Enden",
+ "email": "info@endroid.nl"
+ }
+ ],
+ "description": "Endroid QR Code",
+ "homepage": "https://github.com/endroid/qr-code",
+ "keywords": [
+ "bundle",
+ "code",
+ "endroid",
+ "php",
+ "qr",
+ "qrcode"
+ ],
+ "support": {
+ "issues": "https://github.com/endroid/qr-code/issues",
+ "source": "https://github.com/endroid/qr-code/tree/3.9.7"
+ },
+ "funding": [
+ {
+ "url": "https://github.com/endroid",
+ "type": "github"
+ }
+ ],
+ "time": "2021-04-20T19:10:54+00:00"
+ },
+ {
+ "name": "ezyang/htmlpurifier",
+ "version": "v4.19.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/ezyang/htmlpurifier.git",
+ "reference": "b287d2a16aceffbf6e0295559b39662612b77fcf"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/ezyang/htmlpurifier/zipball/b287d2a16aceffbf6e0295559b39662612b77fcf",
+ "reference": "b287d2a16aceffbf6e0295559b39662612b77fcf",
+ "shasum": ""
+ },
+ "require": {
+ "php": "~5.6.0 || ~7.0.0 || ~7.1.0 || ~7.2.0 || ~7.3.0 || ~7.4.0 || ~8.0.0 || ~8.1.0 || ~8.2.0 || ~8.3.0 || ~8.4.0 || ~8.5.0"
+ },
+ "require-dev": {
+ "cerdic/css-tidy": "^1.7 || ^2.0",
+ "simpletest/simpletest": "dev-master"
+ },
+ "suggest": {
+ "cerdic/css-tidy": "If you want to use the filter 'Filter.ExtractStyleBlocks'.",
+ "ext-bcmath": "Used for unit conversion and imagecrash protection",
+ "ext-iconv": "Converts text to and from non-UTF-8 encodings",
+ "ext-tidy": "Used for pretty-printing HTML"
+ },
+ "type": "library",
+ "autoload": {
+ "files": [
+ "library/HTMLPurifier.composer.php"
+ ],
+ "psr-0": {
+ "HTMLPurifier": "library/"
+ },
+ "exclude-from-classmap": [
+ "/library/HTMLPurifier/Language/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "LGPL-2.1-or-later"
+ ],
+ "authors": [
+ {
+ "name": "Edward Z. Yang",
+ "email": "admin@htmlpurifier.org",
+ "homepage": "http://ezyang.com"
+ }
+ ],
+ "description": "Standards compliant HTML filter written in PHP",
+ "homepage": "http://htmlpurifier.org/",
+ "keywords": [
+ "html"
+ ],
+ "support": {
+ "issues": "https://github.com/ezyang/htmlpurifier/issues",
+ "source": "https://github.com/ezyang/htmlpurifier/tree/v4.19.0"
+ },
+ "time": "2025-10-17T16:34:55+00:00"
+ },
+ {
+ "name": "guzzlehttp/guzzle",
+ "version": "6.5.8",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/guzzle/guzzle.git",
+ "reference": "a52f0440530b54fa079ce76e8c5d196a42cad981"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/guzzle/guzzle/zipball/a52f0440530b54fa079ce76e8c5d196a42cad981",
+ "reference": "a52f0440530b54fa079ce76e8c5d196a42cad981",
+ "shasum": ""
+ },
+ "require": {
+ "ext-json": "*",
+ "guzzlehttp/promises": "^1.0",
+ "guzzlehttp/psr7": "^1.9",
+ "php": ">=5.5",
+ "symfony/polyfill-intl-idn": "^1.17"
+ },
+ "require-dev": {
+ "ext-curl": "*",
+ "phpunit/phpunit": "^4.8.35 || ^5.7 || ^6.4 || ^7.0",
+ "psr/log": "^1.1"
+ },
+ "suggest": {
+ "psr/log": "Required for using the Log middleware"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "6.5-dev"
+ }
+ },
+ "autoload": {
+ "files": [
+ "src/functions_include.php"
+ ],
+ "psr-4": {
+ "GuzzleHttp\\": "src/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Graham Campbell",
+ "email": "hello@gjcampbell.co.uk",
+ "homepage": "https://github.com/GrahamCampbell"
+ },
+ {
+ "name": "Michael Dowling",
+ "email": "mtdowling@gmail.com",
+ "homepage": "https://github.com/mtdowling"
+ },
+ {
+ "name": "Jeremy Lindblom",
+ "email": "jeremeamia@gmail.com",
+ "homepage": "https://github.com/jeremeamia"
+ },
+ {
+ "name": "George Mponos",
+ "email": "gmponos@gmail.com",
+ "homepage": "https://github.com/gmponos"
+ },
+ {
+ "name": "Tobias Nyholm",
+ "email": "tobias.nyholm@gmail.com",
+ "homepage": "https://github.com/Nyholm"
+ },
+ {
+ "name": "Márk Sági-Kazár",
+ "email": "mark.sagikazar@gmail.com",
+ "homepage": "https://github.com/sagikazarmark"
+ },
+ {
+ "name": "Tobias Schultze",
+ "email": "webmaster@tubo-world.de",
+ "homepage": "https://github.com/Tobion"
+ }
+ ],
+ "description": "Guzzle is a PHP HTTP client library",
+ "homepage": "http://guzzlephp.org/",
+ "keywords": [
+ "client",
+ "curl",
+ "framework",
+ "http",
+ "http client",
+ "rest",
+ "web service"
+ ],
+ "support": {
+ "issues": "https://github.com/guzzle/guzzle/issues",
+ "source": "https://github.com/guzzle/guzzle/tree/6.5.8"
+ },
+ "funding": [
+ {
+ "url": "https://github.com/GrahamCampbell",
+ "type": "github"
+ },
+ {
+ "url": "https://github.com/Nyholm",
+ "type": "github"
+ },
+ {
+ "url": "https://tidelift.com/funding/github/packagist/guzzlehttp/guzzle",
+ "type": "tidelift"
+ }
+ ],
+ "time": "2022-06-20T22:16:07+00:00"
+ },
+ {
+ "name": "guzzlehttp/promises",
+ "version": "1.5.3",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/guzzle/promises.git",
+ "reference": "67ab6e18aaa14d753cc148911d273f6e6cb6721e"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/guzzle/promises/zipball/67ab6e18aaa14d753cc148911d273f6e6cb6721e",
+ "reference": "67ab6e18aaa14d753cc148911d273f6e6cb6721e",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=5.5"
+ },
+ "require-dev": {
+ "symfony/phpunit-bridge": "^4.4 || ^5.1"
+ },
+ "type": "library",
+ "autoload": {
+ "files": [
+ "src/functions_include.php"
+ ],
+ "psr-4": {
+ "GuzzleHttp\\Promise\\": "src/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Graham Campbell",
+ "email": "hello@gjcampbell.co.uk",
+ "homepage": "https://github.com/GrahamCampbell"
+ },
+ {
+ "name": "Michael Dowling",
+ "email": "mtdowling@gmail.com",
+ "homepage": "https://github.com/mtdowling"
+ },
+ {
+ "name": "Tobias Nyholm",
+ "email": "tobias.nyholm@gmail.com",
+ "homepage": "https://github.com/Nyholm"
+ },
+ {
+ "name": "Tobias Schultze",
+ "email": "webmaster@tubo-world.de",
+ "homepage": "https://github.com/Tobion"
+ }
+ ],
+ "description": "Guzzle promises library",
+ "keywords": [
+ "promise"
+ ],
+ "support": {
+ "issues": "https://github.com/guzzle/promises/issues",
+ "source": "https://github.com/guzzle/promises/tree/1.5.3"
+ },
+ "funding": [
+ {
+ "url": "https://github.com/GrahamCampbell",
+ "type": "github"
+ },
+ {
+ "url": "https://github.com/Nyholm",
+ "type": "github"
+ },
+ {
+ "url": "https://tidelift.com/funding/github/packagist/guzzlehttp/promises",
+ "type": "tidelift"
+ }
+ ],
+ "time": "2023-05-21T12:31:43+00:00"
+ },
+ {
+ "name": "guzzlehttp/psr7",
+ "version": "1.9.1",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/guzzle/psr7.git",
+ "reference": "e4490cabc77465aaee90b20cfc9a770f8c04be6b"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/guzzle/psr7/zipball/e4490cabc77465aaee90b20cfc9a770f8c04be6b",
+ "reference": "e4490cabc77465aaee90b20cfc9a770f8c04be6b",
"shasum": ""
},
"require": {
"php": ">=5.4.0",
- "topthink/think-installer": "~1.0"
+ "psr/http-message": "~1.0",
+ "ralouphie/getallheaders": "^2.0.5 || ^3.0.0"
+ },
+ "provide": {
+ "psr/http-message-implementation": "1.0"
},
"require-dev": {
- "johnkary/phpunit-speedtrap": "^1.0",
- "mikey179/vfsstream": "~1.6",
- "phpdocumentor/reflection-docblock": "^2.0",
- "phploc/phploc": "2.*",
- "phpunit/phpunit": "4.8.*",
- "sebastian/phpcpd": "2.*"
+ "ext-zlib": "*",
+ "phpunit/phpunit": "~4.8.36 || ^5.7.27 || ^6.5.14 || ^7.5.20 || ^8.5.8 || ^9.3.10"
+ },
+ "suggest": {
+ "laminas/laminas-httphandlerrunner": "Emit PSR-7 responses"
+ },
+ "type": "library",
+ "autoload": {
+ "files": [
+ "src/functions_include.php"
+ ],
+ "psr-4": {
+ "GuzzleHttp\\Psr7\\": "src/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Graham Campbell",
+ "email": "hello@gjcampbell.co.uk",
+ "homepage": "https://github.com/GrahamCampbell"
+ },
+ {
+ "name": "Michael Dowling",
+ "email": "mtdowling@gmail.com",
+ "homepage": "https://github.com/mtdowling"
+ },
+ {
+ "name": "George Mponos",
+ "email": "gmponos@gmail.com",
+ "homepage": "https://github.com/gmponos"
+ },
+ {
+ "name": "Tobias Nyholm",
+ "email": "tobias.nyholm@gmail.com",
+ "homepage": "https://github.com/Nyholm"
+ },
+ {
+ "name": "Márk Sági-Kazár",
+ "email": "mark.sagikazar@gmail.com",
+ "homepage": "https://github.com/sagikazarmark"
+ },
+ {
+ "name": "Tobias Schultze",
+ "email": "webmaster@tubo-world.de",
+ "homepage": "https://github.com/Tobion"
+ }
+ ],
+ "description": "PSR-7 message implementation that also provides common utility methods",
+ "keywords": [
+ "http",
+ "message",
+ "psr-7",
+ "request",
+ "response",
+ "stream",
+ "uri",
+ "url"
+ ],
+ "support": {
+ "issues": "https://github.com/guzzle/psr7/issues",
+ "source": "https://github.com/guzzle/psr7/tree/1.9.1"
+ },
+ "funding": [
+ {
+ "url": "https://github.com/GrahamCampbell",
+ "type": "github"
+ },
+ {
+ "url": "https://github.com/Nyholm",
+ "type": "github"
+ },
+ {
+ "url": "https://tidelift.com/funding/github/packagist/guzzlehttp/psr7",
+ "type": "tidelift"
+ }
+ ],
+ "time": "2023-04-17T16:00:37+00:00"
+ },
+ {
+ "name": "hashids/hashids",
+ "version": "2.0.4",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/vinkla/hashids.git",
+ "reference": "7a945a5192d4a5c8888364970feece9bc26179df"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/vinkla/hashids/zipball/7a945a5192d4a5c8888364970feece9bc26179df",
+ "reference": "7a945a5192d4a5c8888364970feece9bc26179df",
+ "shasum": ""
+ },
+ "require": {
+ "php": "^5.6.4 || ^7.0"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "^5.7 || ^6.3"
+ },
+ "suggest": {
+ "ext-bcmatch": "Required to use BC Math arbitrary precision mathematics (*).",
+ "ext-gmp": "Required to use GNU multiple precision mathematics (*)."
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "2.1-dev"
+ }
},
- "type": "think-framework",
"autoload": {
"psr-4": {
- "think\\": "library/think"
+ "Hashids\\": "src/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Ivan Akimov",
+ "email": "ivan@barreleye.com",
+ "homepage": "https://twitter.com/IvanAkimov"
+ },
+ {
+ "name": "Vincent Klaiber",
+ "email": "hello@vinkla.com",
+ "homepage": "https://vinkla.com"
+ }
+ ],
+ "description": "Generate short, unique, non-sequential ids (like YouTube and Bitly) from numbers",
+ "homepage": "http://hashids.org/php",
+ "keywords": [
+ "bitly",
+ "decode",
+ "encode",
+ "hash",
+ "hashid",
+ "hashids",
+ "ids",
+ "obfuscate",
+ "youtube"
+ ],
+ "support": {
+ "issues": "https://github.com/vinkla/hashids/issues",
+ "source": "https://github.com/vinkla/hashids/tree/2.0.4"
+ },
+ "time": "2017-10-28T11:24:20+00:00"
+ },
+ {
+ "name": "khanamiryan/qrcode-detector-decoder",
+ "version": "1.0.6",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/khanamiryan/php-qrcode-detector-decoder.git",
+ "reference": "45326fb83a2a375065dbb3a134b5b8a5872da569"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/khanamiryan/php-qrcode-detector-decoder/zipball/45326fb83a2a375065dbb3a134b5b8a5872da569",
+ "reference": "45326fb83a2a375065dbb3a134b5b8a5872da569",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=5.6"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "^5.7 | ^7.5 | ^8.0 | ^9.0",
+ "rector/rector": "^0.13.6",
+ "symplify/easy-coding-standard": "^11.0"
+ },
+ "type": "library",
+ "autoload": {
+ "files": [
+ "lib/Common/customFunctions.php"
+ ],
+ "psr-4": {
+ "Zxing\\": "lib/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT",
+ "Apache-2.0"
+ ],
+ "authors": [
+ {
+ "name": "Ashot Khanamiryan",
+ "email": "a.khanamiryan@gmail.com",
+ "homepage": "https://github.com/khanamiryan",
+ "role": "Developer"
+ }
+ ],
+ "description": "QR code decoder / reader",
+ "homepage": "https://github.com/khanamiryan/php-qrcode-detector-decoder/",
+ "keywords": [
+ "barcode",
+ "qr",
+ "zxing"
+ ],
+ "support": {
+ "issues": "https://github.com/khanamiryan/php-qrcode-detector-decoder/issues",
+ "source": "https://github.com/khanamiryan/php-qrcode-detector-decoder/tree/1.0.6"
+ },
+ "time": "2022-06-29T09:25:13+00:00"
+ },
+ {
+ "name": "lizhichao/word",
+ "version": "v2.1",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/lizhichao/VicWord.git",
+ "reference": "f17172d45f505e7140da0bde2103defc13255326"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/lizhichao/VicWord/zipball/f17172d45f505e7140da0bde2103defc13255326",
+ "reference": "f17172d45f505e7140da0bde2103defc13255326",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=5.6.0"
+ },
+ "type": "library",
+ "autoload": {
+ "psr-4": {
+ "Lizhichao\\Word\\": "Lib"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"Apache-2.0"
],
+ "authors": [
+ {
+ "name": "tanszhe",
+ "email": "1018595261@qq.com"
+ }
+ ],
+ "description": "This is a participle library",
+ "support": {
+ "issues": "https://github.com/lizhichao/VicWord/issues",
+ "source": "https://github.com/lizhichao/VicWord/tree/master"
+ },
+ "time": "2020-07-30T07:33:06+00:00"
+ },
+ {
+ "name": "maennchen/zipstream-php",
+ "version": "2.2.6",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/maennchen/ZipStream-PHP.git",
+ "reference": "30ad6f93cf3efe4192bc7a4c9cad11ff8f4f237f"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/maennchen/ZipStream-PHP/zipball/30ad6f93cf3efe4192bc7a4c9cad11ff8f4f237f",
+ "reference": "30ad6f93cf3efe4192bc7a4c9cad11ff8f4f237f",
+ "shasum": ""
+ },
+ "require": {
+ "myclabs/php-enum": "^1.5",
+ "php": "^7.4 || ^8.0",
+ "psr/http-message": "^1.0",
+ "symfony/polyfill-mbstring": "^1.0"
+ },
+ "require-dev": {
+ "ext-zip": "*",
+ "friendsofphp/php-cs-fixer": "^3.9",
+ "guzzlehttp/guzzle": "^6.5.3 || ^7.2.0",
+ "mikey179/vfsstream": "^1.6",
+ "php-coveralls/php-coveralls": "^2.4",
+ "phpunit/phpunit": "^8.5.8 || ^9.4.2",
+ "vimeo/psalm": "^4.1"
+ },
+ "type": "library",
+ "autoload": {
+ "psr-4": {
+ "ZipStream\\": "src/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Paul Duncan",
+ "email": "pabs@pablotron.org"
+ },
+ {
+ "name": "Jonatan Männchen",
+ "email": "jonatan@maennchen.ch"
+ },
+ {
+ "name": "Jesse Donat",
+ "email": "donatj@gmail.com"
+ },
+ {
+ "name": "András Kolesár",
+ "email": "kolesar@kolesar.hu"
+ }
+ ],
+ "description": "ZipStream is a library for dynamically streaming dynamic zip files from PHP without writing to the disk at all on the server.",
+ "keywords": [
+ "stream",
+ "zip"
+ ],
+ "support": {
+ "issues": "https://github.com/maennchen/ZipStream-PHP/issues",
+ "source": "https://github.com/maennchen/ZipStream-PHP/tree/2.2.6"
+ },
+ "funding": [
+ {
+ "url": "https://github.com/maennchen",
+ "type": "github"
+ },
+ {
+ "url": "https://opencollective.com/zipstream",
+ "type": "open_collective"
+ }
+ ],
+ "time": "2022-11-25T18:57:19+00:00"
+ },
+ {
+ "name": "markbaker/complex",
+ "version": "3.0.2",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/MarkBaker/PHPComplex.git",
+ "reference": "95c56caa1cf5c766ad6d65b6344b807c1e8405b9"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/MarkBaker/PHPComplex/zipball/95c56caa1cf5c766ad6d65b6344b807c1e8405b9",
+ "reference": "95c56caa1cf5c766ad6d65b6344b807c1e8405b9",
+ "shasum": ""
+ },
+ "require": {
+ "php": "^7.2 || ^8.0"
+ },
+ "require-dev": {
+ "dealerdirect/phpcodesniffer-composer-installer": "dev-master",
+ "phpcompatibility/php-compatibility": "^9.3",
+ "phpunit/phpunit": "^7.0 || ^8.0 || ^9.0",
+ "squizlabs/php_codesniffer": "^3.7"
+ },
+ "type": "library",
+ "autoload": {
+ "psr-4": {
+ "Complex\\": "classes/src/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Mark Baker",
+ "email": "mark@lange.demon.co.uk"
+ }
+ ],
+ "description": "PHP Class for working with complex numbers",
+ "homepage": "https://github.com/MarkBaker/PHPComplex",
+ "keywords": [
+ "complex",
+ "mathematics"
+ ],
+ "support": {
+ "issues": "https://github.com/MarkBaker/PHPComplex/issues",
+ "source": "https://github.com/MarkBaker/PHPComplex/tree/3.0.2"
+ },
+ "time": "2022-12-06T16:21:08+00:00"
+ },
+ {
+ "name": "markbaker/matrix",
+ "version": "3.0.1",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/MarkBaker/PHPMatrix.git",
+ "reference": "728434227fe21be27ff6d86621a1b13107a2562c"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/MarkBaker/PHPMatrix/zipball/728434227fe21be27ff6d86621a1b13107a2562c",
+ "reference": "728434227fe21be27ff6d86621a1b13107a2562c",
+ "shasum": ""
+ },
+ "require": {
+ "php": "^7.1 || ^8.0"
+ },
+ "require-dev": {
+ "dealerdirect/phpcodesniffer-composer-installer": "dev-master",
+ "phpcompatibility/php-compatibility": "^9.3",
+ "phpdocumentor/phpdocumentor": "2.*",
+ "phploc/phploc": "^4.0",
+ "phpmd/phpmd": "2.*",
+ "phpunit/phpunit": "^7.0 || ^8.0 || ^9.0",
+ "sebastian/phpcpd": "^4.0",
+ "squizlabs/php_codesniffer": "^3.7"
+ },
+ "type": "library",
+ "autoload": {
+ "psr-4": {
+ "Matrix\\": "classes/src/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Mark Baker",
+ "email": "mark@demon-angel.eu"
+ }
+ ],
+ "description": "PHP Class for working with matrices",
+ "homepage": "https://github.com/MarkBaker/PHPMatrix",
+ "keywords": [
+ "mathematics",
+ "matrix",
+ "vector"
+ ],
+ "support": {
+ "issues": "https://github.com/MarkBaker/PHPMatrix/issues",
+ "source": "https://github.com/MarkBaker/PHPMatrix/tree/3.0.1"
+ },
+ "time": "2022-12-02T22:17:43+00:00"
+ },
+ {
+ "name": "monolog/monolog",
+ "version": "1.27.1",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/Seldaek/monolog.git",
+ "reference": "904713c5929655dc9b97288b69cfeedad610c9a1"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/Seldaek/monolog/zipball/904713c5929655dc9b97288b69cfeedad610c9a1",
+ "reference": "904713c5929655dc9b97288b69cfeedad610c9a1",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=5.3.0",
+ "psr/log": "~1.0"
+ },
+ "provide": {
+ "psr/log-implementation": "1.0.0"
+ },
+ "require-dev": {
+ "aws/aws-sdk-php": "^2.4.9 || ^3.0",
+ "doctrine/couchdb": "~1.0@dev",
+ "graylog2/gelf-php": "~1.0",
+ "php-amqplib/php-amqplib": "~2.4",
+ "php-console/php-console": "^3.1.3",
+ "phpstan/phpstan": "^0.12.59",
+ "phpunit/phpunit": "~4.5",
+ "ruflin/elastica": ">=0.90 <3.0",
+ "sentry/sentry": "^0.13",
+ "swiftmailer/swiftmailer": "^5.3|^6.0"
+ },
+ "suggest": {
+ "aws/aws-sdk-php": "Allow sending log messages to AWS services like DynamoDB",
+ "doctrine/couchdb": "Allow sending log messages to a CouchDB server",
+ "ext-amqp": "Allow sending log messages to an AMQP server (1.0+ required)",
+ "ext-mongo": "Allow sending log messages to a MongoDB server",
+ "graylog2/gelf-php": "Allow sending log messages to a GrayLog2 server",
+ "mongodb/mongodb": "Allow sending log messages to a MongoDB server via PHP Driver",
+ "php-amqplib/php-amqplib": "Allow sending log messages to an AMQP server using php-amqplib",
+ "php-console/php-console": "Allow sending log messages to Google Chrome",
+ "rollbar/rollbar": "Allow sending log messages to Rollbar",
+ "ruflin/elastica": "Allow sending log messages to an Elastic Search server",
+ "sentry/sentry": "Allow sending log messages to a Sentry server"
+ },
+ "type": "library",
+ "autoload": {
+ "psr-4": {
+ "Monolog\\": "src/Monolog"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Jordi Boggiano",
+ "email": "j.boggiano@seld.be",
+ "homepage": "http://seld.be"
+ }
+ ],
+ "description": "Sends your logs to files, sockets, inboxes, databases and various web services",
+ "homepage": "http://github.com/Seldaek/monolog",
+ "keywords": [
+ "log",
+ "logging",
+ "psr-3"
+ ],
+ "support": {
+ "issues": "https://github.com/Seldaek/monolog/issues",
+ "source": "https://github.com/Seldaek/monolog/tree/1.27.1"
+ },
+ "funding": [
+ {
+ "url": "https://github.com/Seldaek",
+ "type": "github"
+ },
+ {
+ "url": "https://tidelift.com/funding/github/packagist/monolog/monolog",
+ "type": "tidelift"
+ }
+ ],
+ "time": "2022-06-09T08:53:42+00:00"
+ },
+ {
+ "name": "myclabs/php-enum",
+ "version": "1.8.5",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/myclabs/php-enum.git",
+ "reference": "e7be26966b7398204a234f8673fdad5ac6277802"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/myclabs/php-enum/zipball/e7be26966b7398204a234f8673fdad5ac6277802",
+ "reference": "e7be26966b7398204a234f8673fdad5ac6277802",
+ "shasum": ""
+ },
+ "require": {
+ "ext-json": "*",
+ "php": "^7.3 || ^8.0"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "^9.5",
+ "squizlabs/php_codesniffer": "1.*",
+ "vimeo/psalm": "^4.6.2 || ^5.2"
+ },
+ "type": "library",
+ "autoload": {
+ "psr-4": {
+ "MyCLabs\\Enum\\": "src/"
+ },
+ "classmap": [
+ "stubs/Stringable.php"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "PHP Enum contributors",
+ "homepage": "https://github.com/myclabs/php-enum/graphs/contributors"
+ }
+ ],
+ "description": "PHP Enum implementation",
+ "homepage": "https://github.com/myclabs/php-enum",
+ "keywords": [
+ "enum"
+ ],
+ "support": {
+ "issues": "https://github.com/myclabs/php-enum/issues",
+ "source": "https://github.com/myclabs/php-enum/tree/1.8.5"
+ },
+ "funding": [
+ {
+ "url": "https://github.com/mnapoli",
+ "type": "github"
+ },
+ {
+ "url": "https://tidelift.com/funding/github/packagist/myclabs/php-enum",
+ "type": "tidelift"
+ }
+ ],
+ "time": "2025-01-14T11:49:03+00:00"
+ },
+ {
+ "name": "overtrue/socialite",
+ "version": "2.0.24",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/overtrue/socialite.git",
+ "reference": "ee7e7b000ec7d64f2b8aba1f6a2eec5cdf3f8bec"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/overtrue/socialite/zipball/ee7e7b000ec7d64f2b8aba1f6a2eec5cdf3f8bec",
+ "reference": "ee7e7b000ec7d64f2b8aba1f6a2eec5cdf3f8bec",
+ "shasum": ""
+ },
+ "require": {
+ "ext-json": "*",
+ "guzzlehttp/guzzle": "^5.0|^6.0|^7.0",
+ "php": ">=5.6",
+ "symfony/http-foundation": "^2.7|^3.0|^4.0|^5.0"
+ },
+ "require-dev": {
+ "mockery/mockery": "~1.2",
+ "phpunit/phpunit": "^6.0|^7.0|^8.0|^9.0"
+ },
+ "type": "library",
+ "autoload": {
+ "psr-4": {
+ "Overtrue\\Socialite\\": "src/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "overtrue",
+ "email": "anzhengchao@gmail.com"
+ }
+ ],
+ "description": "A collection of OAuth 2 packages that extracts from laravel/socialite.",
+ "keywords": [
+ "login",
+ "oauth",
+ "qq",
+ "social",
+ "wechat",
+ "weibo"
+ ],
+ "support": {
+ "issues": "https://github.com/overtrue/socialite/issues",
+ "source": "https://github.com/overtrue/socialite/tree/2.0.24"
+ },
+ "funding": [
+ {
+ "url": "https://www.patreon.com/overtrue",
+ "type": "patreon"
+ }
+ ],
+ "time": "2021-05-13T16:04:48+00:00"
+ },
+ {
+ "name": "overtrue/wechat",
+ "version": "4.9.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/w7corp/easywechat.git",
+ "reference": "92791f5d957269c633b9aa175f842f6006f945b1"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/w7corp/easywechat/zipball/92791f5d957269c633b9aa175f842f6006f945b1",
+ "reference": "92791f5d957269c633b9aa175f842f6006f945b1",
+ "shasum": ""
+ },
+ "require": {
+ "easywechat-composer/easywechat-composer": "^1.1",
+ "ext-fileinfo": "*",
+ "ext-openssl": "*",
+ "ext-simplexml": "*",
+ "guzzlehttp/guzzle": "^6.2 || ^7.0",
+ "monolog/monolog": "^1.22 || ^2.0",
+ "overtrue/socialite": "~2.0",
+ "php": ">=7.2",
+ "pimple/pimple": "^3.0",
+ "psr/simple-cache": "^1.0",
+ "symfony/cache": "^3.3 || ^4.3 || ^5.0",
+ "symfony/event-dispatcher": "^4.3 || ^5.0",
+ "symfony/http-foundation": "^2.7 || ^3.0 || ^4.0 || ^5.0",
+ "symfony/psr-http-message-bridge": "^0.3 || ^1.0 || ^2.0"
+ },
+ "require-dev": {
+ "friendsofphp/php-cs-fixer": "^2.15",
+ "mikey179/vfsstream": "^1.6",
+ "mockery/mockery": "^1.2.3",
+ "phpstan/phpstan": "^0.12.0",
+ "phpunit/phpunit": "^7.5"
+ },
+ "type": "library",
+ "autoload": {
+ "files": [
+ "src/Kernel/Support/Helpers.php",
+ "src/Kernel/Helpers.php"
+ ],
+ "psr-4": {
+ "EasyWeChat\\": "src/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "overtrue",
+ "email": "anzhengchao@gmail.com"
+ }
+ ],
+ "description": "微信SDK",
+ "keywords": [
+ "easywechat",
+ "sdk",
+ "wechat",
+ "weixin",
+ "weixin-sdk"
+ ],
+ "support": {
+ "issues": "https://github.com/w7corp/easywechat/issues",
+ "source": "https://github.com/w7corp/easywechat/tree/4.9.0"
+ },
+ "funding": [
+ {
+ "url": "https://github.com/overtrue",
+ "type": "github"
+ }
+ ],
+ "abandoned": "w7corp/easywechat",
+ "time": "2023-04-28T03:30:34+00:00"
+ },
+ {
+ "name": "phpoffice/phpspreadsheet",
+ "version": "1.30.1",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/PHPOffice/PhpSpreadsheet.git",
+ "reference": "fa8257a579ec623473eabfe49731de5967306c4c"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/PHPOffice/PhpSpreadsheet/zipball/fa8257a579ec623473eabfe49731de5967306c4c",
+ "reference": "fa8257a579ec623473eabfe49731de5967306c4c",
+ "shasum": ""
+ },
+ "require": {
+ "composer/pcre": "^1||^2||^3",
+ "ext-ctype": "*",
+ "ext-dom": "*",
+ "ext-fileinfo": "*",
+ "ext-gd": "*",
+ "ext-iconv": "*",
+ "ext-libxml": "*",
+ "ext-mbstring": "*",
+ "ext-simplexml": "*",
+ "ext-xml": "*",
+ "ext-xmlreader": "*",
+ "ext-xmlwriter": "*",
+ "ext-zip": "*",
+ "ext-zlib": "*",
+ "ezyang/htmlpurifier": "^4.15",
+ "maennchen/zipstream-php": "^2.1 || ^3.0",
+ "markbaker/complex": "^3.0",
+ "markbaker/matrix": "^3.0",
+ "php": ">=7.4.0 <8.5.0",
+ "psr/http-client": "^1.0",
+ "psr/http-factory": "^1.0",
+ "psr/simple-cache": "^1.0 || ^2.0 || ^3.0"
+ },
+ "require-dev": {
+ "dealerdirect/phpcodesniffer-composer-installer": "dev-main",
+ "dompdf/dompdf": "^1.0 || ^2.0 || ^3.0",
+ "friendsofphp/php-cs-fixer": "^3.2",
+ "mitoteam/jpgraph": "^10.3",
+ "mpdf/mpdf": "^8.1.1",
+ "phpcompatibility/php-compatibility": "^9.3",
+ "phpstan/phpstan": "^1.1",
+ "phpstan/phpstan-phpunit": "^1.0",
+ "phpunit/phpunit": "^8.5 || ^9.0",
+ "squizlabs/php_codesniffer": "^3.7",
+ "tecnickcom/tcpdf": "^6.5"
+ },
+ "suggest": {
+ "dompdf/dompdf": "Option for rendering PDF with PDF Writer",
+ "ext-intl": "PHP Internationalization Functions",
+ "mitoteam/jpgraph": "Option for rendering charts, or including charts with PDF or HTML Writers",
+ "mpdf/mpdf": "Option for rendering PDF with PDF Writer",
+ "tecnickcom/tcpdf": "Option for rendering PDF with PDF Writer"
+ },
+ "type": "library",
+ "autoload": {
+ "psr-4": {
+ "PhpOffice\\PhpSpreadsheet\\": "src/PhpSpreadsheet"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Maarten Balliauw",
+ "homepage": "https://blog.maartenballiauw.be"
+ },
+ {
+ "name": "Mark Baker",
+ "homepage": "https://markbakeruk.net"
+ },
+ {
+ "name": "Franck Lefevre",
+ "homepage": "https://rootslabs.net"
+ },
+ {
+ "name": "Erik Tilt"
+ },
+ {
+ "name": "Adrien Crivelli"
+ }
+ ],
+ "description": "PHPSpreadsheet - Read, Create and Write Spreadsheet documents in PHP - Spreadsheet engine",
+ "homepage": "https://github.com/PHPOffice/PhpSpreadsheet",
+ "keywords": [
+ "OpenXML",
+ "excel",
+ "gnumeric",
+ "ods",
+ "php",
+ "spreadsheet",
+ "xls",
+ "xlsx"
+ ],
+ "support": {
+ "issues": "https://github.com/PHPOffice/PhpSpreadsheet/issues",
+ "source": "https://github.com/PHPOffice/PhpSpreadsheet/tree/1.30.1"
+ },
+ "time": "2025-10-26T16:01:04+00:00"
+ },
+ {
+ "name": "phrity/net-uri",
+ "version": "1.3.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/sirn-se/phrity-net-uri.git",
+ "reference": "3f458e0c4d1ddc0e218d7a5b9420127c63925f43"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/sirn-se/phrity-net-uri/zipball/3f458e0c4d1ddc0e218d7a5b9420127c63925f43",
+ "reference": "3f458e0c4d1ddc0e218d7a5b9420127c63925f43",
+ "shasum": ""
+ },
+ "require": {
+ "php": "^7.4 | ^8.0",
+ "psr/http-factory": "^1.0",
+ "psr/http-message": "^1.0 | ^2.0"
+ },
+ "require-dev": {
+ "php-coveralls/php-coveralls": "^2.0",
+ "phpunit/phpunit": "^9.0 | ^10.0",
+ "squizlabs/php_codesniffer": "^3.0"
+ },
+ "type": "library",
+ "autoload": {
+ "psr-4": {
+ "Phrity\\Net\\": "src/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Sören Jensen",
+ "email": "sirn@sirn.se",
+ "homepage": "https://phrity.sirn.se"
+ }
+ ],
+ "description": "PSR-7 Uri and PSR-17 UriFactory implementation",
+ "homepage": "https://phrity.sirn.se/net-uri",
+ "keywords": [
+ "psr-17",
+ "psr-7",
+ "uri",
+ "uri factory"
+ ],
+ "support": {
+ "issues": "https://github.com/sirn-se/phrity-net-uri/issues",
+ "source": "https://github.com/sirn-se/phrity-net-uri/tree/1.3.0"
+ },
+ "time": "2023-08-21T10:33:06+00:00"
+ },
+ {
+ "name": "phrity/util-errorhandler",
+ "version": "1.1.1",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/sirn-se/phrity-util-errorhandler.git",
+ "reference": "483228156e06673963902b1cc1e6bd9541ab4d5e"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/sirn-se/phrity-util-errorhandler/zipball/483228156e06673963902b1cc1e6bd9541ab4d5e",
+ "reference": "483228156e06673963902b1cc1e6bd9541ab4d5e",
+ "shasum": ""
+ },
+ "require": {
+ "php": "^7.4 | ^8.0"
+ },
+ "require-dev": {
+ "php-coveralls/php-coveralls": "^2.0",
+ "phpunit/phpunit": "^9.0 | ^10.0 | ^11.0",
+ "squizlabs/php_codesniffer": "^3.5"
+ },
+ "type": "library",
+ "autoload": {
+ "psr-4": {
+ "Phrity\\Util\\": "src/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Sören Jensen",
+ "email": "sirn@sirn.se",
+ "homepage": "https://phrity.sirn.se"
+ }
+ ],
+ "description": "Inline error handler; catch and resolve errors for code block.",
+ "homepage": "https://phrity.sirn.se/util-errorhandler",
+ "keywords": [
+ "error",
+ "warning"
+ ],
+ "support": {
+ "issues": "https://github.com/sirn-se/phrity-util-errorhandler/issues",
+ "source": "https://github.com/sirn-se/phrity-util-errorhandler/tree/1.1.1"
+ },
+ "time": "2024-09-12T06:49:16+00:00"
+ },
+ {
+ "name": "pimple/pimple",
+ "version": "v3.6.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/silexphp/Pimple.git",
+ "reference": "a70f552d338f9266eec6606c1f0b324da5514c96"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/silexphp/Pimple/zipball/a70f552d338f9266eec6606c1f0b324da5514c96",
+ "reference": "a70f552d338f9266eec6606c1f0b324da5514c96",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=7.2.5",
+ "psr/container": "^1.1 || ^2.0"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "*"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "3.4.x-dev"
+ }
+ },
+ "autoload": {
+ "psr-0": {
+ "Pimple": "src/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Fabien Potencier",
+ "email": "fabien@symfony.com"
+ }
+ ],
+ "description": "Pimple, a simple Dependency Injection Container",
+ "homepage": "https://pimple.symfony.com",
+ "keywords": [
+ "container",
+ "dependency injection"
+ ],
+ "support": {
+ "source": "https://github.com/silexphp/Pimple/tree/v3.6.0"
+ },
+ "time": "2025-11-12T12:31:38+00:00"
+ },
+ {
+ "name": "psr/cache",
+ "version": "1.0.1",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/php-fig/cache.git",
+ "reference": "d11b50ad223250cf17b86e38383413f5a6764bf8"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/php-fig/cache/zipball/d11b50ad223250cf17b86e38383413f5a6764bf8",
+ "reference": "d11b50ad223250cf17b86e38383413f5a6764bf8",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=5.3.0"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "1.0.x-dev"
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "Psr\\Cache\\": "src/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "PHP-FIG",
+ "homepage": "http://www.php-fig.org/"
+ }
+ ],
+ "description": "Common interface for caching libraries",
+ "keywords": [
+ "cache",
+ "psr",
+ "psr-6"
+ ],
+ "support": {
+ "source": "https://github.com/php-fig/cache/tree/master"
+ },
+ "time": "2016-08-06T20:24:11+00:00"
+ },
+ {
+ "name": "psr/container",
+ "version": "2.0.2",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/php-fig/container.git",
+ "reference": "c71ecc56dfe541dbd90c5360474fbc405f8d5963"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/php-fig/container/zipball/c71ecc56dfe541dbd90c5360474fbc405f8d5963",
+ "reference": "c71ecc56dfe541dbd90c5360474fbc405f8d5963",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=7.4.0"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "2.0.x-dev"
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "Psr\\Container\\": "src/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "PHP-FIG",
+ "homepage": "https://www.php-fig.org/"
+ }
+ ],
+ "description": "Common Container Interface (PHP FIG PSR-11)",
+ "homepage": "https://github.com/php-fig/container",
+ "keywords": [
+ "PSR-11",
+ "container",
+ "container-interface",
+ "container-interop",
+ "psr"
+ ],
+ "support": {
+ "issues": "https://github.com/php-fig/container/issues",
+ "source": "https://github.com/php-fig/container/tree/2.0.2"
+ },
+ "time": "2021-11-05T16:47:00+00:00"
+ },
+ {
+ "name": "psr/event-dispatcher",
+ "version": "1.0.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/php-fig/event-dispatcher.git",
+ "reference": "dbefd12671e8a14ec7f180cab83036ed26714bb0"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/php-fig/event-dispatcher/zipball/dbefd12671e8a14ec7f180cab83036ed26714bb0",
+ "reference": "dbefd12671e8a14ec7f180cab83036ed26714bb0",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=7.2.0"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "1.0.x-dev"
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "Psr\\EventDispatcher\\": "src/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "PHP-FIG",
+ "homepage": "http://www.php-fig.org/"
+ }
+ ],
+ "description": "Standard interfaces for event handling.",
+ "keywords": [
+ "events",
+ "psr",
+ "psr-14"
+ ],
+ "support": {
+ "issues": "https://github.com/php-fig/event-dispatcher/issues",
+ "source": "https://github.com/php-fig/event-dispatcher/tree/1.0.0"
+ },
+ "time": "2019-01-08T18:20:26+00:00"
+ },
+ {
+ "name": "psr/http-client",
+ "version": "1.0.3",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/php-fig/http-client.git",
+ "reference": "bb5906edc1c324c9a05aa0873d40117941e5fa90"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/php-fig/http-client/zipball/bb5906edc1c324c9a05aa0873d40117941e5fa90",
+ "reference": "bb5906edc1c324c9a05aa0873d40117941e5fa90",
+ "shasum": ""
+ },
+ "require": {
+ "php": "^7.0 || ^8.0",
+ "psr/http-message": "^1.0 || ^2.0"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "1.0.x-dev"
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "Psr\\Http\\Client\\": "src/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "PHP-FIG",
+ "homepage": "https://www.php-fig.org/"
+ }
+ ],
+ "description": "Common interface for HTTP clients",
+ "homepage": "https://github.com/php-fig/http-client",
+ "keywords": [
+ "http",
+ "http-client",
+ "psr",
+ "psr-18"
+ ],
+ "support": {
+ "source": "https://github.com/php-fig/http-client"
+ },
+ "time": "2023-09-23T14:17:50+00:00"
+ },
+ {
+ "name": "psr/http-factory",
+ "version": "1.1.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/php-fig/http-factory.git",
+ "reference": "2b4765fddfe3b508ac62f829e852b1501d3f6e8a"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/php-fig/http-factory/zipball/2b4765fddfe3b508ac62f829e852b1501d3f6e8a",
+ "reference": "2b4765fddfe3b508ac62f829e852b1501d3f6e8a",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=7.1",
+ "psr/http-message": "^1.0 || ^2.0"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "1.0.x-dev"
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "Psr\\Http\\Message\\": "src/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "PHP-FIG",
+ "homepage": "https://www.php-fig.org/"
+ }
+ ],
+ "description": "PSR-17: Common interfaces for PSR-7 HTTP message factories",
+ "keywords": [
+ "factory",
+ "http",
+ "message",
+ "psr",
+ "psr-17",
+ "psr-7",
+ "request",
+ "response"
+ ],
+ "support": {
+ "source": "https://github.com/php-fig/http-factory"
+ },
+ "time": "2024-04-15T12:06:14+00:00"
+ },
+ {
+ "name": "psr/http-message",
+ "version": "1.1",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/php-fig/http-message.git",
+ "reference": "cb6ce4845ce34a8ad9e68117c10ee90a29919eba"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/php-fig/http-message/zipball/cb6ce4845ce34a8ad9e68117c10ee90a29919eba",
+ "reference": "cb6ce4845ce34a8ad9e68117c10ee90a29919eba",
+ "shasum": ""
+ },
+ "require": {
+ "php": "^7.2 || ^8.0"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "1.1.x-dev"
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "Psr\\Http\\Message\\": "src/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "PHP-FIG",
+ "homepage": "http://www.php-fig.org/"
+ }
+ ],
+ "description": "Common interface for HTTP messages",
+ "homepage": "https://github.com/php-fig/http-message",
+ "keywords": [
+ "http",
+ "http-message",
+ "psr",
+ "psr-7",
+ "request",
+ "response"
+ ],
+ "support": {
+ "source": "https://github.com/php-fig/http-message/tree/1.1"
+ },
+ "time": "2023-04-04T09:50:52+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"
+ ],
+ "support": {
+ "source": "https://github.com/php-fig/log/tree/1.1.4"
+ },
+ "time": "2021-05-03T11:20:27+00:00"
+ },
+ {
+ "name": "psr/simple-cache",
+ "version": "1.0.1",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/php-fig/simple-cache.git",
+ "reference": "408d5eafb83c57f6365a3ca330ff23aa4a5fa39b"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/php-fig/simple-cache/zipball/408d5eafb83c57f6365a3ca330ff23aa4a5fa39b",
+ "reference": "408d5eafb83c57f6365a3ca330ff23aa4a5fa39b",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=5.3.0"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "1.0.x-dev"
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "Psr\\SimpleCache\\": "src/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "PHP-FIG",
+ "homepage": "http://www.php-fig.org/"
+ }
+ ],
+ "description": "Common interfaces for simple caching",
+ "keywords": [
+ "cache",
+ "caching",
+ "psr",
+ "psr-16",
+ "simple-cache"
+ ],
+ "support": {
+ "source": "https://github.com/php-fig/simple-cache/tree/master"
+ },
+ "time": "2017-10-23T01:57:42+00:00"
+ },
+ {
+ "name": "ralouphie/getallheaders",
+ "version": "3.0.3",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/ralouphie/getallheaders.git",
+ "reference": "120b605dfeb996808c31b6477290a714d356e822"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/ralouphie/getallheaders/zipball/120b605dfeb996808c31b6477290a714d356e822",
+ "reference": "120b605dfeb996808c31b6477290a714d356e822",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=5.6"
+ },
+ "require-dev": {
+ "php-coveralls/php-coveralls": "^2.1",
+ "phpunit/phpunit": "^5 || ^6.5"
+ },
+ "type": "library",
+ "autoload": {
+ "files": [
+ "src/getallheaders.php"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Ralph Khattar",
+ "email": "ralph.khattar@gmail.com"
+ }
+ ],
+ "description": "A polyfill for getallheaders.",
+ "support": {
+ "issues": "https://github.com/ralouphie/getallheaders/issues",
+ "source": "https://github.com/ralouphie/getallheaders/tree/develop"
+ },
+ "time": "2019-03-08T08:55:37+00:00"
+ },
+ {
+ "name": "symfony/cache",
+ "version": "v4.3.11",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/symfony/cache.git",
+ "reference": "8794ccf68ac341fc19311919d2287f7557bfccba"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/symfony/cache/zipball/8794ccf68ac341fc19311919d2287f7557bfccba",
+ "reference": "8794ccf68ac341fc19311919d2287f7557bfccba",
+ "shasum": ""
+ },
+ "require": {
+ "php": "^7.1.3",
+ "psr/cache": "~1.0",
+ "psr/log": "~1.0",
+ "symfony/cache-contracts": "^1.1",
+ "symfony/service-contracts": "^1.1",
+ "symfony/var-exporter": "^4.2"
+ },
+ "conflict": {
+ "doctrine/dbal": "<2.5",
+ "symfony/dependency-injection": "<3.4",
+ "symfony/var-dumper": "<3.4"
+ },
+ "provide": {
+ "psr/cache-implementation": "1.0",
+ "psr/simple-cache-implementation": "1.0",
+ "symfony/cache-implementation": "1.0"
+ },
+ "require-dev": {
+ "cache/integration-tests": "dev-master",
+ "doctrine/cache": "~1.6",
+ "doctrine/dbal": "~2.5",
+ "predis/predis": "~1.1",
+ "psr/simple-cache": "^1.0",
+ "symfony/config": "~4.2",
+ "symfony/dependency-injection": "~3.4|~4.1",
+ "symfony/var-dumper": "^4.1.1"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "4.3-dev"
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "Symfony\\Component\\Cache\\": ""
+ },
+ "exclude-from-classmap": [
+ "/Tests/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Nicolas Grekas",
+ "email": "p@tchwork.com"
+ },
+ {
+ "name": "Symfony Community",
+ "homepage": "https://symfony.com/contributors"
+ }
+ ],
+ "description": "Symfony Cache component with PSR-6, PSR-16, and tags",
+ "homepage": "https://symfony.com",
+ "keywords": [
+ "caching",
+ "psr6"
+ ],
+ "support": {
+ "source": "https://github.com/symfony/cache/tree/v4.3.11"
+ },
+ "time": "2020-01-27T09:15:09+00:00"
+ },
+ {
+ "name": "symfony/cache-contracts",
+ "version": "v1.10.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/symfony/cache-contracts.git",
+ "reference": "a872a66e0bf7bac179c89bc96c7098bef1949f81"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/symfony/cache-contracts/zipball/a872a66e0bf7bac179c89bc96c7098bef1949f81",
+ "reference": "a872a66e0bf7bac179c89bc96c7098bef1949f81",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=7.1.3",
+ "psr/cache": "^1.0|^2.0|^3.0"
+ },
+ "suggest": {
+ "symfony/cache-implementation": ""
+ },
+ "type": "library",
+ "extra": {
+ "thanks": {
+ "url": "https://github.com/symfony/contracts",
+ "name": "symfony/contracts"
+ },
+ "branch-alias": {
+ "dev-main": "1.1-dev"
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "Symfony\\Contracts\\Cache\\": ""
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Nicolas Grekas",
+ "email": "p@tchwork.com"
+ },
+ {
+ "name": "Symfony Community",
+ "homepage": "https://symfony.com/contributors"
+ }
+ ],
+ "description": "Generic abstractions related to caching",
+ "homepage": "https://symfony.com",
+ "keywords": [
+ "abstractions",
+ "contracts",
+ "decoupling",
+ "interfaces",
+ "interoperability",
+ "standards"
+ ],
+ "support": {
+ "source": "https://github.com/symfony/cache-contracts/tree/v1.10.0"
+ },
+ "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": "2022-01-02T09:41:36+00:00"
+ },
+ {
+ "name": "symfony/deprecation-contracts",
+ "version": "v2.5.4",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/symfony/deprecation-contracts.git",
+ "reference": "605389f2a7e5625f273b53960dc46aeaf9c62918"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/605389f2a7e5625f273b53960dc46aeaf9c62918",
+ "reference": "605389f2a7e5625f273b53960dc46aeaf9c62918",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=7.1"
+ },
+ "type": "library",
+ "extra": {
+ "thanks": {
+ "url": "https://github.com/symfony/contracts",
+ "name": "symfony/contracts"
+ },
+ "branch-alias": {
+ "dev-main": "2.5-dev"
+ }
+ },
+ "autoload": {
+ "files": [
+ "function.php"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Nicolas Grekas",
+ "email": "p@tchwork.com"
+ },
+ {
+ "name": "Symfony Community",
+ "homepage": "https://symfony.com/contributors"
+ }
+ ],
+ "description": "A generic function and convention to trigger deprecation notices",
+ "homepage": "https://symfony.com",
+ "support": {
+ "source": "https://github.com/symfony/deprecation-contracts/tree/v2.5.4"
+ },
+ "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": "2024-09-25T14:11:13+00:00"
+ },
+ {
+ "name": "symfony/event-dispatcher",
+ "version": "v5.4.45",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/symfony/event-dispatcher.git",
+ "reference": "72982eb416f61003e9bb6e91f8b3213600dcf9e9"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/72982eb416f61003e9bb6e91f8b3213600dcf9e9",
+ "reference": "72982eb416f61003e9bb6e91f8b3213600dcf9e9",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=7.2.5",
+ "symfony/deprecation-contracts": "^2.1|^3",
+ "symfony/event-dispatcher-contracts": "^2|^3",
+ "symfony/polyfill-php80": "^1.16"
+ },
+ "conflict": {
+ "symfony/dependency-injection": "<4.4"
+ },
+ "provide": {
+ "psr/event-dispatcher-implementation": "1.0",
+ "symfony/event-dispatcher-implementation": "2.0"
+ },
+ "require-dev": {
+ "psr/log": "^1|^2|^3",
+ "symfony/config": "^4.4|^5.0|^6.0",
+ "symfony/dependency-injection": "^4.4|^5.0|^6.0",
+ "symfony/error-handler": "^4.4|^5.0|^6.0",
+ "symfony/expression-language": "^4.4|^5.0|^6.0",
+ "symfony/http-foundation": "^4.4|^5.0|^6.0",
+ "symfony/service-contracts": "^1.1|^2|^3",
+ "symfony/stopwatch": "^4.4|^5.0|^6.0"
+ },
+ "suggest": {
+ "symfony/dependency-injection": "",
+ "symfony/http-kernel": ""
+ },
+ "type": "library",
+ "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": "Provides tools that allow your application components to communicate with each other by dispatching events and listening to them",
+ "homepage": "https://symfony.com",
+ "support": {
+ "source": "https://github.com/symfony/event-dispatcher/tree/v5.4.45"
+ },
+ "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": "2024-09-25T14:11:13+00:00"
+ },
+ {
+ "name": "symfony/event-dispatcher-contracts",
+ "version": "v2.5.4",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/symfony/event-dispatcher-contracts.git",
+ "reference": "e0fe3d79b516eb75126ac6fa4cbf19b79b08c99f"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/symfony/event-dispatcher-contracts/zipball/e0fe3d79b516eb75126ac6fa4cbf19b79b08c99f",
+ "reference": "e0fe3d79b516eb75126ac6fa4cbf19b79b08c99f",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=7.2.5",
+ "psr/event-dispatcher": "^1"
+ },
+ "suggest": {
+ "symfony/event-dispatcher-implementation": ""
+ },
+ "type": "library",
+ "extra": {
+ "thanks": {
+ "url": "https://github.com/symfony/contracts",
+ "name": "symfony/contracts"
+ },
+ "branch-alias": {
+ "dev-main": "2.5-dev"
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "Symfony\\Contracts\\EventDispatcher\\": ""
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Nicolas Grekas",
+ "email": "p@tchwork.com"
+ },
+ {
+ "name": "Symfony Community",
+ "homepage": "https://symfony.com/contributors"
+ }
+ ],
+ "description": "Generic abstractions related to dispatching event",
+ "homepage": "https://symfony.com",
+ "keywords": [
+ "abstractions",
+ "contracts",
+ "decoupling",
+ "interfaces",
+ "interoperability",
+ "standards"
+ ],
+ "support": {
+ "source": "https://github.com/symfony/event-dispatcher-contracts/tree/v2.5.4"
+ },
+ "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": "2024-09-25T14:11:13+00:00"
+ },
+ {
+ "name": "symfony/http-foundation",
+ "version": "v5.4.50",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/symfony/http-foundation.git",
+ "reference": "1a0706e8b8041046052ea2695eb8aeee04f97609"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/symfony/http-foundation/zipball/1a0706e8b8041046052ea2695eb8aeee04f97609",
+ "reference": "1a0706e8b8041046052ea2695eb8aeee04f97609",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=7.2.5",
+ "symfony/deprecation-contracts": "^2.1|^3",
+ "symfony/polyfill-mbstring": "~1.1",
+ "symfony/polyfill-php80": "^1.16"
+ },
+ "require-dev": {
+ "predis/predis": "^1.0|^2.0",
+ "symfony/cache": "^4.4|^5.0|^6.0",
+ "symfony/dependency-injection": "^5.4|^6.0",
+ "symfony/expression-language": "^4.4|^5.0|^6.0",
+ "symfony/http-kernel": "^5.4.12|^6.0.12|^6.1.4",
+ "symfony/mime": "^4.4|^5.0|^6.0",
+ "symfony/rate-limiter": "^5.2|^6.0"
+ },
+ "suggest": {
+ "symfony/mime": "To use the file extension guesser"
+ },
+ "type": "library",
+ "autoload": {
+ "psr-4": {
+ "Symfony\\Component\\HttpFoundation\\": ""
+ },
+ "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": "Defines an object-oriented layer for the HTTP specification",
+ "homepage": "https://symfony.com",
+ "support": {
+ "source": "https://github.com/symfony/http-foundation/tree/v5.4.50"
+ },
+ "funding": [
+ {
+ "url": "https://symfony.com/sponsor",
+ "type": "custom"
+ },
+ {
+ "url": "https://github.com/fabpot",
+ "type": "github"
+ },
+ {
+ "url": "https://github.com/nicolas-grekas",
+ "type": "github"
+ },
+ {
+ "url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
+ "type": "tidelift"
+ }
+ ],
+ "time": "2025-11-03T12:58:48+00:00"
+ },
+ {
+ "name": "symfony/options-resolver",
+ "version": "v5.4.45",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/symfony/options-resolver.git",
+ "reference": "74e5b6f0db3e8589e6cfd5efb317a1fc2bb52fb6"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/symfony/options-resolver/zipball/74e5b6f0db3e8589e6cfd5efb317a1fc2bb52fb6",
+ "reference": "74e5b6f0db3e8589e6cfd5efb317a1fc2bb52fb6",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=7.2.5",
+ "symfony/deprecation-contracts": "^2.1|^3",
+ "symfony/polyfill-php73": "~1.0",
+ "symfony/polyfill-php80": "^1.16"
+ },
+ "type": "library",
+ "autoload": {
+ "psr-4": {
+ "Symfony\\Component\\OptionsResolver\\": ""
+ },
+ "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": "Provides an improved replacement for the array_replace PHP function",
+ "homepage": "https://symfony.com",
+ "keywords": [
+ "config",
+ "configuration",
+ "options"
+ ],
+ "support": {
+ "source": "https://github.com/symfony/options-resolver/tree/v5.4.45"
+ },
+ "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": "2024-09-25T14:11:13+00:00"
+ },
+ {
+ "name": "symfony/polyfill-ctype",
+ "version": "v1.33.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/symfony/polyfill-ctype.git",
+ "reference": "a3cc8b044a6ea513310cbd48ef7333b384945638"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/a3cc8b044a6ea513310cbd48ef7333b384945638",
+ "reference": "a3cc8b044a6ea513310cbd48ef7333b384945638",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=7.2"
+ },
+ "provide": {
+ "ext-ctype": "*"
+ },
+ "suggest": {
+ "ext-ctype": "For best performance"
+ },
+ "type": "library",
+ "extra": {
+ "thanks": {
+ "url": "https://github.com/symfony/polyfill",
+ "name": "symfony/polyfill"
+ }
+ },
+ "autoload": {
+ "files": [
+ "bootstrap.php"
+ ],
+ "psr-4": {
+ "Symfony\\Polyfill\\Ctype\\": ""
+ }
+ },
+ "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"
+ ],
+ "support": {
+ "source": "https://github.com/symfony/polyfill-ctype/tree/v1.33.0"
+ },
+ "funding": [
+ {
+ "url": "https://symfony.com/sponsor",
+ "type": "custom"
+ },
+ {
+ "url": "https://github.com/fabpot",
+ "type": "github"
+ },
+ {
+ "url": "https://github.com/nicolas-grekas",
+ "type": "github"
+ },
+ {
+ "url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
+ "type": "tidelift"
+ }
+ ],
+ "time": "2024-09-09T11:45:10+00:00"
+ },
+ {
+ "name": "symfony/polyfill-intl-grapheme",
+ "version": "v1.33.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/symfony/polyfill-intl-grapheme.git",
+ "reference": "380872130d3a5dd3ace2f4010d95125fde5d5c70"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/symfony/polyfill-intl-grapheme/zipball/380872130d3a5dd3ace2f4010d95125fde5d5c70",
+ "reference": "380872130d3a5dd3ace2f4010d95125fde5d5c70",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=7.2"
+ },
+ "suggest": {
+ "ext-intl": "For best performance"
+ },
+ "type": "library",
+ "extra": {
+ "thanks": {
+ "url": "https://github.com/symfony/polyfill",
+ "name": "symfony/polyfill"
+ }
+ },
+ "autoload": {
+ "files": [
+ "bootstrap.php"
+ ],
+ "psr-4": {
+ "Symfony\\Polyfill\\Intl\\Grapheme\\": ""
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Nicolas Grekas",
+ "email": "p@tchwork.com"
+ },
+ {
+ "name": "Symfony Community",
+ "homepage": "https://symfony.com/contributors"
+ }
+ ],
+ "description": "Symfony polyfill for intl's grapheme_* functions",
+ "homepage": "https://symfony.com",
+ "keywords": [
+ "compatibility",
+ "grapheme",
+ "intl",
+ "polyfill",
+ "portable",
+ "shim"
+ ],
+ "support": {
+ "source": "https://github.com/symfony/polyfill-intl-grapheme/tree/v1.33.0"
+ },
+ "funding": [
+ {
+ "url": "https://symfony.com/sponsor",
+ "type": "custom"
+ },
+ {
+ "url": "https://github.com/fabpot",
+ "type": "github"
+ },
+ {
+ "url": "https://github.com/nicolas-grekas",
+ "type": "github"
+ },
+ {
+ "url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
+ "type": "tidelift"
+ }
+ ],
+ "time": "2025-06-27T09:58:17+00:00"
+ },
+ {
+ "name": "symfony/polyfill-intl-idn",
+ "version": "v1.33.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/symfony/polyfill-intl-idn.git",
+ "reference": "9614ac4d8061dc257ecc64cba1b140873dce8ad3"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/symfony/polyfill-intl-idn/zipball/9614ac4d8061dc257ecc64cba1b140873dce8ad3",
+ "reference": "9614ac4d8061dc257ecc64cba1b140873dce8ad3",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=7.2",
+ "symfony/polyfill-intl-normalizer": "^1.10"
+ },
+ "suggest": {
+ "ext-intl": "For best performance"
+ },
+ "type": "library",
+ "extra": {
+ "thanks": {
+ "url": "https://github.com/symfony/polyfill",
+ "name": "symfony/polyfill"
+ }
+ },
+ "autoload": {
+ "files": [
+ "bootstrap.php"
+ ],
+ "psr-4": {
+ "Symfony\\Polyfill\\Intl\\Idn\\": ""
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Laurent Bassin",
+ "email": "laurent@bassin.info"
+ },
+ {
+ "name": "Trevor Rowbotham",
+ "email": "trevor.rowbotham@pm.me"
+ },
+ {
+ "name": "Symfony Community",
+ "homepage": "https://symfony.com/contributors"
+ }
+ ],
+ "description": "Symfony polyfill for intl's idn_to_ascii and idn_to_utf8 functions",
+ "homepage": "https://symfony.com",
+ "keywords": [
+ "compatibility",
+ "idn",
+ "intl",
+ "polyfill",
+ "portable",
+ "shim"
+ ],
+ "support": {
+ "source": "https://github.com/symfony/polyfill-intl-idn/tree/v1.33.0"
+ },
+ "funding": [
+ {
+ "url": "https://symfony.com/sponsor",
+ "type": "custom"
+ },
+ {
+ "url": "https://github.com/fabpot",
+ "type": "github"
+ },
+ {
+ "url": "https://github.com/nicolas-grekas",
+ "type": "github"
+ },
+ {
+ "url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
+ "type": "tidelift"
+ }
+ ],
+ "time": "2024-09-10T14:38:51+00:00"
+ },
+ {
+ "name": "symfony/polyfill-intl-normalizer",
+ "version": "v1.33.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/symfony/polyfill-intl-normalizer.git",
+ "reference": "3833d7255cc303546435cb650316bff708a1c75c"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/symfony/polyfill-intl-normalizer/zipball/3833d7255cc303546435cb650316bff708a1c75c",
+ "reference": "3833d7255cc303546435cb650316bff708a1c75c",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=7.2"
+ },
+ "suggest": {
+ "ext-intl": "For best performance"
+ },
+ "type": "library",
+ "extra": {
+ "thanks": {
+ "url": "https://github.com/symfony/polyfill",
+ "name": "symfony/polyfill"
+ }
+ },
+ "autoload": {
+ "files": [
+ "bootstrap.php"
+ ],
+ "psr-4": {
+ "Symfony\\Polyfill\\Intl\\Normalizer\\": ""
+ },
+ "classmap": [
+ "Resources/stubs"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Nicolas Grekas",
+ "email": "p@tchwork.com"
+ },
+ {
+ "name": "Symfony Community",
+ "homepage": "https://symfony.com/contributors"
+ }
+ ],
+ "description": "Symfony polyfill for intl's Normalizer class and related functions",
+ "homepage": "https://symfony.com",
+ "keywords": [
+ "compatibility",
+ "intl",
+ "normalizer",
+ "polyfill",
+ "portable",
+ "shim"
+ ],
+ "support": {
+ "source": "https://github.com/symfony/polyfill-intl-normalizer/tree/v1.33.0"
+ },
+ "funding": [
+ {
+ "url": "https://symfony.com/sponsor",
+ "type": "custom"
+ },
+ {
+ "url": "https://github.com/fabpot",
+ "type": "github"
+ },
+ {
+ "url": "https://github.com/nicolas-grekas",
+ "type": "github"
+ },
+ {
+ "url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
+ "type": "tidelift"
+ }
+ ],
+ "time": "2024-09-09T11:45:10+00:00"
+ },
+ {
+ "name": "symfony/polyfill-mbstring",
+ "version": "v1.33.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/symfony/polyfill-mbstring.git",
+ "reference": "6d857f4d76bd4b343eac26d6b539585d2bc56493"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/6d857f4d76bd4b343eac26d6b539585d2bc56493",
+ "reference": "6d857f4d76bd4b343eac26d6b539585d2bc56493",
+ "shasum": ""
+ },
+ "require": {
+ "ext-iconv": "*",
+ "php": ">=7.2"
+ },
+ "provide": {
+ "ext-mbstring": "*"
+ },
+ "suggest": {
+ "ext-mbstring": "For best performance"
+ },
+ "type": "library",
+ "extra": {
+ "thanks": {
+ "url": "https://github.com/symfony/polyfill",
+ "name": "symfony/polyfill"
+ }
+ },
+ "autoload": {
+ "files": [
+ "bootstrap.php"
+ ],
+ "psr-4": {
+ "Symfony\\Polyfill\\Mbstring\\": ""
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Nicolas Grekas",
+ "email": "p@tchwork.com"
+ },
+ {
+ "name": "Symfony Community",
+ "homepage": "https://symfony.com/contributors"
+ }
+ ],
+ "description": "Symfony polyfill for the Mbstring extension",
+ "homepage": "https://symfony.com",
+ "keywords": [
+ "compatibility",
+ "mbstring",
+ "polyfill",
+ "portable",
+ "shim"
+ ],
+ "support": {
+ "source": "https://github.com/symfony/polyfill-mbstring/tree/v1.33.0"
+ },
+ "funding": [
+ {
+ "url": "https://symfony.com/sponsor",
+ "type": "custom"
+ },
+ {
+ "url": "https://github.com/fabpot",
+ "type": "github"
+ },
+ {
+ "url": "https://github.com/nicolas-grekas",
+ "type": "github"
+ },
+ {
+ "url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
+ "type": "tidelift"
+ }
+ ],
+ "time": "2024-12-23T08:48:59+00:00"
+ },
+ {
+ "name": "symfony/polyfill-php73",
+ "version": "v1.33.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/symfony/polyfill-php73.git",
+ "reference": "0f68c03565dcaaf25a890667542e8bd75fe7e5bb"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/symfony/polyfill-php73/zipball/0f68c03565dcaaf25a890667542e8bd75fe7e5bb",
+ "reference": "0f68c03565dcaaf25a890667542e8bd75fe7e5bb",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=7.2"
+ },
+ "type": "library",
+ "extra": {
+ "thanks": {
+ "url": "https://github.com/symfony/polyfill",
+ "name": "symfony/polyfill"
+ }
+ },
+ "autoload": {
+ "files": [
+ "bootstrap.php"
+ ],
+ "psr-4": {
+ "Symfony\\Polyfill\\Php73\\": ""
+ },
+ "classmap": [
+ "Resources/stubs"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Nicolas Grekas",
+ "email": "p@tchwork.com"
+ },
+ {
+ "name": "Symfony Community",
+ "homepage": "https://symfony.com/contributors"
+ }
+ ],
+ "description": "Symfony polyfill backporting some PHP 7.3+ features to lower PHP versions",
+ "homepage": "https://symfony.com",
+ "keywords": [
+ "compatibility",
+ "polyfill",
+ "portable",
+ "shim"
+ ],
+ "support": {
+ "source": "https://github.com/symfony/polyfill-php73/tree/v1.33.0"
+ },
+ "funding": [
+ {
+ "url": "https://symfony.com/sponsor",
+ "type": "custom"
+ },
+ {
+ "url": "https://github.com/fabpot",
+ "type": "github"
+ },
+ {
+ "url": "https://github.com/nicolas-grekas",
+ "type": "github"
+ },
+ {
+ "url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
+ "type": "tidelift"
+ }
+ ],
+ "time": "2024-09-09T11:45:10+00:00"
+ },
+ {
+ "name": "symfony/polyfill-php80",
+ "version": "v1.33.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/symfony/polyfill-php80.git",
+ "reference": "0cc9dd0f17f61d8131e7df6b84bd344899fe2608"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/0cc9dd0f17f61d8131e7df6b84bd344899fe2608",
+ "reference": "0cc9dd0f17f61d8131e7df6b84bd344899fe2608",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=7.2"
+ },
+ "type": "library",
+ "extra": {
+ "thanks": {
+ "url": "https://github.com/symfony/polyfill",
+ "name": "symfony/polyfill"
+ }
+ },
+ "autoload": {
+ "files": [
+ "bootstrap.php"
+ ],
+ "psr-4": {
+ "Symfony\\Polyfill\\Php80\\": ""
+ },
+ "classmap": [
+ "Resources/stubs"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Ion Bazan",
+ "email": "ion.bazan@gmail.com"
+ },
+ {
+ "name": "Nicolas Grekas",
+ "email": "p@tchwork.com"
+ },
+ {
+ "name": "Symfony Community",
+ "homepage": "https://symfony.com/contributors"
+ }
+ ],
+ "description": "Symfony polyfill backporting some PHP 8.0+ features to lower PHP versions",
+ "homepage": "https://symfony.com",
+ "keywords": [
+ "compatibility",
+ "polyfill",
+ "portable",
+ "shim"
+ ],
+ "support": {
+ "source": "https://github.com/symfony/polyfill-php80/tree/v1.33.0"
+ },
+ "funding": [
+ {
+ "url": "https://symfony.com/sponsor",
+ "type": "custom"
+ },
+ {
+ "url": "https://github.com/fabpot",
+ "type": "github"
+ },
+ {
+ "url": "https://github.com/nicolas-grekas",
+ "type": "github"
+ },
+ {
+ "url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
+ "type": "tidelift"
+ }
+ ],
+ "time": "2025-01-02T08:10:11+00:00"
+ },
+ {
+ "name": "symfony/property-access",
+ "version": "v5.4.45",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/symfony/property-access.git",
+ "reference": "111e7ed617509f1a9139686055d234aad6e388e0"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/symfony/property-access/zipball/111e7ed617509f1a9139686055d234aad6e388e0",
+ "reference": "111e7ed617509f1a9139686055d234aad6e388e0",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=7.2.5",
+ "symfony/deprecation-contracts": "^2.1|^3",
+ "symfony/polyfill-php80": "^1.16",
+ "symfony/property-info": "^5.2|^6.0"
+ },
+ "require-dev": {
+ "symfony/cache": "^4.4|^5.0|^6.0"
+ },
+ "suggest": {
+ "psr/cache-implementation": "To cache access methods."
+ },
+ "type": "library",
+ "autoload": {
+ "psr-4": {
+ "Symfony\\Component\\PropertyAccess\\": ""
+ },
+ "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": "Provides functions to read and write from/to an object or array using a simple string notation",
+ "homepage": "https://symfony.com",
+ "keywords": [
+ "access",
+ "array",
+ "extraction",
+ "index",
+ "injection",
+ "object",
+ "property",
+ "property-path",
+ "reflection"
+ ],
+ "support": {
+ "source": "https://github.com/symfony/property-access/tree/v5.4.45"
+ },
+ "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": "2024-09-25T14:11:13+00:00"
+ },
+ {
+ "name": "symfony/property-info",
+ "version": "v5.4.48",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/symfony/property-info.git",
+ "reference": "a0396295ad585f95fccd690bc6a281e5bd303902"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/symfony/property-info/zipball/a0396295ad585f95fccd690bc6a281e5bd303902",
+ "reference": "a0396295ad585f95fccd690bc6a281e5bd303902",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=7.2.5",
+ "symfony/deprecation-contracts": "^2.1|^3",
+ "symfony/polyfill-php80": "^1.16",
+ "symfony/string": "^5.1|^6.0"
+ },
+ "conflict": {
+ "phpdocumentor/reflection-docblock": "<3.2.2",
+ "phpdocumentor/type-resolver": "<1.4.0",
+ "symfony/dependency-injection": "<4.4"
+ },
+ "require-dev": {
+ "doctrine/annotations": "^1.10.4|^2",
+ "phpdocumentor/reflection-docblock": "^3.0|^4.0|^5.0",
+ "phpstan/phpdoc-parser": "^1.0|^2.0",
+ "symfony/cache": "^4.4|^5.0|^6.0",
+ "symfony/dependency-injection": "^4.4|^5.0|^6.0",
+ "symfony/serializer": "^4.4|^5.0|^6.0"
+ },
+ "suggest": {
+ "phpdocumentor/reflection-docblock": "To use the PHPDoc",
+ "psr/cache-implementation": "To cache results",
+ "symfony/doctrine-bridge": "To use Doctrine metadata",
+ "symfony/serializer": "To use Serializer metadata"
+ },
+ "type": "library",
+ "autoload": {
+ "psr-4": {
+ "Symfony\\Component\\PropertyInfo\\": ""
+ },
+ "exclude-from-classmap": [
+ "/Tests/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Kévin Dunglas",
+ "email": "dunglas@gmail.com"
+ },
+ {
+ "name": "Symfony Community",
+ "homepage": "https://symfony.com/contributors"
+ }
+ ],
+ "description": "Extracts information about PHP class' properties using metadata of popular sources",
+ "homepage": "https://symfony.com",
+ "keywords": [
+ "doctrine",
+ "phpdoc",
+ "property",
+ "symfony",
+ "type",
+ "validator"
+ ],
+ "support": {
+ "source": "https://github.com/symfony/property-info/tree/v5.4.48"
+ },
+ "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": "2024-11-25T16:14:41+00:00"
+ },
+ {
+ "name": "symfony/psr-http-message-bridge",
+ "version": "v2.3.1",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/symfony/psr-http-message-bridge.git",
+ "reference": "581ca6067eb62640de5ff08ee1ba6850a0ee472e"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/symfony/psr-http-message-bridge/zipball/581ca6067eb62640de5ff08ee1ba6850a0ee472e",
+ "reference": "581ca6067eb62640de5ff08ee1ba6850a0ee472e",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=7.2.5",
+ "psr/http-message": "^1.0 || ^2.0",
+ "symfony/deprecation-contracts": "^2.5 || ^3.0",
+ "symfony/http-foundation": "^5.4 || ^6.0"
+ },
+ "require-dev": {
+ "nyholm/psr7": "^1.1",
+ "psr/log": "^1.1 || ^2 || ^3",
+ "symfony/browser-kit": "^5.4 || ^6.0",
+ "symfony/config": "^5.4 || ^6.0",
+ "symfony/event-dispatcher": "^5.4 || ^6.0",
+ "symfony/framework-bundle": "^5.4 || ^6.0",
+ "symfony/http-kernel": "^5.4 || ^6.0",
+ "symfony/phpunit-bridge": "^6.2"
+ },
+ "suggest": {
+ "nyholm/psr7": "For a super lightweight PSR-7/17 implementation"
+ },
+ "type": "symfony-bridge",
+ "extra": {
+ "branch-alias": {
+ "dev-main": "2.3-dev"
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "Symfony\\Bridge\\PsrHttpMessage\\": ""
+ },
+ "exclude-from-classmap": [
+ "/Tests/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Fabien Potencier",
+ "email": "fabien@symfony.com"
+ },
+ {
+ "name": "Symfony Community",
+ "homepage": "http://symfony.com/contributors"
+ }
+ ],
+ "description": "PSR HTTP message bridge",
+ "homepage": "http://symfony.com",
+ "keywords": [
+ "http",
+ "http-message",
+ "psr-17",
+ "psr-7"
+ ],
+ "support": {
+ "issues": "https://github.com/symfony/psr-http-message-bridge/issues",
+ "source": "https://github.com/symfony/psr-http-message-bridge/tree/v2.3.1"
+ },
+ "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": "2023-07-26T11:53:26+00:00"
+ },
+ {
+ "name": "symfony/service-contracts",
+ "version": "v1.1.2",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/symfony/service-contracts.git",
+ "reference": "191afdcb5804db960d26d8566b7e9a2843cab3a0"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/symfony/service-contracts/zipball/191afdcb5804db960d26d8566b7e9a2843cab3a0",
+ "reference": "191afdcb5804db960d26d8566b7e9a2843cab3a0",
+ "shasum": ""
+ },
+ "require": {
+ "php": "^7.1.3"
+ },
+ "suggest": {
+ "psr/container": "",
+ "symfony/service-implementation": ""
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "1.1-dev"
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "Symfony\\Contracts\\Service\\": ""
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Nicolas Grekas",
+ "email": "p@tchwork.com"
+ },
+ {
+ "name": "Symfony Community",
+ "homepage": "https://symfony.com/contributors"
+ }
+ ],
+ "description": "Generic abstractions related to writing services",
+ "homepage": "https://symfony.com",
+ "keywords": [
+ "abstractions",
+ "contracts",
+ "decoupling",
+ "interfaces",
+ "interoperability",
+ "standards"
+ ],
+ "support": {
+ "source": "https://github.com/symfony/service-contracts/tree/v1.1.2"
+ },
+ "time": "2019-05-28T07:50:59+00:00"
+ },
+ {
+ "name": "symfony/string",
+ "version": "v5.4.47",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/symfony/string.git",
+ "reference": "136ca7d72f72b599f2631aca474a4f8e26719799"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/symfony/string/zipball/136ca7d72f72b599f2631aca474a4f8e26719799",
+ "reference": "136ca7d72f72b599f2631aca474a4f8e26719799",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=7.2.5",
+ "symfony/polyfill-ctype": "~1.8",
+ "symfony/polyfill-intl-grapheme": "~1.0",
+ "symfony/polyfill-intl-normalizer": "~1.0",
+ "symfony/polyfill-mbstring": "~1.0",
+ "symfony/polyfill-php80": "~1.15"
+ },
+ "conflict": {
+ "symfony/translation-contracts": ">=3.0"
+ },
+ "require-dev": {
+ "symfony/error-handler": "^4.4|^5.0|^6.0",
+ "symfony/http-client": "^4.4|^5.0|^6.0",
+ "symfony/translation-contracts": "^1.1|^2",
+ "symfony/var-exporter": "^4.4|^5.0|^6.0"
+ },
+ "type": "library",
+ "autoload": {
+ "files": [
+ "Resources/functions.php"
+ ],
+ "psr-4": {
+ "Symfony\\Component\\String\\": ""
+ },
+ "exclude-from-classmap": [
+ "/Tests/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Nicolas Grekas",
+ "email": "p@tchwork.com"
+ },
+ {
+ "name": "Symfony Community",
+ "homepage": "https://symfony.com/contributors"
+ }
+ ],
+ "description": "Provides an object-oriented API to strings and deals with bytes, UTF-8 code points and grapheme clusters in a unified way",
+ "homepage": "https://symfony.com",
+ "keywords": [
+ "grapheme",
+ "i18n",
+ "string",
+ "unicode",
+ "utf-8",
+ "utf8"
+ ],
+ "support": {
+ "source": "https://github.com/symfony/string/tree/v5.4.47"
+ },
+ "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": "2024-11-10T20:33:58+00:00"
+ },
+ {
+ "name": "symfony/var-exporter",
+ "version": "v4.4.43",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/symfony/var-exporter.git",
+ "reference": "4a7a3a3d55c471d396e6d28011368b7b83cb518b"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/symfony/var-exporter/zipball/4a7a3a3d55c471d396e6d28011368b7b83cb518b",
+ "reference": "4a7a3a3d55c471d396e6d28011368b7b83cb518b",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=7.1.3",
+ "symfony/polyfill-php80": "^1.16"
+ },
+ "require-dev": {
+ "symfony/var-dumper": "^4.4.9|^5.0.9"
+ },
+ "type": "library",
+ "autoload": {
+ "psr-4": {
+ "Symfony\\Component\\VarExporter\\": ""
+ },
+ "exclude-from-classmap": [
+ "/Tests/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Nicolas Grekas",
+ "email": "p@tchwork.com"
+ },
+ {
+ "name": "Symfony Community",
+ "homepage": "https://symfony.com/contributors"
+ }
+ ],
+ "description": "Allows exporting any serializable PHP data structure to plain PHP code",
+ "homepage": "https://symfony.com",
+ "keywords": [
+ "clone",
+ "construct",
+ "export",
+ "hydrate",
+ "instantiate",
+ "serialize"
+ ],
+ "support": {
+ "source": "https://github.com/symfony/var-exporter/tree/v4.4.43"
+ },
+ "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": "2022-05-27T11:44:32+00:00"
+ },
+ {
+ "name": "textalk/websocket",
+ "version": "1.6.3",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/Textalk/websocket-php.git",
+ "reference": "67de79745b1a357caf812bfc44e0abf481cee012"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/Textalk/websocket-php/zipball/67de79745b1a357caf812bfc44e0abf481cee012",
+ "reference": "67de79745b1a357caf812bfc44e0abf481cee012",
+ "shasum": ""
+ },
+ "require": {
+ "php": "^7.4 | ^8.0",
+ "phrity/net-uri": "^1.0",
+ "phrity/util-errorhandler": "^1.0",
+ "psr/http-message": "^1.0",
+ "psr/log": "^1.0 | ^2.0 | ^3.0"
+ },
+ "require-dev": {
+ "php-coveralls/php-coveralls": "^2.0",
+ "phpunit/phpunit": "^9.0",
+ "squizlabs/php_codesniffer": "^3.5"
+ },
+ "type": "library",
+ "autoload": {
+ "psr-4": {
+ "WebSocket\\": "lib"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "ISC"
+ ],
+ "authors": [
+ {
+ "name": "Fredrik Liljegren"
+ },
+ {
+ "name": "Sören Jensen"
+ }
+ ],
+ "description": "WebSocket client and server",
+ "support": {
+ "issues": "https://github.com/Textalk/websocket-php/issues",
+ "source": "https://github.com/Textalk/websocket-php/tree/1.6.3"
+ },
+ "time": "2022-11-07T18:59:33+00:00"
+ },
+ {
+ "name": "topthink/framework",
+ "version": "v5.1.12",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/top-think/framework.git",
+ "reference": "f879603ee321af8fde56d8855445cf98bc81b042"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/top-think/framework/zipball/f879603ee321af8fde56d8855445cf98bc81b042",
+ "reference": "f879603ee321af8fde56d8855445cf98bc81b042",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=5.6.0",
+ "topthink/think-installer": "~1.0"
+ },
+ "require-dev": {
+ "johnkary/phpunit-speedtrap": "^1.0",
+ "mikey179/vfsstream": "~1.6",
+ "phpdocumentor/reflection-docblock": "^2.0",
+ "phploc/phploc": "2.*",
+ "phpunit/phpunit": "^5.0|^6.0",
+ "sebastian/phpcpd": "2.*",
+ "squizlabs/php_codesniffer": "2.*"
+ },
+ "type": "think-framework",
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "Apache-2.0"
+ ],
"authors": [
{
"name": "liu21st",
"email": "liu21st@gmail.com"
+ },
+ {
+ "name": "yunwuxin",
+ "email": "448901948@qq.com"
}
],
"description": "the new thinkphp framework",
@@ -55,7 +3839,144 @@
"orm",
"thinkphp"
],
- "time": "2022-10-25T14:59:38+00:00"
+ "support": {
+ "issues": "https://github.com/top-think/framework/issues",
+ "source": "https://github.com/top-think/framework/tree/5.1"
+ },
+ "time": "2018-04-26T03:46:41+00:00"
+ },
+ {
+ "name": "topthink/think-captcha",
+ "version": "v2.0.2",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/top-think/think-captcha.git",
+ "reference": "54c8a51552f99ff9ea89ea9c272383a8f738ceee"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/top-think/think-captcha/zipball/54c8a51552f99ff9ea89ea9c272383a8f738ceee",
+ "reference": "54c8a51552f99ff9ea89ea9c272383a8f738ceee",
+ "shasum": ""
+ },
+ "require": {
+ "topthink/framework": "5.1.*"
+ },
+ "type": "library",
+ "autoload": {
+ "files": [
+ "src/helper.php"
+ ],
+ "psr-4": {
+ "think\\captcha\\": "src/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "Apache-2.0"
+ ],
+ "authors": [
+ {
+ "name": "yunwuxin",
+ "email": "448901948@qq.com"
+ }
+ ],
+ "description": "captcha package for thinkphp5",
+ "support": {
+ "issues": "https://github.com/top-think/think-captcha/issues",
+ "source": "https://github.com/top-think/think-captcha/tree/2.0"
+ },
+ "time": "2017-12-31T16:37:49+00:00"
+ },
+ {
+ "name": "topthink/think-helper",
+ "version": "v3.1.11",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/top-think/think-helper.git",
+ "reference": "1d6ada9b9f3130046bf6922fe1bd159c8d88a33c"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/top-think/think-helper/zipball/1d6ada9b9f3130046bf6922fe1bd159c8d88a33c",
+ "reference": "1d6ada9b9f3130046bf6922fe1bd159c8d88a33c",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=7.1.0"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "^9.5"
+ },
+ "type": "library",
+ "autoload": {
+ "files": [
+ "src/helper.php"
+ ],
+ "psr-4": {
+ "think\\": "src"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "Apache-2.0"
+ ],
+ "authors": [
+ {
+ "name": "yunwuxin",
+ "email": "448901948@qq.com"
+ }
+ ],
+ "description": "The ThinkPHP6 Helper Package",
+ "support": {
+ "issues": "https://github.com/top-think/think-helper/issues",
+ "source": "https://github.com/top-think/think-helper/tree/v3.1.11"
+ },
+ "time": "2025-04-07T06:55:59+00:00"
+ },
+ {
+ "name": "topthink/think-image",
+ "version": "v1.0.8",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/top-think/think-image.git",
+ "reference": "d1d748cbb2fe2f29fca6138cf96cb8b5113892f1"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/top-think/think-image/zipball/d1d748cbb2fe2f29fca6138cf96cb8b5113892f1",
+ "reference": "d1d748cbb2fe2f29fca6138cf96cb8b5113892f1",
+ "shasum": ""
+ },
+ "require": {
+ "ext-gd": "*"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "4.8.*",
+ "topthink/framework": "^5.0"
+ },
+ "type": "library",
+ "autoload": {
+ "psr-4": {
+ "think\\": "src"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "Apache-2.0"
+ ],
+ "authors": [
+ {
+ "name": "yunwuxin",
+ "email": "448901948@qq.com"
+ }
+ ],
+ "description": "The ThinkPHP5 Image Package",
+ "support": {
+ "issues": "https://github.com/top-think/think-image/issues",
+ "source": "https://github.com/top-think/think-image/tree/v1.0.8"
+ },
+ "time": "2024-08-07T10:06:35+00:00"
},
{
"name": "topthink/think-installer",
@@ -96,17 +4017,351 @@
"email": "448901948@qq.com"
}
],
+ "support": {
+ "issues": "https://github.com/top-think/think-installer/issues",
+ "source": "https://github.com/top-think/think-installer/tree/v1.0.14"
+ },
"time": "2021-03-25T08:34:02+00:00"
+ },
+ {
+ "name": "topthink/think-queue",
+ "version": "v2.0.3",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/top-think/think-queue.git",
+ "reference": "465320c9cb7811df22d4ff8f29f58ead7d104348"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/top-think/think-queue/zipball/465320c9cb7811df22d4ff8f29f58ead7d104348",
+ "reference": "465320c9cb7811df22d4ff8f29f58ead7d104348",
+ "shasum": ""
+ },
+ "require": {
+ "topthink/think-helper": ">=1.0.4",
+ "topthink/think-installer": ">=1.0.10"
+ },
+ "type": "think-extend",
+ "extra": {
+ "think-config": {
+ "queue": "src/config.php"
+ }
+ },
+ "autoload": {
+ "files": [
+ "src/common.php"
+ ],
+ "psr-4": {
+ "think\\": "src"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "Apache-2.0"
+ ],
+ "authors": [
+ {
+ "name": "yunwuxin",
+ "email": "448901948@qq.com"
+ }
+ ],
+ "description": "The ThinkPHP5 Queue Package",
+ "support": {
+ "issues": "https://github.com/top-think/think-queue/issues",
+ "source": "https://github.com/top-think/think-queue/tree/master"
+ },
+ "time": "2018-05-04T05:29:53+00:00"
+ },
+ {
+ "name": "topthink/think-worker",
+ "version": "v2.0.3",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/top-think/think-worker.git",
+ "reference": "7b7a64b2911cc11298b11677508f1a1936a2fb70"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/top-think/think-worker/zipball/7b7a64b2911cc11298b11677508f1a1936a2fb70",
+ "reference": "7b7a64b2911cc11298b11677508f1a1936a2fb70",
+ "shasum": ""
+ },
+ "require": {
+ "topthink/framework": "5.1.*",
+ "workerman/workerman": "^3.3.0"
+ },
+ "type": "library",
+ "autoload": {
+ "files": [
+ "src/config.php"
+ ],
+ "psr-4": {
+ "think\\worker\\": "src"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "Apache-2.0"
+ ],
+ "authors": [
+ {
+ "name": "liu21st",
+ "email": "liu21st@gmail.com"
+ }
+ ],
+ "description": "workerman extend for thinkphp5",
+ "support": {
+ "issues": "https://github.com/top-think/think-worker/issues",
+ "source": "https://github.com/top-think/think-worker/tree/2.0"
+ },
+ "time": "2018-06-28T06:04:53+00:00"
+ },
+ {
+ "name": "workerman/gateway-worker",
+ "version": "v3.0.22",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/walkor/GatewayWorker.git",
+ "reference": "a615036c482d11f68b693998575e804752ef9068"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/walkor/GatewayWorker/zipball/a615036c482d11f68b693998575e804752ef9068",
+ "reference": "a615036c482d11f68b693998575e804752ef9068",
+ "shasum": ""
+ },
+ "require": {
+ "workerman/workerman": ">=3.5.0"
+ },
+ "type": "library",
+ "autoload": {
+ "psr-4": {
+ "GatewayWorker\\": "./src"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "homepage": "http://www.workerman.net",
+ "keywords": [
+ "communication",
+ "distributed"
+ ],
+ "support": {
+ "issues": "https://github.com/walkor/GatewayWorker/issues",
+ "source": "https://github.com/walkor/GatewayWorker/tree/v3.0.22"
+ },
+ "funding": [
+ {
+ "url": "https://opencollective.com/walkor",
+ "type": "open_collective"
+ },
+ {
+ "url": "https://www.patreon.com/walkor",
+ "type": "patreon"
+ }
+ ],
+ "time": "2021-12-23T13:13:09+00:00"
+ },
+ {
+ "name": "workerman/workerman",
+ "version": "v3.5.35",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/walkor/workerman.git",
+ "reference": "3cc0adae51ba36db38b11e7996c64250d356dbe7"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/walkor/workerman/zipball/3cc0adae51ba36db38b11e7996c64250d356dbe7",
+ "reference": "3cc0adae51ba36db38b11e7996c64250d356dbe7",
+ "shasum": ""
+ },
+ "require": {
+ "php": "^5.3||^7.0"
+ },
+ "suggest": {
+ "ext-event": "For better performance. "
+ },
+ "type": "library",
+ "autoload": {
+ "psr-4": {
+ "Workerman\\": "./"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "walkor",
+ "email": "walkor@workerman.net",
+ "homepage": "http://www.workerman.net",
+ "role": "Developer"
+ }
+ ],
+ "description": "An asynchronous event driven PHP framework for easily building fast, scalable network applications.",
+ "homepage": "http://www.workerman.net",
+ "keywords": [
+ "asynchronous",
+ "event-loop"
+ ],
+ "support": {
+ "email": "walkor@workerman.net",
+ "forum": "http://wenda.workerman.net/",
+ "issues": "https://github.com/walkor/workerman/issues",
+ "source": "https://github.com/walkor/workerman",
+ "wiki": "http://doc.workerman.net/"
+ },
+ "funding": [
+ {
+ "url": "https://opencollective.com/workerman",
+ "type": "open_collective"
+ },
+ {
+ "url": "https://www.patreon.com/walkor",
+ "type": "patreon"
+ }
+ ],
+ "time": "2023-09-13T14:30:13+00:00"
+ }
+ ],
+ "packages-dev": [
+ {
+ "name": "symfony/var-dumper",
+ "version": "v3.4.47",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/symfony/var-dumper.git",
+ "reference": "0719f6cf4633a38b2c1585140998579ce23b4b7d"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/symfony/var-dumper/zipball/0719f6cf4633a38b2c1585140998579ce23b4b7d",
+ "reference": "0719f6cf4633a38b2c1585140998579ce23b4b7d",
+ "shasum": ""
+ },
+ "require": {
+ "php": "^5.5.9|>=7.0.8",
+ "symfony/polyfill-mbstring": "~1.0"
+ },
+ "conflict": {
+ "phpunit/phpunit": "<4.8.35|<5.4.3,>=5.0"
+ },
+ "require-dev": {
+ "ext-iconv": "*",
+ "twig/twig": "~1.34|~2.4"
+ },
+ "suggest": {
+ "ext-iconv": "To convert non-UTF-8 strings to UTF-8 (or symfony/polyfill-iconv in case ext-iconv cannot be used).",
+ "ext-intl": "To show region name in time zone dump",
+ "ext-symfony_debug": ""
+ },
+ "type": "library",
+ "autoload": {
+ "files": [
+ "Resources/functions/dump.php"
+ ],
+ "psr-4": {
+ "Symfony\\Component\\VarDumper\\": ""
+ },
+ "exclude-from-classmap": [
+ "/Tests/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Nicolas Grekas",
+ "email": "p@tchwork.com"
+ },
+ {
+ "name": "Symfony Community",
+ "homepage": "https://symfony.com/contributors"
+ }
+ ],
+ "description": "Symfony mechanism for exploring and dumping PHP variables",
+ "homepage": "https://symfony.com",
+ "keywords": [
+ "debug",
+ "dump"
+ ],
+ "support": {
+ "source": "https://github.com/symfony/var-dumper/tree/v3.4.47"
+ },
+ "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-24T10:57:07+00:00"
+ },
+ {
+ "name": "topthink/think-migration",
+ "version": "v2.0.3",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/top-think/think-migration.git",
+ "reference": "70c89850ca29c2eab988c7c3475d1d5331901bb8"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/top-think/think-migration/zipball/70c89850ca29c2eab988c7c3475d1d5331901bb8",
+ "reference": "70c89850ca29c2eab988c7c3475d1d5331901bb8",
+ "shasum": ""
+ },
+ "require": {
+ "topthink/framework": "5.1.*"
+ },
+ "type": "library",
+ "autoload": {
+ "files": [
+ "src/config.php"
+ ],
+ "psr-4": {
+ "Phinx\\": "phinx/src/Phinx",
+ "think\\migration\\": "src"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "Apache-2.0"
+ ],
+ "authors": [
+ {
+ "name": "yunwuxin",
+ "email": "448901948@qq.com"
+ }
+ ],
+ "support": {
+ "issues": "https://github.com/top-think/think-migration/issues",
+ "source": "https://github.com/top-think/think-migration/tree/2.0"
+ },
+ "time": "2017-12-31T16:32:22+00:00"
}
],
- "packages-dev": [],
"aliases": [],
- "minimum-stability": "stable",
+ "minimum-stability": "dev",
"stability-flags": [],
- "prefer-stable": false,
+ "prefer-stable": true,
"prefer-lowest": false,
"platform": {
- "php": ">=5.4.0"
+ "php": ">=5.6.0"
},
- "platform-dev": []
+ "platform-dev": [],
+ "plugin-api-version": "2.3.0"
}
From 5a5160b92d8c77c193ea1f8bc044e5d18bf27b63 Mon Sep 17 00:00:00 2001
From: wong <106998207@qq.com>
Date: Thu, 20 Nov 2025 11:48:31 +0800
Subject: [PATCH 02/10] =?UTF-8?q?=E4=BB=A3=E7=A0=81=E4=BC=98=E5=8C=96?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
Server/application/common.php | 30 +++++++++++++++++++++---------
1 file changed, 21 insertions(+), 9 deletions(-)
diff --git a/Server/application/common.php b/Server/application/common.php
index 37a12739..8785f12c 100644
--- a/Server/application/common.php
+++ b/Server/application/common.php
@@ -75,7 +75,18 @@ if (!function_exists('requestCurl')) {
if (!function_exists('dataBuild')) {
function dataBuild($array)
{
- return is_array($array) ? http_build_query($array) : $array;
+ if (!is_array($array)) {
+ return $array;
+ }
+
+ // 处理嵌套数组
+ foreach ($array as $key => $value) {
+ if (is_array($value)) {
+ $array[$key] = json_encode($value);
+ }
+ }
+
+ return http_build_query($array);
}
}
@@ -550,14 +561,15 @@ if (!function_exists('exit_data')) {
exit();
}
}
-
-/**
- * 调试打印变量但不终止程序
- * @return void
- */
-function dump()
-{
- call_user_func_array(['app\\common\\helper\\Debug', 'dump'], func_get_args());
+if (!function_exists('dump')) {
+ /**
+ * 调试打印变量但不终止程序
+ * @return void
+ */
+ function dump()
+ {
+ call_user_func_array(['app\\common\\helper\\Debug', 'dump'], func_get_args());
+ }
}
if (!function_exists('artificialAllotWechatFriend')) {
From d3fae3bbd0a3ee8693116e1eb6b89d7097cab9a5 Mon Sep 17 00:00:00 2001
From: wong <106998207@qq.com>
Date: Mon, 1 Dec 2025 15:42:54 +0800
Subject: [PATCH 03/10] =?UTF-8?q?=E9=98=9F=E5=88=97=E4=BC=98=E5=8C=96?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
Server/README_scheduler.md | 254 ++++++++++
Server/application/command.php | 3 +
.../command/TaskSchedulerCommand.php | 457 ++++++++++++++++++
Server/config/task_scheduler.php | 301 ++++++++++++
4 files changed, 1015 insertions(+)
create mode 100644 Server/README_scheduler.md
create mode 100644 Server/application/command/TaskSchedulerCommand.php
create mode 100644 Server/config/task_scheduler.php
diff --git a/Server/README_scheduler.md b/Server/README_scheduler.md
new file mode 100644
index 00000000..4c485684
--- /dev/null
+++ b/Server/README_scheduler.md
@@ -0,0 +1,254 @@
+# 统一任务调度器使用说明
+
+## 概述
+
+统一任务调度器(TaskSchedulerCommand)是一个集中管理所有定时任务的调度系统,支持:
+- ✅ 单条 crontab 配置管理所有任务
+- ✅ 多进程并发执行任务
+- ✅ 自动根据 cron 表达式判断任务执行时间
+- ✅ 任务锁机制,防止重复执行
+- ✅ 完善的日志记录
+
+## 安装配置
+
+### 1. 配置文件
+
+任务配置位于 `config/task_scheduler.php`,格式如下:
+
+```php
+'任务标识' => [
+ 'command' => '命令名称', // 必填:执行的命令
+ 'schedule' => 'cron表达式', // 必填:cron表达式
+ 'options' => ['--option=value'], // 可选:命令参数
+ 'enabled' => true, // 可选:是否启用
+ 'max_concurrent' => 1, // 可选:最大并发数
+ 'timeout' => 3600, // 可选:超时时间(秒)
+ 'log_file' => 'custom.log', // 可选:自定义日志文件
+]
+```
+
+### 2. Cron 表达式格式
+
+标准 cron 格式:`分钟 小时 日 月 星期`
+
+示例:
+- `*/1 * * * *` - 每分钟执行
+- `*/5 * * * *` - 每5分钟执行
+- `*/30 * * * *` - 每30分钟执行
+- `0 2 * * *` - 每天凌晨2点执行
+- `0 3 */3 * *` - 每3天的3点执行
+
+### 3. Crontab 配置
+
+**只需要在 crontab 中添加一条任务:**
+
+```bash
+# 每分钟执行一次调度器(调度器内部会根据 cron 表达式判断哪些任务需要执行)
+* * * * * cd /www/wwwroot/mckb_quwanzhi_com/Server && php think scheduler:run >> /www/wwwroot/mckb_quwanzhi_com/Server/runtime/log/scheduler.log 2>&1
+```
+
+### 4. 系统要求
+
+- PHP >= 5.6.0
+- 推荐启用 `pcntl` 扩展以支持多进程并发(非必需,未启用时使用单进程顺序执行)
+
+检查 pcntl 扩展:
+```bash
+php -m | grep pcntl
+```
+
+## 使用方法
+
+### 手动执行调度器
+
+```bash
+# 执行调度器(会自动判断当前时间需要执行的任务)
+php think scheduler:run
+```
+
+### 查看任务配置
+
+```bash
+# 查看所有已注册的命令
+php think list
+```
+
+### 启用/禁用任务
+
+编辑 `config/task_scheduler.php`,设置 `'enabled' => false` 即可禁用任务。
+
+## 功能特性
+
+### 1. 多进程并发执行
+
+- 默认最大并发数:10 个进程
+- 自动管理进程池
+- 自动清理僵尸进程
+
+### 2. 任务锁机制
+
+- 每个任务在执行时会设置锁(5分钟内不重复执行)
+- 防止任务重复执行
+- 锁存储在缓存中,自动过期
+
+### 3. 日志记录
+
+- 调度器日志:`runtime/log/scheduler.log`
+- 每个任务的日志:`runtime/log/{log_file}`
+- 任务执行开始和结束都有标记
+
+### 4. 超时控制
+
+- 默认超时时间:3600 秒(1小时)
+- 可在配置中为每个任务单独设置超时时间
+- 超时后自动终止任务
+
+## 配置示例
+
+### 高频任务(每分钟)
+
+```php
+'wechat_friends_active' => [
+ 'command' => 'wechatFriends:list',
+ 'schedule' => '*/1 * * * *',
+ 'options' => ['--isDel=0'],
+ 'enabled' => true,
+],
+```
+
+### 中频任务(每5分钟)
+
+```php
+'device_active' => [
+ 'command' => 'device:list',
+ 'schedule' => '*/5 * * * *',
+ 'options' => ['--isDel=0'],
+ 'enabled' => true,
+],
+```
+
+### 每日任务
+
+```php
+'wechat_calculate_score' => [
+ 'command' => 'wechat:calculate-score',
+ 'schedule' => '0 2 * * *', // 每天凌晨2点
+ 'options' => [],
+ 'enabled' => true,
+],
+```
+
+### 定期任务(每3天)
+
+```php
+'sync_all_friends' => [
+ 'command' => 'sync:allFriends',
+ 'schedule' => '0 3 */3 * *', // 每3天的3点
+ 'options' => [],
+ 'enabled' => true,
+],
+```
+
+## 从旧配置迁移
+
+### 旧配置(多条 crontab)
+
+```bash
+*/5 * * * * cd /path && php think device:list --isDel=0 >> log1.log 2>&1
+*/1 * * * * cd /path && php think wechatFriends:list >> log2.log 2>&1
+```
+
+### 新配置(单条 crontab + 配置文件)
+
+**Crontab:**
+```bash
+* * * * * cd /path && php think scheduler:run >> scheduler.log 2>&1
+```
+
+**config/task_scheduler.php:**
+```php
+'device_active' => [
+ 'command' => 'device:list',
+ 'schedule' => '*/5 * * * *',
+ 'options' => ['--isDel=0'],
+ 'log_file' => 'log1.log',
+],
+'wechat_friends' => [
+ 'command' => 'wechatFriends:list',
+ 'schedule' => '*/1 * * * *',
+ 'log_file' => 'log2.log',
+],
+```
+
+## 监控和调试
+
+### 查看调度器日志
+
+```bash
+tail -f runtime/log/scheduler.log
+```
+
+### 查看任务执行日志
+
+```bash
+tail -f runtime/log/crontab_device_active.log
+```
+
+### 检查任务是否在执行
+
+```bash
+# 查看进程
+ps aux | grep "php think"
+```
+
+### 手动测试任务
+
+```bash
+# 直接执行某个任务
+php think device:list --isDel=0
+```
+
+## 注意事项
+
+1. **时间同步**:确保服务器时间准确,调度器依赖系统时间判断任务执行时间
+2. **资源限制**:根据服务器性能调整 `maxConcurrent` 参数
+3. **日志清理**:定期清理日志文件,避免占用过多磁盘空间
+4. **任务冲突**:如果任务执行时间较长,建议调整执行频率或增加并发数
+5. **缓存依赖**:任务锁使用缓存,确保缓存服务正常运行
+
+## 故障排查
+
+### 任务未执行
+
+1. 检查任务是否启用:`'enabled' => true`
+2. 检查 cron 表达式是否正确
+3. 检查调度器是否正常运行:查看 `scheduler.log`
+4. 检查任务锁:任务可能在5分钟内重复执行被跳过
+
+### 任务执行失败
+
+1. 查看任务日志:`runtime/log/{log_file}`
+2. 检查命令是否正确:手动执行命令测试
+3. 检查权限:确保有执行权限和日志写入权限
+
+### 多进程不工作
+
+1. 检查 pcntl 扩展:`php -m | grep pcntl`
+2. 检查系统限制:`ulimit -u` 查看最大进程数
+3. 查看调度器日志中的错误信息
+
+## 性能优化建议
+
+1. **合理设置并发数**:根据服务器 CPU 核心数和内存大小调整
+2. **错开高频任务**:避免所有任务在同一分钟执行
+3. **优化任务执行时间**:减少任务执行时长
+4. **使用队列**:对于耗时任务,建议使用队列异步处理
+
+## 更新日志
+
+### v1.0.0 (2024-01-XX)
+- 初始版本
+- 支持多进程并发执行
+- 支持 cron 表达式调度
+- 支持任务锁机制
+
diff --git a/Server/application/command.php b/Server/application/command.php
index b5c4d0e5..ce06453b 100644
--- a/Server/application/command.php
+++ b/Server/application/command.php
@@ -42,4 +42,7 @@ return [
'wechat:calculate-score' => 'app\command\CalculateWechatAccountScoreCommand', // 统一计算微信账号健康分
'wechat:update-score' => 'app\command\UpdateWechatAccountScoreCommand', // 更新微信账号评分记录
+
+ // 统一任务调度器
+ 'scheduler:run' => 'app\command\TaskSchedulerCommand', // 统一任务调度器,支持多进程并发执行
];
diff --git a/Server/application/command/TaskSchedulerCommand.php b/Server/application/command/TaskSchedulerCommand.php
new file mode 100644
index 00000000..06a1dbaf
--- /dev/null
+++ b/Server/application/command/TaskSchedulerCommand.php
@@ -0,0 +1,457 @@
+> /path/to/log/scheduler.log 2>&1
+ */
+class TaskSchedulerCommand extends Command
+{
+ /**
+ * 任务配置
+ */
+ protected $tasks = [];
+
+ /**
+ * 最大并发进程数
+ */
+ protected $maxConcurrent = 10;
+
+ /**
+ * 当前运行的进程数
+ */
+ protected $runningProcesses = [];
+
+ /**
+ * 日志目录
+ */
+ protected $logDir = '';
+
+ protected function configure()
+ {
+ $this->setName('scheduler:run')
+ ->setDescription('统一任务调度器,支持多进程并发执行所有定时任务');
+ }
+
+ protected function execute(Input $input, Output $output)
+ {
+ $output->writeln('==========================================');
+ $output->writeln('任务调度器启动');
+ $output->writeln('时间: ' . date('Y-m-d H:i:s'));
+ $output->writeln('==========================================');
+
+ // 检查是否支持 pcntl 扩展
+ if (!function_exists('pcntl_fork')) {
+ $output->writeln('错误:系统不支持 pcntl 扩展,无法使用多进程功能');
+ $output->writeln('提示:将使用单进程顺序执行任务');
+ $this->maxConcurrent = 1;
+ }
+
+ // 加载任务配置
+ $this->tasks = Config::get('task_scheduler', []);
+ if (empty($this->tasks)) {
+ $output->writeln('错误:未找到任务配置');
+ return false;
+ }
+
+ // 设置日志目录
+ $this->logDir = runtime_path() . 'log' . DIRECTORY_SEPARATOR;
+ if (!is_dir($this->logDir)) {
+ mkdir($this->logDir, 0755, true);
+ }
+
+ // 获取当前时间
+ $currentTime = time();
+ $currentMinute = date('i', $currentTime);
+ $currentHour = date('H', $currentTime);
+ $currentDay = date('d', $currentTime);
+ $currentMonth = date('m', $currentTime);
+ $currentWeekday = date('w', $currentTime); // 0=Sunday, 6=Saturday
+
+ $output->writeln("当前时间: {$currentHour}:{$currentMinute}");
+ $output->writeln("已加载 " . count($this->tasks) . " 个任务配置");
+
+ // 筛选需要执行的任务
+ $tasksToRun = [];
+ foreach ($this->tasks as $taskId => $task) {
+ if (!isset($task['enabled']) || !$task['enabled']) {
+ continue;
+ }
+
+ if ($this->shouldRun($task['schedule'], $currentMinute, $currentHour, $currentDay, $currentMonth, $currentWeekday)) {
+ $tasksToRun[$taskId] = $task;
+ }
+ }
+
+ if (empty($tasksToRun)) {
+ $output->writeln('当前时间没有需要执行的任务');
+ return true;
+ }
+
+ $output->writeln("找到 " . count($tasksToRun) . " 个需要执行的任务");
+
+ // 执行任务
+ if ($this->maxConcurrent > 1 && function_exists('pcntl_fork')) {
+ $this->executeConcurrent($tasksToRun, $output);
+ } else {
+ $this->executeSequential($tasksToRun, $output);
+ }
+
+ // 清理僵尸进程
+ $this->cleanupZombieProcesses();
+
+ $output->writeln('==========================================');
+ $output->writeln('任务调度器执行完成');
+ $output->writeln('==========================================');
+
+ return true;
+ }
+
+ /**
+ * 判断任务是否应该执行
+ *
+ * @param string $schedule cron表达式,格式:分钟 小时 日 月 星期
+ * @param int $minute 当前分钟
+ * @param int $hour 当前小时
+ * @param int $day 当前日期
+ * @param int $month 当前月份
+ * @param int $weekday 当前星期
+ * @return bool
+ */
+ protected function shouldRun($schedule, $minute, $hour, $day, $month, $weekday)
+ {
+ $parts = preg_split('/\s+/', trim($schedule));
+ if (count($parts) < 5) {
+ return false;
+ }
+
+ list($scheduleMinute, $scheduleHour, $scheduleDay, $scheduleMonth, $scheduleWeekday) = $parts;
+
+ // 解析分钟
+ if (!$this->matchCronField($scheduleMinute, $minute)) {
+ return false;
+ }
+
+ // 解析小时
+ if (!$this->matchCronField($scheduleHour, $hour)) {
+ return false;
+ }
+
+ // 解析日期
+ if (!$this->matchCronField($scheduleDay, $day)) {
+ return false;
+ }
+
+ // 解析月份
+ if (!$this->matchCronField($scheduleMonth, $month)) {
+ return false;
+ }
+
+ // 解析星期(注意:cron中0和7都表示星期日)
+ if ($scheduleWeekday !== '*') {
+ $scheduleWeekday = str_replace('7', '0', $scheduleWeekday);
+ if (!$this->matchCronField($scheduleWeekday, $weekday)) {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ /**
+ * 匹配cron字段
+ *
+ * @param string $field cron字段表达式
+ * @param int $value 当前值
+ * @return bool
+ */
+ protected function matchCronField($field, $value)
+ {
+ // 通配符
+ if ($field === '*') {
+ return true;
+ }
+
+ // 列表(逗号分隔)
+ if (strpos($field, ',') !== false) {
+ $values = explode(',', $field);
+ foreach ($values as $v) {
+ if ($this->matchCronField(trim($v), $value)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ // 范围(如 1-5)
+ if (strpos($field, '-') !== false) {
+ list($start, $end) = explode('-', $field);
+ return $value >= (int)$start && $value <= (int)$end;
+ }
+
+ // 步长(如 */5 或 0-59/5)
+ if (strpos($field, '/') !== false) {
+ $parts = explode('/', $field);
+ $base = $parts[0];
+ $step = (int)$parts[1];
+
+ if ($base === '*') {
+ return $value % $step === 0;
+ } else {
+ // 处理范围步长,如 0-59/5
+ if (strpos($base, '-') !== false) {
+ list($start, $end) = explode('-', $base);
+ if ($value >= (int)$start && $value <= (int)$end) {
+ return ($value - (int)$start) % $step === 0;
+ }
+ return false;
+ } else {
+ return $value % $step === 0;
+ }
+ }
+ }
+
+ // 精确匹配
+ return (int)$field === $value;
+ }
+
+ /**
+ * 并发执行任务(多进程)
+ *
+ * @param array $tasks 任务列表
+ * @param Output $output 输出对象
+ */
+ protected function executeConcurrent($tasks, Output $output)
+ {
+ $output->writeln('使用多进程并发执行任务(最大并发数:' . $this->maxConcurrent . ')');
+
+ foreach ($tasks as $taskId => $task) {
+ // 等待可用进程槽
+ while (count($this->runningProcesses) >= $this->maxConcurrent) {
+ $this->waitForProcesses();
+ usleep(100000); // 等待100ms
+ }
+
+ // 检查任务是否已经在运行(防止重复执行)
+ $lockKey = "scheduler_task_lock:{$taskId}";
+ $lockTime = Cache::get($lockKey);
+ if ($lockTime && (time() - $lockTime) < 300) { // 5分钟内不重复执行
+ $output->writeln("任务 {$taskId} 正在运行中,跳过");
+ continue;
+ }
+
+ // 创建子进程
+ $pid = pcntl_fork();
+
+ if ($pid == -1) {
+ // 创建进程失败
+ $output->writeln("创建子进程失败:{$taskId}");
+ Log::error("任务调度器:创建子进程失败", ['task' => $taskId]);
+ continue;
+ } elseif ($pid == 0) {
+ // 子进程:执行任务
+ $this->runTask($taskId, $task);
+ exit(0);
+ } else {
+ // 父进程:记录子进程PID
+ $this->runningProcesses[$pid] = [
+ 'task_id' => $taskId,
+ 'start_time' => time(),
+ ];
+ $output->writeln("启动任务:{$taskId} (PID: {$pid})");
+
+ // 设置任务锁
+ Cache::set($lockKey, time(), 600); // 10分钟过期
+ }
+ }
+
+ // 等待所有子进程完成
+ while (!empty($this->runningProcesses)) {
+ $this->waitForProcesses();
+ usleep(500000); // 等待500ms
+ }
+ }
+
+ /**
+ * 顺序执行任务(单进程)
+ *
+ * @param array $tasks 任务列表
+ * @param Output $output 输出对象
+ */
+ protected function executeSequential($tasks, Output $output)
+ {
+ $output->writeln('使用单进程顺序执行任务');
+
+ foreach ($tasks as $taskId => $task) {
+ $output->writeln("执行任务:{$taskId}");
+ $this->runTask($taskId, $task);
+ }
+ }
+
+ /**
+ * 执行单个任务
+ *
+ * @param string $taskId 任务ID
+ * @param array $task 任务配置
+ */
+ protected function runTask($taskId, $task)
+ {
+ $startTime = microtime(true);
+ $logFile = $this->logDir . ($task['log_file'] ?? "scheduler_{$taskId}.log");
+
+ // 确保日志目录存在
+ $logDir = dirname($logFile);
+ if (!is_dir($logDir)) {
+ mkdir($logDir, 0755, true);
+ }
+
+ // 构建命令
+ $thinkPath = root_path() . 'think';
+ $command = "php {$thinkPath} {$task['command']}";
+ if (!empty($task['options'])) {
+ foreach ($task['options'] as $option) {
+ $command .= ' ' . escapeshellarg($option);
+ }
+ }
+
+ // 添加日志重定向
+ $command .= " >> " . escapeshellarg($logFile) . " 2>&1";
+
+ // 记录任务开始
+ $logMessage = "\n" . str_repeat('=', 60) . "\n";
+ $logMessage .= "任务开始执行: {$taskId}\n";
+ $logMessage .= "执行时间: " . date('Y-m-d H:i:s') . "\n";
+ $logMessage .= "命令: {$command}\n";
+ $logMessage .= str_repeat('=', 60) . "\n";
+ file_put_contents($logFile, $logMessage, FILE_APPEND);
+
+ // 执行命令
+ $descriptorspec = [
+ 0 => ['file', (PHP_OS_FAMILY === 'Windows' ? 'NUL' : '/dev/null'), 'r'], // stdin
+ 1 => ['file', $logFile, 'a'], // stdout
+ 2 => ['file', $logFile, 'a'], // stderr
+ ];
+
+ $process = @proc_open($command, $descriptorspec, $pipes, root_path());
+
+ if (is_resource($process)) {
+ // 关闭管道
+ if (isset($pipes[0])) @fclose($pipes[0]);
+ if (isset($pipes[1])) @fclose($pipes[1]);
+ if (isset($pipes[2])) @fclose($pipes[2]);
+
+ // 设置超时
+ $timeout = $task['timeout'] ?? 3600;
+ $startWaitTime = time();
+
+ // 等待进程完成或超时
+ while (true) {
+ $status = proc_get_status($process);
+
+ if (!$status['running']) {
+ break;
+ }
+
+ // 检查超时
+ if ((time() - $startWaitTime) > $timeout) {
+ if (function_exists('proc_terminate')) {
+ proc_terminate($process, SIGTERM);
+ // 等待进程终止
+ sleep(2);
+ $status = proc_get_status($process);
+ if ($status['running']) {
+ // 强制终止
+ proc_terminate($process, SIGKILL);
+ }
+ }
+ Log::warning("任务执行超时", [
+ 'task' => $taskId,
+ 'timeout' => $timeout,
+ ]);
+ break;
+ }
+
+ usleep(500000); // 等待500ms
+ }
+
+ // 关闭进程
+ proc_close($process);
+ } else {
+ // 如果 proc_open 失败,尝试直接执行(后台执行)
+ if (PHP_OS_FAMILY === 'Windows') {
+ pclose(popen("start /B " . $command, "r"));
+ } else {
+ exec($command . ' > /dev/null 2>&1 &');
+ }
+ }
+
+ $endTime = microtime(true);
+ $duration = round($endTime - $startTime, 2);
+
+ // 记录任务完成
+ $logMessage = "\n" . str_repeat('=', 60) . "\n";
+ $logMessage .= "任务执行完成: {$taskId}\n";
+ $logMessage .= "完成时间: " . date('Y-m-d H:i:s') . "\n";
+ $logMessage .= "执行时长: {$duration} 秒\n";
+ $logMessage .= str_repeat('=', 60) . "\n";
+ file_put_contents($logFile, $logMessage, FILE_APPEND);
+
+ Log::info("任务执行完成", [
+ 'task' => $taskId,
+ 'duration' => $duration,
+ ]);
+ }
+
+ /**
+ * 等待进程完成
+ */
+ protected function waitForProcesses()
+ {
+ foreach ($this->runningProcesses as $pid => $info) {
+ $status = 0;
+ $result = pcntl_waitpid($pid, $status, WNOHANG);
+
+ if ($result == $pid || $result == -1) {
+ // 进程已结束
+ unset($this->runningProcesses[$pid]);
+
+ $duration = time() - $info['start_time'];
+ Log::info("子进程执行完成", [
+ 'pid' => $pid,
+ 'task' => $info['task_id'],
+ 'duration' => $duration,
+ ]);
+ }
+ }
+ }
+
+ /**
+ * 清理僵尸进程
+ */
+ protected function cleanupZombieProcesses()
+ {
+ if (!function_exists('pcntl_waitpid')) {
+ return;
+ }
+
+ $status = 0;
+ while (($pid = pcntl_waitpid(-1, $status, WNOHANG)) > 0) {
+ // 清理僵尸进程
+ }
+ }
+}
+
diff --git a/Server/config/task_scheduler.php b/Server/config/task_scheduler.php
new file mode 100644
index 00000000..7fa7ea37
--- /dev/null
+++ b/Server/config/task_scheduler.php
@@ -0,0 +1,301 @@
+ [
+ // 'command' => '命令名称', // 必填:执行的 ThinkPHP 命令(见 application/command.php)
+ // 'schedule' => 'cron表达式', // 必填:cron 表达式,如 '*/5 * * * *' 表示每5分钟
+ // 'options' => ['--option=value'], // 可选:命令参数(原来 crontab 里的 --xxx=yyy)
+ // 'enabled' => true, // 可选:是否启用,默认 true
+ // 'max_concurrent'=> 1, // 可选:单任务最大并发数(目前由调度器统一控制,可预留)
+ // 'timeout' => 3600, // 可选:超时时间(秒),默认 3600
+ // 'log_file' => 'custom.log', // 可选:日志文件名,默认使用任务标识
+ // ]
+
+ // ===========================
+ // 高频任务(每分钟或更频繁)
+ // ===========================
+
+ // 同步微信好友列表(未删除好友),用于保持系统中好友数据实时更新
+ 'wechat_friends_active' => [
+ 'command' => 'wechatFriends:list',
+ 'schedule' => '*/1 * * * *', // 每1分钟
+ 'options' => ['--isDel=0'],
+ 'enabled' => true,
+ 'max_concurrent' => 1,
+ 'log_file' => 'crontab_wechatFriends_active.log',
+ ],
+
+ // 拉取“添加好友任务”列表,驱动自动加好友的任务队列
+ 'friend_task' => [
+ 'command' => 'friendTask:list',
+ 'schedule' => '*/1 * * * *', // 每1分钟
+ 'options' => [],
+ 'enabled' => true,
+ 'max_concurrent' => 1,
+ 'log_file' => 'crontab_friendTask.log',
+ ],
+
+ // 同步微信好友私聊消息列表,写入消息表,供客服工作台使用
+ 'message_friends' => [
+ 'command' => 'message:friendsList',
+ 'schedule' => '*/1 * * * *', // 每1分钟
+ 'options' => [],
+ 'enabled' => true,
+ 'max_concurrent' => 1,
+ 'log_file' => 'crontab_messageFriends.log',
+ ],
+
+ // 同步微信群聊消息列表,写入消息表,供群聊记录与风控分析
+ 'message_chatroom' => [
+ 'command' => 'message:chatroomList',
+ 'schedule' => '*/1 * * * *', // 每1分钟
+ 'options' => [],
+ 'enabled' => true,
+ 'max_concurrent' => 1,
+ 'log_file' => 'crontab_messageChatroom.log',
+ ],
+
+ // 客服端消息提醒任务,负责给在线客服推送新消息通知
+ 'kf_notice' => [
+ 'command' => 'kf:notice',
+ 'schedule' => '*/1 * * * *', // 每1分钟
+ 'options' => [],
+ 'enabled' => true,
+ 'max_concurrent' => 1,
+ 'log_file' => 'kf_notice.log',
+ ],
+
+ // ===========================
+ // 中频任务(每 2-5 分钟)
+ // ===========================
+
+ // 同步微信设备列表(未删除设备),用于设备管理与监控
+ 'device_active' => [
+ 'command' => 'device:list',
+ 'schedule' => '*/5 * * * *', // 每5分钟
+ 'options' => ['--isDel=0'],
+ 'enabled' => true,
+ 'max_concurrent' => 1,
+ 'log_file' => 'crontab_device_active.log',
+ ],
+
+ // 同步微信群聊列表(未删除群),用于群管理与后续任务分配
+ 'wechat_chatroom_active' => [
+ 'command' => 'wechatChatroom:list',
+ 'schedule' => '*/5 * * * *', // 每5分钟
+ 'options' => ['--isDel=0'],
+ 'enabled' => true,
+ 'max_concurrent' => 1,
+ 'log_file' => 'crontab_wechatChatroom_active.log',
+ ],
+
+ // 同步微信群成员列表(群好友),维持群成员明细数据
+ 'group_friends' => [
+ 'command' => 'groupFriends:list',
+ 'schedule' => '*/5 * * * *', // 每5分钟
+ 'options' => [],
+ 'enabled' => true,
+ 'max_concurrent' => 1,
+ 'log_file' => 'crontab_groupFriends.log',
+ ],
+
+ // 同步“微信客服列表”,获取绑定到公司的微信号,用于工作台与分配规则
+ 'wechat_list' => [
+ 'command' => 'wechatList:list',
+ 'schedule' => '*/5 * * * *', // 每5分钟
+ 'options' => [],
+ 'enabled' => true,
+ 'max_concurrent' => 1,
+ 'log_file' => 'crontab_wechatList.log',
+ ],
+
+ // 同步公司账号列表(企业/租户账号),供后台管理与统计
+ 'account_list' => [
+ 'command' => 'account:list',
+ 'schedule' => '*/5 * * * *', // 每5分钟
+ 'options' => [],
+ 'enabled' => true,
+ 'max_concurrent' => 1,
+ 'log_file' => 'crontab_account.log',
+ ],
+
+ // 内容采集任务,将外部或设备内容同步到系统内容库
+ 'content_collect' => [
+ 'command' => 'content:collect',
+ 'schedule' => '*/5 * * * *', // 每5分钟
+ 'options' => [],
+ 'enabled' => true,
+ 'max_concurrent' => 1,
+ 'log_file' => 'crontab_contentCollect.log',
+ ],
+
+ // 工作台:自动点赞好友/客户朋友圈,提高账号活跃度
+ 'workbench_auto_like' => [
+ 'command' => 'workbench:autoLike',
+ 'schedule' => '*/6 * * * *', // 每6分钟
+ 'options' => [],
+ 'enabled' => true,
+ 'max_concurrent' => 1,
+ 'log_file' => 'crontab_workbench_autoLike.log',
+ ],
+
+ // 工作台:自动建群任务,按规则批量创建微信群
+ 'workbench_group_create' => [
+ 'command' => 'workbench:groupCreate',
+ 'schedule' => '*/5 * * * *', // 每5分钟
+ 'options' => [],
+ 'enabled' => true,
+ 'max_concurrent' => 1,
+ 'log_file' => 'workbench_groupCreate.log',
+ ],
+
+ // 工作台:自动导入通讯录到系统,生成加粉/建群等任务
+ 'workbench_import_contact' => [
+ 'command' => 'workbench:import-contact',
+ 'schedule' => '*/5 * * * *', // 每5分钟
+ 'options' => [],
+ 'enabled' => true,
+ 'max_concurrent' => 1,
+ 'log_file' => 'import_contact.log',
+ ],
+
+ // ===========================
+ // 低频任务(每 2 分钟)
+ // ===========================
+
+ // 清洗并同步微信原始数据到存客宝业务表(数据治理任务)
+ 'sync_wechat_data' => [
+ 'command' => 'sync:wechatData',
+ 'schedule' => '*/2 * * * *', // 每2分钟
+ 'options' => [],
+ 'enabled' => true,
+ 'max_concurrent' => 1,
+ 'log_file' => 'sync_wechat_data.log',
+ ],
+
+ // 工作台:流量分发任务,把流量池中的线索按规则分配给微信号或员工
+ 'workbench_traffic_distribute' => [
+ 'command' => 'workbench:trafficDistribute',
+ 'schedule' => '*/2 * * * *', // 每2分钟
+ 'options' => [],
+ 'enabled' => true,
+ 'max_concurrent' => 1,
+ 'log_file' => 'traffic_distribute.log',
+ ],
+
+ // 工作台:朋友圈同步任务,拉取并落库朋友圈内容
+ 'workbench_moments' => [
+ 'command' => 'workbench:moments',
+ 'schedule' => '*/2 * * * *', // 每2分钟
+ 'options' => [],
+ 'enabled' => true,
+ 'max_concurrent' => 1,
+ 'log_file' => 'workbench_moments.log',
+ ],
+
+ // 预防性切换好友任务,监控频繁/风控风险,自动切换加人对象,保护微信号
+ 'switch_friends' => [
+ 'command' => 'switch:friends',
+ 'schedule' => '*/2 * * * *', // 每2分钟
+ 'options' => [],
+ 'enabled' => true,
+ 'max_concurrent' => 1,
+ 'log_file' => 'switch_friends.log',
+ ],
+
+ // ===========================
+ // 低频任务(每 30 分钟)
+ // ===========================
+
+ // 拉取设备通话记录(语音/电话),用于质检、统计或标签打分
+ 'call_recording' => [
+ 'command' => 'call-recording:list',
+ 'schedule' => '*/30 * * * *', // 每30分钟
+ 'options' => [],
+ 'enabled' => true,
+ 'max_concurrent' => 1,
+ 'log_file' => 'call_recording.log',
+ ],
+
+ // ===========================
+ // 每日 / 每几天任务
+ // ===========================
+
+ // 每日 1:00 同步“已删除设备”列表,补齐历史状态
+ 'device_deleted' => [
+ 'command' => 'device:list',
+ 'schedule' => '0 1 * * *', // 每天1点
+ 'options' => ['--isDel=1'],
+ 'enabled' => true,
+ 'max_concurrent' => 1,
+ 'log_file' => 'crontab_device_deleted.log',
+ ],
+
+ // 每日 1:10 同步“已停用设备”列表,更新停用状态
+ 'device_stopped' => [
+ 'command' => 'device:list',
+ 'schedule' => '10 1 * * *', // 每天1:10
+ 'options' => ['--isDel=2'],
+ 'enabled' => true,
+ 'max_concurrent' => 1,
+ 'log_file' => 'crontab_device_stopped.log',
+ ],
+
+ // 每日 1:30 同步“已删除微信好友”,用于历史恢复与报表
+ 'wechat_friends_deleted' => [
+ 'command' => 'wechatFriends:list',
+ 'schedule' => '30 1 * * *', // 每天1:30
+ 'options' => ['--isDel=1'],
+ 'enabled' => true,
+ 'max_concurrent' => 1,
+ 'log_file' => 'crontab_wechatFriends_deleted.log',
+ ],
+
+ // 每日 1:30 同步“已删除微信群聊”,用于统计与留痕
+ 'wechat_chatroom_deleted' => [
+ 'command' => 'wechatChatroom:list',
+ 'schedule' => '30 1 * * *', // 每天1:30
+ 'options' => ['--isDel=1'],
+ 'enabled' => true,
+ 'max_concurrent' => 1,
+ 'log_file' => 'crontab_wechatChatroom_deleted.log',
+ ],
+
+ // 每日 2:00 统一计算所有微信账号健康分(基础分 + 动态分)
+ 'wechat_calculate_score' => [
+ 'command' => 'wechat:calculate-score',
+ 'schedule' => '0 2 * * *', // 每天2点
+ 'options' => [],
+ 'enabled' => true,
+ 'max_concurrent' => 1,
+ 'log_file' => 'calculate_score.log',
+ ],
+
+ // 每 3 天执行的全量任务
+
+ // 每 3 天 3:00 全量同步所有在线好友,做一次大规模校准
+ 'sync_all_friends' => [
+ 'command' => 'sync:allFriends',
+ 'schedule' => '0 3 */3 * *', // 每3天的3点
+ 'options' => [],
+ 'enabled' => true,
+ 'max_concurrent' => 1,
+ 'log_file' => 'all_friends.log',
+ ],
+
+ // 已禁用的任务(注释掉的任务)
+ // 'workbench_group_push' => [
+ // 'command' => 'workbench:groupPush',
+ // 'schedule' => '*/2 * * * *',
+ // 'options' => [],
+ // 'enabled' => false,
+ // 'log_file' => 'workbench_groupPush.log',
+ // ],
+];
+
From 44edfe7a810fc68d166cf41221aed47596aba683 Mon Sep 17 00:00:00 2001
From: wong <106998207@qq.com>
Date: Mon, 1 Dec 2025 16:25:15 +0800
Subject: [PATCH 04/10] =?UTF-8?q?=E6=B6=88=E6=81=AF=E5=90=8C=E6=AD=A5?=
=?UTF-8?q?=E4=BC=98=E5=8C=96?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../api/controller/MessageController.php | 45 ++++++++++---------
1 file changed, 25 insertions(+), 20 deletions(-)
diff --git a/Server/application/api/controller/MessageController.php b/Server/application/api/controller/MessageController.php
index 6b47ebe4..734f3f7d 100644
--- a/Server/application/api/controller/MessageController.php
+++ b/Server/application/api/controller/MessageController.php
@@ -61,10 +61,8 @@ class MessageController extends BaseController
// 发送请求获取好友列表
$result = requestCurl($this->baseUrl . 'api/WechatFriend/listWechatFriendForMsgPagination', $params, 'POST', $header, 'json');
$response = handleApiResponse($result);
-
// 获取同步消息标志
$syncMessages = $this->request->param('syncMessages', true);
-
// 如果需要同步消息,则获取每个好友的消息
if ($syncMessages && !empty($response['results'])) {
$from = strtotime($fromTime) * 1000;
@@ -90,7 +88,6 @@ class MessageController extends BaseController
// 调用获取消息的接口
$messageResult = requestCurl($this->baseUrl . 'api/FriendMessage/searchMessage', $messageParams, 'GET', $header, 'json');
$messageResponse = handleApiResponse($messageResult);
-
// 保存消息到数据库
if (!empty($messageResponse)) {
foreach ($messageResponse as $item) {
@@ -353,12 +350,6 @@ class MessageController extends BaseController
{
// 检查消息是否已存在
$exists = WechatMessageModel::where('id', $item['id']) ->find();
-
- // 如果消息已存在,直接返回
- if ($exists) {
- return;
- }
-
// 将毫秒时间戳转换为秒级时间戳
$createTime = isset($item['createTime']) ? strtotime($item['createTime']) : null;
$deleteTime = !empty($item['isDeleted']) ? strtotime($item['deleteTime']) : null;
@@ -387,7 +378,8 @@ class MessageController extends BaseController
'wechatTime' => $wechatTime
];
- //已被删除
+
+ //已被删除
if ($item['msgType'] == 10000 && strpos($item['content'],'开启了朋友验证') !== false) {
Db::table('s2_wechat_friend')->where('id',$item['wechatFriendId'])->update(['isDeleted'=> 1,'deleteTime' => $wechatTime]);
}else{
@@ -425,8 +417,19 @@ class MessageController extends BaseController
}
}
}
- // 创建新记录
- $res = WechatMessageModel::create($data);
+
+ $id = '';
+ if (empty($exists)){
+ // 创建新记录
+ $res = WechatMessageModel::create($data);
+ $id= $res['id'];
+ }else{
+ $id = $data['id'];
+ unset($data['id']);
+ $res = $exists->save($data);
+ }
+
+
// 1 文字 3图片 47动态图片 34语言 43视频 42名片 40/20链接 49文件
if (!empty($res) && empty($item['isSend']) && in_array($item['msgType'],[1,3,20,34,40,42,43,47,49])){
@@ -439,13 +442,14 @@ class MessageController extends BaseController
'companyId' => $friend['companyId'],
'trafficPoolId' => $trafficPoolId,
'source' => 0,
- 'uniqueId' => $res['id'],
+ 'uniqueId' => $id,
'sourceData' => json_encode([]),
'remark' => '用户发送了消息',
'createTime' => time(),
'updateTime' => time()
];
- Db::name('user_portrait')->insert($data);
+ Db::name('user_portrait')->insert($data);
+
}
}
}
@@ -461,11 +465,7 @@ class MessageController extends BaseController
{
// 检查消息是否已存在
$exists = WechatMessageModel::where('id', $item['id'])->find();
-
- // 如果消息已存在,直接返回
- if ($exists) {
- return true;
- }
+
// 处理发送者信息
$sender = $item['sender'] ?? [];
@@ -515,7 +515,12 @@ class MessageController extends BaseController
// 创建新记录
try {
- WechatMessageModel::create($data);
+ if(empty($exists)){
+ WechatMessageModel::create($data);
+ }else{
+ unset($data['id']);
+ $exists->save($data);
+ }
return true;
} catch (\Exception $e) {
return false;
From 0bc6c3a22a225f380ab67588c330a211eb53ff52 Mon Sep 17 00:00:00 2001
From: wong <106998207@qq.com>
Date: Mon, 1 Dec 2025 16:41:40 +0800
Subject: [PATCH 05/10] =?UTF-8?q?=E4=BB=A3=E7=A0=81=E4=BC=98=E5=8C=96?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../command/TaskSchedulerCommand.php | 17 +++++++++++++++--
1 file changed, 15 insertions(+), 2 deletions(-)
diff --git a/Server/application/command/TaskSchedulerCommand.php b/Server/application/command/TaskSchedulerCommand.php
index 06a1dbaf..b91bb06d 100644
--- a/Server/application/command/TaskSchedulerCommand.php
+++ b/Server/application/command/TaskSchedulerCommand.php
@@ -61,10 +61,23 @@ class TaskSchedulerCommand extends Command
$this->maxConcurrent = 1;
}
- // 加载任务配置
+ // 加载任务配置(优先使用框架配置,其次直接引入配置文件,避免加载失败)
$this->tasks = Config::get('task_scheduler', []);
+
+ // 如果通过 Config 没有读到,再尝试直接 include 配置文件
if (empty($this->tasks)) {
- $output->writeln('错误:未找到任务配置');
+ // 以项目根目录为基准查找 config/task_scheduler.php
+ $configFile = dirname(__DIR__, 2) . DIRECTORY_SEPARATOR . 'config' . DIRECTORY_SEPARATOR . 'task_scheduler.php';
+ if (is_file($configFile)) {
+ $config = include $configFile;
+ if (is_array($config) && !empty($config)) {
+ $this->tasks = $config;
+ }
+ }
+ }
+
+ if (empty($this->tasks)) {
+ $output->writeln('错误:未找到任务配置(task_scheduler),请检查 config/task_scheduler.php 是否存在且返回数组');
return false;
}
From ff7097f2d961005f75b6ab543042d6dddc6d7fc6 Mon Sep 17 00:00:00 2001
From: wong <106998207@qq.com>
Date: Mon, 1 Dec 2025 16:46:23 +0800
Subject: [PATCH 06/10] 1
---
Server/application/command/TaskSchedulerCommand.php | 7 ++++---
1 file changed, 4 insertions(+), 3 deletions(-)
diff --git a/Server/application/command/TaskSchedulerCommand.php b/Server/application/command/TaskSchedulerCommand.php
index b91bb06d..0ad3cc48 100644
--- a/Server/application/command/TaskSchedulerCommand.php
+++ b/Server/application/command/TaskSchedulerCommand.php
@@ -81,8 +81,8 @@ class TaskSchedulerCommand extends Command
return false;
}
- // 设置日志目录
- $this->logDir = runtime_path() . 'log' . DIRECTORY_SEPARATOR;
+ // 设置日志目录(注意要使用全局函数,避免命名空间影响)
+ $this->logDir = \runtime_path() . 'log' . DIRECTORY_SEPARATOR;
if (!is_dir($this->logDir)) {
mkdir($this->logDir, 0755, true);
}
@@ -333,7 +333,8 @@ class TaskSchedulerCommand extends Command
}
// 构建命令
- $thinkPath = root_path() . 'think';
+ // 使用项目根目录下的 think 脚本(同命令行 php think)
+ $thinkPath = \root_path() . 'think';
$command = "php {$thinkPath} {$task['command']}";
if (!empty($task['options'])) {
foreach ($task['options'] as $option) {
From 2939b63998d03aaabded67d04f48b102b205173b Mon Sep 17 00:00:00 2001
From: wong <106998207@qq.com>
Date: Mon, 1 Dec 2025 16:47:57 +0800
Subject: [PATCH 07/10] 1
---
.../application/command/TaskSchedulerCommand.php | 15 +++++++++++----
1 file changed, 11 insertions(+), 4 deletions(-)
diff --git a/Server/application/command/TaskSchedulerCommand.php b/Server/application/command/TaskSchedulerCommand.php
index 0ad3cc48..9cad5c14 100644
--- a/Server/application/command/TaskSchedulerCommand.php
+++ b/Server/application/command/TaskSchedulerCommand.php
@@ -81,8 +81,12 @@ class TaskSchedulerCommand extends Command
return false;
}
- // 设置日志目录(注意要使用全局函数,避免命名空间影响)
- $this->logDir = \runtime_path() . 'log' . DIRECTORY_SEPARATOR;
+ // 设置日志目录(ThinkPHP5 中无 runtime_path 辅助函数,直接使用 ROOT_PATH/runtime/log)
+ if (!defined('ROOT_PATH')) {
+ // CLI 下正常情况下 ROOT_PATH 已在入口脚本 define,这里兜底一次
+ define('ROOT_PATH', dirname(__DIR__, 2));
+ }
+ $this->logDir = ROOT_PATH . DIRECTORY_SEPARATOR . 'runtime' . DIRECTORY_SEPARATOR . 'log' . DIRECTORY_SEPARATOR;
if (!is_dir($this->logDir)) {
mkdir($this->logDir, 0755, true);
}
@@ -334,7 +338,10 @@ class TaskSchedulerCommand extends Command
// 构建命令
// 使用项目根目录下的 think 脚本(同命令行 php think)
- $thinkPath = \root_path() . 'think';
+ if (!defined('ROOT_PATH')) {
+ define('ROOT_PATH', dirname(__DIR__, 2));
+ }
+ $thinkPath = ROOT_PATH . DIRECTORY_SEPARATOR . 'think';
$command = "php {$thinkPath} {$task['command']}";
if (!empty($task['options'])) {
foreach ($task['options'] as $option) {
@@ -360,7 +367,7 @@ class TaskSchedulerCommand extends Command
2 => ['file', $logFile, 'a'], // stderr
];
- $process = @proc_open($command, $descriptorspec, $pipes, root_path());
+ $process = @proc_open($command, $descriptorspec, $pipes, ROOT_PATH);
if (is_resource($process)) {
// 关闭管道
From 2c37314c4fdf49d19660eb6c694677f041e45379 Mon Sep 17 00:00:00 2001
From: wong <106998207@qq.com>
Date: Mon, 1 Dec 2025 17:41:57 +0800
Subject: [PATCH 08/10] =?UTF-8?q?=E4=BB=A3=E7=A0=81=E4=BC=98=E5=8C=96?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
Server/application/api/controller/MessageController.php | 9 +++++++++
1 file changed, 9 insertions(+)
diff --git a/Server/application/api/controller/MessageController.php b/Server/application/api/controller/MessageController.php
index 734f3f7d..0f7f6d3d 100644
--- a/Server/application/api/controller/MessageController.php
+++ b/Server/application/api/controller/MessageController.php
@@ -350,6 +350,12 @@ class MessageController extends BaseController
{
// 检查消息是否已存在
$exists = WechatMessageModel::where('id', $item['id']) ->find();
+
+ if ($exists['sendStatus'] == 0){
+ return true;
+ }
+
+
// 将毫秒时间戳转换为秒级时间戳
$createTime = isset($item['createTime']) ? strtotime($item['createTime']) : null;
$deleteTime = !empty($item['isDeleted']) ? strtotime($item['deleteTime']) : null;
@@ -466,6 +472,9 @@ class MessageController extends BaseController
// 检查消息是否已存在
$exists = WechatMessageModel::where('id', $item['id'])->find();
+ if ($exists['sendStatus'] == 0){
+ return true;
+ }
// 处理发送者信息
$sender = $item['sender'] ?? [];
From 354d6c4f6276400e278cf14be896b38135bb82a8 Mon Sep 17 00:00:00 2001
From: wong <106998207@qq.com>
Date: Mon, 1 Dec 2025 18:09:06 +0800
Subject: [PATCH 09/10] =?UTF-8?q?=E4=BB=A3=E7=A0=81=E4=BC=98=E5=8C=96?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
Server/application/api/controller/MessageController.php | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/Server/application/api/controller/MessageController.php b/Server/application/api/controller/MessageController.php
index 0f7f6d3d..98b4fe49 100644
--- a/Server/application/api/controller/MessageController.php
+++ b/Server/application/api/controller/MessageController.php
@@ -351,7 +351,7 @@ class MessageController extends BaseController
// 检查消息是否已存在
$exists = WechatMessageModel::where('id', $item['id']) ->find();
- if ($exists['sendStatus'] == 0){
+ if (!empty($exists) && $exists['sendStatus'] == 0){
return true;
}
@@ -472,7 +472,7 @@ class MessageController extends BaseController
// 检查消息是否已存在
$exists = WechatMessageModel::where('id', $item['id'])->find();
- if ($exists['sendStatus'] == 0){
+ if (!empty($exists) && $exists['sendStatus'] == 0){
return true;
}
From 5f5b567749ac255355957a6691ef26ba0c1d32ee Mon Sep 17 00:00:00 2001
From: wong <106998207@qq.com>
Date: Tue, 2 Dec 2025 10:51:27 +0800
Subject: [PATCH 10/10] =?UTF-8?q?=E8=B0=83=E6=95=B4=E6=B6=88=E6=81=AF?=
=?UTF-8?q?=E5=90=8C=E6=AD=A5=E5=A4=84=E7=90=86?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
Server/application/api/controller/MessageController.php | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/Server/application/api/controller/MessageController.php b/Server/application/api/controller/MessageController.php
index 98b4fe49..87575f31 100644
--- a/Server/application/api/controller/MessageController.php
+++ b/Server/application/api/controller/MessageController.php
@@ -75,7 +75,7 @@ class MessageController extends BaseController
'keyword' => '',
'msgType' => '',
'accountId' => '',
- 'count' => 100,
+ 'count' => 20,
'messageId' => '',
'olderData' => true,
'wechatAccountId' => $friend['wechatAccountId'],
@@ -238,7 +238,7 @@ class MessageController extends BaseController
'keyword' => '',
'msgType' =>'',
'accountId' => '',
- 'count' => 100,
+ 'count' => 20,
'messageId' => '',
'olderData' => true,
'wechatId' => '',