commit 04bad9184679d0a63e2d6b460e87b3ad06f2c077 Author: lingling <1077478963@qq.com> Date: Tue Apr 16 10:41:39 2024 +0800 第一次提交 diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..516299c --- /dev/null +++ b/.gitignore @@ -0,0 +1,8 @@ +/runtime +/.idea +/.vscode +/vendor +*.log +.env +/tests/tmp +/tests/.phpunit.result.cache diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..2c66292 --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2021 walkor and contributors (see https://github.com/walkor/webman/contributors) + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/README.md b/README.md new file mode 100644 index 0000000..9538cd9 --- /dev/null +++ b/README.md @@ -0,0 +1,59 @@ +
+

webman

+ +基于workerman开发的超高性能PHP框架 + + +

学习

+ + + +
+ +

赞助商

+ +

特别赞助

+ + + + +

铂金赞助

+ + + +

金牌赞助

+ + +
+ + +
+

LICENSE

+The webman is open-sourced software licensed under the MIT. +
+ +
+ + diff --git a/app/controller/IndexController.php b/app/controller/IndexController.php new file mode 100644 index 0000000..435a182 --- /dev/null +++ b/app/controller/IndexController.php @@ -0,0 +1,28 @@ + 'webman']); + } + + public function json(Request $request) + { + return json(['code' => 0, 'msg' => 'ok']); + } + +} diff --git a/app/functions.php b/app/functions.php new file mode 100644 index 0000000..5c9c58d --- /dev/null +++ b/app/functions.php @@ -0,0 +1,4 @@ + + * @copyright walkor + * @link http://www.workerman.net/ + * @license http://www.opensource.org/licenses/mit-license.php MIT License + */ + +namespace app\middleware; + +use Webman\MiddlewareInterface; +use Webman\Http\Response; +use Webman\Http\Request; + +/** + * Class StaticFile + * @package app\middleware + */ +class StaticFile implements MiddlewareInterface +{ + public function process(Request $request, callable $next): Response + { + // Access to files beginning with. Is prohibited + if (strpos($request->path(), '/.') !== false) { + return response('

403 forbidden

