From 5d8ee95964f5668cd1a1288d413085cc0f078ab4 Mon Sep 17 00:00:00 2001 From: Fractal Zombie Date: Wed, 19 Dec 2018 21:11:55 +0200 Subject: [PATCH 1/3] Refactoring. Removes old laravel|lumen versions. Added support for 5.6|5.7 laravel|lumen. Added to config support for hot reload (Next PR). --- .gitignore | 1 + .scrutinizer.yml | 12 + .travis.yml | 12 +- README.md | 2 +- composer.json | 124 ++++----- config/swoole_http.php | 19 +- config/swoole_websocket.php | 4 +- copy_versioned_files.php | 27 ++ phpunit.xml.dist | 10 +- routes/laravel_routes.php | 1 + routes/lumen_routes.php | 4 +- routes/websocket.php | 3 +- src/Commands/HttpServerCommand.php | 114 ++++----- src/Concerns/InteractsWithSwooleTable.php | 29 ++- src/Concerns/InteractsWithWebsocket.php | 238 +++++++++++------- src/Concerns/ResetApplication.php | 9 +- src/Concerns/WithApplication.php | 43 ++-- src/Controllers/SocketIOController.php | 11 +- src/Coroutine/ConnectionException.php | 1 + src/Coroutine/Connectors/ConnectorFactory.php | 106 ++++++++ src/Coroutine/Connectors/MySqlConnector.php | 34 +-- src/Coroutine/Context.php | 18 +- src/Coroutine/MySqlConnection.php | 14 +- src/Coroutine/PDO.php | 159 +++++++++--- src/Coroutine/PDOStatement.php | 101 +++++--- src/Coroutine/StatementException.php | 1 + .../FrameworkNotSupportException.php | 22 ++ src/Exceptions/SandboxException.php | 1 + .../WebsocketNotSetInConfigException.php | 22 ++ src/Helpers/FW.php | 103 ++++++++ src/Helpers/OS.php | 55 ++++ src/Helpers/Service.php | 17 ++ src/HttpServiceProvider.php | 91 +++++-- src/LaravelServiceProvider.php | 3 +- src/LumenServiceProvider.php | 1 + src/Server/Facades/Sandbox.php | 1 + src/Server/Facades/Server.php | 1 + src/Server/Manager.php | 139 +++++----- src/Server/Resetters/BindRequest.php | 9 +- src/Server/Resetters/ClearInstances.php | 6 +- .../Resetters/RebindKernelContainer.php | 13 +- .../Resetters/RebindRouterContainer.php | 17 +- src/Server/Resetters/RebindViewContainer.php | 16 +- src/Server/Resetters/ResetConfig.php | 6 +- src/Server/Resetters/ResetCookie.php | 6 +- src/Server/Resetters/ResetProviders.php | 14 +- src/Server/Resetters/ResetSession.php | 6 +- src/Server/Resetters/ResetterContract.php | 3 +- src/Server/Sandbox.php | 81 ++++-- src/Server/helpers.php | 12 +- src/Table/Facades/SwooleTable.php | 4 + src/Table/SwooleTable.php | 6 +- src/Task/Connectors/SwooleTaskConnector.php | 15 +- src/Task/QueueFactory.php | 108 ++++++++ src/Task/SwooleTaskJob.php | 30 ++- src/Task/SwooleTaskQueue.php | 50 ++-- src/Transformers/Request.php | 34 ++- src/Transformers/Response.php | 23 +- src/Websocket/Authenticatable.php | 43 +++- src/Websocket/Facades/Room.php | 4 + src/Websocket/Facades/Websocket.php | 4 + src/Websocket/HandlerContract.php | 1 + src/Websocket/Middleware/Authenticate.php | 15 +- src/Websocket/Middleware/DecryptCookies.php | 47 ++-- src/Websocket/Middleware/StartSession.php | 26 +- src/Websocket/Parser.php | 8 +- src/Websocket/Push.php | 205 +++++++++++++++ src/Websocket/Rooms/RedisRoom.php | 160 +++++++++--- src/Websocket/Rooms/RoomContract.php | 35 ++- src/Websocket/Rooms/TableRoom.php | 121 +++++++-- src/Websocket/SimpleParser.php | 8 +- src/Websocket/SocketIO/Packet.php | 27 +- src/Websocket/SocketIO/SocketIOParser.php | 11 +- .../SocketIO/Strategies/HeartbeatStrategy.php | 4 + src/Websocket/SocketIO/WebsocketHandler.php | 10 +- src/Websocket/Websocket.php | 63 +++-- stubs/5.5/MySqlConnector.stub | 53 ++++ stubs/5.6/MySqlConnector.stub | 53 ++++ stubs/5.6/SwooleTaskQueue.stub | 114 +++++++++ stubs/5.7/SwooleTaskQueue.stub | 115 +++++++++ tests/Coroutine/ConnectorFactoryTest.php | 45 ++++ tests/Coroutine/ContextTest.php | 7 +- tests/Server/ManagerTest.php | 77 +++--- tests/Server/ResettersTest.php | 31 ++- tests/Server/SandboxTest.php | 45 +++- tests/SocketIO/PacketTest.php | 15 +- tests/SocketIO/ParserTest.php | 11 +- tests/SocketIO/SocketIOControllerTest.php | 18 +- tests/SocketIO/WebsocketHandlerTest.php | 8 +- tests/Table/TableTest.php | 3 +- tests/Task/FakeJob.php | 5 +- tests/Task/QueueFactoryTest.php | 58 +++++ tests/Task/SwooleJobTest.php | 5 +- tests/Task/SwooleQueueTest.php | 7 +- tests/TestCase.php | 9 +- tests/Transformers/RequestTest.php | 16 +- tests/Transformers/ResponseTest.php | 5 +- .../Websocket/Middleware/AuthenticateTest.php | 5 +- .../Middleware/DecrpytCookiesTest.php | 11 +- .../Websocket/Middleware/StartSessionTest.php | 5 +- tests/Websocket/RedisRoomTest.php | 3 +- tests/Websocket/SimpleParserTest.php | 6 +- tests/Websocket/TableRoomTest.php | 3 +- tests/Websocket/WebsocketTest.php | 18 +- tests/fixtures/bootstrap/app.php | 8 +- .../app/Providers/RouteServiceProvider.php | 1 + .../app/Providers/TestServiceProvider.php | 1 + tests/fixtures/laravel/config/swoole_http.php | 2 +- .../app/providers/TestServiceProvider.php | 1 + tests/fixtures/lumen/config/swoole_http.php | 2 +- 110 files changed, 2772 insertions(+), 798 deletions(-) create mode 100644 .scrutinizer.yml create mode 100644 copy_versioned_files.php create mode 100644 src/Coroutine/Connectors/ConnectorFactory.php create mode 100644 src/Exceptions/FrameworkNotSupportException.php create mode 100644 src/Exceptions/WebsocketNotSetInConfigException.php create mode 100644 src/Helpers/FW.php create mode 100644 src/Helpers/OS.php create mode 100644 src/Helpers/Service.php create mode 100644 src/Task/QueueFactory.php create mode 100644 src/Websocket/Push.php create mode 100644 stubs/5.5/MySqlConnector.stub create mode 100644 stubs/5.6/MySqlConnector.stub create mode 100644 stubs/5.6/SwooleTaskQueue.stub create mode 100644 stubs/5.7/SwooleTaskQueue.stub create mode 100644 tests/Coroutine/ConnectorFactoryTest.php create mode 100644 tests/Task/QueueFactoryTest.php diff --git a/.gitignore b/.gitignore index 8918ec05..b56fa873 100644 --- a/.gitignore +++ b/.gitignore @@ -2,6 +2,7 @@ .DS_Store phpunit.xml composer.lock +.scannerwork # Folders vendor diff --git a/.scrutinizer.yml b/.scrutinizer.yml new file mode 100644 index 00000000..90494730 --- /dev/null +++ b/.scrutinizer.yml @@ -0,0 +1,12 @@ +build: + environment: + php: 7.2 + +filter: + excluded_paths: + - "tests/*" + - "routes/*" + - "config/*" + - "stubs/*" + dependency_paths: + - "vendor/*" \ No newline at end of file diff --git a/.travis.yml b/.travis.yml index 6709f198..8b7faf44 100644 --- a/.travis.yml +++ b/.travis.yml @@ -4,10 +4,6 @@ sudo: false matrix: include: - - php: 7.2 - env: FRAMEWORK_VERSION=laravel/framework:5.1.* - - php: 7.2 - env: FRAMEWORK_VERSION=laravel/framework:5.2.* - php: 7.2 env: FRAMEWORK_VERSION=laravel/framework:5.3.* - php: 7.2 @@ -15,15 +11,19 @@ matrix: - php: 7.2 env: FRAMEWORK_VERSION=laravel/framework:5.5.* - php: 7.2 - env: FRAMEWORK_VERSION=laravel/lumen-framework:5.1.* + env: FRAMEWORK_VERSION=laravel/framework:5.6.* - php: 7.2 - env: FRAMEWORK_VERSION=laravel/lumen-framework:5.2.* + env: FRAMEWORK_VERSION=laravel/framework:5.7.* - php: 7.2 env: FRAMEWORK_VERSION=laravel/lumen-framework:5.3.* - php: 7.2 env: FRAMEWORK_VERSION=laravel/lumen-framework:5.4.* - php: 7.2 env: FRAMEWORK_VERSION=laravel/lumen-framework:5.5.* + - php: 7.2 + env: FRAMEWORK_VERSION=laravel/lumen-framework:5.6.* + - php: 7.2 + env: FRAMEWORK_VERSION=laravel/lumen-framework:5.7.* before_install: - printf "\n" | pecl install swoole diff --git a/README.md b/README.md index 5fef1611..2c9fbbc7 100644 --- a/README.md +++ b/README.md @@ -12,7 +12,7 @@ This package provides a high performance HTTP server to speed up your Laravel/Lu | PHP | Laravel | Lumen | Swoole | |:-------:|:-------:|:-----:|:-------:| -| >=7.1 | ~5.1 | ~5.1 | >=4.0.0 | +| >=7.1 | ~5.3 | ~5.1 | >=4.0.0 | ## Features diff --git a/composer.json b/composer.json index 85b7537c..b45c7ab5 100644 --- a/composer.json +++ b/composer.json @@ -1,60 +1,72 @@ { - "name": "swooletw/laravel-swoole", - "description": "High performance HTTP server based on Swoole. Speed up your Laravel and Lumen applications.", - "keywords": ["swoole", "laravel", "lumen", "performance", "http", "server"], - "license": "MIT", - "authors": [ - { - "name": "Albert Chen", - "email": "albert@unisharp.com" - }, - { - "name": "Huang Yi", - "email": "coodeer@163.com" - } - ], - "require": { - "php": "^7.1", - "illuminate/console": "~5.1", - "illuminate/contracts": "~5.1", - "illuminate/http": "~5.1", - "illuminate/support": "~5.1", - "predis/predis": "^1.1" - }, - "require-dev": { - "laravel/lumen-framework": "~5.1", - "phpunit/phpunit": "^6.1", - "phpunit/php-code-coverage": "^5.2", - "satooshi/php-coveralls": "^1.0", - "mockery/mockery": "~1.0", - "codedungeon/phpunit-result-printer": "^0.14.0", - "php-mock/php-mock": "^2.0" - }, - "autoload": { - "files": [ - "src/Server/helpers.php" - ], - "psr-4": { - "SwooleTW\\Http\\": "src" - } - }, - "autoload-dev": { - "psr-4": { - "SwooleTW\\Http\\Tests\\": "tests", - "SwooleTW\\Http\\Tests\\Fixtures\\Laravel\\App\\": "tests/fixtures/laravel/app" - } + "name": "swooletw/laravel-swoole", + "description": "High performance HTTP server based on Swoole. Speed up your Laravel and Lumen applications.", + "keywords": [ + "swoole", + "laravel", + "lumen", + "performance", + "http", + "server" + ], + "license": "MIT", + "authors": [ + { + "name": "Albert Chen", + "email": "albert@unisharp.com" }, - "extra": { - "laravel": { - "providers": [ - "SwooleTW\\Http\\LaravelServiceProvider" - ], - "aliases": { - "Server": "SwooleTW\\Http\\Server\\Facades\\Server", - "Table": "SwooleTW\\Http\\Server\\Facades\\Table", - "Room": "SwooleTW\\Http\\Websocket\\Facades\\Room", - "Websocket": "SwooleTW\\Http\\Websocket\\Facades\\Websocket" - } - } + { + "name": "Huang Yi", + "email": "coodeer@163.com" + } + ], + "require": { + "php": "^7.2", + "illuminate/console": "~5.3", + "illuminate/contracts": "~5.3", + "illuminate/http": "~5.3", + "illuminate/support": "~5.3", + "predis/predis": "^1.1" + }, + "require-dev": { + "laravel/lumen-framework": "~5.3", + "phpunit/phpunit": "^6.1", + "phpunit/php-code-coverage": "^5.2", + "satooshi/php-coveralls": "^1.0", + "mockery/mockery": "~1.0", + "codedungeon/phpunit-result-printer": "^0.14.0", + "php-mock/php-mock": "^2.0" + }, + "autoload": { + "files": [ + "src/Server/helpers.php" + ], + "psr-4": { + "SwooleTW\\Http\\": "src" + } + }, + "autoload-dev": { + "psr-4": { + "SwooleTW\\Http\\Tests\\": "tests", + "SwooleTW\\Http\\Tests\\Fixtures\\Laravel\\App\\": "tests/fixtures/laravel/app" + } + }, + "extra": { + "laravel": { + "providers": [ + "SwooleTW\\Http\\LaravelServiceProvider" + ], + "aliases": { + "Server": "SwooleTW\\Http\\Server\\Facades\\Server", + "Table": "SwooleTW\\Http\\Server\\Facades\\Table", + "Room": "SwooleTW\\Http\\Websocket\\Facades\\Room", + "Websocket": "SwooleTW\\Http\\Websocket\\Facades\\Websocket" + } } + }, + "scripts": { + "post-autoload-dump": [ + "@php copy_versioned_files.php" + ] + } } diff --git a/config/swoole_http.php b/config/swoole_http.php index 2f70159c..a49fcb6b 100644 --- a/config/swoole_http.php +++ b/config/swoole_http.php @@ -1,7 +1,5 @@ base_path('public'), // Determine if to use swoole to respond request for static files 'handle_static_files' => env('SWOOLE_HANDLE_STATIC', true), + 'log' => env('SWOOLE_HTTP_LOG', true), // You must add --enable-openssl while compiling Swoole // Put `SWOOLE_SOCK_TCP | SWOOLE_SSL` if you want to enable SSL 'socket_type' => SWOOLE_SOCK_TCP, + 'process_type' => SWOOLE_PROCESS, 'options' => [ 'pid_file' => env('SWOOLE_HTTP_PID_FILE', base_path('storage/logs/swoole_http.pid')), 'log_file' => env('SWOOLE_HTTP_LOG_FILE', base_path('storage/logs/swoole_http.log')), @@ -53,6 +53,19 @@ 'enabled' => env('SWOOLE_HTTP_WEBSOCKET', false), ], + /* + |-------------------------------------------------------------------------- + | Hot reload configuration + |-------------------------------------------------------------------------- + */ + 'hot_reload' => [ + 'enabled' => env('SWOOLE_HOT_RELOAD_ENABLE', true), + 'level' => env('SWOOLE_HOT_RELOAD_DEEP_LEVEL', 10), + 'directory' => env('SWOOLE_HOT_RELOAD_DIRECTORY', base_path()), + 'log' => env('SWOOLE_HOT_RELOAD_LOG', true), + 'files' => ['*.php'], + ], + /* |-------------------------------------------------------------------------- | Console output will be transferred to response content if enabled. @@ -120,5 +133,5 @@ // ['name' => 'column_name', 'type' => Table::TYPE_STRING, 'size' => 1024], // ] // ], - ] + ], ]; diff --git a/config/swoole_websocket.php b/config/swoole_websocket.php index a9c770da..d01a1edb 100644 --- a/config/swoole_websocket.php +++ b/config/swoole_websocket.php @@ -77,7 +77,7 @@ 'room_rows' => 4096, 'room_size' => 2048, 'client_rows' => 8192, - 'client_size' => 2048 + 'client_size' => 2048, ], 'redis' => [ @@ -92,6 +92,6 @@ // ], 'prefix' => 'swoole:', - ] + ], ], ]; diff --git a/copy_versioned_files.php b/copy_versioned_files.php new file mode 100644 index 00000000..50d9393a --- /dev/null +++ b/copy_versioned_files.php @@ -0,0 +1,27 @@ + - - - ./tests - - ./src + + + ./tests + + diff --git a/routes/laravel_routes.php b/routes/laravel_routes.php index 9afb5f6e..53564c96 100644 --- a/routes/laravel_routes.php +++ b/routes/laravel_routes.php @@ -1,5 +1,6 @@ get('socket.io', [ - 'as' => 'io.get', 'uses' => 'SocketIOController@upgrade' + 'as' => 'io.get', 'uses' => 'SocketIOController@upgrade', ]); $app->post('socket.io', [ - 'as' => 'io.post', 'uses' => 'SocketIOController@reject' + 'as' => 'io.post', 'uses' => 'SocketIOController@reject', ]); diff --git a/routes/websocket.php b/routes/websocket.php index a956ac7d..ddebfe14 100644 --- a/routes/websocket.php +++ b/routes/websocket.php @@ -1,5 +1,6 @@ emit('message', $data); }); - -// Websocket::on('test', 'ExampleController@method'); \ No newline at end of file diff --git a/src/Commands/HttpServerCommand.php b/src/Commands/HttpServerCommand.php index 157c9b54..30ab626d 100644 --- a/src/Commands/HttpServerCommand.php +++ b/src/Commands/HttpServerCommand.php @@ -2,9 +2,11 @@ namespace SwooleTW\Http\Commands; -use Throwable; -use Swoole\Process; + use Illuminate\Console\Command; +use Illuminate\Support\Arr; +use Swoole\Process; +use Throwable; /** * @codeCoverageIgnore @@ -38,14 +40,14 @@ class HttpServerCommand extends Command * * @var int */ - protected $pid; + protected $currentPid; /** * The configs for this package. * * @var array */ - protected $configs; + protected $config; /** * Execute the console command. @@ -65,7 +67,7 @@ public function handle() */ protected function loadConfigs() { - $this->configs = $this->laravel['config']->get('swoole_http'); + $this->config = $this->laravel->make('config')->get('swoole_http'); } /** @@ -81,13 +83,14 @@ protected function runAction() */ protected function start() { - if ($this->isRunning($this->getPid())) { + if ($this->isRunning($this->getCurrentPid())) { $this->error('Failed! swoole_http_server process is already running.'); - exit(1); + + return; } - $host = $this->configs['server']['host']; - $port = $this->configs['server']['port']; + $host = Arr::get($this->config, 'server.host'); + $port = Arr::get($this->config, 'server.port'); $this->info('Starting swoole http server...'); $this->info("Swoole http server started: "); @@ -104,11 +107,12 @@ protected function start() */ protected function stop() { - $pid = $this->getPid(); + $pid = $this->getCurrentPid(); - if (! $this->isRunning($pid)) { + if (!$this->isRunning($pid)) { $this->error("Failed! There is no swoole_http_server process running."); - exit(1); + + return; } $this->info('Stopping swoole http server...'); @@ -117,7 +121,8 @@ protected function stop() if ($isRunning) { $this->error('Unable to stop the swoole_http_server process.'); - exit(1); + + return; } // I don't known why Swoole didn't trigger "onShutdown" after sending SIGTERM. @@ -132,7 +137,7 @@ protected function stop() */ protected function restart() { - $pid = $this->getPid(); + $pid = $this->getCurrentPid(); if ($this->isRunning($pid)) { $this->stop(); @@ -146,20 +151,22 @@ protected function restart() */ protected function reload() { - $pid = $this->getPid(); + $pid = $this->getCurrentPid(); - if (! $this->isRunning($pid)) { + if (!$this->isRunning($pid)) { $this->error("Failed! There is no swoole_http_server process running."); - exit(1); + + return; } $this->info('Reloading swoole_http_server...'); $isRunning = $this->killProcess($pid, SIGUSR1); - if (! $isRunning) { + if (!$isRunning) { $this->error('> failure'); - exit(1); + + return; } $this->info('> success'); @@ -175,20 +182,18 @@ protected function infos() /** * Display PHP and Swoole miscs infos. - * - * @param bool $more */ protected function showInfos() { - $pid = $this->getPid(); + $pid = $this->getCurrentPid(); $isRunning = $this->isRunning($pid); - $host = $this->configs['server']['host']; - $port = $this->configs['server']['port']; - $reactorNum = $this->configs['server']['options']['reactor_num']; - $workerNum = $this->configs['server']['options']['worker_num']; - $taskWorkerNum = $this->configs['server']['options']['task_worker_num']; - $isWebsocket = $this->configs['websocket']['enabled']; - $logFile = $this->configs['server']['options']['log_file']; + $host = Arr::get($this->config, 'server.host'); + $port = Arr::get($this->config, 'server.port'); + $reactorNum = Arr::get($this->config, 'server.options.reactor_num'); + $workerNum = Arr::get($this->config, 'server.options.worker_num'); + $taskWorkerNum = Arr::get($this->config, 'server.options.task_worker_num'); + $isWebsocket = Arr::get($this->config, 'websocket.enabled'); + $logFile = Arr::get($this->config, 'server.options.log_file'); $table = [ ['PHP Version', 'Version' => phpversion()], @@ -215,9 +220,10 @@ protected function initAction() { $this->action = $this->argument('action'); - if (! in_array($this->action, ['start', 'stop', 'restart', 'reload', 'infos'])) { + if (!in_array($this->action, ['start', 'stop', 'restart', 'reload', 'infos'], true)) { $this->error("Invalid argument '{$this->action}'. Expected 'start', 'stop', 'restart', 'reload' or 'infos'."); - exit(1); + + return; } } @@ -225,11 +231,12 @@ protected function initAction() * If Swoole process is running. * * @param int $pid + * * @return bool */ protected function isRunning($pid) { - if (! $pid) { + if (!$pid) { return false; } @@ -246,6 +253,7 @@ protected function isRunning($pid) * @param int $pid * @param int $sig * @param int $wait + * * @return bool */ protected function killProcess($pid, $sig, $wait = 0) @@ -256,7 +264,7 @@ protected function killProcess($pid, $sig, $wait = 0) $start = time(); do { - if (! $this->isRunning($pid)) { + if (!$this->isRunning($pid)) { break; } @@ -272,26 +280,17 @@ protected function killProcess($pid, $sig, $wait = 0) * * @return int|null */ - protected function getPid() + protected function getCurrentPid() { - if ($this->pid) { - return $this->pid; + if ($this->currentPid) { + return $this->currentPid; } - $pid = null; $path = $this->getPidPath(); - if (file_exists($path)) { - $pid = (int) file_get_contents($path); - - if (! $pid) { - $this->removePidFile(); - } else { - $this->pid = $pid; - } - } - - return $this->pid; + return $this->currentPid = file_exists($path) + ? (int)file_get_contents($path) ?? $this->removePidFile() + : null; } /** @@ -301,7 +300,7 @@ protected function getPid() */ protected function getPidPath() { - return $this->configs['server']['options']['pid_file']; + return Arr::get($this->config, 'server.options.pid_file', storage_path('logs/swoole.pid')); } /** @@ -317,9 +316,9 @@ protected function removePidFile() /** * Return daemonize config. */ - protected function isDaemon() + protected function isDaemon(): bool { - return $this->configs['server']['options']['daemonize']; + return Arr::get($this->config, 'server.options.daemonize', false); } /** @@ -329,13 +328,16 @@ protected function checkEnvironment() { if (strtoupper(substr(PHP_OS, 0, 3)) === 'WIN') { $this->error("Swoole extension doesn't support Windows OS yet."); - exit; - } elseif (! extension_loaded('swoole')) { + + return; + } else if (!extension_loaded('swoole')) { $this->error("Can't detect Swoole extension installed."); - exit; - } elseif (! version_compare(swoole_version(), '4.0.0', 'ge')) { + + return; + } else if (!version_compare(swoole_version(), '4.0.0', 'ge')) { $this->error("Your Swoole version must be higher than 4.0 to use coroutine."); - exit; + + return; } } } diff --git a/src/Concerns/InteractsWithSwooleTable.php b/src/Concerns/InteractsWithSwooleTable.php index 443eaf52..aa9e1b17 100644 --- a/src/Concerns/InteractsWithSwooleTable.php +++ b/src/Concerns/InteractsWithSwooleTable.php @@ -2,22 +2,30 @@ namespace SwooleTW\Http\Concerns; + +use Illuminate\Contracts\Console\Application as ConsoleApp; use Swoole\Table; use SwooleTW\Http\Table\SwooleTable; +/** + * Trait InteractsWithSwooleTable + * + * @property \Illuminate\Contracts\Container\Container $container + * @property \Illuminate\Contracts\Container\Container $app + */ trait InteractsWithSwooleTable { /** - * @var \SwooleTW\Http\Server\Table + * @var \SwooleTW\Http\Table\SwooleTable */ - protected $table; + protected $currentTable; /** * Register customized swoole talbes. */ protected function createTables() { - $this->table = new SwooleTable; + $this->currentTable = new SwooleTable; $this->registerTables(); } @@ -26,7 +34,7 @@ protected function createTables() */ protected function registerTables() { - $tables = $this->container['config']->get('swoole_http.tables', []); + $tables = $this->container->make('config')->get('swoole_http.tables', []); foreach ($tables as $key => $value) { $table = new Table($value['size']); @@ -40,7 +48,7 @@ protected function registerTables() } $table->create(); - $this->table->add($key, $table); + $this->currentTable->add($key, $table); } } @@ -49,9 +57,12 @@ protected function registerTables() */ protected function bindSwooleTable() { - $this->app->singleton(SwooleTable::class, function () { - return $this->table; - }); - $this->app->alias(SwooleTable::class, 'swoole.table'); + if (!$this->app instanceof ConsoleApp) { + $this->app->singleton(SwooleTable::class, function () { + return $this->currentTable; + }); + + $this->app->alias(SwooleTable::class, 'swoole.table'); + } } } diff --git a/src/Concerns/InteractsWithWebsocket.php b/src/Concerns/InteractsWithWebsocket.php index c22e1cfc..66bff107 100644 --- a/src/Concerns/InteractsWithWebsocket.php +++ b/src/Concerns/InteractsWithWebsocket.php @@ -2,33 +2,43 @@ namespace SwooleTW\Http\Concerns; -use Throwable; -use Swoole\Websocket\Frame; -use Swoole\Websocket\Server; + +use Illuminate\Contracts\Container\Container; use Illuminate\Pipeline\Pipeline; -use SwooleTW\Http\Websocket\Parser; -use Illuminate\Support\Facades\Facade; -use SwooleTW\Http\Websocket\Websocket; +use Illuminate\Support\Arr; +use SwooleTW\Http\Exceptions\WebsocketNotSetInConfigException; +use SwooleTW\Http\Helpers\Service; use SwooleTW\Http\Transformers\Request; use SwooleTW\Http\Websocket\HandlerContract; +use SwooleTW\Http\Websocket\Parser; +use SwooleTW\Http\Websocket\Push; use SwooleTW\Http\Websocket\Rooms\RoomContract; +use SwooleTW\Http\Websocket\Websocket; +use Throwable; +/** + * Trait InteractsWithWebsocket + * + * @property \Illuminate\Contracts\Container\Container $container + * @property \Illuminate\Contracts\Container\Container $app + * @property array $types + */ trait InteractsWithWebsocket { /** * @var boolean */ - protected $isWebsocket = false; + protected $isServerWebsocket = false; /** - * @var SwooleTW\Http\Websocket\HandlerContract + * @var \SwooleTW\Http\Websocket\HandlerContract */ protected $websocketHandler; /** - * @var SwooleTW\Http\Websocket\Parser + * @var \SwooleTW\Http\Websocket\Parser */ - protected $parser; + protected $payloadParser; /** * Websocket server events. @@ -40,34 +50,35 @@ trait InteractsWithWebsocket /** * "onOpen" listener. * - * @param \Swoole\Websocket\Server $server * @param \Swoole\Http\Request $swooleRequest */ - public function onOpen($server, $swooleRequest) + public function onOpen($swooleRequest) { $illuminateRequest = Request::make($swooleRequest)->toIlluminate(); + $websocket = $this->app->make(Service::WEBSOCKET_ALIAS); + $sandbox = $this->app->make(Service::SANDBOX_ALIAS); try { - $this->app['swoole.websocket']->reset(true)->setSender($swooleRequest->fd); + $websocket->reset(true)->setSender($swooleRequest->fd); // set currnt request to sandbox - $this->app['swoole.sandbox']->setRequest($illuminateRequest); + $sandbox->setRequest($illuminateRequest); // enable sandbox - $this->app['swoole.sandbox']->enable(); + $sandbox->enable(); // check if socket.io connection established - if (! $this->websocketHandler->onOpen($swooleRequest->fd, $illuminateRequest)) { + if (!$this->websocketHandler->onOpen($swooleRequest->fd, $illuminateRequest)) { return; } // trigger 'connect' websocket event - if ($this->app['swoole.websocket']->eventExists('connect')) { + if ($websocket->eventExists('connect')) { // set sandbox container to websocket pipeline - $this->app['swoole.websocket']->setContainer($this->app['swoole.sandbox']->getApplication()); - $this->app['swoole.websocket']->call('connect', $illuminateRequest); + $websocket->setContainer($sandbox->getApplication()); + $websocket->call('connect', $illuminateRequest); } } catch (Throwable $e) { $this->logServerError($e); } finally { // disable and recycle sandbox resource - $this->app['swoole.sandbox']->disable(); + $sandbox->disable(); } } @@ -79,31 +90,33 @@ public function onOpen($server, $swooleRequest) */ public function onMessage($server, $frame) { - try { - // execute parser strategies and skip non-message packet - if ($this->parser->execute($server, $frame)) { - return; - } + // execute parser strategies and skip non-message packet + if ($this->payloadParser->execute($server, $frame)) { + return; + } + + $websocket = $this->app->make(Service::WEBSOCKET_ALIAS); + $sandbox = $this->app->make(Service::SANDBOX_ALIAS); + try { // decode raw message via parser - $payload = $this->parser->decode($frame); + $payload = $this->payloadParser->decode($frame); - $this->app['swoole.websocket']->reset(true)->setSender($frame->fd); + $websocket->reset(true)->setSender($frame->fd); // enable sandbox - $this->app['swoole.sandbox']->enable(); + $sandbox->enable(); // dispatch message to registered event callback - if ($this->app['swoole.websocket']->eventExists($payload['event'])) { - $this->app['swoole.websocket']->call($payload['event'], $payload['data']); - } else { - $this->websocketHandler->onMessage($frame); - } + ['event' => $event, 'data' => $data] = $payload; + $websocket->eventExists($event) + ? $websocket->call($event, $data) + : $this->websocketHandler->onMessage($frame); } catch (Throwable $e) { $this->logServerError($e); } finally { // disable and recycle sandbox resource - $this->app['swoole.sandbox']->disable(); + $sandbox->disable(); } } @@ -116,20 +129,22 @@ public function onMessage($server, $frame) */ public function onClose($server, $fd, $reactorId) { - if (! $this->isWebsocket($fd)) { + if (!$this->isServerWebsocket($fd) || !$server instanceof Websocket) { return; } + $websocket = $this->app->make(Service::WEBSOCKET_ALIAS); + try { - $this->app['swoole.websocket']->reset(true)->setSender($fd); + $websocket->reset(true)->setSender($fd); // trigger 'disconnect' websocket event - if ($this->app['swoole.websocket']->eventExists('disconnect')) { - $this->app['swoole.websocket']->call('disconnect'); + if ($websocket->eventExists('disconnect')) { + $websocket->call('disconnect'); } else { $this->websocketHandler->onClose($fd, $reactorId); } // leave all rooms - $this->app['swoole.websocket']->leave(); + $websocket->leave(); } catch (Throwable $e) { $this->logServerError($e); } @@ -143,40 +158,37 @@ public function onClose($server, $fd, $reactorId) */ public function pushMessage($server, array $data) { - [$opcode, $sender, $fds, $broadcast, $assigned, $event, $message] = $this->normalizePushData($data); - $message = $this->parser->encode($event, $message); + $push = Push::new($data); + $payload = $this->payloadParser->encode($push->getEvent(), $push->getMessage()); // attach sender if not broadcast - if (! $broadcast && $sender && ! in_array($sender, $fds)) { - $fds[] = $sender; + if (!$push->isBroadcast() && $push->getSender() && !$push->hasOwnDescriptor()) { + $push->addDescriptor($push->getSender()); } // check if to broadcast all clients - if ($broadcast && empty($fds) && ! $assigned) { - foreach ($server->connections as $fd) { - if ($this->isWebsocket($fd)) { - $fds[] = $fd; - } - } + if ($push->isBroadcastToAllDescriptors()) { + $push->mergeDescriptor($this->filterWebsocket($server->connections)); } // push message to designated fds - foreach ($fds as $fd) { - if (($broadcast && $sender === (integer) $fd) || ! $server->exist($fd)) { - continue; + foreach ($push->getDescriptors() as $descriptor) { + if ($server->exist($descriptor) || !$push->isBroadcastToDescriptor((int)$descriptor)) { + $server->push($descriptor, $payload, $push->getOpcode()); } - $server->push($fd, $message, $opcode); } } /** * Set frame parser for websocket. * - * @param \SwooleTW\Http\Websocket\Parser $parser + * @param \SwooleTW\Http\Websocket\Parser $payloadParser + * + * @return \SwooleTW\Http\Concerns\InteractsWithWebsocket */ - public function setParser(Parser $parser) + public function setPayloadParser(Parser $payloadParser) { - $this->parser = $parser; + $this->payloadParser = $payloadParser; return $this; } @@ -184,9 +196,9 @@ public function setParser(Parser $parser) /** * Get frame parser for websocket. */ - public function getParser() + public function getPayloadParser() { - return $this->parser; + return $this->payloadParser; } /** @@ -194,35 +206,58 @@ public function getParser() */ protected function prepareWebsocket() { - $isWebsocket = $this->container['config']->get('swoole_http.websocket.enabled'); - $parser = $this->container['config']->get('swoole_websocket.parser'); + $config = $this->container->make(Service::CONFIG_ALIAS); + $isWebsocket = $config->get('swoole_http.websocket.enabled'); + $parser = $config->get('swoole_websocket.parser'); if ($isWebsocket) { - array_push($this->events, ...$this->wsEvents); - $this->isWebsocket = true; - $this->setParser(new $parser); + $this->types = array_merge($this->types ?? [], $this->wsEvents); + $this->isServerWebsocket = true; + $this->setPayloadParser(new $parser); } } /** * Check if it's a websocket fd. + * + * @param int $fd + * + * @return bool */ - protected function isWebsocket(int $fd) + protected function isServerWebsocket(int $fd): bool { - $info = $this->container['swoole.server']->connection_info($fd); + $info = $this->container->make(Service::SERVER_ALIAS)->connection_info($fd); - return array_key_exists('websocket_status', $info) && $info['websocket_status']; + return Arr::has($info, 'websocket_status') && Arr::get($info, 'websocket_status'); + } + + /** + * Returns all descriptors that are websocket + * + * @param array $descriptors + * + * @return array + */ + protected function filterWebsocket(array $descriptors): array + { + $callback = function ($descriptor) { + return $this->isServerWebsocket($descriptor); + }; + + return collect($descriptors)->filter($callback)->toArray(); } /** * Prepare websocket handler for onOpen and onClose callback. + * + * @throws \Exception */ protected function prepareWebsocketHandler() { - $handlerClass = $this->container['config']->get('swoole_websocket.handler'); + $handlerClass = $this->container->make(Service::CONFIG_ALIAS)->get('swoole_websocket.handler'); - if (! $handlerClass) { - throw new Exception('Websocket handler is not set in swoole_websocket config'); + if (!$handlerClass) { + throw new WebsocketNotSetInConfigException; } $this->setWebsocketHandler($this->app->make($handlerClass)); @@ -230,6 +265,10 @@ protected function prepareWebsocketHandler() /** * Set websocket handler. + * + * @param \SwooleTW\Http\Websocket\HandlerContract $handler + * + * @return \SwooleTW\Http\Concerns\InteractsWithWebsocket */ public function setWebsocketHandler(HandlerContract $handler) { @@ -240,35 +279,39 @@ public function setWebsocketHandler(HandlerContract $handler) /** * Get websocket handler. + * + * @return \SwooleTW\Http\Websocket\HandlerContract */ - public function getWebsocketHandler() + public function getWebsocketHandler(): HandlerContract { return $this->websocketHandler; } /** - * Get websocket handler for onOpen and onClose callback. + * @param string $class + * @param array $settings + * + * @return \SwooleTW\Http\Websocket\Rooms\RoomContract */ - protected function getWebsocketRoom() + protected function createRoom(string $class, array $settings): RoomContract { - $driver = $this->container['config']->get('swoole_websocket.default'); - $configs = $this->container['config']->get("swoole_websocket.settings.{$driver}"); - $className = $this->container['config']->get("swoole_websocket.drivers.{$driver}"); - - $websocketRoom = new $className($configs); - $websocketRoom->prepare(); - - return $websocketRoom; + return new $class($settings); } /** * Bind room instance to Laravel app container. */ - protected function bindRoom() + protected function bindRoom(): void { - $this->app->singleton(RoomContract::class, function ($app) { - return $this->getWebsocketRoom(); + $this->app->singleton(RoomContract::class, function (Container $container) { + $config = $container->make(Service::CONFIG_ALIAS); + $driver = $config->get('swoole_websocket.default'); + $settings = $config->get("swoole_websocket.settings.{$driver}"); + $className = $config->get("swoole_websocket.drivers.{$driver}"); + + return $this->createRoom($className, $settings); }); + $this->app->alias(RoomContract::class, 'swoole.room'); } @@ -277,10 +320,11 @@ protected function bindRoom() */ protected function bindWebsocket() { - $this->app->singleton(Websocket::class, function ($app) { - return new Websocket($app['swoole.room'], new Pipeline($app)); + $this->app->singleton(Websocket::class, function (Container $app) { + return new Websocket($app->make(Service::ROOM_ALIAS), new Pipeline($app)); }); - $this->app->alias(Websocket::class, 'swoole.websocket'); + + $this->app->alias(Websocket::class, Service::WEBSOCKET_ALIAS); } /** @@ -288,9 +332,9 @@ protected function bindWebsocket() */ protected function loadWebsocketRoutes() { - $routePath = $this->container['config']->get('swoole_websocket.route_file'); + $routePath = $this->container->make(Service::CONFIG_ALIAS)->get('swoole_websocket.route_file'); - if (! file_exists($routePath)) { + if (!file_exists($routePath)) { $routePath = __DIR__ . '/../../routes/websocket.php'; } @@ -299,16 +343,20 @@ protected function loadWebsocketRoutes() /** * Normalize data for message push. + * + * @param array $data + * + * @return array */ public function normalizePushData(array $data) { - $opcode = $data['opcode'] ?? 1; - $sender = $data['sender'] ?? 0; - $fds = $data['fds'] ?? []; - $broadcast = $data['broadcast'] ?? false; - $assigned = $data['assigned'] ?? false; - $event = $data['event'] ?? null; - $message = $data['message'] ?? null; + $opcode = Arr::get($data, 'opcode', 1); + $sender = Arr::get($data, 'sender', 0); + $fds = Arr::get($data, 'fds', []); + $broadcast = Arr::get($data, 'broadcast', false); + $assigned = Arr::get($data, 'assigned', false); + $event = Arr::get($data, 'event', null); + $message = Arr::get($data, 'message', null); return [$opcode, $sender, $fds, $broadcast, $assigned, $event, $message]; } diff --git a/src/Concerns/ResetApplication.php b/src/Concerns/ResetApplication.php index 6f86569f..4e611a3e 100644 --- a/src/Concerns/ResetApplication.php +++ b/src/Concerns/ResetApplication.php @@ -2,6 +2,7 @@ namespace SwooleTW\Http\Concerns; + use Illuminate\Contracts\Container\Container; use SwooleTW\Http\Exceptions\SandboxException; use SwooleTW\Http\Server\Resetters\ResetterContract; @@ -19,7 +20,7 @@ trait ResetApplication protected $providers = []; /** - * @var array + * @var \SwooleTW\Http\Server\Resetters\ResetterContract[]|array */ protected $resetters = []; @@ -48,7 +49,7 @@ protected function setInitialProviders() $providers = $this->config->get('swoole_http.providers', []); foreach ($providers as $provider) { - if (class_exists($provider) && ! in_array($provider, $this->providers)) { + if (class_exists($provider) && !in_array($provider, $this->providers)) { $providerClass = new $provider($app); $this->providers[$provider] = $providerClass; } @@ -73,7 +74,7 @@ protected function setInitialResetters() foreach ($resetters as $resetter) { $resetterClass = $app->make($resetter); - if (! $resetterClass instanceof ResetterContract) { + if (!$resetterClass instanceof ResetterContract) { throw new SandboxException("{$resetter} must implement " . ResetterContract::class); } $this->resetters[$resetter] = $resetterClass; @@ -90,6 +91,8 @@ public function getResetters() /** * Reset Laravel/Lumen Application. + * + * @param \Illuminate\Contracts\Container\Container $app */ public function resetApp(Container $app) { diff --git a/src/Concerns/WithApplication.php b/src/Concerns/WithApplication.php index d34385dc..46053cbf 100644 --- a/src/Concerns/WithApplication.php +++ b/src/Concerns/WithApplication.php @@ -2,33 +2,39 @@ namespace SwooleTW\Http\Concerns; -use Illuminate\Http\Request; + +use Illuminate\Contracts\Container\Container; use Illuminate\Contracts\Http\Kernel; use Illuminate\Support\Facades\Facade; -use Illuminate\Contracts\Container\Container; -use Laravel\Lumen\Application as LumenApplication; -use Symfony\Component\HttpFoundation\StreamedResponse; -use Symfony\Component\HttpFoundation\BinaryFileResponse; -use Symfony\Component\HttpFoundation\Response as SymfonyResponse; - +use SwooleTW\Http\Exceptions\FrameworkNotSupportException; +use SwooleTW\Http\Helpers\Service; + +/** + * Trait WithApplication + * + * @property Container $container + * @property string $framework + */ trait WithApplication { /** * Laravel|Lumen Application. * - * @var \Illuminate\Contracts\Container\Container + * @var \Illuminate\Contracts\Container\Container|mixed */ protected $app; /** * Bootstrap framework. + * + * @throws \ReflectionException */ protected function bootstrap() { if ($this->framework === 'laravel') { $bootstrappers = $this->getBootstrappers(); $this->app->bootstrapWith($bootstrappers); - } elseif (is_null(Facade::getFacadeApplication())) { + } else if (is_null(Facade::getFacadeApplication())) { $this->app->withFacades(); } @@ -42,15 +48,16 @@ protected function bootstrap() */ protected function loadApplication() { - return require $this->basePath . '/bootstrap/app.php'; + return require "{$this->basePath}/bootstrap/app.php"; } /** - * @return \Illuminate\Contracts\Container\Container + * @return \Illuminate\Contracts\Container\Container|mixed + * @throws \ReflectionException */ public function getApplication() { - if (! $this->app instanceof Container) { + if (!$this->app instanceof Container) { $this->app = $this->loadApplication(); $this->bootstrap(); } @@ -60,6 +67,8 @@ public function getApplication() /** * Set laravel application. + * + * @param \Illuminate\Contracts\Container\Container $app */ public function setApplication(Container $app) { @@ -70,6 +79,7 @@ public function setApplication(Container $app) * Get bootstrappers. * * @return array + * @throws \ReflectionException */ protected function getBootstrappers() { @@ -91,14 +101,15 @@ protected function getBootstrappers() * Set framework. * * @param string $framework + * * @throws \Exception */ protected function setFramework($framework) { $framework = strtolower($framework); - if (! in_array($framework, ['laravel', 'lumen'])) { - throw new \Exception(sprintf('Not support framework "%s".', $framework)); + if (!in_array($framework, ['laravel', 'lumen'])) { + throw new FrameworkNotSupportException($framework); } $this->framework = $framework; @@ -132,10 +143,12 @@ public function getBasePath() /** * Reslove some instances before request. + * + * @throws \ReflectionException */ protected function preResolveInstances() { - $resolves = $this->container['config']->get('swoole_http.pre_resolved', []); + $resolves = $this->container->make(Service::CONFIG_ALIAS)->get('swoole_http.pre_resolved', []); foreach ($resolves as $abstract) { if ($this->getApplication()->offsetExists($abstract)) { diff --git a/src/Controllers/SocketIOController.php b/src/Controllers/SocketIOController.php index be16a5ac..48819983 100644 --- a/src/Controllers/SocketIOController.php +++ b/src/Controllers/SocketIOController.php @@ -2,6 +2,7 @@ namespace SwooleTW\Http\Controllers; + use Illuminate\Http\Request; use Illuminate\Support\Facades\Config; @@ -11,10 +12,10 @@ class SocketIOController public function upgrade(Request $request) { - if (! in_array($request->input('transport'), $this->transports)) { + if (!in_array($request->input('transport'), $this->transports)) { return response()->json([ 'code' => 0, - 'message' => 'Transport unknown' + 'message' => 'Transport unknown', ], 400); } @@ -26,17 +27,17 @@ public function upgrade(Request $request) 'sid' => base64_encode(uniqid()), 'upgrades' => ['websocket'], 'pingInterval' => Config::get('swoole_websocket.ping_interval'), - 'pingTimeout' => Config::get('swoole_websocket.ping_timeout') + 'pingTimeout' => Config::get('swoole_websocket.ping_timeout'), ]); return '97:0' . $payload . '2:40'; } - public function reject(Request $request) + public function reject() { return response()->json([ 'code' => 3, - 'message' => 'Bad request' + 'message' => 'Bad request', ], 400); } } diff --git a/src/Coroutine/ConnectionException.php b/src/Coroutine/ConnectionException.php index f5ae28c0..1698f80b 100644 --- a/src/Coroutine/ConnectionException.php +++ b/src/Coroutine/ConnectionException.php @@ -2,6 +2,7 @@ namespace SwooleTW\Http\Coroutine; + class ConnectionException extends \Exception { // diff --git a/src/Coroutine/Connectors/ConnectorFactory.php b/src/Coroutine/Connectors/ConnectorFactory.php new file mode 100644 index 00000000..37dcb51a --- /dev/null +++ b/src/Coroutine/Connectors/ConnectorFactory.php @@ -0,0 +1,106 @@ +getDocComment(), $result)) { + $fileVersion = Arr::first($result); + } + } + + return version_compare($fileVersion, $version, '>='); + } catch (\Exception $e) { + return false; + } + } + + /** + * @param string $version + * + * @return bool + */ + protected static function hasBreakingChanges(string $version): bool + { + return version_compare($version, self::CHANGE_VERSION, '>='); + } +} diff --git a/src/Coroutine/Connectors/MySqlConnector.php b/src/Coroutine/Connectors/MySqlConnector.php index 627aadd8..7082d761 100644 --- a/src/Coroutine/Connectors/MySqlConnector.php +++ b/src/Coroutine/Connectors/MySqlConnector.php @@ -2,21 +2,27 @@ namespace SwooleTW\Http\Coroutine\Connectors; -use Exception; + +use Illuminate\Database\Connectors\MySqlConnector as BaseConnector; use Illuminate\Support\Str; use SwooleTW\Http\Coroutine\PDO as SwoolePDO; -use Illuminate\Database\Connectors\MySqlConnector as BaseConnector; +use Throwable; +/** + * Class MySqlConnector (5.6) + */ class MySqlConnector extends BaseConnector { /** * Create a new PDO connection instance. * - * @param string $dsn - * @param string $username - * @param string $password - * @param array $options + * @param string $dsn + * @param string $username + * @param string $password + * @param array $options + * * @return \PDO + * @throws \SwooleTW\Http\Coroutine\ConnectionException */ protected function createPdoConnection($dsn, $username, $password, $options) { @@ -26,16 +32,16 @@ protected function createPdoConnection($dsn, $username, $password, $options) /** * Handle an exception that occurred during connect execution. * - * @param \Exception $e - * @param string $dsn - * @param string $username - * @param string $password - * @param array $options - * @return \PDO + * @param \Throwable $e + * @param string $dsn + * @param string $username + * @param string $password + * @param array $options * - * @throws \Exception + * @return \PDO + * @throws \Throwable */ - protected function tryAgainIfCausedByLostConnection(Exception $e, $dsn, $username, $password, $options) + protected function tryAgainIfCausedByLostConnection(Throwable $e, $dsn, $username, $password, $options) { // https://github.com/swoole/swoole-src/blob/a414e5e8fec580abb3dbd772d483e12976da708f/swoole_mysql_coro.c#L196 if ($this->causedByLostConnection($e) || Str::contains($e->getMessage(), 'is closed')) { diff --git a/src/Coroutine/Context.php b/src/Coroutine/Context.php index a2f49a34..9f118229 100644 --- a/src/Coroutine/Context.php +++ b/src/Coroutine/Context.php @@ -2,8 +2,9 @@ namespace SwooleTW\Http\Coroutine; -use Swoole\Coroutine; + use Illuminate\Contracts\Container\Container; +use Swoole\Coroutine; class Context { @@ -31,6 +32,8 @@ public static function getApp() /** * Set app container by current coroutine id. + * + * @param \Illuminate\Contracts\Container\Container $app */ public static function setApp(Container $app) { @@ -39,6 +42,10 @@ public static function setApp(Container $app) /** * Get data by current coroutine id. + * + * @param string $key + * + * @return mixed|null */ public static function getData(string $key) { @@ -47,6 +54,9 @@ public static function getData(string $key) /** * Set data by current coroutine id. + * + * @param string $key + * @param $value */ public static function setData(string $key, $value) { @@ -55,6 +65,8 @@ public static function setData(string $key, $value) /** * Remove data by current coroutine id. + * + * @param string $key */ public static function removeData(string $key) { @@ -62,7 +74,7 @@ public static function removeData(string $key) } /** - * Get data by current coroutine id. + * Get data keys by current coroutine id. */ public static function getDataKeys() { @@ -70,7 +82,7 @@ public static function getDataKeys() } /** - * Get data by current coroutine id. + * Clear data by current coroutine id. */ public static function clear() { diff --git a/src/Coroutine/MySqlConnection.php b/src/Coroutine/MySqlConnection.php index be73c294..27e972b5 100644 --- a/src/Coroutine/MySqlConnection.php +++ b/src/Coroutine/MySqlConnection.php @@ -2,20 +2,22 @@ namespace SwooleTW\Http\Coroutine; + use Closure; -use Illuminate\Support\Str; -use Illuminate\Database\QueryException; use Illuminate\Database\MySqlConnection as BaseConnection; +use Illuminate\Database\QueryException; +use Illuminate\Support\Str; class MySqlConnection extends BaseConnection { /** * Handle a query exception that occurred during query execution. * - * @param \Illuminate\Database\QueryException $e - * @param string $query - * @param array $bindings - * @param \Closure $callback + * @param \Illuminate\Database\QueryException $e + * @param string $query + * @param array $bindings + * @param \Closure $callback + * * @return mixed * * @throws \Illuminate\Database\QueryException diff --git a/src/Coroutine/PDO.php b/src/Coroutine/PDO.php index 5e4a7aeb..c79e2af9 100644 --- a/src/Coroutine/PDO.php +++ b/src/Coroutine/PDO.php @@ -9,27 +9,30 @@ namespace SwooleTW\Http\Coroutine; + use Exception; -use PDO as BasePDO; use Illuminate\Database\QueryException; -use SwooleTW\Http\Coroutine\PDOStatement; -use SwooleTW\Http\Coroutine\StatementException; -use SwooleTW\Http\Coroutine\ConnectionException; +use Illuminate\Support\Arr; +use PDO as BasePDO; +/** + * Class PDO + */ class PDO extends BasePDO { public static $keyMap = [ - 'dbname' => 'database' + 'dbname' => 'database', ]; - private static $defaultOptions = [ + private static $options = [ 'host' => '', 'port' => 3306, 'user' => '', 'password' => '', 'database' => '', 'charset' => 'utf8mb4', - 'strict_type' => true + 'strict_type' => true, + 'timeout' => -1, ]; /** @var \Swoole\Coroutine\Mysql */ @@ -37,26 +40,42 @@ class PDO extends BasePDO public $inTransaction = false; - public function __construct( - string $dsn, - string $username = '', - string $password = '', - array $driverOptions = [] - ) { + /** + * PDO constructor. + * + * @param string $dsn + * @param string $username + * @param string $password + * @param array $options + * + * @throws \SwooleTW\Http\Coroutine\ConnectionException + */ + public function __construct(string $dsn, string $username = '', string $password = '', array $options = []) + { + parent::__construct($dsn, $username, $password, $options); $this->setClient(); $this->connect($this->getOptions(...func_get_args())); } + /** + * @param mixed $client + */ protected function setClient($client = null) { $this->client = $client ?: new \Swoole\Coroutine\Mysql(); } + /** + * @param array $options + * + * @return $this + * @throws \SwooleTW\Http\Coroutine\ConnectionException + */ protected function connect(array $options = []) { $this->client->connect($options); - if (! $this->client->connected) { + if (!$this->client->connected) { $message = $this->client->connect_error ?: $this->client->error; $errorCode = $this->client->connect_errno ?: $this->client->errno; @@ -66,19 +85,27 @@ protected function connect(array $options = []) return $this; } + /** + * @param $dsn + * @param $username + * @param $password + * @param $driverOptions + * + * @return array + */ protected function getOptions($dsn, $username, $password, $driverOptions) { $dsn = explode(':', $dsn); $driver = ucwords(array_shift($dsn)); $dsn = explode(';', implode(':', $dsn)); - $options = []; + $configuredOptions = []; static::checkDriver($driver); foreach ($dsn as $kv) { $kv = explode('=', $kv); - if ($kv) { - $options[$kv[0]] = $kv[1] ?? ''; + if (count($kv)) { + $configuredOptions[$kv[0]] = $kv[1] ?? ''; } } @@ -87,63 +114,92 @@ protected function getOptions($dsn, $username, $password, $driverOptions) 'password' => $password, ]; - $options = $driverOptions + $authorization + $options; + $configuredOptions = $driverOptions + $authorization + $configuredOptions; foreach (static::$keyMap as $pdoKey => $swpdoKey) { - if (isset($options[$pdoKey])) { - $options[$swpdoKey] = $options[$pdoKey]; - unset($options[$pdoKey]); + if (isset($configuredOptions[$pdoKey])) { + $configuredOptions[$swpdoKey] = $configuredOptions[$pdoKey]; + unset($configuredOptions[$pdoKey]); } } - return $options + static::$defaultOptions; + return array_merge($configuredOptions, static::$options); } + /** + * @param string $driver + */ public static function checkDriver(string $driver) { - if (! in_array($driver, static::getAvailableDrivers())) { + if (!in_array($driver, static::getAvailableDrivers())) { throw new \InvalidArgumentException("{$driver} driver is not supported yet."); } } + /** + * @return array + */ public static function getAvailableDrivers() { return ['Mysql']; } + /** + * @return bool|void + */ public function beginTransaction() { $this->client->begin(); $this->inTransaction = true; } + /** + * @return bool|void + */ public function rollBack() { $this->client->rollback(); $this->inTransaction = false; } + /** + * @return bool|void + */ public function commit() { $this->client->commit(); $this->inTransaction = true; } + /** + * @return bool + */ public function inTransaction() { return $this->inTransaction; } + /** + * @param null $seqname + * + * @return int|string + */ public function lastInsertId($seqname = null) { return $this->client->insert_id; } + /** + * @return mixed|void + */ public function errorCode() { $this->client->errno; } + /** + * @return array + */ public function errorInfo() { return [ @@ -153,6 +209,11 @@ public function errorInfo() ]; } + /** + * @param string $statement + * + * @return int + */ public function exec($statement): int { $this->query($statement); @@ -160,9 +221,17 @@ public function exec($statement): int return $this->client->affected_rows; } - public function query(string $statement, float $timeout = -1) + /** + * @param string $statement + * @param int $mode + * @param mixed $arg3 + * @param array $ctorargs + * + * @return array|bool|false|\PDOStatement + */ + public function query($statement, $mode = PDO::ATTR_DEFAULT_FETCH_MODE, $arg3 = null, array $ctorargs = []) { - $result = $this->client->query($statement, $timeout); + $result = $this->client->query($statement, Arr::get(self::$options, 'timeout')); if ($result === false) { $exception = new Exception($this->client->error, $this->client->errno); @@ -172,39 +241,44 @@ public function query(string $statement, float $timeout = -1) return $result; } - private function rewriteToPosition(string $statement) + /** + * @param string $statement + * @param array $options + * + * @return bool|\PDOStatement|\SwooleTW\Http\Coroutine\PDOStatement + */ + public function prepare($statement, $options = null) { - // - } - - public function prepare($statement, $driverOptions = null) - { - $driverOptions = is_null($driverOptions) ? [] : $driverOptions; + $options = is_null($options) ? [] : $options; if (strpos($statement, ':') !== false) { $i = 0; $bindKeyMap = []; $statement = preg_replace_callback( - '/:(\w+)\b/', + '/:([a-zA-Z_]\w*?)\b/', function ($matches) use (&$i, &$bindKeyMap) { $bindKeyMap[$matches[1]] = $i++; return '?'; - }, - $statement - ); + }, $statement); } $stmtObj = $this->client->prepare($statement); if ($stmtObj) { $stmtObj->bindKeyMap = $bindKeyMap ?? []; - return new PDOStatement($this, $stmtObj, $driverOptions); + + return new PDOStatement($this, $stmtObj, $options); } else { $statementException = new StatementException($this->client->error, $this->client->errno); throw new QueryException($statement, [], $statementException); } } + /** + * @param int $attribute + * + * @return bool|mixed|string + */ public function getAttribute($attribute) { switch ($attribute) { @@ -221,7 +295,7 @@ public function getAttribute($attribute) case \PDO::ATTR_PERSISTENT: case \PDO::ATTR_PREFETCH: case \PDO::ATTR_SERVER_INFO: - return $this->serverInfo['timeout'] ?? static::$defaultOptions['timeout']; + return self::$options['timeout']; case \PDO::ATTR_SERVER_VERSION: return 'Swoole Mysql'; case \PDO::ATTR_TIMEOUT: @@ -230,6 +304,12 @@ public function getAttribute($attribute) } } + /** + * @param string $string + * @param null $paramtype + * + * @return string|void + */ public function quote($string, $paramtype = null) { throw new \BadMethodCallException(<<client->close(); diff --git a/src/Coroutine/PDOStatement.php b/src/Coroutine/PDOStatement.php index bec3fa1a..b30ae1bf 100644 --- a/src/Coroutine/PDOStatement.php +++ b/src/Coroutine/PDOStatement.php @@ -9,21 +9,62 @@ namespace SwooleTW\Http\Coroutine; + use PDOStatement as BaseStatement; -use SwooleTW\Http\Coroutine\PDO; use Swoole\Coroutine\MySQL\Statement; +/** + * Class PDOStatement + */ class PDOStatement extends BaseStatement { + /** + * @var \SwooleTW\Http\Coroutine\PDO + */ private $parent; + + /** + * @var \Swoole\Coroutine\MySQL\Statement|mixed + */ public $statement; + + /** + * @var int|mixed + */ public $timeout; + + /** + * @var array + */ public $bindMap = []; + + /** + * @var int + */ public $cursor = -1; + + /** + * @var int + */ public $cursorOrientation = PDO::FETCH_ORI_NEXT; + + /** + * @var array + */ public $resultSet = []; + + /** + * @var int + */ public $fetchStyle = PDO::FETCH_BOTH; + /** + * PDOStatement constructor. + * + * @param \SwooleTW\Http\Coroutine\PDO $parent + * @param \Swoole\Coroutine\MySQL\Statement $statement + * @param array $driverOptions + */ public function __construct(PDO $parent, Statement $statement, array $driverOptions = []) { $this->parent = $parent; @@ -48,7 +89,7 @@ public function rowCount() public function bindParam($parameter, &$variable, $type = null, $maxlen = null, $driverdata = null) { - if (! is_string($parameter) && ! is_int($parameter)) { + if (!is_string($parameter) && !is_int($parameter)) { return false; } @@ -60,15 +101,15 @@ public function bindParam($parameter, &$variable, $type = null, $maxlen = null, public function bindValue($parameter, $variable, $type = null) { - if (! is_string($parameter) && ! is_int($parameter)) { + if (!is_string($parameter) && !is_int($parameter)) { return false; } if (is_object($variable)) { - if (! method_exists($variable, '__toString')) { + if (!method_exists($variable, '__toString')) { return false; } else { - $variable = (string) $variable; + $variable = (string)$variable; } } @@ -86,16 +127,18 @@ private function afterExecute() public function execute($inputParameters = null) { - if (! empty($inputParameters)) { + if (!empty($inputParameters)) { foreach ($inputParameters as $key => $value) { $this->bindParam($key, $value); } } $inputParameters = []; - if (! empty($this->statement->bindKeyMap)) { + if (!empty($this->statement->bindKeyMap)) { foreach ($this->statement->bindKeyMap as $nameKey => $numKey) { - $inputParameters[$numKey] = $this->bindMap[$nameKey]; + if (isset($this->bindMap[$nameKey])) { + $inputParameters[$numKey] = $this->bindMap[$nameKey]; + } } } else { $inputParameters = $this->bindMap; @@ -105,12 +148,18 @@ public function execute($inputParameters = null) $this->resultSet = ($ok = $result !== false) ? $result : []; $this->afterExecute(); + if ($result === false) { + throw new \PDOException($this->errorInfo(), $this->errorCode()); + } + return $ok; } - public function setFetchMode($fetchStyle, $params = null) + public function setFetchMode($fetchStyle, $params = null, array $ctorarfg = []) { $this->fetchStyle = $fetchStyle; + + return true; } private function __executeWhenStringQueryEmpty() @@ -137,13 +186,9 @@ private function transBoth($rawData) return $temp; } - private function transStyle( - $rawData, - $fetchStyle = null, - $fetchArgument = null, - $ctorArgs = null - ) { - if (! is_array($rawData)) { + private function transStyle($rawData, $fetchStyle = null, $fetchArgument = null, $ctorArgs = null) + { + if (!is_array($rawData)) { return false; } if (empty($rawData)) { @@ -151,7 +196,8 @@ private function transStyle( } $fetchStyle = is_null($fetchStyle) ? $this->fetchStyle : $fetchStyle; - $ctorArgs = is_null($ctorArgs) ? [] : $ctorArgs; + // TODO Use it if needed + #$ctorArgs = is_null($ctorArgs) ? [] : $ctorArgs; $resultSet = []; switch ($fetchStyle) { @@ -166,7 +212,7 @@ private function transStyle( break; case PDO::FETCH_OBJ: foreach ($rawData as $row) { - $resultSet[] = (object) $row; + $resultSet[] = (object)$row; } break; case PDO::FETCH_NUM: @@ -182,16 +228,12 @@ private function transStyle( return $resultSet; } - public function fetch( - $fetchStyle = null, - $cursorOrientation = null, - $cursorOffset = null, - $fetchArgument = null - ) { + public function fetch($fetchStyle = null, $cursorOrientation = null, $cursorOffset = null, $fetchArgument = null) + { $this->__executeWhenStringQueryEmpty(); - $cursorOrientation = is_null($cursorOrientation) ? PDO::FETCH_ORI_NEXT : $cursorOrientation; - $cursorOffset = is_null($cursorOffset) ? 0 : (int) $cursorOffset; + $cursorOrientation = \is_null($cursorOrientation) ? PDO::FETCH_ORI_NEXT : $cursorOrientation; + $cursorOffset = \is_null($cursorOffset) ? 0 : (int)$cursorOffset; switch ($cursorOrientation) { case PDO::FETCH_ORI_ABS: @@ -222,16 +264,15 @@ public function fetch( /** * Returns a single column from the next row of a result set or FALSE if there are no more rows. * - * @param int $column_number - * 0-indexed number of the column you wish to retrieve from the row. - * If no value is supplied, PDOStatement::fetchColumn() fetches the first column. + * @param int|null $columnNumber * * @return bool|mixed */ public function fetchColumn($columnNumber = null) { - $columnNumber = is_null($columnNumber) ? 0 : $columnNumber; + $columnNumber = \is_null($columnNumber) ? 0 : $columnNumber; $this->__executeWhenStringQueryEmpty(); + return $this->fetch(PDO::FETCH_COLUMN, PDO::FETCH_ORI_NEXT, 0, $columnNumber); } diff --git a/src/Coroutine/StatementException.php b/src/Coroutine/StatementException.php index ca839e08..9259bcbd 100644 --- a/src/Coroutine/StatementException.php +++ b/src/Coroutine/StatementException.php @@ -2,6 +2,7 @@ namespace SwooleTW\Http\Coroutine; + class StatementException extends \Exception { // diff --git a/src/Exceptions/FrameworkNotSupportException.php b/src/Exceptions/FrameworkNotSupportException.php new file mode 100644 index 00000000..90401358 --- /dev/null +++ b/src/Exceptions/FrameworkNotSupportException.php @@ -0,0 +1,22 @@ +version(), $expression)) { + return $version; + } + + throw new LogicException('No any version found.'); + } + + /** + * Extracts lumen version from $app->version() + * + * @param string $version + * @param string $expression + * + * @return string|null + */ + protected static function extractVersion(string $version, string $expression): ?string + { + if (preg_match($expression, $version, $result)) { + return Arr::first($result); + } + + return null; + } +} \ No newline at end of file diff --git a/src/Helpers/OS.php b/src/Helpers/OS.php new file mode 100644 index 00000000..1104473b --- /dev/null +++ b/src/Helpers/OS.php @@ -0,0 +1,55 @@ +publishes([ __DIR__ . '/../config/swoole_http.php' => base_path('config/swoole_http.php'), __DIR__ . '/../config/swoole_websocket.php' => base_path('config/swoole_websocket.php'), - __DIR__ . '/../routes/websocket.php' => base_path('routes/websocket.php') + __DIR__ . '/../routes/websocket.php' => base_path('routes/websocket.php'), ], 'laravel-swoole'); - if ($this->app['config']->get('swoole_http.websocket.enabled')) { + if ($this->app->make(Service::CONFIG_ALIAS)->get('swoole_http.websocket.enabled')) { $this->bootRoutes(); } } @@ -95,7 +99,7 @@ protected function mergeConfigs() */ protected function setIsWebsocket() { - $this->isWebsocket = $this->app['config']->get('swoole_http.websocket.enabled'); + $this->isWebsocket = $this->app->make(Service::CONFIG_ALIAS)->get('swoole_http.websocket.enabled'); } /** @@ -114,11 +118,13 @@ protected function registerCommands() protected function createSwooleServer() { $server = $this->isWebsocket ? WebsocketServer::class : HttpServer::class; - $host = $this->app['config']->get('swoole_http.server.host'); - $port = $this->app['config']->get('swoole_http.server.port'); - $socketType = $this->app['config']->get('swoole_http.server.socket_type', SWOOLE_SOCK_TCP); + $config = $this->app->make(Service::CONFIG_ALIAS); + $host = $config->get('swoole_http.server.host'); + $port = $config->get('swoole_http.server.port'); + $socketType = $config->get('swoole_http.server.socket_type', SWOOLE_SOCK_TCP); + $processType = $config->get('swoole.http.server.process_type', SWOOLE_PROCESS); - static::$server = new $server($host, $port, SWOOLE_PROCESS, $socketType); + static::$server = new $server($host, $port, $processType, $socketType); } /** @@ -126,11 +132,11 @@ protected function createSwooleServer() */ protected function configureSwooleServer() { - $config = $this->app['config']; + $config = $this->app->make(Service::CONFIG_ALIAS); $options = $config->get('swoole_http.server.options'); // only enable task worker in websocket mode and for queue driver - if ($config->get('queue.default') !== 'swoole' && ! $this->isWebsocket) { + if ($config->get('queue.default') !== 'swoole' && !$this->isWebsocket) { unset($config['task_worker_num']); } @@ -149,9 +155,10 @@ protected function registerServer() $this->createSwooleServer(); $this->configureSwooleServer(); } + return static::$server; }); - $this->app->alias(Server::class, 'swoole.server'); + $this->app->alias(Server::class, Service::SERVER_ALIAS); } /** @@ -159,29 +166,69 @@ protected function registerServer() */ protected function registerDatabaseDriver() { - $this->app->resolving('db', function ($db) { + $this->app->extend('db', function ($db) { $db->extend('mysql-coroutine', function ($config, $name) { $config['name'] = $name; - $connection = function () use ($config) { - return (new MySqlConnector())->connect($config); - }; + $config = $this->getMergedDatabaseConfig($config, $name); - return new MySqlConnection( - $connection, + $connection = new MySqlConnection( + $this->getNewMySqlConnection($config), $config['database'], $config['prefix'], $config ); + + if (isset($config['read'])) { + $connection->setReadPdo($this->getNewMySqlConnection($config)); + } + + return $connection; }); + + return $db; }); } + /** + * Get mereged config for coroutine mysql. + * + * @param array $config + * @param string $name + * + * @return array + */ + protected function getMergedDatabaseConfig(array $config, string $name) + { + $config['name'] = $name; + + if (isset($config['read'])) { + $config = array_merge($config, $config['read']); + } + if (isset($config['write'])) { + $config = array_merge($config, $config['write']); + } + + return $config; + } + + /** + * Get a new mysql connection. + * + * @param array $config + * + * @return \PDO + */ + protected function getNewMySqlConnection(array $config) + { + return ConnectorFactory::make(FW::version())->connect($config); + } + /** * Register queue driver for swoole async task. */ protected function registerSwooleQueueDriver() { - $this->app->afterResolving('queue', function ($manager) { + $this->app->afterResolving('queue', function (Manager $manager) { $manager->addConnector('swoole', function () { return new SwooleTaskConnector($this->app->make(Server::class)); }); diff --git a/src/LaravelServiceProvider.php b/src/LaravelServiceProvider.php index 5cf86a30..fe35a3ce 100644 --- a/src/LaravelServiceProvider.php +++ b/src/LaravelServiceProvider.php @@ -2,6 +2,7 @@ namespace SwooleTW\Http; + use SwooleTW\Http\Server\Manager; /** @@ -28,6 +29,6 @@ protected function registerManager() */ protected function bootRoutes() { - require __DIR__.'/../routes/laravel_routes.php'; + require __DIR__ . '/../routes/laravel_routes.php'; } } diff --git a/src/LumenServiceProvider.php b/src/LumenServiceProvider.php index f7ae8414..8e1bdfa9 100644 --- a/src/LumenServiceProvider.php +++ b/src/LumenServiceProvider.php @@ -2,6 +2,7 @@ namespace SwooleTW\Http; + use SwooleTW\Http\Server\Manager; /** diff --git a/src/Server/Facades/Sandbox.php b/src/Server/Facades/Sandbox.php index 8c468254..6375ecbb 100644 --- a/src/Server/Facades/Sandbox.php +++ b/src/Server/Facades/Sandbox.php @@ -2,6 +2,7 @@ namespace SwooleTW\Http\Server\Facades; + use Illuminate\Support\Facades\Facade; class Sandbox extends Facade diff --git a/src/Server/Facades/Server.php b/src/Server/Facades/Server.php index 7a34102a..8fc3e2b3 100644 --- a/src/Server/Facades/Server.php +++ b/src/Server/Facades/Server.php @@ -2,6 +2,7 @@ namespace SwooleTW\Http\Server\Facades; + use Illuminate\Support\Facades\Facade; class Server extends Facade diff --git a/src/Server/Manager.php b/src/Server/Manager.php index b5715d81..695362b6 100644 --- a/src/Server/Manager.php +++ b/src/Server/Manager.php @@ -2,20 +2,26 @@ namespace SwooleTW\Http\Server; -use Throwable; -use Swoole\Http\Server; -use SwooleTW\Http\Server\Sandbox; -use SwooleTW\Http\Task\SwooleTaskJob; -use Illuminate\Support\Facades\Facade; -use SwooleTW\Http\Websocket\Websocket; -use SwooleTW\Http\Transformers\Request; -use SwooleTW\Http\Transformers\Response; -use SwooleTW\Http\Concerns\WithApplication; + +use Exception; use Illuminate\Contracts\Container\Container; use Illuminate\Contracts\Debug\ExceptionHandler; -use SwooleTW\Http\Concerns\InteractsWithWebsocket; +use Illuminate\Support\Facades\Facade; +use Illuminate\Support\Str; use SwooleTW\Http\Concerns\InteractsWithSwooleTable; +use SwooleTW\Http\Concerns\InteractsWithWebsocket; +use SwooleTW\Http\Concerns\WithApplication; +use SwooleTW\Http\Helpers\OS; +use SwooleTW\Http\Task\SwooleTaskJob; +use SwooleTW\Http\Transformers\Request; +use SwooleTW\Http\Transformers\Response; +use SwooleTW\Http\Websocket\Websocket; +use Symfony\Component\Debug\Exception\FatalThrowableError; +use Throwable; +/** + * Class Manager + */ class Manager { use InteractsWithWebsocket, @@ -53,10 +59,11 @@ class Manager /** * HTTP server manager constructor. * - * @param \Swoole\Http\Server $server * @param \Illuminate\Contracts\Container\Container $container * @param string $framework * @param string $basePath + * + * @throws \Exception */ public function __construct(Container $container, $framework, $basePath = null) { @@ -71,7 +78,7 @@ public function __construct(Container $container, $framework, $basePath = null) */ public function run() { - $this->container['swoole.server']->start(); + $this->container->make('swoole.server')->start(); } /** @@ -79,7 +86,7 @@ public function run() */ public function stop() { - $this->container['swoole.server']->shutdown(); + $this->container->make('swoole.server')->shutdown(); } /** @@ -98,17 +105,12 @@ protected function initialize() protected function setSwooleServerListeners() { foreach ($this->events as $event) { - $listener = 'on' . ucfirst($event); + $listener = Str::camel("on_$event"); + $callback = method_exists($this, $listener) ? [$this, $listener] : function () use ($event) { + $this->container->make('events')->fire("swoole.$event", func_get_args()); + }; - if (method_exists($this, $listener)) { - $this->container['swoole.server']->on($event, [$this, $listener]); - } else { - $this->container['swoole.server']->on($event, function () use ($event) { - $event = sprintf('swoole.%s', $event); - - $this->container['events']->fire($event, func_get_args()); - }); - } + $this->container->make('swoole.server')->on($event, $callback); } } @@ -120,7 +122,7 @@ public function onStart() $this->setProcessName('master process'); $this->createPidFile(); - $this->container['events']->fire('swoole.start', func_get_args()); + $this->container->make('events')->fire('swoole.start', func_get_args()); } /** @@ -131,23 +133,29 @@ public function onStart() public function onManagerStart() { $this->setProcessName('manager process'); - $this->container['events']->fire('swoole.managerStart', func_get_args()); + $this->container->make('events')->fire('swoole.managerStart', func_get_args()); } /** * "onWorkerStart" listener. + * + * @param \Swoole\Http\Server|mixed $server + * + * @throws \Exception */ public function onWorkerStart($server) { $this->clearCache(); - $this->setProcessName('worker process'); - $this->container['events']->fire('swoole.workerStart', func_get_args()); + $this->container->make('events')->fire('swoole.workerStart', func_get_args()); // don't init laravel app in task workers if ($server->taskworker) { + $this->setProcessName('task process'); + return; } + $this->setProcessName('worker process'); // clear events instance in case of repeated listeners in worker process Facade::clearResolvedInstance('events'); @@ -159,7 +167,7 @@ public function onWorkerStart($server) $this->bindToLaravelApp(); // prepare websocket handler and routes - if ($this->isWebsocket) { + if ($this->isServerWebsocket) { $this->prepareWebsocketHandler(); $this->loadWebsocketRoutes(); } @@ -173,11 +181,11 @@ public function onWorkerStart($server) */ public function onRequest($swooleRequest, $swooleResponse) { - $this->app['events']->fire('swoole.request'); + $this->app->make('events')->fire('swoole.request'); $this->resetOnRequest(); - $handleStatic = $this->container['config']->get('swoole_http.handle_static_files', true); - $publicPath = $this->container['config']->get('swoole_http.server.public_path', base_path('public')); + $handleStatic = $this->container->make('config')->get('swoole_http.handle_static_files', true); + $publicPath = $this->container->make('config')->get('swoole_http.server.public_path', base_path('public')); try { // handle static file request first @@ -188,17 +196,17 @@ public function onRequest($swooleRequest, $swooleResponse) $illuminateRequest = Request::make($swooleRequest)->toIlluminate(); // set current request to sandbox - $this->app['swoole.sandbox']->setRequest($illuminateRequest); + $this->app->make('swoole.sandbox')->setRequest($illuminateRequest); // enable sandbox - $this->app['swoole.sandbox']->enable(); + $this->app->make('swoole.sandbox')->enable(); // handle request via laravel/lumen's dispatcher - $illuminateResponse = $this->app['swoole.sandbox']->run($illuminateRequest); + $illuminateResponse = $this->app->make('swoole.sandbox')->run($illuminateRequest); $response = Response::make($illuminateResponse, $swooleResponse); $response->send(); } catch (Throwable $e) { try { - $exceptionResponse = $this->app[ExceptionHandler::class]->render($illuminateRequest, $e); + $exceptionResponse = $this->app->make(ExceptionHandler::class)->render(null, $e); $response = Response::make($exceptionResponse, $swooleResponse); $response->send(); } catch (Throwable $e) { @@ -206,7 +214,7 @@ public function onRequest($swooleRequest, $swooleResponse) } } finally { // disable and recycle sandbox resource - $this->app['swoole.sandbox']->disable(); + $this->app->make('swoole.sandbox')->disable(); } } @@ -216,31 +224,36 @@ public function onRequest($swooleRequest, $swooleResponse) protected function resetOnRequest() { // Reset websocket data - if ($this->isWebsocket) { - $this->app['swoole.websocket']->reset(true); + if ($this->isServerWebsocket) { + $this->app->make('swoole.websocket')->reset(true); } } /** * Set onTask listener. + * + * @param mixed $server + * @param string $taskId + * @param string $srcWorkerId + * @param mixed $data */ public function onTask($server, $taskId, $srcWorkerId, $data) { - $this->container['events']->fire('swoole.task', func_get_args()); + $this->container->make('events')->fire('swoole.task', func_get_args()); try { // push websocket message if (is_array($data)) { - if ($this->isWebsocket + if ($this->isServerWebsocket && array_key_exists('action', $data) && $data['action'] === Websocket::PUSH_ACTION) { $this->pushMessage($server, $data['data'] ?? []); } - // push async task to queue - } elseif (is_string($data)) { - $decoded = json_decode($data, true); + // push async task to queue + } else if (is_string($data)) { + $decoded = \json_decode($data, true); - if (JSON_ERROR_NONE === json_last_error() && isset($decoded['job'])) { + if (JSON_ERROR_NONE === \json_last_error() && isset($decoded['job'])) { (new SwooleTaskJob($this->container, $server, $data, $taskId, $srcWorkerId))->fire(); } } @@ -251,10 +264,16 @@ public function onTask($server, $taskId, $srcWorkerId, $data) /** * Set onFinish listener. + * + * @param mixed $server + * @param string $taskId + * @param mixed $data */ public function onFinish($server, $taskId, $data) { // task worker callback + $this->container->make('events')->fire('swoole.finish', func_get_args()); + return; } @@ -274,7 +293,7 @@ protected function bindToLaravelApp() $this->bindSandbox(); $this->bindSwooleTable(); - if ($this->isWebsocket) { + if ($this->isServerWebsocket) { $this->bindRoom(); $this->bindWebsocket(); } @@ -288,6 +307,7 @@ protected function bindSandbox() $this->app->singleton(Sandbox::class, function ($app) { return new Sandbox($app, $this->framework); }); + $this->app->alias(Sandbox::class, 'swoole.sandbox'); } @@ -298,7 +318,7 @@ protected function bindSandbox() */ protected function getPidFile() { - return $this->container['config']->get('swoole_http.server.options.pid_file'); + return $this->container->make('config')->get('swoole_http.server.options.pid_file'); } /** @@ -329,11 +349,11 @@ protected function removePidFile() */ protected function clearCache() { - if (function_exists('apc_clear_cache')) { + if (extension_loaded('apc')) { apc_clear_cache(); } - if (function_exists('opcache_reset')) { + if (extension_loaded('Zend OPcache')) { opcache_reset(); } } @@ -342,32 +362,23 @@ protected function clearCache() * Set process name. * * @codeCoverageIgnore + * * @param $process */ protected function setProcessName($process) { // MacOS doesn't support modifying process name. - if ($this->isMacOS() || $this->isInTesting()) { + if (OS::is(OS::MAC_OS) || $this->isInTesting()) { return; } $serverName = 'swoole_http_server'; - $appName = $this->container['config']->get('app.name', 'Laravel'); + $appName = $this->container->make('config')->get('app.name', 'Laravel'); $name = sprintf('%s: %s for %s', $serverName, $process, $appName); swoole_set_process_name($name); } - /** - * Indicates if the process is running in macOS. - * - * @return bool - */ - protected function isMacOS() - { - return PHP_OS === 'Darwin'; - } - /** * Indicates if it's in phpunit environment. * @@ -381,10 +392,14 @@ protected function isInTesting() /** * Log server error. * - * @param Throwable + * @param \Throwable|\Exception $e */ public function logServerError(Throwable $e) { - $this->container[ExceptionHandler::class]->report($e); + if (!$e instanceof Exception) { + $e = new FatalThrowableError($e); + } + + $this->container->make(ExceptionHandler::class)->report($e); } } diff --git a/src/Server/Resetters/BindRequest.php b/src/Server/Resetters/BindRequest.php index 35df56ce..610329c9 100644 --- a/src/Server/Resetters/BindRequest.php +++ b/src/Server/Resetters/BindRequest.php @@ -2,11 +2,14 @@ namespace SwooleTW\Http\Server\Resetters; + +use Illuminate\Contracts\Container\Container; use Illuminate\Http\Request; use SwooleTW\Http\Server\Sandbox; -use Illuminate\Contracts\Container\Container; -use SwooleTW\Http\Server\Resetters\ResetterContract; +/** + * Class BindRequest + */ class BindRequest implements ResetterContract { /** @@ -14,6 +17,8 @@ class BindRequest implements ResetterContract * * @param \Illuminate\Contracts\Container\Container $app * @param \SwooleTW\Http\Server\Sandbox $sandbox + * + * @return \Illuminate\Contracts\Container\Container */ public function handle(Container $app, Sandbox $sandbox) { diff --git a/src/Server/Resetters/ClearInstances.php b/src/Server/Resetters/ClearInstances.php index 24fc6963..9d0d446c 100644 --- a/src/Server/Resetters/ClearInstances.php +++ b/src/Server/Resetters/ClearInstances.php @@ -2,9 +2,9 @@ namespace SwooleTW\Http\Server\Resetters; -use SwooleTW\Http\Server\Sandbox; + use Illuminate\Contracts\Container\Container; -use SwooleTW\Http\Server\Resetters\ResetterContract; +use SwooleTW\Http\Server\Sandbox; class ClearInstances implements ResetterContract { @@ -13,6 +13,8 @@ class ClearInstances implements ResetterContract * * @param \Illuminate\Contracts\Container\Container $app * @param \SwooleTW\Http\Server\Sandbox $sandbox + * + * @return \Illuminate\Contracts\Container\Container */ public function handle(Container $app, Sandbox $sandbox) { diff --git a/src/Server/Resetters/RebindKernelContainer.php b/src/Server/Resetters/RebindKernelContainer.php index f97a07ac..7a8187be 100644 --- a/src/Server/Resetters/RebindKernelContainer.php +++ b/src/Server/Resetters/RebindKernelContainer.php @@ -2,18 +2,25 @@ namespace SwooleTW\Http\Server\Resetters; -use SwooleTW\Http\Server\Sandbox; -use Illuminate\Contracts\Http\Kernel; + use Illuminate\Contracts\Container\Container; -use SwooleTW\Http\Server\Resetters\ResetterContract; +use Illuminate\Contracts\Http\Kernel; +use SwooleTW\Http\Server\Sandbox; class RebindKernelContainer implements ResetterContract { + /** + * @var \Illuminate\Contracts\Container\Container + */ + protected $app; + /** * "handle" function for resetting app. * * @param \Illuminate\Contracts\Container\Container $app * @param \SwooleTW\Http\Server\Sandbox $sandbox + * + * @return \Illuminate\Contracts\Container\Container */ public function handle(Container $app, Sandbox $sandbox) { diff --git a/src/Server/Resetters/RebindRouterContainer.php b/src/Server/Resetters/RebindRouterContainer.php index c51398ce..ca6151ed 100644 --- a/src/Server/Resetters/RebindRouterContainer.php +++ b/src/Server/Resetters/RebindRouterContainer.php @@ -2,18 +2,30 @@ namespace SwooleTW\Http\Server\Resetters; -use SwooleTW\Http\Server\Sandbox; + use Illuminate\Contracts\Container\Container; -use SwooleTW\Http\Server\Resetters\ResetterContract; +use SwooleTW\Http\Server\Sandbox; use Symfony\Component\HttpKernel\Exception\NotFoundHttpException; class RebindRouterContainer implements ResetterContract { + /** + * @var \Illuminate\Contracts\Container\Container + */ + protected $container; + + /** + * @var mixed + */ + protected $routes; + /** * "handle" function for resetting app. * * @param \Illuminate\Contracts\Container\Container $app * @param \SwooleTW\Http\Server\Sandbox $sandbox + * + * @return \Illuminate\Contracts\Container\Container */ public function handle(Container $app, Sandbox $sandbox) { @@ -26,6 +38,7 @@ public function handle(Container $app, Sandbox $sandbox) return; } try { + /** @var mixed $route */ $route = $this->routes->match($request); // clear resolved controller if (property_exists($route, 'container')) { diff --git a/src/Server/Resetters/RebindViewContainer.php b/src/Server/Resetters/RebindViewContainer.php index 52bd5ab1..3f1cb57f 100644 --- a/src/Server/Resetters/RebindViewContainer.php +++ b/src/Server/Resetters/RebindViewContainer.php @@ -2,17 +2,29 @@ namespace SwooleTW\Http\Server\Resetters; -use SwooleTW\Http\Server\Sandbox; + use Illuminate\Contracts\Container\Container; -use SwooleTW\Http\Server\Resetters\ResetterContract; +use SwooleTW\Http\Server\Sandbox; class RebindViewContainer implements ResetterContract { + /** + * @var Container + */ + protected $container; + + /** + * @var array + */ + protected $shared; + /** * "handle" function for resetting app. * * @param \Illuminate\Contracts\Container\Container $app * @param \SwooleTW\Http\Server\Sandbox $sandbox + * + * @return \Illuminate\Contracts\Container\Container */ public function handle(Container $app, Sandbox $sandbox) { diff --git a/src/Server/Resetters/ResetConfig.php b/src/Server/Resetters/ResetConfig.php index 5fbfd042..4a0356c8 100644 --- a/src/Server/Resetters/ResetConfig.php +++ b/src/Server/Resetters/ResetConfig.php @@ -2,9 +2,9 @@ namespace SwooleTW\Http\Server\Resetters; -use SwooleTW\Http\Server\Sandbox; + use Illuminate\Contracts\Container\Container; -use SwooleTW\Http\Server\Resetters\ResetterContract; +use SwooleTW\Http\Server\Sandbox; class ResetConfig implements ResetterContract { @@ -13,6 +13,8 @@ class ResetConfig implements ResetterContract * * @param \Illuminate\Contracts\Container\Container $app * @param \SwooleTW\Http\Server\Sandbox $sandbox + * + * @return \Illuminate\Contracts\Container\Container */ public function handle(Container $app, Sandbox $sandbox) { diff --git a/src/Server/Resetters/ResetCookie.php b/src/Server/Resetters/ResetCookie.php index c9b76da9..2d89cf44 100644 --- a/src/Server/Resetters/ResetCookie.php +++ b/src/Server/Resetters/ResetCookie.php @@ -2,9 +2,9 @@ namespace SwooleTW\Http\Server\Resetters; -use SwooleTW\Http\Server\Sandbox; + use Illuminate\Contracts\Container\Container; -use SwooleTW\Http\Server\Resetters\ResetterContract; +use SwooleTW\Http\Server\Sandbox; class ResetCookie implements ResetterContract { @@ -13,6 +13,8 @@ class ResetCookie implements ResetterContract * * @param \Illuminate\Contracts\Container\Container $app * @param \SwooleTW\Http\Server\Sandbox $sandbox + * + * @return \Illuminate\Contracts\Container\Container */ public function handle(Container $app, Sandbox $sandbox) { diff --git a/src/Server/Resetters/ResetProviders.php b/src/Server/Resetters/ResetProviders.php index 0b11648e..f232f9d8 100644 --- a/src/Server/Resetters/ResetProviders.php +++ b/src/Server/Resetters/ResetProviders.php @@ -2,17 +2,24 @@ namespace SwooleTW\Http\Server\Resetters; -use SwooleTW\Http\Server\Sandbox; + use Illuminate\Contracts\Container\Container; -use SwooleTW\Http\Server\Resetters\ResetterContract; +use SwooleTW\Http\Server\Sandbox; class ResetProviders implements ResetterContract { + /** + * @var \Illuminate\Contracts\Container\Container + */ + protected $app; + /** * "handle" function for resetting app. * * @param \Illuminate\Contracts\Container\Container $app * @param \SwooleTW\Http\Server\Sandbox $sandbox + * + * @return \Illuminate\Contracts\Container\Container */ public function handle(Container $app, Sandbox $sandbox) { @@ -31,6 +38,9 @@ public function handle(Container $app, Sandbox $sandbox) /** * Rebind service provider's container. + * + * @param $app + * @param $provider */ protected function rebindProviderContainer($app, $provider) { diff --git a/src/Server/Resetters/ResetSession.php b/src/Server/Resetters/ResetSession.php index 84db650c..3848d55d 100644 --- a/src/Server/Resetters/ResetSession.php +++ b/src/Server/Resetters/ResetSession.php @@ -2,9 +2,9 @@ namespace SwooleTW\Http\Server\Resetters; -use SwooleTW\Http\Server\Sandbox; + use Illuminate\Contracts\Container\Container; -use SwooleTW\Http\Server\Resetters\ResetterContract; +use SwooleTW\Http\Server\Sandbox; class ResetSession implements ResetterContract { @@ -13,6 +13,8 @@ class ResetSession implements ResetterContract * * @param \Illuminate\Contracts\Container\Container $app * @param \SwooleTW\Http\Server\Sandbox $sandbox + * + * @return \Illuminate\Contracts\Container\Container */ public function handle(Container $app, Sandbox $sandbox) { diff --git a/src/Server/Resetters/ResetterContract.php b/src/Server/Resetters/ResetterContract.php index 5f63611f..e6398751 100644 --- a/src/Server/Resetters/ResetterContract.php +++ b/src/Server/Resetters/ResetterContract.php @@ -2,8 +2,9 @@ namespace SwooleTW\Http\Server\Resetters; -use SwooleTW\Http\Server\Sandbox; + use Illuminate\Contracts\Container\Container; +use SwooleTW\Http\Server\Sandbox; interface ResetterContract { diff --git a/src/Server/Sandbox.php b/src/Server/Sandbox.php index 0dbf367f..8c6059ce 100644 --- a/src/Server/Sandbox.php +++ b/src/Server/Sandbox.php @@ -2,25 +2,30 @@ namespace SwooleTW\Http\Server; -use Illuminate\Http\Request; -use Illuminate\Container\Container; -use SwooleTW\Http\Coroutine\Context; + +use Illuminate\Container\Container as ContainerFacade; +use Illuminate\Contracts\Config\Repository as ConfigContract; +use Illuminate\Contracts\Container\Container; use Illuminate\Contracts\Http\Kernel; +use Illuminate\Http\Request; use Illuminate\Support\Facades\Facade; +use Laravel\Lumen\Application as LumenApplication; use SwooleTW\Http\Concerns\ResetApplication; +use SwooleTW\Http\Coroutine\Context; use SwooleTW\Http\Exceptions\SandboxException; -use Laravel\Lumen\Application as LumenApplication; -use Symfony\Component\HttpFoundation\StreamedResponse; use Symfony\Component\HttpFoundation\BinaryFileResponse; -use Illuminate\Contracts\Config\Repository as ConfigContract; use Symfony\Component\HttpFoundation\Response as SymfonyResponse; +use Symfony\Component\HttpFoundation\StreamedResponse; +/** + * Class Sandbox + */ class Sandbox { use ResetApplication; /** - * @var \Illuminate\Container\Container + * @var \Illuminate\Contracts\Container\Container */ protected $app; @@ -31,10 +36,15 @@ class Sandbox /** * Constructor + * + * @param null $app + * @param null $framework + * + * @throws \SwooleTW\Http\Exceptions\SandboxException */ public function __construct($app = null, $framework = null) { - if (! $app instanceof Container) { + if (!$app instanceof Container) { return; } @@ -45,6 +55,10 @@ public function __construct($app = null, $framework = null) /** * Set framework type. + * + * @param string $framework + * + * @return \SwooleTW\Http\Server\Sandbox */ public function setFramework(string $framework) { @@ -64,7 +78,9 @@ public function getFramework() /** * Set a base application. * - * @param \Illuminate\Container\Container + * @param \Illuminate\Contracts\Container\Container $app + * + * @return \SwooleTW\Http\Server\Sandbox */ public function setBaseApp(Container $app) { @@ -77,6 +93,8 @@ public function setBaseApp(Container $app) * Set current request. * * @param \Illuminate\Http\Request + * + * @return \SwooleTW\Http\Server\Sandbox */ public function setRequest(Request $request) { @@ -88,7 +106,9 @@ public function setRequest(Request $request) /** * Set current snapshot. * - * @param \Illuminate\Container\Container + * @param \Illuminate\Contracts\Container\Container $snapshot + * + * @return \SwooleTW\Http\Server\Sandbox */ public function setSnapshot(Container $snapshot) { @@ -99,10 +119,12 @@ public function setSnapshot(Container $snapshot) /** * Initialize based on base app. + * + * @throws \SwooleTW\Http\Exceptions\SandboxException */ public function initialize() { - if (! $this->app instanceof Container) { + if (!$this->app instanceof Container) { throw new SandboxException('A base app has not been set.'); } @@ -116,7 +138,7 @@ public function initialize() /** * Get base application. * - * @return \Illuminate\Container\Container + * @return \Illuminate\Contracts\Container\Container */ public function getBaseApp() { @@ -126,12 +148,12 @@ public function getBaseApp() /** * Get an application snapshot * - * @return \Illuminate\Container\Container + * @return \Illuminate\Contracts\Container\Container|mixed */ public function getApplication() { $snapshot = $this->getSnapshot(); - if ($snapshot instanceOf Container) { + if ($snapshot instanceof Container) { return $snapshot; } @@ -145,11 +167,14 @@ public function getApplication() * Run framework. * * @param \Illuminate\Http\Request $request + * * @return \Illuminate\Http\Response + * @throws \SwooleTW\Http\Exceptions\SandboxException + * @throws \ReflectionException */ public function run(Request $request) { - if (! $this->getSnapshot() instanceof Container) { + if (!$this->getSnapshot() instanceof Container) { throw new SandboxException('Sandbox is not enabled.'); } @@ -166,7 +191,9 @@ public function run(Request $request) * Handle request for non-ob case. * * @param \Illuminate\Http\Request $request + * * @return \Illuminate\Http\Response + * @throws \ReflectionException */ protected function prepareResponse(Request $request) { @@ -183,7 +210,9 @@ protected function prepareResponse(Request $request) * Handle request for ob output. * * @param \Illuminate\Http\Request $request + * * @return \Illuminate\Http\Response + * @throws \ReflectionException */ protected function prepareObResponse(Request $request) { @@ -197,18 +226,19 @@ protected function prepareObResponse(Request $request) $isFile = false; if ($isStream = $response instanceof StreamedResponse) { $response->sendContent(); - } elseif ($response instanceof SymfonyResponse) { + } else if ($response instanceof SymfonyResponse) { $content = $response->getContent(); - } elseif (! $isFile = $response instanceof BinaryFileResponse) { - $content = (string) $response; + } else if (!$isFile = $response instanceof BinaryFileResponse) { + $content = (string)$response; } // process terminating logics $this->terminate($request, $response); // append ob content to response - if (! $isFile && ob_get_length() > 0) { + if (!$isFile && ob_get_length() > 0) { if ($isStream) { + // TODO add output to StreamedResponse to avoid 'Field declared dynamically' $response->output = ob_get_contents(); } else { $response->setContent(ob_get_contents() . $content); @@ -224,6 +254,7 @@ protected function prepareObResponse(Request $request) * Handle request through Laravel or Lumen. * * @param \Illuminate\Http\Request $request + * * @return \Illuminate\Http\Response */ protected function handleRequest(Request $request) @@ -254,6 +285,8 @@ public function isLaravel() /** * @param \Illuminate\Http\Request $request * @param \Illuminate\Http\Response $response + * + * @throws \ReflectionException */ public function terminate(Request $request, $response) { @@ -277,10 +310,12 @@ public function terminate(Request $request, $response) /** * Set laravel snapshot to container and facade. + * + * @throws \SwooleTW\Http\Exceptions\SandboxException */ public function enable() { - if (! $this->config instanceof ConfigContract) { + if (!$this->config instanceof ConfigContract) { throw new SandboxException('Please initialize after setting base app.'); } @@ -299,6 +334,8 @@ public function disable() /** * Replace app's self bindings. + * + * @param \Illuminate\Contracts\Container\Container|mixed $app */ public function setInstance(Container $app) { @@ -309,7 +346,7 @@ public function setInstance(Container $app) $app->instance(LumenApplication::class, $app); } - Container::setInstance($app); + ContainerFacade::setInstance($app); Context::setApp($app); Facade::clearResolvedInstances(); Facade::setFacadeApplication($app); @@ -328,7 +365,7 @@ public function getSnapshot() */ protected function removeRequest() { - return Context::removeData('_request'); + Context::removeData('_request'); } /** diff --git a/src/Server/helpers.php b/src/Server/helpers.php index 7fb15785..624043bc 100644 --- a/src/Server/helpers.php +++ b/src/Server/helpers.php @@ -3,16 +3,20 @@ /** * This is only for `function not exists` in config/swoole_http.php. */ -if (! function_exists('swoole_cpu_num')) { - function swoole_cpu_num() +if (!function_exists('swoole_cpu_num')) { + function swoole_cpu_num(): int { - return; + return 1; } } /** * This is only for `function not exists` in config/swoole_http.php. */ -if (! defined('SWOOLE_SOCK_TCP')) { +if (!defined('SWOOLE_SOCK_TCP')) { define('SWOOLE_SOCK_TCP', 1); } + +if (!defined('SWOOLE_PROCESS')) { + define('SWOOLE_PROCESS', 3); +} diff --git a/src/Table/Facades/SwooleTable.php b/src/Table/Facades/SwooleTable.php index f5441690..fb89a85b 100644 --- a/src/Table/Facades/SwooleTable.php +++ b/src/Table/Facades/SwooleTable.php @@ -2,8 +2,12 @@ namespace SwooleTW\Http\Table\Facades; + use Illuminate\Support\Facades\Facade; +/** + * Class SwooleTable + */ class SwooleTable extends Facade { /** diff --git a/src/Table/SwooleTable.php b/src/Table/SwooleTable.php index 9dfe8947..be046f30 100644 --- a/src/Table/SwooleTable.php +++ b/src/Table/SwooleTable.php @@ -2,6 +2,7 @@ namespace SwooleTW\Http\Table; + use Swoole\Table; class SwooleTable @@ -18,6 +19,7 @@ class SwooleTable * * @param string $name * @param \Swoole\Table $table + * * @return \SwooleTW\Http\Table\SwooleTable */ public function add(string $name, Table $table) @@ -31,6 +33,7 @@ public function add(string $name, Table $table) * Get a swoole table by its name from existing tables. * * @param string $name + * * @return \Swoole\Table $table */ public function get(string $name) @@ -51,7 +54,8 @@ public function getAll() /** * Dynamically access table. * - * @param string $key + * @param string $key + * * @return table */ public function __get($key) diff --git a/src/Task/Connectors/SwooleTaskConnector.php b/src/Task/Connectors/SwooleTaskConnector.php index 3b690aac..0ab71f3a 100644 --- a/src/Task/Connectors/SwooleTaskConnector.php +++ b/src/Task/Connectors/SwooleTaskConnector.php @@ -2,9 +2,14 @@ namespace SwooleTW\Http\Task\Connectors; -use SwooleTW\Http\Task\SwooleTaskQueue; + use Illuminate\Queue\Connectors\ConnectorInterface; +use SwooleTW\Http\Helpers\FW; +use SwooleTW\Http\Task\QueueFactory; +/** + * Class SwooleTaskConnector + */ class SwooleTaskConnector implements ConnectorInterface { /** @@ -14,10 +19,11 @@ class SwooleTaskConnector implements ConnectorInterface */ protected $swoole; - /** + /** * Create a new Swoole Async task connector instance. * * @param \Swoole\Http\Server $swoole + * * @return void */ public function __construct($swoole) @@ -28,11 +34,12 @@ public function __construct($swoole) /** * Establish a queue connection. * - * @param array $config + * @param array $config + * * @return \Illuminate\Contracts\Queue\Queue */ public function connect(array $config) { - return new SwooleTaskQueue($this->swoole); + return QueueFactory::make($this->swoole, FW::version()); } } diff --git a/src/Task/QueueFactory.php b/src/Task/QueueFactory.php new file mode 100644 index 00000000..a9d8bb9a --- /dev/null +++ b/src/Task/QueueFactory.php @@ -0,0 +1,108 @@ +getDocComment(), $result)) { + $fileVersion = Arr::first($result); + } + } + + return version_compare($fileVersion, $version, '>='); + } catch (\Exception $e) { + return false; + } + } + + /** + * @param string $version + * + * @return bool + */ + protected static function hasBreakingChanges(string $version): bool + { + return version_compare($version, self::CHANGE_VERSION, '>='); + } +} diff --git a/src/Task/SwooleTaskJob.php b/src/Task/SwooleTaskJob.php index 5a70b7a9..701c2b55 100644 --- a/src/Task/SwooleTaskJob.php +++ b/src/Task/SwooleTaskJob.php @@ -2,10 +2,14 @@ namespace SwooleTW\Http\Task; -use Illuminate\Queue\Jobs\Job; + use Illuminate\Contracts\Container\Container; use Illuminate\Contracts\Queue\Job as JobContract; +use Illuminate\Queue\Jobs\Job; +/** + * Class SwooleTaskJob + */ class SwooleTaskJob extends Job implements JobContract { /** @@ -36,15 +40,19 @@ class SwooleTaskJob extends Job implements JobContract */ protected $srcWrokerId; + /** + * @var int + */ + protected $srcWorkderId; + /** * Create a new job instance. * - * @param \Illuminate\Container\Container $container - * @param \Swoole\Http\Server $swoole - * @param string $job - * @param int $taskId - * @param int $srcWorkerId - * @return void + * @param \Illuminate\Contracts\Container\Container $container + * @param \Swoole\Http\Server $swoole + * @param string $job + * @param int $taskId + * @param $srcWrokerId */ public function __construct(Container $container, $swoole, $job, $taskId, $srcWrokerId) { @@ -63,7 +71,7 @@ public function __construct(Container $container, $swoole, $job, $taskId, $srcWr public function fire() { if (method_exists($this, 'resolveAndFire')) { - $this->resolveAndFire(json_decode($this->getRawBody(), true)); + $this->resolveAndFire(\json_decode($this->getRawBody(), true)); } else { parent::fire(); } @@ -71,6 +79,7 @@ public function fire() /** * Get the number of times the job has been attempted. + * * @return int */ public function attempts() @@ -80,6 +89,7 @@ public function attempts() /** * Get the raw body string for the job. + * * @return string */ public function getRawBody() @@ -87,9 +97,9 @@ public function getRawBody() return $this->job; } - /** * Get the job identifier. + * * @return string */ public function getJobId() @@ -100,7 +110,7 @@ public function getJobId() /** * Get the service container instance. * - * @return \Illuminate\Container\Container + * @return \Illuminate\Contracts\Container\Container */ public function getContainer() { diff --git a/src/Task/SwooleTaskQueue.php b/src/Task/SwooleTaskQueue.php index 734fbc4a..0a28fedf 100644 --- a/src/Task/SwooleTaskQueue.php +++ b/src/Task/SwooleTaskQueue.php @@ -2,11 +2,15 @@ namespace SwooleTW\Http\Task; + use Exception; -use Swoole\Timer; -use Illuminate\Queue\Queue; use Illuminate\Contracts\Queue\Queue as QueueContract; +use Illuminate\Queue\Queue; +use Swoole\Timer; +/** + * Class SwooleTaskQueue (5.7) + */ class SwooleTaskQueue extends Queue implements QueueContract { /** @@ -19,7 +23,7 @@ class SwooleTaskQueue extends Queue implements QueueContract /** * Create Async Task instance. * - * @param \Swoole\Http\Server $swoole + * @param \Swoole\Http\Server $swoole */ public function __construct($swoole) { @@ -29,9 +33,10 @@ public function __construct($swoole) /** * Push a new job onto the queue. * - * @param string|object $job - * @param mixed $data - * @param string $queue + * @param string|object $job + * @param mixed $data + * @param string $queue + * * @return mixed */ public function push($job, $data = '', $queue = null) @@ -42,23 +47,25 @@ public function push($job, $data = '', $queue = null) /** * Push a raw payload onto the queue. * - * @param string $payload - * @param string $queue - * @param array $options + * @param string $payload + * @param string $queue + * @param array $options + * * @return mixed */ public function pushRaw($payload, $queue = null, array $options = []) { - return $this->swoole->task($payload, ! is_numeric($queue) ? 1 : (int) $queue); + return $this->swoole->task($payload, !is_numeric($queue) ? 1 : (int)$queue); } /** * Push a new job onto the queue after a delay. * - * @param \DateTimeInterface|\DateInterval|int $delay - * @param string|object $job - * @param mixed $data - * @param string $queue + * @param \DateTimeInterface|\DateInterval|int $delay + * @param string|object $job + * @param mixed $data + * @param string $queue + * * @return mixed */ public function later($delay, $job, $data = '', $queue = null) @@ -71,12 +78,13 @@ public function later($delay, $job, $data = '', $queue = null) /** * Create a typical, string based queue payload array. * - * @param string $job - * @param mixed $data + * @param string $job + * @param string $queue + * @param mixed $data * - * @throws Expcetion + * @throws \Exception */ - protected function createStringPayload($job, $data) + protected function createStringPayload($job, $queue, $data) { throw new Exception('Unsupported empty data'); } @@ -84,7 +92,8 @@ protected function createStringPayload($job, $data) /** * Get the size of the queue. * - * @param string $queue + * @param string $queue + * * @return int */ public function size($queue = null) @@ -95,7 +104,8 @@ public function size($queue = null) /** * Pop the next job off of the queue. * - * @param string $queue + * @param string $queue + * * @return \Illuminate\Contracts\Queue\Job|null */ public function pop($queue = null) diff --git a/src/Transformers/Request.php b/src/Transformers/Request.php index 704ab911..c5777f2a 100644 --- a/src/Transformers/Request.php +++ b/src/Transformers/Request.php @@ -2,15 +2,18 @@ namespace SwooleTW\Http\Transformers; + use Illuminate\Http\Request as IlluminateRequest; use Swoole\Http\Request as SwooleRequest; -use Swoole\Http\Response as SwooleResponse; use Symfony\Component\HttpFoundation\ParameterBag; use Symfony\Component\HttpFoundation\Request as SymfonyRequest; +/** + * Class Request + */ class Request { - const BLACK_LIST = ['php', 'htaccess', 'config']; + private const BLACK_LIST = ['php', 'htaccess', 'config']; /** * @var \Illuminate\Http\Request @@ -21,7 +24,8 @@ class Request * Make a request. * * @param \Swoole\Http\Request $swooleRequest - * @return \SwooleTW\Http\Server\Request + * + * @return \SwooleTW\Http\Transformers\Request */ public static function make(SwooleRequest $swooleRequest) { @@ -40,6 +44,7 @@ public static function make(SwooleRequest $swooleRequest) * @param array $files * @param array $server * @param string $content + * * @throws \LogicException */ public function __construct(array $get, array $post, array $cookie, array $files, array $server, $content = null) @@ -56,8 +61,8 @@ public function __construct(array $get, array $post, array $cookie, array $files * @param array $files * @param array $server * @param string $content - * @return \Illuminate\Http\Request - * @throws \LogicException + * + * @return void */ protected function createIlluminateRequest($get, $post, $cookie, $files, $server, $content = null) { @@ -86,7 +91,7 @@ protected function createIlluminateRequest($get, $post, $cookie, $files, $server $request = new SymfonyRequest($get, $post, [], $cookie, $files, $server, $content); if (0 === strpos($request->headers->get('CONTENT_TYPE'), 'application/x-www-form-urlencoded') - && in_array(strtoupper($request->server->get('REQUEST_METHOD', 'GET')), array('PUT', 'DELETE', 'PATCH')) + && in_array(strtoupper($request->server->get('REQUEST_METHOD', 'GET')), ['PUT', 'DELETE', 'PATCH']) ) { parse_str($request->getContent(), $data); $request->request = new ParameterBag($data); @@ -115,6 +120,7 @@ public function getIlluminateRequest() * Transforms request parameters. * * @param \Swoole\Http\Request $request + * * @return array */ protected static function toIlluminateParameters(SwooleRequest $request) @@ -136,6 +142,7 @@ protected static function toIlluminateParameters(SwooleRequest $request) * * @param array $server * @param array $header + * * @return array */ protected static function transformServerParameters(array $server, array $header) @@ -151,7 +158,7 @@ protected static function transformServerParameters(array $server, array $header $key = str_replace('-', '_', $key); $key = strtoupper($key); - if (! in_array($key, ['REMOTE_ADDR', 'SERVER_PORT', 'HTTPS'])) { + if (!in_array($key, ['REMOTE_ADDR', 'SERVER_PORT', 'HTTPS'])) { $key = 'HTTP_' . $key; } @@ -166,27 +173,28 @@ protected static function transformServerParameters(array $server, array $header * * @param \Swoole\Http\Request $swooleRequest * @param \Swoole\Http\Response $swooleResponse - * @param string $path - * @return boolean + * @param string $publicPath + * + * @return boolean|null */ public static function handleStatic($swooleRequest, $swooleResponse, string $publicPath) { $uri = $swooleRequest->server['request_uri'] ?? ''; $extension = substr(strrchr($uri, '.'), 1); if ($extension && in_array($extension, static::BLACK_LIST)) { - return; + return null; } $filename = $publicPath . $uri; - if (! is_file($filename) || filesize($filename) === 0) { - return; + if (!is_file($filename) || filesize($filename) === 0) { + return null; } $swooleResponse->status(200); $mime = mime_content_type($filename); if ($extension === 'js') { $mime = 'text/javascript'; - } elseif ($extension === 'css') { + } else if ($extension === 'css') { $mime = 'text/css'; } $swooleResponse->header('Content-Type', $mime); diff --git a/src/Transformers/Response.php b/src/Transformers/Response.php index 5efd0239..873e5508 100644 --- a/src/Transformers/Response.php +++ b/src/Transformers/Response.php @@ -2,6 +2,7 @@ namespace SwooleTW\Http\Transformers; + use Illuminate\Http\Response as IlluminateResponse; use Swoole\Http\Response as SwooleResponse; use Symfony\Component\HttpFoundation\BinaryFileResponse; @@ -25,7 +26,8 @@ class Response * * @param $illuminateResponse * @param \Swoole\Http\Response $swooleResponse - * @return \SwooleTW\Http\Server\Response + * + * @return \SwooleTW\Http\Transformers\Response */ public static function make($illuminateResponse, SwooleResponse $swooleResponse) { @@ -65,7 +67,7 @@ protected function sendHeaders() $illuminateResponse = $this->getIlluminateResponse(); /* RFC2616 - 14.18 says all Responses need to have a Date */ - if (! $illuminateResponse->headers->has('Date')) { + if (!$illuminateResponse->headers->has('Date')) { $illuminateResponse->setDate(\DateTime::createFromFormat('U', time())); } @@ -103,11 +105,10 @@ protected function sendContent() { $illuminateResponse = $this->getIlluminateResponse(); - if ($illuminateResponse instanceof StreamedResponse && - property_exists($illuminateResponse, 'output') - ) { + if ($illuminateResponse instanceof StreamedResponse && property_exists($illuminateResponse, 'output')) { + // TODO Add Streamed Response with output $this->swooleResponse->end($illuminateResponse->output); - } elseif ($illuminateResponse instanceof BinaryFileResponse) { + } else if ($illuminateResponse instanceof BinaryFileResponse) { $this->swooleResponse->sendfile($illuminateResponse->getFile()->getPathname()); } else { $this->swooleResponse->end($illuminateResponse->getContent()); @@ -116,7 +117,8 @@ protected function sendContent() /** * @param \Swoole\Http\Response $swooleResponse - * @return \SwooleTW\Http\Server\Response + * + * @return \SwooleTW\Http\Transformers\Response */ protected function setSwooleResponse(SwooleResponse $swooleResponse) { @@ -135,12 +137,13 @@ public function getSwooleResponse() /** * @param mixed illuminateResponse - * @return \SwooleTW\Http\Server\Response + * + * @return \SwooleTW\Http\Transformers\Response */ protected function setIlluminateResponse($illuminateResponse) { - if (! $illuminateResponse instanceof SymfonyResponse) { - $content = (string) $illuminateResponse; + if (!$illuminateResponse instanceof SymfonyResponse) { + $content = (string)$illuminateResponse; $illuminateResponse = new IlluminateResponse($content); } diff --git a/src/Websocket/Authenticatable.php b/src/Websocket/Authenticatable.php index ae9d1c3d..b33dfcac 100644 --- a/src/Websocket/Authenticatable.php +++ b/src/Websocket/Authenticatable.php @@ -2,15 +2,25 @@ namespace SwooleTW\Http\Websocket; -use InvalidArgumentException; + use Illuminate\Contracts\Auth\Authenticatable as AuthenticatableContract; +use InvalidArgumentException; +/** + * Trait Authenticatable + * + * @property-read \SwooleTW\Http\Websocket\Rooms\RoomContract $room + */ trait Authenticatable { protected $userId; /** * Login using current user. + * + * @param \Illuminate\Contracts\Auth\Authenticatable $user + * + * @return mixed */ public function loginUsing(AuthenticatableContract $user) { @@ -19,6 +29,10 @@ public function loginUsing(AuthenticatableContract $user) /** * Login using current userId. + * + * @param $userId + * + * @return mixed */ public function loginUsingId($userId) { @@ -27,11 +41,13 @@ public function loginUsingId($userId) /** * Logout with current sender's fd. + * + * @return mixed */ public function logout() { if (is_null($userId = $this->getUserId())) { - return; + return null; } return $this->leave(static::USER_PREFIX . $userId); @@ -39,13 +55,18 @@ public function logout() /** * Set multiple recepients' fds by users. + * + * @param $users + * + * @return \SwooleTW\Http\Websocket\Authenticatable */ public function toUser($users) { $users = is_object($users) ? func_get_args() : $users; - $userIds = array_map(function ($user) { + $userIds = array_map(function (AuthenticatableContract $user) { $this->checkUser($user); + return $user->getAuthIdentifier(); }, $users); @@ -54,6 +75,10 @@ public function toUser($users) /** * Set multiple recepients' fds by userIds. + * + * @param $userIds + * + * @return \SwooleTW\Http\Websocket\Authenticatable */ public function toUserId($userIds) { @@ -72,7 +97,7 @@ public function toUserId($userIds) */ public function getUserId() { - if (! is_null($this->userId)) { + if (!is_null($this->userId)) { return $this->userId; } @@ -89,18 +114,24 @@ public function getUserId() /** * Check if a user is online by given userId. + * + * @param $userId + * + * @return bool */ public function isUserIdOnline($userId) { - return ! empty($this->room->getClients(static::USER_PREFIX . $userId)); + return !empty($this->room->getClients(static::USER_PREFIX . $userId)); } /** * Check if user object implements AuthenticatableContract. + * + * @param $user */ protected function checkUser($user) { - if (! $user instanceOf AuthenticatableContract) { + if (!$user instanceOf AuthenticatableContract) { throw new InvalidArgumentException('user object must implement ' . AuthenticatableContract::class); } } diff --git a/src/Websocket/Facades/Room.php b/src/Websocket/Facades/Room.php index e0a26fd4..e702b9c8 100644 --- a/src/Websocket/Facades/Room.php +++ b/src/Websocket/Facades/Room.php @@ -2,8 +2,12 @@ namespace SwooleTW\Http\Websocket\Facades; + use Illuminate\Support\Facades\Facade; +/** + * Class Room + */ class Room extends Facade { /** diff --git a/src/Websocket/Facades/Websocket.php b/src/Websocket/Facades/Websocket.php index 8c24866b..a7313000 100644 --- a/src/Websocket/Facades/Websocket.php +++ b/src/Websocket/Facades/Websocket.php @@ -2,8 +2,12 @@ namespace SwooleTW\Http\Websocket\Facades; + use Illuminate\Support\Facades\Facade; +/** + * Class Websocket + */ class Websocket extends Facade { /** diff --git a/src/Websocket/HandlerContract.php b/src/Websocket/HandlerContract.php index c664026f..658d5eea 100644 --- a/src/Websocket/HandlerContract.php +++ b/src/Websocket/HandlerContract.php @@ -2,6 +2,7 @@ namespace SwooleTW\Http\Websocket; + use Illuminate\Http\Request; use Swoole\Websocket\Frame; diff --git a/src/Websocket/Middleware/Authenticate.php b/src/Websocket/Middleware/Authenticate.php index 27315d7b..3ca343dd 100644 --- a/src/Websocket/Middleware/Authenticate.php +++ b/src/Websocket/Middleware/Authenticate.php @@ -2,23 +2,28 @@ namespace SwooleTW\Http\Websocket\Middleware; + use Closure; use Illuminate\Auth\AuthenticationException; use Illuminate\Contracts\Auth\Factory as Auth; +/** + * Class Authenticate + */ class Authenticate { /** * The authentication factory instance. * - * @var \Illuminate\Contracts\Auth\Factory + * @var \Illuminate\Contracts\Auth\Factory|mixed */ protected $auth; /** * Create a new middleware instance. * - * @param \Illuminate\Contracts\Auth\Factory $auth + * @param \Illuminate\Contracts\Auth\Factory $auth + * * @return void */ public function __construct(Auth $auth) @@ -29,11 +34,11 @@ public function __construct(Auth $auth) /** * Handle an incoming request. * - * @param \Illuminate\Http\Request $request - * @param \Closure $next + * @param \Illuminate\Http\Request $request + * @param \Closure $next + * * @return mixed * - * @throws \Illuminate\Auth\AuthenticationException */ public function handle($request, Closure $next) { diff --git a/src/Websocket/Middleware/DecryptCookies.php b/src/Websocket/Middleware/DecryptCookies.php index 6a76c65e..6d564944 100644 --- a/src/Websocket/Middleware/DecryptCookies.php +++ b/src/Websocket/Middleware/DecryptCookies.php @@ -2,12 +2,15 @@ namespace SwooleTW\Http\Websocket\Middleware; + use Closure; -use Symfony\Component\HttpFoundation\Cookie; -use Symfony\Component\HttpFoundation\Request; use Illuminate\Contracts\Encryption\DecryptException; use Illuminate\Contracts\Encryption\Encrypter as EncrypterContract; +use Symfony\Component\HttpFoundation\Request; +/** + * Class DecryptCookies + */ class DecryptCookies { /** @@ -35,7 +38,8 @@ class DecryptCookies /** * Create a new CookieGuard instance. * - * @param \Illuminate\Contracts\Encryption\Encrypter $encrypter + * @param \Illuminate\Contracts\Encryption\Encrypter $encrypter + * * @return void */ public function __construct(EncrypterContract $encrypter) @@ -46,19 +50,21 @@ public function __construct(EncrypterContract $encrypter) /** * Disable encryption for the given cookie name(s). * - * @param string|array $name + * @param string|array $name + * * @return void */ public function disableFor($name) { - $this->except = array_merge($this->except, (array) $name); + $this->except = array_merge($this->except, (array)$name); } /** * Handle an incoming request. * - * @param \Illuminate\Http\Request $request - * @param \Closure $next + * @param \Illuminate\Http\Request $request + * @param \Closure $next + * * @return \Symfony\Component\HttpFoundation\Response */ public function handle($request, Closure $next) @@ -69,7 +75,8 @@ public function handle($request, Closure $next) /** * Decrypt the cookies on the request. * - * @param \Symfony\Component\HttpFoundation\Request $request + * @param \Symfony\Component\HttpFoundation\Request $request + * * @return \Symfony\Component\HttpFoundation\Request */ protected function decrypt(Request $request) @@ -92,21 +99,23 @@ protected function decrypt(Request $request) /** * Decrypt the given cookie and return the value. * - * @param string $name - * @param string|array $cookie + * @param string $name + * @param string|array $cookie + * * @return string|array */ protected function decryptCookie($name, $cookie) { return is_array($cookie) - ? $this->decryptArray($cookie) - : $this->encrypter->decrypt($cookie, static::serialized($name)); + ? $this->decryptArray($cookie) + : $this->encrypter->decrypt($cookie, static::serialized($name)); } /** * Decrypt an array based cookie. * - * @param array $cookie + * @param array $cookie + * * @return array */ protected function decryptArray(array $cookie) @@ -114,7 +123,7 @@ protected function decryptArray(array $cookie) $decrypted = []; foreach ($cookie as $key => $value) { - if (is_string($value)) { + if (\is_string($value)) { $decrypted[$key] = $this->encrypter->decrypt($value, static::serialized($key)); } } @@ -126,20 +135,22 @@ protected function decryptArray(array $cookie) * Determine whether encryption has been disabled for the given cookie. * * @param string $name + * * @return bool */ - public function isDisabled($name) + public function isDisabled(string $name) { - return in_array($name, $this->except); + return \in_array($name, $this->except); } /** * Determine if the cookie contents should be serialized. * - * @param string $name + * @param string $name + * * @return bool */ - public static function serialized($name) + public static function serialized(string $name) { return static::$serialize; } diff --git a/src/Websocket/Middleware/StartSession.php b/src/Websocket/Middleware/StartSession.php index bb5de3eb..44511480 100644 --- a/src/Websocket/Middleware/StartSession.php +++ b/src/Websocket/Middleware/StartSession.php @@ -2,11 +2,15 @@ namespace SwooleTW\Http\Websocket\Middleware; + use Closure; +use Illuminate\Contracts\Session\Session; use Illuminate\Http\Request; use Illuminate\Session\SessionManager; -use Illuminate\Contracts\Session\Session; +/** + * Class StartSession + */ class StartSession { /** @@ -19,7 +23,8 @@ class StartSession /** * Create a new session middleware. * - * @param \Illuminate\Session\SessionManager $manager + * @param \Illuminate\Session\SessionManager $manager + * * @return void */ public function __construct(SessionManager $manager) @@ -30,8 +35,9 @@ public function __construct(SessionManager $manager) /** * Handle an incoming request. * - * @param \Illuminate\Http\Request $request - * @param \Closure $next + * @param \Illuminate\Http\Request $request + * @param \Closure $next + * * @return mixed */ public function handle($request, Closure $next) @@ -48,12 +54,13 @@ public function handle($request, Closure $next) /** * Start the session for the given request. * - * @param \Illuminate\Http\Request $request + * @param \Illuminate\Http\Request $request + * * @return \Illuminate\Contracts\Session\Session */ protected function startSession(Request $request) { - return tap($this->getSession($request), function ($session) use ($request) { + return tap($this->getSession($request), function (Session $session) use ($request) { $session->setRequestOnHandler($request); $session->start(); @@ -63,12 +70,13 @@ protected function startSession(Request $request) /** * Get the session implementation from the manager. * - * @param \Illuminate\Http\Request $request + * @param \Illuminate\Http\Request $request + * * @return \Illuminate\Contracts\Session\Session */ public function getSession(Request $request) { - return tap($this->manager->driver(), function ($session) use ($request) { + return tap($this->manager->driver(), function (Session $session) use ($request) { $session->setId($request->cookies->get($session->getName())); }); } @@ -80,6 +88,6 @@ public function getSession(Request $request) */ protected function sessionConfigured() { - return ! is_null($this->manager->getSessionConfig()['driver'] ?? null); + return !is_null($this->manager->getSessionConfig()['driver'] ?? null); } } diff --git a/src/Websocket/Parser.php b/src/Websocket/Parser.php index c8a22543..a9805048 100644 --- a/src/Websocket/Parser.php +++ b/src/Websocket/Parser.php @@ -2,6 +2,7 @@ namespace SwooleTW\Http\Websocket; + use Illuminate\Support\Facades\App; abstract class Parser @@ -15,6 +16,9 @@ abstract class Parser * Execute strategies before decoding payload. * If return value is true will skip decoding. * + * @param \Swoole\WebSocket\Server $server + * @param \Swoole\WebSocket\Frame $frame + * * @return boolean */ public function execute($server, $frame) @@ -24,7 +28,7 @@ public function execute($server, $frame) foreach ($this->strategies as $strategy) { $result = App::call($strategy . '@handle', [ 'server' => $server, - 'frame' => $frame + 'frame' => $frame, ]); if ($result === true) { $skip = true; @@ -40,6 +44,7 @@ public function execute($server, $frame) * * @param string $event * @param mixed $data + * * @return mixed */ abstract public function encode(string $event, $data); @@ -49,6 +54,7 @@ abstract public function encode(string $event, $data); * Define and return event name and payload data here. * * @param \Swoole\Websocket\Frame $frame + * * @return array */ abstract public function decode($frame); diff --git a/src/Websocket/Push.php b/src/Websocket/Push.php new file mode 100644 index 00000000..40de4bd0 --- /dev/null +++ b/src/Websocket/Push.php @@ -0,0 +1,205 @@ +opcode = $opcode; + $this->sender = $sender; + $this->descriptors = $descriptors; + $this->broadcast = $broadcast; + $this->assigned = $assigned; + $this->event = $event; + $this->message = $message; + } + + /** + * Static constructor + * + * @param array $data + * + * @return \SwooleTW\Http\Websocket\Push + */ + public static function new(array $data) + { + $opcode = Arr::get($data, 'opcode', 1); + $sender = Arr::get($data, 'sender', 0); + $descriptors = Arr::get($data, 'fds', []); + $broadcast = Arr::get($data, 'broadcast', false); + $assigned = Arr::get($data, 'assigned', false); + $event = Arr::get($data, 'event', ''); + $message = Arr::get($data, 'message', null); + + return new static($opcode, $sender, $descriptors, $broadcast, $assigned, $event, $message); + } + + /** + * @return int + */ + public function getOpcode(): int + { + return $this->opcode; + } + + /** + * @return int + */ + public function getSender(): int + { + return $this->sender; + } + + /** + * @return array + */ + public function getDescriptors(): array + { + return $this->descriptors; + } + + /** + * @param int $descriptor + */ + public function addDescriptor($descriptor): void + { + $this->descriptors[] = $descriptor; + } + + /** + * @param array $descriptors + */ + public function mergeDescriptor(array $descriptors): void + { + $this->descriptors[] = array_merge($this->descriptors, $descriptors); + } + + /** + * @param int $descriptor + * + * @return bool + */ + public function hasDescriptor(int $descriptor): bool + { + return \in_array($descriptor, $this->descriptors, true); + } + + /** + * @return bool + */ + public function hasOwnDescriptor(): bool + { + return $this->hasDescriptor($this->sender); + } + + /** + * @return bool + */ + public function isBroadcast(): bool + { + return $this->broadcast; + } + + /** + * @return bool + */ + public function isAssigned(): bool + { + return $this->assigned; + } + + /** + * @return string + */ + public function getEvent(): string + { + return $this->event; + } + + /** + * @return string|null + */ + public function getMessage(): ?string + { + return $this->message; + } + + /** + * @return bool + */ + public function isBroadcastToAllDescriptors(): bool + { + return $this->isBroadcast() && !$this->isAssigned() && count($this->descriptors) > 0; + } + + /** + * @param int $descriptor + * + * @return bool + */ + public function isBroadcastToDescriptor(int $descriptor): bool + { + return $this->isBroadcast() && $this->getSender() === $descriptor; + } +} \ No newline at end of file diff --git a/src/Websocket/Rooms/RedisRoom.php b/src/Websocket/Rooms/RedisRoom.php index 410ac391..060ead65 100644 --- a/src/Websocket/Rooms/RedisRoom.php +++ b/src/Websocket/Rooms/RedisRoom.php @@ -2,47 +2,75 @@ namespace SwooleTW\Http\Websocket\Rooms; + +use Illuminate\Support\Arr; use Predis\Client as RedisClient; -use SwooleTW\Http\Websocket\Rooms\RoomContract; +use Predis\Pipeline\Pipeline; +/** + * Class RedisRoom + */ class RedisRoom implements RoomContract { + /** + * @var \Predis\Client + */ protected $redis; + /** + * @var array + */ protected $config; + /** + * @var string + */ protected $prefix = 'swoole:'; + /** + * RedisRoom constructor. + * + * @param array $config + */ public function __construct(array $config) { $this->config = $config; } - public function prepare(RedisClient $redis = null) + /** + * @param \Predis\Client|null $redis + * + * @return \SwooleTW\Http\Websocket\Rooms\RoomContract + */ + public function prepare(RedisClient $redis = null): RoomContract { $this->setRedis($redis); $this->setPrefix(); $this->cleanRooms(); + + return $this; } /** * Set redis client. + * + * @param \Predis\Client|null $redis */ - public function setRedis(RedisClient $redis = null) + public function setRedis(?RedisClient $redis = null) { - $server = $this->config['server'] ?? []; - $options = $this->config['options'] ?? []; + if (!$redis) { + $server = Arr::get($this->config, 'server', []); + $options = Arr::get($this->config, 'options', []); - // forbid setting prefix from options - if (array_key_exists('prefix', $options)) { - unset($options['prefix']); - } + // forbid setting prefix from options + if (Arr::has($options, 'prefix')) { + $options = Arr::except($options, 'prefix'); + } - if ($redis) { - $this->redis = $redis; - } else { - $this->redis = new RedisClient($server, $options); + $redis = new RedisClient($server, $options); } + + $this->redis = $redis; } /** @@ -50,8 +78,8 @@ public function setRedis(RedisClient $redis = null) */ protected function setPrefix() { - if (array_key_exists('prefix', $this->config)) { - $this->prefix = $this->config['prefix']; + if ($prefix = Arr::get($this->config, 'prefix')) { + $this->prefix = $prefix; } } @@ -63,35 +91,56 @@ public function getRedis() return $this->redis; } - public function add(int $fd, $roomNames) + /** + * Add multiple socket fds to a room. + * + * @param int fd + * @param array|string rooms + */ + public function add(int $fd, $rooms) { - $roomNames = is_array($roomNames) ? $roomNames : [$roomNames]; + $rooms = \is_array($rooms) ? $rooms : [$rooms]; - $this->addValue($fd, $roomNames, 'fds'); + $this->addValue($fd, $rooms, RoomContract::DESCRIPTORS_KEY); - foreach ($roomNames as $room) { - $this->addValue($room, [$fd], 'rooms'); + foreach ($rooms as $room) { + $this->addValue($room, [$fd], RoomContract::ROOMS_KEY); } } - public function delete(int $fd, $roomNames = []) + /** + * Delete multiple socket fds from a room. + * + * @param int fd + * @param array|string rooms + */ + public function delete(int $fd, $rooms) { - $roomNames = is_array($roomNames) ? $roomNames : [$roomNames]; - $roomNames = count($roomNames) ? $roomNames : $this->getRooms($fd); + $rooms = \is_array($rooms) ? $rooms : [$rooms]; + $rooms = \count($rooms) ? $rooms : $this->getRooms($fd); - $this->removeValue($fd, $roomNames, 'fds'); + $this->removeValue($fd, $rooms, RoomContract::DESCRIPTORS_KEY); - foreach ($roomNames as $room) { - $this->removeValue($room, [$fd], 'rooms'); + foreach ($rooms as $room) { + $this->removeValue($room, [$fd], RoomContract::ROOMS_KEY); } } + /** + * Add value to redis. + * + * @param $key + * @param array $values + * @param string $table + * + * @return $this + */ public function addValue($key, array $values, string $table) { $this->checkTable($table); $redisKey = $this->getKey($key, $table); - $this->redis->pipeline(function ($pipe) use ($redisKey, $values) { + $this->redis->pipeline(function (Pipeline $pipe) use ($redisKey, $values) { foreach ($values as $value) { $pipe->sadd($redisKey, $value); } @@ -100,12 +149,21 @@ public function addValue($key, array $values, string $table) return $this; } + /** + * Remove value from reddis. + * + * @param $key + * @param array $values + * @param string $table + * + * @return $this + */ public function removeValue($key, array $values, string $table) { $this->checkTable($table); $redisKey = $this->getKey($key, $table); - $this->redis->pipeline(function ($pipe) use ($redisKey, $values) { + $this->redis->pipeline(function (Pipeline $pipe) use ($redisKey, $values) { foreach ($values as $value) { $pipe->srem($redisKey, $value); } @@ -114,23 +172,50 @@ public function removeValue($key, array $values, string $table) return $this; } + /** + * Get all sockets by a room key. + * + * @param string room + * + * @return array + */ public function getClients(string $room) { - return $this->getValue($room, 'rooms'); + return $this->getValue($room, RoomContract::ROOMS_KEY) ?? []; } + /** + * Get all rooms by a fd. + * + * @param int fd + * + * @return array + */ public function getRooms(int $fd) { - return $this->getValue($fd, 'fds'); + return $this->getValue($fd, RoomContract::DESCRIPTORS_KEY) ?? []; } + /** + * Check table for rooms and descriptors. + * + * @param string $table + */ protected function checkTable(string $table) { - if (! in_array($table, ['rooms', 'fds'])) { + if (!in_array($table, [RoomContract::ROOMS_KEY, RoomContract::DESCRIPTORS_KEY])) { throw new \InvalidArgumentException('Invalid table name.'); } } + /** + * Get value. + * + * @param string $key + * @param string $table + * + * @return array + */ public function getValue(string $key, string $table) { $this->checkTable($table); @@ -138,12 +223,23 @@ public function getValue(string $key, string $table) return $this->redis->smembers($this->getKey($key, $table)); } + /** + * Get key. + * + * @param string $key + * @param string $table + * + * @return string + */ public function getKey(string $key, string $table) { return "{$this->prefix}{$table}:{$key}"; } - protected function cleanRooms() + /** + * Clean all rooms. + */ + protected function cleanRooms(): void { $keys = $this->redis->keys("{$this->prefix}*"); if (count($keys)) { diff --git a/src/Websocket/Rooms/RoomContract.php b/src/Websocket/Rooms/RoomContract.php index 8a1252a7..e3e91625 100644 --- a/src/Websocket/Rooms/RoomContract.php +++ b/src/Websocket/Rooms/RoomContract.php @@ -2,40 +2,61 @@ namespace SwooleTW\Http\Websocket\Rooms; + interface RoomContract { + /** + * Rooms key + * + * @const string + */ + public const ROOMS_KEY = 'rooms'; + + /** + * Descriptors key + * + * @const string + */ + public const DESCRIPTORS_KEY = 'fds'; + /** * Do some init stuffs before workers started. + * + * @return \SwooleTW\Http\Websocket\Rooms\RoomContract */ - public function prepare(); + public function prepare(): RoomContract; /** * Add multiple socket fds to a room. * - * @int fd - * @string|array rooms + * @param int fd + * @param array|string rooms */ public function add(int $fd, $rooms); /** * Delete multiple socket fds from a room. * - * @int fd - * @string|array rooms + * @param int fd + * @param array|string rooms */ public function delete(int $fd, $rooms); /** * Get all sockets by a room key. * - * @string room + * @param string room + * + * @return array */ public function getClients(string $room); /** * Get all rooms by a fd. * - * @int fd + * @param int fd + * + * @return array */ public function getRooms(int $fd); } diff --git a/src/Websocket/Rooms/TableRoom.php b/src/Websocket/Rooms/TableRoom.php index ad3e9146..42ddb74f 100644 --- a/src/Websocket/Rooms/TableRoom.php +++ b/src/Websocket/Rooms/TableRoom.php @@ -2,32 +2,59 @@ namespace SwooleTW\Http\Websocket\Rooms; + use Swoole\Table; -use SwooleTW\Http\Websocket\Rooms\RoomContract; class TableRoom implements RoomContract { + /** + * @var array + */ protected $config; + /** + * @var \Swoole\Table + */ protected $rooms; + /** + * @var \Swoole\Table + */ protected $fds; + /** + * TableRoom constructor. + * + * @param array $config + */ public function __construct(array $config) { $this->config = $config; } - public function prepare() + /** + * Do some init stuffs before workers started. + * + * @return \SwooleTW\Http\Websocket\Rooms\RoomContract + */ + public function prepare(): RoomContract { $this->initRoomsTable(); $this->initFdsTable(); + + return $this; } + /** + * Add multiple socket fds to a room. + * + * @param int fd + * @param array|string rooms + */ public function add(int $fd, $roomNames) { $rooms = $this->getRooms($fd); - $roomNames = is_array($roomNames) ? $roomNames : [$roomNames]; + $roomNames = \is_array($roomNames) ? $roomNames : [$roomNames]; foreach ($roomNames as $room) { $fds = $this->getClients($room); @@ -45,54 +72,92 @@ public function add(int $fd, $roomNames) $this->setRooms($fd, $rooms); } + /** + * Delete multiple socket fds from a room. + * + * @param int fd + * @param array|string rooms + */ public function delete(int $fd, $roomNames = []) { $allRooms = $this->getRooms($fd); - $roomNames = is_array($roomNames) ? $roomNames : [$roomNames]; - $rooms = count($roomNames) ? $roomNames : $allRooms; + $roomNames = \is_array($roomNames) ? $roomNames : [$roomNames]; + $rooms = \count($roomNames) ? $roomNames : $allRooms; $removeRooms = []; foreach ($rooms as $room) { $fds = $this->getClients($room); - if (! in_array($fd, $fds)) { + if (!in_array($fd, $fds)) { continue; } - $this->setClients($room, array_values(array_diff($fds, [$fd])), 'rooms'); + $this->setClients($room, array_values(array_diff($fds, [$fd]))); $removeRooms[] = $room; } - $this->setRooms($fd, array_values(array_diff($allRooms, $removeRooms)), 'fds'); + $this->setRooms($fd, collect($allRooms)->diff($removeRooms)->values()->toArray()); } + /** + * Get all sockets by a room key. + * + * @param string room + * + * @return array + */ public function getClients(string $room) { - return $this->getValue($room, 'rooms'); + return $this->getValue($room, RoomContract::ROOMS_KEY) ?? []; } + /** + * Get all rooms by a fd. + * + * @param int fd + * + * @return array + */ public function getRooms(int $fd) { - return $this->getValue($fd, 'fds'); + return $this->getValue($fd, RoomContract::DESCRIPTORS_KEY) ?? []; } - protected function setClients(string $room, array $fds) + /** + * @param string $room + * @param array $fds + * + * @return \SwooleTW\Http\Websocket\Rooms\TableRoom + */ + protected function setClients(string $room, array $fds): TableRoom { - return $this->setValue($room, $fds, 'rooms'); + return $this->setValue($room, $fds, RoomContract::ROOMS_KEY); } - protected function setRooms(int $fd, array $rooms) + /** + * @param int $fd + * @param array $rooms + * + * @return \SwooleTW\Http\Websocket\Rooms\TableRoom + */ + protected function setRooms(int $fd, array $rooms): TableRoom { - return $this->setValue($fd, $rooms, 'fds'); + return $this->setValue($fd, $rooms, RoomContract::DESCRIPTORS_KEY); } - protected function initRoomsTable() + /** + * Init rooms table + */ + protected function initRoomsTable(): void { $this->rooms = new Table($this->config['room_rows']); $this->rooms->column('value', Table::TYPE_STRING, $this->config['room_size']); $this->rooms->create(); } + /** + * Init descriptors table + */ protected function initFdsTable() { $this->fds = new Table($this->config['client_rows']); @@ -100,17 +165,34 @@ protected function initFdsTable() $this->fds->create(); } + /** + * Set value to table + * + * @param $key + * @param array $value + * @param string $table + * + * @return $this + */ public function setValue($key, array $value, string $table) { $this->checkTable($table); $this->$table->set($key, [ - 'value' => json_encode($value) + 'value' => json_encode($value), ]); return $this; } + /** + * Get value from table + * + * @param string $key + * @param string $table + * + * @return array|mixed + */ public function getValue(string $key, string $table) { $this->checkTable($table); @@ -120,9 +202,14 @@ public function getValue(string $key, string $table) return $value ? json_decode($value['value'], true) : []; } + /** + * Check table for exists + * + * @param string $table + */ protected function checkTable(string $table) { - if (! property_exists($this, $table) || ! $this->$table instanceof Table) { + if (!property_exists($this, $table) || !$this->$table instanceof Table) { throw new \InvalidArgumentException('Invalid table name.'); } } diff --git a/src/Websocket/SimpleParser.php b/src/Websocket/SimpleParser.php index a052dafc..1b0cadd0 100644 --- a/src/Websocket/SimpleParser.php +++ b/src/Websocket/SimpleParser.php @@ -2,8 +2,6 @@ namespace SwooleTW\Http\Websocket; -use Swoole\Websocket\Server; -use SwooleTW\Http\Websocket\Parser; class SimpleParser extends Parser { @@ -17,13 +15,14 @@ class SimpleParser extends Parser * * @param string $event * @param mixed $data + * * @return mixed */ public function encode(string $event, $data) { return json_encode([ 'event' => $event, - 'data' => $data + 'data' => $data, ]); } @@ -32,6 +31,7 @@ public function encode(string $event, $data) * Define and return event name and payload data here. * * @param \Swoole\Websocket\Frame $frame + * * @return array */ public function decode($frame) @@ -40,7 +40,7 @@ public function decode($frame) return [ 'event' => $data['event'] ?? null, - 'data' => $data['data'] ?? null + 'data' => $data['data'] ?? null, ]; } } diff --git a/src/Websocket/SocketIO/Packet.php b/src/Websocket/SocketIO/Packet.php index 07a4188a..bb7b83e4 100644 --- a/src/Websocket/SocketIO/Packet.php +++ b/src/Websocket/SocketIO/Packet.php @@ -2,6 +2,10 @@ namespace SwooleTW\Http\Websocket\SocketIO; + +/** + * Class Packet + */ class Packet { /** @@ -84,7 +88,7 @@ class Packet 3 => 'PONG', 4 => 'MESSAGE', 5 => 'UPGRADE', - 6 => 'NOOP' + 6 => 'NOOP', ]; /** @@ -97,25 +101,33 @@ class Packet 3 => 'ACK', 4 => 'ERROR', 5 => 'BINARY_EVENT', - 6 => 'BINARY_ACK' + 6 => 'BINARY_ACK', ]; /** * Get socket packet type of a raw payload. + * + * @param string $packet + * + * @return int|null */ public static function getSocketType(string $packet) { $type = $packet[0] ?? null; - if (! array_key_exists($type, static::$socketTypes)) { + if (!array_key_exists($type, static::$socketTypes)) { return null; } - return (int) $type; + return (int)$type; } /** * Get data packet from a raw payload. + * + * @param string $packet + * + * @return array|null */ public static function getPayload(string $packet) { @@ -135,12 +147,17 @@ public static function getPayload(string $packet) return [ 'event' => $data[0], - 'data' => $data[1] ?? null + 'data' => $data[1] ?? null, ]; } /** * Return if a socket packet belongs to specific type. + * + * @param $packet + * @param string $typeName + * + * @return bool */ public static function isSocketType($packet, string $typeName) { diff --git a/src/Websocket/SocketIO/SocketIOParser.php b/src/Websocket/SocketIO/SocketIOParser.php index 8c3e50d6..8272ba4a 100644 --- a/src/Websocket/SocketIO/SocketIOParser.php +++ b/src/Websocket/SocketIO/SocketIOParser.php @@ -2,17 +2,20 @@ namespace SwooleTW\Http\Websocket\SocketIO; + use SwooleTW\Http\Websocket\Parser; -use SwooleTW\Http\Websocket\SocketIO\Packet; use SwooleTW\Http\Websocket\SocketIO\Strategies\HeartbeatStrategy; +/** + * Class SocketIOParser + */ class SocketIOParser extends Parser { /** * Strategy classes need to implement handle method. */ protected $strategies = [ - HeartbeatStrategy::class + HeartbeatStrategy::class, ]; /** @@ -20,6 +23,7 @@ class SocketIOParser extends Parser * * @param string $event * @param mixed $data + * * @return mixed */ public function encode(string $event, $data) @@ -37,6 +41,7 @@ public function encode(string $event, $data) * Define and return payload here. * * @param \Swoole\Websocket\Frame $frame + * * @return array */ public function decode($frame) @@ -45,7 +50,7 @@ public function decode($frame) return [ 'event' => $payload['event'] ?? null, - 'data' => $payload['data'] ?? null + 'data' => $payload['data'] ?? null, ]; } } diff --git a/src/Websocket/SocketIO/Strategies/HeartbeatStrategy.php b/src/Websocket/SocketIO/Strategies/HeartbeatStrategy.php index e1fe7c64..88a8ae16 100644 --- a/src/Websocket/SocketIO/Strategies/HeartbeatStrategy.php +++ b/src/Websocket/SocketIO/Strategies/HeartbeatStrategy.php @@ -2,6 +2,7 @@ namespace SwooleTW\Http\Websocket\SocketIO\Strategies; + use SwooleTW\Http\Websocket\SocketIO\Packet; class HeartbeatStrategy @@ -9,6 +10,9 @@ class HeartbeatStrategy /** * If return value is true will skip decoding. * + * @param \Swoole\WebSocket\Server $server + * @param \Swoole\WebSocket\Frame $frame + * * @return boolean */ public function handle($server, $frame) diff --git a/src/Websocket/SocketIO/WebsocketHandler.php b/src/Websocket/SocketIO/WebsocketHandler.php index c78f6498..34b0e34e 100644 --- a/src/Websocket/SocketIO/WebsocketHandler.php +++ b/src/Websocket/SocketIO/WebsocketHandler.php @@ -2,12 +2,12 @@ namespace SwooleTW\Http\Websocket\SocketIO; -use Swoole\Websocket\Frame; + use Illuminate\Http\Request; use Illuminate\Support\Facades\App; use Illuminate\Support\Facades\Config; +use Swoole\Websocket\Frame; use SwooleTW\Http\Websocket\HandlerContract; -use SwooleTW\Http\Websocket\SocketIO\Packet; class WebsocketHandler implements HandlerContract { @@ -16,15 +16,17 @@ class WebsocketHandler implements HandlerContract * * @param int $fd * @param \Illuminate\Http\Request $request + * + * @return bool */ public function onOpen($fd, Request $request) { - if (! $request->input('sid')) { + if (!$request->input('sid')) { $payload = json_encode([ 'sid' => base64_encode(uniqid()), 'upgrades' => [], 'pingInterval' => Config::get('swoole_websocket.ping_interval'), - 'pingTimeout' => Config::get('swoole_websocket.ping_timeout') + 'pingTimeout' => Config::get('swoole_websocket.ping_timeout'), ]); $initPayload = Packet::OPEN . $payload; $connectPayload = Packet::MESSAGE . Packet::CONNECT; diff --git a/src/Websocket/Websocket.php b/src/Websocket/Websocket.php index d0da2d59..caad0773 100644 --- a/src/Websocket/Websocket.php +++ b/src/Websocket/Websocket.php @@ -2,13 +2,13 @@ namespace SwooleTW\Http\Websocket; -use InvalidArgumentException; + +use Illuminate\Contracts\Container\Container; +use Illuminate\Contracts\Pipeline\Pipeline as PipelineContract; use Illuminate\Support\Facades\App; use Illuminate\Support\Facades\Config; -use SwooleTW\Http\Websocket\Authenticatable; -use Illuminate\Contracts\Container\Container; +use InvalidArgumentException; use SwooleTW\Http\Websocket\Rooms\RoomContract; -use Illuminate\Contracts\Pipeline\Pipeline as PipelineContract; class Websocket { @@ -56,14 +56,14 @@ class Websocket /** * Pipeline instance. * - * @var PipelineContract + * @var \Illuminate\Contracts\Pipeline\Pipeline */ protected $pipeline; /** * Room adapter. * - * @var RoomContract + * @var \SwooleTW\Http\Websocket\Rooms\RoomContract */ protected $room; @@ -94,14 +94,15 @@ public function broadcast() * Set multiple recipients fd or room names. * * @param integer, string, array + * * @return $this */ - public function to($values) + public function to($values): self { $values = is_string($values) || is_integer($values) ? func_get_args() : $values; foreach ($values as $value) { - if (! in_array($value, $this->to)) { + if (!in_array($value, $this->to)) { $this->to[] = $value; } } @@ -113,9 +114,10 @@ public function to($values) * Join sender to multiple rooms. * * @param string, array $rooms + * * @return $this */ - public function join($rooms) + public function join($rooms): self { $rooms = is_string($rooms) || is_integer($rooms) ? func_get_args() : $rooms; @@ -127,10 +129,11 @@ public function join($rooms) /** * Make sender leave multiple rooms. * - * @param string, array + * @param array $rooms + * * @return $this */ - public function leave($rooms = []) + public function leave($rooms = []): self { $rooms = is_string($rooms) || is_integer($rooms) ? func_get_args() : $rooms; @@ -144,12 +147,13 @@ public function leave($rooms = []) * * @param string * @param mixed + * * @return boolean */ - public function emit(string $event, $data) + public function emit(string $event, $data): bool { $fds = $this->getFds(); - $assigned = ! empty($this->to); + $assigned = !empty($this->to); // if no fds are found, but rooms are assigned // that means trying to emit to a non-existing room @@ -166,8 +170,8 @@ public function emit(string $event, $data) 'broadcast' => $this->isBroadcast, 'assigned' => $assigned, 'event' => $event, - 'message' => $data - ] + 'message' => $data, + ], ]); $this->reset(); @@ -179,6 +183,7 @@ public function emit(string $event, $data) * An alias of `join` function. * * @param string + * * @return $this */ public function in($room) @@ -193,11 +198,12 @@ public function in($room) * * @param string * @param callback + * * @return $this */ public function on(string $event, $callback) { - if (! is_string($callback) && ! is_callable($callback)) { + if (!is_string($callback) && !is_callable($callback)) { throw new InvalidArgumentException( 'Invalid websocket callback. Must be a string or callable.' ); @@ -212,6 +218,7 @@ public function on(string $event, $callback) * Check if this event name exists. * * @param string + * * @return boolean */ public function eventExists(string $event) @@ -224,11 +231,12 @@ public function eventExists(string $event) * * @param string * @param mixed + * * @return mixed */ public function call(string $event, $data = null) { - if (! $this->eventExists($event)) { + if (!$this->eventExists($event)) { return null; } @@ -243,7 +251,7 @@ public function call(string $event, $data = null) return App::call($this->callbacks[$event], [ 'websocket' => $this, - $dataKey => $data + $dataKey => $data, ]); } @@ -251,6 +259,7 @@ public function call(string $event, $data = null) * Close current connection. * * @param integer + * * @return boolean */ public function close(int $fd = null) @@ -262,6 +271,7 @@ public function close(int $fd = null) * Set sender fd. * * @param integer + * * @return $this */ public function setSender(int $fd) @@ -320,6 +330,10 @@ protected function getFds() /** * Reset some data status. + * + * @param bool $force + * + * @return \SwooleTW\Http\Websocket\Websocket */ public function reset($force = false) { @@ -336,6 +350,10 @@ public function reset($force = false) /** * Get or set middleware. + * + * @param array|string|null $middleware + * + * @return array|\SwooleTW\Http\Websocket\Websocket */ public function middleware($middleware = null) { @@ -362,6 +380,8 @@ protected function setDefaultMiddleware() /** * Set container to pipeline. + * + * @param \Illuminate\Contracts\Container\Container $container */ public function setContainer(Container $container) { @@ -377,6 +397,10 @@ public function setContainer(Container $container) /** * Set pipeline. + * + * @param \Illuminate\Contracts\Pipeline\Pipeline $pipeline + * + * @return \SwooleTW\Http\Websocket\Websocket */ public function setPipeline(PipelineContract $pipeline) { @@ -396,7 +420,8 @@ public function getPipeline() /** * Set the given request through the middleware. * - * @param \Illuminate\Http\Request $request + * @param \Illuminate\Http\Request $request + * * @return \Illuminate\Http\Request */ protected function setRequestThroughMiddleware($request) diff --git a/stubs/5.5/MySqlConnector.stub b/stubs/5.5/MySqlConnector.stub new file mode 100644 index 00000000..45281ac0 --- /dev/null +++ b/stubs/5.5/MySqlConnector.stub @@ -0,0 +1,53 @@ +causedByLostConnection($e) || Str::contains($e->getMessage(), 'is closed')) { + return $this->createPdoConnection($dsn, $username, $password, $options); + } + + throw $e; + } +} diff --git a/stubs/5.6/MySqlConnector.stub b/stubs/5.6/MySqlConnector.stub new file mode 100644 index 00000000..7082d761 --- /dev/null +++ b/stubs/5.6/MySqlConnector.stub @@ -0,0 +1,53 @@ +causedByLostConnection($e) || Str::contains($e->getMessage(), 'is closed')) { + return $this->createPdoConnection($dsn, $username, $password, $options); + } + + throw $e; + } +} diff --git a/stubs/5.6/SwooleTaskQueue.stub b/stubs/5.6/SwooleTaskQueue.stub new file mode 100644 index 00000000..be9a2422 --- /dev/null +++ b/stubs/5.6/SwooleTaskQueue.stub @@ -0,0 +1,114 @@ +swoole = $swoole; + } + + /** + * Push a new job onto the queue. + * + * @param string|object $job + * @param mixed $data + * @param string $queue + * + * @return mixed + */ + public function push($job, $data = '', $queue = null) + { + return $this->pushRaw($this->createPayload($job, $data), $queue); + } + + /** + * Push a raw payload onto the queue. + * + * @param string $payload + * @param string $queue + * @param array $options + * + * @return mixed + */ + public function pushRaw($payload, $queue = null, array $options = []) + { + return $this->swoole->task($payload, !is_numeric($queue) ? 1 : (int)$queue); + } + + /** + * Push a new job onto the queue after a delay. + * + * @param \DateTimeInterface|\DateInterval|int $delay + * @param string|object $job + * @param mixed $data + * @param string $queue + * + * @return mixed + */ + public function later($delay, $job, $data = '', $queue = null) + { + return Timer::after($this->secondsUntil($delay) * 1000, function () use ($job, $data, $queue) { + return $this->push($job, $data, $queue); + }); + } + + /** + * Create a typical, string based queue payload array. + * + * @param string $job + * @param mixed $data + * + * @throws \Exception + */ + protected function createStringPayload($job, $data) + { + throw new Exception('Unsupported empty data'); + } + + /** + * Get the size of the queue. + * + * @param string $queue + * + * @return int + */ + public function size($queue = null) + { + return -1; + } + + /** + * Pop the next job off of the queue. + * + * @param string $queue + * + * @return \Illuminate\Contracts\Queue\Job|null + */ + public function pop($queue = null) + { + return null; + } +} diff --git a/stubs/5.7/SwooleTaskQueue.stub b/stubs/5.7/SwooleTaskQueue.stub new file mode 100644 index 00000000..0a28fedf --- /dev/null +++ b/stubs/5.7/SwooleTaskQueue.stub @@ -0,0 +1,115 @@ +swoole = $swoole; + } + + /** + * Push a new job onto the queue. + * + * @param string|object $job + * @param mixed $data + * @param string $queue + * + * @return mixed + */ + public function push($job, $data = '', $queue = null) + { + return $this->pushRaw($this->createPayload($job, $data), $queue); + } + + /** + * Push a raw payload onto the queue. + * + * @param string $payload + * @param string $queue + * @param array $options + * + * @return mixed + */ + public function pushRaw($payload, $queue = null, array $options = []) + { + return $this->swoole->task($payload, !is_numeric($queue) ? 1 : (int)$queue); + } + + /** + * Push a new job onto the queue after a delay. + * + * @param \DateTimeInterface|\DateInterval|int $delay + * @param string|object $job + * @param mixed $data + * @param string $queue + * + * @return mixed + */ + public function later($delay, $job, $data = '', $queue = null) + { + return Timer::after($this->secondsUntil($delay) * 1000, function () use ($job, $data, $queue) { + return $this->push($job, $data, $queue); + }); + } + + /** + * Create a typical, string based queue payload array. + * + * @param string $job + * @param string $queue + * @param mixed $data + * + * @throws \Exception + */ + protected function createStringPayload($job, $queue, $data) + { + throw new Exception('Unsupported empty data'); + } + + /** + * Get the size of the queue. + * + * @param string $queue + * + * @return int + */ + public function size($queue = null) + { + return -1; + } + + /** + * Pop the next job off of the queue. + * + * @param string $queue + * + * @return \Illuminate\Contracts\Queue\Job|null + */ + public function pop($queue = null) + { + return null; + } +} diff --git a/tests/Coroutine/ConnectorFactoryTest.php b/tests/Coroutine/ConnectorFactoryTest.php new file mode 100644 index 00000000..d47169f4 --- /dev/null +++ b/tests/Coroutine/ConnectorFactoryTest.php @@ -0,0 +1,45 @@ +=') ? '5.6' : '5.5'; + $stub = ConnectorFactory::stub($version); + + $this->assertTrue(Str::contains($stub, $search)); + } + + public function testItCanCompareNeededStubByVersion() + { + $version = '5.5'; + $search = '5.6'; + + $stub = ConnectorFactory::stub($version); + + $this->assertNotTrue(Str::contains($stub, $search)); + } + + public function testItCanMakeNeededQueueByVersion() + { + $version = FW::version(); + $queue = ConnectorFactory::make($version); + + $this->assertInstanceOf(ConnectorFactory::CONNECTOR_CLASS, $queue); + } +} \ No newline at end of file diff --git a/tests/Coroutine/ContextTest.php b/tests/Coroutine/ContextTest.php index fb5c6c36..d413482e 100644 --- a/tests/Coroutine/ContextTest.php +++ b/tests/Coroutine/ContextTest.php @@ -2,11 +2,12 @@ namespace SwooleTW\Http\Tests\Coroutine; -use TypeError; -use Mockery as m; -use SwooleTW\Http\Tests\TestCase; + use Illuminate\Container\Container; +use Mockery as m; use SwooleTW\Http\Coroutine\Context; +use SwooleTW\Http\Tests\TestCase; +use TypeError; class ContextTest extends TestCase { diff --git a/tests/Server/ManagerTest.php b/tests/Server/ManagerTest.php index d0b80fc7..69740c8c 100644 --- a/tests/Server/ManagerTest.php +++ b/tests/Server/ManagerTest.php @@ -2,26 +2,27 @@ namespace SwooleTW\Http\Tests\Server; + +use Illuminate\Container\Container; +use Illuminate\Contracts\Debug\ExceptionHandler; +use Illuminate\Support\Facades\Config; +use Laravel\Lumen\Exceptions\Handler; use Mockery as m; -use Swoole\Table; use Swoole\Http\Request; use Swoole\Http\Response; +use Swoole\Table; use SwooleTW\Http\Server\Manager; use SwooleTW\Http\Server\Sandbox; -use SwooleTW\Http\Tests\TestCase; -use Illuminate\Container\Container; -use SwooleTW\Http\Websocket\Parser; use SwooleTW\Http\Table\SwooleTable; -use Swoole\Http\Server as HttpServer; -use Illuminate\Support\Facades\Config; -use SwooleTW\Http\Websocket\Websocket; +use SwooleTW\Http\Tests\TestCase; +use SwooleTW\Http\Websocket\Facades\Websocket as WebsocketFacade; use SwooleTW\Http\Websocket\HandlerContract; -use SwooleTW\Http\Websocket\Rooms\TableRoom; +use SwooleTW\Http\Websocket\Parser; use SwooleTW\Http\Websocket\Rooms\RoomContract; -use Illuminate\Contracts\Debug\ExceptionHandler; +use SwooleTW\Http\Websocket\Rooms\TableRoom; use SwooleTW\Http\Websocket\SocketIO\SocketIOParser; use SwooleTW\Http\Websocket\SocketIO\WebsocketHandler; -use SwooleTW\Http\Websocket\Facades\Websocket as WebsocketFacade; +use SwooleTW\Http\Websocket\Websocket; class ManagerTest extends TestCase { @@ -31,13 +32,13 @@ class ManagerTest extends TestCase 'table_name' => [ 'size' => 1024, 'columns' => [ - ['name' => 'column_name', 'type' => Table::TYPE_STRING, 'size' => 1024] - ] - ] + ['name' => 'column_name', 'type' => Table::TYPE_STRING, 'size' => 1024], + ], + ], ], 'swoole_http.providers' => [], 'swoole_http.resetters' => [], - 'swoole_http.pre_resolved' => ['foo'] + 'swoole_http.pre_resolved' => ['foo'], ]; protected $websocketConfig = [ @@ -49,13 +50,13 @@ class ManagerTest extends TestCase 'room_rows' => 10, 'room_size' => 10, 'client_rows' => 10, - 'client_size' => 10 + 'client_size' => 10, ], 'swoole_websocket.drivers.table' => TableRoom::class, 'swoole_http.tables' => [], 'swoole_http.providers' => [], 'swoole_http.resetters' => [], - 'swoole_http.server.public_path' => '/' + 'swoole_http.server.public_path' => '/', ]; public function testGetFramework() @@ -74,7 +75,7 @@ public function testGetWebsocketParser() { $manager = $this->getWebsocketManager(); - $this->assertTrue($manager->getParser() instanceof SocketIOParser); + $this->assertTrue($manager->getPayloadParser() instanceof SocketIOParser); } public function testRun() @@ -127,7 +128,7 @@ public function testOnManagerStart() public function testOnWorkerStart() { $server = $this->getServer(); - $manager = $this->getManager(); + $this->getManager(); $container = $this->getContainer($this->getServer(), $this->getConfig(true)); $container->singleton('events', function () { @@ -153,7 +154,7 @@ public function testOnWorkerStart() public function testLoadApplication() { $server = $this->getServer(); - $manager = $this->getManager(); + $this->getManager(); $container = $this->getContainer($this->getServer(), $this->getConfig()); $container->singleton('events', function () { @@ -164,7 +165,7 @@ public function testLoadApplication() $manager = $this->getManager($container, $framework = 'laravel', $path); $manager->onWorkerStart($server); - $app = $manager->getApplication(); + $manager->getApplication(); } public function testOnTaskWorkerStart() @@ -184,8 +185,8 @@ public function testOnTaskWorkerStart() public function testOnRequest() { - $server = $this->getServer(); - $manager = $this->getManager(); + $this->getServer(); + $this->getManager(); $container = $this->getContainer($this->getServer(), $this->getConfig(true)); $container->singleton('events', function () { @@ -196,6 +197,7 @@ public function testOnRequest() $websocket->shouldReceive('reset') ->with(true) ->once(); + return $websocket; }); $container->singleton('swoole.sandbox', function () { @@ -210,6 +212,7 @@ public function testOnRequest() ->once(); $sandbox->shouldReceive('disable') ->once(); + return $sandbox; }); @@ -249,12 +252,14 @@ public function testOnRequestException() $sandbox = m::mock(Sandbox::class); $sandbox->shouldReceive('disable') ->once(); + return $sandbox; }); $container->singleton(ExceptionHandler::class, function () { $handler = m::mock(ExceptionHandler::class); $handler->shouldReceive('render') ->once(); + return $handler; }); @@ -316,9 +321,9 @@ public function testSetParser() { $parser = m::mock(Parser::class); $manager = $this->getManager(); - $manager->setParser($parser); + $manager->setPayloadParser($parser); - $this->assertSame($parser, $manager->getParser()); + $this->assertSame($parser, $manager->getPayloadParser()); } public function testSetWebsocketHandler() @@ -339,6 +344,7 @@ public function testLogServerError() $handler->shouldReceive('report') ->with($exception) ->once(); + return $handler; }); $manager = $this->getManager($container); @@ -371,9 +377,10 @@ public function testOnOpen() $websocket->shouldReceive('setContainer') ->with(m::type(Container::class)) ->once(); - $websocket->shouldReceive('call') + $websocket->shouldReceive('call') ->with('connect', m::type('Illuminate\Http\Request')) ->once(); + return $websocket; }); $container->singleton('swoole.sandbox', function () { @@ -388,6 +395,7 @@ public function testOnOpen() $sandbox->shouldReceive('getApplication') ->once() ->andReturn(m::mock(Container::class)); + return $sandbox; }); @@ -399,7 +407,7 @@ public function testOnOpen() $manager = $this->getWebsocketManager(); $manager->setApplication($container); $manager->setWebsocketHandler($handler); - $manager->onOpen('server', $request); + $manager->onOpen($request); } public function testOnMessage() @@ -417,7 +425,7 @@ public function testOnMessage() ->once() ->andReturn($payload = [ 'event' => 'event', - 'data' => 'data' + 'data' => 'data', ]); $container = $this->getContainer(); @@ -437,6 +445,7 @@ public function testOnMessage() $websocket->shouldReceive('call') ->with($payload['event'], $payload['data']) ->once(); + return $websocket; }); $container->singleton('swoole.sandbox', function () { @@ -445,12 +454,13 @@ public function testOnMessage() ->once(); $sandbox->shouldReceive('disable') ->once(); + return $sandbox; }); $manager = $this->getWebsocketManager(); $manager->setApplication($container); - $manager->setParser($parser); + $manager->setPayloadParser($parser); $manager->onMessage('server', $frame); } @@ -476,6 +486,7 @@ public function testOnClose() ->once(); $websocket->shouldReceive('leave') ->once(); + return $websocket; }); @@ -492,8 +503,9 @@ public function testOnClose() ->with($fd) ->once() ->andReturn([ - 'websocket_status' => true + 'websocket_status' => true, ]); + return $server; }); @@ -511,7 +523,7 @@ public function testNormalizePushMessage() 'broadcast' => 'broadcast', 'assigned' => 'assigned', 'event' => 'event', - 'message' => 'message' + 'message' => 'message', ]; $manager = $this->getWebsocketManager(); @@ -531,7 +543,7 @@ public function testPushMessage() $data = [ 'fds' => [1, 2, 3], 'event' => 'event', - 'message' => 'message' + 'message' => 'message', ]; $parser = m::mock(Parser::class); @@ -548,7 +560,7 @@ public function testPushMessage() ->times(count($data['fds'])); $manager = $this->getWebsocketManager(); - $manager->setParser($parser); + $manager->setPayloadParser($parser); $manager->pushMessage($server, $data); } @@ -574,6 +586,7 @@ protected function getContainer($server = null, $config = null) $container->singleton('swoole.server', function () use ($server) { return $server; }); + $container->singleton(ExceptionHandler::class, Handler::class); return $container; } diff --git a/tests/Server/ResettersTest.php b/tests/Server/ResettersTest.php index ff416dc2..d2675fcb 100644 --- a/tests/Server/ResettersTest.php +++ b/tests/Server/ResettersTest.php @@ -2,22 +2,23 @@ namespace SwooleTW\Http\Tests\Server; -use Mockery as m; -use Illuminate\Http\Request; -use SwooleTW\Http\Server\Sandbox; -use SwooleTW\Http\Tests\TestCase; + use Illuminate\Container\Container; use Illuminate\Contracts\Http\Kernel; +use Illuminate\Http\Request; use Illuminate\Support\ServiceProvider; +use Mockery as m; use SwooleTW\Http\Server\Resetters\BindRequest; -use SwooleTW\Http\Server\Resetters\ResetConfig; -use SwooleTW\Http\Server\Resetters\ResetCookie; -use SwooleTW\Http\Server\Resetters\ResetSession; use SwooleTW\Http\Server\Resetters\ClearInstances; -use SwooleTW\Http\Server\Resetters\ResetProviders; -use SwooleTW\Http\Server\Resetters\RebindViewContainer; use SwooleTW\Http\Server\Resetters\RebindKernelContainer; use SwooleTW\Http\Server\Resetters\RebindRouterContainer; +use SwooleTW\Http\Server\Resetters\RebindViewContainer; +use SwooleTW\Http\Server\Resetters\ResetConfig; +use SwooleTW\Http\Server\Resetters\ResetCookie; +use SwooleTW\Http\Server\Resetters\ResetProviders; +use SwooleTW\Http\Server\Resetters\ResetSession; +use SwooleTW\Http\Server\Sandbox; +use SwooleTW\Http\Tests\TestCase; class ResettersTest extends TestCase { @@ -233,7 +234,13 @@ public function testResetProviders() } } -class TestProvider extends ServiceProvider { - public function register() {} - public function boot() {} +class TestProvider extends ServiceProvider +{ + public function register() + { + } + + public function boot() + { + } } diff --git a/tests/Server/SandboxTest.php b/tests/Server/SandboxTest.php index 9f04a1e6..ee4e02cf 100644 --- a/tests/Server/SandboxTest.php +++ b/tests/Server/SandboxTest.php @@ -2,21 +2,18 @@ namespace SwooleTW\Http\Tests\Server; -use Mockery as m; -use RuntimeException; -use Swoole\Coroutine; -use ReflectionProperty; -use Illuminate\Http\Request; + use Illuminate\Config\Repository; -use SwooleTW\Http\Server\Sandbox; -use SwooleTW\Http\Tests\TestCase; use Illuminate\Container\Container; +use Illuminate\Contracts\Container\Container as ContainerContract; +use Illuminate\Http\Request; +use Mockery as m; use SwooleTW\Http\Coroutine\Context; -use SwooleTW\Http\Server\Application; -use Illuminate\Support\Facades\Facade; use SwooleTW\Http\Exceptions\SandboxException; +use SwooleTW\Http\Server\Application; use SwooleTW\Http\Server\Resetters\ResetterContract; -use Illuminate\Contracts\Container\Container as ContainerContract; +use SwooleTW\Http\Server\Sandbox; +use SwooleTW\Http\Tests\TestCase; class SandboxTest extends TestCase { @@ -99,6 +96,31 @@ public function testGetApplication() $this->assertTrue($sandbox->getSnapshot() instanceof Container); } + public function testGetCachedSnapshot() + { + $container = m::mock(Container::class); + $snapshot = m::mock(Container::class); + $snapshot->shouldReceive('offsetGet') + ->with('foo') + ->once() + ->andReturn($result = 'bar'); + + $sandbox = new Sandbox; + $sandbox->setBaseApp($container); + $sandbox->setSnapshot($snapshot); + + $this->assertTrue($sandbox->getApplication() instanceof Container); + $this->assertEquals($result, $sandbox->getApplication()->foo); + } + + public function testRunWithoutSnapshot() + { + $this->expectException(SandboxException::class); + + $sandbox = new Sandbox; + $sandbox->run($request = m::mock(Request::class)); + } + public function testSetRequest() { $request = m::mock(Request::class); @@ -143,7 +165,8 @@ protected function getContainer() } } -class TestResetter implements ResetterContract { +class TestResetter implements ResetterContract +{ public function handle(ContainerContract $app, Sandbox $sandbox) { return 'foo'; diff --git a/tests/SocketIO/PacketTest.php b/tests/SocketIO/PacketTest.php index 484b2d9b..e2b7b20d 100644 --- a/tests/SocketIO/PacketTest.php +++ b/tests/SocketIO/PacketTest.php @@ -2,6 +2,7 @@ namespace SwooleTW\Http\Tests\SocketIO; + use SwooleTW\Http\Tests\TestCase; use SwooleTW\Http\Websocket\SocketIO\Packet; @@ -33,35 +34,35 @@ public function testGetPayload() $packet = '42["foo","bar"]'; $this->assertSame([ 'event' => 'foo', - 'data' => 'bar' + 'data' => 'bar', ], Packet::getPayload($packet)); $packet = '42["foo", "bar"]'; $this->assertSame([ 'event' => 'foo', - 'data' => 'bar' + 'data' => 'bar', ], Packet::getPayload($packet)); $packet = '42["foo",{"message":"test"}]'; $this->assertSame([ 'event' => 'foo', 'data' => [ - 'message' => 'test' - ] + 'message' => 'test', + ], ], Packet::getPayload($packet)); $packet = '42["foo", {"message":"test"}]'; $this->assertSame([ 'event' => 'foo', 'data' => [ - 'message' => 'test' - ] + 'message' => 'test', + ], ], Packet::getPayload($packet)); $packet = '42["foo"]'; $this->assertSame([ 'event' => 'foo', - 'data' => null + 'data' => null, ], Packet::getPayload($packet)); } diff --git a/tests/SocketIO/ParserTest.php b/tests/SocketIO/ParserTest.php index ff8c613f..346a829c 100644 --- a/tests/SocketIO/ParserTest.php +++ b/tests/SocketIO/ParserTest.php @@ -2,10 +2,11 @@ namespace SwooleTW\Http\Tests\SocketIO; + +use Illuminate\Support\Facades\App; use Mockery as m; use Swoole\Websocket\Frame; use SwooleTW\Http\Tests\TestCase; -use Illuminate\Support\Facades\App; use SwooleTW\Http\Websocket\SocketIO\SocketIOParser; use SwooleTW\Http\Websocket\SocketIO\Strategies\HeartbeatStrategy; @@ -24,7 +25,7 @@ public function testEncode() $data = ['message' => 'test']; $this->assertSame('42["foo",{"message":"test"}]', $parser->encode($event, $data)); - $data = (object) ['message' => 'test']; + $data = (object)['message' => 'test']; $this->assertSame('42["foo",{"message":"test"}]', $parser->encode($event, $data)); } @@ -38,15 +39,15 @@ public function testDecode() $this->assertSame([ 'event' => 'foo', 'data' => [ - 'message' => 'test' - ] + 'message' => 'test', + ], ], $parser->decode($frame)); $payload = '42["foo","bar"]'; $frame->data = $payload; $this->assertSame([ 'event' => 'foo', - 'data' => 'bar' + 'data' => 'bar', ], $parser->decode($frame)); } diff --git a/tests/SocketIO/SocketIOControllerTest.php b/tests/SocketIO/SocketIOControllerTest.php index a805a767..d9a9f78d 100644 --- a/tests/SocketIO/SocketIOControllerTest.php +++ b/tests/SocketIO/SocketIOControllerTest.php @@ -2,11 +2,12 @@ namespace SwooleTW\Http\Tests\SocketIO; -use Mockery as m; + use Illuminate\Http\Request; -use SwooleTW\Http\Tests\TestCase; use Illuminate\Support\Facades\Config; +use Mockery as m; use SwooleTW\Http\Controllers\SocketIOController; +use SwooleTW\Http\Tests\TestCase; class SocketIOControllerTest extends TestCase { @@ -24,8 +25,9 @@ public function testUnknownTransport() ->once() ->with([ 'code' => 0, - 'message' => 'Transport unknown' + 'message' => 'Transport unknown', ], 400); + return $response; }); @@ -66,6 +68,7 @@ public function testUpgradePayload() $base64Encode = false; $this->mockMethod('base64_encode', function () use (&$base64Encode) { $base64Encode = true; + return 'payload'; }); @@ -82,7 +85,7 @@ public function testUpgradePayload() 'sid' => 'payload', 'upgrades' => ['websocket'], 'pingInterval' => 1, - 'pingTimeout' => 1 + 'pingTimeout' => 1, ]); $expectedPayload = '97:0' . $expectedPayload . '2:40'; @@ -95,21 +98,20 @@ public function testUpgradePayload() public function testReject() { - $request = m::mock(Request::class); - $this->mockMethod('response', function () { $response = m::mock('response'); $response->shouldReceive('json') ->once() ->with([ 'code' => 3, - 'message' => 'Bad request' + 'message' => 'Bad request', ], 400); + return $response; }); $controller = new SocketIOController; - $controller->reject($request); + $controller->reject(); } protected function mockMethod($name, \Closure $function, $namespace = null) diff --git a/tests/SocketIO/WebsocketHandlerTest.php b/tests/SocketIO/WebsocketHandlerTest.php index 09575f6f..7cd011f8 100644 --- a/tests/SocketIO/WebsocketHandlerTest.php +++ b/tests/SocketIO/WebsocketHandlerTest.php @@ -2,12 +2,13 @@ namespace SwooleTW\Http\Tests\SocketIO; -use Mockery as m; -use Swoole\Websocket\Frame; + use Illuminate\Http\Request; -use SwooleTW\Http\Tests\TestCase; use Illuminate\Support\Facades\App; use Illuminate\Support\Facades\Config; +use Mockery as m; +use Swoole\Websocket\Frame; +use SwooleTW\Http\Tests\TestCase; use SwooleTW\Http\Websocket\SocketIO\WebsocketHandler; class WebsocketHandlerTest extends TestCase @@ -31,6 +32,7 @@ public function testOnOpen() $jsonEncode = false; $this->mockMethod('json_encode', function () use (&$jsonEncode) { $jsonEncode = true; + return '{foo: "bar"}'; }, 'SwooleTW\Http\Websocket\SocketIO'); diff --git a/tests/Table/TableTest.php b/tests/Table/TableTest.php index 35efc296..7e35a6e4 100644 --- a/tests/Table/TableTest.php +++ b/tests/Table/TableTest.php @@ -2,10 +2,11 @@ namespace SwooleTW\Http\Tests\Table; + use Mockery as m; use Swoole\Table; -use SwooleTW\Http\Tests\TestCase; use SwooleTW\Http\Table\SwooleTable; +use SwooleTW\Http\Tests\TestCase; class TableTest extends TestCase { diff --git a/tests/Task/FakeJob.php b/tests/Task/FakeJob.php index 49b6ab5f..37f953b9 100644 --- a/tests/Task/FakeJob.php +++ b/tests/Task/FakeJob.php @@ -2,10 +2,11 @@ namespace SwooleTW\Http\Tests\Task; + use Illuminate\Bus\Queueable; -use Illuminate\Queue\SerializesModels; -use Illuminate\Queue\InteractsWithQueue; use Illuminate\Contracts\Queue\ShouldQueue; +use Illuminate\Queue\InteractsWithQueue; +use Illuminate\Queue\SerializesModels; class FakeJob implements ShouldQueue { diff --git a/tests/Task/QueueFactoryTest.php b/tests/Task/QueueFactoryTest.php new file mode 100644 index 00000000..4afc0e51 --- /dev/null +++ b/tests/Task/QueueFactoryTest.php @@ -0,0 +1,58 @@ +=') ? '5.7' : '5.6'; + $stub = QueueFactory::stub($version); + + $this->assertTrue(Str::contains($stub, $search)); + } + + public function testItCanCompareNeededStubByVersion() + { + $version = '5.6'; + $search = '5.7'; + + $stub = QueueFactory::stub($version); + + $this->assertNotTrue(Str::contains($stub, $search)); + } + + public function testItCanMakeNeededQueueByVersion() + { + $version = FW::version(); + + $server = $this->getServer(); + $queue = QueueFactory::make($server, $version); + + $this->assertInstanceOf(QueueFactory::QUEUE_CLASS, $queue); + } + + protected function getServer() + { + $server = m::mock('server'); +// $server->shouldReceive('on'); + $server->taskworker = false; + $server->master_pid = -1; + + return $server; + } +} \ No newline at end of file diff --git a/tests/Task/SwooleJobTest.php b/tests/Task/SwooleJobTest.php index 7171e1ff..98fc5c23 100644 --- a/tests/Task/SwooleJobTest.php +++ b/tests/Task/SwooleJobTest.php @@ -2,10 +2,11 @@ namespace SwooleTW\Http\Tests\Task; -use Mockery as m; -use SwooleTW\Http\Tests\TestCase; + use Illuminate\Container\Container; +use Mockery as m; use SwooleTW\Http\Task\SwooleTaskJob; +use SwooleTW\Http\Tests\TestCase; class SwooleJobTest extends TestCase { diff --git a/tests/Task/SwooleQueueTest.php b/tests/Task/SwooleQueueTest.php index fecbc734..bb3fcf23 100644 --- a/tests/Task/SwooleQueueTest.php +++ b/tests/Task/SwooleQueueTest.php @@ -2,17 +2,18 @@ namespace SwooleTW\Http\Tests\Task; + use Mockery as m; +use SwooleTW\Http\Helpers\FW; +use SwooleTW\Http\Task\QueueFactory; use SwooleTW\Http\Tests\TestCase; -use SwooleTW\Http\Task\SwooleTaskQueue; class SwooleQueueTest extends TestCase { public function testPushProperlyPushesJobOntoSwoole() { $server = $this->getServer(); - - $queue = new SwooleTaskQueue($server); + $queue = QueueFactory::make($server, FW::version()); $server->shouldReceive('task')->once(); $queue->push(new FakeJob); } diff --git a/tests/TestCase.php b/tests/TestCase.php index 9d2ff71a..0965d984 100644 --- a/tests/TestCase.php +++ b/tests/TestCase.php @@ -2,12 +2,13 @@ namespace SwooleTW\Http\Tests; + +use Illuminate\Support\Facades\Facade; use Mockery as m; use phpmock\Mock; use phpmock\MockBuilder; -use SwooleTW\Http\Coroutine\Context; -use Illuminate\Support\Facades\Facade; use PHPUnit\Framework\TestCase as BaseTestCase; +use SwooleTW\Http\Coroutine\Context; class TestCase extends BaseTestCase { @@ -28,8 +29,8 @@ protected function mockMethod($name, \Closure $function, $namespace = null) { $builder = new MockBuilder(); $builder->setNamespace($namespace) - ->setName($name) - ->setFunction($function); + ->setName($name) + ->setFunction($function); $mock = $builder->build(); $mock->enable(); diff --git a/tests/Transformers/RequestTest.php b/tests/Transformers/RequestTest.php index 226ffa40..d68555d1 100644 --- a/tests/Transformers/RequestTest.php +++ b/tests/Transformers/RequestTest.php @@ -2,11 +2,12 @@ namespace SwooleTW\Http\Tests\Transformers; + +use Illuminate\Http\Request as IlluminateRequest; use Mockery as m; +use Swoole\Http\Request as SwooleRequest; use SwooleTW\Http\Tests\TestCase; use SwooleTW\Http\Transformers\Request; -use Swoole\Http\Request as SwooleRequest; -use Illuminate\Http\Request as IlluminateRequest; class RequestTest extends TestCase { @@ -34,12 +35,14 @@ public function testHandleStatic() $fileSize = false; $this->mockMethod('filesize', function () use (&$fileSize) { $fileSize = true; + return 1; }); $mimeContentType = false; $this->mockMethod('mime_content_type', function () use (&$mimeContentType) { $mimeContentType = true; + return 'foo'; }); @@ -74,6 +77,7 @@ public function testHandleStaticWithNoneFile() $isFile = false; $this->mockMethod('is_file', function () use (&$isFile) { $isFile = true; + return false; }); @@ -91,17 +95,23 @@ protected function mockMethod($name, \Closure $function, $namespace = null) class SwooleRequestStub extends SwooleRequest { public $get = []; + public $post = []; + public $header = ['foo' => 'bar']; + public $server = [ 'HTTP_CONTENT_LENGTH' => 0, 'CONTENT_LENGTH' => 0, 'HTTP_CONTENT_TYPE' => null, 'CONTENT_TYPE' => null, - 'request_uri' => 'foo.bar' + 'request_uri' => 'foo.bar', ]; + public $cookie = []; + public $files = []; + public $fd = 1; function rawContent() diff --git a/tests/Transformers/ResponseTest.php b/tests/Transformers/ResponseTest.php index d25084e5..3a2c268d 100644 --- a/tests/Transformers/ResponseTest.php +++ b/tests/Transformers/ResponseTest.php @@ -2,10 +2,11 @@ namespace SwooleTW\Http\Tests\Transformers; + +use Illuminate\Http\Response as IlluminateResponse; +use Swoole\Http\Response as SwooleResponse; use SwooleTW\Http\Tests\TestCase; use SwooleTW\Http\Transformers\Response; -use Swoole\Http\Response as SwooleResponse; -use Illuminate\Http\Response as IlluminateResponse; class ResponseTest extends TestCase { diff --git a/tests/Websocket/Middleware/AuthenticateTest.php b/tests/Websocket/Middleware/AuthenticateTest.php index 95abf43a..7f24acd1 100644 --- a/tests/Websocket/Middleware/AuthenticateTest.php +++ b/tests/Websocket/Middleware/AuthenticateTest.php @@ -2,10 +2,11 @@ namespace SwooleTW\Http\Tests\Websocket\Middleware; -use Mockery as m; + +use Illuminate\Contracts\Auth\Factory as Auth; use Illuminate\Http\Request; +use Mockery as m; use SwooleTW\Http\Tests\TestCase; -use Illuminate\Contracts\Auth\Factory as Auth; use SwooleTW\Http\Websocket\Middleware\Authenticate; class AuthenticateTest extends TestCase diff --git a/tests/Websocket/Middleware/DecrpytCookiesTest.php b/tests/Websocket/Middleware/DecrpytCookiesTest.php index e9f8913d..586f171e 100644 --- a/tests/Websocket/Middleware/DecrpytCookiesTest.php +++ b/tests/Websocket/Middleware/DecrpytCookiesTest.php @@ -2,12 +2,13 @@ namespace SwooleTW\Http\Tests\Websocket\Middleware; -use Mockery as m; + +use Illuminate\Contracts\Encryption\Encrypter as EncrypterContract; use Illuminate\Http\Request; +use Mockery as m; use SwooleTW\Http\Tests\TestCase; -use Symfony\Component\HttpFoundation\ParameterBag; use SwooleTW\Http\Websocket\Middleware\DecryptCookies; -use Illuminate\Contracts\Encryption\Encrypter as EncrypterContract; +use Symfony\Component\HttpFoundation\ParameterBag; class DecrpytCookiesTest extends TestCase { @@ -27,8 +28,8 @@ public function testDecrypt() 'foo' => 'bar', 'seafood' => 'sasaya', 'aaa' => [ - 'bbb' => 'ccc' - ] + 'bbb' => 'ccc', + ], ]); $encrypter = m::mock(EncrypterContract::class); diff --git a/tests/Websocket/Middleware/StartSessionTest.php b/tests/Websocket/Middleware/StartSessionTest.php index ac95c708..b9d75c64 100644 --- a/tests/Websocket/Middleware/StartSessionTest.php +++ b/tests/Websocket/Middleware/StartSessionTest.php @@ -2,11 +2,8 @@ namespace SwooleTW\Http\Tests\Websocket\Middleware; -use Mockery as m; -use Illuminate\Http\Request; + use SwooleTW\Http\Tests\TestCase; -use Illuminate\Session\SessionManager; -use SwooleTW\Http\Websocket\Middleware\StartSession; class StartSessionTest extends TestCase { diff --git a/tests/Websocket/RedisRoomTest.php b/tests/Websocket/RedisRoomTest.php index 8acf0c24..ce2b3634 100644 --- a/tests/Websocket/RedisRoomTest.php +++ b/tests/Websocket/RedisRoomTest.php @@ -2,9 +2,10 @@ namespace SwooleTW\Http\Tests\Websocket; + use Mockery as m; -use SwooleTW\Http\Tests\TestCase; use Predis\Client as RedisClient; +use SwooleTW\Http\Tests\TestCase; use SwooleTW\Http\Websocket\Rooms\RedisRoom; class RedisRoomTest extends TestCase diff --git a/tests/Websocket/SimpleParserTest.php b/tests/Websocket/SimpleParserTest.php index 2ef763cd..214b3a26 100644 --- a/tests/Websocket/SimpleParserTest.php +++ b/tests/Websocket/SimpleParserTest.php @@ -2,9 +2,9 @@ namespace SwooleTW\Http\Tests\Websocket; + use Mockery as m; use Swoole\Websocket\Frame; -use Swoole\Websocket\Server; use SwooleTW\Http\Tests\TestCase; use SwooleTW\Http\Websocket\SimpleParser; @@ -18,7 +18,7 @@ public function testEncode() $parser = new SimpleParser; $this->assertSame(json_encode([ 'event' => $event, - 'data' => $data + 'data' => $data, ]), $parser->encode($event, $data)); } @@ -26,7 +26,7 @@ public function testDecode() { $payload = json_encode($data = [ 'event' => 'foo', - 'data' => 'bar' + 'data' => 'bar', ]); $frame = m::mock(Frame::class); $frame->data = $payload; diff --git a/tests/Websocket/TableRoomTest.php b/tests/Websocket/TableRoomTest.php index 4eaf412c..b2df7d3a 100644 --- a/tests/Websocket/TableRoomTest.php +++ b/tests/Websocket/TableRoomTest.php @@ -2,6 +2,7 @@ namespace SwooleTW\Http\Tests\Websocket; + use Swoole\Table; use SwooleTW\Http\Tests\TestCase; use SwooleTW\Http\Websocket\Rooms\TableRoom; @@ -16,7 +17,7 @@ public function setUp() 'room_rows' => 4096, 'room_size' => 2048, 'client_rows' => 8192, - 'client_size' => 2048 + 'client_size' => 2048, ]; $this->tableRoom = new TableRoom($config); $this->tableRoom->prepare(); diff --git a/tests/Websocket/WebsocketTest.php b/tests/Websocket/WebsocketTest.php index 91dfceab..5341b124 100644 --- a/tests/Websocket/WebsocketTest.php +++ b/tests/Websocket/WebsocketTest.php @@ -2,17 +2,18 @@ namespace SwooleTW\Http\Tests\Websocket; -use Mockery as m; + +use Illuminate\Container\Container; +use Illuminate\Contracts\Auth\Authenticatable as AuthenticatableContract; use Illuminate\Http\Request; -use InvalidArgumentException; use Illuminate\Pipeline\Pipeline; -use SwooleTW\Http\Tests\TestCase; -use Illuminate\Container\Container; use Illuminate\Support\Facades\App; use Illuminate\Support\Facades\Config; -use SwooleTW\Http\Websocket\Websocket; +use InvalidArgumentException; +use Mockery as m; +use SwooleTW\Http\Tests\TestCase; use SwooleTW\Http\Websocket\Rooms\RoomContract; -use Illuminate\Contracts\Auth\Authenticatable as AuthenticatableContract; +use SwooleTW\Http\Websocket\Websocket; class WebsocketTest extends TestCase { @@ -339,8 +340,8 @@ public function testEmit() 'broadcast' => $broadcast, 'assigned' => true, 'event' => $event = 'event', - 'message' => $data = 'data' - ] + 'message' => $data = 'data', + ], ]) ->once(); @@ -369,7 +370,6 @@ public function testClose() $websocket = $this->getWebsocket(); $websocket->close($fd); - } protected function getWebsocket(RoomContract $room = null, $pipeline = null) diff --git a/tests/fixtures/bootstrap/app.php b/tests/fixtures/bootstrap/app.php index a7ad3f4a..4ab5ca49 100644 --- a/tests/fixtures/bootstrap/app.php +++ b/tests/fixtures/bootstrap/app.php @@ -1,8 +1,9 @@ [ SwooleTW\Http\Tests\Fixtures\Laravel\App\Providers\TestServiceProvider::class, - ] + ], ]; diff --git a/tests/fixtures/lumen/app/providers/TestServiceProvider.php b/tests/fixtures/lumen/app/providers/TestServiceProvider.php index a76a8b4e..6441b5da 100644 --- a/tests/fixtures/lumen/app/providers/TestServiceProvider.php +++ b/tests/fixtures/lumen/app/providers/TestServiceProvider.php @@ -2,6 +2,7 @@ namespace SwooleTW\Http\Tests\Fixtures\Lumen\App\Providers; + use Illuminate\Support\ServiceProvider; class TestServiceProvider extends ServiceProvider diff --git a/tests/fixtures/lumen/config/swoole_http.php b/tests/fixtures/lumen/config/swoole_http.php index f9fa02d9..5a9e3c08 100644 --- a/tests/fixtures/lumen/config/swoole_http.php +++ b/tests/fixtures/lumen/config/swoole_http.php @@ -21,5 +21,5 @@ ], 'providers' => [ SwooleTW\Http\Tests\Fixtures\Lumen\App\Providers\TestServiceProvider::class, - ] + ], ]; From 0e160f2133c8edb6d11015e8a2495765327b4986 Mon Sep 17 00:00:00 2001 From: Fractal Zombie Date: Wed, 19 Dec 2018 21:35:50 +0200 Subject: [PATCH 2/3] Refactoring. Removes old laravel|lumen versions. Added support for 5.6|5.7 laravel|lumen. Added to config support for hot reload (Next PR). --- src/Coroutine/Connectors/MySqlConnector.php | 1 - src/Task/SwooleTaskQueue.php | 51 ++++++++++++--------- 2 files changed, 30 insertions(+), 22 deletions(-) diff --git a/src/Coroutine/Connectors/MySqlConnector.php b/src/Coroutine/Connectors/MySqlConnector.php index ebcb052b..7082d761 100644 --- a/src/Coroutine/Connectors/MySqlConnector.php +++ b/src/Coroutine/Connectors/MySqlConnector.php @@ -26,7 +26,6 @@ class MySqlConnector extends BaseConnector */ protected function createPdoConnection($dsn, $username, $password, $options) { - //TODO I'm thinking make it out by MysqlPool return new SwoolePDO($dsn, $username, $password, $options); } diff --git a/src/Task/SwooleTaskQueue.php b/src/Task/SwooleTaskQueue.php index 2cb76603..0a28fedf 100644 --- a/src/Task/SwooleTaskQueue.php +++ b/src/Task/SwooleTaskQueue.php @@ -2,11 +2,15 @@ namespace SwooleTW\Http\Task; + use Exception; -use Swoole\Timer; -use Illuminate\Queue\Queue; use Illuminate\Contracts\Queue\Queue as QueueContract; +use Illuminate\Queue\Queue; +use Swoole\Timer; +/** + * Class SwooleTaskQueue (5.7) + */ class SwooleTaskQueue extends Queue implements QueueContract { /** @@ -19,7 +23,7 @@ class SwooleTaskQueue extends Queue implements QueueContract /** * Create Async Task instance. * - * @param \Swoole\Http\Server $swoole + * @param \Swoole\Http\Server $swoole */ public function __construct($swoole) { @@ -29,9 +33,10 @@ public function __construct($swoole) /** * Push a new job onto the queue. * - * @param string|object $job - * @param mixed $data - * @param string $queue + * @param string|object $job + * @param mixed $data + * @param string $queue + * * @return mixed */ public function push($job, $data = '', $queue = null) @@ -42,24 +47,25 @@ public function push($job, $data = '', $queue = null) /** * Push a raw payload onto the queue. * - * @param string $payload - * @param string $queue - * @param array $options + * @param string $payload + * @param string $queue + * @param array $options + * * @return mixed */ public function pushRaw($payload, $queue = null, array $options = []) { - //wiki https://wiki.swoole.com/wiki/page/134.html, task($data,$dst_worker_id), $dst_worker_id should be default -1 - return $this->swoole->task($payload, (!is_numeric($queue) || $queue < 0) ? -1 : (int)$queue); + return $this->swoole->task($payload, !is_numeric($queue) ? 1 : (int)$queue); } /** * Push a new job onto the queue after a delay. * - * @param \DateTimeInterface|\DateInterval|int $delay - * @param string|object $job - * @param mixed $data - * @param string $queue + * @param \DateTimeInterface|\DateInterval|int $delay + * @param string|object $job + * @param mixed $data + * @param string $queue + * * @return mixed */ public function later($delay, $job, $data = '', $queue = null) @@ -72,12 +78,13 @@ public function later($delay, $job, $data = '', $queue = null) /** * Create a typical, string based queue payload array. * - * @param string $job - * @param mixed $data + * @param string $job + * @param string $queue + * @param mixed $data * - * @throws Expcetion + * @throws \Exception */ - protected function createStringPayload($job, $data) + protected function createStringPayload($job, $queue, $data) { throw new Exception('Unsupported empty data'); } @@ -85,7 +92,8 @@ protected function createStringPayload($job, $data) /** * Get the size of the queue. * - * @param string $queue + * @param string $queue + * * @return int */ public function size($queue = null) @@ -96,7 +104,8 @@ public function size($queue = null) /** * Pop the next job off of the queue. * - * @param string $queue + * @param string $queue + * * @return \Illuminate\Contracts\Queue\Job|null */ public function pop($queue = null) From 4346606b0568e64f0a5daa958b1fe0a0d4bb9870 Mon Sep 17 00:00:00 2001 From: Fractal Zombie Date: Thu, 20 Dec 2018 12:55:11 +0200 Subject: [PATCH 3/3] Fix code style for PR. --- src/Commands/HttpServerCommand.php | 39 +++++++++------- src/Concerns/InteractsWithSwooleTable.php | 3 +- src/Concerns/InteractsWithWebsocket.php | 15 +++---- src/Concerns/ResetApplication.php | 7 ++- src/Concerns/WithApplication.php | 11 ++--- src/Controllers/SocketIOController.php | 41 ++++++++++------- src/Coroutine/ConnectionException.php | 1 - src/Coroutine/Connectors/ConnectorFactory.php | 11 +++-- src/Coroutine/Connectors/MySqlConnector.php | 1 - src/Coroutine/Context.php | 1 - src/Coroutine/MySqlConnection.php | 6 ++- src/Coroutine/PDO.php | 18 ++++---- src/Coroutine/PDOStatement.php | 17 ++++--- src/Coroutine/StatementException.php | 1 - .../FrameworkNotSupportException.php | 1 - src/Exceptions/SandboxException.php | 1 - .../WebsocketNotSetInConfigException.php | 2 - src/Helpers/FW.php | 1 - src/Helpers/OS.php | 1 - src/Helpers/Service.php | 1 - src/HttpServiceProvider.php | 29 +++++++----- src/LaravelServiceProvider.php | 3 +- src/LumenServiceProvider.php | 5 +-- src/Server/Facades/Sandbox.php | 1 - src/Server/Facades/Server.php | 1 - src/Server/Manager.php | 30 +++++++++---- src/Server/Resetters/BindRequest.php | 1 - src/Server/Resetters/ClearInstances.php | 1 - .../Resetters/RebindKernelContainer.php | 1 - .../Resetters/RebindRouterContainer.php | 1 - src/Server/Resetters/RebindViewContainer.php | 1 - src/Server/Resetters/ResetConfig.php | 1 - src/Server/Resetters/ResetCookie.php | 1 - src/Server/Resetters/ResetProviders.php | 1 - src/Server/Resetters/ResetSession.php | 1 - src/Server/Resetters/ResetterContract.php | 1 - src/Server/Sandbox.php | 18 +++++--- src/Server/helpers.php | 6 +-- src/Table/Facades/SwooleTable.php | 1 - src/Table/SwooleTable.php | 1 - src/Task/Connectors/SwooleTaskConnector.php | 1 - src/Task/QueueFactory.php | 11 +++-- src/Task/SwooleTaskJob.php | 1 - src/Task/SwooleTaskQueue.php | 3 +- src/Transformers/Request.php | 19 ++++---- src/Transformers/Response.php | 22 ++++++---- src/Websocket/Authenticatable.php | 15 +++---- src/Websocket/Facades/Room.php | 1 - src/Websocket/Facades/Websocket.php | 1 - src/Websocket/HandlerContract.php | 1 - src/Websocket/Middleware/Authenticate.php | 1 - src/Websocket/Middleware/DecryptCookies.php | 1 - src/Websocket/Middleware/StartSession.php | 3 +- src/Websocket/Parser.php | 12 ++--- src/Websocket/Push.php | 6 +-- src/Websocket/Rooms/RedisRoom.php | 5 +-- src/Websocket/Rooms/RoomContract.php | 1 - src/Websocket/Rooms/TableRoom.php | 14 +++--- src/Websocket/SimpleParser.php | 11 ++--- src/Websocket/SocketIO/Packet.php | 3 +- src/Websocket/SocketIO/SocketIOParser.php | 5 +-- .../SocketIO/Strategies/HeartbeatStrategy.php | 1 - src/Websocket/SocketIO/WebsocketHandler.php | 21 ++++----- src/Websocket/Websocket.php | 44 ++++++++++--------- 64 files changed, 249 insertions(+), 238 deletions(-) diff --git a/src/Commands/HttpServerCommand.php b/src/Commands/HttpServerCommand.php index 30ab626d..1bbe7582 100644 --- a/src/Commands/HttpServerCommand.php +++ b/src/Commands/HttpServerCommand.php @@ -2,7 +2,6 @@ namespace SwooleTW\Http\Commands; - use Illuminate\Console\Command; use Illuminate\Support\Arr; use Swoole\Process; @@ -95,8 +94,10 @@ protected function start() $this->info('Starting swoole http server...'); $this->info("Swoole http server started: "); if ($this->isDaemon()) { - $this->info('> (You can run this command to ensure the ' . - 'swoole_http_server process is running: ps aux|grep "swoole")'); + $this->info( + '> (You can run this command to ensure the '. + 'swoole_http_server process is running: ps aux|grep "swoole")' + ); } $this->laravel->make('swoole.manager')->run(); @@ -109,7 +110,7 @@ protected function stop() { $pid = $this->getCurrentPid(); - if (!$this->isRunning($pid)) { + if (! $this->isRunning($pid)) { $this->error("Failed! There is no swoole_http_server process running."); return; @@ -153,7 +154,7 @@ protected function reload() { $pid = $this->getCurrentPid(); - if (!$this->isRunning($pid)) { + if (! $this->isRunning($pid)) { $this->error("Failed! There is no swoole_http_server process running."); return; @@ -163,7 +164,7 @@ protected function reload() $isRunning = $this->killProcess($pid, SIGUSR1); - if (!$isRunning) { + if (! $isRunning) { $this->error('> failure'); return; @@ -220,8 +221,10 @@ protected function initAction() { $this->action = $this->argument('action'); - if (!in_array($this->action, ['start', 'stop', 'restart', 'reload', 'infos'], true)) { - $this->error("Invalid argument '{$this->action}'. Expected 'start', 'stop', 'restart', 'reload' or 'infos'."); + if (! in_array($this->action, ['start', 'stop', 'restart', 'reload', 'infos'], true)) { + $this->error( + "Invalid argument '{$this->action}'. Expected 'start', 'stop', 'restart', 'reload' or 'infos'." + ); return; } @@ -236,7 +239,7 @@ protected function initAction() */ protected function isRunning($pid) { - if (!$pid) { + if (! $pid) { return false; } @@ -264,7 +267,7 @@ protected function killProcess($pid, $sig, $wait = 0) $start = time(); do { - if (!$this->isRunning($pid)) { + if (! $this->isRunning($pid)) { break; } @@ -330,14 +333,18 @@ protected function checkEnvironment() $this->error("Swoole extension doesn't support Windows OS yet."); return; - } else if (!extension_loaded('swoole')) { - $this->error("Can't detect Swoole extension installed."); + } else { + if (! extension_loaded('swoole')) { + $this->error("Can't detect Swoole extension installed."); - return; - } else if (!version_compare(swoole_version(), '4.0.0', 'ge')) { - $this->error("Your Swoole version must be higher than 4.0 to use coroutine."); + return; + } else { + if (! version_compare(swoole_version(), '4.0.0', 'ge')) { + $this->error("Your Swoole version must be higher than 4.0 to use coroutine."); - return; + return; + } + } } } } diff --git a/src/Concerns/InteractsWithSwooleTable.php b/src/Concerns/InteractsWithSwooleTable.php index aa9e1b17..eca5381f 100644 --- a/src/Concerns/InteractsWithSwooleTable.php +++ b/src/Concerns/InteractsWithSwooleTable.php @@ -2,7 +2,6 @@ namespace SwooleTW\Http\Concerns; - use Illuminate\Contracts\Console\Application as ConsoleApp; use Swoole\Table; use SwooleTW\Http\Table\SwooleTable; @@ -57,7 +56,7 @@ protected function registerTables() */ protected function bindSwooleTable() { - if (!$this->app instanceof ConsoleApp) { + if (! $this->app instanceof ConsoleApp) { $this->app->singleton(SwooleTable::class, function () { return $this->currentTable; }); diff --git a/src/Concerns/InteractsWithWebsocket.php b/src/Concerns/InteractsWithWebsocket.php index 66bff107..81aa724c 100644 --- a/src/Concerns/InteractsWithWebsocket.php +++ b/src/Concerns/InteractsWithWebsocket.php @@ -2,7 +2,6 @@ namespace SwooleTW\Http\Concerns; - use Illuminate\Contracts\Container\Container; use Illuminate\Pipeline\Pipeline; use Illuminate\Support\Arr; @@ -65,7 +64,7 @@ public function onOpen($swooleRequest) // enable sandbox $sandbox->enable(); // check if socket.io connection established - if (!$this->websocketHandler->onOpen($swooleRequest->fd, $illuminateRequest)) { + if (! $this->websocketHandler->onOpen($swooleRequest->fd, $illuminateRequest)) { return; } // trigger 'connect' websocket event @@ -129,7 +128,7 @@ public function onMessage($server, $frame) */ public function onClose($server, $fd, $reactorId) { - if (!$this->isServerWebsocket($fd) || !$server instanceof Websocket) { + if (! $this->isServerWebsocket($fd) || ! $server instanceof Websocket) { return; } @@ -162,7 +161,7 @@ public function pushMessage($server, array $data) $payload = $this->payloadParser->encode($push->getEvent(), $push->getMessage()); // attach sender if not broadcast - if (!$push->isBroadcast() && $push->getSender() && !$push->hasOwnDescriptor()) { + if (! $push->isBroadcast() && $push->getSender() && ! $push->hasOwnDescriptor()) { $push->addDescriptor($push->getSender()); } @@ -173,7 +172,7 @@ public function pushMessage($server, array $data) // push message to designated fds foreach ($push->getDescriptors() as $descriptor) { - if ($server->exist($descriptor) || !$push->isBroadcastToDescriptor((int)$descriptor)) { + if ($server->exist($descriptor) || ! $push->isBroadcastToDescriptor((int)$descriptor)) { $server->push($descriptor, $payload, $push->getOpcode()); } } @@ -256,7 +255,7 @@ protected function prepareWebsocketHandler() { $handlerClass = $this->container->make(Service::CONFIG_ALIAS)->get('swoole_websocket.handler'); - if (!$handlerClass) { + if (! $handlerClass) { throw new WebsocketNotSetInConfigException; } @@ -334,8 +333,8 @@ protected function loadWebsocketRoutes() { $routePath = $this->container->make(Service::CONFIG_ALIAS)->get('swoole_websocket.route_file'); - if (!file_exists($routePath)) { - $routePath = __DIR__ . '/../../routes/websocket.php'; + if (! file_exists($routePath)) { + $routePath = __DIR__.'/../../routes/websocket.php'; } return require $routePath; diff --git a/src/Concerns/ResetApplication.php b/src/Concerns/ResetApplication.php index 4e611a3e..a6c96c01 100644 --- a/src/Concerns/ResetApplication.php +++ b/src/Concerns/ResetApplication.php @@ -2,7 +2,6 @@ namespace SwooleTW\Http\Concerns; - use Illuminate\Contracts\Container\Container; use SwooleTW\Http\Exceptions\SandboxException; use SwooleTW\Http\Server\Resetters\ResetterContract; @@ -49,7 +48,7 @@ protected function setInitialProviders() $providers = $this->config->get('swoole_http.providers', []); foreach ($providers as $provider) { - if (class_exists($provider) && !in_array($provider, $this->providers)) { + if (class_exists($provider) && ! in_array($provider, $this->providers)) { $providerClass = new $provider($app); $this->providers[$provider] = $providerClass; } @@ -74,8 +73,8 @@ protected function setInitialResetters() foreach ($resetters as $resetter) { $resetterClass = $app->make($resetter); - if (!$resetterClass instanceof ResetterContract) { - throw new SandboxException("{$resetter} must implement " . ResetterContract::class); + if (! $resetterClass instanceof ResetterContract) { + throw new SandboxException("{$resetter} must implement ".ResetterContract::class); } $this->resetters[$resetter] = $resetterClass; } diff --git a/src/Concerns/WithApplication.php b/src/Concerns/WithApplication.php index 46053cbf..8aa54ec4 100644 --- a/src/Concerns/WithApplication.php +++ b/src/Concerns/WithApplication.php @@ -2,7 +2,6 @@ namespace SwooleTW\Http\Concerns; - use Illuminate\Contracts\Container\Container; use Illuminate\Contracts\Http\Kernel; use Illuminate\Support\Facades\Facade; @@ -34,8 +33,10 @@ protected function bootstrap() if ($this->framework === 'laravel') { $bootstrappers = $this->getBootstrappers(); $this->app->bootstrapWith($bootstrappers); - } else if (is_null(Facade::getFacadeApplication())) { - $this->app->withFacades(); + } else { + if (is_null(Facade::getFacadeApplication())) { + $this->app->withFacades(); + } } $this->preResolveInstances(); @@ -57,7 +58,7 @@ protected function loadApplication() */ public function getApplication() { - if (!$this->app instanceof Container) { + if (! $this->app instanceof Container) { $this->app = $this->loadApplication(); $this->bootstrap(); } @@ -108,7 +109,7 @@ protected function setFramework($framework) { $framework = strtolower($framework); - if (!in_array($framework, ['laravel', 'lumen'])) { + if (! in_array($framework, ['laravel', 'lumen'])) { throw new FrameworkNotSupportException($framework); } diff --git a/src/Controllers/SocketIOController.php b/src/Controllers/SocketIOController.php index 48819983..321aed94 100644 --- a/src/Controllers/SocketIOController.php +++ b/src/Controllers/SocketIOController.php @@ -2,7 +2,6 @@ namespace SwooleTW\Http\Controllers; - use Illuminate\Http\Request; use Illuminate\Support\Facades\Config; @@ -12,32 +11,40 @@ class SocketIOController public function upgrade(Request $request) { - if (!in_array($request->input('transport'), $this->transports)) { - return response()->json([ - 'code' => 0, - 'message' => 'Transport unknown', - ], 400); + if (! in_array($request->input('transport'), $this->transports)) { + return response()->json( + [ + 'code' => 0, + 'message' => 'Transport unknown', + ], + 400 + ); } if ($request->has('sid')) { return '1:6'; } - $payload = json_encode([ - 'sid' => base64_encode(uniqid()), - 'upgrades' => ['websocket'], - 'pingInterval' => Config::get('swoole_websocket.ping_interval'), - 'pingTimeout' => Config::get('swoole_websocket.ping_timeout'), - ]); + $payload = json_encode( + [ + 'sid' => base64_encode(uniqid()), + 'upgrades' => ['websocket'], + 'pingInterval' => Config::get('swoole_websocket.ping_interval'), + 'pingTimeout' => Config::get('swoole_websocket.ping_timeout'), + ] + ); - return '97:0' . $payload . '2:40'; + return '97:0'.$payload.'2:40'; } public function reject() { - return response()->json([ - 'code' => 3, - 'message' => 'Bad request', - ], 400); + return response()->json( + [ + 'code' => 3, + 'message' => 'Bad request', + ], + 400 + ); } } diff --git a/src/Coroutine/ConnectionException.php b/src/Coroutine/ConnectionException.php index 1698f80b..f5ae28c0 100644 --- a/src/Coroutine/ConnectionException.php +++ b/src/Coroutine/ConnectionException.php @@ -2,7 +2,6 @@ namespace SwooleTW\Http\Coroutine; - class ConnectionException extends \Exception { // diff --git a/src/Coroutine/Connectors/ConnectorFactory.php b/src/Coroutine/Connectors/ConnectorFactory.php index 37dcb51a..32f6e437 100644 --- a/src/Coroutine/Connectors/ConnectorFactory.php +++ b/src/Coroutine/Connectors/ConnectorFactory.php @@ -2,7 +2,6 @@ namespace SwooleTW\Http\Coroutine\Connectors; - use Illuminate\Support\Arr; use SwooleTW\Http\Helpers\FW; @@ -30,7 +29,7 @@ class ConnectorFactory * * @const string */ - public const CONNECTOR_CLASS_PATH = __DIR__ . '/MySqlConnector.php'; + public const CONNECTOR_CLASS_PATH = __DIR__.'/MySqlConnector.php'; /** * @param string $version @@ -40,7 +39,7 @@ class ConnectorFactory public static function make(string $version): MySqlConnector { $isMatch = static::isFileVersionMatch($version); - $class = static::copy(static::stub($version), !$isMatch); + $class = static::copy(static::stub($version), ! $isMatch); return new $class(); } @@ -53,8 +52,8 @@ public static function make(string $version): MySqlConnector public static function stub(string $version): string { return static::hasBreakingChanges($version) - ? __DIR__ . '/../../../stubs/5.6/MySqlConnector.stub' - : __DIR__ . '/../../../stubs/5.5/MySqlConnector.stub'; + ? __DIR__.'/../../../stubs/5.6/MySqlConnector.stub' + : __DIR__.'/../../../stubs/5.5/MySqlConnector.stub'; } /** @@ -65,7 +64,7 @@ public static function stub(string $version): string */ public static function copy(string $stub, bool $rewrite = false): string { - if (!file_exists(static::CONNECTOR_CLASS_PATH) || $rewrite) { + if (! file_exists(static::CONNECTOR_CLASS_PATH) || $rewrite) { copy($stub, static::CONNECTOR_CLASS_PATH); } diff --git a/src/Coroutine/Connectors/MySqlConnector.php b/src/Coroutine/Connectors/MySqlConnector.php index 7082d761..2efa720a 100644 --- a/src/Coroutine/Connectors/MySqlConnector.php +++ b/src/Coroutine/Connectors/MySqlConnector.php @@ -2,7 +2,6 @@ namespace SwooleTW\Http\Coroutine\Connectors; - use Illuminate\Database\Connectors\MySqlConnector as BaseConnector; use Illuminate\Support\Str; use SwooleTW\Http\Coroutine\PDO as SwoolePDO; diff --git a/src/Coroutine/Context.php b/src/Coroutine/Context.php index 9f118229..2ea8a20c 100644 --- a/src/Coroutine/Context.php +++ b/src/Coroutine/Context.php @@ -2,7 +2,6 @@ namespace SwooleTW\Http\Coroutine; - use Illuminate\Contracts\Container\Container; use Swoole\Coroutine; diff --git a/src/Coroutine/MySqlConnection.php b/src/Coroutine/MySqlConnection.php index 27e972b5..631ad6bb 100644 --- a/src/Coroutine/MySqlConnection.php +++ b/src/Coroutine/MySqlConnection.php @@ -2,7 +2,6 @@ namespace SwooleTW\Http\Coroutine; - use Closure; use Illuminate\Database\MySqlConnection as BaseConnection; use Illuminate\Database\QueryException; @@ -25,7 +24,10 @@ class MySqlConnection extends BaseConnection protected function tryAgainIfCausedByLostConnection(QueryException $e, $query, $bindings, Closure $callback) { // https://github.com/swoole/swoole-src/blob/a414e5e8fec580abb3dbd772d483e12976da708f/swoole_mysql_coro.c#L1140 - if ($this->causedByLostConnection($e->getPrevious()) || Str::contains($e->getMessage(), ['is closed', 'is not established'])) { + if ($this->causedByLostConnection($e->getPrevious()) || Str::contains( + $e->getMessage(), + ['is closed', 'is not established'] + )) { $this->reconnect(); return $this->runQueryCallback($query, $bindings, $callback); diff --git a/src/Coroutine/PDO.php b/src/Coroutine/PDO.php index c79e2af9..54e44972 100644 --- a/src/Coroutine/PDO.php +++ b/src/Coroutine/PDO.php @@ -9,7 +9,6 @@ namespace SwooleTW\Http\Coroutine; - use Exception; use Illuminate\Database\QueryException; use Illuminate\Support\Arr; @@ -75,7 +74,7 @@ protected function connect(array $options = []) { $this->client->connect($options); - if (!$this->client->connected) { + if (! $this->client->connected) { $message = $this->client->connect_error ?: $this->client->error; $errorCode = $this->client->connect_errno ?: $this->client->errno; @@ -131,7 +130,7 @@ protected function getOptions($dsn, $username, $password, $driverOptions) */ public static function checkDriver(string $driver) { - if (!in_array($driver, static::getAvailableDrivers())) { + if (! in_array($driver, static::getAvailableDrivers())) { throw new \InvalidArgumentException("{$driver} driver is not supported yet."); } } @@ -253,13 +252,11 @@ public function prepare($statement, $options = null) if (strpos($statement, ':') !== false) { $i = 0; $bindKeyMap = []; - $statement = preg_replace_callback( - '/:([a-zA-Z_]\w*?)\b/', - function ($matches) use (&$i, &$bindKeyMap) { - $bindKeyMap[$matches[1]] = $i++; + $statement = preg_replace_callback('/:([a-zA-Z_]\w*?)\b/', function ($matches) use (&$i, &$bindKeyMap) { + $bindKeyMap[$matches[1]] = $i++; - return '?'; - }, $statement); + return '?'; + }, $statement); } $stmtObj = $this->client->prepare($statement); @@ -312,7 +309,8 @@ public function getAttribute($attribute) */ public function quote($string, $paramtype = null) { - throw new \BadMethodCallException(<<resultSet = ($ok = $result !== false) ? $result : []; $this->afterExecute(); - if ($result === false){ + if ($result === false) { throw new \PDOException($this->errorInfo(), $this->errorCode()); } @@ -172,7 +178,7 @@ private function transStyle( break; case PDO::FETCH_OBJ: foreach ($rawData as $row) { - $resultSet[] = (object) $row; + $resultSet[] = (object)$row; } break; case PDO::FETCH_NUM: @@ -197,7 +203,7 @@ public function fetch( $this->__executeWhenStringQueryEmpty(); $cursorOrientation = is_null($cursorOrientation) ? PDO::FETCH_ORI_NEXT : $cursorOrientation; - $cursorOffset = is_null($cursorOffset) ? 0 : (int) $cursorOffset; + $cursorOffset = is_null($cursorOffset) ? 0 : (int)$cursorOffset; switch ($cursorOrientation) { case PDO::FETCH_ORI_ABS: @@ -238,6 +244,7 @@ public function fetchColumn($columnNumber = null) { $columnNumber = is_null($columnNumber) ? 0 : $columnNumber; $this->__executeWhenStringQueryEmpty(); + return $this->fetch(PDO::FETCH_COLUMN, PDO::FETCH_ORI_NEXT, 0, $columnNumber); } diff --git a/src/Coroutine/StatementException.php b/src/Coroutine/StatementException.php index 9259bcbd..ca839e08 100644 --- a/src/Coroutine/StatementException.php +++ b/src/Coroutine/StatementException.php @@ -2,7 +2,6 @@ namespace SwooleTW\Http\Coroutine; - class StatementException extends \Exception { // diff --git a/src/Exceptions/FrameworkNotSupportException.php b/src/Exceptions/FrameworkNotSupportException.php index 90401358..f393279c 100644 --- a/src/Exceptions/FrameworkNotSupportException.php +++ b/src/Exceptions/FrameworkNotSupportException.php @@ -2,7 +2,6 @@ namespace SwooleTW\Http\Exceptions; - /** * Class FrameworkNotSupportException */ diff --git a/src/Exceptions/SandboxException.php b/src/Exceptions/SandboxException.php index 1626ebd0..9a124ef3 100644 --- a/src/Exceptions/SandboxException.php +++ b/src/Exceptions/SandboxException.php @@ -2,7 +2,6 @@ namespace SwooleTW\Http\Exceptions; - use Exception; class SandboxException extends Exception diff --git a/src/Exceptions/WebsocketNotSetInConfigException.php b/src/Exceptions/WebsocketNotSetInConfigException.php index 3d5f21d5..b5285d63 100644 --- a/src/Exceptions/WebsocketNotSetInConfigException.php +++ b/src/Exceptions/WebsocketNotSetInConfigException.php @@ -2,9 +2,7 @@ namespace SwooleTW\Http\Exceptions; - use Exception; -use Throwable; class WebsocketNotSetInConfigException extends Exception { diff --git a/src/Helpers/FW.php b/src/Helpers/FW.php index d85ed4b8..238f7ec5 100644 --- a/src/Helpers/FW.php +++ b/src/Helpers/FW.php @@ -2,7 +2,6 @@ namespace SwooleTW\Http\Helpers; - use Illuminate\Support\Arr; use LogicException; diff --git a/src/Helpers/OS.php b/src/Helpers/OS.php index 1104473b..8f33cde7 100644 --- a/src/Helpers/OS.php +++ b/src/Helpers/OS.php @@ -2,7 +2,6 @@ namespace SwooleTW\Http\Helpers; - use Illuminate\Support\Str; /** diff --git a/src/Helpers/Service.php b/src/Helpers/Service.php index 06505638..5fa972e6 100644 --- a/src/Helpers/Service.php +++ b/src/Helpers/Service.php @@ -2,7 +2,6 @@ namespace SwooleTW\Http\Helpers; - /** * Class Service */ diff --git a/src/HttpServiceProvider.php b/src/HttpServiceProvider.php index cb9f82b6..071291ca 100644 --- a/src/HttpServiceProvider.php +++ b/src/HttpServiceProvider.php @@ -2,7 +2,6 @@ namespace SwooleTW\Http; - use Illuminate\Queue\Capsule\Manager; use Illuminate\Support\ServiceProvider; use Swoole\Http\Server as HttpServer; @@ -74,11 +73,14 @@ abstract protected function bootRoutes(); */ public function boot() { - $this->publishes([ - __DIR__ . '/../config/swoole_http.php' => base_path('config/swoole_http.php'), - __DIR__ . '/../config/swoole_websocket.php' => base_path('config/swoole_websocket.php'), - __DIR__ . '/../routes/websocket.php' => base_path('routes/websocket.php'), - ], 'laravel-swoole'); + $this->publishes( + [ + __DIR__.'/../config/swoole_http.php' => base_path('config/swoole_http.php'), + __DIR__.'/../config/swoole_websocket.php' => base_path('config/swoole_websocket.php'), + __DIR__.'/../routes/websocket.php' => base_path('routes/websocket.php'), + ], + 'laravel-swoole' + ); if ($this->app->make(Service::CONFIG_ALIAS)->get('swoole_http.websocket.enabled')) { $this->bootRoutes(); @@ -90,8 +92,8 @@ public function boot() */ protected function mergeConfigs() { - $this->mergeConfigFrom(__DIR__ . '/../config/swoole_http.php', 'swoole_http'); - $this->mergeConfigFrom(__DIR__ . '/../config/swoole_websocket.php', 'swoole_websocket'); + $this->mergeConfigFrom(__DIR__.'/../config/swoole_http.php', 'swoole_http'); + $this->mergeConfigFrom(__DIR__.'/../config/swoole_websocket.php', 'swoole_websocket'); } /** @@ -107,9 +109,11 @@ protected function setIsWebsocket() */ protected function registerCommands() { - $this->commands([ - HttpServerCommand::class, - ]); + $this->commands( + [ + HttpServerCommand::class, + ] + ); } /** @@ -136,7 +140,7 @@ protected function configureSwooleServer() $options = $config->get('swoole_http.server.options'); // only enable task worker in websocket mode and for queue driver - if ($config->get('queue.default') !== 'swoole' && !$this->isWebsocket) { + if ($config->get('queue.default') !== 'swoole' && ! $this->isWebsocket) { unset($config['task_worker_num']); } @@ -158,6 +162,7 @@ protected function registerServer() return static::$server; }); + $this->app->alias(Server::class, Service::SERVER_ALIAS); } diff --git a/src/LaravelServiceProvider.php b/src/LaravelServiceProvider.php index fe35a3ce..5cf86a30 100644 --- a/src/LaravelServiceProvider.php +++ b/src/LaravelServiceProvider.php @@ -2,7 +2,6 @@ namespace SwooleTW\Http; - use SwooleTW\Http\Server\Manager; /** @@ -29,6 +28,6 @@ protected function registerManager() */ protected function bootRoutes() { - require __DIR__ . '/../routes/laravel_routes.php'; + require __DIR__.'/../routes/laravel_routes.php'; } } diff --git a/src/LumenServiceProvider.php b/src/LumenServiceProvider.php index 8e1bdfa9..40f218b4 100644 --- a/src/LumenServiceProvider.php +++ b/src/LumenServiceProvider.php @@ -2,7 +2,6 @@ namespace SwooleTW\Http; - use SwooleTW\Http\Server\Manager; /** @@ -33,11 +32,11 @@ protected function bootRoutes() if (property_exists($app, 'router')) { $app->router->group(['namespace' => 'SwooleTW\Http\Controllers'], function ($app) { - require __DIR__ . '/../routes/lumen_routes.php'; + require __DIR__.'/../routes/lumen_routes.php'; }); } else { $app->group(['namespace' => 'App\Http\Controllers'], function ($app) { - require __DIR__ . '/../routes/lumen_routes.php'; + require __DIR__.'/../routes/lumen_routes.php'; }); } } diff --git a/src/Server/Facades/Sandbox.php b/src/Server/Facades/Sandbox.php index 6375ecbb..8c468254 100644 --- a/src/Server/Facades/Sandbox.php +++ b/src/Server/Facades/Sandbox.php @@ -2,7 +2,6 @@ namespace SwooleTW\Http\Server\Facades; - use Illuminate\Support\Facades\Facade; class Sandbox extends Facade diff --git a/src/Server/Facades/Server.php b/src/Server/Facades/Server.php index 8fc3e2b3..7a34102a 100644 --- a/src/Server/Facades/Server.php +++ b/src/Server/Facades/Server.php @@ -2,7 +2,6 @@ namespace SwooleTW\Http\Server\Facades; - use Illuminate\Support\Facades\Facade; class Server extends Facade diff --git a/src/Server/Manager.php b/src/Server/Manager.php index 695362b6..3eb47bb1 100644 --- a/src/Server/Manager.php +++ b/src/Server/Manager.php @@ -2,7 +2,6 @@ namespace SwooleTW\Http\Server; - use Exception; use Illuminate\Contracts\Container\Container; use Illuminate\Contracts\Debug\ExceptionHandler; @@ -51,9 +50,20 @@ class Manager * @var array */ protected $events = [ - 'start', 'shutDown', 'workerStart', 'workerStop', 'packet', - 'bufferFull', 'bufferEmpty', 'task', 'finish', 'pipeMessage', - 'workerError', 'managerStart', 'managerStop', 'request', + 'start', + 'shutDown', + 'workerStart', + 'workerStop', + 'packet', + 'bufferFull', + 'bufferEmpty', + 'task', + 'finish', + 'pipeMessage', + 'workerError', + 'managerStart', + 'managerStop', + 'request', ]; /** @@ -250,11 +260,13 @@ public function onTask($server, $taskId, $srcWorkerId, $data) $this->pushMessage($server, $data['data'] ?? []); } // push async task to queue - } else if (is_string($data)) { - $decoded = \json_decode($data, true); + } else { + if (is_string($data)) { + $decoded = \json_decode($data, true); - if (JSON_ERROR_NONE === \json_last_error() && isset($decoded['job'])) { - (new SwooleTaskJob($this->container, $server, $data, $taskId, $srcWorkerId))->fire(); + if (JSON_ERROR_NONE === \json_last_error() && isset($decoded['job'])) { + (new SwooleTaskJob($this->container, $server, $data, $taskId, $srcWorkerId))->fire(); + } } } } catch (Throwable $e) { @@ -396,7 +408,7 @@ protected function isInTesting() */ public function logServerError(Throwable $e) { - if (!$e instanceof Exception) { + if (! $e instanceof Exception) { $e = new FatalThrowableError($e); } diff --git a/src/Server/Resetters/BindRequest.php b/src/Server/Resetters/BindRequest.php index 610329c9..b0787829 100644 --- a/src/Server/Resetters/BindRequest.php +++ b/src/Server/Resetters/BindRequest.php @@ -2,7 +2,6 @@ namespace SwooleTW\Http\Server\Resetters; - use Illuminate\Contracts\Container\Container; use Illuminate\Http\Request; use SwooleTW\Http\Server\Sandbox; diff --git a/src/Server/Resetters/ClearInstances.php b/src/Server/Resetters/ClearInstances.php index 9d0d446c..865516f1 100644 --- a/src/Server/Resetters/ClearInstances.php +++ b/src/Server/Resetters/ClearInstances.php @@ -2,7 +2,6 @@ namespace SwooleTW\Http\Server\Resetters; - use Illuminate\Contracts\Container\Container; use SwooleTW\Http\Server\Sandbox; diff --git a/src/Server/Resetters/RebindKernelContainer.php b/src/Server/Resetters/RebindKernelContainer.php index 7a8187be..f2d8b9b4 100644 --- a/src/Server/Resetters/RebindKernelContainer.php +++ b/src/Server/Resetters/RebindKernelContainer.php @@ -2,7 +2,6 @@ namespace SwooleTW\Http\Server\Resetters; - use Illuminate\Contracts\Container\Container; use Illuminate\Contracts\Http\Kernel; use SwooleTW\Http\Server\Sandbox; diff --git a/src/Server/Resetters/RebindRouterContainer.php b/src/Server/Resetters/RebindRouterContainer.php index ca6151ed..15274195 100644 --- a/src/Server/Resetters/RebindRouterContainer.php +++ b/src/Server/Resetters/RebindRouterContainer.php @@ -2,7 +2,6 @@ namespace SwooleTW\Http\Server\Resetters; - use Illuminate\Contracts\Container\Container; use SwooleTW\Http\Server\Sandbox; use Symfony\Component\HttpKernel\Exception\NotFoundHttpException; diff --git a/src/Server/Resetters/RebindViewContainer.php b/src/Server/Resetters/RebindViewContainer.php index 3f1cb57f..525f9daa 100644 --- a/src/Server/Resetters/RebindViewContainer.php +++ b/src/Server/Resetters/RebindViewContainer.php @@ -2,7 +2,6 @@ namespace SwooleTW\Http\Server\Resetters; - use Illuminate\Contracts\Container\Container; use SwooleTW\Http\Server\Sandbox; diff --git a/src/Server/Resetters/ResetConfig.php b/src/Server/Resetters/ResetConfig.php index 4a0356c8..24cea3aa 100644 --- a/src/Server/Resetters/ResetConfig.php +++ b/src/Server/Resetters/ResetConfig.php @@ -2,7 +2,6 @@ namespace SwooleTW\Http\Server\Resetters; - use Illuminate\Contracts\Container\Container; use SwooleTW\Http\Server\Sandbox; diff --git a/src/Server/Resetters/ResetCookie.php b/src/Server/Resetters/ResetCookie.php index 2d89cf44..85da6cba 100644 --- a/src/Server/Resetters/ResetCookie.php +++ b/src/Server/Resetters/ResetCookie.php @@ -2,7 +2,6 @@ namespace SwooleTW\Http\Server\Resetters; - use Illuminate\Contracts\Container\Container; use SwooleTW\Http\Server\Sandbox; diff --git a/src/Server/Resetters/ResetProviders.php b/src/Server/Resetters/ResetProviders.php index f232f9d8..0193106b 100644 --- a/src/Server/Resetters/ResetProviders.php +++ b/src/Server/Resetters/ResetProviders.php @@ -2,7 +2,6 @@ namespace SwooleTW\Http\Server\Resetters; - use Illuminate\Contracts\Container\Container; use SwooleTW\Http\Server\Sandbox; diff --git a/src/Server/Resetters/ResetSession.php b/src/Server/Resetters/ResetSession.php index 3848d55d..9a97ac53 100644 --- a/src/Server/Resetters/ResetSession.php +++ b/src/Server/Resetters/ResetSession.php @@ -2,7 +2,6 @@ namespace SwooleTW\Http\Server\Resetters; - use Illuminate\Contracts\Container\Container; use SwooleTW\Http\Server\Sandbox; diff --git a/src/Server/Resetters/ResetterContract.php b/src/Server/Resetters/ResetterContract.php index e6398751..27a5d85c 100644 --- a/src/Server/Resetters/ResetterContract.php +++ b/src/Server/Resetters/ResetterContract.php @@ -2,7 +2,6 @@ namespace SwooleTW\Http\Server\Resetters; - use Illuminate\Contracts\Container\Container; use SwooleTW\Http\Server\Sandbox; diff --git a/src/Server/Sandbox.php b/src/Server/Sandbox.php index 1ab2041b..ccf0f74c 100644 --- a/src/Server/Sandbox.php +++ b/src/Server/Sandbox.php @@ -2,18 +2,18 @@ namespace SwooleTW\Http\Server; -use Illuminate\Http\Request; use Illuminate\Container\Container; -use SwooleTW\Http\Coroutine\Context; +use Illuminate\Contracts\Config\Repository as ConfigContract; use Illuminate\Contracts\Http\Kernel; +use Illuminate\Http\Request; use Illuminate\Support\Facades\Facade; +use Laravel\Lumen\Application as LumenApplication; use SwooleTW\Http\Concerns\ResetApplication; +use SwooleTW\Http\Coroutine\Context; use SwooleTW\Http\Exceptions\SandboxException; -use Laravel\Lumen\Application as LumenApplication; -use Symfony\Component\HttpFoundation\StreamedResponse; use Symfony\Component\HttpFoundation\BinaryFileResponse; -use Illuminate\Contracts\Config\Repository as ConfigContract; use Symfony\Component\HttpFoundation\Response as SymfonyResponse; +use Symfony\Component\HttpFoundation\StreamedResponse; class Sandbox { @@ -145,6 +145,7 @@ public function getApplication() * Run framework. * * @param \Illuminate\Http\Request $request + * * @return \Illuminate\Http\Response */ public function run(Request $request) @@ -166,6 +167,7 @@ public function run(Request $request) * Handle request for non-ob case. * * @param \Illuminate\Http\Request $request + * * @return \Illuminate\Http\Response */ protected function prepareResponse(Request $request) @@ -183,6 +185,7 @@ protected function prepareResponse(Request $request) * Handle request for ob output. * * @param \Illuminate\Http\Request $request + * * @return \Illuminate\Http\Response */ protected function prepareObResponse(Request $request) @@ -200,7 +203,7 @@ protected function prepareObResponse(Request $request) } elseif ($response instanceof SymfonyResponse) { $content = $response->getContent(); } elseif (! $isFile = $response instanceof BinaryFileResponse) { - $content = (string) $response; + $content = (string)$response; } // process terminating logics @@ -211,7 +214,7 @@ protected function prepareObResponse(Request $request) if ($isStream) { $response->output = ob_get_contents(); } else { - $response->setContent(ob_get_contents() . $content); + $response->setContent(ob_get_contents().$content); } } @@ -224,6 +227,7 @@ protected function prepareObResponse(Request $request) * Handle request through Laravel or Lumen. * * @param \Illuminate\Http\Request $request + * * @return \Illuminate\Http\Response */ protected function handleRequest(Request $request) diff --git a/src/Server/helpers.php b/src/Server/helpers.php index 624043bc..51dd9fcb 100644 --- a/src/Server/helpers.php +++ b/src/Server/helpers.php @@ -3,7 +3,7 @@ /** * This is only for `function not exists` in config/swoole_http.php. */ -if (!function_exists('swoole_cpu_num')) { +if (! function_exists('swoole_cpu_num')) { function swoole_cpu_num(): int { return 1; @@ -13,10 +13,10 @@ function swoole_cpu_num(): int /** * This is only for `function not exists` in config/swoole_http.php. */ -if (!defined('SWOOLE_SOCK_TCP')) { +if (! defined('SWOOLE_SOCK_TCP')) { define('SWOOLE_SOCK_TCP', 1); } -if (!defined('SWOOLE_PROCESS')) { +if (! defined('SWOOLE_PROCESS')) { define('SWOOLE_PROCESS', 3); } diff --git a/src/Table/Facades/SwooleTable.php b/src/Table/Facades/SwooleTable.php index fb89a85b..e9f9de11 100644 --- a/src/Table/Facades/SwooleTable.php +++ b/src/Table/Facades/SwooleTable.php @@ -2,7 +2,6 @@ namespace SwooleTW\Http\Table\Facades; - use Illuminate\Support\Facades\Facade; /** diff --git a/src/Table/SwooleTable.php b/src/Table/SwooleTable.php index be046f30..3c154775 100644 --- a/src/Table/SwooleTable.php +++ b/src/Table/SwooleTable.php @@ -2,7 +2,6 @@ namespace SwooleTW\Http\Table; - use Swoole\Table; class SwooleTable diff --git a/src/Task/Connectors/SwooleTaskConnector.php b/src/Task/Connectors/SwooleTaskConnector.php index 0ab71f3a..6e3c0664 100644 --- a/src/Task/Connectors/SwooleTaskConnector.php +++ b/src/Task/Connectors/SwooleTaskConnector.php @@ -2,7 +2,6 @@ namespace SwooleTW\Http\Task\Connectors; - use Illuminate\Queue\Connectors\ConnectorInterface; use SwooleTW\Http\Helpers\FW; use SwooleTW\Http\Task\QueueFactory; diff --git a/src/Task/QueueFactory.php b/src/Task/QueueFactory.php index a9d8bb9a..72cdee8c 100644 --- a/src/Task/QueueFactory.php +++ b/src/Task/QueueFactory.php @@ -2,7 +2,6 @@ namespace SwooleTW\Http\Task; - use Illuminate\Contracts\Queue\Queue; use Illuminate\Support\Arr; use SwooleTW\Http\Helpers\FW; @@ -31,7 +30,7 @@ class QueueFactory * * @const string */ - public const QUEUE_CLASS_PATH = __DIR__ . '/SwooleTaskQueue.php'; + public const QUEUE_CLASS_PATH = __DIR__.'/SwooleTaskQueue.php'; /** * @param \Swoole\Http\Server $server @@ -42,7 +41,7 @@ class QueueFactory public static function make($server, string $version): Queue { $isMatch = static::isFileVersionMatch($version); - $class = static::copy(static::stub($version), !$isMatch); + $class = static::copy(static::stub($version), ! $isMatch); return new $class($server); } @@ -55,8 +54,8 @@ public static function make($server, string $version): Queue public static function stub(string $version): string { return static::hasBreakingChanges($version) - ? __DIR__ . '/../../stubs/5.7/SwooleTaskQueue.stub' - : __DIR__ . '/../../stubs/5.6/SwooleTaskQueue.stub'; + ? __DIR__.'/../../stubs/5.7/SwooleTaskQueue.stub' + : __DIR__.'/../../stubs/5.6/SwooleTaskQueue.stub'; } /** @@ -67,7 +66,7 @@ public static function stub(string $version): string */ public static function copy(string $stub, bool $rewrite = false): string { - if (!file_exists(static::QUEUE_CLASS_PATH) || $rewrite) { + if (! file_exists(static::QUEUE_CLASS_PATH) || $rewrite) { copy($stub, static::QUEUE_CLASS_PATH); } diff --git a/src/Task/SwooleTaskJob.php b/src/Task/SwooleTaskJob.php index 701c2b55..526c8e03 100644 --- a/src/Task/SwooleTaskJob.php +++ b/src/Task/SwooleTaskJob.php @@ -2,7 +2,6 @@ namespace SwooleTW\Http\Task; - use Illuminate\Contracts\Container\Container; use Illuminate\Contracts\Queue\Job as JobContract; use Illuminate\Queue\Jobs\Job; diff --git a/src/Task/SwooleTaskQueue.php b/src/Task/SwooleTaskQueue.php index 0a28fedf..760b9345 100644 --- a/src/Task/SwooleTaskQueue.php +++ b/src/Task/SwooleTaskQueue.php @@ -2,7 +2,6 @@ namespace SwooleTW\Http\Task; - use Exception; use Illuminate\Contracts\Queue\Queue as QueueContract; use Illuminate\Queue\Queue; @@ -55,7 +54,7 @@ public function push($job, $data = '', $queue = null) */ public function pushRaw($payload, $queue = null, array $options = []) { - return $this->swoole->task($payload, !is_numeric($queue) ? 1 : (int)$queue); + return $this->swoole->task($payload, ! is_numeric($queue) ? 1 : (int)$queue); } /** diff --git a/src/Transformers/Request.php b/src/Transformers/Request.php index c5777f2a..2b48c6e1 100644 --- a/src/Transformers/Request.php +++ b/src/Transformers/Request.php @@ -2,7 +2,6 @@ namespace SwooleTW\Http\Transformers; - use Illuminate\Http\Request as IlluminateRequest; use Swoole\Http\Request as SwooleRequest; use Symfony\Component\HttpFoundation\ParameterBag; @@ -29,7 +28,9 @@ class Request */ public static function make(SwooleRequest $swooleRequest) { - list($get, $post, $cookie, $files, $server, $content) + list( + $get, $post, $cookie, $files, $server, $content + ) = static::toIlluminateParameters($swooleRequest); return new static($get, $post, $cookie, $files, $server, $content); @@ -158,8 +159,8 @@ protected static function transformServerParameters(array $server, array $header $key = str_replace('-', '_', $key); $key = strtoupper($key); - if (!in_array($key, ['REMOTE_ADDR', 'SERVER_PORT', 'HTTPS'])) { - $key = 'HTTP_' . $key; + if (! in_array($key, ['REMOTE_ADDR', 'SERVER_PORT', 'HTTPS'])) { + $key = 'HTTP_'.$key; } $__SERVER[$key] = $value; @@ -185,8 +186,8 @@ public static function handleStatic($swooleRequest, $swooleResponse, string $pub return null; } - $filename = $publicPath . $uri; - if (!is_file($filename) || filesize($filename) === 0) { + $filename = $publicPath.$uri; + if (! is_file($filename) || filesize($filename) === 0) { return null; } @@ -194,8 +195,10 @@ public static function handleStatic($swooleRequest, $swooleResponse, string $pub $mime = mime_content_type($filename); if ($extension === 'js') { $mime = 'text/javascript'; - } else if ($extension === 'css') { - $mime = 'text/css'; + } else { + if ($extension === 'css') { + $mime = 'text/css'; + } } $swooleResponse->header('Content-Type', $mime); $swooleResponse->sendfile($filename); diff --git a/src/Transformers/Response.php b/src/Transformers/Response.php index 873e5508..a0af8eca 100644 --- a/src/Transformers/Response.php +++ b/src/Transformers/Response.php @@ -2,7 +2,6 @@ namespace SwooleTW\Http\Transformers; - use Illuminate\Http\Response as IlluminateResponse; use Swoole\Http\Response as SwooleResponse; use Symfony\Component\HttpFoundation\BinaryFileResponse; @@ -67,7 +66,7 @@ protected function sendHeaders() $illuminateResponse = $this->getIlluminateResponse(); /* RFC2616 - 14.18 says all Responses need to have a Date */ - if (!$illuminateResponse->headers->has('Date')) { + if (! $illuminateResponse->headers->has('Date')) { $illuminateResponse->setDate(\DateTime::createFromFormat('U', time())); } @@ -90,9 +89,12 @@ protected function sendHeaders() foreach ($illuminateResponse->headers->getCookies() as $cookie) { // may need to consider rawcookie $this->swooleResponse->cookie( - $cookie->getName(), $cookie->getValue(), - $cookie->getExpiresTime(), $cookie->getPath(), - $cookie->getDomain(), $cookie->isSecure(), + $cookie->getName(), + $cookie->getValue(), + $cookie->getExpiresTime(), + $cookie->getPath(), + $cookie->getDomain(), + $cookie->isSecure(), $cookie->isHttpOnly() ); } @@ -108,10 +110,12 @@ protected function sendContent() if ($illuminateResponse instanceof StreamedResponse && property_exists($illuminateResponse, 'output')) { // TODO Add Streamed Response with output $this->swooleResponse->end($illuminateResponse->output); - } else if ($illuminateResponse instanceof BinaryFileResponse) { - $this->swooleResponse->sendfile($illuminateResponse->getFile()->getPathname()); } else { - $this->swooleResponse->end($illuminateResponse->getContent()); + if ($illuminateResponse instanceof BinaryFileResponse) { + $this->swooleResponse->sendfile($illuminateResponse->getFile()->getPathname()); + } else { + $this->swooleResponse->end($illuminateResponse->getContent()); + } } } @@ -142,7 +146,7 @@ public function getSwooleResponse() */ protected function setIlluminateResponse($illuminateResponse) { - if (!$illuminateResponse instanceof SymfonyResponse) { + if (! $illuminateResponse instanceof SymfonyResponse) { $content = (string)$illuminateResponse; $illuminateResponse = new IlluminateResponse($content); } diff --git a/src/Websocket/Authenticatable.php b/src/Websocket/Authenticatable.php index b33dfcac..8d07e7bf 100644 --- a/src/Websocket/Authenticatable.php +++ b/src/Websocket/Authenticatable.php @@ -2,7 +2,6 @@ namespace SwooleTW\Http\Websocket; - use Illuminate\Contracts\Auth\Authenticatable as AuthenticatableContract; use InvalidArgumentException; @@ -36,7 +35,7 @@ public function loginUsing(AuthenticatableContract $user) */ public function loginUsingId($userId) { - return $this->join(static::USER_PREFIX . $userId); + return $this->join(static::USER_PREFIX.$userId); } /** @@ -50,7 +49,7 @@ public function logout() return null; } - return $this->leave(static::USER_PREFIX . $userId); + return $this->leave(static::USER_PREFIX.$userId); } /** @@ -85,7 +84,7 @@ public function toUserId($userIds) $userIds = is_string($userIds) || is_integer($userIds) ? func_get_args() : $userIds; foreach ($userIds as $userId) { - $fds = $this->room->getClients(static::USER_PREFIX . $userId); + $fds = $this->room->getClients(static::USER_PREFIX.$userId); $this->to($fds); } @@ -97,7 +96,7 @@ public function toUserId($userIds) */ public function getUserId() { - if (!is_null($this->userId)) { + if (! is_null($this->userId)) { return $this->userId; } @@ -121,7 +120,7 @@ public function getUserId() */ public function isUserIdOnline($userId) { - return !empty($this->room->getClients(static::USER_PREFIX . $userId)); + return ! empty($this->room->getClients(static::USER_PREFIX.$userId)); } /** @@ -131,8 +130,8 @@ public function isUserIdOnline($userId) */ protected function checkUser($user) { - if (!$user instanceOf AuthenticatableContract) { - throw new InvalidArgumentException('user object must implement ' . AuthenticatableContract::class); + if (! $user instanceOf AuthenticatableContract) { + throw new InvalidArgumentException('user object must implement '.AuthenticatableContract::class); } } } diff --git a/src/Websocket/Facades/Room.php b/src/Websocket/Facades/Room.php index e702b9c8..72f3122a 100644 --- a/src/Websocket/Facades/Room.php +++ b/src/Websocket/Facades/Room.php @@ -2,7 +2,6 @@ namespace SwooleTW\Http\Websocket\Facades; - use Illuminate\Support\Facades\Facade; /** diff --git a/src/Websocket/Facades/Websocket.php b/src/Websocket/Facades/Websocket.php index a7313000..5dcc4f05 100644 --- a/src/Websocket/Facades/Websocket.php +++ b/src/Websocket/Facades/Websocket.php @@ -2,7 +2,6 @@ namespace SwooleTW\Http\Websocket\Facades; - use Illuminate\Support\Facades\Facade; /** diff --git a/src/Websocket/HandlerContract.php b/src/Websocket/HandlerContract.php index 658d5eea..c664026f 100644 --- a/src/Websocket/HandlerContract.php +++ b/src/Websocket/HandlerContract.php @@ -2,7 +2,6 @@ namespace SwooleTW\Http\Websocket; - use Illuminate\Http\Request; use Swoole\Websocket\Frame; diff --git a/src/Websocket/Middleware/Authenticate.php b/src/Websocket/Middleware/Authenticate.php index 3ca343dd..ccc4bfa9 100644 --- a/src/Websocket/Middleware/Authenticate.php +++ b/src/Websocket/Middleware/Authenticate.php @@ -2,7 +2,6 @@ namespace SwooleTW\Http\Websocket\Middleware; - use Closure; use Illuminate\Auth\AuthenticationException; use Illuminate\Contracts\Auth\Factory as Auth; diff --git a/src/Websocket/Middleware/DecryptCookies.php b/src/Websocket/Middleware/DecryptCookies.php index 6d564944..d199a703 100644 --- a/src/Websocket/Middleware/DecryptCookies.php +++ b/src/Websocket/Middleware/DecryptCookies.php @@ -2,7 +2,6 @@ namespace SwooleTW\Http\Websocket\Middleware; - use Closure; use Illuminate\Contracts\Encryption\DecryptException; use Illuminate\Contracts\Encryption\Encrypter as EncrypterContract; diff --git a/src/Websocket/Middleware/StartSession.php b/src/Websocket/Middleware/StartSession.php index 44511480..332dfdb0 100644 --- a/src/Websocket/Middleware/StartSession.php +++ b/src/Websocket/Middleware/StartSession.php @@ -2,7 +2,6 @@ namespace SwooleTW\Http\Websocket\Middleware; - use Closure; use Illuminate\Contracts\Session\Session; use Illuminate\Http\Request; @@ -88,6 +87,6 @@ public function getSession(Request $request) */ protected function sessionConfigured() { - return !is_null($this->manager->getSessionConfig()['driver'] ?? null); + return ! is_null($this->manager->getSessionConfig()['driver'] ?? null); } } diff --git a/src/Websocket/Parser.php b/src/Websocket/Parser.php index a9805048..d1722e22 100644 --- a/src/Websocket/Parser.php +++ b/src/Websocket/Parser.php @@ -2,7 +2,6 @@ namespace SwooleTW\Http\Websocket; - use Illuminate\Support\Facades\App; abstract class Parser @@ -26,10 +25,13 @@ public function execute($server, $frame) $skip = false; foreach ($this->strategies as $strategy) { - $result = App::call($strategy . '@handle', [ - 'server' => $server, - 'frame' => $frame, - ]); + $result = App::call( + $strategy.'@handle', + [ + 'server' => $server, + 'frame' => $frame, + ] + ); if ($result === true) { $skip = true; break; diff --git a/src/Websocket/Push.php b/src/Websocket/Push.php index 40de4bd0..531a7e3e 100644 --- a/src/Websocket/Push.php +++ b/src/Websocket/Push.php @@ -2,7 +2,6 @@ namespace SwooleTW\Http\Websocket; - use Illuminate\Support\Arr; /** @@ -64,8 +63,7 @@ private function __construct( bool $assigned, string $event, string $message = null - ) - { + ) { $this->opcode = $opcode; $this->sender = $sender; $this->descriptors = $descriptors; @@ -190,7 +188,7 @@ public function getMessage(): ?string */ public function isBroadcastToAllDescriptors(): bool { - return $this->isBroadcast() && !$this->isAssigned() && count($this->descriptors) > 0; + return $this->isBroadcast() && ! $this->isAssigned() && count($this->descriptors) > 0; } /** diff --git a/src/Websocket/Rooms/RedisRoom.php b/src/Websocket/Rooms/RedisRoom.php index 060ead65..16f28f35 100644 --- a/src/Websocket/Rooms/RedisRoom.php +++ b/src/Websocket/Rooms/RedisRoom.php @@ -2,7 +2,6 @@ namespace SwooleTW\Http\Websocket\Rooms; - use Illuminate\Support\Arr; use Predis\Client as RedisClient; use Predis\Pipeline\Pipeline; @@ -58,7 +57,7 @@ public function prepare(RedisClient $redis = null): RoomContract */ public function setRedis(?RedisClient $redis = null) { - if (!$redis) { + if (! $redis) { $server = Arr::get($this->config, 'server', []); $options = Arr::get($this->config, 'options', []); @@ -203,7 +202,7 @@ public function getRooms(int $fd) */ protected function checkTable(string $table) { - if (!in_array($table, [RoomContract::ROOMS_KEY, RoomContract::DESCRIPTORS_KEY])) { + if (! in_array($table, [RoomContract::ROOMS_KEY, RoomContract::DESCRIPTORS_KEY])) { throw new \InvalidArgumentException('Invalid table name.'); } } diff --git a/src/Websocket/Rooms/RoomContract.php b/src/Websocket/Rooms/RoomContract.php index e3e91625..28aaefee 100644 --- a/src/Websocket/Rooms/RoomContract.php +++ b/src/Websocket/Rooms/RoomContract.php @@ -2,7 +2,6 @@ namespace SwooleTW\Http\Websocket\Rooms; - interface RoomContract { /** diff --git a/src/Websocket/Rooms/TableRoom.php b/src/Websocket/Rooms/TableRoom.php index 42ddb74f..a02091e2 100644 --- a/src/Websocket/Rooms/TableRoom.php +++ b/src/Websocket/Rooms/TableRoom.php @@ -2,7 +2,6 @@ namespace SwooleTW\Http\Websocket\Rooms; - use Swoole\Table; class TableRoom implements RoomContract @@ -88,7 +87,7 @@ public function delete(int $fd, $roomNames = []) foreach ($rooms as $room) { $fds = $this->getClients($room); - if (!in_array($fd, $fds)) { + if (! in_array($fd, $fds)) { continue; } @@ -178,9 +177,12 @@ public function setValue($key, array $value, string $table) { $this->checkTable($table); - $this->$table->set($key, [ - 'value' => json_encode($value), - ]); + $this->$table->set( + $key, + [ + 'value' => json_encode($value), + ] + ); return $this; } @@ -209,7 +211,7 @@ public function getValue(string $key, string $table) */ protected function checkTable(string $table) { - if (!property_exists($this, $table) || !$this->$table instanceof Table) { + if (! property_exists($this, $table) || ! $this->$table instanceof Table) { throw new \InvalidArgumentException('Invalid table name.'); } } diff --git a/src/Websocket/SimpleParser.php b/src/Websocket/SimpleParser.php index 1b0cadd0..fd3758ae 100644 --- a/src/Websocket/SimpleParser.php +++ b/src/Websocket/SimpleParser.php @@ -2,7 +2,6 @@ namespace SwooleTW\Http\Websocket; - class SimpleParser extends Parser { /** @@ -20,10 +19,12 @@ class SimpleParser extends Parser */ public function encode(string $event, $data) { - return json_encode([ - 'event' => $event, - 'data' => $data, - ]); + return json_encode( + [ + 'event' => $event, + 'data' => $data, + ] + ); } /** diff --git a/src/Websocket/SocketIO/Packet.php b/src/Websocket/SocketIO/Packet.php index bb7b83e4..5da3f021 100644 --- a/src/Websocket/SocketIO/Packet.php +++ b/src/Websocket/SocketIO/Packet.php @@ -2,7 +2,6 @@ namespace SwooleTW\Http\Websocket\SocketIO; - /** * Class Packet */ @@ -115,7 +114,7 @@ public static function getSocketType(string $packet) { $type = $packet[0] ?? null; - if (!array_key_exists($type, static::$socketTypes)) { + if (! array_key_exists($type, static::$socketTypes)) { return null; } diff --git a/src/Websocket/SocketIO/SocketIOParser.php b/src/Websocket/SocketIO/SocketIOParser.php index 8272ba4a..3c259bcf 100644 --- a/src/Websocket/SocketIO/SocketIOParser.php +++ b/src/Websocket/SocketIO/SocketIOParser.php @@ -2,7 +2,6 @@ namespace SwooleTW\Http\Websocket\SocketIO; - use SwooleTW\Http\Websocket\Parser; use SwooleTW\Http\Websocket\SocketIO\Strategies\HeartbeatStrategy; @@ -28,12 +27,12 @@ class SocketIOParser extends Parser */ public function encode(string $event, $data) { - $packet = Packet::MESSAGE . Packet::EVENT; + $packet = Packet::MESSAGE.Packet::EVENT; $shouldEncode = is_array($data) || is_object($data); $data = $shouldEncode ? json_encode($data) : $data; $format = $shouldEncode ? '["%s",%s]' : '["%s","%s"]'; - return $packet . sprintf($format, $event, $data); + return $packet.sprintf($format, $event, $data); } /** diff --git a/src/Websocket/SocketIO/Strategies/HeartbeatStrategy.php b/src/Websocket/SocketIO/Strategies/HeartbeatStrategy.php index 88a8ae16..5d65bc09 100644 --- a/src/Websocket/SocketIO/Strategies/HeartbeatStrategy.php +++ b/src/Websocket/SocketIO/Strategies/HeartbeatStrategy.php @@ -2,7 +2,6 @@ namespace SwooleTW\Http\Websocket\SocketIO\Strategies; - use SwooleTW\Http\Websocket\SocketIO\Packet; class HeartbeatStrategy diff --git a/src/Websocket/SocketIO/WebsocketHandler.php b/src/Websocket/SocketIO/WebsocketHandler.php index 34b0e34e..d76b60af 100644 --- a/src/Websocket/SocketIO/WebsocketHandler.php +++ b/src/Websocket/SocketIO/WebsocketHandler.php @@ -2,7 +2,6 @@ namespace SwooleTW\Http\Websocket\SocketIO; - use Illuminate\Http\Request; use Illuminate\Support\Facades\App; use Illuminate\Support\Facades\Config; @@ -21,15 +20,17 @@ class WebsocketHandler implements HandlerContract */ public function onOpen($fd, Request $request) { - if (!$request->input('sid')) { - $payload = json_encode([ - 'sid' => base64_encode(uniqid()), - 'upgrades' => [], - 'pingInterval' => Config::get('swoole_websocket.ping_interval'), - 'pingTimeout' => Config::get('swoole_websocket.ping_timeout'), - ]); - $initPayload = Packet::OPEN . $payload; - $connectPayload = Packet::MESSAGE . Packet::CONNECT; + if (! $request->input('sid')) { + $payload = json_encode( + [ + 'sid' => base64_encode(uniqid()), + 'upgrades' => [], + 'pingInterval' => Config::get('swoole_websocket.ping_interval'), + 'pingTimeout' => Config::get('swoole_websocket.ping_timeout'), + ] + ); + $initPayload = Packet::OPEN.$payload; + $connectPayload = Packet::MESSAGE.Packet::CONNECT; App::make('swoole.server')->push($fd, $initPayload); App::make('swoole.server')->push($fd, $connectPayload); diff --git a/src/Websocket/Websocket.php b/src/Websocket/Websocket.php index caad0773..b945d02b 100644 --- a/src/Websocket/Websocket.php +++ b/src/Websocket/Websocket.php @@ -2,7 +2,6 @@ namespace SwooleTW\Http\Websocket; - use Illuminate\Contracts\Container\Container; use Illuminate\Contracts\Pipeline\Pipeline as PipelineContract; use Illuminate\Support\Facades\App; @@ -102,7 +101,7 @@ public function to($values): self $values = is_string($values) || is_integer($values) ? func_get_args() : $values; foreach ($values as $value) { - if (!in_array($value, $this->to)) { + if (! in_array($value, $this->to)) { $this->to[] = $value; } } @@ -153,7 +152,7 @@ public function leave($rooms = []): self public function emit(string $event, $data): bool { $fds = $this->getFds(); - $assigned = !empty($this->to); + $assigned = ! empty($this->to); // if no fds are found, but rooms are assigned // that means trying to emit to a non-existing room @@ -162,17 +161,19 @@ public function emit(string $event, $data): bool return false; } - $result = App::make('swoole.server')->task([ - 'action' => static::PUSH_ACTION, - 'data' => [ - 'sender' => $this->sender, - 'fds' => $fds, - 'broadcast' => $this->isBroadcast, - 'assigned' => $assigned, - 'event' => $event, - 'message' => $data, - ], - ]); + $result = App::make('swoole.server')->task( + [ + 'action' => static::PUSH_ACTION, + 'data' => [ + 'sender' => $this->sender, + 'fds' => $fds, + 'broadcast' => $this->isBroadcast, + 'assigned' => $assigned, + 'event' => $event, + 'message' => $data, + ], + ] + ); $this->reset(); @@ -203,7 +204,7 @@ public function in($room) */ public function on(string $event, $callback) { - if (!is_string($callback) && !is_callable($callback)) { + if (! is_string($callback) && ! is_callable($callback)) { throw new InvalidArgumentException( 'Invalid websocket callback. Must be a string or callable.' ); @@ -236,7 +237,7 @@ public function eventExists(string $event) */ public function call(string $event, $data = null) { - if (!$this->eventExists($event)) { + if (! $this->eventExists($event)) { return null; } @@ -249,10 +250,13 @@ public function call(string $event, $data = null) $data = $this->setRequestThroughMiddleware($data); } - return App::call($this->callbacks[$event], [ - 'websocket' => $this, - $dataKey => $data, - ]); + return App::call( + $this->callbacks[$event], + [ + 'websocket' => $this, + $dataKey => $data, + ] + ); } /**