', 403); + } + /** @var Response $response */ + $response = $next($request); + // Add cross domain HTTP header + /*$response->withHeaders([ + 'Access-Control-Allow-Origin' => '*', + 'Access-Control-Allow-Credentials' => 'true', + ]);*/ + return $response; + } +} diff --git a/app/model/Test.php b/app/model/Test.php new file mode 100644 index 0000000..92d70e3 --- /dev/null +++ b/app/model/Test.php @@ -0,0 +1,29 @@ + + + + + + + + webman + + + +hello + + diff --git a/composer.json b/composer.json new file mode 100644 index 0000000..2bf1db9 --- /dev/null +++ b/composer.json @@ -0,0 +1,56 @@ +{ + "name": "workerman/webman", + "type": "project", + "keywords": [ + "high performance", + "http service" + ], + "homepage": "https://www.workerman.net", + "license": "MIT", + "description": "High performance HTTP Service Framework.", + "authors": [ + { + "name": "walkor", + "email": "walkor@workerman.net", + "homepage": "https://www.workerman.net", + "role": "Developer" + } + ], + "support": { + "email": "walkor@workerman.net", + "issues": "https://github.com/walkor/webman/issues", + "forum": "https://wenda.workerman.net/", + "wiki": "https://workerman.net/doc/webman", + "source": "https://github.com/walkor/webman" + }, + "require": { + "php": ">=7.2", + "workerman/webman-framework": "^1.5.0", + "monolog/monolog": "^2.0" + }, + "suggest": { + "ext-event": "For better performance. " + }, + "autoload": { + "psr-4": { + "": "./", + "app\\": "./app", + "App\\": "./app", + "app\\View\\Components\\": "./app/view/components" + }, + "files": [ + "./support/helpers.php" + ] + }, + "scripts": { + "post-package-install": [ + "support\\Plugin::install" + ], + "post-package-update": [ + "support\\Plugin::install" + ], + "pre-package-uninstall": [ + "support\\Plugin::uninstall" + ] + } +} diff --git a/composer.lock b/composer.lock new file mode 100644 index 0000000..81cf567 --- /dev/null +++ b/composer.lock @@ -0,0 +1,401 @@ +{ + "_readme": [ + "This file locks the dependencies of your project to a known state", + "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", + "This file is @generated automatically" + ], + "content-hash": "6ec3c93a41026fd9ff565142f2ec2413", + "packages": [ + { + "name": "monolog/monolog", + "version": "2.9.3", + "source": { + "type": "git", + "url": "https://github.com/Seldaek/monolog.git", + "reference": "a30bfe2e142720dfa990d0a7e573997f5d884215" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/Seldaek/monolog/zipball/a30bfe2e142720dfa990d0a7e573997f5d884215", + "reference": "a30bfe2e142720dfa990d0a7e573997f5d884215", + "shasum": "" + }, + "require": { + "php": ">=7.2", + "psr/log": "^1.0.1 || ^2.0 || ^3.0" + }, + "provide": { + "psr/log-implementation": "1.0.0 || 2.0.0 || 3.0.0" + }, + "require-dev": { + "aws/aws-sdk-php": "^2.4.9 || ^3.0", + "doctrine/couchdb": "~1.0@dev", + "elasticsearch/elasticsearch": "^7 || ^8", + "ext-json": "*", + "graylog2/gelf-php": "^1.4.2 || ^2@dev", + "guzzlehttp/guzzle": "^7.4", + "guzzlehttp/psr7": "^2.2", + "mongodb/mongodb": "^1.8", + "php-amqplib/php-amqplib": "~2.4 || ^3", + "phpspec/prophecy": "^1.15", + "phpstan/phpstan": "^1.10", + "phpunit/phpunit": "^8.5.38 || ^9.6.19", + "predis/predis": "^1.1 || ^2.0", + "rollbar/rollbar": "^1.3 || ^2 || ^3", + "ruflin/elastica": "^7", + "swiftmailer/swiftmailer": "^5.3|^6.0", + "symfony/mailer": "^5.4 || ^6", + "symfony/mime": "^5.4 || ^6" + }, + "suggest": { + "aws/aws-sdk-php": "Allow sending log messages to AWS services like DynamoDB", + "doctrine/couchdb": "Allow sending log messages to a CouchDB server", + "elasticsearch/elasticsearch": "Allow sending log messages to an Elasticsearch server via official client", + "ext-amqp": "Allow sending log messages to an AMQP server (1.0+ required)", + "ext-curl": "Required to send log messages using the IFTTTHandler, the LogglyHandler, the SendGridHandler, the SlackWebhookHandler or the TelegramBotHandler", + "ext-mbstring": "Allow to work properly with unicode symbols", + "ext-mongodb": "Allow sending log messages to a MongoDB server (via driver)", + "ext-openssl": "Required to send log messages using SSL", + "ext-sockets": "Allow sending log messages to a Syslog server (via UDP driver)", + "graylog2/gelf-php": "Allow sending log messages to a GrayLog2 server", + "mongodb/mongodb": "Allow sending log messages to a MongoDB server (via library)", + "php-amqplib/php-amqplib": "Allow sending log messages to an AMQP server using php-amqplib", + "rollbar/rollbar": "Allow sending log messages to Rollbar", + "ruflin/elastica": "Allow sending log messages to an Elastic Search server" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "2.x-dev" + } + }, + "autoload": { + "psr-4": { + "Monolog\\": "src/Monolog" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Jordi Boggiano", + "email": "j.boggiano@seld.be", + "homepage": "https://seld.be" + } + ], + "description": "Sends your logs to files, sockets, inboxes, databases and various web services", + "homepage": "https://github.com/Seldaek/monolog", + "keywords": [ + "log", + "logging", + "psr-3" + ], + "support": { + "issues": "https://github.com/Seldaek/monolog/issues", + "source": "https://github.com/Seldaek/monolog/tree/2.9.3" + }, + "funding": [ + { + "url": "https://github.com/Seldaek", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/monolog/monolog", + "type": "tidelift" + } + ], + "time": "2024-04-12T20:52:51+00:00" + }, + { + "name": "nikic/fast-route", + "version": "v1.3.0", + "source": { + "type": "git", + "url": "https://github.com/nikic/FastRoute.git", + "reference": "181d480e08d9476e61381e04a71b34dc0432e812" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/nikic/FastRoute/zipball/181d480e08d9476e61381e04a71b34dc0432e812", + "reference": "181d480e08d9476e61381e04a71b34dc0432e812", + "shasum": "" + }, + "require": { + "php": ">=5.4.0" + }, + "require-dev": { + "phpunit/phpunit": "^4.8.35|~5.7" + }, + "type": "library", + "autoload": { + "files": [ + "src/functions.php" + ], + "psr-4": { + "FastRoute\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Nikita Popov", + "email": "nikic@php.net" + } + ], + "description": "Fast request router for PHP", + "keywords": [ + "router", + "routing" + ], + "support": { + "issues": "https://github.com/nikic/FastRoute/issues", + "source": "https://github.com/nikic/FastRoute/tree/master" + }, + "time": "2018-02-13T20:26:39+00:00" + }, + { + "name": "psr/container", + "version": "2.0.1", + "source": { + "type": "git", + "url": "https://github.com/php-fig/container.git", + "reference": "2ae37329ee82f91efadc282cc2d527fd6065a5ef" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/container/zipball/2ae37329ee82f91efadc282cc2d527fd6065a5ef", + "reference": "2ae37329ee82f91efadc282cc2d527fd6065a5ef", + "shasum": "" + }, + "require": { + "php": ">=7.2.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.1" + }, + "time": "2021-03-24T13:40:57+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": "workerman/webman-framework", + "version": "v1.5.16", + "source": { + "type": "git", + "url": "https://github.com/walkor/webman-framework.git", + "reference": "84335520a340ee60adf7cf17aeb0edb9536c24e8" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/walkor/webman-framework/zipball/84335520a340ee60adf7cf17aeb0edb9536c24e8", + "reference": "84335520a340ee60adf7cf17aeb0edb9536c24e8", + "shasum": "" + }, + "require": { + "ext-json": "*", + "nikic/fast-route": "^1.3", + "php": ">=7.2", + "psr/container": ">=1.0", + "workerman/workerman": "^4.0.4 || ^5.0.0" + }, + "suggest": { + "ext-event": "For better performance. " + }, + "type": "library", + "autoload": { + "psr-4": { + "Webman\\": "./src", + "Support\\": "./src/support", + "support\\": "./src/support", + "Support\\View\\": "./src/support/view", + "Support\\Bootstrap\\": "./src/support/bootstrap", + "Support\\Exception\\": "./src/support/exception" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "walkor", + "email": "walkor@workerman.net", + "homepage": "https://www.workerman.net", + "role": "Developer" + } + ], + "description": "High performance HTTP Service Framework.", + "homepage": "https://www.workerman.net", + "keywords": [ + "High Performance", + "http service" + ], + "support": { + "email": "walkor@workerman.net", + "forum": "https://wenda.workerman.net/", + "issues": "https://github.com/walkor/webman/issues", + "source": "https://github.com/walkor/webman-framework", + "wiki": "https://doc.workerman.net/" + }, + "time": "2024-01-15T12:11:49+00:00" + }, + { + "name": "workerman/workerman", + "version": "v4.1.15", + "source": { + "type": "git", + "url": "https://github.com/walkor/workerman.git", + "reference": "afc8242fc769ab7cf22eb4ac22b97cb59d465e4e" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/walkor/workerman/zipball/afc8242fc769ab7cf22eb4ac22b97cb59d465e4e", + "reference": "afc8242fc769ab7cf22eb4ac22b97cb59d465e4e", + "shasum": "" + }, + "require": { + "php": ">=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": "2024-02-19T02:10:39+00:00" + } + ], + "packages-dev": [], + "aliases": [], + "minimum-stability": "stable", + "stability-flags": [], + "prefer-stable": false, + "prefer-lowest": false, + "platform": { + "php": ">=7.2" + }, + "platform-dev": [], + "plugin-api-version": "2.3.0" +} diff --git a/config/app.php b/config/app.php new file mode 100644 index 0000000..f26e358 --- /dev/null +++ b/config/app.php @@ -0,0 +1,26 @@ + + * @copyright walkor + * @link http://www.workerman.net/ + * @license http://www.opensource.org/licenses/mit-license.php MIT License + */ + +use support\Request; + +return [ + 'debug' => true, + 'error_reporting' => E_ALL, + 'default_timezone' => 'Asia/Shanghai', + 'request_class' => Request::class, + 'public_path' => base_path() . DIRECTORY_SEPARATOR . 'public', + 'runtime_path' => base_path(false) . DIRECTORY_SEPARATOR . 'runtime', + 'controller_suffix' => 'Controller', + 'controller_reuse' => false, +]; diff --git a/config/autoload.php b/config/autoload.php new file mode 100644 index 0000000..69a8135 --- /dev/null +++ b/config/autoload.php @@ -0,0 +1,21 @@ + + * @copyright walkor + * @link http://www.workerman.net/ + * @license http://www.opensource.org/licenses/mit-license.php MIT License + */ + +return [ + 'files' => [ + base_path() . '/app/functions.php', + base_path() . '/support/Request.php', + base_path() . '/support/Response.php', + ] +]; diff --git a/config/bootstrap.php b/config/bootstrap.php new file mode 100644 index 0000000..44054e0 --- /dev/null +++ b/config/bootstrap.php @@ -0,0 +1,18 @@ + + * @copyright walkor + * @link http://www.workerman.net/ + * @license http://www.opensource.org/licenses/mit-license.php MIT License + */ + +return [ + support\bootstrap\Session::class, + support\bootstrap\LaravelDb::class, +]; diff --git a/config/container.php b/config/container.php new file mode 100644 index 0000000..106b7b4 --- /dev/null +++ b/config/container.php @@ -0,0 +1,15 @@ + + * @copyright walkor + * @link http://www.workerman.net/ + * @license http://www.opensource.org/licenses/mit-license.php MIT License + */ + +return new Webman\Container; \ No newline at end of file diff --git a/config/database.php b/config/database.php new file mode 100644 index 0000000..7dc463a --- /dev/null +++ b/config/database.php @@ -0,0 +1,15 @@ + + * @copyright walkor + * @link http://www.workerman.net/ + * @license http://www.opensource.org/licenses/mit-license.php MIT License + */ + +return []; diff --git a/config/dependence.php b/config/dependence.php new file mode 100644 index 0000000..8e964ed --- /dev/null +++ b/config/dependence.php @@ -0,0 +1,15 @@ + + * @copyright walkor + * @link http://www.workerman.net/ + * @license http://www.opensource.org/licenses/mit-license.php MIT License + */ + +return []; \ No newline at end of file diff --git a/config/exception.php b/config/exception.php new file mode 100644 index 0000000..f2aede3 --- /dev/null +++ b/config/exception.php @@ -0,0 +1,17 @@ + + * @copyright walkor + * @link http://www.workerman.net/ + * @license http://www.opensource.org/licenses/mit-license.php MIT License + */ + +return [ + '' => support\exception\Handler::class, +]; \ No newline at end of file diff --git a/config/log.php b/config/log.php new file mode 100644 index 0000000..7f05de5 --- /dev/null +++ b/config/log.php @@ -0,0 +1,32 @@ + + * @copyright walkor + * @link http://www.workerman.net/ + * @license http://www.opensource.org/licenses/mit-license.php MIT License + */ + +return [ + 'default' => [ + 'handlers' => [ + [ + 'class' => Monolog\Handler\RotatingFileHandler::class, + 'constructor' => [ + runtime_path() . '/logs/webman.log', + 7, //$maxFiles + Monolog\Logger::DEBUG, + ], + 'formatter' => [ + 'class' => Monolog\Formatter\LineFormatter::class, + 'constructor' => [null, 'Y-m-d H:i:s', true], + ], + ] + ], + ], +]; diff --git a/config/middleware.php b/config/middleware.php new file mode 100644 index 0000000..8e964ed --- /dev/null +++ b/config/middleware.php @@ -0,0 +1,15 @@ + + * @copyright walkor + * @link http://www.workerman.net/ + * @license http://www.opensource.org/licenses/mit-license.php MIT License + */ + +return []; \ No newline at end of file diff --git a/config/process.php b/config/process.php new file mode 100644 index 0000000..f94d27f --- /dev/null +++ b/config/process.php @@ -0,0 +1,42 @@ + + * @copyright walkor + * @link http://www.workerman.net/ + * @license http://www.opensource.org/licenses/mit-license.php MIT License + */ + +global $argv; + +return [ + // File update detection and automatic reload + 'monitor' => [ + 'handler' => process\Monitor::class, + 'reloadable' => false, + 'constructor' => [ + // Monitor these directories + 'monitorDir' => array_merge([ + app_path(), + config_path(), + base_path() . '/process', + base_path() . '/support', + base_path() . '/resource', + base_path() . '/.env', + ], glob(base_path() . '/plugin/*/app'), glob(base_path() . '/plugin/*/config'), glob(base_path() . '/plugin/*/api')), + // Files with these suffixes will be monitored + 'monitorExtensions' => [ + 'php', 'html', 'htm', 'env' + ], + 'options' => [ + 'enable_file_monitor' => !in_array('-d', $argv) && DIRECTORY_SEPARATOR === '/', + 'enable_memory_monitor' => DIRECTORY_SEPARATOR === '/', + ] + ] + ] +]; diff --git a/config/redis.php b/config/redis.php new file mode 100644 index 0000000..2f9757a --- /dev/null +++ b/config/redis.php @@ -0,0 +1,22 @@ + + * @copyright walkor + * @link http://www.workerman.net/ + * @license http://www.opensource.org/licenses/mit-license.php MIT License + */ + +return [ + 'default' => [ + 'host' => '127.0.0.1', + 'password' => null, + 'port' => 6379, + 'database' => 0, + ], +]; diff --git a/config/route.php b/config/route.php new file mode 100644 index 0000000..a5064fc --- /dev/null +++ b/config/route.php @@ -0,0 +1,21 @@ + + * @copyright walkor + * @link http://www.workerman.net/ + * @license http://www.opensource.org/licenses/mit-license.php MIT License + */ + +use Webman\Route; + + + + + + diff --git a/config/server.php b/config/server.php new file mode 100644 index 0000000..84ea0ef --- /dev/null +++ b/config/server.php @@ -0,0 +1,31 @@ + + * @copyright walkor + * @link http://www.workerman.net/ + * @license http://www.opensource.org/licenses/mit-license.php MIT License + */ + +return [ + 'listen' => 'http://0.0.0.0:8787', + 'transport' => 'tcp', + 'context' => [], + 'name' => 'webman', + 'count' => cpu_count() * 4, + 'user' => '', + 'group' => '', + 'reusePort' => false, + 'event_loop' => '', + 'stop_timeout' => 2, + 'pid_file' => runtime_path() . '/webman.pid', + 'status_file' => runtime_path() . '/webman.status', + 'stdout_file' => runtime_path() . '/logs/stdout.log', + 'log_file' => runtime_path() . '/logs/workerman.log', + 'max_package_size' => 10 * 1024 * 1024 +]; diff --git a/config/session.php b/config/session.php new file mode 100644 index 0000000..043f8c4 --- /dev/null +++ b/config/session.php @@ -0,0 +1,65 @@ + + * @copyright walkor + * @link http://www.workerman.net/ + * @license http://www.opensource.org/licenses/mit-license.php MIT License + */ + +use Webman\Session\FileSessionHandler; +use Webman\Session\RedisSessionHandler; +use Webman\Session\RedisClusterSessionHandler; + +return [ + + 'type' => 'file', // or redis or redis_cluster + + 'handler' => FileSessionHandler::class, + + 'config' => [ + 'file' => [ + 'save_path' => runtime_path() . '/sessions', + ], + 'redis' => [ + 'host' => '127.0.0.1', + 'port' => 6379, + 'auth' => '', + 'timeout' => 2, + 'database' => '', + 'prefix' => 'redis_session_', + ], + 'redis_cluster' => [ + 'host' => ['127.0.0.1:7000', '127.0.0.1:7001', '127.0.0.1:7001'], + 'timeout' => 2, + 'auth' => '', + 'prefix' => 'redis_session_', + ] + ], + + 'session_name' => 'PHPSID', + + 'auto_update_timestamp' => false, + + 'lifetime' => 7*24*60*60, + + 'cookie_lifetime' => 365*24*60*60, + + 'cookie_path' => '/', + + 'domain' => '', + + 'http_only' => true, + + 'secure' => false, + + 'same_site' => '', + + 'gc_probability' => [1, 1000], + +]; diff --git a/config/static.php b/config/static.php new file mode 100644 index 0000000..6313679 --- /dev/null +++ b/config/static.php @@ -0,0 +1,23 @@ + + * @copyright walkor + * @link http://www.workerman.net/ + * @license http://www.opensource.org/licenses/mit-license.php MIT License + */ + +/** + * Static file settings + */ +return [ + 'enable' => true, + 'middleware' => [ // Static file Middleware + //app\middleware\StaticFile::class, + ], +]; \ No newline at end of file diff --git a/config/translation.php b/config/translation.php new file mode 100644 index 0000000..96589b2 --- /dev/null +++ b/config/translation.php @@ -0,0 +1,25 @@ + + * @copyright walkor + * @link http://www.workerman.net/ + * @license http://www.opensource.org/licenses/mit-license.php MIT License + */ + +/** + * Multilingual configuration + */ +return [ + // Default language + 'locale' => 'zh_CN', + // Fallback language + 'fallback_locale' => ['zh_CN', 'en'], + // Folder where language files are stored + 'path' => base_path() . '/resource/translations', +]; \ No newline at end of file diff --git a/config/view.php b/config/view.php new file mode 100644 index 0000000..e3a7b85 --- /dev/null +++ b/config/view.php @@ -0,0 +1,22 @@ + + * @copyright walkor + * @link http://www.workerman.net/ + * @license http://www.opensource.org/licenses/mit-license.php MIT License + */ + +use support\view\Raw; +use support\view\Twig; +use support\view\Blade; +use support\view\ThinkPHP; + +return [ + 'handler' => Raw::class +]; diff --git a/process/Monitor.php b/process/Monitor.php new file mode 100644 index 0000000..92b3716 --- /dev/null +++ b/process/Monitor.php @@ -0,0 +1,243 @@ + + * @copyright walkor + * @link http://www.workerman.net/ + * @license http://www.opensource.org/licenses/mit-license.php MIT License + */ + +namespace process; + +use FilesystemIterator; +use RecursiveDirectoryIterator; +use RecursiveIteratorIterator; +use SplFileInfo; +use Workerman\Timer; +use Workerman\Worker; + +/** + * Class FileMonitor + * @package process + */ +class Monitor +{ + /** + * @var array + */ + protected $paths = []; + + /** + * @var array + */ + protected $extensions = []; + + /** + * @var string + */ + public static $lockFile = __DIR__ . '/../runtime/monitor.lock'; + + /** + * Pause monitor + * @return void + */ + public static function pause() + { + file_put_contents(static::$lockFile, time()); + } + + /** + * Resume monitor + * @return void + */ + public static function resume(): void + { + clearstatcache(); + if (is_file(static::$lockFile)) { + unlink(static::$lockFile); + } + } + + /** + * Whether monitor is paused + * @return bool + */ + public static function isPaused(): bool + { + clearstatcache(); + return file_exists(static::$lockFile); + } + + /** + * FileMonitor constructor. + * @param $monitorDir + * @param $monitorExtensions + * @param array $options + */ + public function __construct($monitorDir, $monitorExtensions, array $options = []) + { + static::resume(); + $this->paths = (array)$monitorDir; + $this->extensions = $monitorExtensions; + if (!Worker::getAllWorkers()) { + return; + } + $disableFunctions = explode(',', ini_get('disable_functions')); + if (in_array('exec', $disableFunctions, true)) { + echo "\nMonitor file change turned off because exec() has been disabled by disable_functions setting in " . PHP_CONFIG_FILE_PATH . "/php.ini\n"; + } else { + if ($options['enable_file_monitor'] ?? true) { + Timer::add(1, function () { + $this->checkAllFilesChange(); + }); + } + } + + $memoryLimit = $this->getMemoryLimit($options['memory_limit'] ?? null); + if ($memoryLimit && ($options['enable_memory_monitor'] ?? true)) { + Timer::add(60, [$this, 'checkMemory'], [$memoryLimit]); + } + } + + /** + * @param $monitorDir + * @return bool + */ + public function checkFilesChange($monitorDir): bool + { + static $lastMtime, $tooManyFilesCheck; + if (!$lastMtime) { + $lastMtime = time(); + } + clearstatcache(); + if (!is_dir($monitorDir)) { + if (!is_file($monitorDir)) { + return false; + } + $iterator = [new SplFileInfo($monitorDir)]; + } else { + // recursive traversal directory + $dirIterator = new RecursiveDirectoryIterator($monitorDir, FilesystemIterator::SKIP_DOTS | FilesystemIterator::FOLLOW_SYMLINKS); + $iterator = new RecursiveIteratorIterator($dirIterator); + } + $count = 0; + foreach ($iterator as $file) { + $count ++; + /** var SplFileInfo $file */ + if (is_dir($file->getRealPath())) { + continue; + } + // check mtime + if (in_array($file->getExtension(), $this->extensions, true) && $lastMtime < $file->getMTime()) { + $var = 0; + exec('"'.PHP_BINARY . '" -l ' . $file, $out, $var); + $lastMtime = $file->getMTime(); + if ($var) { + continue; + } + echo $file . " update and reload\n"; + // send SIGUSR1 signal to master process for reload + if (DIRECTORY_SEPARATOR === '/') { + posix_kill(posix_getppid(), SIGUSR1); + } else { + return true; + } + break; + } + } + if (!$tooManyFilesCheck && $count > 1000) { + echo "Monitor: There are too many files ($count files) in $monitorDir which makes file monitoring very slow\n"; + $tooManyFilesCheck = 1; + } + return false; + } + + /** + * @return bool + */ + public function checkAllFilesChange(): bool + { + if (static::isPaused()) { + return false; + } + foreach ($this->paths as $path) { + if ($this->checkFilesChange($path)) { + return true; + } + } + return false; + } + + /** + * @param $memoryLimit + * @return void + */ + public function checkMemory($memoryLimit) + { + if (static::isPaused() || $memoryLimit <= 0) { + return; + } + $ppid = posix_getppid(); + $childrenFile = "/proc/$ppid/task/$ppid/children"; + if (!is_file($childrenFile) || !($children = file_get_contents($childrenFile))) { + return; + } + foreach (explode(' ', $children) as $pid) { + $pid = (int)$pid; + $statusFile = "/proc/$pid/status"; + if (!is_file($statusFile) || !($status = file_get_contents($statusFile))) { + continue; + } + $mem = 0; + if (preg_match('/VmRSS\s*?:\s*?(\d+?)\s*?kB/', $status, $match)) { + $mem = $match[1]; + } + $mem = (int)($mem / 1024); + if ($mem >= $memoryLimit) { + posix_kill($pid, SIGINT); + } + } + } + + /** + * Get memory limit + * @return float + */ + protected function getMemoryLimit($memoryLimit) + { + if ($memoryLimit === 0) { + return 0; + } + $usePhpIni = false; + if (!$memoryLimit) { + $memoryLimit = ini_get('memory_limit'); + $usePhpIni = true; + } + + if ($memoryLimit == -1) { + return 0; + } + $unit = strtolower($memoryLimit[strlen($memoryLimit) - 1]); + if ($unit === 'g') { + $memoryLimit = 1024 * (int)$memoryLimit; + } else if ($unit === 'm') { + $memoryLimit = (int)$memoryLimit; + } else if ($unit === 'k') { + $memoryLimit = ((int)$memoryLimit / 1024); + } else { + $memoryLimit = ((int)$memoryLimit / (1024 * 1024)); + } + if ($memoryLimit < 30) { + $memoryLimit = 30; + } + if ($usePhpIni) { + $memoryLimit = (int)(0.8 * $memoryLimit); + } + return $memoryLimit; + } +} diff --git a/public/404.html b/public/404.html new file mode 100644 index 0000000..2bde119 --- /dev/null +++ b/public/404.html @@ -0,0 +1,12 @@ + + + 404 Not Found - webman + + +
+

404 Not Found

+
+
+
webman
+ + diff --git a/public/favicon.ico b/public/favicon.ico new file mode 100644 index 0000000..b9f722e Binary files /dev/null and b/public/favicon.ico differ diff --git a/start.php b/start.php new file mode 100644 index 0000000..489e447 --- /dev/null +++ b/start.php @@ -0,0 +1,4 @@ +#!/usr/bin/env php + + * @copyright walkor + * @link http://www.workerman.net/ + * @license http://www.opensource.org/licenses/mit-license.php MIT License + */ + +namespace support; + +/** + * Class Request + * @package support + */ +class Request extends \Webman\Http\Request +{ + +} \ No newline at end of file diff --git a/support/Response.php b/support/Response.php new file mode 100644 index 0000000..9bc4e1e --- /dev/null +++ b/support/Response.php @@ -0,0 +1,24 @@ + + * @copyright walkor + * @link http://www.workerman.net/ + * @license http://www.opensource.org/licenses/mit-license.php MIT License + */ + +namespace support; + +/** + * Class Response + * @package support + */ +class Response extends \Webman\Http\Response +{ + +} \ No newline at end of file diff --git a/support/bootstrap.php b/support/bootstrap.php new file mode 100644 index 0000000..d9471e6 --- /dev/null +++ b/support/bootstrap.php @@ -0,0 +1,133 @@ + + * @copyright walkor + * @link http://www.workerman.net/ + * @license http://www.opensource.org/licenses/mit-license.php MIT License + */ + +use Dotenv\Dotenv; +use support\Log; +use Webman\Bootstrap; +use Webman\Config; +use Webman\Middleware; +use Webman\Route; +use Webman\Util; + +$worker = $worker ?? null; + +set_error_handler(function ($level, $message, $file = '', $line = 0) { + if (error_reporting() & $level) { + throw new ErrorException($message, 0, $level, $file, $line); + } +}); + +if ($worker) { + register_shutdown_function(function ($startTime) { + if (time() - $startTime <= 0.1) { + sleep(1); + } + }, time()); +} + +if (class_exists('Dotenv\Dotenv') && file_exists(base_path(false) . '/.env')) { + if (method_exists('Dotenv\Dotenv', 'createUnsafeMutable')) { + Dotenv::createUnsafeMutable(base_path(false))->load(); + } else { + Dotenv::createMutable(base_path(false))->load(); + } +} + +Config::clear(); +support\App::loadAllConfig(['route']); +if ($timezone = config('app.default_timezone')) { + date_default_timezone_set($timezone); +} + +foreach (config('autoload.files', []) as $file) { + include_once $file; +} +foreach (config('plugin', []) as $firm => $projects) { + foreach ($projects as $name => $project) { + if (!is_array($project)) { + continue; + } + foreach ($project['autoload']['files'] ?? [] as $file) { + include_once $file; + } + } + foreach ($projects['autoload']['files'] ?? [] as $file) { + include_once $file; + } +} + +Middleware::load(config('middleware', [])); +foreach (config('plugin', []) as $firm => $projects) { + foreach ($projects as $name => $project) { + if (!is_array($project) || $name === 'static') { + continue; + } + Middleware::load($project['middleware'] ?? []); + } + Middleware::load($projects['middleware'] ?? [], $firm); + if ($staticMiddlewares = config("plugin.$firm.static.middleware")) { + Middleware::load(['__static__' => $staticMiddlewares], $firm); + } +} +Middleware::load(['__static__' => config('static.middleware', [])]); + +foreach (config('bootstrap', []) as $className) { + if (!class_exists($className)) { + $log = "Warning: Class $className setting in config/bootstrap.php not found\r\n"; + echo $log; + Log::error($log); + continue; + } + /** @var Bootstrap $className */ + $className::start($worker); +} + +foreach (config('plugin', []) as $firm => $projects) { + foreach ($projects as $name => $project) { + if (!is_array($project)) { + continue; + } + foreach ($project['bootstrap'] ?? [] as $className) { + if (!class_exists($className)) { + $log = "Warning: Class $className setting in config/plugin/$firm/$name/bootstrap.php not found\r\n"; + echo $log; + Log::error($log); + continue; + } + /** @var Bootstrap $className */ + $className::start($worker); + } + } + foreach ($projects['bootstrap'] ?? [] as $className) { + /** @var string $className */ + if (!class_exists($className)) { + $log = "Warning: Class $className setting in plugin/$firm/config/bootstrap.php not found\r\n"; + echo $log; + Log::error($log); + continue; + } + /** @var Bootstrap $className */ + $className::start($worker); + } +} + +$directory = base_path() . '/plugin'; +$paths = [config_path()]; +foreach (Util::scanDir($directory) as $path) { + if (is_dir($path = "$path/config")) { + $paths[] = $path; + } +} +Route::load($paths); + diff --git a/support/helpers.php b/support/helpers.php new file mode 100644 index 0000000..8de22c0 --- /dev/null +++ b/support/helpers.php @@ -0,0 +1,528 @@ + + * @copyright walkor + * @link http://www.workerman.net/ + * @license http://www.opensource.org/licenses/mit-license.php MIT License + */ + +use support\Container; +use support\Request; +use support\Response; +use support\Translation; +use support\view\Blade; +use support\view\Raw; +use support\view\ThinkPHP; +use support\view\Twig; +use Twig\Error\LoaderError; +use Twig\Error\RuntimeError; +use Twig\Error\SyntaxError; +use Webman\App; +use Webman\Config; +use Webman\Route; +use Workerman\Protocols\Http\Session; +use Workerman\Worker; + +// Project base path +define('BASE_PATH', dirname(__DIR__)); + +/** + * return the program execute directory + * @param string $path + * @return string + */ +function run_path(string $path = ''): string +{ + static $runPath = ''; + if (!$runPath) { + $runPath = is_phar() ? dirname(Phar::running(false)) : BASE_PATH; + } + return path_combine($runPath, $path); +} + +/** + * if the param $path equal false,will return this program current execute directory + * @param string|false $path + * @return string + */ +function base_path($path = ''): string +{ + if (false === $path) { + return run_path(); + } + return path_combine(BASE_PATH, $path); +} + +/** + * App path + * @param string $path + * @return string + */ +function app_path(string $path = ''): string +{ + return path_combine(BASE_PATH . DIRECTORY_SEPARATOR . 'app', $path); +} + +/** + * Public path + * @param string $path + * @return string + */ +function public_path(string $path = ''): string +{ + static $publicPath = ''; + if (!$publicPath) { + $publicPath = \config('app.public_path') ?: run_path('public'); + } + return path_combine($publicPath, $path); +} + +/** + * Config path + * @param string $path + * @return string + */ +function config_path(string $path = ''): string +{ + return path_combine(BASE_PATH . DIRECTORY_SEPARATOR . 'config', $path); +} + +/** + * Runtime path + * @param string $path + * @return string + */ +function runtime_path(string $path = ''): string +{ + static $runtimePath = ''; + if (!$runtimePath) { + $runtimePath = \config('app.runtime_path') ?: run_path('runtime'); + } + return path_combine($runtimePath, $path); +} + +/** + * Generate paths based on given information + * @param string $front + * @param string $back + * @return string + */ +function path_combine(string $front, string $back): string +{ + return $front . ($back ? (DIRECTORY_SEPARATOR . ltrim($back, DIRECTORY_SEPARATOR)) : $back); +} + +/** + * Response + * @param int $status + * @param array $headers + * @param string $body + * @return Response + */ +function response(string $body = '', int $status = 200, array $headers = []): Response +{ + return new Response($status, $headers, $body); +} + +/** + * Json response + * @param $data + * @param int $options + * @return Response + */ +function json($data, int $options = JSON_UNESCAPED_UNICODE): Response +{ + return new Response(200, ['Content-Type' => 'application/json'], json_encode($data, $options)); +} + +/** + * Xml response + * @param $xml + * @return Response + */ +function xml($xml): Response +{ + if ($xml instanceof SimpleXMLElement) { + $xml = $xml->asXML(); + } + return new Response(200, ['Content-Type' => 'text/xml'], $xml); +} + +/** + * Jsonp response + * @param $data + * @param string $callbackName + * @return Response + */ +function jsonp($data, string $callbackName = 'callback'): Response +{ + if (!is_scalar($data) && null !== $data) { + $data = json_encode($data); + } + return new Response(200, [], "$callbackName($data)"); +} + +/** + * Redirect response + * @param string $location + * @param int $status + * @param array $headers + * @return Response + */ +function redirect(string $location, int $status = 302, array $headers = []): Response +{ + $response = new Response($status, ['Location' => $location]); + if (!empty($headers)) { + $response->withHeaders($headers); + } + return $response; +} + +/** + * View response + * @param string $template + * @param array $vars + * @param string|null $app + * @param string|null $plugin + * @return Response + */ +function view(string $template, array $vars = [], string $app = null, string $plugin = null): Response +{ + $request = \request(); + $plugin = $plugin === null ? ($request->plugin ?? '') : $plugin; + $handler = \config($plugin ? "plugin.$plugin.view.handler" : 'view.handler'); + return new Response(200, [], $handler::render($template, $vars, $app, $plugin)); +} + +/** + * Raw view response + * @param string $template + * @param array $vars + * @param string|null $app + * @return Response + * @throws Throwable + */ +function raw_view(string $template, array $vars = [], string $app = null): Response +{ + return new Response(200, [], Raw::render($template, $vars, $app)); +} + +/** + * Blade view response + * @param string $template + * @param array $vars + * @param string|null $app + * @return Response + */ +function blade_view(string $template, array $vars = [], string $app = null): Response +{ + return new Response(200, [], Blade::render($template, $vars, $app)); +} + +/** + * Think view response + * @param string $template + * @param array $vars + * @param string|null $app + * @return Response + */ +function think_view(string $template, array $vars = [], string $app = null): Response +{ + return new Response(200, [], ThinkPHP::render($template, $vars, $app)); +} + +/** + * Twig view response + * @param string $template + * @param array $vars + * @param string|null $app + * @return Response + * @throws LoaderError + * @throws RuntimeError + * @throws SyntaxError + */ +function twig_view(string $template, array $vars = [], string $app = null): Response +{ + return new Response(200, [], Twig::render($template, $vars, $app)); +} + +/** + * Get request + * @return \Webman\Http\Request|Request|null + */ +function request() +{ + return App::request(); +} + +/** + * Get config + * @param string|null $key + * @param $default + * @return array|mixed|null + */ +function config(string $key = null, $default = null) +{ + return Config::get($key, $default); +} + +/** + * Create url + * @param string $name + * @param ...$parameters + * @return string + */ +function route(string $name, ...$parameters): string +{ + $route = Route::getByName($name); + if (!$route) { + return ''; + } + + if (!$parameters) { + return $route->url(); + } + + if (is_array(current($parameters))) { + $parameters = current($parameters); + } + + return $route->url($parameters); +} + +/** + * Session + * @param mixed $key + * @param mixed $default + * @return mixed|bool|Session + */ +function session($key = null, $default = null) +{ + $session = \request()->session(); + if (null === $key) { + return $session; + } + if (is_array($key)) { + $session->put($key); + return null; + } + if (strpos($key, '.')) { + $keyArray = explode('.', $key); + $value = $session->all(); + foreach ($keyArray as $index) { + if (!isset($value[$index])) { + return $default; + } + $value = $value[$index]; + } + return $value; + } + return $session->get($key, $default); +} + +/** + * Translation + * @param string $id + * @param array $parameters + * @param string|null $domain + * @param string|null $locale + * @return string + */ +function trans(string $id, array $parameters = [], string $domain = null, string $locale = null): string +{ + $res = Translation::trans($id, $parameters, $domain, $locale); + return $res === '' ? $id : $res; +} + +/** + * Locale + * @param string|null $locale + * @return string + */ +function locale(string $locale = null): string +{ + if (!$locale) { + return Translation::getLocale(); + } + Translation::setLocale($locale); + return $locale; +} + +/** + * 404 not found + * @return Response + */ +function not_found(): Response +{ + return new Response(404, [], file_get_contents(public_path() . '/404.html')); +} + +/** + * Copy dir + * @param string $source + * @param string $dest + * @param bool $overwrite + * @return void + */ +function copy_dir(string $source, string $dest, bool $overwrite = false) +{ + if (is_dir($source)) { + if (!is_dir($dest)) { + mkdir($dest); + } + $files = scandir($source); + foreach ($files as $file) { + if ($file !== "." && $file !== "..") { + copy_dir("$source/$file", "$dest/$file", $overwrite); + } + } + } else if (file_exists($source) && ($overwrite || !file_exists($dest))) { + copy($source, $dest); + } +} + +/** + * Remove dir + * @param string $dir + * @return bool + */ +function remove_dir(string $dir): bool +{ + if (is_link($dir) || is_file($dir)) { + return unlink($dir); + } + $files = array_diff(scandir($dir), array('.', '..')); + foreach ($files as $file) { + (is_dir("$dir/$file") && !is_link($dir)) ? remove_dir("$dir/$file") : unlink("$dir/$file"); + } + return rmdir($dir); +} + +/** + * Bind worker + * @param $worker + * @param $class + */ +function worker_bind($worker, $class) +{ + $callbackMap = [ + 'onConnect', + 'onMessage', + 'onClose', + 'onError', + 'onBufferFull', + 'onBufferDrain', + 'onWorkerStop', + 'onWebSocketConnect', + 'onWorkerReload' + ]; + foreach ($callbackMap as $name) { + if (method_exists($class, $name)) { + $worker->$name = [$class, $name]; + } + } + if (method_exists($class, 'onWorkerStart')) { + call_user_func([$class, 'onWorkerStart'], $worker); + } +} + +/** + * Start worker + * @param $processName + * @param $config + * @return void + */ +function worker_start($processName, $config) +{ + $worker = new Worker($config['listen'] ?? null, $config['context'] ?? []); + $propertyMap = [ + 'count', + 'user', + 'group', + 'reloadable', + 'reusePort', + 'transport', + 'protocol', + ]; + $worker->name = $processName; + foreach ($propertyMap as $property) { + if (isset($config[$property])) { + $worker->$property = $config[$property]; + } + } + + $worker->onWorkerStart = function ($worker) use ($config) { + require_once base_path('/support/bootstrap.php'); + if (isset($config['handler'])) { + if (!class_exists($config['handler'])) { + echo "process error: class {$config['handler']} not exists\r\n"; + return; + } + + $instance = Container::make($config['handler'], $config['constructor'] ?? []); + worker_bind($worker, $instance); + } + }; +} + +/** + * Get realpath + * @param string $filePath + * @return string + */ +function get_realpath(string $filePath): string +{ + if (strpos($filePath, 'phar://') === 0) { + return $filePath; + } else { + return realpath($filePath); + } +} + +/** + * Is phar + * @return bool + */ +function is_phar(): bool +{ + return class_exists(Phar::class, false) && Phar::running(); +} + +/** + * Get cpu count + * @return int + */ +function cpu_count(): int +{ + // Windows does not support the number of processes setting. + if (DIRECTORY_SEPARATOR === '\\') { + return 1; + } + $count = 4; + if (is_callable('shell_exec')) { + if (strtolower(PHP_OS) === 'darwin') { + $count = (int)shell_exec('sysctl -n machdep.cpu.core_count'); + } else { + $count = (int)shell_exec('nproc'); + } + } + return $count > 0 ? $count : 4; +} + +/** + * Get request parameters, if no parameter name is passed, an array of all values is returned, default values is supported + * @param string|null $param param's name + * @param mixed|null $default default value + * @return mixed|null + */ +function input(string $param = null, $default = null) +{ + return is_null($param) ? request()->all() : request()->input($param, $default); +} diff --git a/windows.bat b/windows.bat new file mode 100644 index 0000000..f07ce53 --- /dev/null +++ b/windows.bat @@ -0,0 +1,3 @@ +CHCP 65001 +php windows.php +pause \ No newline at end of file diff --git a/windows.php b/windows.php new file mode 100644 index 0000000..21fa888 --- /dev/null +++ b/windows.php @@ -0,0 +1,118 @@ +load(); + } else { + Dotenv::createMutable(base_path())->load(); + } +} + +App::loadAllConfig(['route']); + +$errorReporting = config('app.error_reporting'); +if (isset($errorReporting)) { + error_reporting($errorReporting); +} + +$runtimeProcessPath = runtime_path() . DIRECTORY_SEPARATOR . '/windows'; +if (!is_dir($runtimeProcessPath)) { + mkdir($runtimeProcessPath); +} +$processFiles = [ + __DIR__ . DIRECTORY_SEPARATOR . 'start.php' +]; +foreach (config('process', []) as $processName => $config) { + $processFiles[] = write_process_file($runtimeProcessPath, $processName, ''); +} + +foreach (config('plugin', []) as $firm => $projects) { + foreach ($projects as $name => $project) { + if (!is_array($project)) { + continue; + } + foreach ($project['process'] ?? [] as $processName => $config) { + $processFiles[] = write_process_file($runtimeProcessPath, $processName, "$firm.$name"); + } + } + foreach ($projects['process'] ?? [] as $processName => $config) { + $processFiles[] = write_process_file($runtimeProcessPath, $processName, $firm); + } +} + +function write_process_file($runtimeProcessPath, $processName, $firm): string +{ + $processParam = $firm ? "plugin.$firm.$processName" : $processName; + $configParam = $firm ? "config('plugin.$firm.process')['$processName']" : "config('process')['$processName']"; + $fileContent = << true]); + if (!$resource) { + exit("Can not execute $cmd\r\n"); + } + return $resource; +} + +$resource = popen_processes($processFiles); +echo "\r\n"; +while (1) { + sleep(1); + if (!empty($monitor) && $monitor->checkAllFilesChange()) { + $status = proc_get_status($resource); + $pid = $status['pid']; + shell_exec("taskkill /F /T /PID $pid"); + proc_close($resource); + $resource = popen_processes($processFiles); + } +}